Add blocklist controls to domain settings. https://redmine.stoutner.com/issues/223
authorSoren Stoutner <soren@stoutner.com>
Tue, 8 May 2018 00:21:39 +0000 (17:21 -0700)
committerSoren Stoutner <soren@stoutner.com>
Tue, 8 May 2018 00:21:39 +0000 (17:21 -0700)
.idea/dictionaries/soren.xml
app/src/free/assets/ru/about_permissions_dark.html
app/src/free/assets/ru/about_permissions_light.html
app/src/free/assets/ru/about_privacy_policy_dark.html
app/src/free/assets/ru/about_privacy_policy_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/fragments/DomainSettingsFragment.java
app/src/main/java/com/stoutner/privacybrowser/fragments/DomainsListFragment.java
app/src/main/java/com/stoutner/privacybrowser/helpers/DomainsDatabaseHelper.java
app/src/main/res/layout/domain_settings_fragment.xml

index f8c44b0..26e198d 100644 (file)
@@ -54,6 +54,7 @@
       <w>enablethirdpartycookies</w>
       <w>exynos</w>
       <w>fanboy</w>
+      <w>fanboys</w>
       <w>favoriteicon</w>
       <w>fbee</w>
       <w>fdfilter</w>
index b07f8fe..2d4c025 100644 (file)
         <hr/>
         <br/>
 
-        <p>In addition, Privacy Browser Free displays ads from Google’s AdMob network using the Firebase backend.
-            For the free flavor, Firebase adds the following permissions even though they are not listed in the manifest file.</p>
+        <p>Кроме того, Privacy Browser Free отображает объявления из сети Google AdMob с использованием бэкенда Firebase.
+            Для бесплатной версии Firebase добавляет следующие разрешения, даже если они не перечислены в файле манифеста.</p>
 
-        <h3>View network connections</h3>
+        <h3>Просмотр сетевых подключений</h3>
         <p><a href="https://developer.android.com/reference/android/Manifest.permission.html#ACCESS_NETWORK_STATE">android.permission.ACCESS_NETWORK_STATE</a></p>
-        <p>Allows the ads to tell when you are connected to the internet and when you aren’t (presumably so they don’t try to reload an ad when you are disconnected).
-            They can also tell if you are connected via Wi-Fi, 2G, 3G, 4G, etc.</p>
+        <p>Позволяет рекламе узнавать наличие подключения к интернету (возможно, таким образом предотвращаются попытки загрузки рекламы при отсутствии активного соединения).
+            Кроме того, передается тип подключения - Wi-Fi, 2G, 3G, 4G, и т.д.</p>
 
-        <h3>Prevent phone from sleeping</h3>
+        <h3>Предотвращение засыпания устройства</h3>
         <p><a href="https://developer.android.com/reference/android/Manifest.permission.html#WAKE_LOCK">android.permission.WAKE_LOCK</a></p>
-        <p>Allows the ads to keep the processor from sleeping and the screen from dimming, although in my testing I don’t think the ads actually do this.</p>
+        <p>Позволяет рекламе предотвращать переход процессора в режим сна и экран от выключения. Результаты тестировании не свидетельствуют о том, что реклама на самом деле это делает.</p>
 
-        <h3>Receive data from Internet</h3>
+        <h3>Получение данных из интернета</h3>
         <p><a href="http://androidpermissions.com/permission/com.google.android.c2dm.permission.RECEIVE">com.google.android.c2dm.permission.RECEIVE</a></p>
-        <p>Allows Google to send information directly to the AdView without having to receive a request first (cloud-to-device messaging).</p>
+        <p>Позволяет Google отправлять информацию непосредственно в AdView без необходимости сначала получать запрос (обмен сообщениями между облаком и устройством).</p>
 
-        <h3>Receive data from Internet</h3>
+        <h3>Получение данных из интернета</h3>
         <p><a href="https://developers.google.com/cloud-messaging/android/client">com.stoutner.privacybrowser.free.permission.C2D_MESSAGE</a></p>
-        <p>Secures the cloud-to-device messages so that only Privacy Browser Free can receive them.</p>
+        <p>Обеспечивает защиту сообщений между облаком и устройством, чтобы их могли получать только Privacy Browser Free can receive them.</p>
     </body>
 </html>
\ No newline at end of file
index 55cb81b..389d2c0 100644 (file)
         <hr/>
         <br/>
 
-        <p>In addition, Privacy Browser Free displays ads from Google’s AdMob network using the Firebase backend.
-            For the free flavor, Firebase adds the following permissions even though they are not listed in the manifest file.</p>
+        <p>Кроме того, Privacy Browser Free отображает объявления из сети Google AdMob с использованием бэкенда Firebase.
+            Для бесплатной версии Firebase добавляет следующие разрешения, даже если они не перечислены в файле манифеста.</p>
 
-        <h3>View network connections</h3>
+        <h3>Просмотр сетевых подключений</h3>
         <p><a href="https://developer.android.com/reference/android/Manifest.permission.html#ACCESS_NETWORK_STATE">android.permission.ACCESS_NETWORK_STATE</a></p>
-        <p>Allows the ads to tell when you are connected to the internet and when you aren’t (presumably so they don’t try to reload an ad when you are disconnected).
-            They can also tell if you are connected via Wi-Fi, 2G, 3G, 4G, etc.</p>
+        <p>Позволяет рекламе узнавать наличие подключения к интернету (возможно, таким образом предотвращаются попытки загрузки рекламы при отсутствии активного соединения).
+            Кроме того, передается тип подключения - Wi-Fi, 2G, 3G, 4G, и т.д.</p>
 
-        <h3>Prevent phone from sleeping</h3>
+        <h3>Предотвращение засыпания устройства</h3>
         <p><a href="https://developer.android.com/reference/android/Manifest.permission.html#WAKE_LOCK">android.permission.WAKE_LOCK</a></p>
-        <p>Allows the ads to keep the processor from sleeping and the screen from dimming, although in my testing I don't think the ads actually do this.</p>
+        <p>Позволяет рекламе предотвращать переход процессора в режим сна и экран от выключения. Результаты тестировании не свидетельствуют о том, что реклама на самом деле это делает.</p>
 
-        <h3>Receive data from Internet</h3>
+        <h3>Получение данных из интернета</h3>
         <p><a href="http://androidpermissions.com/permission/com.google.android.c2dm.permission.RECEIVE">com.google.android.c2dm.permission.RECEIVE</a></p>
-        <p>Allows Google to send information directly to the AdView without having to receive a request first (cloud-to-device messaging).</p>
+        <p>Позволяет Google отправлять информацию непосредственно в AdView без необходимости сначала получать запрос (обмен сообщениями между облаком и устройством).</p>
 
-        <h3>Receive data from Internet</h3>
+        <h3>Получение данных из интернета</h3>
         <p><a href="https://developers.google.com/cloud-messaging/android/client">com.stoutner.privacybrowser.free.permission.C2D_MESSAGE</a></p>
-        <p>Secures the cloud-to-device messages so that only Privacy Browser Free can receive them.</p>
+        <p>Обеспечивает защиту сообщений между облаком и устройством, чтобы их могли получать только Privacy Browser Free can receive them.</p>
     </body>
 </html>
\ No newline at end of file
index 843cf4e..a3ad28b 100644 (file)
         </ul>
 
 
-        <h3>Advertisements</h3>
-        <p>Privacy Browser Free displays a banner ad across the bottom of the screen using Google's AdMob network, which has its <a href="https://www.google.com/intl/en/policies/privacy/">own privacy policy</a>.
-            Note that unless you have <a href="http://www.techrepublic.com/article/pro-tip-how-to-opt-out-of-interest-based-ads-on-your-android-phone/">opted out of interest-based ads</a>,
-            the advertiser will receive a copy of your unique device advertising ID, which allows them to track your device across apps.
-            AdMob reports <em>anonymized summaries</em> of the following information to developers.</p>
+        <h3>Реклама</h3>
+        <p>Privacy Browser Free отображает рекламный баннер в нижней части экрана с помощью сети Google AdMob, которая имеет <a href="https://www.google.com/intl/en/policies/privacy/">собственную политику конфиденциальности</a>.
+            Обратите внимание, что если вы <a href="http://www.techrepublic.com/article/pro-tip-how-to-opt-out-of-interest-based-ads-on-your-android-phone/">не отказались от рекламы на основе интересов</a>,
+            рекламодатель получит копию уникального рекламного идентификатора устройства, который позволит ему отслеживать ваше устройство в различных приложениях.
+            AdMob отправляет <em>анонимные отчеты</em> разработчикам, содержащие следующую информацию.</p>
         <ul>
-            <li><item>Total impressions</item></li>
-            <li><item>Total clicks</item></li>
-            <li><item>Platforms</item> (eg. high-end mobile devices, tablets)</li>
-            <li><item>Activity by country</item></li>
+            <li><item>Всего показов</item></li>
+            <li><item>Всего кликов</item></li>
+            <li><item>Платформы</item> (напр. высокопроизводительные мобильные устройства, планшеты)</li>
+            <li><item>Активность по странам</item></li>
         </ul>
 
 
index fecbf0c..413bf53 100644 (file)
         </ul>
 
 
-        <h3>Advertisements</h3>
-        <p>Privacy Browser Free displays a banner ad across the bottom of the screen using Google's AdMob network, which has its <a href="https://www.google.com/intl/en/policies/privacy/">own privacy policy</a>.
-            Note that unless you have <a href="http://www.techrepublic.com/article/pro-tip-how-to-opt-out-of-interest-based-ads-on-your-android-phone/">opted out of interest-based ads</a>,
-            the advertiser will receive a copy of your unique device advertising ID, which allows them to track your device across apps.
-            AdMob reports <em>anonymized summaries</em> of the following information to developers.</p>
+        <h3>Реклама</h3>
+        <p>Privacy Browser Free отображает рекламный баннер в нижней части экрана с помощью сети Google AdMob, которая имеет <a href="https://www.google.com/intl/en/policies/privacy/">собственную политику конфиденциальности</a>.
+            Обратите внимание, что если вы <a href="http://www.techrepublic.com/article/pro-tip-how-to-opt-out-of-interest-based-ads-on-your-android-phone/">не отказались от рекламы на основе интересов</a>,
+            рекламодатель получит копию уникального рекламного идентификатора устройства, который позволит ему отслеживать ваше устройство в различных приложениях.
+            AdMob отправляет <em>анонимные отчеты</em> разработчикам, содержащие следующую информацию.</p>
         <ul>
-            <li><item>Total impressions</item></li>
-            <li><item>Total clicks</item></li>
-            <li><item>Platforms</item> (eg. high-end mobile devices, tablets)</li>
-            <li><item>Activity by country</item></li>
+            <li><item>Всего показов</item></li>
+            <li><item>Всего кликов</item></li>
+            <li><item>Платформы</item> (напр. высокопроизводительные мобильные устройства, планшеты)</li>
+            <li><item>Активность по странам</item></li>
         </ul>
 
 
index 3090d8a..8c6ff34 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright © 2017 Soren Stoutner <soren@stoutner.com>.
+ * Copyright © 2017-2018 Soren Stoutner <soren@stoutner.com>.
  *
  * This file is part of Privacy Browser <https://www.stoutner.com/privacy-browser>.
  *
@@ -512,15 +512,12 @@ public class DomainsActivity extends AppCompatActivity implements AddDomainDialo
                 saveDomainSettings();
             }
 
-            // Dismiss the undo delete `SnackBar` if it is shown.
+            // Dismiss the undo delete SnackBar if it is shown.
             if (undoDeleteSnackbar != null && undoDeleteSnackbar.isShown()) {
                 undoDeleteSnackbar.dismiss();
 
-                // Create a `Runnable` to return to the main activity.
-                Runnable navigateHomeRunnable = () -> {
-                    // Pass `onBackPressed()` to the system.
-                    super.onBackPressed();
-                };
+                // Create a runnable to return to the main activity.
+                Runnable navigateHomeRunnable = super::onBackPressed;
 
                 // Navigate home after 300 milliseconds to make sure that the previous domain has been deleted from the database.
                 Handler handler = new Handler();
@@ -533,7 +530,7 @@ public class DomainsActivity extends AppCompatActivity implements AddDomainDialo
             // Save the current domain settings.
             saveDomainSettings();
 
-            // Display `DomainsListFragment`.
+            // Display the domains list fragment.
             DomainsListFragment domainsListFragment = new DomainsListFragment();
             supportFragmentManager.beginTransaction().replace(R.id.domains_listview_fragment_container, domainsListFragment).commit();
             supportFragmentManager.executePendingTransactions();
@@ -551,11 +548,8 @@ public class DomainsActivity extends AppCompatActivity implements AddDomainDialo
             if (undoDeleteSnackbar != null && undoDeleteSnackbar.isShown()) {
                 undoDeleteSnackbar.dismiss();
 
-                // Create a `Runnable` to return to the main activity.
-                Runnable navigateHomeRunnable = () -> {
-                    // Pass `onBackPressed()` to the system.
-                    super.onBackPressed();
-                };
+                // Create a runnable to return to the main activity.
+                Runnable navigateHomeRunnable = super::onBackPressed;
 
                 // Navigate home after 300 milliseconds to make sure that the previous domain has been deleted from the database.
                 Handler handler = new Handler();
@@ -569,12 +563,12 @@ public class DomainsActivity extends AppCompatActivity implements AddDomainDialo
 
     @Override
     public void onAddDomain(AppCompatDialogFragment dialogFragment) {
-        // Dismiss `undoDeleteSnackbar` if it is currently displayed.
+        // Dismiss the undo delete snackbar if it is currently displayed.
         if ((undoDeleteSnackbar != null) && (undoDeleteSnackbar.isShown())) {
             undoDeleteSnackbar.dismiss();
         }
 
-        // Get the new domain name `String` from `dialogFragment`.
+        // Get the new domain name String from the dialog fragment.
         EditText domainNameEditText = dialogFragment.getDialog().findViewById(R.id.domain_name_edittext);
         String domainNameString = domainNameEditText.getText().toString();
 
@@ -607,11 +601,15 @@ public class DomainsActivity extends AppCompatActivity implements AddDomainDialo
     private void saveDomainSettings() {
         // Get handles for the domain settings.
         EditText domainNameEditText = findViewById(R.id.domain_settings_name_edittext);
-        Switch javaScriptEnabledSwitch = findViewById(R.id.domain_settings_javascript_switch);
-        Switch firstPartyCookiesEnabledSwitch = findViewById(R.id.domain_settings_first_party_cookies_switch);
-        Switch thirdPartyCookiesEnabledSwitch = findViewById(R.id.domain_settings_third_party_cookies_switch);
-        Switch domStorageEnabledSwitch = findViewById(R.id.domain_settings_dom_storage_switch);
-        Switch formDataEnabledSwitch = findViewById(R.id.domain_settings_form_data_switch);
+        Switch javaScriptSwitch = findViewById(R.id.domain_settings_javascript_switch);
+        Switch firstPartyCookiesSwitch = findViewById(R.id.domain_settings_first_party_cookies_switch);
+        Switch thirdPartyCookiesSwitch = findViewById(R.id.domain_settings_third_party_cookies_switch);
+        Switch domStorageSwitch = findViewById(R.id.domain_settings_dom_storage_switch);
+        Switch formDataSwitch = findViewById(R.id.domain_settings_form_data_switch);
+        Switch easyListSwitch = findViewById(R.id.domain_settings_easylist_switch);
+        Switch easyPrivacySwitch = findViewById(R.id.domain_settings_easyprivacy_switch);
+        Switch fanboysAnnoyanceSwitch = findViewById(R.id.domain_settings_fanboys_annoyance_list_switch);
+        Switch fanboysSocialBlockingSwitch = findViewById(R.id.domain_settings_fanboys_social_blocking_list_switch);
         Spinner userAgentSpinner = findViewById(R.id.domain_settings_user_agent_spinner);
         EditText customUserAgentEditText = findViewById(R.id.domain_settings_custom_user_agent_edittext);
         Spinner fontSizeSpinner = findViewById(R.id.domain_settings_font_size_spinner);
@@ -623,11 +621,15 @@ public class DomainsActivity extends AppCompatActivity implements AddDomainDialo
 
         // Extract the data for the domain settings.
         String domainNameString = domainNameEditText.getText().toString();
-        boolean javaScriptEnabledBoolean = javaScriptEnabledSwitch.isChecked();
-        boolean firstPartyCookiesEnabledBoolean = firstPartyCookiesEnabledSwitch.isChecked();
-        boolean thirdPartyCookiesEnabledBoolean = thirdPartyCookiesEnabledSwitch.isChecked();
-        boolean domStorageEnabledEnabledBoolean  = domStorageEnabledSwitch.isChecked();
-        boolean formDataEnabledBoolean = formDataEnabledSwitch.isChecked();
+        boolean javaScriptEnabled = javaScriptSwitch.isChecked();
+        boolean firstPartyCookiesEnabled = firstPartyCookiesSwitch.isChecked();
+        boolean thirdPartyCookiesEnabled = thirdPartyCookiesSwitch.isChecked();
+        boolean domStorageEnabled  = domStorageSwitch.isChecked();
+        boolean formDataEnabled = formDataSwitch.isChecked();
+        boolean easyListEnabled = easyListSwitch.isChecked();
+        boolean easyPrivacyEnabled = easyPrivacySwitch.isChecked();
+        boolean fanboysAnnoyanceEnabled = fanboysAnnoyanceSwitch.isChecked();
+        boolean fanboysSocialBlockingEnabled = fanboysSocialBlockingSwitch.isChecked();
         int userAgentPositionInt = userAgentSpinner.getSelectedItemPosition();
         int fontSizePositionInt = fontSizeSpinner.getSelectedItemPosition();
         int displayWebpageImagesInt = displayWebpageImagesSpinner.getSelectedItemPosition();
@@ -647,8 +649,9 @@ public class DomainsActivity extends AppCompatActivity implements AddDomainDialo
         // Save the domain settings.
         if (savedSslCertificateRadioButton.isChecked()) {  // The current certificate is being used.
             // Update the database except for the certificate.
-            domainsDatabaseHelper.updateDomainExceptCertificate(DomainsActivity.currentDomainDatabaseId, domainNameString, javaScriptEnabledBoolean, firstPartyCookiesEnabledBoolean, thirdPartyCookiesEnabledBoolean, domStorageEnabledEnabledBoolean,
-                    formDataEnabledBoolean, userAgentString, fontSizeInt, displayWebpageImagesInt, nightModeInt, pinnedSslCertificate);
+            domainsDatabaseHelper.updateDomainExceptCertificate(DomainsActivity.currentDomainDatabaseId, domainNameString, javaScriptEnabled, firstPartyCookiesEnabled, thirdPartyCookiesEnabled,
+                    domStorageEnabled, formDataEnabled, easyListEnabled, easyPrivacyEnabled, fanboysAnnoyanceEnabled, fanboysSocialBlockingEnabled, userAgentString, fontSizeInt, displayWebpageImagesInt,
+                    nightModeInt, pinnedSslCertificate);
         } else if (currentWebsiteCertificateRadioButton.isChecked()) {  // The certificate is being updated with the current website certificate.
             // Get the current website SSL certificate.
             SslCertificate currentWebsiteSslCertificate = MainWebViewActivity.sslCertificate;
@@ -664,13 +667,15 @@ public class DomainsActivity extends AppCompatActivity implements AddDomainDialo
             long endDateLong = currentWebsiteSslCertificate.getValidNotAfterDate().getTime();
 
             // Update the database.
-            domainsDatabaseHelper.updateDomainWithCertificate(currentDomainDatabaseId, domainNameString, javaScriptEnabledBoolean, firstPartyCookiesEnabledBoolean, thirdPartyCookiesEnabledBoolean, domStorageEnabledEnabledBoolean, formDataEnabledBoolean,
-                    userAgentString, fontSizeInt, displayWebpageImagesInt, nightModeInt, pinnedSslCertificate, issuedToCommonName, issuedToOrganization, issuedToOrganizationalUnit, issuedByCommonName, issuedByOrganization, issuedByOrganizationalUnit,
-                    startDateLong, endDateLong);
+            domainsDatabaseHelper.updateDomainWithCertificate(currentDomainDatabaseId, domainNameString, javaScriptEnabled, firstPartyCookiesEnabled, thirdPartyCookiesEnabled, domStorageEnabled,
+                    formDataEnabled, easyListEnabled, easyPrivacyEnabled, fanboysAnnoyanceEnabled, fanboysSocialBlockingEnabled, userAgentString, fontSizeInt, displayWebpageImagesInt, nightModeInt,
+                    pinnedSslCertificate, issuedToCommonName, issuedToOrganization, issuedToOrganizationalUnit, issuedByCommonName, issuedByOrganization, issuedByOrganizationalUnit, startDateLong, endDateLong);
+
         } else {  // No certificate is selected.
             // Update the database, with PINNED_SSL_CERTIFICATE set to false.
-            domainsDatabaseHelper.updateDomainExceptCertificate(currentDomainDatabaseId, domainNameString, javaScriptEnabledBoolean, firstPartyCookiesEnabledBoolean, thirdPartyCookiesEnabledBoolean, domStorageEnabledEnabledBoolean, formDataEnabledBoolean,
-                    userAgentString, fontSizeInt, displayWebpageImagesInt, nightModeInt, false);
+            domainsDatabaseHelper.updateDomainExceptCertificate(currentDomainDatabaseId, domainNameString, javaScriptEnabled, firstPartyCookiesEnabled, thirdPartyCookiesEnabled, domStorageEnabled,
+                    formDataEnabled, easyListEnabled, easyPrivacyEnabled, fanboysAnnoyanceEnabled, fanboysSocialBlockingEnabled, userAgentString, fontSizeInt, displayWebpageImagesInt, nightModeInt,
+                    false);
         }
     }
 
index ff82699..bf7db71 100644 (file)
@@ -282,8 +282,8 @@ public class MainWebViewActivity extends AppCompatActivity implements AddDomainD
     // The block list variables are used in `onCreate()` and `applyAppSettings()`.
     private boolean easyListEnabled;
     private boolean easyPrivacyEnabled;
-    private boolean fanboyAnnoyanceListEnabled;
-    private boolean fanboySocialBlockingListEnabled;
+    private boolean fanboysAnnoyanceListEnabled;
+    private boolean fanboysSocialBlockingListEnabled;
 
     // `privacyBrowserRuntime` is used in `onCreate()`, `onOptionsItemSelected()`, and `applyAppSettings()`.
     private Runtime privacyBrowserRuntime;
@@ -1145,12 +1145,12 @@ public class MainWebViewActivity extends AppCompatActivity implements AddDomainD
                 }
 
                 // Check Fanboy’s Annoyance List if it is enabled.
-                if (fanboyAnnoyanceListEnabled) {
+                if (fanboysAnnoyanceListEnabled) {
                     if (blockListHelper.isBlocked(formattedUrlString, url, fanboyAnnoyance)) {
                         // The resource request was blocked.  Return an empty web resource response.
                         return emptyWebResourceResponse;
                     }
-                } else if (fanboySocialBlockingListEnabled){  // Only check Fanboy’s Social Blocking List if Fanboy’s Annoyance List is disabled.
+                } else if (fanboysSocialBlockingListEnabled){  // Only check Fanboy’s Social Blocking List if Fanboy’s Annoyance List is disabled.
                     if (blockListHelper.isBlocked(formattedUrlString, url, fanboySocial)) {
                         // The resource request was blocked.  Return an empty web resource response.
                         return emptyWebResourceResponse;
@@ -3025,10 +3025,6 @@ public class MainWebViewActivity extends AppCompatActivity implements AddDomainD
         String torSearchCustomURLString = sharedPreferences.getString("tor_search_custom_url", "");
         String searchString = sharedPreferences.getString("search", "https://duckduckgo.com/html/?q=");
         String searchCustomURLString = sharedPreferences.getString("search_custom_url", "");
-        easyListEnabled = sharedPreferences.getBoolean("easylist", true);
-        easyPrivacyEnabled = sharedPreferences.getBoolean("easyprivacy", true);
-        fanboyAnnoyanceListEnabled = sharedPreferences.getBoolean("fanboy_annoyance_list", true);
-        fanboySocialBlockingListEnabled = sharedPreferences.getBoolean("fanboy_social_blocking_list", true);
         incognitoModeEnabled = sharedPreferences.getBoolean("incognito_mode", false);
         boolean doNotTrackEnabled = sharedPreferences.getBoolean("do_not_track", false);
         boolean proxyThroughOrbot = sharedPreferences.getBoolean("proxy_through_orbot", false);
@@ -3282,6 +3278,10 @@ public class MainWebViewActivity extends AppCompatActivity implements AddDomainD
                 thirdPartyCookiesEnabled = (currentHostDomainSettingsCursor.getInt(currentHostDomainSettingsCursor.getColumnIndex(DomainsDatabaseHelper.ENABLE_THIRD_PARTY_COOKIES)) == 1);
                 domStorageEnabled = (currentHostDomainSettingsCursor.getInt(currentHostDomainSettingsCursor.getColumnIndex(DomainsDatabaseHelper.ENABLE_DOM_STORAGE)) == 1);
                 saveFormDataEnabled = (currentHostDomainSettingsCursor.getInt(currentHostDomainSettingsCursor.getColumnIndex(DomainsDatabaseHelper.ENABLE_FORM_DATA)) == 1);
+                easyListEnabled = (currentHostDomainSettingsCursor.getInt(currentHostDomainSettingsCursor.getColumnIndex(DomainsDatabaseHelper.ENABLE_EASYLIST)) == 1);
+                easyPrivacyEnabled = (currentHostDomainSettingsCursor.getInt(currentHostDomainSettingsCursor.getColumnIndex(DomainsDatabaseHelper.ENABLE_EASYPRIVACY)) == 1);
+                fanboysAnnoyanceListEnabled = (currentHostDomainSettingsCursor.getInt(currentHostDomainSettingsCursor.getColumnIndex(DomainsDatabaseHelper.ENABLE_FANBOYS_ANNOYANCE_LIST)) == 1);
+                fanboysSocialBlockingListEnabled = (currentHostDomainSettingsCursor.getInt(currentHostDomainSettingsCursor.getColumnIndex(DomainsDatabaseHelper.ENABLE_FANBOYS_SOCIAL_BLOCKING_LIST)) == 1);
                 String userAgentString = currentHostDomainSettingsCursor.getString(currentHostDomainSettingsCursor.getColumnIndex(DomainsDatabaseHelper.USER_AGENT));
                 int fontSize = currentHostDomainSettingsCursor.getInt(currentHostDomainSettingsCursor.getColumnIndex(DomainsDatabaseHelper.FONT_SIZE));
                 displayWebpageImagesInt = currentHostDomainSettingsCursor.getInt(currentHostDomainSettingsCursor.getColumnIndex(DomainsDatabaseHelper.DISPLAY_IMAGES));
@@ -3395,6 +3395,10 @@ public class MainWebViewActivity extends AppCompatActivity implements AddDomainD
                 thirdPartyCookiesEnabled = sharedPreferences.getBoolean("third_party_cookies_enabled", false);
                 domStorageEnabled = sharedPreferences.getBoolean("dom_storage_enabled", false);
                 saveFormDataEnabled = sharedPreferences.getBoolean("save_form_data_enabled", false);
+                easyListEnabled = sharedPreferences.getBoolean("easylist", true);
+                easyPrivacyEnabled = sharedPreferences.getBoolean("easyprivacy", true);
+                fanboysAnnoyanceListEnabled = sharedPreferences.getBoolean("fanboy_annoyance_list", true);
+                fanboysSocialBlockingListEnabled = sharedPreferences.getBoolean("fanboy_social_blocking_list", true);
 
                 // Set `javaScriptEnabled` to be `true` if `night_mode` is `true`.
                 if (nightMode) {
index d003a99..3468748 100644 (file)
@@ -77,7 +77,7 @@ public class DomainSettingsFragment extends Fragment {
         databaseId = getArguments().getInt(DATABASE_ID);
     }
 
-    // We have to use the deprecated `getDrawable()` until the minimum API >= 21.
+    // The deprecated `getDrawable()` must be used until the minimum API >= 21.
     @SuppressWarnings("deprecation")
     @Override
     public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
@@ -111,6 +111,14 @@ public class DomainSettingsFragment extends Fragment {
         final ImageView domStorageImageView = domainSettingsView.findViewById(R.id.domain_settings_dom_storage_imageview);
         Switch formDataEnabledSwitch = domainSettingsView.findViewById(R.id.domain_settings_form_data_switch);
         final ImageView formDataImageView = domainSettingsView.findViewById(R.id.domain_settings_form_data_imageview);
+        Switch easyListSwitch = domainSettingsView.findViewById(R.id.domain_settings_easylist_switch);
+        ImageView easyListImageView = domainSettingsView.findViewById(R.id.domain_settings_easylist_imageview);
+        Switch easyPrivacySwitch = domainSettingsView.findViewById(R.id.domain_settings_easyprivacy_switch);
+        ImageView easyPrivacyImageView = domainSettingsView.findViewById(R.id.domain_settings_easyprivacy_imageview);
+        Switch fanboysAnnoyanceListSwitch = domainSettingsView.findViewById(R.id.domain_settings_fanboys_annoyance_list_switch);
+        ImageView fanboysAnnoyanceListImageView = domainSettingsView.findViewById(R.id.domain_settings_fanboys_annoyance_list_imageview);
+        Switch fanboysSocialBlockingListSwitch = domainSettingsView.findViewById(R.id.domain_settings_fanboys_social_blocking_list_switch);
+        ImageView fanboysSocialBlockingListImageView = domainSettingsView.findViewById(R.id.domain_settings_fanboys_social_blocking_list_imageview);
         final Spinner userAgentSpinner = domainSettingsView.findViewById(R.id.domain_settings_user_agent_spinner);
         final TextView userAgentTextView = domainSettingsView.findViewById(R.id.domain_settings_user_agent_textview);
         final EditText customUserAgentEditText = domainSettingsView.findViewById(R.id.domain_settings_custom_user_agent_edittext);
@@ -156,7 +164,7 @@ public class DomainSettingsFragment extends Fragment {
         // Get the current website SSL certificate
         final SslCertificate currentWebsiteSslCertificate = MainWebViewActivity.sslCertificate;
 
-        // Initialize the database handler.  The two `nulls` do not specify the database name or a `CursorFactory`.  The `0` specifies the database version, but that is ignored and set instead using a constant in `DomainsDatabaseHelper`.
+        // Initialize the database handler.  The `0` specifies the database version, but that is ignored and set instead using a constant in `DomainsDatabaseHelper`.
         DomainsDatabaseHelper domainsDatabaseHelper = new DomainsDatabaseHelper(context, null, null, 0);
 
         // Get the database `Cursor` for this ID and move it to the first row.
@@ -170,6 +178,10 @@ public class DomainSettingsFragment extends Fragment {
         int thirdPartyCookiesEnabledInt = domainCursor.getInt(domainCursor.getColumnIndex(DomainsDatabaseHelper.ENABLE_THIRD_PARTY_COOKIES));
         final int domStorageEnabledInt = domainCursor.getInt(domainCursor.getColumnIndex(DomainsDatabaseHelper.ENABLE_DOM_STORAGE));
         int formDataEnabledInt = domainCursor.getInt(domainCursor.getColumnIndex(DomainsDatabaseHelper.ENABLE_FORM_DATA));
+        int easyListEnabledInt = domainCursor.getInt(domainCursor.getColumnIndex(DomainsDatabaseHelper.ENABLE_EASYLIST));
+        int easyPrivacyEnabledInt = 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));
         final String currentUserAgentString = domainCursor.getString(domainCursor.getColumnIndex(DomainsDatabaseHelper.USER_AGENT));
         int fontSizeInt = domainCursor.getInt(domainCursor.getColumnIndex(DomainsDatabaseHelper.FONT_SIZE));
         int displayImagesInt = domainCursor.getInt(domainCursor.getColumnIndex(DomainsDatabaseHelper.DISPLAY_IMAGES));
@@ -339,7 +351,7 @@ public class DomainSettingsFragment extends Fragment {
             javaScriptEnabledSwitch.setChecked(false);
         }
 
-        // Set the first-party cookies status.  Once minimum API >= 21 we can use a selector as the tint mode instead of specifying different icons.
+        // 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);
             firstPartyCookiesImageView.setImageDrawable(resources.getDrawable(R.drawable.cookies_enabled));
@@ -358,7 +370,7 @@ public class DomainSettingsFragment extends Fragment {
         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.
-                // Set the third-party cookies status.  Once minimum API >= 21 we can use a selector as the tint mode instead of specifying different icons.
+                // 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);
                     thirdPartyCookiesImageView.setImageDrawable(resources.getDrawable(R.drawable.cookies_warning));
@@ -400,7 +412,7 @@ public class DomainSettingsFragment extends Fragment {
             // Enable the DOM storage `Switch`.
             domStorageEnabledSwitch.setEnabled(true);
 
-            // Set the DOM storage status.  Once minimum API >= 21 we can use a selector as the tint mode instead of specifying different icons.
+            // 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);
                 domStorageImageView.setImageDrawable(resources.getDrawable(R.drawable.dom_storage_enabled));
@@ -434,12 +446,12 @@ public class DomainSettingsFragment extends Fragment {
             }
         }
 
-        // Set the form data status.  Once minimum API >= 21 we can use a selector as the tint mode instead of specifying different icons.
-        if (formDataEnabledInt == 1) {  // Form data is enabled.
+        // Set the form data status.  Once the minimum API >= 21 a selector can be used as the tint mode instead of specifying different icons.
+        if (formDataEnabledInt == 1) {  // Form data is on.
             formDataEnabledSwitch.setChecked(true);
             formDataImageView.setImageDrawable(resources.getDrawable(R.drawable.form_data_enabled));
-        } else {  // Form data is disabled.
-            // Set the form data switch to off.
+        } else {  // Form data is off.
+            // Turn the form data switch to off.
             formDataEnabledSwitch.setChecked(false);
 
             // Set the icon according to the theme.
@@ -450,8 +462,123 @@ public class DomainSettingsFragment extends Fragment {
             }
         }
 
-        // We need to inflated a `WebView` to get the default user agent.
-        // `@SuppressLint("InflateParams")` removes the warning about using `null` as the `ViewGroup`, which in this case makes sense because we don't want to display `bare_webview` on the screen.  `false` does not attach the view to the root.
+        // 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.
+            // Turn the switch on.
+            easyListSwitch.setChecked(true);
+
+            // Set the icon according to the theme.
+            if (MainWebViewActivity.darkTheme) {
+                easyListImageView.setImageDrawable(resources.getDrawable(R.drawable.block_ads_enabled_dark));
+            } else {
+                easyListImageView.setImageDrawable(resources.getDrawable(R.drawable.block_ads_enabled_light));
+            }
+        } else {  // EasyList is off.
+            // Turn the switch off.
+            easyListSwitch.setChecked(false);
+
+            // Set the icon according to the theme.
+            if (MainWebViewActivity.darkTheme) {
+                easyListImageView.setImageDrawable(resources.getDrawable(R.drawable.block_ads_disabled_dark));
+            } else {
+                easyListImageView.setImageDrawable(resources.getDrawable(R.drawable.block_ads_disabled_light));
+            }
+        }
+
+        // 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.
+            // Turn the switch on.
+            easyPrivacySwitch.setChecked(true);
+
+            // Set the icon according to the theme.
+            if (MainWebViewActivity.darkTheme) {
+                easyPrivacyImageView.setImageDrawable(resources.getDrawable(R.drawable.block_tracking_enabled_dark));
+            } else {
+                easyPrivacyImageView.setImageDrawable(resources.getDrawable(R.drawable.block_tracking_enabled_light));
+            }
+        } else {  // EasyPrivacy is off.
+            // Turn the switch off.
+            easyPrivacySwitch.setChecked(false);
+
+            // Set the icon according to the theme.
+            if (MainWebViewActivity.darkTheme) {
+                easyPrivacyImageView.setImageDrawable(resources.getDrawable(R.drawable.block_tracking_disabled_dark));
+            } else {
+                easyPrivacyImageView.setImageDrawable(resources.getDrawable(R.drawable.block_tracking_disabled_light));
+            }
+        }
+
+        // Set the Fanboy's Annoyance List status.  Once the minimum API >= 21 a selector can be used as the tint mode instead of specifying different icons.
+        if (fanboysAnnoyanceListInt == 1) {  // Fanboy's Annoyance List is on.
+            // Turn the switch on.
+            fanboysAnnoyanceListSwitch.setChecked(true);
+
+            // Set the icon according to the theme.
+            if (MainWebViewActivity.darkTheme) {
+                fanboysAnnoyanceListImageView.setImageDrawable(resources.getDrawable(R.drawable.social_media_enabled_dark));
+            } else {
+                fanboysAnnoyanceListImageView.setImageDrawable(resources.getDrawable(R.drawable.social_media_enabled_light));
+            }
+        } else {  // Fanboy's Annoyance List is off.
+            // Turn the switch off.
+            fanboysAnnoyanceListSwitch.setChecked(false);
+
+            // Set the icon according to the theme.
+            if (MainWebViewActivity.darkTheme) {
+                fanboysAnnoyanceListImageView.setImageDrawable(resources.getDrawable(R.drawable.social_media_disabled_dark));
+            } else {
+                fanboysAnnoyanceListImageView.setImageDrawable(resources.getDrawable(R.drawable.social_media_disabled_light));
+            }
+        }
+
+        // Only enable Fanboy's Social Blocking List if Fanboy's Annoyance List is off.
+        if (fanboysAnnoyanceListInt == 0) {  // Fanboy's Annoyance List is on.
+            // Enable Fanboy's Social Blocking List.  Once the minimum API >= 21 a selector can be used as the tint mode instead of specifying different icons.
+            if (fanboysSocialBlockingListInt == 1) {  // Fanboy's Social Blocking List is on.
+                // Enable the switch and turn it on.
+                fanboysSocialBlockingListSwitch.setEnabled(true);
+                fanboysSocialBlockingListSwitch.setChecked(true);
+
+                // Set the icon according to the theme.
+                if (MainWebViewActivity.darkTheme) {
+                    fanboysSocialBlockingListImageView.setImageDrawable(resources.getDrawable(R.drawable.social_media_enabled_dark));
+                } else {
+                    fanboysSocialBlockingListImageView.setImageDrawable(resources.getDrawable(R.drawable.social_media_enabled_light));
+                }
+            } else {  // Fanboy's Social Blocking List is off.
+                // Enable the switch but turn it off.
+                fanboysSocialBlockingListSwitch.setEnabled(true);
+                fanboysSocialBlockingListSwitch.setChecked(false);
+
+                // Set the icon according to the theme.
+                if (MainWebViewActivity.darkTheme) {
+                    fanboysSocialBlockingListImageView.setImageDrawable(resources.getDrawable(R.drawable.social_media_disabled_dark));
+                } else {
+                    fanboysSocialBlockingListImageView.setImageDrawable(resources.getDrawable(R.drawable.social_media_disabled_light));
+                }
+            }
+        } else {  // Fanboy's Annoyance List is on.
+            // Disable Fanboy's Social Blocking List.  Once the minimum API >= 21 a selector can be used as the tint mode instead of specifying different icons.
+            if (fanboysSocialBlockingListInt == 1) {  // Fanboy's Social Blocking List is on.
+                // Disable the switch but turn it on.
+                fanboysSocialBlockingListSwitch.setEnabled(false);
+                fanboysSocialBlockingListSwitch.setChecked(true);
+            } else {  // Fanboy's Social Blocking List is off.
+                // Disable the switch and turn it off.
+                fanboysSocialBlockingListSwitch.setEnabled(false);
+                fanboysSocialBlockingListSwitch.setChecked(false);
+            }
+
+            // Set the icon according to the theme.
+            if (MainWebViewActivity.darkTheme) {
+                fanboysSocialBlockingListImageView.setImageDrawable(resources.getDrawable(R.drawable.social_media_ghosted_dark));
+            } else {
+                fanboysSocialBlockingListImageView.setImageDrawable(resources.getDrawable(R.drawable.social_media_ghosted_light));
+            }
+        }
+
+        // Inflated a WebView to get the default user agent.
+        // `@SuppressLint("InflateParams")` removes the warning about using `null` as the `ViewGroup`, which in this case makes sense because the bare WebView should not be displayed on the screen.
         @SuppressLint("InflateParams") View bareWebViewLayout = inflater.inflate(R.layout.bare_webview, null, false);
         WebView bareWebView = bareWebViewLayout.findViewById(R.id.bare_webview);
         final String webViewDefaultUserAgentString = bareWebView.getSettings().getUserAgentString();
@@ -549,7 +676,7 @@ public class DomainSettingsFragment extends Fragment {
             displayImagesTextView.setText(displayImagesArrayAdapter.getItem(DomainsDatabaseHelper.DISPLAY_WEBPAGE_IMAGES_DISABLED));
         }
 
-        // Set the display website images icon and `TextView` settings.  Once minimum API >= 21 we can use a selector as the tint mode instead of specifying different icons.
+        // Set the display website images icon and `TextView` settings.  Once the minimum API >= 21 a selector can be used as the tint mode instead of specifying different icons.
         switch (displayImagesInt) {
             case DomainsDatabaseHelper.DISPLAY_WEBPAGE_IMAGES_SYSTEM_DEFAULT:
                 if (defaultDisplayWebpageImagesBoolean) {  // Display webpage images enabled by default.
@@ -613,7 +740,7 @@ public class DomainSettingsFragment extends Fragment {
             nightModeTextView.setText(nightModeArrayAdapter.getItem(DomainsDatabaseHelper.NIGHT_MODE_DISABLED));
         }
 
-        // Set the night mode icon and `TextView` settings.  Once minimum API >= 21 we can use a selector as the tint mode instead of specifying different icons.
+        // Set the night mode icon and `TextView` settings.  Once the minimum API >= 21 a selector can be used as the tint mode instead of specifying different icons.
         switch (displayImagesInt) {
             case DomainsDatabaseHelper.NIGHT_MODE_SYSTEM_DEFAULT:
                 if (defaultNightModeBoolean) {  // Night mode enabled by default.
@@ -668,7 +795,7 @@ public class DomainSettingsFragment extends Fragment {
         });
         
         // Set the pinned SSL certificate icon.
-        if (pinnedSslCertificateInt == 1) {  // Pinned SSL certificate is enabled.  Once minimum API >= 21 we can use a selector as the tint mode instead of specifying different icons.
+        if (pinnedSslCertificateInt == 1) {  // Pinned SSL certificate is enabled.  Once the minimum API >= 21 a selector can be used as the tint mode instead of specifying different icons.
             // Check the switch.
             pinnedSslCertificateSwitch.setChecked(true);
 
@@ -753,8 +880,10 @@ public class DomainSettingsFragment extends Fragment {
             SpannableStringBuilder currentWebsiteCertificateIssuedByCNameStringBuilder = new SpannableStringBuilder(cNameLabel + currentWebsiteCertificateIssuedByCNameString);
             SpannableStringBuilder currentWebsiteCertificateIssuedByONameStringBuilder = new SpannableStringBuilder(oNameLabel + currentWebsiteCertificateIssuedByONameString);
             SpannableStringBuilder currentWebsiteCertificateIssuedByUNameStringBuilder = new SpannableStringBuilder(uNameLabel + currentWebsiteCertificateIssuedByUNameString);
-            SpannableStringBuilder currentWebsiteCertificateStartDateStringBuilder = new SpannableStringBuilder(startDateLabel + DateFormat.getDateTimeInstance(DateFormat.MEDIUM, DateFormat.LONG).format(currentWebsiteCertificateStartDate));
-            SpannableStringBuilder currentWebsiteCertificateEndDateStringBuilder = new SpannableStringBuilder(endDateLabel + DateFormat.getDateTimeInstance(DateFormat.MEDIUM, DateFormat.LONG).format(currentWebsiteCertificateEndDate));
+            SpannableStringBuilder currentWebsiteCertificateStartDateStringBuilder = new SpannableStringBuilder(startDateLabel + DateFormat.getDateTimeInstance(DateFormat.MEDIUM, DateFormat.LONG)
+                    .format(currentWebsiteCertificateStartDate));
+            SpannableStringBuilder currentWebsiteCertificateEndDateStringBuilder = new SpannableStringBuilder(endDateLabel + DateFormat.getDateTimeInstance(DateFormat.MEDIUM, DateFormat.LONG)
+                    .format(currentWebsiteCertificateEndDate));
 
             // Setup the `StringBuilders` to display the general certificate information in blue.  `SPAN_INCLUSIVE_INCLUSIVE` allows the span to grow in either direction.
             currentWebsiteCertificateIssuedToONameStringBuilder.setSpan(blueColorSpan, oNameLabel.length(), currentWebsiteCertificateIssuedToONameStringBuilder.length(), Spanned.SPAN_INCLUSIVE_INCLUSIVE);
@@ -845,7 +974,7 @@ public class DomainSettingsFragment extends Fragment {
         }
 
 
-        // Set the `javaScriptEnabledSwitch` `OnCheckedChangeListener()`.
+        // Set the JavaScript switch listener.
         javaScriptEnabledSwitch.setOnCheckedChangeListener((CompoundButton buttonView, boolean isChecked) -> {
             if (isChecked) {  // JavaScript is enabled.
                 // Update the JavaScript icon.
@@ -881,13 +1010,13 @@ public class DomainSettingsFragment extends Fragment {
             }
         });
 
-        // Set the `firstPartyCookiesEnabledSwitch` `OnCheckedChangeListener()`.
+        // Set the first-party cookies switch listener.
         firstPartyCookiesEnabledSwitch.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`.
+                // Enable the third-party cookies switch.
                 thirdPartyCookiesEnabledSwitch.setEnabled(true);
 
                 // Update the third-party cookies icon.
@@ -909,7 +1038,7 @@ public class DomainSettingsFragment extends Fragment {
                     firstPartyCookiesImageView.setImageDrawable(resources.getDrawable(R.drawable.cookies_disabled_light));
                 }
 
-                // Disable the third-party cookies `Switch`.
+                // Disable the third-party cookies switch.
                 thirdPartyCookiesEnabledSwitch.setEnabled(false);
 
                 // Set the third-party cookies icon according to the theme.
@@ -921,7 +1050,7 @@ public class DomainSettingsFragment extends Fragment {
             }
         });
 
-        // Set the `thirdPartyCookiesEnabledSwitch` `OnCheckedChangeListener()`.
+        // Set the third-party cookies switch listener.
         thirdPartyCookiesEnabledSwitch.setOnCheckedChangeListener((CompoundButton buttonView, boolean isChecked) -> {
             // Update the icon.
             if (isChecked) {
@@ -936,7 +1065,7 @@ public class DomainSettingsFragment extends Fragment {
             }
         });
 
-        // Set the `domStorageEnabledSwitch` `OnCheckedChangeListener()`.
+        // Set the DOM Storage switch listener.
         domStorageEnabledSwitch.setOnCheckedChangeListener((CompoundButton buttonView, boolean isChecked) -> {
             // Update the icon.
             if (isChecked) {
@@ -951,7 +1080,7 @@ public class DomainSettingsFragment extends Fragment {
             }
         });
 
-        // Set the `formDataEnabledSwitch` `OnCheckedChangeListener()`.
+        // Set the form data switch listener.
         formDataEnabledSwitch.setOnCheckedChangeListener((CompoundButton buttonView, boolean isChecked) -> {
             // Update the icon.
             if (isChecked) {
@@ -966,7 +1095,118 @@ public class DomainSettingsFragment extends Fragment {
             }
         });
 
-        // Set the `userAgentSpinner` `onItemClickListener()`.
+        // Set the EasyList switch listener.
+        easyListSwitch.setOnCheckedChangeListener((CompoundButton buttonView, boolean isChecked) -> {
+            // Update the icon.
+            if (isChecked) {  // EasyList is on.
+                // Set the icon according to the theme.
+                if (MainWebViewActivity.darkTheme) {
+                    easyListImageView.setImageDrawable(resources.getDrawable(R.drawable.block_ads_enabled_dark));
+                } else {
+                    easyListImageView.setImageDrawable(resources.getDrawable(R.drawable.block_ads_enabled_light));
+                }
+            } else {  // EasyList is off.
+                // Set the icon according to the theme.
+                if (MainWebViewActivity.darkTheme) {
+                    easyListImageView.setImageDrawable(resources.getDrawable(R.drawable.block_ads_disabled_dark));
+                } else {
+                    easyListImageView.setImageDrawable(resources.getDrawable(R.drawable.block_ads_disabled_light));
+                }
+            }
+        });
+
+        // Set the EasyPrivacy switch listener.
+        easyPrivacySwitch.setOnCheckedChangeListener((CompoundButton buttonView, boolean isChecked) -> {
+            // Update the icon.
+            if (isChecked) {  // EasyPrivacy is on.
+                // Set the icon according to the theme.
+                if (MainWebViewActivity.darkTheme) {
+                    easyPrivacyImageView.setImageDrawable(resources.getDrawable(R.drawable.block_tracking_enabled_dark));
+                } else {
+                    easyPrivacyImageView.setImageDrawable(resources.getDrawable(R.drawable.block_tracking_enabled_light));
+                }
+            } else {  // EasyPrivacy is off.
+                // Set the icon according to the theme.
+                if (MainWebViewActivity.darkTheme) {
+                    easyPrivacyImageView.setImageDrawable(resources.getDrawable(R.drawable.block_tracking_disabled_dark));
+                } else {
+                    easyPrivacyImageView.setImageDrawable(resources.getDrawable(R.drawable.block_tracking_disabled_light));
+                }
+            }
+        });
+
+        // Set the Fanboy's Annoyance List switch listener.
+        fanboysAnnoyanceListSwitch.setOnCheckedChangeListener((CompoundButton buttonView, boolean isChecked) -> {
+            // Update the icon and Fanboy's Social Blocking List.
+            if (isChecked) {  // Fanboy's Annoyance List is on.
+                // Set the icon according to the theme.
+                if (MainWebViewActivity.darkTheme) {
+                    fanboysAnnoyanceListImageView.setImageDrawable(resources.getDrawable(R.drawable.social_media_enabled_dark));
+                } else {
+                    fanboysAnnoyanceListImageView.setImageDrawable(resources.getDrawable(R.drawable.social_media_enabled_light));
+                }
+
+                // Disable the Fanboy's Social Blocking List switch.
+                fanboysSocialBlockingListSwitch.setEnabled(false);
+
+                // Update the Fanboy's Social Blocking List icon according to the theme.
+                if (MainWebViewActivity.darkTheme) {
+                    fanboysSocialBlockingListImageView.setImageDrawable(resources.getDrawable(R.drawable.social_media_ghosted_dark));
+                } else {
+                    fanboysSocialBlockingListImageView.setImageDrawable(resources.getDrawable(R.drawable.social_media_ghosted_light));
+                }
+            } else {  // Fanboy's Annoyance List is off.
+                // Set the icon according to the theme.
+                if (MainWebViewActivity.darkTheme) {
+                    fanboysAnnoyanceListImageView.setImageDrawable(resources.getDrawable(R.drawable.social_media_disabled_dark));
+                } else {
+                    fanboysAnnoyanceListImageView.setImageDrawable(resources.getDrawable(R.drawable.social_media_disabled_light));
+                }
+
+                // Enable the Fanboy's Social Blocking List switch.
+                fanboysSocialBlockingListSwitch.setEnabled(true);
+
+                // Update the Fanboy's Social Blocking List icon.
+                if (fanboysSocialBlockingListSwitch.isChecked()) {  // Fanboy's Social Blocking List is on.
+                    // Update the icon according to the theme.
+                    if (MainWebViewActivity.darkTheme) {
+                        fanboysSocialBlockingListImageView.setImageDrawable(resources.getDrawable(R.drawable.social_media_enabled_dark));
+                    } else {
+                        fanboysSocialBlockingListImageView.setImageDrawable(resources.getDrawable(R.drawable.social_media_enabled_light));
+                    }
+                } else {  // Fanboy's Social Blocking List is off.
+                    // Update the icon according to the theme.
+                    if (MainWebViewActivity.darkTheme) {
+                        fanboysSocialBlockingListImageView.setImageDrawable(resources.getDrawable(R.drawable.social_media_disabled_dark));
+                    } else {
+                        fanboysSocialBlockingListImageView.setImageDrawable(resources.getDrawable(R.drawable.social_media_disabled_light));
+                    }
+                }
+            }
+
+        });
+
+        // Set the Fanboy's Social Blocking List switch listener.
+        fanboysSocialBlockingListSwitch.setOnCheckedChangeListener((CompoundButton buttonView, boolean isChecked) -> {
+            // Update the icon.
+            if (isChecked) {  // Fanboy's Social Blocking List is on.
+                // Set the icon according to the theme.
+                if (MainWebViewActivity.darkTheme) {
+                    fanboysSocialBlockingListImageView.setImageDrawable(resources.getDrawable(R.drawable.social_media_enabled_dark));
+                } else {
+                    fanboysSocialBlockingListImageView.setImageDrawable(resources.getDrawable(R.drawable.social_media_enabled_light));
+                }
+            } else {  // Fanboy's Social Blocking List is off.
+                // Set the icon according to the theme.
+                if (MainWebViewActivity.darkTheme) {
+                    fanboysSocialBlockingListImageView.setImageDrawable(resources.getDrawable(R.drawable.social_media_disabled_dark));
+                } else {
+                    fanboysSocialBlockingListImageView.setImageDrawable(resources.getDrawable(R.drawable.social_media_disabled_light));
+                }
+            }
+        });
+
+        // Set the user agent spinner listener.
         userAgentSpinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
             @Override
             public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
@@ -1034,7 +1274,7 @@ public class DomainSettingsFragment extends Fragment {
             }
         });
 
-        // Set the `fontSizeSpinner` `onItemSelectedListener()`.
+        // Set the font size spinner listener.
         fontSizeSpinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
             @Override
             public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
@@ -1052,7 +1292,7 @@ public class DomainSettingsFragment extends Fragment {
             }
         });
 
-        // Set the `displayWebpageImagesSpinner` `onItemSelectedListener()`.
+        // Set the display webpage images spinner listener.
         displayWebpageImagesSpinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
             @Override
             public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
@@ -1111,11 +1351,11 @@ public class DomainSettingsFragment extends Fragment {
             }
         });
 
-        // Set the `nightModeSpinner` `onItemSelectedListener()`.
+        // Set the night mode spinner listener.
         nightModeSpinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
             @Override
             public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
-                // Update the icon and the visibility of `nightModeTextView`.  Once minimum API >= 21 we can use a selector as the tint mode instead of specifying different icons.
+                // Update the icon and the visibility of `nightModeTextView`.  Once the minimum API >= 21 a selector can be used as the tint mode instead of specifying different icons.
                 switch (position) {
                     case DomainsDatabaseHelper.NIGHT_MODE_SYSTEM_DEFAULT:
                         if (defaultNightModeBoolean) {  // Night mode enabled by default.
@@ -1185,7 +1425,7 @@ public class DomainSettingsFragment extends Fragment {
                     // Enable the DOM storage `Switch`.
                     domStorageEnabledSwitch.setEnabled(true);
 
-                    // Set the DOM storage status.  Once minimum API >= 21 we can use a selector as the tint mode instead of specifying different icons.
+                    // 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);
                         domStorageImageView.setImageDrawable(resources.getDrawable(R.drawable.dom_storage_enabled));
@@ -1226,7 +1466,7 @@ public class DomainSettingsFragment extends Fragment {
             }
         });
         
-        // Set the `pinnedSSLCertificateSwitch` `onCheckedChangeListener()`.
+        // Set the pinned SSL certificate switch listener.
         pinnedSslCertificateSwitch.setOnCheckedChangeListener((CompoundButton buttonView, boolean isChecked) -> {
             // Update the icon
             if (isChecked) {  // Pinned SSL certificate is enabled.
@@ -1321,7 +1561,8 @@ public class DomainSettingsFragment extends Fragment {
             domainNamesMatch = true;
         }
 
-        // Check various wildcard permutations if `domainName` and `certificateCommonName` are not empty.  `noinspection ConstantCondition` removes Android Studio's incorrect lint warning that `domainName` can never be `null`.
+        // Check various wildcard permutations if `domainName` and `certificateCommonName` are not empty.
+        // `noinspection ConstantCondition` removes Android Studio's incorrect lint warning that `domainName` can never be `null`.
         //noinspection ConstantConditions
         if ((domainName != null) && (certificateCommonName != null)) {
             // If `domainName` starts with a wildcard, check the base domain against all the subdomains of `certificateCommonName`.
index 26a2bf3..54b09ee 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright © 2017 Soren Stoutner <soren@stoutner.com>.
+ * Copyright © 2017-2018 Soren Stoutner <soren@stoutner.com>.
  *
  * This file is part of Privacy Browser <https://www.stoutner.com/privacy-browser>.
  *
@@ -21,6 +21,7 @@ package com.stoutner.privacybrowser.fragments;
 
 import android.net.http.SslCertificate;
 import android.os.Bundle;
+import android.support.annotation.NonNull;
 import android.support.design.widget.FloatingActionButton;
 // We have to use `android.support.v4.app.Fragment` until minimum API >= 23.  Otherwise we cannot call `getContext()`.
 import android.support.v4.app.Fragment;
@@ -41,16 +42,19 @@ import com.stoutner.privacybrowser.activities.MainWebViewActivity;
 import com.stoutner.privacybrowser.helpers.DomainsDatabaseHelper;
 
 public class DomainsListFragment extends Fragment {
-    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
+    public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
         // Inflate `domains_list_fragment`.  `false` does not attach it to the root `container`.
         View domainsListFragmentView = inflater.inflate(R.layout.domains_list_fragment, container, false);
 
         // Initialize `domainsListView`.
         ListView domainsListView = domainsListFragmentView.findViewById(R.id.domains_listview);
 
-        // Initialize the database handler.  The two `nulls` do not specify the database name or a `CursorFactory`.  The `0` specifies the database version, but that is ignored and set instead using a constant in `DomainsDatabaseHelper`.
+        // Initialize the database handler.  The `0` specifies the database version, but that is ignored and set instead using a constant in `DomainsDatabaseHelper`.
         final DomainsDatabaseHelper domainsDatabaseHelper = new DomainsDatabaseHelper(getContext(), null, null, 0);
 
+        // Remove the incorrect lint error below that `.getSupportFragmentManager()` might be null.
+        assert getActivity() != null;
+
         // Get a handle for `supportFragmentManager`.
         final FragmentManager supportFragmentManager = getActivity().getSupportFragmentManager();
 
@@ -69,11 +73,15 @@ public class DomainsListFragment extends Fragment {
 
                 // Get handles for the domain settings.
                 EditText domainNameEditText = domainSettingsFragmentView.findViewById(R.id.domain_settings_name_edittext);
-                Switch javaScriptEnabledSwitch = domainSettingsFragmentView.findViewById(R.id.domain_settings_javascript_switch);
-                Switch firstPartyCookiesEnabledSwitch = domainSettingsFragmentView.findViewById(R.id.domain_settings_first_party_cookies_switch);
-                Switch thirdPartyCookiesEnabledSwitch = domainSettingsFragmentView.findViewById(R.id.domain_settings_third_party_cookies_switch);
-                Switch domStorageEnabledSwitch = domainSettingsFragmentView.findViewById(R.id.domain_settings_dom_storage_switch);
-                Switch formDataEnabledSwitch = domainSettingsFragmentView.findViewById(R.id.domain_settings_form_data_switch);
+                Switch javaScriptSwitch = domainSettingsFragmentView.findViewById(R.id.domain_settings_javascript_switch);
+                Switch firstPartyCookiesSwitch = domainSettingsFragmentView.findViewById(R.id.domain_settings_first_party_cookies_switch);
+                Switch thirdPartyCookiesSwitch = domainSettingsFragmentView.findViewById(R.id.domain_settings_third_party_cookies_switch);
+                Switch domStorageSwitch = domainSettingsFragmentView.findViewById(R.id.domain_settings_dom_storage_switch);
+                Switch formDataSwitch = domainSettingsFragmentView.findViewById(R.id.domain_settings_form_data_switch);
+                Switch easyListSwitch = domainSettingsFragmentView.findViewById(R.id.domain_settings_easylist_switch);
+                Switch easyPrivacySwitch = domainSettingsFragmentView.findViewById(R.id.domain_settings_easyprivacy_switch);
+                Switch fanboysAnnoyanceSwitch = domainSettingsFragmentView.findViewById(R.id.domain_settings_fanboys_annoyance_list_switch);
+                Switch fanboysSocialBlockingSwitch = domainSettingsFragmentView.findViewById(R.id.domain_settings_fanboys_social_blocking_list_switch);
                 Spinner userAgentSpinner = domainSettingsFragmentView.findViewById(R.id.domain_settings_user_agent_spinner);
                 EditText customUserAgentEditText = domainSettingsFragmentView.findViewById(R.id.domain_settings_custom_user_agent_edittext);
                 Spinner fontSizeSpinner = domainSettingsFragmentView.findViewById(R.id.domain_settings_font_size_spinner);
@@ -85,11 +93,15 @@ public class DomainsListFragment extends Fragment {
 
                 // Extract the data for the domain settings.
                 String domainNameString = domainNameEditText.getText().toString();
-                boolean javaScriptEnabledBoolean = javaScriptEnabledSwitch.isChecked();
-                boolean firstPartyCookiesEnabledBoolean = firstPartyCookiesEnabledSwitch.isChecked();
-                boolean thirdPartyCookiesEnabledBoolean = thirdPartyCookiesEnabledSwitch.isChecked();
-                boolean domStorageEnabledEnabledBoolean  = domStorageEnabledSwitch.isChecked();
-                boolean formDataEnabledBoolean = formDataEnabledSwitch.isChecked();
+                boolean javaScriptEnabled = javaScriptSwitch.isChecked();
+                boolean firstPartyCookiesEnabled = firstPartyCookiesSwitch.isChecked();
+                boolean thirdPartyCookiesEnabled = thirdPartyCookiesSwitch.isChecked();
+                boolean domStorageEnabled  = domStorageSwitch.isChecked();
+                boolean formDataEnabled = formDataSwitch.isChecked();
+                boolean easyListEnabled = easyListSwitch.isChecked();
+                boolean easyPrivacyEnabled = easyPrivacySwitch.isChecked();
+                boolean fanboysAnnoyanceEnabled = fanboysAnnoyanceSwitch.isChecked();
+                boolean fanboysSocialBlockingEnabled = fanboysSocialBlockingSwitch.isChecked();
                 int userAgentPositionInt = userAgentSpinner.getSelectedItemPosition();
                 int fontSizePositionInt = fontSizeSpinner.getSelectedItemPosition();
                 int displayWebpageImagesInt = displayWebpageImagesSpinner.getSelectedItemPosition();
@@ -109,8 +121,9 @@ public class DomainsListFragment extends Fragment {
                 // Save the domain settings.
                 if (savedSslCertificateRadioButton.isChecked()) {  // The current certificate is being used.
                     // Update the database except for the certificate.
-                    domainsDatabaseHelper.updateDomainExceptCertificate(DomainsActivity.currentDomainDatabaseId, domainNameString, javaScriptEnabledBoolean, firstPartyCookiesEnabledBoolean, thirdPartyCookiesEnabledBoolean, domStorageEnabledEnabledBoolean,
-                            formDataEnabledBoolean, userAgentString, fontSizeInt, displayWebpageImagesInt, nightModeInt, pinnedSslCertificate);
+                    domainsDatabaseHelper.updateDomainExceptCertificate(DomainsActivity.currentDomainDatabaseId, domainNameString, javaScriptEnabled, firstPartyCookiesEnabled, thirdPartyCookiesEnabled,
+                            domStorageEnabled, formDataEnabled, easyListEnabled, easyPrivacyEnabled, fanboysAnnoyanceEnabled, fanboysSocialBlockingEnabled, userAgentString, fontSizeInt, displayWebpageImagesInt,
+                            nightModeInt, pinnedSslCertificate);
                 } else if (currentWebsiteCertificateRadioButton.isChecked()) {  // The certificate is being updated with the current website certificate.
                     // Get the current website SSL certificate.
                     SslCertificate currentWebsiteSslCertificate = MainWebViewActivity.sslCertificate;
@@ -126,13 +139,15 @@ public class DomainsListFragment extends Fragment {
                     long endDateLong = currentWebsiteSslCertificate.getValidNotAfterDate().getTime();
 
                     // Update the database.
-                    domainsDatabaseHelper.updateDomainWithCertificate(DomainsActivity.currentDomainDatabaseId, domainNameString, javaScriptEnabledBoolean, firstPartyCookiesEnabledBoolean, thirdPartyCookiesEnabledBoolean, domStorageEnabledEnabledBoolean,
-                            formDataEnabledBoolean, userAgentString, fontSizeInt, displayWebpageImagesInt, nightModeInt, pinnedSslCertificate, issuedToCommonName, issuedToOrganization, issuedToOrganizationalUnit, issuedByCommonName, issuedByOrganization,
+                    domainsDatabaseHelper.updateDomainWithCertificate(DomainsActivity.currentDomainDatabaseId, domainNameString, javaScriptEnabled, firstPartyCookiesEnabled, thirdPartyCookiesEnabled,
+                            domStorageEnabled, formDataEnabled, easyListEnabled, easyPrivacyEnabled, fanboysAnnoyanceEnabled, fanboysSocialBlockingEnabled, userAgentString, fontSizeInt, displayWebpageImagesInt,
+                            nightModeInt, pinnedSslCertificate, issuedToCommonName, issuedToOrganization, issuedToOrganizationalUnit, issuedByCommonName, issuedByOrganization,
                             issuedByOrganizationalUnit, startDateLong, endDateLong);
                 } else {  // No certificate is selected.
                     // Update the database, with PINNED_SSL_CERTIFICATE set to false.
-                    domainsDatabaseHelper.updateDomainExceptCertificate(DomainsActivity.currentDomainDatabaseId, domainNameString, javaScriptEnabledBoolean, firstPartyCookiesEnabledBoolean, thirdPartyCookiesEnabledBoolean, domStorageEnabledEnabledBoolean,
-                            formDataEnabledBoolean, userAgentString, fontSizeInt, displayWebpageImagesInt, nightModeInt, false);
+                    domainsDatabaseHelper.updateDomainExceptCertificate(DomainsActivity.currentDomainDatabaseId, domainNameString, javaScriptEnabled, firstPartyCookiesEnabled, thirdPartyCookiesEnabled,
+                            domStorageEnabled, formDataEnabled, easyListEnabled, easyPrivacyEnabled, fanboysAnnoyanceEnabled, fanboysSocialBlockingEnabled, userAgentString, fontSizeInt, displayWebpageImagesInt,
+                            nightModeInt, false);
                 }
             }
 
index 0331a01..350b33b 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright © 2017 Soren Stoutner <soren@stoutner.com>.
+ * Copyright © 2017-2018 Soren Stoutner <soren@stoutner.com>.
  *
  * This file is part of Privacy Browser <https://www.stoutner.com/privacy-browser>.
  *
@@ -21,12 +21,14 @@ package com.stoutner.privacybrowser.helpers;
 
 import android.content.ContentValues;
 import android.content.Context;
+import android.content.SharedPreferences;
 import android.database.Cursor;
 import android.database.sqlite.SQLiteDatabase;
 import android.database.sqlite.SQLiteOpenHelper;
+import android.preference.PreferenceManager;
 
 public class DomainsDatabaseHelper extends SQLiteOpenHelper {
-    private static final int SCHEMA_VERSION = 4;
+    private static final int SCHEMA_VERSION = 5;
     private static final String DOMAINS_DATABASE = "domains.db";
     private static final String DOMAINS_TABLE = "domains";
 
@@ -37,6 +39,10 @@ public class DomainsDatabaseHelper extends SQLiteOpenHelper {
     public static final String ENABLE_THIRD_PARTY_COOKIES = "enablethirdpartycookies";
     public static final String ENABLE_DOM_STORAGE = "enabledomstorage";
     public static final String ENABLE_FORM_DATA = "enableformdata";
+    public static final String ENABLE_EASYLIST = "enableeasylist";
+    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 USER_AGENT = "useragent";
     public static final String FONT_SIZE = "fontsize";
     public static final String DISPLAY_IMAGES = "displayimages";
@@ -61,9 +67,14 @@ public class DomainsDatabaseHelper extends SQLiteOpenHelper {
     public static final int NIGHT_MODE_ENABLED = 1;
     public static final int NIGHT_MODE_DISABLED = 2;
 
+    private Context appContext;
+
     // Initialize the database.  The lint warnings for the unused parameters are suppressed.
     public DomainsDatabaseHelper(Context context, @SuppressWarnings("UnusedParameters") String name, SQLiteDatabase.CursorFactory cursorFactory, @SuppressWarnings("UnusedParameters") int version) {
         super(context, DOMAINS_DATABASE, cursorFactory, SCHEMA_VERSION);
+
+        // Store a handle for the context.
+        appContext = context;
     }
 
     @Override
@@ -77,6 +88,10 @@ public class DomainsDatabaseHelper extends SQLiteOpenHelper {
                 ENABLE_THIRD_PARTY_COOKIES + " BOOLEAN, " +
                 ENABLE_DOM_STORAGE + " BOOLEAN, " +
                 ENABLE_FORM_DATA + " BOOLEAN, " +
+                ENABLE_EASYLIST + " BOOLEAN, " +
+                ENABLE_EASYPRIVACY + " BOOLEAN, " +
+                ENABLE_FANBOYS_ANNOYANCE_LIST + " BOOLEAN, " +
+                ENABLE_FANBOYS_SOCIAL_BLOCKING_LIST + " BOOLEAN, " +
                 USER_AGENT + " TEXT, " +
                 FONT_SIZE + " INTEGER, " +
                 DISPLAY_IMAGES + " INTEGER, " +
@@ -97,14 +112,14 @@ public class DomainsDatabaseHelper extends SQLiteOpenHelper {
 
     @Override
     public void onUpgrade(SQLiteDatabase domainsDatabase, int oldVersion, int newVersion) {
-        // Upgrade `DOMAINS_TABLE`.
+        // Upgrade the database table.
         switch (oldVersion) {
-            // Upgrade from `SCHEMA_VERSION` 1.
+            // Upgrade from schema version 1.
             case 1:
-                // Add the `DISPLAY_IMAGES` column.
+                // Add the display images column.
                 domainsDatabase.execSQL("ALTER TABLE " + DOMAINS_TABLE + " ADD COLUMN " + DISPLAY_IMAGES + " INTEGER");
 
-            // Upgrade from `SCHEMA_VERSION` 2.
+            // Upgrade from schema version 2.
             case 2:
                 //  Add the SSL certificate columns.
                 domainsDatabase.execSQL("ALTER TABLE " + DOMAINS_TABLE + " ADD COLUMN " + PINNED_SSL_CERTIFICATE + " BOOLEAN");
@@ -117,10 +132,55 @@ public class DomainsDatabaseHelper extends SQLiteOpenHelper {
                 domainsDatabase.execSQL("ALTER TABLE " + DOMAINS_TABLE + " ADD COLUMN " + SSL_START_DATE + " INTEGER");
                 domainsDatabase.execSQL("ALTER TABLE " + DOMAINS_TABLE + " ADD COLUMN " + SSL_END_DATE + " INTEGER");
 
-            // Upgrade from `SCHEMA_VERSION` 3.
+            // Upgrade from schema version 3.
             case 3:
                 // Add the `NIGHT_MODE` column.
                 domainsDatabase.execSQL("ALTER TABLE " + DOMAINS_TABLE + " ADD COLUMN " + NIGHT_MODE + " INTEGER");
+
+            // Upgrade from schema version 4.
+            case 4:
+                // Add the block lists columns.
+                domainsDatabase.execSQL("ALTER TABLE " + DOMAINS_TABLE + " ADD COLUMN " + ENABLE_EASYLIST + " BOOLEAN");
+                domainsDatabase.execSQL("ALTER TABLE " + DOMAINS_TABLE + " ADD COLUMN " + ENABLE_EASYPRIVACY + " BOOLEAN");
+                domainsDatabase.execSQL("ALTER TABLE " + DOMAINS_TABLE + " ADD COLUMN " + ENABLE_FANBOYS_ANNOYANCE_LIST + " BOOLEAN");
+                domainsDatabase.execSQL("ALTER TABLE " + DOMAINS_TABLE + " ADD COLUMN " + ENABLE_FANBOYS_SOCIAL_BLOCKING_LIST + " BOOLEAN");
+
+                // Get a handle for the shared preference.
+                SharedPreferences sharedPreferences = PreferenceManager.getDefaultSharedPreferences(appContext);
+
+                // Get the default block list settings.
+                boolean easyListEnabled = sharedPreferences.getBoolean("easylist", true);
+                boolean easyPrivacyEnabled = sharedPreferences.getBoolean("easyprivacy", true);
+                boolean fanboyAnnoyanceListEnabled = sharedPreferences.getBoolean("fanboy_annoyance_list", true);
+                boolean fanboySocialBlockingListEnabled = sharedPreferences.getBoolean("fanboy_social_blocking_list", true);
+
+                // Set EasyList for existing rows according to the current system-wide default.
+                if (easyListEnabled) {
+                    domainsDatabase.execSQL("UPDATE " + DOMAINS_TABLE + " SET " + ENABLE_EASYLIST + " = " + 1);
+                } else {
+                    domainsDatabase.execSQL("UPDATE " + DOMAINS_TABLE + " SET " + ENABLE_EASYLIST + " = " + 0);
+                }
+
+                // Set EasyPrivacy for existing rows according to the current system-wide default.
+                if (easyPrivacyEnabled) {
+                    domainsDatabase.execSQL("UPDATE " + DOMAINS_TABLE + " SET " + ENABLE_EASYPRIVACY + " = " + 1);
+                } else {
+                    domainsDatabase.execSQL("UPDATE " + DOMAINS_TABLE + " SET " + ENABLE_EASYPRIVACY + " = " + 0);
+                }
+
+                // Set Fanboy's Annoyance List for existing rows according to the current system-wide default.
+                if (fanboyAnnoyanceListEnabled) {
+                    domainsDatabase.execSQL("UPDATE " + DOMAINS_TABLE + " SET " + ENABLE_FANBOYS_ANNOYANCE_LIST + " = " + 1);
+                } else {
+                    domainsDatabase.execSQL("UPDATE " + DOMAINS_TABLE + " SET " + ENABLE_FANBOYS_ANNOYANCE_LIST + " = " + 0);
+                }
+
+                // Set Fanboy's Social Blocking List for existing rows according to the current system-wide default.
+                if (fanboySocialBlockingListEnabled) {
+                    domainsDatabase.execSQL("UPDATE " + DOMAINS_TABLE + " SET " + ENABLE_FANBOYS_SOCIAL_BLOCKING_LIST + " = " + 1);
+                } else {
+                    domainsDatabase.execSQL("UPDATE " + DOMAINS_TABLE + " SET " + ENABLE_FANBOYS_SOCIAL_BLOCKING_LIST + " = " + 0);
+                }
         }
     }
 
@@ -179,13 +239,31 @@ public class DomainsDatabaseHelper extends SQLiteOpenHelper {
         // Store the domain data in a `ContentValues`.
         ContentValues domainContentValues = new ContentValues();
 
+        // Get a handle for the shared preference.
+        SharedPreferences sharedPreferences = PreferenceManager.getDefaultSharedPreferences(appContext);
+
+        // Get the default settings.
+        boolean javaScriptEnabled = sharedPreferences.getBoolean("javascript_enabled", false);
+        boolean firstPartyCookiesEnabled = sharedPreferences.getBoolean("first_party_cookies_enabled", false);
+        boolean thirdPartyCookiesEnabled = sharedPreferences.getBoolean("third_party_cookies_enabled", false);
+        boolean domStorageEnabled = sharedPreferences.getBoolean("dom_storage_enabled", false);
+        boolean saveFormDataEnabled = sharedPreferences.getBoolean("save_form_data_enabled", false);
+        boolean easyListEnabled = sharedPreferences.getBoolean("easylist", true);
+        boolean easyPrivacyEnabled = sharedPreferences.getBoolean("easyprivacy", true);
+        boolean fanboyAnnoyanceListEnabled = sharedPreferences.getBoolean("fanboy_annoyance_list", true);
+        boolean fanboySocialBlockingListEnabled = sharedPreferences.getBoolean("fanboy_social_blocking_list", true);
+
         // 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, false);
-        domainContentValues.put(ENABLE_FIRST_PARTY_COOKIES, false);
-        domainContentValues.put(ENABLE_THIRD_PARTY_COOKIES, false);
-        domainContentValues.put(ENABLE_DOM_STORAGE, false);
-        domainContentValues.put(ENABLE_FORM_DATA, false);
+        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);
+        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(USER_AGENT, "System default user agent");
         domainContentValues.put(FONT_SIZE, 0);
         domainContentValues.put(DISPLAY_IMAGES, 0);
@@ -204,8 +282,10 @@ public class DomainsDatabaseHelper extends SQLiteOpenHelper {
         return newDomainDatabaseId;
     }
 
-    public void updateDomainExceptCertificate(int databaseId, String domainName, boolean javaScriptEnabled, boolean firstPartyCookiesEnabled, boolean thirdPartyCookiesEnabled, boolean domStorageEnabled, boolean formDataEnabled, String userAgent, int fontSize,
-                                              int displayImages, int nightMode, boolean pinnedSslCertificate) {
+    public void updateDomainExceptCertificate(int databaseId, String domainName, boolean javaScriptEnabled, boolean firstPartyCookiesEnabled, boolean thirdPartyCookiesEnabled, boolean domStorageEnabled,
+                                              boolean formDataEnabled, boolean easyListEnabled, boolean easyPrivacyEnabled, boolean fanboysAnnoyanceEnabled, boolean fanboysSocialBlockingEnabled,
+                                              String userAgent, int fontSize, int displayImages, int nightMode, boolean pinnedSslCertificate) {
+
         // Store the domain data in a `ContentValues`.
         ContentValues domainContentValues = new ContentValues();
 
@@ -216,6 +296,10 @@ public class DomainsDatabaseHelper extends SQLiteOpenHelper {
         domainContentValues.put(ENABLE_THIRD_PARTY_COOKIES, thirdPartyCookiesEnabled);
         domainContentValues.put(ENABLE_DOM_STORAGE, domStorageEnabled);
         domainContentValues.put(ENABLE_FORM_DATA, formDataEnabled);
+        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(USER_AGENT, userAgent);
         domainContentValues.put(FONT_SIZE, fontSize);
         domainContentValues.put(DISPLAY_IMAGES, displayImages);
@@ -232,9 +316,12 @@ public class DomainsDatabaseHelper extends SQLiteOpenHelper {
         domainsDatabase.close();
     }
 
-    public void updateDomainWithCertificate(int databaseId, String domainName, boolean javaScriptEnabled, boolean firstPartyCookiesEnabled, boolean thirdPartyCookiesEnabled, boolean domStorageEnabled, boolean formDataEnabled, String userAgent, int fontSize,
-                                            int displayImages, int nightMode, boolean pinnedSslCertificate, String sslIssuedToCommonName, String sslIssuedToOrganization, String sslIssuedToOrganizationalUnit, String sslIssuedByCommonName, String sslIssuedByOrganization,
-                                            String sslIssuedByOrganizationalUnit, long sslStartDate, long sslEndDate) {
+    public void updateDomainWithCertificate(int databaseId, String domainName, boolean javaScriptEnabled, boolean firstPartyCookiesEnabled, boolean thirdPartyCookiesEnabled, boolean domStorageEnabled,
+                                            boolean formDataEnabled, boolean easyListEnabled, boolean easyPrivacyEnabled, boolean fanboysAnnoyanceEnabled, boolean fanboysSocialBlockingEnabled, String userAgent,
+                                            int fontSize, int displayImages, int nightMode, boolean pinnedSslCertificate, String sslIssuedToCommonName, String sslIssuedToOrganization,
+                                            String sslIssuedToOrganizationalUnit, String sslIssuedByCommonName, String sslIssuedByOrganization, String sslIssuedByOrganizationalUnit, long sslStartDate,
+                                            long sslEndDate) {
+
         // Store the domain data in a `ContentValues`.
         ContentValues domainContentValues = new ContentValues();
 
@@ -245,6 +332,10 @@ public class DomainsDatabaseHelper extends SQLiteOpenHelper {
         domainContentValues.put(ENABLE_THIRD_PARTY_COOKIES, thirdPartyCookiesEnabled);
         domainContentValues.put(ENABLE_DOM_STORAGE, domStorageEnabled);
         domainContentValues.put(ENABLE_FORM_DATA, formDataEnabled);
+        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(USER_AGENT, userAgent);
         domainContentValues.put(FONT_SIZE, fontSize);
         domainContentValues.put(DISPLAY_IMAGES, displayImages);
@@ -269,8 +360,8 @@ public class DomainsDatabaseHelper extends SQLiteOpenHelper {
         domainsDatabase.close();
     }
 
-    public void updateCertificate(int databaseId, String sslIssuedToCommonName, String sslIssuedToOrganization, String sslIssuedToOrganizationalUnit, String sslIssuedByCommonName, String sslIssuedByOrganization, String sslIssuedByOrganizationalUnit,
-                                  long sslStartDate, long sslEndDate) {
+    public void updateCertificate(int databaseId, String sslIssuedToCommonName, String sslIssuedToOrganization, String sslIssuedToOrganizationalUnit, String sslIssuedByCommonName,
+                                  String sslIssuedByOrganization, String sslIssuedByOrganizationalUnit, long sslStartDate, long sslEndDate) {
         // Store the domain data in a `ContentValues`.
         ContentValues domainContentValues = new ContentValues();
 
index 40e7cc7..769072a 100644 (file)
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="utf-8"?>
 
 <!--
-  Copyright © 2017 Soren Stoutner <soren@stoutner.com>.
+  Copyright © 2017-2018 Soren Stoutner <soren@stoutner.com>.
 
   This file is part of Privacy Browser <https://www.stoutner.com/privacy-browser>.
 
                 android:textSize="18sp" />
         </LinearLayout>
 
+        <!-- EasyList. -->
+        <LinearLayout
+            android:layout_height="wrap_content"
+            android:layout_width="match_parent"
+            android:orientation="horizontal" >
+
+            <ImageView
+                android:id="@+id/domain_settings_easylist_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/domain_settings_easylist_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/easylist"
+                android:textColor="?android:textColorPrimary"
+                android:textSize="18sp" />
+        </LinearLayout>
+
+        <!-- EasyPrivacy. -->
+        <LinearLayout
+            android:layout_height="wrap_content"
+            android:layout_width="match_parent"
+            android:orientation="horizontal" >
+
+            <ImageView
+                android:id="@+id/domain_settings_easyprivacy_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/domain_settings_easyprivacy_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/easyprivacy"
+                android:textColor="?android:textColorPrimary"
+                android:textSize="18sp" />
+        </LinearLayout>
+
+        <!-- Fanboy's Annoyance List. -->
+        <LinearLayout
+            android:layout_height="wrap_content"
+            android:layout_width="match_parent"
+            android:orientation="horizontal" >
+
+            <ImageView
+                android:id="@+id/domain_settings_fanboys_annoyance_list_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/domain_settings_fanboys_annoyance_list_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/fanboy_annoyance_list"
+                android:textColor="?android:textColorPrimary"
+                android:textSize="18sp" />
+        </LinearLayout>
+
+        <!-- Fanboy's Social Blocking List. -->
+        <LinearLayout
+            android:layout_height="wrap_content"
+            android:layout_width="match_parent"
+            android:orientation="horizontal" >
+
+            <ImageView
+                android:id="@+id/domain_settings_fanboys_social_blocking_list_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/domain_settings_fanboys_social_blocking_list_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/fanboy_social_blocking_list"
+                android:textColor="?android:textColorPrimary"
+                android:textSize="18sp" />
+        </LinearLayout>
+
         <!-- User Agent. -->
         <LinearLayout
             android:layout_height="wrap_content"
                 android:layout_width="match_parent"
                 android:layout_marginStart="40dp"
                 android:layout_marginEnd="60dp"
-                android:inputType="textUri" />
+                android:inputType="textUri"
+                android:hint="@string/custom_user_agent"/>
         </LinearLayout>
 
         <!-- Font Size. -->