From: Soren Stoutner Date: Fri, 26 May 2023 23:44:34 +0000 (-0700) Subject: Change the domain settings switches to spinners. https://redmine.stoutner.com/issues/407 X-Git-Tag: v3.15~6 X-Git-Url: https://gitweb.stoutner.com/?a=commitdiff_plain;h=09795c801b5e5d85beb63259a2d9cb39f756fa61;p=PrivacyBrowserAndroid.git Change the domain settings switches to spinners. https://redmine.stoutner.com/issues/407 --- diff --git a/app/build.gradle b/app/build.gradle index 6d9a6d9e..9465739a 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -83,17 +83,17 @@ dependencies { implementation 'androidx.appcompat:appcompat:1.6.1' implementation 'androidx.cardview:cardview:1.0.0' implementation 'androidx.coordinatorlayout:coordinatorlayout:1.2.0' - implementation 'androidx.core:core-ktx:1.10.0' + implementation 'androidx.core:core-ktx:1.10.1' implementation 'androidx.drawerlayout:drawerlayout:1.2.0' implementation 'androidx.lifecycle:lifecycle-viewmodel-ktx:2.6.1' implementation 'androidx.preference:preference-ktx:1.2.0' implementation 'androidx.swiperefreshlayout:swiperefreshlayout:1.1.0' implementation 'androidx.viewpager:viewpager:1.0.0' - implementation 'androidx.webkit:webkit:1.6.1' + implementation 'androidx.webkit:webkit:1.7.0' // Include the Kotlin standard library. This should be the same version number listed in project build.gradle. implementation 'org.jetbrains.kotlin:kotlin-stdlib:1.8.10' // Include the Google material library. - implementation 'com.google.android.material:material:1.8.0' + implementation 'com.google.android.material:material:1.9.0' } diff --git a/app/src/main/java/com/stoutner/privacybrowser/activities/DomainsActivity.kt b/app/src/main/java/com/stoutner/privacybrowser/activities/DomainsActivity.kt index 1866a66d..5c5107c5 100644 --- a/app/src/main/java/com/stoutner/privacybrowser/activities/DomainsActivity.kt +++ b/app/src/main/java/com/stoutner/privacybrowser/activities/DomainsActivity.kt @@ -35,8 +35,8 @@ import android.widget.RadioButton import android.widget.ScrollView import android.widget.Spinner import android.widget.TextView -import androidx.activity.OnBackPressedCallback +import androidx.activity.OnBackPressedCallback import androidx.appcompat.app.AppCompatActivity import androidx.appcompat.widget.SwitchCompat import androidx.appcompat.widget.Toolbar @@ -55,6 +55,8 @@ import com.stoutner.privacybrowser.fragments.DomainSettingsFragment import com.stoutner.privacybrowser.fragments.DomainsListFragment import com.stoutner.privacybrowser.fragments.DomainsListFragment.DismissSnackbarInterface import com.stoutner.privacybrowser.fragments.DomainsListFragment.SaveDomainSettingsInterface +import com.stoutner.privacybrowser.helpers.DOMAIN_NAME +import com.stoutner.privacybrowser.helpers.ID import com.stoutner.privacybrowser.helpers.DomainsDatabaseHelper // Define the public constants. @@ -485,7 +487,7 @@ class DomainsActivity : AppCompatActivity(), AddDomainListener, DismissSnackbarI override fun bindView(view: View, context: Context, cursor: Cursor) { // Get the domain name string. - val domainNameString = cursor.getString(cursor.getColumnIndexOrThrow(DomainsDatabaseHelper.DOMAIN_NAME)) + val domainNameString = cursor.getString(cursor.getColumnIndexOrThrow(DOMAIN_NAME)) // Get a handle for the domain name text view. val domainNameTextView = view.findViewById(R.id.domain_name_textview) @@ -535,7 +537,7 @@ class DomainsActivity : AppCompatActivity(), AddDomainListener, DismissSnackbarI override fun bindView(view: View, context: Context, cursor: Cursor) { /// Get the domain name string. - val domainNameString = cursor.getString(cursor.getColumnIndexOrThrow(DomainsDatabaseHelper.DOMAIN_NAME)) + val domainNameString = cursor.getString(cursor.getColumnIndexOrThrow(DOMAIN_NAME)) // Get a handle for the domain name text view. val domainNameTextView = view.findViewById(R.id.domain_name_textview) @@ -692,17 +694,17 @@ class DomainsActivity : AppCompatActivity(), AddDomainListener, DismissSnackbarI override fun saveDomainSettings(view: View) { // Get handles for the domain settings. val domainNameEditText = view.findViewById(R.id.domain_settings_name_edittext) - val javaScriptSwitch = view.findViewById(R.id.javascript_switch) - val cookiesSwitch = view.findViewById(R.id.cookies_switch) - val domStorageSwitch = view.findViewById(R.id.dom_storage_switch) - val formDataSwitch = view.findViewById(R.id.form_data_switch) // Form data can be removed once the minimum API >= 26. - val easyListSwitch = view.findViewById(R.id.easylist_switch) - val easyPrivacySwitch = view.findViewById(R.id.easyprivacy_switch) - val fanboysAnnoyanceSwitch = view.findViewById(R.id.fanboys_annoyance_list_switch) - val fanboysSocialBlockingSwitch = view.findViewById(R.id.fanboys_social_blocking_list_switch) - val ultraListSwitch = view.findViewById(R.id.ultralist_switch) - val ultraPrivacySwitch = view.findViewById(R.id.ultraprivacy_switch) - val blockAllThirdPartyRequestsSwitch = view.findViewById(R.id.block_all_third_party_requests_switch) + val javaScriptSpinner = view.findViewById(R.id.javascript_spinner) + val cookiesSpinner = view.findViewById(R.id.cookies_spinner) + val domStorageSpinner = view.findViewById(R.id.dom_storage_spinner) + val formDataSpinner = view.findViewById(R.id.form_data_spinner) // Form data can be removed once the minimum API >= 26. + val easyListSpinner = view.findViewById(R.id.easylist_spinner) + val easyPrivacySpinner = view.findViewById(R.id.easyprivacy_spinner) + val fanboysAnnoyanceSpinner = view.findViewById(R.id.fanboys_annoyance_list_spinner) + val fanboysSocialBlockingSpinner = view.findViewById(R.id.fanboys_social_blocking_list_spinner) + val ultraListSpinner = view.findViewById(R.id.ultralist_spinner) + val ultraPrivacySpinner = view.findViewById(R.id.ultraprivacy_spinner) + val blockAllThirdPartyRequestsSpinner = view.findViewById(R.id.block_all_third_party_requests_spinner) val userAgentSpinner = view.findViewById(R.id.user_agent_spinner) val customUserAgentEditText = view.findViewById(R.id.custom_user_agent_edittext) val fontSizeSpinner = view.findViewById(R.id.font_size_spinner) @@ -718,17 +720,17 @@ class DomainsActivity : AppCompatActivity(), AddDomainListener, DismissSnackbarI // Extract the data for the domain settings. val domainNameString = domainNameEditText.text.toString() - val javaScript = javaScriptSwitch.isChecked - val cookies = cookiesSwitch.isChecked - val domStorage = domStorageSwitch.isChecked - val formData = formDataSwitch.isChecked // Form data can be removed once the minimum API >= 26. - val easyList = easyListSwitch.isChecked - val easyPrivacy = easyPrivacySwitch.isChecked - val fanboysAnnoyance = fanboysAnnoyanceSwitch.isChecked - val fanboysSocialBlocking = fanboysSocialBlockingSwitch.isChecked - val ultraList = ultraListSwitch.isChecked - val ultraPrivacy = ultraPrivacySwitch.isChecked - val blockAllThirdPartyRequests = blockAllThirdPartyRequestsSwitch.isChecked + val javaScriptInt = javaScriptSpinner.selectedItemPosition + val cookiesInt = cookiesSpinner.selectedItemPosition + val domStorageInt = domStorageSpinner.selectedItemPosition + val formDataInt = formDataSpinner.selectedItemPosition // Form data can be removed once the minimum API >= 26. + val easyListInt = easyListSpinner.selectedItemPosition + val easyPrivacyInt = easyPrivacySpinner.selectedItemPosition + val fanboysAnnoyanceInt = fanboysAnnoyanceSpinner.selectedItemPosition + val fanboysSocialBlockingInt = fanboysSocialBlockingSpinner.selectedItemPosition + val ultraListInt = ultraListSpinner.selectedItemPosition + val ultraPrivacyInt = ultraPrivacySpinner.selectedItemPosition + val blockAllThirdPartyRequestsInt = blockAllThirdPartyRequestsSpinner.selectedItemPosition val userAgentSwitchPosition = userAgentSpinner.selectedItemPosition val fontSizeSwitchPosition = fontSizeSpinner.selectedItemPosition val swipeToRefreshInt = swipeToRefreshSpinner.selectedItemPosition @@ -763,8 +765,8 @@ class DomainsActivity : AppCompatActivity(), AddDomainListener, DismissSnackbarI fontSizeInt = customFontSizeEditText.text.toString().toInt() // Save the domain settings. - domainsDatabaseHelper.updateDomain(currentDomainDatabaseId, domainNameString, javaScript, cookies, domStorage, formData, easyList, easyPrivacy, fanboysAnnoyance, fanboysSocialBlocking, ultraList, - ultraPrivacy, blockAllThirdPartyRequests, userAgentName, fontSizeInt, swipeToRefreshInt, webViewThemeInt, wideViewportInt, displayWebpageImagesInt, + domainsDatabaseHelper.updateDomain(currentDomainDatabaseId, domainNameString, javaScriptInt, cookiesInt, domStorageInt, formDataInt, easyListInt, easyPrivacyInt, fanboysAnnoyanceInt, + fanboysSocialBlockingInt, ultraListInt, ultraPrivacyInt, blockAllThirdPartyRequestsInt, userAgentName, fontSizeInt, swipeToRefreshInt, webViewThemeInt, wideViewportInt, displayWebpageImagesInt, pinnedSslCertificate, pinnedIpAddress) // Update the pinned SSL certificate if a new one is checked. @@ -793,7 +795,7 @@ class DomainsActivity : AppCompatActivity(), AddDomainListener, DismissSnackbarI val domainNameTextView = view.findViewById(R.id.domain_name_textview) // Get the domain name string. - val domainNameString = cursor.getString(cursor.getColumnIndexOrThrow(DomainsDatabaseHelper.DOMAIN_NAME)) + val domainNameString = cursor.getString(cursor.getColumnIndexOrThrow(DOMAIN_NAME)) // Set the domain name. domainNameTextView.text = domainNameString @@ -820,7 +822,7 @@ class DomainsActivity : AppCompatActivity(), AddDomainListener, DismissSnackbarI domainsCursor.moveToPosition(i) // Get the database ID for this position. - val currentDatabaseId = domainsCursor.getInt(domainsCursor.getColumnIndexOrThrow(DomainsDatabaseHelper.ID)) + val currentDatabaseId = domainsCursor.getInt(domainsCursor.getColumnIndexOrThrow(ID)) // Set the highlighted domain position if the database ID for this matches the highlighted domain database ID. if (highlightedDomainDatabaseId == currentDatabaseId) @@ -834,7 +836,7 @@ class DomainsActivity : AppCompatActivity(), AddDomainListener, DismissSnackbarI domainsCursor.moveToPosition(highlightedDomainPosition) // Get the database ID for the highlighted domain. - currentDomainDatabaseId = domainsCursor.getInt(domainsCursor.getColumnIndexOrThrow(DomainsDatabaseHelper.ID)) + currentDomainDatabaseId = domainsCursor.getInt(domainsCursor.getColumnIndexOrThrow(ID)) // Create an arguments bundle. val argumentsBundle = Bundle() diff --git a/app/src/main/java/com/stoutner/privacybrowser/activities/ImportExportActivity.kt b/app/src/main/java/com/stoutner/privacybrowser/activities/ImportExportActivity.kt index 245bd598..f53e44a2 100644 --- a/app/src/main/java/com/stoutner/privacybrowser/activities/ImportExportActivity.kt +++ b/app/src/main/java/com/stoutner/privacybrowser/activities/ImportExportActivity.kt @@ -36,8 +36,8 @@ import android.widget.LinearLayout import android.widget.RadioButton import android.widget.Spinner import android.widget.TextView -import androidx.activity.result.contract.ActivityResultContracts +import androidx.activity.result.contract.ActivityResultContracts import androidx.appcompat.app.AppCompatActivity import androidx.appcompat.widget.Toolbar import androidx.cardview.widget.CardView @@ -49,6 +49,9 @@ import com.google.android.material.textfield.TextInputLayout import com.stoutner.privacybrowser.R import com.stoutner.privacybrowser.BuildConfig +import com.stoutner.privacybrowser.helpers.EXPORT_SUCCESSFUL +import com.stoutner.privacybrowser.helpers.IMPORT_EXPORT_SCHEMA_VERSION +import com.stoutner.privacybrowser.helpers.IMPORT_SUCCESSFUL import com.stoutner.privacybrowser.helpers.ImportExportDatabaseHelper import java.io.File @@ -392,7 +395,7 @@ class ImportExportActivity : AppCompatActivity() { savedInstanceState.putString(IMPORT_EXPORT_BUTTON_TEXT, importExportButton.text.toString()) } - fun onClickRadioButton(@Suppress("UNUSED_PARAMETER") view: View) { + fun onClickRadioButton(view: View) { // Check to see if import or export was selected. if (view.id == R.id.import_radiobutton) { // The import radio button is selected. // Check to see if OpenPGP encryption is selected. @@ -457,9 +460,9 @@ class ImportExportActivity : AppCompatActivity() { } else { // Export is selected // Open the file picker with the export name according to the encryption type. if (encryptionSpinner.selectedItemPosition == NO_ENCRYPTION) // No encryption is selected. - browseForExportActivityResultLauncher.launch(getString(R.string.privacy_browser_settings_pbs, BuildConfig.VERSION_NAME, ImportExportDatabaseHelper.SCHEMA_VERSION)) + browseForExportActivityResultLauncher.launch(getString(R.string.privacy_browser_settings_pbs, BuildConfig.VERSION_NAME, IMPORT_EXPORT_SCHEMA_VERSION)) else // Password encryption is selected. - browseForExportActivityResultLauncher.launch(getString(R.string.privacy_browser_settings_pbs_aes, BuildConfig.VERSION_NAME, ImportExportDatabaseHelper.SCHEMA_VERSION)) + browseForExportActivityResultLauncher.launch(getString(R.string.privacy_browser_settings_pbs_aes, BuildConfig.VERSION_NAME, IMPORT_EXPORT_SCHEMA_VERSION)) } } @@ -494,7 +497,7 @@ class ImportExportActivity : AppCompatActivity() { } // Restart Privacy Browser if successful. - if (importStatus == ImportExportDatabaseHelper.IMPORT_SUCCESSFUL) + if (importStatus == IMPORT_SUCCESSFUL) restartPrivacyBrowser() } @@ -600,7 +603,7 @@ class ImportExportActivity : AppCompatActivity() { temporaryUnencryptedImportFile.delete() // Restart Privacy Browser if successful. - if (importStatus == ImportExportDatabaseHelper.IMPORT_SUCCESSFUL) + if (importStatus == IMPORT_SUCCESSFUL) restartPrivacyBrowser() } catch (exception: Exception) { // Update the import status. @@ -658,7 +661,7 @@ class ImportExportActivity : AppCompatActivity() { openKeychainDecryptActivityResultLauncher.launch(openKeychainDecryptIntent) // Update the import status. - importStatus = ImportExportDatabaseHelper.IMPORT_SUCCESSFUL + importStatus = IMPORT_SUCCESSFUL } catch (exception: Exception) { // Update the import status. importStatus = exception.toString() @@ -666,11 +669,9 @@ class ImportExportActivity : AppCompatActivity() { } } - // Respond to the import status. - if (importStatus != ImportExportDatabaseHelper.IMPORT_SUCCESSFUL) { - // Display a snack bar with the import error. + // Display a snack bar with the import error if it was unsuccessful. + if (importStatus != IMPORT_SUCCESSFUL) Snackbar.make(fileNameEditText, getString(R.string.import_failed, importStatus), Snackbar.LENGTH_INDEFINITE).show() - } } else { // Export is selected. // Export according to the encryption type. when (encryptionSpinner.selectedItemPosition) { @@ -690,11 +691,10 @@ class ImportExportActivity : AppCompatActivity() { exportFileOutputStream.close() // Display an export disposition snackbar. - if (noEncryptionExportStatus == ImportExportDatabaseHelper.EXPORT_SUCCESSFUL) { + if (noEncryptionExportStatus == EXPORT_SUCCESSFUL) Snackbar.make(fileNameEditText, getString(R.string.export_successful), Snackbar.LENGTH_SHORT).show() - } else { + else Snackbar.make(fileNameEditText, getString(R.string.export_failed, noEncryptionExportStatus), Snackbar.LENGTH_INDEFINITE).show() - } } catch (fileNotFoundException: FileNotFoundException) { // Display a snackbar with the exception. Snackbar.make(fileNameEditText, getString(R.string.export_failed, fileNotFoundException), Snackbar.LENGTH_INDEFINITE).show() @@ -810,7 +810,7 @@ class ImportExportActivity : AppCompatActivity() { temporaryUnencryptedExportFile.delete() // Display an export disposition snackbar. - if (passwordEncryptionExportStatus == ImportExportDatabaseHelper.EXPORT_SUCCESSFUL) + if (passwordEncryptionExportStatus == EXPORT_SUCCESSFUL) Snackbar.make(fileNameEditText, getString(R.string.export_successful), Snackbar.LENGTH_SHORT).show() else Snackbar.make(fileNameEditText, getString(R.string.export_failed, passwordEncryptionExportStatus), Snackbar.LENGTH_INDEFINITE).show() @@ -830,7 +830,7 @@ class ImportExportActivity : AppCompatActivity() { // Set the temporary pre-encrypted export file. temporaryPreEncryptedExportFile = File(fileProviderDirectory.toString() + "/" + - getString(R.string.privacy_browser_settings_pbs, BuildConfig.VERSION_NAME, ImportExportDatabaseHelper.SCHEMA_VERSION)) + getString(R.string.privacy_browser_settings_pbs, BuildConfig.VERSION_NAME, IMPORT_EXPORT_SCHEMA_VERSION)) // Delete the temporary pre-encrypted export file if it already exists. if (temporaryPreEncryptedExportFile.exists()) @@ -849,7 +849,7 @@ class ImportExportActivity : AppCompatActivity() { temporaryPreEncryptedExportOutputStream.close() // Display an export error snackbar if the temporary pre-encrypted export failed. - if (openpgpEncryptionExportStatus != ImportExportDatabaseHelper.EXPORT_SUCCESSFUL) + if (openpgpEncryptionExportStatus != EXPORT_SUCCESSFUL) Snackbar.make(fileNameEditText, getString(R.string.export_failed, openpgpEncryptionExportStatus), Snackbar.LENGTH_INDEFINITE).show() // Create an encryption intent for OpenKeychain. @@ -898,4 +898,4 @@ class ImportExportActivity : AppCompatActivity() { // Restart Privacy Browser after 150 milliseconds to allow enough time for the preferences to be saved. restartHandler.postDelayed(restartRunnable, 150) } -} \ No newline at end of file +} diff --git a/app/src/main/java/com/stoutner/privacybrowser/activities/MainWebViewActivity.kt b/app/src/main/java/com/stoutner/privacybrowser/activities/MainWebViewActivity.kt index e2571187..16b40d85 100644 --- a/app/src/main/java/com/stoutner/privacybrowser/activities/MainWebViewActivity.kt +++ b/app/src/main/java/com/stoutner/privacybrowser/activities/MainWebViewActivity.kt @@ -137,10 +137,40 @@ import com.stoutner.privacybrowser.dialogs.UrlHistoryDialog import com.stoutner.privacybrowser.dialogs.ViewSslCertificateDialog import com.stoutner.privacybrowser.dialogs.WaitingForProxyDialog import com.stoutner.privacybrowser.fragments.WebViewTabFragment +import com.stoutner.privacybrowser.helpers.COOKIES +import com.stoutner.privacybrowser.helpers.DARK_THEME +import com.stoutner.privacybrowser.helpers.DISABLED +import com.stoutner.privacybrowser.helpers.DISPLAY_IMAGES +import com.stoutner.privacybrowser.helpers.DOMAIN_NAME +import com.stoutner.privacybrowser.helpers.ENABLE_DOM_STORAGE +import com.stoutner.privacybrowser.helpers.ENABLE_EASYLIST +import com.stoutner.privacybrowser.helpers.ENABLE_EASYPRIVACY +import com.stoutner.privacybrowser.helpers.ENABLE_FANBOYS_ANNOYANCE_LIST +import com.stoutner.privacybrowser.helpers.ENABLE_FANBOYS_SOCIAL_BLOCKING_LIST +import com.stoutner.privacybrowser.helpers.ENABLE_FORM_DATA +import com.stoutner.privacybrowser.helpers.ENABLE_JAVASCRIPT +import com.stoutner.privacybrowser.helpers.ENABLE_ULTRAPRIVACY +import com.stoutner.privacybrowser.helpers.ENABLED +import com.stoutner.privacybrowser.helpers.FONT_SIZE +import com.stoutner.privacybrowser.helpers.ID +import com.stoutner.privacybrowser.helpers.IP_ADDRESSES +import com.stoutner.privacybrowser.helpers.LIGHT_THEME +import com.stoutner.privacybrowser.helpers.PINNED_IP_ADDRESSES +import com.stoutner.privacybrowser.helpers.PINNED_SSL_CERTIFICATE import com.stoutner.privacybrowser.helpers.REQUEST_ALLOWED import com.stoutner.privacybrowser.helpers.REQUEST_BLOCKED import com.stoutner.privacybrowser.helpers.REQUEST_DEFAULT import com.stoutner.privacybrowser.helpers.REQUEST_THIRD_PARTY +import com.stoutner.privacybrowser.helpers.SSL_ISSUED_BY_COMMON_NAME +import com.stoutner.privacybrowser.helpers.SSL_ISSUED_BY_ORGANIZATION +import com.stoutner.privacybrowser.helpers.SSL_ISSUED_BY_ORGANIZATIONAL_UNIT +import com.stoutner.privacybrowser.helpers.SSL_ISSUED_TO_COMMON_NAME +import com.stoutner.privacybrowser.helpers.SSL_ISSUED_TO_ORGANIZATION +import com.stoutner.privacybrowser.helpers.SSL_ISSUED_TO_ORGANIZATIONAL_UNIT +import com.stoutner.privacybrowser.helpers.SWIPE_TO_REFRESH +import com.stoutner.privacybrowser.helpers.SYSTEM_DEFAULT +import com.stoutner.privacybrowser.helpers.WEBVIEW_THEME +import com.stoutner.privacybrowser.helpers.WIDE_VIEWPORT import com.stoutner.privacybrowser.helpers.BookmarksDatabaseHelper import com.stoutner.privacybrowser.helpers.CheckFilterListHelper import com.stoutner.privacybrowser.helpers.DomainsDatabaseHelper @@ -153,7 +183,6 @@ import com.stoutner.privacybrowser.views.EASYPRIVACY import com.stoutner.privacybrowser.views.FANBOYS_ANNOYANCE_LIST import com.stoutner.privacybrowser.views.FANBOYS_SOCIAL_BLOCKING_LIST import com.stoutner.privacybrowser.views.THIRD_PARTY_REQUESTS -import com.stoutner.privacybrowser.views.ULTRALIST import com.stoutner.privacybrowser.views.ULTRAPRIVACY import com.stoutner.privacybrowser.views.NestedScrollWebView @@ -226,6 +255,9 @@ class MainWebViewActivity : AppCompatActivity(), CreateBookmarkDialog.CreateBook private lateinit var bookmarksTitleTextView: TextView private lateinit var coordinatorLayout: CoordinatorLayout private lateinit var cookieManager: CookieManager + private lateinit var defaultFontSizeString: String + private lateinit var defaultUserAgentName: String + private lateinit var defaultWebViewTheme: String private lateinit var domainsSettingsSet: MutableSet private lateinit var drawerLayout: DrawerLayout private lateinit var easyList: ArrayList>> @@ -296,10 +328,13 @@ class MainWebViewActivity : AppCompatActivity(), CreateBookmarkDialog.CreateBook private lateinit var tabsLinearLayout: LinearLayout private lateinit var toolbar: Toolbar private lateinit var webViewDefaultUserAgent: String + private lateinit var webViewThemeEntryValuesStringArray: Array private lateinit var webViewViewPager2: ViewPager2 private lateinit var ultraList: ArrayList>> private lateinit var urlEditText: EditText private lateinit var urlRelativeLayout: RelativeLayout + private lateinit var userAgentDataArray: Array + private lateinit var userAgentNamesArray: ArrayAdapter // Define the class variables. private var actionBarDrawerToggle: ActionBarDrawerToggle? = null @@ -309,8 +344,22 @@ class MainWebViewActivity : AppCompatActivity(), CreateBookmarkDialog.CreateBook private var bookmarksDrawerPinned = false private var bottomAppBar = false private var currentWebView: NestedScrollWebView? = null + private var defaultBlockAllThirdPartyRequests = false + private var defaultCookies = false + private var defaultDisplayWebpageImages = true + private var defaultDomStorage = false + private var defaultEasyList = true + private var defaultEasyPrivacy = true + private var defaultFanboysAnnoyanceList = true + private var defaultFanboysSocialBlockingList = true + private var defaultFormData = false // Form data can be removed once the minimum API >= 26. private var defaultProgressViewEndOffset = 0 private var defaultProgressViewStartOffset = 0 + private var defaultJavaScript = false + private var defaultSwipeToRefresh = true + private var defaultUltraList = true + private var defaultUltraPrivacy = true + private var defaultWideViewport = true private var displayAdditionalAppBarIcons = false private var displayingFullScreenVideo = false private var domainsDatabaseHelper: DomainsDatabaseHelper? = null @@ -1057,7 +1106,7 @@ class MainWebViewActivity : AppCompatActivity(), CreateBookmarkDialog.CreateBook // Set the status of the menu item checkboxes. optionsDomStorageMenuItem.isChecked = currentWebView!!.settings.domStorageEnabled @Suppress("DEPRECATION") - optionsSaveFormDataMenuItem.isChecked = currentWebView!!.settings.saveFormData // Form data can be removed once the minimum API >= 26. + optionsSaveFormDataMenuItem.isChecked = currentWebView!!.settings.saveFormData // Form data can be removed once the minimum API >= 26. optionsEasyListMenuItem.isChecked = currentWebView!!.easyListEnabled optionsEasyPrivacyMenuItem.isChecked = currentWebView!!.easyPrivacyEnabled optionsFanboysAnnoyanceListMenuItem.isChecked = currentWebView!!.fanboysAnnoyanceListEnabled @@ -1075,7 +1124,7 @@ class MainWebViewActivity : AppCompatActivity(), CreateBookmarkDialog.CreateBook optionsEasyPrivacyMenuItem.title = currentWebView!!.getRequestsCount(EASYPRIVACY).toString() + " - " + getString(R.string.easyprivacy) optionsFanboysAnnoyanceListMenuItem.title = currentWebView!!.getRequestsCount(FANBOYS_ANNOYANCE_LIST).toString() + " - " + getString(R.string.fanboys_annoyance_list) optionsFanboysSocialBlockingListMenuItem.title = currentWebView!!.getRequestsCount(FANBOYS_SOCIAL_BLOCKING_LIST).toString() + " - " + getString(R.string.fanboys_social_blocking_list) - optionsUltraListMenuItem.title = currentWebView!!.getRequestsCount(ULTRALIST).toString() + " - " + getString(R.string.ultralist) + optionsUltraListMenuItem.title = currentWebView!!.getRequestsCount(com.stoutner.privacybrowser.views.ULTRALIST).toString() + " - " + getString(R.string.ultralist) optionsUltraPrivacyMenuItem.title = currentWebView!!.getRequestsCount(ULTRAPRIVACY).toString() + " - " + getString(R.string.ultraprivacy) optionsBlockAllThirdPartyRequestsMenuItem.title = currentWebView!!.getRequestsCount(THIRD_PARTY_REQUESTS).toString() + " - " + getString(R.string.block_all_third_party_requests) @@ -2707,6 +2756,32 @@ class MainWebViewActivity : AppCompatActivity(), CreateBookmarkDialog.CreateBook } private fun applyAppSettings() { + // Store the default preferences used in `applyDomainSettings()`. These are done here so that expensive preference requests are not done each time a domain is loaded. + defaultJavaScript = sharedPreferences.getBoolean(getString(R.string.javascript_key), false) + defaultCookies = sharedPreferences.getBoolean(getString(R.string.cookies_key), false) + defaultDomStorage = sharedPreferences.getBoolean(getString(R.string.dom_storage_key), false) + defaultFormData = sharedPreferences.getBoolean(getString(R.string.save_form_data_key), false) // Form data can be removed once the minimum API >= 26. + defaultEasyList = sharedPreferences.getBoolean(getString(R.string.easylist_key), true) + defaultEasyPrivacy = sharedPreferences.getBoolean(getString(R.string.easyprivacy_key), true) + defaultFanboysAnnoyanceList = sharedPreferences.getBoolean(getString(R.string.fanboys_annoyance_list_key), true) + defaultFanboysSocialBlockingList = sharedPreferences.getBoolean(getString(R.string.fanboys_social_blocking_list_key), true) + defaultUltraList = sharedPreferences.getBoolean(getString(R.string.ultralist_key), true) + defaultUltraPrivacy = sharedPreferences.getBoolean(getString(R.string.ultraprivacy_key), true) + defaultBlockAllThirdPartyRequests = sharedPreferences.getBoolean(getString(R.string.block_all_third_party_requests_key), false) + defaultFontSizeString = sharedPreferences.getString(getString(R.string.font_size_key), getString(R.string.font_size_default_value))!! + defaultUserAgentName = sharedPreferences.getString(getString(R.string.user_agent_key), getString(R.string.user_agent_default_value))!! + defaultSwipeToRefresh = sharedPreferences.getBoolean(getString(R.string.swipe_to_refresh_key), true) + defaultWebViewTheme = sharedPreferences.getString(getString(R.string.webview_theme_key), getString(R.string.webview_theme_default_value))!! + defaultWideViewport = sharedPreferences.getBoolean(getString(R.string.wide_viewport_key), true) + defaultDisplayWebpageImages = sharedPreferences.getBoolean(getString(R.string.display_webpage_images_key), true) + + // Get the WebView theme entry values string array. This is done here so that expensive resource requests are not made each time a domain is loaded. + webViewThemeEntryValuesStringArray = resources.getStringArray(R.array.webview_theme_entry_values) + + // Get the user agent array adapter and string array. These are done here so that expensive resource requests are not made each time a domain is loaded. + userAgentNamesArray = ArrayAdapter.createFromResource(this, R.array.user_agent_names, R.layout.spinner_item) + userAgentDataArray = resources.getStringArray(R.array.user_agent_data) + // Store the values from the shared preferences in variables. incognitoModeEnabled = sharedPreferences.getBoolean(getString(R.string.incognito_mode_key), false) sanitizeTrackingQueries = sharedPreferences.getBoolean(getString(R.string.tracking_queries_key), true) @@ -2861,7 +2936,7 @@ class MainWebViewActivity : AppCompatActivity(), CreateBookmarkDialog.CreateBook newHostName = "" // Apply the domain settings if a new domain is being loaded or if the new domain is blank. This allows the user to set temporary settings for JavaScript, cookies, DOM storage, etc. - if (nestedScrollWebView.currentDomainName != newHostName || newHostName == "") { + if ((nestedScrollWebView.currentDomainName != newHostName) || (newHostName == "")) { // A new domain is being loaded. // Set the new host name as the current domain name. nestedScrollWebView.currentDomainName = newHostName @@ -2929,22 +3004,7 @@ class MainWebViewActivity : AppCompatActivity(), CreateBookmarkDialog.CreateBook newHostName = newHostName.substring(newHostName.indexOf(".") + 1) } - // Store the general preference information. - val defaultFontSizeString = sharedPreferences.getString(getString(R.string.font_size_key), getString(R.string.font_size_default_value)) - val defaultUserAgentName = sharedPreferences.getString(getString(R.string.user_agent_key), getString(R.string.user_agent_default_value)) - val defaultSwipeToRefresh = sharedPreferences.getBoolean(getString(R.string.swipe_to_refresh_key), true) - val webViewTheme = sharedPreferences.getString(getString(R.string.webview_theme_key), getString(R.string.webview_theme_default_value)) - val wideViewport = sharedPreferences.getBoolean(getString(R.string.wide_viewport_key), true) - val displayWebpageImages = sharedPreferences.getBoolean(getString(R.string.display_webpage_images_key), true) - - // Get the WebView theme entry values string array. - val webViewThemeEntryValuesStringArray = resources.getStringArray(R.array.webview_theme_entry_values) - - // Initialize the user agent array adapter and string array. - val userAgentNamesArray = ArrayAdapter.createFromResource(this, R.array.user_agent_names, R.layout.spinner_item) - val userAgentDataArray = resources.getStringArray(R.array.user_agent_data) - - // Apply either the domain settings for the default settings. + // Apply either the domain settings or the default settings. if (nestedScrollWebView.domainSettingsApplied) { // The url has custom domain settings. // Get a cursor for the current host. val currentDomainSettingsCursor = domainsDatabaseHelper!!.getCursorForDomainName(domainNameInDatabase!!) @@ -2953,69 +3013,121 @@ class MainWebViewActivity : AppCompatActivity(), CreateBookmarkDialog.CreateBook currentDomainSettingsCursor.moveToFirst() // Get the settings from the cursor. - nestedScrollWebView.domainSettingsDatabaseId = currentDomainSettingsCursor.getInt(currentDomainSettingsCursor.getColumnIndexOrThrow(DomainsDatabaseHelper.ID)) - nestedScrollWebView.settings.javaScriptEnabled = currentDomainSettingsCursor.getInt(currentDomainSettingsCursor.getColumnIndexOrThrow(DomainsDatabaseHelper.ENABLE_JAVASCRIPT)) == 1 - nestedScrollWebView.acceptCookies = currentDomainSettingsCursor.getInt(currentDomainSettingsCursor.getColumnIndexOrThrow(DomainsDatabaseHelper.COOKIES)) == 1 - nestedScrollWebView.settings.domStorageEnabled = currentDomainSettingsCursor.getInt(currentDomainSettingsCursor.getColumnIndexOrThrow(DomainsDatabaseHelper.ENABLE_DOM_STORAGE)) == 1 - // Form data can be removed once the minimum API >= 26. - val saveFormData = currentDomainSettingsCursor.getInt(currentDomainSettingsCursor.getColumnIndexOrThrow(DomainsDatabaseHelper.ENABLE_FORM_DATA)) == 1 - nestedScrollWebView.easyListEnabled = currentDomainSettingsCursor.getInt(currentDomainSettingsCursor.getColumnIndexOrThrow(DomainsDatabaseHelper.ENABLE_EASYLIST)) == 1 - nestedScrollWebView.easyPrivacyEnabled = currentDomainSettingsCursor.getInt(currentDomainSettingsCursor.getColumnIndexOrThrow(DomainsDatabaseHelper.ENABLE_EASYPRIVACY)) == 1 - nestedScrollWebView.fanboysAnnoyanceListEnabled = currentDomainSettingsCursor.getInt(currentDomainSettingsCursor.getColumnIndexOrThrow(DomainsDatabaseHelper.ENABLE_FANBOYS_ANNOYANCE_LIST)) == 1 - nestedScrollWebView.fanboysSocialBlockingListEnabled = - currentDomainSettingsCursor.getInt(currentDomainSettingsCursor.getColumnIndexOrThrow(DomainsDatabaseHelper.ENABLE_FANBOYS_SOCIAL_BLOCKING_LIST)) == 1 - nestedScrollWebView.ultraListEnabled = currentDomainSettingsCursor.getInt(currentDomainSettingsCursor.getColumnIndexOrThrow(DomainsDatabaseHelper.ULTRALIST)) == 1 - nestedScrollWebView.ultraPrivacyEnabled = currentDomainSettingsCursor.getInt(currentDomainSettingsCursor.getColumnIndexOrThrow(DomainsDatabaseHelper.ENABLE_ULTRAPRIVACY)) == 1 - nestedScrollWebView.blockAllThirdPartyRequests = currentDomainSettingsCursor.getInt(currentDomainSettingsCursor.getColumnIndexOrThrow(DomainsDatabaseHelper.BLOCK_ALL_THIRD_PARTY_REQUESTS)) == 1 - val userAgentName = currentDomainSettingsCursor.getString(currentDomainSettingsCursor.getColumnIndexOrThrow(DomainsDatabaseHelper.USER_AGENT)) - val fontSize = currentDomainSettingsCursor.getInt(currentDomainSettingsCursor.getColumnIndexOrThrow(DomainsDatabaseHelper.FONT_SIZE)) - val swipeToRefreshInt = currentDomainSettingsCursor.getInt(currentDomainSettingsCursor.getColumnIndexOrThrow(DomainsDatabaseHelper.SWIPE_TO_REFRESH)) - val webViewThemeInt = currentDomainSettingsCursor.getInt(currentDomainSettingsCursor.getColumnIndexOrThrow(DomainsDatabaseHelper.WEBVIEW_THEME)) - val wideViewportInt = currentDomainSettingsCursor.getInt(currentDomainSettingsCursor.getColumnIndexOrThrow(DomainsDatabaseHelper.WIDE_VIEWPORT)) - val displayWebpageImagesInt = currentDomainSettingsCursor.getInt(currentDomainSettingsCursor.getColumnIndexOrThrow(DomainsDatabaseHelper.DISPLAY_IMAGES)) - val pinnedSslCertificate = currentDomainSettingsCursor.getInt(currentDomainSettingsCursor.getColumnIndexOrThrow(DomainsDatabaseHelper.PINNED_SSL_CERTIFICATE)) == 1 - val pinnedSslIssuedToCName = currentDomainSettingsCursor.getString(currentDomainSettingsCursor.getColumnIndexOrThrow(DomainsDatabaseHelper.SSL_ISSUED_TO_COMMON_NAME)) - val pinnedSslIssuedToOName = currentDomainSettingsCursor.getString(currentDomainSettingsCursor.getColumnIndexOrThrow(DomainsDatabaseHelper.SSL_ISSUED_TO_ORGANIZATION)) - val pinnedSslIssuedToUName = currentDomainSettingsCursor.getString(currentDomainSettingsCursor.getColumnIndexOrThrow(DomainsDatabaseHelper.SSL_ISSUED_TO_ORGANIZATIONAL_UNIT)) - val pinnedSslIssuedByCName = currentDomainSettingsCursor.getString(currentDomainSettingsCursor.getColumnIndexOrThrow(DomainsDatabaseHelper.SSL_ISSUED_BY_COMMON_NAME)) - val pinnedSslIssuedByOName = currentDomainSettingsCursor.getString(currentDomainSettingsCursor.getColumnIndexOrThrow(DomainsDatabaseHelper.SSL_ISSUED_BY_ORGANIZATION)) - val pinnedSslIssuedByUName = currentDomainSettingsCursor.getString(currentDomainSettingsCursor.getColumnIndexOrThrow(DomainsDatabaseHelper.SSL_ISSUED_BY_ORGANIZATIONAL_UNIT)) - val pinnedSslStartDate = Date(currentDomainSettingsCursor.getLong(currentDomainSettingsCursor.getColumnIndexOrThrow(DomainsDatabaseHelper.SSL_START_DATE))) - val pinnedSslEndDate = Date(currentDomainSettingsCursor.getLong(currentDomainSettingsCursor.getColumnIndexOrThrow(DomainsDatabaseHelper.SSL_END_DATE))) - val pinnedIpAddresses = currentDomainSettingsCursor.getInt(currentDomainSettingsCursor.getColumnIndexOrThrow(DomainsDatabaseHelper.PINNED_IP_ADDRESSES)) == 1 - val pinnedHostIpAddresses = currentDomainSettingsCursor.getString(currentDomainSettingsCursor.getColumnIndexOrThrow(DomainsDatabaseHelper.IP_ADDRESSES)) + nestedScrollWebView.domainSettingsDatabaseId = currentDomainSettingsCursor.getInt(currentDomainSettingsCursor.getColumnIndexOrThrow(ID)) + val javaScriptInt = currentDomainSettingsCursor.getInt(currentDomainSettingsCursor.getColumnIndexOrThrow(ENABLE_JAVASCRIPT)) + val cookiesInt = currentDomainSettingsCursor.getInt(currentDomainSettingsCursor.getColumnIndexOrThrow(COOKIES)) + val domStorageInt = currentDomainSettingsCursor.getInt(currentDomainSettingsCursor.getColumnIndexOrThrow(ENABLE_DOM_STORAGE)) + val formDataInt = currentDomainSettingsCursor.getInt(currentDomainSettingsCursor.getColumnIndexOrThrow(ENABLE_FORM_DATA)) // Form data can be removed once the minimum API >= 26. + val easyListInt = currentDomainSettingsCursor.getInt(currentDomainSettingsCursor.getColumnIndexOrThrow(ENABLE_EASYLIST)) + val easyPrivacyInt = currentDomainSettingsCursor.getInt(currentDomainSettingsCursor.getColumnIndexOrThrow(ENABLE_EASYPRIVACY)) + val fanboysAnnoyanceListInt = currentDomainSettingsCursor.getInt(currentDomainSettingsCursor.getColumnIndexOrThrow(ENABLE_FANBOYS_ANNOYANCE_LIST)) + val fanboysSocialBlockingListInt = currentDomainSettingsCursor.getInt(currentDomainSettingsCursor.getColumnIndexOrThrow(ENABLE_FANBOYS_SOCIAL_BLOCKING_LIST)) + val ultraListInt = currentDomainSettingsCursor.getInt(currentDomainSettingsCursor.getColumnIndexOrThrow(com.stoutner.privacybrowser.helpers.ULTRALIST)) + val ultraPrivacyInt = currentDomainSettingsCursor.getInt(currentDomainSettingsCursor.getColumnIndexOrThrow(ENABLE_ULTRAPRIVACY)) + val blockAllThirdPartyRequestsInt = currentDomainSettingsCursor.getInt(currentDomainSettingsCursor.getColumnIndexOrThrow(com.stoutner.privacybrowser.helpers.BLOCK_ALL_THIRD_PARTY_REQUESTS)) + val userAgentName = currentDomainSettingsCursor.getString(currentDomainSettingsCursor.getColumnIndexOrThrow(com.stoutner.privacybrowser.helpers.USER_AGENT)) + val fontSize = currentDomainSettingsCursor.getInt(currentDomainSettingsCursor.getColumnIndexOrThrow(FONT_SIZE)) + val swipeToRefreshInt = currentDomainSettingsCursor.getInt(currentDomainSettingsCursor.getColumnIndexOrThrow(SWIPE_TO_REFRESH)) + val webViewThemeInt = currentDomainSettingsCursor.getInt(currentDomainSettingsCursor.getColumnIndexOrThrow(WEBVIEW_THEME)) + val wideViewportInt = currentDomainSettingsCursor.getInt(currentDomainSettingsCursor.getColumnIndexOrThrow(WIDE_VIEWPORT)) + val displayWebpageImagesInt = currentDomainSettingsCursor.getInt(currentDomainSettingsCursor.getColumnIndexOrThrow(DISPLAY_IMAGES)) + val pinnedSslCertificate = (currentDomainSettingsCursor.getInt(currentDomainSettingsCursor.getColumnIndexOrThrow(PINNED_SSL_CERTIFICATE)) == 1) + val pinnedSslIssuedToCName = currentDomainSettingsCursor.getString(currentDomainSettingsCursor.getColumnIndexOrThrow(SSL_ISSUED_TO_COMMON_NAME)) + val pinnedSslIssuedToOName = currentDomainSettingsCursor.getString(currentDomainSettingsCursor.getColumnIndexOrThrow(SSL_ISSUED_TO_ORGANIZATION)) + val pinnedSslIssuedToUName = currentDomainSettingsCursor.getString(currentDomainSettingsCursor.getColumnIndexOrThrow(SSL_ISSUED_TO_ORGANIZATIONAL_UNIT)) + val pinnedSslIssuedByCName = currentDomainSettingsCursor.getString(currentDomainSettingsCursor.getColumnIndexOrThrow(SSL_ISSUED_BY_COMMON_NAME)) + val pinnedSslIssuedByOName = currentDomainSettingsCursor.getString(currentDomainSettingsCursor.getColumnIndexOrThrow(SSL_ISSUED_BY_ORGANIZATION)) + val pinnedSslIssuedByUName = currentDomainSettingsCursor.getString(currentDomainSettingsCursor.getColumnIndexOrThrow(SSL_ISSUED_BY_ORGANIZATIONAL_UNIT)) + val pinnedSslStartDate = Date(currentDomainSettingsCursor.getLong(currentDomainSettingsCursor.getColumnIndexOrThrow(com.stoutner.privacybrowser.helpers.SSL_START_DATE))) + val pinnedSslEndDate = Date(currentDomainSettingsCursor.getLong(currentDomainSettingsCursor.getColumnIndexOrThrow(com.stoutner.privacybrowser.helpers.SSL_END_DATE))) + val pinnedIpAddresses = (currentDomainSettingsCursor.getInt(currentDomainSettingsCursor.getColumnIndexOrThrow(PINNED_IP_ADDRESSES)) == 1) + val pinnedHostIpAddresses = currentDomainSettingsCursor.getString(currentDomainSettingsCursor.getColumnIndexOrThrow(IP_ADDRESSES)) // Close the current host domain settings cursor. currentDomainSettingsCursor.close() - // If there is a pinned SSL certificate, store it in the WebView. - if (pinnedSslCertificate) - nestedScrollWebView.setPinnedSslCertificate(pinnedSslIssuedToCName, pinnedSslIssuedToOName, pinnedSslIssuedToUName, pinnedSslIssuedByCName, pinnedSslIssuedByOName, pinnedSslIssuedByUName, - pinnedSslStartDate, pinnedSslEndDate) + // Set the JavaScript status. + when (javaScriptInt) { + SYSTEM_DEFAULT -> nestedScrollWebView.settings.javaScriptEnabled = defaultJavaScript + ENABLED -> nestedScrollWebView.settings.javaScriptEnabled = true + DISABLED -> nestedScrollWebView.settings.javaScriptEnabled = false + } - // If there is a pinned IP address, store it in the WebView. - if (pinnedIpAddresses) - nestedScrollWebView.pinnedIpAddresses = pinnedHostIpAddresses + // Store the cookies status. + when (cookiesInt) { + SYSTEM_DEFAULT -> nestedScrollWebView.acceptCookies = defaultCookies + ENABLED -> nestedScrollWebView.acceptCookies = true + DISABLED -> nestedScrollWebView.acceptCookies = false + } - // Apply the cookie domain settings. + // Apply the cookies status. cookieManager.setAcceptCookie(nestedScrollWebView.acceptCookies) + // Set the DOM storage status. + when (domStorageInt) { + SYSTEM_DEFAULT -> nestedScrollWebView.settings.domStorageEnabled = defaultDomStorage + ENABLED -> nestedScrollWebView.settings.domStorageEnabled = true + DISABLED -> nestedScrollWebView.settings.domStorageEnabled = false + } + // Apply the form data setting if the API < 26. @Suppress("DEPRECATION") - if (Build.VERSION.SDK_INT < 26) - nestedScrollWebView.settings.saveFormData = saveFormData - - // Apply the font size. - try { // Try the specified font size to see if it is valid. - if (fontSize == 0) { // Apply the default font size. - // Set the font size from the value in the app settings. - nestedScrollWebView.settings.textZoom = defaultFontSizeString!!.toInt() - } else { // Apply the font size from domain settings. - nestedScrollWebView.settings.textZoom = fontSize + if (Build.VERSION.SDK_INT < 26) { + // Set the form data status. + when (formDataInt) { + SYSTEM_DEFAULT -> nestedScrollWebView.settings.saveFormData = defaultFormData + ENABLED -> nestedScrollWebView.settings.saveFormData = true + DISABLED -> nestedScrollWebView.settings.saveFormData = false } - } catch (exception: Exception) { // The specified font size is invalid - // Set the font size to be 100% - nestedScrollWebView.settings.textZoom = 100 + } + + // Set the EasyList status. + when (easyListInt) { + SYSTEM_DEFAULT -> nestedScrollWebView.easyListEnabled = defaultEasyList + ENABLED -> nestedScrollWebView.easyListEnabled = true + DISABLED -> nestedScrollWebView.easyListEnabled = false + } + + // Set the EasyPrivacy status. + when (easyPrivacyInt) { + SYSTEM_DEFAULT -> nestedScrollWebView.easyPrivacyEnabled = defaultEasyPrivacy + ENABLED -> nestedScrollWebView.easyPrivacyEnabled = true + DISABLED -> nestedScrollWebView.easyPrivacyEnabled = false + } + + // Set the Fanboy's Annoyance List status. + when (fanboysAnnoyanceListInt) { + SYSTEM_DEFAULT -> nestedScrollWebView.fanboysAnnoyanceListEnabled = defaultFanboysAnnoyanceList + ENABLED -> nestedScrollWebView.fanboysAnnoyanceListEnabled = true + DISABLED -> nestedScrollWebView.fanboysAnnoyanceListEnabled = false + } + + // Set the Fanboy's Social Blocking List status. + when (fanboysSocialBlockingListInt) { + SYSTEM_DEFAULT -> nestedScrollWebView.fanboysSocialBlockingListEnabled = defaultFanboysSocialBlockingList + ENABLED -> nestedScrollWebView.fanboysSocialBlockingListEnabled = true + DISABLED -> nestedScrollWebView.fanboysSocialBlockingListEnabled = false + } + + // Set the UltraList status. + when (ultraListInt) { + SYSTEM_DEFAULT -> nestedScrollWebView.ultraListEnabled = defaultUltraList + ENABLED -> nestedScrollWebView.ultraListEnabled = true + DISABLED -> nestedScrollWebView.ultraListEnabled = false + } + + // Set the UltraPrivacy status. + when (ultraPrivacyInt) { + SYSTEM_DEFAULT -> nestedScrollWebView.ultraPrivacyEnabled = defaultUltraPrivacy + ENABLED -> nestedScrollWebView.ultraPrivacyEnabled = true + DISABLED -> nestedScrollWebView.ultraPrivacyEnabled = false + } + + // Set the block all third-party requests status. + when (blockAllThirdPartyRequestsInt) { + SYSTEM_DEFAULT -> nestedScrollWebView.blockAllThirdPartyRequests = defaultBlockAllThirdPartyRequests + ENABLED -> nestedScrollWebView.blockAllThirdPartyRequests = true + DISABLED -> nestedScrollWebView.blockAllThirdPartyRequests = false } // Set the user agent. @@ -3052,9 +3164,22 @@ class MainWebViewActivity : AppCompatActivity(), CreateBookmarkDialog.CreateBook } } + // Apply the font size. + try { // Try the specified font size to see if it is valid. + if (fontSize == 0) { // Apply the default font size. + // Set the font size from the value in the app settings. + nestedScrollWebView.settings.textZoom = defaultFontSizeString.toInt() + } else { // Apply the font size from domain settings. + nestedScrollWebView.settings.textZoom = fontSize + } + } catch (exception: Exception) { // The specified font size is invalid + // Set the font size to be 100% + nestedScrollWebView.settings.textZoom = 100 + } + // Set swipe to refresh. when (swipeToRefreshInt) { - DomainsDatabaseHelper.SYSTEM_DEFAULT -> { + SYSTEM_DEFAULT -> { // Store the swipe to refresh status in the nested scroll WebView. nestedScrollWebView.swipeToRefresh = defaultSwipeToRefresh @@ -3071,7 +3196,7 @@ class MainWebViewActivity : AppCompatActivity(), CreateBookmarkDialog.CreateBook } } - DomainsDatabaseHelper.ENABLED -> { + ENABLED -> { // Store the swipe to refresh status in the nested scroll WebView. nestedScrollWebView.swipeToRefresh = true @@ -3082,7 +3207,7 @@ class MainWebViewActivity : AppCompatActivity(), CreateBookmarkDialog.CreateBook } } - DomainsDatabaseHelper.DISABLED -> { + DISABLED -> { // Store the swipe to refresh status in the nested scroll WebView. nestedScrollWebView.swipeToRefresh = false @@ -3096,8 +3221,8 @@ class MainWebViewActivity : AppCompatActivity(), CreateBookmarkDialog.CreateBook // Set the WebView theme. when (webViewThemeInt) { // Set the WebView theme. - DomainsDatabaseHelper.SYSTEM_DEFAULT -> - when (webViewTheme) { + SYSTEM_DEFAULT -> + when (defaultWebViewTheme) { // The light theme is selected. Turn off algorithmic darkening. webViewThemeEntryValuesStringArray[1] -> WebSettingsCompat.setAlgorithmicDarkeningAllowed(nestedScrollWebView.settings, false) @@ -3115,60 +3240,68 @@ class MainWebViewActivity : AppCompatActivity(), CreateBookmarkDialog.CreateBook } // Turn off algorithmic darkening. - DomainsDatabaseHelper.LIGHT_THEME -> WebSettingsCompat.setAlgorithmicDarkeningAllowed(nestedScrollWebView.settings, false) + LIGHT_THEME -> WebSettingsCompat.setAlgorithmicDarkeningAllowed(nestedScrollWebView.settings, false) // Turn on algorithmic darkening. - DomainsDatabaseHelper.DARK_THEME -> WebSettingsCompat.setAlgorithmicDarkeningAllowed(nestedScrollWebView.settings, true) + DARK_THEME -> WebSettingsCompat.setAlgorithmicDarkeningAllowed(nestedScrollWebView.settings, true) } } // Set the wide viewport status. when (wideViewportInt) { - DomainsDatabaseHelper.SYSTEM_DEFAULT -> nestedScrollWebView.settings.useWideViewPort = wideViewport - DomainsDatabaseHelper.ENABLED -> nestedScrollWebView.settings.useWideViewPort = true - DomainsDatabaseHelper.DISABLED -> nestedScrollWebView.settings.useWideViewPort = false + SYSTEM_DEFAULT -> nestedScrollWebView.settings.useWideViewPort = defaultWideViewport + ENABLED -> nestedScrollWebView.settings.useWideViewPort = true + DISABLED -> nestedScrollWebView.settings.useWideViewPort = false } // Set the display webpage images status. when (displayWebpageImagesInt) { - DomainsDatabaseHelper.SYSTEM_DEFAULT -> nestedScrollWebView.settings.loadsImagesAutomatically = displayWebpageImages - DomainsDatabaseHelper.ENABLED -> nestedScrollWebView.settings.loadsImagesAutomatically = true - DomainsDatabaseHelper.DISABLED -> nestedScrollWebView.settings.loadsImagesAutomatically = false + SYSTEM_DEFAULT -> nestedScrollWebView.settings.loadsImagesAutomatically = defaultDisplayWebpageImages + ENABLED -> nestedScrollWebView.settings.loadsImagesAutomatically = true + DISABLED -> nestedScrollWebView.settings.loadsImagesAutomatically = false } + // If there is a pinned SSL certificate, store it in the WebView. + if (pinnedSslCertificate) + nestedScrollWebView.setPinnedSslCertificate(pinnedSslIssuedToCName, pinnedSslIssuedToOName, pinnedSslIssuedToUName, pinnedSslIssuedByCName, pinnedSslIssuedByOName, pinnedSslIssuedByUName, + pinnedSslStartDate, pinnedSslEndDate) + + // If there is a pinned IP address, store it in the WebView. + if (pinnedIpAddresses) + nestedScrollWebView.pinnedIpAddresses = pinnedHostIpAddresses + // Set a background on the URL relative layout to indicate that custom domain settings are being used. urlRelativeLayout.background = AppCompatResources.getDrawable(this, R.drawable.domain_settings_url_background) } else { // The new URL does not have custom domain settings. Load the defaults. // Store the values from the shared preferences. - nestedScrollWebView.settings.javaScriptEnabled = sharedPreferences.getBoolean(getString(R.string.javascript_key), false) - nestedScrollWebView.acceptCookies = sharedPreferences.getBoolean(getString(R.string.cookies_key), false) - nestedScrollWebView.settings.domStorageEnabled = sharedPreferences.getBoolean(getString(R.string.dom_storage_key), false) - val saveFormData = sharedPreferences.getBoolean(getString(R.string.save_form_data_key), false) // Form data can be removed once the minimum API >= 26. - nestedScrollWebView.easyListEnabled = sharedPreferences.getBoolean(getString(R.string.easylist_key), true) - nestedScrollWebView.easyPrivacyEnabled = sharedPreferences.getBoolean(getString(R.string.easyprivacy_key), true) - nestedScrollWebView.fanboysAnnoyanceListEnabled = sharedPreferences.getBoolean(getString(R.string.fanboys_annoyance_list_key), true) - nestedScrollWebView.fanboysSocialBlockingListEnabled = sharedPreferences.getBoolean(getString(R.string.fanboys_social_blocking_list_key), true) - nestedScrollWebView.ultraListEnabled = sharedPreferences.getBoolean(getString(R.string.ultralist_key), true) - nestedScrollWebView.ultraPrivacyEnabled = sharedPreferences.getBoolean(getString(R.string.ultraprivacy_key), true) - nestedScrollWebView.blockAllThirdPartyRequests = sharedPreferences.getBoolean(getString(R.string.block_all_third_party_requests_key), false) + nestedScrollWebView.settings.javaScriptEnabled = defaultJavaScript + nestedScrollWebView.acceptCookies = defaultCookies + nestedScrollWebView.settings.domStorageEnabled = defaultDomStorage + nestedScrollWebView.easyListEnabled = defaultEasyList + nestedScrollWebView.easyPrivacyEnabled = defaultEasyPrivacy + nestedScrollWebView.fanboysAnnoyanceListEnabled = defaultFanboysAnnoyanceList + nestedScrollWebView.fanboysSocialBlockingListEnabled = defaultFanboysSocialBlockingList + nestedScrollWebView.ultraListEnabled = defaultUltraList + nestedScrollWebView.ultraPrivacyEnabled = defaultUltraPrivacy + nestedScrollWebView.blockAllThirdPartyRequests = defaultBlockAllThirdPartyRequests // Apply the default cookie setting. cookieManager.setAcceptCookie(nestedScrollWebView.acceptCookies) + // Apply the form data setting if the API < 26. + if (Build.VERSION.SDK_INT < 26) + @Suppress("DEPRECATION") + nestedScrollWebView.settings.saveFormData = defaultFormData + // Apply the default font size setting. try { // Try to set the font size from the value in the app settings. - nestedScrollWebView.settings.textZoom = defaultFontSizeString!!.toInt() + nestedScrollWebView.settings.textZoom = defaultFontSizeString.toInt() } catch (exception: Exception) { // If the app settings value is invalid, set the font size to 100%. nestedScrollWebView.settings.textZoom = 100 } - // Apply the form data setting if the API < 26. - if (Build.VERSION.SDK_INT < 26) - @Suppress("DEPRECATION") - nestedScrollWebView.settings.saveFormData = saveFormData - // Store the swipe to refresh status in the nested scroll WebView. nestedScrollWebView.swipeToRefresh = defaultSwipeToRefresh @@ -3206,7 +3339,7 @@ class MainWebViewActivity : AppCompatActivity(), CreateBookmarkDialog.CreateBook // Set the WebView theme if the device is running API >= 29 and algorithmic darkening is supported. if ((Build.VERSION.SDK_INT >= 29) && WebViewFeature.isFeatureSupported(WebViewFeature.ALGORITHMIC_DARKENING)) { // Set the WebView theme. - when (webViewTheme) { + when (defaultWebViewTheme) { // The light theme is selected. Turn off algorithmic darkening. webViewThemeEntryValuesStringArray[1] -> WebSettingsCompat.setAlgorithmicDarkeningAllowed(nestedScrollWebView.settings, false) @@ -3225,10 +3358,10 @@ class MainWebViewActivity : AppCompatActivity(), CreateBookmarkDialog.CreateBook } // Set the viewport. - nestedScrollWebView.settings.useWideViewPort = wideViewport + nestedScrollWebView.settings.useWideViewPort = defaultWideViewport // Set the loading of webpage images. - nestedScrollWebView.settings.loadsImagesAutomatically = displayWebpageImages + nestedScrollWebView.settings.loadsImagesAutomatically = defaultDisplayWebpageImages // Set a transparent background on the URL relative layout. urlRelativeLayout.background = AppCompatResources.getDrawable(this, R.color.transparent) @@ -4900,7 +5033,7 @@ class MainWebViewActivity : AppCompatActivity(), CreateBookmarkDialog.CreateBook // Increment the blocked requests counters. nestedScrollWebView.incrementRequestsCount(BLOCKED_REQUESTS) - nestedScrollWebView.incrementRequestsCount(ULTRALIST) + nestedScrollWebView.incrementRequestsCount(com.stoutner.privacybrowser.views.ULTRALIST) // Update the titles of the filter lists menu items if the WebView is currently displayed. if (webViewDisplayed) { @@ -4912,7 +5045,7 @@ class MainWebViewActivity : AppCompatActivity(), CreateBookmarkDialog.CreateBook // Update the options menu if it has been populated. if (optionsMenu != null) { optionsFilterListsMenuItem.title = getString(R.string.filterlists) + " - " + nestedScrollWebView.getRequestsCount(BLOCKED_REQUESTS) - optionsUltraListMenuItem.title = nestedScrollWebView.getRequestsCount(ULTRALIST).toString() + " - " + getString(R.string.ultralist) + optionsUltraListMenuItem.title = nestedScrollWebView.getRequestsCount(com.stoutner.privacybrowser.views.ULTRALIST).toString() + " - " + getString(R.string.ultralist) } } } @@ -5815,7 +5948,7 @@ class MainWebViewActivity : AppCompatActivity(), CreateBookmarkDialog.CreateBook // Remove any background on the URL relative layout. urlRelativeLayout.background = AppCompatResources.getDrawable(this, R.color.transparent) } - } else if ((pageNumber == savedTabPosition) || (pageNumber == (webViewStateAdapter!!.itemCount - 1))) { // The tab has not been populated yet. + } else if ((pageNumber == savedTabPosition) || (pageNumber >= (webViewStateAdapter!!.itemCount - 1))) { // The tab has not been populated yet. // Try again in 100 milliseconds if the app is being restored or the a new tab has been added (the last tab). // Create a handler to set the current WebView. val setCurrentWebViewHandler = Handler(Looper.getMainLooper()) @@ -5859,7 +5992,7 @@ class MainWebViewActivity : AppCompatActivity(), CreateBookmarkDialog.CreateBook val domainsCount = domainsCursor.count // Get the domain name column index. - val domainNameColumnIndex = domainsCursor.getColumnIndexOrThrow(DomainsDatabaseHelper.DOMAIN_NAME) + val domainNameColumnIndex = domainsCursor.getColumnIndexOrThrow(DOMAIN_NAME) // Populate the domain settings set. for (i in 0 until domainsCount) { diff --git a/app/src/main/java/com/stoutner/privacybrowser/fragments/DomainSettingsFragment.kt b/app/src/main/java/com/stoutner/privacybrowser/fragments/DomainSettingsFragment.kt index 1576c185..ee7bc883 100644 --- a/app/src/main/java/com/stoutner/privacybrowser/fragments/DomainSettingsFragment.kt +++ b/app/src/main/java/com/stoutner/privacybrowser/fragments/DomainSettingsFragment.kt @@ -20,6 +20,7 @@ package com.stoutner.privacybrowser.fragments import android.annotation.SuppressLint +import android.content.Context import android.content.res.Configuration import android.os.Build import android.os.Bundle @@ -58,6 +59,40 @@ import com.stoutner.privacybrowser.activities.SETTINGS_CUSTOM_USER_AGENT import com.stoutner.privacybrowser.activities.SETTINGS_WEBVIEW_DEFAULT_USER_AGENT import com.stoutner.privacybrowser.activities.UNRECOGNIZED_USER_AGENT import com.stoutner.privacybrowser.activities.DomainsActivity +import com.stoutner.privacybrowser.helpers.BLOCK_ALL_THIRD_PARTY_REQUESTS +import com.stoutner.privacybrowser.helpers.COOKIES +import com.stoutner.privacybrowser.helpers.DARK_THEME +import com.stoutner.privacybrowser.helpers.DISABLED +import com.stoutner.privacybrowser.helpers.DISPLAY_IMAGES +import com.stoutner.privacybrowser.helpers.DOMAIN_NAME +import com.stoutner.privacybrowser.helpers.ENABLED +import com.stoutner.privacybrowser.helpers.LIGHT_THEME +import com.stoutner.privacybrowser.helpers.SYSTEM_DEFAULT +import com.stoutner.privacybrowser.helpers.ENABLE_DOM_STORAGE +import com.stoutner.privacybrowser.helpers.ENABLE_EASYLIST +import com.stoutner.privacybrowser.helpers.ENABLE_EASYPRIVACY +import com.stoutner.privacybrowser.helpers.ENABLE_FANBOYS_ANNOYANCE_LIST +import com.stoutner.privacybrowser.helpers.ENABLE_FANBOYS_SOCIAL_BLOCKING_LIST +import com.stoutner.privacybrowser.helpers.ENABLE_FORM_DATA +import com.stoutner.privacybrowser.helpers.ENABLE_JAVASCRIPT +import com.stoutner.privacybrowser.helpers.ENABLE_ULTRAPRIVACY +import com.stoutner.privacybrowser.helpers.FONT_SIZE +import com.stoutner.privacybrowser.helpers.IP_ADDRESSES +import com.stoutner.privacybrowser.helpers.PINNED_IP_ADDRESSES +import com.stoutner.privacybrowser.helpers.PINNED_SSL_CERTIFICATE +import com.stoutner.privacybrowser.helpers.SSL_END_DATE +import com.stoutner.privacybrowser.helpers.SSL_ISSUED_BY_COMMON_NAME +import com.stoutner.privacybrowser.helpers.SSL_ISSUED_BY_ORGANIZATION +import com.stoutner.privacybrowser.helpers.SSL_ISSUED_BY_ORGANIZATIONAL_UNIT +import com.stoutner.privacybrowser.helpers.SSL_ISSUED_TO_COMMON_NAME +import com.stoutner.privacybrowser.helpers.SSL_ISSUED_TO_ORGANIZATION +import com.stoutner.privacybrowser.helpers.SSL_ISSUED_TO_ORGANIZATIONAL_UNIT +import com.stoutner.privacybrowser.helpers.SSL_START_DATE +import com.stoutner.privacybrowser.helpers.SWIPE_TO_REFRESH +import com.stoutner.privacybrowser.helpers.ULTRALIST +import com.stoutner.privacybrowser.helpers.USER_AGENT +import com.stoutner.privacybrowser.helpers.WEBVIEW_THEME +import com.stoutner.privacybrowser.helpers.WIDE_VIEWPORT import com.stoutner.privacybrowser.helpers.DomainsDatabaseHelper import java.lang.IndexOutOfBoundsException @@ -69,6 +104,9 @@ class DomainSettingsFragment : Fragment() { // Define the class variables. private var scrollY = 0 + // Declare the class variables. + private lateinit var context: Context + companion object { // Define the public constants. const val DATABASE_ID = "database_id" @@ -91,46 +129,82 @@ class DomainSettingsFragment : Fragment() { // Inflate the layout. The fragment will take care of attaching the root automatically. val domainSettingsView = inflater.inflate(R.layout.domain_settings_fragment, container, false) + // Get a handle for the context. + context = requireContext() + // Get the current theme status. val currentThemeStatus = resources.configuration.uiMode and Configuration.UI_MODE_NIGHT_MASK // Get a handle for the shared preference. val sharedPreferences = PreferenceManager.getDefaultSharedPreferences(requireContext()) - // Store the default settings. - val defaultUserAgentName = sharedPreferences.getString(getString(R.string.user_agent_key), getString(R.string.user_agent_default_value)) - val defaultCustomUserAgentString = sharedPreferences.getString(getString(R.string.custom_user_agent_key), getString(R.string.custom_user_agent_default_value)) - val defaultFontSizeString = sharedPreferences.getString(getString(R.string.font_size_key), getString(R.string.font_size_default_value)) - val defaultSwipeToRefresh = sharedPreferences.getBoolean(getString(R.string.swipe_to_refresh_key), true) - val defaultWebViewTheme = sharedPreferences.getString(getString(R.string.webview_theme_key), getString(R.string.webview_theme_default_value)) - val defaultWideViewport = sharedPreferences.getBoolean(getString(R.string.wide_viewport_key), true) - val defaultDisplayWebpageImages = sharedPreferences.getBoolean(getString(R.string.display_webpage_images_key), true) + // Get the default values. + val javaScriptDefault = sharedPreferences.getBoolean(getString(R.string.javascript_key), false) + val cookiesDefault = sharedPreferences.getBoolean(getString(R.string.cookies_key), false) + val domStorageDefault = sharedPreferences.getBoolean(getString(R.string.dom_storage_key), false) + val formDataDefault = sharedPreferences.getBoolean(getString(R.string.save_form_data_key), false) // The form data views can be remove once the minimum API >= 26. + val easyListDefault = sharedPreferences.getBoolean(getString(R.string.easylist_key), true) + val easyPrivacyDefault = sharedPreferences.getBoolean(getString(R.string.easyprivacy_key), true) + val fanboysAnnoyanceListDefault = sharedPreferences.getBoolean(getString(R.string.fanboys_annoyance_list_key), true) + val fanboysSocialBlockingListDefault = sharedPreferences.getBoolean(getString(R.string.fanboys_social_blocking_list), true) + val ultraListDefault = sharedPreferences.getBoolean(getString(R.string.ultralist_key), true) + val ultraPrivacyDefault = sharedPreferences.getBoolean(getString(R.string.ultraprivacy_key), true) + val blockAllThirdPartyRequestsDefault = sharedPreferences.getBoolean(getString(R.string.block_all_third_party_requests_key), false) + val userAgentDefault = sharedPreferences.getString(getString(R.string.user_agent_key), getString(R.string.user_agent_default_value)) + val customUserAgentStringDefault = sharedPreferences.getString(getString(R.string.custom_user_agent_key), getString(R.string.custom_user_agent_default_value)) + val fontSizeStringDefault = sharedPreferences.getString(getString(R.string.font_size_key), getString(R.string.font_size_default_value)) + val swipeToRefreshDefault = sharedPreferences.getBoolean(getString(R.string.swipe_to_refresh_key), true) + val webViewThemeDefault = sharedPreferences.getString(getString(R.string.webview_theme_key), getString(R.string.webview_theme_default_value)) + val wideViewportDefault = sharedPreferences.getBoolean(getString(R.string.wide_viewport_key), true) + val displayWebpageImagesDefault = sharedPreferences.getBoolean(getString(R.string.display_webpage_images_key), true) // Get handles for the views. val domainSettingsScrollView = domainSettingsView.findViewById(R.id.domain_settings_scrollview) val domainNameEditText = domainSettingsView.findViewById(R.id.domain_settings_name_edittext) + val javaScriptLinearLayout = domainSettingsView.findViewById(R.id.javascript_linearlayout) val javaScriptImageView = domainSettingsView.findViewById(R.id.javascript_imageview) - val javaScriptSwitch = domainSettingsView.findViewById(R.id.javascript_switch) + val javaScriptSpinner = domainSettingsView.findViewById(R.id.javascript_spinner) + val javaScriptTextView = domainSettingsView.findViewById(R.id.javascript_textview) + val cookiesLinearLayout = domainSettingsView.findViewById(R.id.cookies_linearlayout) val cookiesImageView = domainSettingsView.findViewById(R.id.cookies_imageview) - val cookiesSwitch = domainSettingsView.findViewById(R.id.cookies_switch) + val cookiesSpinner = domainSettingsView.findViewById(R.id.cookies_spinner) + val cookiesTextView = domainSettingsView.findViewById(R.id.cookies_textview) + val domStorageLinearLayout = domainSettingsView.findViewById(R.id.dom_storage_linearlayout) val domStorageImageView = domainSettingsView.findViewById(R.id.dom_storage_imageview) - val domStorageSwitch = domainSettingsView.findViewById(R.id.dom_storage_switch) - val formDataImageView = domainSettingsView.findViewById(R.id.form_data_imageview) // The form data views can be remove once the minimum API >= 26. - val formDataSwitch = domainSettingsView.findViewById(R.id.form_data_switch) // The form data views can be remove once the minimum API >= 26. + val domStorageSpinner = domainSettingsView.findViewById(R.id.dom_storage_spinner) + val domStorageTextView = domainSettingsView.findViewById(R.id.dom_storage_textview) + val formDataLinearLayout = domainSettingsView.findViewById(R.id.form_data_linearlayout) // The form data views can be remove once the minimum API >= 26. + val formDataImageView = domainSettingsView.findViewById(R.id.form_data_imageview) // The form data views can be remove once the minimum API >= 26. + val formDataSpinner = domainSettingsView.findViewById(R.id.form_data_spinner) // The form data views can be remove once the minimum API >= 26. + val formDataTextView = domainSettingsView.findViewById(R.id.form_data_textview) // The form data views can be remove once the minimum API >= 26. + val easyListLinearLayout = domainSettingsView.findViewById(R.id.easylist_linearlayout) val easyListImageView = domainSettingsView.findViewById(R.id.easylist_imageview) - val easyListSwitch = domainSettingsView.findViewById(R.id.easylist_switch) + val easyListSpinner = domainSettingsView.findViewById(R.id.easylist_spinner) + val easyListTextView = domainSettingsView.findViewById(R.id.easylist_textview) + val easyPrivacyLinearLayout = domainSettingsView.findViewById(R.id.easyprivacy_linearlayout) val easyPrivacyImageView = domainSettingsView.findViewById(R.id.easyprivacy_imageview) - val easyPrivacySwitch = domainSettingsView.findViewById(R.id.easyprivacy_switch) + val easyPrivacySpinner = domainSettingsView.findViewById(R.id.easyprivacy_spinner) + val easyPrivacyTextView = domainSettingsView.findViewById(R.id.easyprivacy_textview) + val fanboysAnnoyanceListLinearLayout = domainSettingsView.findViewById(R.id.fanboys_annoyance_list_linearlayout) val fanboysAnnoyanceListImageView = domainSettingsView.findViewById(R.id.fanboys_annoyance_list_imageview) - val fanboysAnnoyanceListSwitch = domainSettingsView.findViewById(R.id.fanboys_annoyance_list_switch) + val fanboysAnnoyanceListSpinner = domainSettingsView.findViewById(R.id.fanboys_annoyance_list_spinner) + val fanboysAnnoyanceListTextView = domainSettingsView.findViewById(R.id.fanboys_annoyance_list_textview) + val fanboysSocialBlockingListLinearLayout = domainSettingsView.findViewById(R.id.fanboys_social_blocking_list_linearlayout) val fanboysSocialBlockingListImageView = domainSettingsView.findViewById(R.id.fanboys_social_blocking_list_imageview) - val fanboysSocialBlockingListSwitch = domainSettingsView.findViewById(R.id.fanboys_social_blocking_list_switch) + val fanboysSocialBlockingListSpinner = domainSettingsView.findViewById(R.id.fanboys_social_blocking_list_spinner) + val fanboysSocialBlockingListTextView = domainSettingsView.findViewById(R.id.fanboys_social_blocking_list_textview) + val ultraListLinearLayout = domainSettingsView.findViewById(R.id.ultralist_linearlayout) val ultraListImageView = domainSettingsView.findViewById(R.id.ultralist_imageview) - val ultraListSwitch = domainSettingsView.findViewById(R.id.ultralist_switch) + val ultraListSpinner = domainSettingsView.findViewById(R.id.ultralist_spinner) + val ultraListTextView = domainSettingsView.findViewById(R.id.ultralist_textview) + val ultraPrivacyLinearLayout = domainSettingsView.findViewById(R.id.ultraprivacy_linearlayout) val ultraPrivacyImageView = domainSettingsView.findViewById(R.id.ultraprivacy_imageview) - val ultraPrivacySwitch = domainSettingsView.findViewById(R.id.ultraprivacy_switch) + val ultraPrivacySpinner = domainSettingsView.findViewById(R.id.ultraprivacy_spinner) + val ultraPrivacyTextView = domainSettingsView.findViewById(R.id.ultraprivacy_textview) + val blockAllThirdPartyRequestsLinearLayout = domainSettingsView.findViewById(R.id.block_all_third_party_requests_linearlayout) val blockAllThirdPartyRequestsImageView = domainSettingsView.findViewById(R.id.block_all_third_party_requests_imageview) - val blockAllThirdPartyRequestsSwitch = domainSettingsView.findViewById(R.id.block_all_third_party_requests_switch) + val blockAllThirdPartyRequestsSpinner = domainSettingsView.findViewById(R.id.block_all_third_party_requests_spinner) + val blockAllThirdPartyRequestsTextView = domainSettingsView.findViewById(R.id.block_all_third_party_requests_textview) val userAgentLinearLayout = domainSettingsView.findViewById(R.id.user_agent_linearlayout) val userAgentSpinner = domainSettingsView.findViewById(R.id.user_agent_spinner) val userAgentTextView = domainSettingsView.findViewById(R.id.user_agent_textview) @@ -191,17 +265,14 @@ class DomainSettingsFragment : Fragment() { val currentIpAddressesRadioButton = domainSettingsView.findViewById(R.id.current_ip_addresses_radiobutton) val currentIpAddressesTextView = domainSettingsView.findViewById(R.id.current_ip_addresses_textview) + // Hide the form data linear layout if the API >= 26. + if (Build.VERSION.SDK_INT >= 26) + formDataLinearLayout.visibility = View.GONE + // Hide the WebView theme linear layout if the API < 29. if (Build.VERSION.SDK_INT < 29) webViewThemeLinearLayout.visibility = View.GONE - // Setup the pinned labels. - val cNameLabel = getString(R.string.common_name) - val oNameLabel = getString(R.string.organization) - val uNameLabel = getString(R.string.organizational_unit) - val startDateLabel = getString(R.string.start_date) - val endDateLabel = getString(R.string.end_date) - // Initialize the database handler. val domainsDatabaseHelper = DomainsDatabaseHelper(requireContext()) @@ -212,57 +283,70 @@ class DomainSettingsFragment : Fragment() { domainCursor.moveToFirst() // Save the cursor entries as variables. - val domainNameString = domainCursor.getString(domainCursor.getColumnIndexOrThrow(DomainsDatabaseHelper.DOMAIN_NAME)) - val javaScriptInt = domainCursor.getInt(domainCursor.getColumnIndexOrThrow(DomainsDatabaseHelper.ENABLE_JAVASCRIPT)) - val cookiesInt = domainCursor.getInt(domainCursor.getColumnIndexOrThrow(DomainsDatabaseHelper.COOKIES)) - val domStorageInt = domainCursor.getInt(domainCursor.getColumnIndexOrThrow(DomainsDatabaseHelper.ENABLE_DOM_STORAGE)) - val formDataInt = domainCursor.getInt(domainCursor.getColumnIndexOrThrow(DomainsDatabaseHelper.ENABLE_FORM_DATA)) // Form data can be remove once the minimum API >= 26. - val easyListInt = domainCursor.getInt(domainCursor.getColumnIndexOrThrow(DomainsDatabaseHelper.ENABLE_EASYLIST)) - val easyPrivacyInt = domainCursor.getInt(domainCursor.getColumnIndexOrThrow(DomainsDatabaseHelper.ENABLE_EASYPRIVACY)) - val fanboysAnnoyanceListInt = domainCursor.getInt(domainCursor.getColumnIndexOrThrow(DomainsDatabaseHelper.ENABLE_FANBOYS_ANNOYANCE_LIST)) - val fanboysSocialBlockingListInt = domainCursor.getInt(domainCursor.getColumnIndexOrThrow(DomainsDatabaseHelper.ENABLE_FANBOYS_SOCIAL_BLOCKING_LIST)) - val ultraListInt = domainCursor.getInt(domainCursor.getColumnIndexOrThrow(DomainsDatabaseHelper.ULTRALIST)) - val ultraPrivacyInt = domainCursor.getInt(domainCursor.getColumnIndexOrThrow(DomainsDatabaseHelper.ENABLE_ULTRAPRIVACY)) - val blockAllThirdPartyRequestsInt = domainCursor.getInt(domainCursor.getColumnIndexOrThrow(DomainsDatabaseHelper.BLOCK_ALL_THIRD_PARTY_REQUESTS)) - val currentUserAgentName = domainCursor.getString(domainCursor.getColumnIndexOrThrow(DomainsDatabaseHelper.USER_AGENT)) - val fontSizeInt = domainCursor.getInt(domainCursor.getColumnIndexOrThrow(DomainsDatabaseHelper.FONT_SIZE)) - val swipeToRefreshInt = domainCursor.getInt(domainCursor.getColumnIndexOrThrow(DomainsDatabaseHelper.SWIPE_TO_REFRESH)) - val webViewThemeInt = domainCursor.getInt(domainCursor.getColumnIndexOrThrow(DomainsDatabaseHelper.WEBVIEW_THEME)) - val wideViewportInt = domainCursor.getInt(domainCursor.getColumnIndexOrThrow(DomainsDatabaseHelper.WIDE_VIEWPORT)) - val displayImagesInt = domainCursor.getInt(domainCursor.getColumnIndexOrThrow(DomainsDatabaseHelper.DISPLAY_IMAGES)) - val pinnedSslCertificateInt = domainCursor.getInt(domainCursor.getColumnIndexOrThrow(DomainsDatabaseHelper.PINNED_SSL_CERTIFICATE)) - val savedSslIssuedToCNameString = domainCursor.getString(domainCursor.getColumnIndexOrThrow(DomainsDatabaseHelper.SSL_ISSUED_TO_COMMON_NAME)) - val savedSslIssuedToONameString = domainCursor.getString(domainCursor.getColumnIndexOrThrow(DomainsDatabaseHelper.SSL_ISSUED_TO_ORGANIZATION)) - val savedSslIssuedToUNameString = domainCursor.getString(domainCursor.getColumnIndexOrThrow(DomainsDatabaseHelper.SSL_ISSUED_TO_ORGANIZATIONAL_UNIT)) - val savedSslIssuedByCNameString = domainCursor.getString(domainCursor.getColumnIndexOrThrow(DomainsDatabaseHelper.SSL_ISSUED_BY_COMMON_NAME)) - val savedSslIssuedByONameString = domainCursor.getString(domainCursor.getColumnIndexOrThrow(DomainsDatabaseHelper.SSL_ISSUED_BY_ORGANIZATION)) - val savedSslIssuedByUNameString = domainCursor.getString(domainCursor.getColumnIndexOrThrow(DomainsDatabaseHelper.SSL_ISSUED_BY_ORGANIZATIONAL_UNIT)) - val pinnedIpAddressesInt = domainCursor.getInt(domainCursor.getColumnIndexOrThrow(DomainsDatabaseHelper.PINNED_IP_ADDRESSES)) - val savedIpAddresses = domainCursor.getString(domainCursor.getColumnIndexOrThrow(DomainsDatabaseHelper.IP_ADDRESSES)) - - // Get the SSL dates from the database. - val savedSslStartDateLong = domainCursor.getLong(domainCursor.getColumnIndexOrThrow(DomainsDatabaseHelper.SSL_START_DATE)) - val savedSslEndDateLong = domainCursor.getLong(domainCursor.getColumnIndexOrThrow(DomainsDatabaseHelper.SSL_END_DATE)) - - // Initialize the saved SSL certificate date variables. - var savedSslStartDate: Date? = null - var savedSslEndDate: Date? = null - - // Only get the saved SSL certificate dates from the cursor if they are not set to `0`. - if (savedSslStartDateLong != 0L) - savedSslStartDate = Date(savedSslStartDateLong) - if (savedSslEndDateLong != 0L) - savedSslEndDate = Date(savedSslEndDateLong) - - // Create array adapters for the spinners. - val translatedUserAgentArrayAdapter = ArrayAdapter.createFromResource(requireContext(), R.array.translated_domain_settings_user_agent_names, R.layout.spinner_item) - val fontSizeArrayAdapter = ArrayAdapter.createFromResource(requireContext(), R.array.font_size_array, R.layout.spinner_item) - val swipeToRefreshArrayAdapter = ArrayAdapter.createFromResource(requireContext(), R.array.swipe_to_refresh_array, R.layout.spinner_item) - val webViewThemeArrayAdapter = ArrayAdapter.createFromResource(requireContext(), R.array.webview_theme_array, R.layout.spinner_item) - val wideViewportArrayAdapter = ArrayAdapter.createFromResource(requireContext(), R.array.wide_viewport_array, R.layout.spinner_item) - val displayImagesArrayAdapter = ArrayAdapter.createFromResource(requireContext(), R.array.display_webpage_images_array, R.layout.spinner_item) + val domainNameString = domainCursor.getString(domainCursor.getColumnIndexOrThrow(DOMAIN_NAME)) + val javaScriptInt = domainCursor.getInt(domainCursor.getColumnIndexOrThrow(ENABLE_JAVASCRIPT)) + val cookiesInt = domainCursor.getInt(domainCursor.getColumnIndexOrThrow(COOKIES)) + val domStorageInt = domainCursor.getInt(domainCursor.getColumnIndexOrThrow(ENABLE_DOM_STORAGE)) + val formDataInt = domainCursor.getInt(domainCursor.getColumnIndexOrThrow(ENABLE_FORM_DATA)) // Form data can be remove once the minimum API >= 26. + val easyListInt = domainCursor.getInt(domainCursor.getColumnIndexOrThrow(ENABLE_EASYLIST)) + val easyPrivacyInt = domainCursor.getInt(domainCursor.getColumnIndexOrThrow(ENABLE_EASYPRIVACY)) + val fanboysAnnoyanceListInt = domainCursor.getInt(domainCursor.getColumnIndexOrThrow(ENABLE_FANBOYS_ANNOYANCE_LIST)) + val fanboysSocialBlockingListInt = domainCursor.getInt(domainCursor.getColumnIndexOrThrow(ENABLE_FANBOYS_SOCIAL_BLOCKING_LIST)) + val ultraListInt = domainCursor.getInt(domainCursor.getColumnIndexOrThrow(ULTRALIST)) + val ultraPrivacyInt = domainCursor.getInt(domainCursor.getColumnIndexOrThrow(ENABLE_ULTRAPRIVACY)) + val blockAllThirdPartyRequestsInt = domainCursor.getInt(domainCursor.getColumnIndexOrThrow(BLOCK_ALL_THIRD_PARTY_REQUESTS)) + val currentUserAgentName = domainCursor.getString(domainCursor.getColumnIndexOrThrow(USER_AGENT)) + val fontSizeInt = domainCursor.getInt(domainCursor.getColumnIndexOrThrow(FONT_SIZE)) + val swipeToRefreshInt = domainCursor.getInt(domainCursor.getColumnIndexOrThrow(SWIPE_TO_REFRESH)) + val webViewThemeInt = domainCursor.getInt(domainCursor.getColumnIndexOrThrow(WEBVIEW_THEME)) + val wideViewportInt = domainCursor.getInt(domainCursor.getColumnIndexOrThrow(WIDE_VIEWPORT)) + val displayImagesInt = domainCursor.getInt(domainCursor.getColumnIndexOrThrow(DISPLAY_IMAGES)) + val pinnedSslCertificateInt = domainCursor.getInt(domainCursor.getColumnIndexOrThrow(PINNED_SSL_CERTIFICATE)) + val savedSslIssuedToCNameString = domainCursor.getString(domainCursor.getColumnIndexOrThrow(SSL_ISSUED_TO_COMMON_NAME)) + val savedSslIssuedToONameString = domainCursor.getString(domainCursor.getColumnIndexOrThrow(SSL_ISSUED_TO_ORGANIZATION)) + val savedSslIssuedToUNameString = domainCursor.getString(domainCursor.getColumnIndexOrThrow(SSL_ISSUED_TO_ORGANIZATIONAL_UNIT)) + val savedSslIssuedByCNameString = domainCursor.getString(domainCursor.getColumnIndexOrThrow(SSL_ISSUED_BY_COMMON_NAME)) + val savedSslIssuedByONameString = domainCursor.getString(domainCursor.getColumnIndexOrThrow(SSL_ISSUED_BY_ORGANIZATION)) + val savedSslIssuedByUNameString = domainCursor.getString(domainCursor.getColumnIndexOrThrow(SSL_ISSUED_BY_ORGANIZATIONAL_UNIT)) + val savedSslStartDateLong = domainCursor.getLong(domainCursor.getColumnIndexOrThrow(SSL_START_DATE)) + val savedSslEndDateLong = domainCursor.getLong(domainCursor.getColumnIndexOrThrow(SSL_END_DATE)) + val pinnedIpAddressesInt = domainCursor.getInt(domainCursor.getColumnIndexOrThrow(PINNED_IP_ADDRESSES)) + val savedIpAddresses = domainCursor.getString(domainCursor.getColumnIndexOrThrow(IP_ADDRESSES)) + + // Close the domain cursor. + domainCursor.close() + + // Create spinner array adapters. + val javaScriptArrayAdapter = ArrayAdapter.createFromResource(context, R.array.javascript_array, R.layout.spinner_item) + val cookiesArrayAdapter = ArrayAdapter.createFromResource(context, R.array.cookies_array, R.layout.spinner_item) + val domStorageArrayAdapter = ArrayAdapter.createFromResource(context, R.array.dom_storage_array, R.layout.spinner_item) + val formDataArrayAdapter = ArrayAdapter.createFromResource(context, R.array.form_data_array, R.layout.spinner_item) // Form data can be remove once the minimum API >= 26. + val easyListArrayAdapter = ArrayAdapter.createFromResource(context, R.array.easylist_array, R.layout.spinner_item) + val easyPrivacyArrayAdapter = ArrayAdapter.createFromResource(context, R.array.easyprivacy_array, R.layout.spinner_item) + val fanboysAnnoyanceListArrayAdapter = ArrayAdapter.createFromResource(context, R.array.fanboys_annoyance_list_array, R.layout.spinner_item) + val fanboysSocialBlockingListArrayAdapter = ArrayAdapter.createFromResource(context, R.array.fanboys_social_blocking_list_array, R.layout.spinner_item) + val ultraListArrayAdapter = ArrayAdapter.createFromResource(context, R.array.ultralist_array, R.layout.spinner_item) + val ultraPrivacyArrayAdapter = ArrayAdapter.createFromResource(context, R.array.ultraprivacy_array, R.layout.spinner_item) + val blockAllThirdPartyRequestsArrayAdapter = ArrayAdapter.createFromResource(context, R.array.block_all_third_party_requests_array, R.layout.spinner_item) + val translatedUserAgentArrayAdapter = ArrayAdapter.createFromResource(context, R.array.translated_domain_settings_user_agent_names, R.layout.spinner_item) + val fontSizeArrayAdapter = ArrayAdapter.createFromResource(context, R.array.font_size_array, R.layout.spinner_item) + val swipeToRefreshArrayAdapter = ArrayAdapter.createFromResource(context, R.array.swipe_to_refresh_array, R.layout.spinner_item) + val webViewThemeArrayAdapter = ArrayAdapter.createFromResource(context, R.array.webview_theme_array, R.layout.spinner_item) + val wideViewportArrayAdapter = ArrayAdapter.createFromResource(context, R.array.wide_viewport_array, R.layout.spinner_item) + val displayImagesArrayAdapter = ArrayAdapter.createFromResource(context, R.array.display_webpage_images_array, R.layout.spinner_item) // Set the drop down view resource on the spinners. + javaScriptArrayAdapter.setDropDownViewResource(R.layout.domain_settings_spinner_dropdown_items) + cookiesArrayAdapter.setDropDownViewResource(R.layout.domain_settings_spinner_dropdown_items) + domStorageArrayAdapter.setDropDownViewResource(R.layout.domain_settings_spinner_dropdown_items) + formDataArrayAdapter.setDropDownViewResource(R.layout.domain_settings_spinner_dropdown_items) // Form data can be remove once the minimum API >= 26. + easyListArrayAdapter.setDropDownViewResource(R.layout.domain_settings_spinner_dropdown_items) + easyPrivacyArrayAdapter.setDropDownViewResource(R.layout.domain_settings_spinner_dropdown_items) + fanboysAnnoyanceListArrayAdapter.setDropDownViewResource(R.layout.domain_settings_spinner_dropdown_items) + fanboysSocialBlockingListArrayAdapter.setDropDownViewResource(R.layout.domain_settings_spinner_dropdown_items) + ultraListArrayAdapter.setDropDownViewResource(R.layout.domain_settings_spinner_dropdown_items) + ultraPrivacyArrayAdapter.setDropDownViewResource(R.layout.domain_settings_spinner_dropdown_items) + blockAllThirdPartyRequestsArrayAdapter.setDropDownViewResource(R.layout.domain_settings_spinner_dropdown_items) translatedUserAgentArrayAdapter.setDropDownViewResource(R.layout.domain_settings_spinner_dropdown_items) fontSizeArrayAdapter.setDropDownViewResource(R.layout.domain_settings_spinner_dropdown_items) swipeToRefreshArrayAdapter.setDropDownViewResource(R.layout.domain_settings_spinner_dropdown_items) @@ -271,6 +355,17 @@ class DomainSettingsFragment : Fragment() { displayImagesArrayAdapter.setDropDownViewResource(R.layout.domain_settings_spinner_dropdown_items) // Set the array adapters for the spinners. + javaScriptSpinner.adapter = javaScriptArrayAdapter + cookiesSpinner.adapter = cookiesArrayAdapter + domStorageSpinner.adapter = domStorageArrayAdapter + formDataSpinner.adapter = formDataArrayAdapter // Form data can be remove once the minimum API >= 26. + easyListSpinner.adapter = easyListArrayAdapter + easyPrivacySpinner.adapter = easyPrivacyArrayAdapter + fanboysAnnoyanceListSpinner.adapter = fanboysAnnoyanceListArrayAdapter + fanboysSocialBlockingListSpinner.adapter = fanboysSocialBlockingListArrayAdapter + ultraListSpinner.adapter = ultraListArrayAdapter + ultraPrivacySpinner.adapter = ultraPrivacyArrayAdapter + blockAllThirdPartyRequestsSpinner.adapter = blockAllThirdPartyRequestsArrayAdapter userAgentSpinner.adapter = translatedUserAgentArrayAdapter fontSizeSpinner.adapter = fontSizeArrayAdapter swipeToRefreshSpinner.adapter = swipeToRefreshArrayAdapter @@ -278,32 +373,89 @@ class DomainSettingsFragment : Fragment() { wideViewportSpinner.adapter = wideViewportArrayAdapter displayImagesSpinner.adapter = displayImagesArrayAdapter - // Create a spannable string builder for each TextView that needs multiple colors of text. - val savedSslIssuedToCNameStringBuilder = SpannableStringBuilder(cNameLabel + savedSslIssuedToCNameString) - val savedSslIssuedToONameStringBuilder = SpannableStringBuilder(oNameLabel + savedSslIssuedToONameString) - val savedSslIssuedToUNameStringBuilder = SpannableStringBuilder(uNameLabel + savedSslIssuedToUNameString) - val savedSslIssuedByCNameStringBuilder = SpannableStringBuilder(cNameLabel + savedSslIssuedByCNameString) - val savedSslIssuedByONameStringBuilder = SpannableStringBuilder(oNameLabel + savedSslIssuedByONameString) - val savedSslIssuedByUNameStringBuilder = SpannableStringBuilder(uNameLabel + savedSslIssuedByUNameString) + // Open the spinners when the text view is tapped. + javaScriptTextView.setOnClickListener { javaScriptSpinner.performClick() } + cookiesTextView.setOnClickListener { cookiesSpinner.performClick() } + domStorageTextView.setOnClickListener { domStorageSpinner.performClick() } + formDataTextView.setOnClickListener { formDataSpinner.performClick() } + easyListTextView.setOnClickListener { easyListSpinner.performClick() } + easyPrivacyTextView.setOnClickListener { easyPrivacySpinner.performClick() } + fanboysAnnoyanceListTextView.setOnClickListener { fanboysAnnoyanceListSpinner.performClick() } + fanboysSocialBlockingListTextView.setOnClickListener { fanboysSocialBlockingListSpinner.performClick() } + ultraListTextView.setOnClickListener { ultraListSpinner.performClick() } + ultraPrivacyTextView.setOnClickListener { ultraPrivacySpinner.performClick() } + blockAllThirdPartyRequestsTextView.setOnClickListener { blockAllThirdPartyRequestsSpinner.performClick() } + userAgentTextView.setOnClickListener { userAgentSpinner.performClick() } + defaultFontSizeTextView.setOnClickListener { fontSizeSpinner.performClick() } + swipeToRefreshTextView.setOnClickListener { swipeToRefreshSpinner.performClick() } + webViewThemeTextView.setOnClickListener { webViewThemeSpinner.performClick() } + wideViewportTextView.setOnClickListener { wideViewportSpinner.performClick() } + displayImagesTextView.setOnClickListener { displayImagesSpinner.performClick() } - // Create the date spannable string builders. - val savedSslStartDateStringBuilder: SpannableStringBuilder = if (savedSslStartDate == null) - SpannableStringBuilder(startDateLabel) - else - SpannableStringBuilder(startDateLabel + DateFormat.getDateTimeInstance(DateFormat.MEDIUM, DateFormat.LONG).format(savedSslStartDate)) + // Set the spinner selections. Items that aren't defined by an integer are handled individually below. + javaScriptSpinner.setSelection(javaScriptInt) + cookiesSpinner.setSelection(cookiesInt) + domStorageSpinner.setSelection(domStorageInt) + formDataSpinner.setSelection(formDataInt) + easyListSpinner.setSelection(easyListInt) + easyPrivacySpinner.setSelection(easyPrivacyInt) + fanboysAnnoyanceListSpinner.setSelection(fanboysAnnoyanceListInt) + fanboysSocialBlockingListSpinner.setSelection(fanboysSocialBlockingListInt) + ultraListSpinner.setSelection(ultraListInt) + ultraPrivacySpinner.setSelection(ultraPrivacyInt) + blockAllThirdPartyRequestsSpinner.setSelection(blockAllThirdPartyRequestsInt) + swipeToRefreshSpinner.setSelection(swipeToRefreshInt) + webViewThemeSpinner.setSelection(webViewThemeInt) + wideViewportSpinner.setSelection(wideViewportInt) + displayImagesSpinner.setSelection(displayImagesInt) - val savedSslEndDateStringBuilder: SpannableStringBuilder = if (savedSslEndDate == null) - SpannableStringBuilder(endDateLabel) - else - SpannableStringBuilder(endDateLabel + DateFormat.getDateTimeInstance(DateFormat.MEDIUM, DateFormat.LONG).format(savedSslEndDate)) + // Populate the text views. Items that aren't defined by an integer are handled individually below. + populateTextView(javaScriptDefault, javaScriptArrayAdapter, javaScriptTextView) + populateTextView(cookiesDefault, cookiesArrayAdapter, cookiesTextView) + populateTextView(domStorageDefault, domStorageArrayAdapter, domStorageTextView) + populateTextView(formDataDefault, formDataArrayAdapter, formDataTextView) + populateTextView(easyListDefault, easyListArrayAdapter, easyListTextView) + populateTextView(easyPrivacyDefault, easyPrivacyArrayAdapter, easyPrivacyTextView) + populateTextView(fanboysAnnoyanceListDefault, fanboysAnnoyanceListArrayAdapter, fanboysAnnoyanceListTextView) + populateTextView(fanboysSocialBlockingListDefault, fanboysSocialBlockingListArrayAdapter, fanboysSocialBlockingListTextView) + populateTextView(ultraListDefault, ultraListArrayAdapter, ultraListTextView) + populateTextView(ultraPrivacyDefault, ultraPrivacyArrayAdapter, ultraPrivacyTextView) + populateTextView(blockAllThirdPartyRequestsDefault, blockAllThirdPartyRequestsArrayAdapter, blockAllThirdPartyRequestsTextView) + populateTextView(swipeToRefreshDefault, swipeToRefreshArrayAdapter, swipeToRefreshTextView) + populateTextView(wideViewportDefault, wideViewportArrayAdapter, wideViewportTextView) + populateTextView(displayWebpageImagesDefault, displayImagesArrayAdapter, displayImagesTextView) + + // Set the icon and text view settings. Non-standard items are handled individually below. + setIconAndTextViewSettings(cookiesInt, cookiesDefault, cookiesLinearLayout, cookiesImageView, cookiesTextView) + setIconAndTextViewSettings(domStorageInt, domStorageDefault, domStorageLinearLayout, domStorageImageView, domStorageTextView) + setIconAndTextViewSettings(formDataInt, formDataDefault, formDataLinearLayout, formDataImageView, formDataTextView) + setIconAndTextViewSettings(easyListInt, easyListDefault, easyListLinearLayout, easyListImageView, easyListTextView) + setIconAndTextViewSettings(easyPrivacyInt, easyPrivacyDefault, easyPrivacyLinearLayout, easyPrivacyImageView, easyListTextView) + setIconAndTextViewSettings(fanboysAnnoyanceListInt, fanboysAnnoyanceListDefault, fanboysAnnoyanceListLinearLayout, fanboysAnnoyanceListImageView, fanboysAnnoyanceListTextView) + setIconAndTextViewSettings(fanboysSocialBlockingListInt, fanboysSocialBlockingListDefault, fanboysSocialBlockingListLinearLayout, fanboysSocialBlockingListImageView, fanboysSocialBlockingListTextView) + setIconAndTextViewSettings(ultraListInt, ultraListDefault, ultraListLinearLayout, ultraListImageView, ultraListTextView) + setIconAndTextViewSettings(ultraPrivacyInt, ultraPrivacyDefault, ultraPrivacyLinearLayout, ultraPrivacyImageView, ultraPrivacyTextView) + setIconAndTextViewSettings(blockAllThirdPartyRequestsInt, blockAllThirdPartyRequestsDefault, blockAllThirdPartyRequestsLinearLayout, blockAllThirdPartyRequestsImageView, + blockAllThirdPartyRequestsTextView) + setIconAndTextViewSettings(swipeToRefreshInt, swipeToRefreshDefault, swipeToRefreshLinearLayout, swipeToRefreshImageView, swipeToRefreshTextView) + setIconAndTextViewSettings(wideViewportInt, wideViewportDefault, wideViewportLinearLayout, wideViewportImageView, wideViewportTextView) + setIconAndTextViewSettings(displayImagesInt, displayWebpageImagesDefault, displayImagesLinearLayout, displayImagesImageView, displayImagesTextView) - // Create the color spans. - val blueColorSpan = ForegroundColorSpan(requireContext().getColor(R.color.alt_blue_text)) - val redColorSpan = ForegroundColorSpan(requireContext().getColor(R.color.red_text)) // Set the domain name from the the database cursor. domainNameEditText.setText(domainNameString) + // Setup the pinned labels. + val cNameLabel = getString(R.string.common_name) + val oNameLabel = getString(R.string.organization) + val uNameLabel = getString(R.string.organizational_unit) + val startDateLabel = getString(R.string.start_date) + val endDateLabel = getString(R.string.end_date) + + // Create the color spans. + val blueColorSpan = ForegroundColorSpan(context.getColor(R.color.alt_blue_text)) + val redColorSpan = ForegroundColorSpan(context.getColor(R.color.red_text)) + // Update the certificates' Common Name color when the domain name text changes. domainNameEditText.addTextChangedListener(object : TextWatcher { override fun beforeTextChanged(s: CharSequence, start: Int, count: Int, after: Int) { @@ -355,80 +507,85 @@ class DomainSettingsFragment : Fragment() { } }) - // Set the switch positions. - javaScriptSwitch.isChecked = (javaScriptInt == 1) - cookiesSwitch.isChecked = (cookiesInt == 1) - domStorageSwitch.isChecked = (domStorageInt == 1) - formDataSwitch.isChecked = (formDataInt == 1) // Form data can be removed once the minimum API >= 26. - easyListSwitch.isChecked = (easyListInt == 1) - easyPrivacySwitch.isChecked = (easyPrivacyInt == 1) - fanboysAnnoyanceListSwitch.isChecked = (fanboysAnnoyanceListInt == 1) - fanboysSocialBlockingListSwitch.isChecked = (fanboysSocialBlockingListInt == 1) - ultraListSwitch.isChecked = (ultraListInt == 1) - ultraPrivacySwitch.isChecked = (ultraPrivacyInt == 1) - blockAllThirdPartyRequestsSwitch.isChecked = (blockAllThirdPartyRequestsInt == 1) - pinnedSslCertificateSwitch.isChecked = (pinnedSslCertificateInt == 1) - pinnedIpAddressesSwitch.isChecked = (pinnedIpAddressesInt == 1) - // Set the switch icon colors. - cookiesImageView.isSelected = (cookiesInt == 1) - domStorageImageView.isSelected = (domStorageInt == 1) - formDataImageView.isSelected = (formDataInt == 1) // Form data can be removed once the minimum API >= 26. - easyListImageView.isSelected = (easyListInt == 1) - easyPrivacyImageView.isSelected = (easyPrivacyInt == 1) - fanboysAnnoyanceListImageView.isSelected = (fanboysAnnoyanceListInt == 1) - fanboysSocialBlockingListImageView.isSelected = (fanboysSocialBlockingListInt == 1) - ultraListImageView.isSelected = (ultraListInt == 1) - ultraPrivacyImageView.isSelected = (ultraPrivacyInt == 1) - blockAllThirdPartyRequestsImageView.isSelected = (blockAllThirdPartyRequestsInt == 1) - pinnedSslCertificateImageView.isSelected = (pinnedSslCertificateInt == 1) - pinnedIpAddressesImageView.isSelected = (pinnedIpAddressesInt == 1) + // Set the javaScript icon and text view settings. + when (javaScriptInt) { + SYSTEM_DEFAULT -> { + // Set the icon. + if (javaScriptDefault) + javaScriptImageView.setImageDrawable(ResourcesCompat.getDrawable(resources, R.drawable.javascript_enabled, null)) + else + javaScriptImageView.setImageDrawable(ResourcesCompat.getDrawable(resources, R.drawable.privacy_mode, null)) - // Set the JavaScript icon. - if (javaScriptInt == 1) - javaScriptImageView.setImageDrawable(ResourcesCompat.getDrawable(resources, R.drawable.javascript_enabled, null)) - else - javaScriptImageView.setImageDrawable(ResourcesCompat.getDrawable(resources, R.drawable.privacy_mode, null)) + // Show the text view. + javaScriptTextView.visibility = View.VISIBLE - // Set the DOM storage switch status based on the JavaScript status. - domStorageSwitch.isEnabled = (javaScriptInt == 1) + // Set the background color to be transparent. + javaScriptLinearLayout.setBackgroundColor(getColor(context, R.color.transparent)) + } - // Set the DOM storage icon ghosted status based on the JavaScript status. - domStorageImageView.isEnabled = (javaScriptInt == 1) + ENABLED -> { + // Set the icon. + javaScriptImageView.setImageDrawable(ResourcesCompat.getDrawable(resources, R.drawable.javascript_enabled, null)) + + // Hide the text view. + javaScriptTextView.visibility = View.GONE - // Set the form data visibility. Form data can be removed once the minimum API >= 26. - if (Build.VERSION.SDK_INT >= 26) { - // Hide the form data image view and switch. - formDataImageView.visibility = View.GONE - formDataSwitch.visibility = View.GONE + // Set the background color to be blue. + javaScriptLinearLayout.setBackgroundColor(getColor(context, R.color.blue_background)) + } + + DISABLED -> { + // Set the icon. + javaScriptImageView.setImageDrawable(ResourcesCompat.getDrawable(resources, R.drawable.privacy_mode, null)) + + // Hide the text view. + javaScriptTextView.visibility = View.GONE + + // Set the background color to be blue. + javaScriptLinearLayout.setBackgroundColor(getColor(context, R.color.blue_background)) + } } - // Set Fanboy's Social Blocking List switch status based on the Annoyance List status. - fanboysSocialBlockingListSwitch.isEnabled = (fanboysAnnoyanceListInt == 0) + + // Calculate if JavaScript is enabled, either because it is the system default and that default is enabled, or because it is explicitly set to be enabled for this domain. + val javaScriptEnabled = (((javaScriptInt == 0) && javaScriptDefault) || (javaScriptInt == 1)) + + // Set the DOM storage spinner and text view status based on the JavaScript status. + domStorageSpinner.isEnabled = javaScriptEnabled + domStorageTextView.isEnabled = javaScriptEnabled + + // Set the DOM storage icon ghosted status based on the JavaScript status. + domStorageImageView.isEnabled = javaScriptEnabled + + + // Calculate if Fanboy's Annoyance List is enabled, either because it is the system default and that default is enabled, or because it is explicitly set to be enabled for this domain. + val fanboysAnnoyanceListEnabled = (((fanboysAnnoyanceListInt == 0) && fanboysAnnoyanceListDefault) || (fanboysAnnoyanceListInt == 1)) + + // Set Fanboy's Social Blocking List spinner and text view status based on the Annoyance List status. + fanboysSocialBlockingListSpinner.isEnabled = !fanboysAnnoyanceListEnabled + fanboysSocialBlockingListTextView.isEnabled = !fanboysAnnoyanceListEnabled // Set the Social Blocking List icon ghosted status based on the Annoyance List status. - fanboysSocialBlockingListImageView.isEnabled = (fanboysAnnoyanceListInt == 0) + fanboysSocialBlockingListImageView.isEnabled = !fanboysAnnoyanceListEnabled - // Open the spinners when the text view is clicked. - userAgentTextView.setOnClickListener { userAgentSpinner.performClick() } - defaultFontSizeTextView.setOnClickListener { fontSizeSpinner.performClick() } - swipeToRefreshTextView.setOnClickListener { swipeToRefreshSpinner.performClick() } - webViewThemeTextView.setOnClickListener { webViewThemeSpinner.performClick() } - wideViewportTextView.setOnClickListener { wideViewportSpinner.performClick() } - displayImagesTextView.setOnClickListener { displayImagesSpinner.performClick() } // 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") val bareWebViewLayout = inflater.inflate(R.layout.bare_webview, null, false) + + // Get a handle for the bare WebView. val bareWebView = bareWebViewLayout.findViewById(R.id.bare_webview) + + // Get the default user agent. val webViewDefaultUserAgentString = bareWebView.settings.userAgentString // Get a handle for the user agent array adapter. This array does not contain the `System default` entry. - val userAgentNamesArray = ArrayAdapter.createFromResource(requireContext(), R.array.user_agent_names, R.layout.spinner_item) + val userAgentNamesArray = ArrayAdapter.createFromResource(context, R.array.user_agent_names, R.layout.spinner_item) // Get the positions of the user agent and the default user agent. val userAgentArrayPosition = userAgentNamesArray.getPosition(currentUserAgentName) - val defaultUserAgentArrayPosition = userAgentNamesArray.getPosition(defaultUserAgentName) + val defaultUserAgentArrayPosition = userAgentNamesArray.getPosition(userAgentDefault) // Get a handle for the user agent data array. This array does not contain the `System default` entry. val userAgentDataArray = resources.getStringArray(R.array.user_agent_data) @@ -438,20 +595,20 @@ class DomainSettingsFragment : Fragment() { // Set the user agent according to the system default. when (defaultUserAgentArrayPosition) { // This is probably because it was set in an older version of Privacy Browser before the switch to persistent user agent names. - UNRECOGNIZED_USER_AGENT -> userAgentTextView.text = defaultUserAgentName + UNRECOGNIZED_USER_AGENT -> userAgentTextView.text = userAgentDefault // Display the WebView default user agent. SETTINGS_WEBVIEW_DEFAULT_USER_AGENT -> userAgentTextView.text = webViewDefaultUserAgentString // Display the custom user agent. - SETTINGS_CUSTOM_USER_AGENT -> userAgentTextView.text = defaultCustomUserAgentString + SETTINGS_CUSTOM_USER_AGENT -> userAgentTextView.text = customUserAgentStringDefault // Get the user agent string from the user agent data array. else -> userAgentTextView.text = userAgentDataArray[defaultUserAgentArrayPosition] } // Set the background color to be transparent. - userAgentLinearLayout.setBackgroundColor(getColor(requireContext(), R.color.transparent)) + userAgentLinearLayout.setBackgroundColor(getColor(context, R.color.transparent)) } else if (userAgentArrayPosition == UNRECOGNIZED_USER_AGENT || currentUserAgentName == getString(R.string.custom_user_agent)) { // A custom user agent is stored in the current user agent name. The second check is necessary in case the user did not change the default custom text. // Set the user agent spinner to `Custom user agent`. @@ -465,7 +622,7 @@ class DomainSettingsFragment : Fragment() { customUserAgentEditText.setText(currentUserAgentName) // Set the background color to be blue. - userAgentLinearLayout.setBackgroundColor(getColor(requireContext(), R.color.blue_background)) + userAgentLinearLayout.setBackgroundColor(getColor(context, R.color.blue_background)) } else { // The user agent name contains one of the canonical user agents. // Set the user agent spinner selection. The spinner has one more entry at the beginning than the user agent data array, so the position must be incremented. userAgentSpinner.setSelection(userAgentArrayPosition + 1) @@ -486,14 +643,14 @@ class DomainSettingsFragment : Fragment() { } // Set the background color to be blue. - userAgentLinearLayout.setBackgroundColor(getColor(requireContext(), R.color.blue_background)) + userAgentLinearLayout.setBackgroundColor(getColor(context, R.color.blue_background)) } // Display the font size settings. - if (fontSizeInt == 0) { // `0` is the code for system default font size. + if (fontSizeInt == SYSTEM_DEFAULT) { // `0` is the code for system default font size. // Set the font size to the system default. - fontSizeSpinner.setSelection(0) + fontSizeSpinner.setSelection(SYSTEM_DEFAULT) // Show the default font size text view. defaultFontSizeTextView.visibility = View.VISIBLE @@ -502,10 +659,10 @@ class DomainSettingsFragment : Fragment() { customFontSizeEditText.visibility = View.GONE // Set the default font size as the text of the custom font size edit text. This way, if the user switches to custom it will already be populated. - customFontSizeEditText.setText(defaultFontSizeString) + customFontSizeEditText.setText(fontSizeStringDefault) // Set the background color to be transparent. - fontSizeLinearLayout.setBackgroundColor(getColor(requireContext(), R.color.transparent)) + fontSizeLinearLayout.setBackgroundColor(getColor(context, R.color.transparent)) } else { // A custom font size is selected. // Set the spinner to the custom font size. fontSizeSpinner.setSelection(1) @@ -520,81 +677,34 @@ class DomainSettingsFragment : Fragment() { customFontSizeEditText.setText(fontSizeInt.toString()) // Set the background color to be blue. - fontSizeLinearLayout.setBackgroundColor(getColor(requireContext(), R.color.blue_background)) + fontSizeLinearLayout.setBackgroundColor(getColor(context, R.color.blue_background)) } // Initialize the default font size percentage string. - val defaultFontSizePercentageString = "$defaultFontSizeString%" + val defaultFontSizePercentageString = "$fontSizeStringDefault%" // Set the default font size text in the text view. defaultFontSizeTextView.text = defaultFontSizePercentageString - // Select the swipe-to-refresh selection in the spinner. - swipeToRefreshSpinner.setSelection(swipeToRefreshInt) - - // Set the swipe-to-refresh text. - if (defaultSwipeToRefresh) - swipeToRefreshTextView.text = swipeToRefreshArrayAdapter.getItem(DomainsDatabaseHelper.ENABLED) - else - swipeToRefreshTextView.text = swipeToRefreshArrayAdapter.getItem(DomainsDatabaseHelper.DISABLED) - - // Set the swipe-to-refresh icon and text view settings. - when (swipeToRefreshInt) { - DomainsDatabaseHelper.SYSTEM_DEFAULT -> { - // Set the icon color. - swipeToRefreshImageView.isSelected = defaultSwipeToRefresh - - // Show the swipe-to-refresh text view. - swipeToRefreshTextView.visibility = View.VISIBLE - - // Set the background color to be transparent. - swipeToRefreshLinearLayout.setBackgroundColor(getColor(requireContext(), R.color.transparent)) - } - - DomainsDatabaseHelper.ENABLED -> { - // Set the icon color. - swipeToRefreshImageView.isSelected = true - - // Hide the swipe-to-refresh text view. - swipeToRefreshTextView.visibility = View.GONE - - // Set the background color to be blue. - swipeToRefreshLinearLayout.setBackgroundColor(getColor(requireContext(), R.color.blue_background)) - } - - DomainsDatabaseHelper.DISABLED -> { - // Set the icon color. - swipeToRefreshImageView.isSelected = false - - // Hide the swipe-to-refresh text view. - swipeToRefreshTextView.visibility = View.GONE - - // Set the background color to be blue. - swipeToRefreshLinearLayout.setBackgroundColor(getColor(requireContext(), R.color.blue_background)) - } - } // Get the WebView theme string arrays. val webViewThemeStringArray = resources.getStringArray(R.array.webview_theme_array) val webViewThemeEntryValuesStringArray = resources.getStringArray(R.array.webview_theme_entry_values) - // Get the WebView theme entry number that matches the current WebView theme. - val appWebViewThemeEntryNumber = when (defaultWebViewTheme) { - webViewThemeEntryValuesStringArray[1] -> { 1 } // The light theme is selected. - webViewThemeEntryValuesStringArray[2] -> { 2 } // The dark theme is selected. - else -> { 0 } // The system default theme is selected. + // Get the WebView theme entry number that matches the current WebView theme string. + val appWebViewThemeEntryNumber = when (webViewThemeDefault) { + webViewThemeEntryValuesStringArray[1] -> { LIGHT_THEME } // The light theme is selected. + webViewThemeEntryValuesStringArray[2] -> { DARK_THEME } // The dark theme is selected. + else -> { SYSTEM_DEFAULT } // The system default theme is selected. } - // Select the WebView theme in the spinner. - webViewThemeSpinner.setSelection(webViewThemeInt) - - // Set the WebView theme text. - if (appWebViewThemeEntryNumber == DomainsDatabaseHelper.SYSTEM_DEFAULT) { // The app WebView theme is system default. + // Set the WebView theme text. This is only displayed if system default is selection, but it should be set here in case the user changes the selection. + if (appWebViewThemeEntryNumber == SYSTEM_DEFAULT) { // The app WebView theme is system default. // Set the text according to the current UI theme. if (currentThemeStatus == Configuration.UI_MODE_NIGHT_NO) - webViewThemeTextView.text = webViewThemeStringArray[DomainsDatabaseHelper.LIGHT_THEME] + webViewThemeTextView.text = webViewThemeStringArray[LIGHT_THEME] else - webViewThemeTextView.text = webViewThemeStringArray[DomainsDatabaseHelper.DARK_THEME] + webViewThemeTextView.text = webViewThemeStringArray[DARK_THEME] } else { // The app WebView theme is not system default. // Set the text according to the app WebView theme. webViewThemeTextView.text = webViewThemeStringArray[appWebViewThemeEntryNumber] @@ -602,22 +712,22 @@ class DomainSettingsFragment : Fragment() { // Set the WebView theme icon and text visibility. when (webViewThemeInt) { - DomainsDatabaseHelper.SYSTEM_DEFAULT -> { + SYSTEM_DEFAULT -> { // Set the icon color. when (appWebViewThemeEntryNumber) { - DomainsDatabaseHelper.SYSTEM_DEFAULT -> webViewThemeImageView.isSelected = (currentThemeStatus == Configuration.UI_MODE_NIGHT_NO) - DomainsDatabaseHelper.LIGHT_THEME -> webViewThemeImageView.isSelected = true - DomainsDatabaseHelper.DARK_THEME -> webViewThemeImageView.isSelected = false + SYSTEM_DEFAULT -> webViewThemeImageView.isSelected = (currentThemeStatus == Configuration.UI_MODE_NIGHT_NO) + LIGHT_THEME -> webViewThemeImageView.isSelected = true + DARK_THEME -> webViewThemeImageView.isSelected = false } // Show the WebView theme text view. webViewThemeTextView.visibility = View.VISIBLE // Set the background color to be transparent. - webViewThemeLinearLayout.setBackgroundColor(getColor(requireContext(), R.color.transparent)) + webViewThemeLinearLayout.setBackgroundColor(getColor(context, R.color.transparent)) } - DomainsDatabaseHelper.LIGHT_THEME -> { + LIGHT_THEME -> { // Set the icon color. webViewThemeImageView.isSelected = true @@ -625,10 +735,10 @@ class DomainSettingsFragment : Fragment() { webViewThemeTextView.visibility = View.GONE // Set the background color to be blue. - webViewThemeLinearLayout.setBackgroundColor(getColor(requireContext(), R.color.blue_background)) + webViewThemeLinearLayout.setBackgroundColor(getColor(context, R.color.blue_background)) } - DomainsDatabaseHelper.DARK_THEME -> { + DARK_THEME -> { // Set the icon color. webViewThemeImageView.isSelected = false @@ -636,102 +746,50 @@ class DomainSettingsFragment : Fragment() { webViewThemeTextView.visibility = View.GONE // Set the background color to be blue. - webViewThemeLinearLayout.setBackgroundColor(getColor(requireContext(), R.color.blue_background)) + webViewThemeLinearLayout.setBackgroundColor(getColor(context, R.color.blue_background)) } } - // Select the wide viewport in the spinner. - wideViewportSpinner.setSelection(wideViewportInt) - - // Set the default wide viewport text. - if (defaultWideViewport) - wideViewportTextView.text = wideViewportArrayAdapter.getItem(DomainsDatabaseHelper.ENABLED) - else - wideViewportTextView.text = wideViewportArrayAdapter.getItem(DomainsDatabaseHelper.DISABLED) - - // Set the wide viewport icon and text view settings. - when (wideViewportInt) { - DomainsDatabaseHelper.SYSTEM_DEFAULT -> { - // Set the icon color. - wideViewportImageView.isSelected = defaultWideViewport - - // Show the wide viewport text view. - wideViewportTextView.visibility = View.VISIBLE - - // Set the background color to be transparent. - wideViewportLinearLayout.setBackgroundColor(getColor(requireContext(), R.color.transparent)) - } - - DomainsDatabaseHelper.ENABLED -> { - // Set the icon color. - wideViewportImageView.isSelected = true - // Hide the wide viewport text view. - wideViewportTextView.visibility = View.GONE + // Set the switch positions. + pinnedSslCertificateSwitch.isChecked = (pinnedSslCertificateInt == 1) + pinnedIpAddressesSwitch.isChecked = (pinnedIpAddressesInt == 1) - // Set the background color to be blue. - wideViewportLinearLayout.setBackgroundColor(getColor(requireContext(), R.color.blue_background)) - } + // Set the switch icon colors. + pinnedSslCertificateImageView.isSelected = (pinnedSslCertificateInt == 1) + pinnedIpAddressesImageView.isSelected = (pinnedIpAddressesInt == 1) - DomainsDatabaseHelper.DISABLED -> { - // Set the icon color. - wideViewportImageView.isSelected = false + // Store the current date. + val currentDate = Calendar.getInstance().time - // Hide the wide viewport text view. - wideViewportTextView.visibility = View.GONE + // Create a spannable string builder for each text view that needs multiple colors of text. + val savedSslIssuedToCNameStringBuilder = SpannableStringBuilder(cNameLabel + savedSslIssuedToCNameString) + val savedSslIssuedToONameStringBuilder = SpannableStringBuilder(oNameLabel + savedSslIssuedToONameString) + val savedSslIssuedToUNameStringBuilder = SpannableStringBuilder(uNameLabel + savedSslIssuedToUNameString) + val savedSslIssuedByCNameStringBuilder = SpannableStringBuilder(cNameLabel + savedSslIssuedByCNameString) + val savedSslIssuedByONameStringBuilder = SpannableStringBuilder(oNameLabel + savedSslIssuedByONameString) + val savedSslIssuedByUNameStringBuilder = SpannableStringBuilder(uNameLabel + savedSslIssuedByUNameString) - // Set the background color to be blue. - wideViewportLinearLayout.setBackgroundColor(getColor(requireContext(), R.color.blue_background)) - } - } + // Initialize the saved SSL certificate date variables. + var savedSslStartDate: Date? = null + var savedSslEndDate: Date? = null - // Display the website images mode in the spinner. - displayImagesSpinner.setSelection(displayImagesInt) + // Only get the saved SSL certificate dates from the cursor if they are not set to `0`. + if (savedSslStartDateLong != 0L) + savedSslStartDate = Date(savedSslStartDateLong) + if (savedSslEndDateLong != 0L) + savedSslEndDate = Date(savedSslEndDateLong) - // Set the default display images text. - if (defaultDisplayWebpageImages) - displayImagesTextView.text = displayImagesArrayAdapter.getItem(DomainsDatabaseHelper.ENABLED) + // Create the date spannable string builders. + val savedSslStartDateStringBuilder: SpannableStringBuilder = if (savedSslStartDate == null) + SpannableStringBuilder(startDateLabel) else - displayImagesTextView.text = displayImagesArrayAdapter.getItem(DomainsDatabaseHelper.DISABLED) - - // Set the display website images icon and text view settings. - when (displayImagesInt) { - DomainsDatabaseHelper.SYSTEM_DEFAULT -> { - // Set the icon color. - displayImagesImageView.isSelected = defaultDisplayWebpageImages - - // Show the display images text view. - displayImagesTextView.visibility = View.VISIBLE - - // Set the background color to be transparent. - displayImagesLinearLayout.setBackgroundColor(getColor(requireContext(), R.color.transparent)) - } - - DomainsDatabaseHelper.ENABLED -> { - // Set the icon color. - displayImagesImageView.isSelected = true - - // Hide the display images text view. - displayImagesTextView.visibility = View.GONE - - // Set the background color to be blue. - displayImagesLinearLayout.setBackgroundColor(getColor(requireContext(), R.color.blue_background)) - } - - DomainsDatabaseHelper.DISABLED -> { - // Set the icon color. - displayImagesImageView.isSelected = false - - // Hide the display images text view. - displayImagesTextView.visibility = View.GONE - - // Set the background color to be blue. - displayImagesLinearLayout.setBackgroundColor(getColor(requireContext(), R.color.blue_background)) - } - } + SpannableStringBuilder(startDateLabel + DateFormat.getDateTimeInstance(DateFormat.MEDIUM, DateFormat.LONG).format(savedSslStartDate)) - // Store the current date. - val currentDate = Calendar.getInstance().time + val savedSslEndDateStringBuilder: SpannableStringBuilder = if (savedSslEndDate == null) + SpannableStringBuilder(endDateLabel) + else + SpannableStringBuilder(endDateLabel + DateFormat.getDateTimeInstance(DateFormat.MEDIUM, DateFormat.LONG).format(savedSslEndDate)) // Setup the string builders to display the general certificate information in blue. `SPAN_INCLUSIVE_INCLUSIVE` allows the span to grow in either direction. savedSslIssuedToONameStringBuilder.setSpan(blueColorSpan, oNameLabel.length, savedSslIssuedToONameStringBuilder.length, Spanned.SPAN_INCLUSIVE_INCLUSIVE) @@ -905,7 +963,7 @@ class DomainSettingsFragment : Fragment() { currentIpAddressesRadioButton.isChecked = false // Darken the background of the current IP addresses linear layout. - currentWebsiteCertificateLinearLayout.setBackgroundResource(R.color.translucent_background) + currentIpAddressesLinearLayout.setBackgroundResource(R.color.translucent_background) } else { // The saved IP addresses are hidden. // Check the current IP addresses radio button. currentIpAddressesRadioButton.isChecked = true @@ -924,87 +982,193 @@ class DomainSettingsFragment : Fragment() { } - // Set the JavaScript switch listener. - javaScriptSwitch.setOnCheckedChangeListener { _: CompoundButton?, isChecked: Boolean -> - // Update the JavaScript icon. - if (isChecked) - javaScriptImageView.setImageDrawable(ResourcesCompat.getDrawable(resources, R.drawable.javascript_enabled, null)) - else - javaScriptImageView.setImageDrawable(ResourcesCompat.getDrawable(resources, R.drawable.privacy_mode, null)) + // Set the JavaScript spinner listener. + javaScriptSpinner.onItemSelectedListener = object : AdapterView.OnItemSelectedListener { + override fun onItemSelected(parent: AdapterView<*>?, view: View?, position: Int, id: Long) { + when (position) { + SYSTEM_DEFAULT -> { + // Set the icon. + if (javaScriptDefault) + javaScriptImageView.setImageDrawable(ResourcesCompat.getDrawable(resources, R.drawable.javascript_enabled, null)) + else + javaScriptImageView.setImageDrawable(ResourcesCompat.getDrawable(resources, R.drawable.privacy_mode, null)) - // Set the DOM storage switch status. - domStorageSwitch.isEnabled = isChecked + // Show the text view. + javaScriptTextView.visibility = View.VISIBLE - // Set the DOM storage ghosted icon status. - domStorageImageView.isEnabled = isChecked + // Set the background color to be transparent. + javaScriptLinearLayout.setBackgroundColor(getColor(context, R.color.transparent)) + } + + ENABLED -> { + // Set the icon. + javaScriptImageView.setImageDrawable(ResourcesCompat.getDrawable(resources, R.drawable.javascript_enabled, null)) + + // Hide the text view. + javaScriptTextView.visibility = View.GONE + + // Set the background color to be blue. + javaScriptLinearLayout.setBackgroundColor(getColor(context, R.color.blue_background)) + } + + DISABLED -> { + // Set the icon. + javaScriptImageView.setImageDrawable(ResourcesCompat.getDrawable(resources, R.drawable.privacy_mode, null)) + + // Hide the text view. + javaScriptTextView.visibility = View.GONE + + // Set the background color to be blue. + javaScriptLinearLayout.setBackgroundColor(getColor(context, R.color.blue_background)) + } + } + + // Calculate if JavaScript is enabled, either because it is the system default and that default is enabled, or because it is explicitly set to be enabled for this domain. + val updatedJavaScriptEnabled = (((position == 0) && javaScriptDefault) || (position == 1)) + + // Set the DOM storage spinner and text view status based on the JavaScript status. + domStorageSpinner.isEnabled = updatedJavaScriptEnabled + domStorageTextView.isEnabled = updatedJavaScriptEnabled + + // Set the DOM storage icon ghosted status based on the JavaScript status. + domStorageImageView.isEnabled = updatedJavaScriptEnabled + } + + override fun onNothingSelected(parent: AdapterView<*>?) { + // Do nothing. + } } // Set the cookies switch listener. - cookiesSwitch.setOnCheckedChangeListener { _: CompoundButton?, isChecked: Boolean -> - // Update the icon color. - cookiesImageView.isSelected = isChecked + cookiesSpinner.onItemSelectedListener = object : AdapterView.OnItemSelectedListener { + override fun onItemSelected(parent: AdapterView<*>?, view: View?, position: Int, id: Long) { + // Update the icon and the text view settings. + setIconAndTextViewSettings(position, cookiesDefault, cookiesLinearLayout, cookiesImageView, cookiesTextView) + } + + override fun onNothingSelected(parent: AdapterView<*>?) { + // Do nothing. + } } - // Set the DOM Storage switch listener. - domStorageSwitch.setOnCheckedChangeListener { _: CompoundButton?, isChecked: Boolean -> - // Update the icon color. - domStorageImageView.isSelected = isChecked + // Set the DOM Storage spinner listener. + domStorageSpinner.onItemSelectedListener = object : AdapterView.OnItemSelectedListener { + override fun onItemSelected(parent: AdapterView<*>?, view: View?, position: Int, id: Long) { + // Update the icon and the text view settings. + setIconAndTextViewSettings(position, domStorageDefault, domStorageLinearLayout, domStorageImageView, domStorageTextView) + } + + override fun onNothingSelected(parent: AdapterView<*>?) { + // Do nothing. + } } - // Set the form data switch listener. It can be removed once the minimum API >= 26. + // Set the form data spinner listener. It can be removed once the minimum API >= 26. if (Build.VERSION.SDK_INT < 26) { - formDataSwitch.setOnCheckedChangeListener { _: CompoundButton?, isChecked: Boolean -> - // Update the icon color. - formDataImageView.isSelected = isChecked + formDataSpinner.onItemSelectedListener = object : AdapterView.OnItemSelectedListener { + override fun onItemSelected(parent: AdapterView<*>?, view: View?, position: Int, id: Long) { + // Update the icon and the text view settings. + setIconAndTextViewSettings(position, formDataDefault, formDataLinearLayout, formDataImageView, formDataTextView) + } + + override fun onNothingSelected(parent: AdapterView<*>?) { + // Do nothing. + } } } - // Set the EasyList switch listener. - easyListSwitch.setOnCheckedChangeListener { _: CompoundButton?, isChecked: Boolean -> - // Update the icon color. - easyListImageView.isSelected = isChecked + // Set the EasyList spinner listener. + easyListSpinner.onItemSelectedListener = object : AdapterView.OnItemSelectedListener { + override fun onItemSelected(parent: AdapterView<*>?, view: View?, position: Int, id: Long) { + // Update the icon and the text view settings. + setIconAndTextViewSettings(position, easyListDefault, easyListLinearLayout, easyListImageView, easyListTextView) + } + + override fun onNothingSelected(parent: AdapterView<*>?) { + // Do nothing. + } } - // Set the EasyPrivacy switch listener. - easyPrivacySwitch.setOnCheckedChangeListener { _: CompoundButton?, isChecked: Boolean -> - // Update the icon color. - easyPrivacyImageView.isSelected = isChecked + // Set the EasyPrivacy spinner listener. + easyPrivacySpinner.onItemSelectedListener = object : AdapterView.OnItemSelectedListener { + override fun onItemSelected(parent: AdapterView<*>?, view: View?, position: Int, id: Long) { + // Update the icon and the text view settings. + setIconAndTextViewSettings(position, easyPrivacyDefault, easyPrivacyLinearLayout, easyPrivacyImageView, easyPrivacyTextView) + } + + override fun onNothingSelected(parent: AdapterView<*>?) { + // Do nothing. + } } - // Set the Fanboy's Annoyance List switch listener. - fanboysAnnoyanceListSwitch.setOnCheckedChangeListener { _: CompoundButton?, isChecked: Boolean -> - // Update the icon color. - fanboysAnnoyanceListImageView.isSelected = isChecked + // Set the Fanboy's Annoyance List spinner listener. + fanboysAnnoyanceListSpinner.onItemSelectedListener = object : AdapterView.OnItemSelectedListener { + override fun onItemSelected(parent: AdapterView<*>?, view: View?, position: Int, id: Long) { + // Update the icon and the text view settings. + setIconAndTextViewSettings(position, fanboysAnnoyanceListDefault, fanboysAnnoyanceListLinearLayout, fanboysAnnoyanceListImageView, fanboysAnnoyanceListTextView) + + // Calculate if Fanboy's Annoyance List is enabled, either because it is the system default and that default is enabled, or because it is explicitly set to be enabled for this domain. + val updatedFanboysAnnoyanceListEnabled = (((position == 0) && fanboysAnnoyanceListDefault) || (position == 1)) - // Set Fanboy's Social Blocking List switch position. - fanboysSocialBlockingListSwitch.isEnabled = !isChecked + // Set Fanboy's Social Blocking List spinner and test view status based on the Annoyance List status. + fanboysSocialBlockingListSpinner.isEnabled = !updatedFanboysAnnoyanceListEnabled + fanboysSocialBlockingListTextView.isEnabled = !updatedFanboysAnnoyanceListEnabled + + // Set the Social Blocking List icon ghosted status based on the Annoyance List status. + fanboysSocialBlockingListImageView.isEnabled = !updatedFanboysAnnoyanceListEnabled + } - // Set the Social Blocking List icon ghosted status. - fanboysSocialBlockingListImageView.isEnabled = !isChecked + override fun onNothingSelected(parent: AdapterView<*>?) { + // Do nothing. + } } - // Set the Fanboy's Social Blocking List switch listener. - fanboysSocialBlockingListSwitch.setOnCheckedChangeListener { _: CompoundButton?, isChecked: Boolean -> - // Update the icon color. - fanboysSocialBlockingListImageView.isSelected = isChecked + // Set the Fanboy's Social Blocking List spinner listener. + fanboysSocialBlockingListSpinner.onItemSelectedListener = object : AdapterView.OnItemSelectedListener { + override fun onItemSelected(parent: AdapterView<*>?, view: View?, position: Int, id: Long) { + // Update the icon and the text view settings. + setIconAndTextViewSettings(position, fanboysSocialBlockingListDefault, fanboysSocialBlockingListLinearLayout, fanboysSocialBlockingListImageView, fanboysSocialBlockingListTextView) + } + + override fun onNothingSelected(parent: AdapterView<*>?) { + // Do nothing. + } } - // Set the UltraList switch listener. - ultraListSwitch.setOnCheckedChangeListener { _: CompoundButton?, isChecked: Boolean -> - // Update the icon color. - ultraListImageView.isSelected = isChecked + // Set the UltraList spinner listener. + ultraListSpinner.onItemSelectedListener = object : AdapterView.OnItemSelectedListener { + override fun onItemSelected(parent: AdapterView<*>?, view: View?, position: Int, id: Long) { + // Update the icon and the text view settings. + setIconAndTextViewSettings(position, ultraListDefault, ultraListLinearLayout, ultraListImageView, ultraListTextView) + } + + override fun onNothingSelected(parent: AdapterView<*>?) { + // Do nothing. + } } - // Set the UltraPrivacy switch listener. - ultraPrivacySwitch.setOnCheckedChangeListener { _: CompoundButton?, isChecked: Boolean -> - // Update the icon color. - ultraPrivacyImageView.isSelected = isChecked + // Set the UltraPrivacy spinner listener. + ultraPrivacySpinner.onItemSelectedListener = object : AdapterView.OnItemSelectedListener { + override fun onItemSelected(parent: AdapterView<*>?, view: View?, position: Int, id: Long) { + // Update the icon and the text view settings. + setIconAndTextViewSettings(position, ultraPrivacyDefault, ultraPrivacyLinearLayout, ultraPrivacyImageView, ultraPrivacyTextView) + } + + override fun onNothingSelected(parent: AdapterView<*>?) { + // Do nothing. + } } - // Set the block all third-party requests switch listener. - blockAllThirdPartyRequestsSwitch.setOnCheckedChangeListener { _: CompoundButton?, isChecked: Boolean -> - // Update the icon color. - blockAllThirdPartyRequestsImageView.isSelected = isChecked + // Set the block all third-party requests spinner listener. + blockAllThirdPartyRequestsSpinner.onItemSelectedListener = object : AdapterView.OnItemSelectedListener { + override fun onItemSelected(parent: AdapterView<*>?, view: View?, position: Int, id: Long) { + // Update the icon and the text view settings. + setIconAndTextViewSettings(position, blockAllThirdPartyRequestsDefault, blockAllThirdPartyRequestsLinearLayout, blockAllThirdPartyRequestsImageView, blockAllThirdPartyRequestsTextView) + } + + override fun onNothingSelected(parent: AdapterView<*>?) { + // Do nothing. + } } // Set the user agent spinner listener. @@ -1022,20 +1186,20 @@ class DomainSettingsFragment : Fragment() { // Set the user text. when (defaultUserAgentArrayPosition) { // This is probably because it was set in an older version of Privacy Browser before the switch to persistent user agent names. - UNRECOGNIZED_USER_AGENT -> userAgentTextView.text = defaultUserAgentName + UNRECOGNIZED_USER_AGENT -> userAgentTextView.text = userAgentDefault // Display the `WebView` default user agent. SETTINGS_WEBVIEW_DEFAULT_USER_AGENT -> userAgentTextView.text = webViewDefaultUserAgentString // Display the custom user agent. - SETTINGS_CUSTOM_USER_AGENT -> userAgentTextView.text = defaultCustomUserAgentString + SETTINGS_CUSTOM_USER_AGENT -> userAgentTextView.text = customUserAgentStringDefault // Get the user agent string from the user agent data array. else -> userAgentTextView.text = userAgentDataArray[defaultUserAgentArrayPosition] } // Set the background color to be transparent. - userAgentLinearLayout.setBackgroundColor(getColor(requireContext(), R.color.transparent)) + userAgentLinearLayout.setBackgroundColor(getColor(context, R.color.transparent)) } DOMAINS_WEBVIEW_DEFAULT_USER_AGENT -> { @@ -1045,15 +1209,15 @@ class DomainSettingsFragment : Fragment() { // Set the user agent text. userAgentTextView.text = webViewDefaultUserAgentString - // Hide the custom user agent EditTex. + // Hide the custom user agent edit text. customUserAgentEditText.visibility = View.GONE // Set the background color to be blue. - userAgentLinearLayout.setBackgroundColor(getColor(requireContext(), R.color.blue_background)) + userAgentLinearLayout.setBackgroundColor(getColor(context, R.color.blue_background)) } DOMAINS_CUSTOM_USER_AGENT -> { - // Hide the user agent TextView. + // Hide the user agent text view. userAgentTextView.visibility = View.GONE // Show the custom user agent edit text. @@ -1063,7 +1227,7 @@ class DomainSettingsFragment : Fragment() { customUserAgentEditText.setText(currentUserAgentName) // Set the background color to be blue. - userAgentLinearLayout.setBackgroundColor(getColor(requireContext(), R.color.blue_background)) + userAgentLinearLayout.setBackgroundColor(getColor(context, R.color.blue_background)) } else -> { @@ -1077,7 +1241,7 @@ class DomainSettingsFragment : Fragment() { customUserAgentEditText.visibility = View.GONE // Set the background color to be blue. - userAgentLinearLayout.setBackgroundColor(getColor(requireContext(), R.color.blue_background)) + userAgentLinearLayout.setBackgroundColor(getColor(context, R.color.blue_background)) } } } @@ -1091,7 +1255,7 @@ class DomainSettingsFragment : Fragment() { fontSizeSpinner.onItemSelectedListener = object : AdapterView.OnItemSelectedListener { override fun onItemSelected(parent: AdapterView<*>?, view: View?, position: Int, id: Long) { // Update the font size display options. - if (position == 0) { // The system default font size has been selected. + if (position == SYSTEM_DEFAULT) { // The system default font size has been selected. // Show the default font size text view. defaultFontSizeTextView.visibility = View.VISIBLE @@ -1099,7 +1263,7 @@ class DomainSettingsFragment : Fragment() { customFontSizeEditText.visibility = View.GONE // Set the background color to be transparent. - fontSizeLinearLayout.setBackgroundColor(getColor(requireContext(), R.color.transparent)) + fontSizeLinearLayout.setBackgroundColor(getColor(context, R.color.transparent)) } else { // A custom font size has been selected. // Hide the default font size text view. defaultFontSizeTextView.visibility = View.GONE @@ -1108,7 +1272,7 @@ class DomainSettingsFragment : Fragment() { customFontSizeEditText.visibility = View.VISIBLE // Set the background color to be blue. - fontSizeLinearLayout.setBackgroundColor(getColor(requireContext(), R.color.blue_background)) + fontSizeLinearLayout.setBackgroundColor(getColor(context, R.color.blue_background)) } } @@ -1120,41 +1284,8 @@ class DomainSettingsFragment : Fragment() { // Set the swipe-to-refresh spinner listener. swipeToRefreshSpinner.onItemSelectedListener = object : AdapterView.OnItemSelectedListener { override fun onItemSelected(parent: AdapterView<*>?, view: View?, position: Int, id: Long) { - // Update the icon and the visibility of the text view. - when (position) { - DomainsDatabaseHelper.SYSTEM_DEFAULT -> { - // Set the icon color. - swipeToRefreshImageView.isSelected = defaultSwipeToRefresh - - // Show the swipe-to-refresh text view. - swipeToRefreshTextView.visibility = View.VISIBLE - - // Set the background color to be transparent. - swipeToRefreshLinearLayout.setBackgroundColor(getColor(requireContext(), R.color.transparent)) - } - - DomainsDatabaseHelper.ENABLED -> { - // Set the icon color. - swipeToRefreshImageView.isSelected = true - - // Hide the swipe-to-refresh text view. - swipeToRefreshTextView.visibility = View.GONE - - // Set the background color to be blue. - swipeToRefreshLinearLayout.setBackgroundColor(getColor(requireContext(), R.color.blue_background)) - } - - DomainsDatabaseHelper.DISABLED -> { - // Set the icon color. - swipeToRefreshImageView.isSelected = false - - // Hide the swipe-to-refresh text view. - swipeToRefreshTextView.visibility = View.GONE - - // Set the background color to be blue. - swipeToRefreshLinearLayout.setBackgroundColor(getColor(requireContext(), R.color.blue_background)) - } - } + // Update the icon and the text view settings. + setIconAndTextViewSettings(position, swipeToRefreshDefault, swipeToRefreshLinearLayout, swipeToRefreshImageView, swipeToRefreshTextView) } override fun onNothingSelected(parent: AdapterView<*>?) { @@ -1165,24 +1296,24 @@ class DomainSettingsFragment : Fragment() { // Set the WebView theme spinner listener. webViewThemeSpinner.onItemSelectedListener = object : AdapterView.OnItemSelectedListener { override fun onItemSelected(parent: AdapterView<*>?, view: View?, position: Int, id: Long) { - // Update the icon and the visibility of the WebView theme text view. + // Update the icon and the WebView theme text view settings. when (position) { - DomainsDatabaseHelper.SYSTEM_DEFAULT -> { + SYSTEM_DEFAULT -> { // Set the icon color. when (appWebViewThemeEntryNumber) { - DomainsDatabaseHelper.SYSTEM_DEFAULT -> webViewThemeImageView.isSelected = (currentThemeStatus == Configuration.UI_MODE_NIGHT_NO) - DomainsDatabaseHelper.LIGHT_THEME -> webViewThemeImageView.isSelected = true - DomainsDatabaseHelper.DARK_THEME -> webViewThemeImageView.isSelected = false + SYSTEM_DEFAULT -> webViewThemeImageView.isSelected = (currentThemeStatus == Configuration.UI_MODE_NIGHT_NO) + LIGHT_THEME -> webViewThemeImageView.isSelected = true + DARK_THEME -> webViewThemeImageView.isSelected = false } // Show the WebView theme text view. webViewThemeTextView.visibility = View.VISIBLE // Set the background color to be transparent. - webViewThemeLinearLayout.setBackgroundColor(getColor(requireContext(), R.color.transparent)) + webViewThemeLinearLayout.setBackgroundColor(getColor(context, R.color.transparent)) } - DomainsDatabaseHelper.LIGHT_THEME -> { + LIGHT_THEME -> { // Set the icon color. webViewThemeImageView.isSelected = true @@ -1190,10 +1321,10 @@ class DomainSettingsFragment : Fragment() { webViewThemeTextView.visibility = View.GONE // Set the background color to be blue. - webViewThemeLinearLayout.setBackgroundColor(getColor(requireContext(), R.color.blue_background)) + webViewThemeLinearLayout.setBackgroundColor(getColor(context, R.color.blue_background)) } - DomainsDatabaseHelper.DARK_THEME -> { + DARK_THEME -> { // Set the icon color. webViewThemeImageView.isSelected = false @@ -1201,7 +1332,7 @@ class DomainSettingsFragment : Fragment() { webViewThemeTextView.visibility = View.GONE // Set the background color to be blue. - webViewThemeLinearLayout.setBackgroundColor(getColor(requireContext(), R.color.blue_background)) + webViewThemeLinearLayout.setBackgroundColor(getColor(context, R.color.blue_background)) } } } @@ -1214,41 +1345,8 @@ class DomainSettingsFragment : Fragment() { // Set the wide viewport spinner listener. wideViewportSpinner.onItemSelectedListener = object : AdapterView.OnItemSelectedListener { override fun onItemSelected(parent: AdapterView<*>?, view: View?, position: Int, id: Long) { - // Update the icon and the visibility of the wide viewport text view. - when (position) { - DomainsDatabaseHelper.SYSTEM_DEFAULT -> { - // Set the icon color. - wideViewportImageView.isSelected = defaultWideViewport - - // Show the wide viewport text view. - wideViewportTextView.visibility = View.VISIBLE - - // Set the background color to be transparent. - wideViewportLinearLayout.setBackgroundColor(getColor(requireContext(), R.color.transparent)) - } - - DomainsDatabaseHelper.ENABLED -> { - // Set the icon color. - wideViewportImageView.isSelected = true - - // Hide the wide viewport text view. - wideViewportTextView.visibility = View.GONE - - // Set the background color to be blue. - wideViewportLinearLayout.setBackgroundColor(getColor(requireContext(), R.color.blue_background)) - } - - DomainsDatabaseHelper.DISABLED -> { - // Set the icon color. - wideViewportImageView.isSelected = false - - // Hid ethe wide viewport text view. - wideViewportTextView.visibility = View.GONE - - // Set the background color to be blue. - wideViewportLinearLayout.setBackgroundColor(getColor(requireContext(), R.color.blue_background)) - } - } + // Update the icon and the text view settings. + setIconAndTextViewSettings(position, wideViewportDefault, wideViewportLinearLayout, wideViewportImageView, wideViewportTextView) } override fun onNothingSelected(parent: AdapterView<*>?) { @@ -1259,41 +1357,8 @@ class DomainSettingsFragment : Fragment() { // Set the display webpage images spinner listener. displayImagesSpinner.onItemSelectedListener = object : AdapterView.OnItemSelectedListener { override fun onItemSelected(parent: AdapterView<*>?, view: View?, position: Int, id: Long) { - // Update the icon and the visibility of the display images text view. - when (position) { - DomainsDatabaseHelper.SYSTEM_DEFAULT -> { - // Set the icon color. - displayImagesImageView.isSelected = defaultDisplayWebpageImages - - // Show the display images text view. - displayImagesTextView.visibility = View.VISIBLE - - // Set the background color to be transparent. - displayImagesLinearLayout.setBackgroundColor(getColor(requireContext(), R.color.transparent)) - } - - DomainsDatabaseHelper.ENABLED -> { - // Set the icon color. - displayImagesImageView.isSelected = true - - // Hide the display images text view. - displayImagesTextView.visibility = View.GONE - - // Set the background color to be blue. - displayImagesLinearLayout.setBackgroundColor(getColor(requireContext(), R.color.blue_background)) - } - - DomainsDatabaseHelper.DISABLED -> { - // Set the icon color. - displayImagesImageView.isSelected = false - - // Hide the display images text view. - displayImagesTextView.visibility = View.GONE - - // Set the background color to be blue. - displayImagesLinearLayout.setBackgroundColor(getColor(requireContext(), R.color.blue_background)) - } - } + // Update the icon and the text view settings. + setIconAndTextViewSettings(position, displayWebpageImagesDefault, displayImagesLinearLayout, displayImagesImageView, displayImagesTextView) } override fun onNothingSelected(parent: AdapterView<*>?) { @@ -1633,4 +1698,50 @@ class DomainSettingsFragment : Fragment() { return domainNamesMatch } + + private fun populateTextView(defaultValue: Boolean, arrayAdapter: ArrayAdapter, textView: TextView) { + // Set the text. + textView.text = if (defaultValue) + arrayAdapter.getItem(ENABLED) + else + arrayAdapter.getItem(DISABLED) + } + + private fun setIconAndTextViewSettings(databaseInt: Int, defaultValue: Boolean, linearLayout: LinearLayout, imageView: ImageView, textView: TextView) { + // Set the icon and text view settings. + when (databaseInt) { + SYSTEM_DEFAULT -> { + // Set the icon color. + imageView.isSelected = defaultValue + + // Show the text view. + textView.visibility = View.VISIBLE + + // Set the background color to be transparent. + linearLayout.setBackgroundColor(getColor(context, R.color.transparent)) + } + + ENABLED -> { + // Set the icon color. + imageView.isSelected = true + + // Hide the text view. + textView.visibility = View.GONE + + // Set the background color to be blue. + linearLayout.setBackgroundColor(getColor(context, R.color.blue_background)) + } + + DISABLED -> { + // Set the icon color. + imageView.isSelected = false + + // Hide the text view. + textView.visibility = View.GONE + + // Set the background color to be blue. + linearLayout.setBackgroundColor(getColor(context, R.color.blue_background)) + } + } + } } diff --git a/app/src/main/java/com/stoutner/privacybrowser/helpers/DomainsDatabaseHelper.kt b/app/src/main/java/com/stoutner/privacybrowser/helpers/DomainsDatabaseHelper.kt index 194310b7..d7270a2a 100644 --- a/app/src/main/java/com/stoutner/privacybrowser/helpers/DomainsDatabaseHelper.kt +++ b/app/src/main/java/com/stoutner/privacybrowser/helpers/DomainsDatabaseHelper.kt @@ -31,94 +31,94 @@ import androidx.preference.PreferenceManager import com.stoutner.privacybrowser.R // Define the class constants. -private const val SCHEMA_VERSION = 15 +private const val SCHEMA_VERSION = 16 + +// Define the public database constants. +const val DOMAINS_DATABASE = "domains.db" +const val DOMAINS_TABLE = "domains" + +// Define the public spinner constants. +const val SYSTEM_DEFAULT = 0 +const val ENABLED = 1 +const val DISABLED = 2 +const val LIGHT_THEME = 1 +const val DARK_THEME = 2 + +// Define the public schema constants. +const val BLOCK_ALL_THIRD_PARTY_REQUESTS = "blockallthirdpartyrequests" +const val COOKIES = "cookies" +const val DISPLAY_IMAGES = "displayimages" +const val DOMAIN_NAME = "domainname" +const val ENABLE_DOM_STORAGE = "enabledomstorage" +const val ENABLE_EASYLIST = "enableeasylist" +const val ENABLE_EASYPRIVACY = "enableeasyprivacy" +const val ENABLE_FANBOYS_ANNOYANCE_LIST = "enablefanboysannoyancelist" +const val ENABLE_FANBOYS_SOCIAL_BLOCKING_LIST = "enablefanboyssocialblockinglist" +const val ENABLE_FORM_DATA = "enableformdata" // Form data can be removed once the minimum API >= 26. +const val ENABLE_JAVASCRIPT = "enablejavascript" +const val ENABLE_ULTRAPRIVACY = "enableultraprivacy" +const val FONT_SIZE = "fontsize" +const val ID = "_id" +const val IP_ADDRESSES = "ip_addresses" +const val PINNED_IP_ADDRESSES = "pinned_ip_addresses" +const val PINNED_SSL_CERTIFICATE = "pinnedsslcertificate" +const val SSL_END_DATE = "sslenddate" +const val SSL_START_DATE = "sslstartdate" +const val SSL_ISSUED_BY_COMMON_NAME = "sslissuedbycommonname" +const val SSL_ISSUED_BY_ORGANIZATION = "sslissuedbyorganization" +const val SSL_ISSUED_BY_ORGANIZATIONAL_UNIT = "sslissuedbyorganizationalunit" +const val SSL_ISSUED_TO_COMMON_NAME = "sslissuedtocommonname" +const val SSL_ISSUED_TO_ORGANIZATION = "sslissuedtoorganization" +const val SSL_ISSUED_TO_ORGANIZATIONAL_UNIT = "sslissuedtoorganizationalunit" +const val SWIPE_TO_REFRESH = "swipetorefresh" +const val ULTRALIST = "ultralist" +const val USER_AGENT = "useragent" +const val WEBVIEW_THEME = "webview_theme" +const val WIDE_VIEWPORT = "wide_viewport" + +// Define the public table creation constant. +const val CREATE_DOMAINS_TABLE = "CREATE TABLE $DOMAINS_TABLE (" + + "$ID INTEGER PRIMARY KEY, " + + "$DOMAIN_NAME TEXT, " + + "$ENABLE_JAVASCRIPT INTEGER, " + + "$COOKIES INTEGER, " + + "$ENABLE_DOM_STORAGE INTEGER, " + + "$ENABLE_FORM_DATA INTEGER, " + + "$ENABLE_EASYLIST INTEGER, " + + "$ENABLE_EASYPRIVACY INTEGER, " + + "$ENABLE_FANBOYS_ANNOYANCE_LIST INTEGER, " + + "$ENABLE_FANBOYS_SOCIAL_BLOCKING_LIST INTEGER, " + + "$ULTRALIST INTEGER, " + + "$ENABLE_ULTRAPRIVACY INTEGER, " + + "$BLOCK_ALL_THIRD_PARTY_REQUESTS INTEGER, " + + "$USER_AGENT TEXT, " + + "$FONT_SIZE INTEGER, " + + "$SWIPE_TO_REFRESH INTEGER, " + + "$WEBVIEW_THEME INTEGER, " + + "$WIDE_VIEWPORT INTEGER, " + + "$DISPLAY_IMAGES INTEGER, " + + "$PINNED_SSL_CERTIFICATE BOOLEAN, " + + "$SSL_ISSUED_TO_COMMON_NAME TEXT, " + + "$SSL_ISSUED_TO_ORGANIZATION TEXT, " + + "$SSL_ISSUED_TO_ORGANIZATIONAL_UNIT TEXT, " + + "$SSL_ISSUED_BY_COMMON_NAME TEXT, " + + "$SSL_ISSUED_BY_ORGANIZATION TEXT, " + + "$SSL_ISSUED_BY_ORGANIZATIONAL_UNIT TEXT, " + + "$SSL_START_DATE INTEGER, " + + "$SSL_END_DATE INTEGER, " + + "$PINNED_IP_ADDRESSES BOOLEAN, " + + "$IP_ADDRESSES TEXT)" class DomainsDatabaseHelper(private val appContext: Context) : SQLiteOpenHelper(appContext, DOMAINS_DATABASE, null, SCHEMA_VERSION) { - // Define the public companion object constants. These can be moved to public class constants once the entire project has migrated to Kotlin. - companion object { - // Define the public database constants. - const val DOMAINS_DATABASE = "domains.db" - const val DOMAINS_TABLE = "domains" - - // Define the public spinner constants. - const val SYSTEM_DEFAULT = 0 - const val ENABLED = 1 - const val DISABLED = 2 - const val LIGHT_THEME = 1 - const val DARK_THEME = 2 - - // Define the public schema constants. - const val ID = "_id" - const val DOMAIN_NAME = "domainname" - const val ENABLE_JAVASCRIPT = "enablejavascript" - const val COOKIES = "cookies" - const val ENABLE_DOM_STORAGE = "enabledomstorage" - const val ENABLE_FORM_DATA = "enableformdata" // Form data can be removed once the minimum API >= 26. - const val ENABLE_EASYLIST = "enableeasylist" - const val ENABLE_EASYPRIVACY = "enableeasyprivacy" - const val ENABLE_FANBOYS_ANNOYANCE_LIST = "enablefanboysannoyancelist" - const val ENABLE_FANBOYS_SOCIAL_BLOCKING_LIST = "enablefanboyssocialblockinglist" - const val ULTRALIST = "ultralist" - const val ENABLE_ULTRAPRIVACY = "enableultraprivacy" - const val BLOCK_ALL_THIRD_PARTY_REQUESTS = "blockallthirdpartyrequests" - const val USER_AGENT = "useragent" - const val FONT_SIZE = "fontsize" - const val SWIPE_TO_REFRESH = "swipetorefresh" - const val WEBVIEW_THEME = "webview_theme" - const val WIDE_VIEWPORT = "wide_viewport" - const val DISPLAY_IMAGES = "displayimages" - const val PINNED_SSL_CERTIFICATE = "pinnedsslcertificate" - const val SSL_ISSUED_TO_COMMON_NAME = "sslissuedtocommonname" - const val SSL_ISSUED_TO_ORGANIZATION = "sslissuedtoorganization" - const val SSL_ISSUED_TO_ORGANIZATIONAL_UNIT = "sslissuedtoorganizationalunit" - const val SSL_ISSUED_BY_COMMON_NAME = "sslissuedbycommonname" - const val SSL_ISSUED_BY_ORGANIZATION = "sslissuedbyorganization" - const val SSL_ISSUED_BY_ORGANIZATIONAL_UNIT = "sslissuedbyorganizationalunit" - const val SSL_START_DATE = "sslstartdate" - const val SSL_END_DATE = "sslenddate" - const val PINNED_IP_ADDRESSES = "pinned_ip_addresses" - const val IP_ADDRESSES = "ip_addresses" - - // Define the public table creation constant. - const val CREATE_DOMAINS_TABLE = "CREATE TABLE $DOMAINS_TABLE (" + - "$ID INTEGER PRIMARY KEY, " + - "$DOMAIN_NAME TEXT, " + - "$ENABLE_JAVASCRIPT BOOLEAN, " + - "$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, " + - "$ULTRALIST BOOLEAN, " + - "$ENABLE_ULTRAPRIVACY BOOLEAN, " + - "$BLOCK_ALL_THIRD_PARTY_REQUESTS BOOLEAN, " + - "$USER_AGENT TEXT, " + - "$FONT_SIZE INTEGER, " + - "$SWIPE_TO_REFRESH INTEGER, " + - "$WEBVIEW_THEME INTEGER, " + - "$WIDE_VIEWPORT INTEGER, " + - "$DISPLAY_IMAGES INTEGER, " + - "$PINNED_SSL_CERTIFICATE BOOLEAN, " + - "$SSL_ISSUED_TO_COMMON_NAME TEXT, " + - "$SSL_ISSUED_TO_ORGANIZATION TEXT, " + - "$SSL_ISSUED_TO_ORGANIZATIONAL_UNIT TEXT, " + - "$SSL_ISSUED_BY_COMMON_NAME TEXT, " + - "$SSL_ISSUED_BY_ORGANIZATION TEXT, " + - "$SSL_ISSUED_BY_ORGANIZATIONAL_UNIT TEXT, " + - "$SSL_START_DATE INTEGER, " + - "$SSL_END_DATE INTEGER, " + - "$PINNED_IP_ADDRESSES BOOLEAN, " + - "$IP_ADDRESSES TEXT)" - } - override fun onCreate(domainsDatabase: SQLiteDatabase) { // Create the domains table. domainsDatabase.execSQL(CREATE_DOMAINS_TABLE) } override fun onUpgrade(domainsDatabase: SQLiteDatabase, oldVersion: Int, newVersion: Int) { + // Get a handle for the shared preference. + val sharedPreferences = PreferenceManager.getDefaultSharedPreferences(appContext) + // Upgrade from schema version 1, first used in Privacy Browser 2.0, to schema version 2, first used in Privacy Browser 2.3. if (oldVersion < 2) { // Add the display images column. @@ -153,14 +153,11 @@ class DomainsDatabaseHelper(private val appContext: Context) : SQLiteOpenHelper( 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. - val sharedPreferences = PreferenceManager.getDefaultSharedPreferences(appContext) - - // Get the default block list settings. - val easyListEnabled = sharedPreferences.getBoolean("easylist", true) - val easyPrivacyEnabled = sharedPreferences.getBoolean("easyprivacy", true) - val fanboyAnnoyanceListEnabled = sharedPreferences.getBoolean("fanboys_annoyance_list", true) - val fanboySocialBlockingListEnabled = sharedPreferences.getBoolean("fanboys_social_blocking_list", true) + // Get the default filter list settings. + val easyListEnabled = sharedPreferences.getBoolean(appContext.getString(R.string.easylist_key), true) + val easyPrivacyEnabled = sharedPreferences.getBoolean(appContext.getString(R.string.easyprivacy_key), true) + val fanboyAnnoyanceListEnabled = sharedPreferences.getBoolean(appContext.getString(R.string.fanboys_annoyance_list_key), true) + val fanboySocialBlockingListEnabled = sharedPreferences.getBoolean(appContext.getString(R.string.fanboys_social_blocking_list_key), true) // Set EasyList for existing rows according to the current system-wide default. // This can switch to using the variables directly once the API >= 30. @@ -265,6 +262,82 @@ class DomainsDatabaseHelper(private val appContext: Context) : SQLiteOpenHelper( // SQLite amazingly only added a command to drop a column in version 3.35.0. // It will be a while before that is supported in Android. // Although a new table could be created and all the data copied to it, I think I will just leave the X-Requested-With column. It will be wiped out the next time an import is run. + + // Upgrade from schema version 15, first used in Privacy Browser 3.12, to schema version 16, first used in Privacy Browser 3.15. + if (oldVersion < 16) { + // Get the current switch default values. + val javaScriptDefaultValue = sharedPreferences.getBoolean(appContext.getString(R.string.javascript_key), false) + val cookiesDefaultValue = sharedPreferences.getBoolean(appContext.getString(R.string.cookies_key), false) + val domStorageDefaultValue = sharedPreferences.getBoolean(appContext.getString(R.string.dom_storage_key), false) + val formDataDefaultValue = sharedPreferences.getBoolean(appContext.getString(R.string.save_form_data_key), false) + val easyListDefaultValue = sharedPreferences.getBoolean(appContext.getString(R.string.easylist_key), true) + val easyPrivacyDefaultValue = sharedPreferences.getBoolean(appContext.getString(R.string.easyprivacy_key), true) + val fanboysAnnoyanceListDefaultValue = sharedPreferences.getBoolean(appContext.getString(R.string.fanboys_annoyance_list_key), true) + val fanboysSocialBlockingListDefaultValue = sharedPreferences.getBoolean(appContext.getString(R.string.fanboys_social_blocking_list), true) + val ultraListDefaultValue = sharedPreferences.getBoolean(appContext.getString(R.string.ultralist_key), true) + val ultraPrivacyDefaultValue = sharedPreferences.getBoolean(appContext.getString(R.string.ultraprivacy_key), true) + val blockAllThirdPartyRequestsDefaultValue = sharedPreferences.getBoolean(appContext.getString(R.string.block_all_third_party_requests_key), false) + + // Get a domains cursor. + val domainsCursor = domainsDatabase.rawQuery("SELECT * FROM $DOMAINS_TABLE", null) + + // Get the domains column indexes. + val javaScriptColumnIndex = domainsCursor.getColumnIndexOrThrow(ENABLE_JAVASCRIPT) + val cookiesColumnIndex = domainsCursor.getColumnIndexOrThrow(COOKIES) + val domStorageColumnIndex = domainsCursor.getColumnIndexOrThrow(ENABLE_DOM_STORAGE) + val formDataColumnIndex = domainsCursor.getColumnIndexOrThrow(ENABLE_FORM_DATA) + val easyListColumnIndex = domainsCursor.getColumnIndexOrThrow(ENABLE_EASYLIST) + val easyPrivacyColumnIndex = domainsCursor.getColumnIndexOrThrow(ENABLE_EASYPRIVACY) + val fanboysAnnoyanceListColumnIndex = domainsCursor.getColumnIndexOrThrow(ENABLE_FANBOYS_ANNOYANCE_LIST) + val fanboysSocialBlockingListColumnIndex = domainsCursor.getColumnIndexOrThrow(ENABLE_FANBOYS_SOCIAL_BLOCKING_LIST) + val ultraListColumnIndex = domainsCursor.getColumnIndexOrThrow(ULTRALIST) + val ultraPrivacyColumnIndex = domainsCursor.getColumnIndexOrThrow(ENABLE_ULTRAPRIVACY) + val blockAllThirdPartyRequestsColumnIndex = domainsCursor.getColumnIndexOrThrow(BLOCK_ALL_THIRD_PARTY_REQUESTS) + + // Convert the domain from the switch booleans to the spinner integers. + for (i in 0 until domainsCursor.count) { + // Move to the current record. + domainsCursor.moveToPosition(i) + + // Get the domain current values. + val javaScriptDomainCurrentValue = domainsCursor.getInt(javaScriptColumnIndex) + val cookiesDomainCurrentValue = domainsCursor.getInt(cookiesColumnIndex) + val domStorageDomainCurrentValue = domainsCursor.getInt(domStorageColumnIndex) + val formDataDomainCurrentValue = domainsCursor.getInt(formDataColumnIndex) + val easyListDomainCurrentValue = domainsCursor.getInt(easyListColumnIndex) + val easyPrivacyDomainCurrentValue = domainsCursor.getInt(easyPrivacyColumnIndex) + val fanboysAnnoyanceListCurrentValue = domainsCursor.getInt(fanboysAnnoyanceListColumnIndex) + val fanboysSocialBlockingListCurrentValue = domainsCursor.getInt(fanboysSocialBlockingListColumnIndex) + val ultraListCurrentValue = domainsCursor.getInt(ultraListColumnIndex) + val ultraPrivacyCurrentValue = domainsCursor.getInt(ultraPrivacyColumnIndex) + val blockAllThirdPartyRequestsCurrentValue = domainsCursor.getInt(blockAllThirdPartyRequestsColumnIndex) + + // Instantiate a domain content values. + val domainContentValues = ContentValues() + + // Populate the domain content values. + domainContentValues.put(ENABLE_JAVASCRIPT, convertFromSwitchToSpinner(javaScriptDefaultValue, javaScriptDomainCurrentValue)) + domainContentValues.put(COOKIES, convertFromSwitchToSpinner(cookiesDefaultValue, cookiesDomainCurrentValue)) + domainContentValues.put(ENABLE_DOM_STORAGE, convertFromSwitchToSpinner(domStorageDefaultValue, domStorageDomainCurrentValue)) + domainContentValues.put(ENABLE_FORM_DATA, convertFromSwitchToSpinner(formDataDefaultValue, formDataDomainCurrentValue)) + domainContentValues.put(ENABLE_EASYLIST, convertFromSwitchToSpinner(easyListDefaultValue, easyListDomainCurrentValue)) + domainContentValues.put(ENABLE_EASYPRIVACY, convertFromSwitchToSpinner(easyPrivacyDefaultValue, easyPrivacyDomainCurrentValue)) + domainContentValues.put(ENABLE_FANBOYS_ANNOYANCE_LIST, convertFromSwitchToSpinner(fanboysAnnoyanceListDefaultValue, fanboysAnnoyanceListCurrentValue)) + domainContentValues.put(ENABLE_FANBOYS_SOCIAL_BLOCKING_LIST, convertFromSwitchToSpinner(fanboysSocialBlockingListDefaultValue, fanboysSocialBlockingListCurrentValue)) + domainContentValues.put(ULTRALIST, convertFromSwitchToSpinner(ultraListDefaultValue, ultraListCurrentValue)) + domainContentValues.put(ENABLE_ULTRAPRIVACY, convertFromSwitchToSpinner(ultraPrivacyDefaultValue, ultraPrivacyCurrentValue)) + domainContentValues.put(BLOCK_ALL_THIRD_PARTY_REQUESTS, convertFromSwitchToSpinner(blockAllThirdPartyRequestsDefaultValue, blockAllThirdPartyRequestsCurrentValue)) + + // Get the current database ID. + val currentDatabaseId = domainsCursor.getInt(domainsCursor.getColumnIndexOrThrow(ID)) + + // Update the row for the specified database ID. + domainsDatabase.update(DOMAINS_TABLE, domainContentValues, "$ID = $currentDatabaseId", null) + } + + // Close the cursor. + domainsCursor.close() + } } val completeCursorOrderedByDomain: Cursor @@ -284,6 +357,18 @@ class DomainsDatabaseHelper(private val appContext: Context) : SQLiteOpenHelper( // Return the database id and the domain name in the domains table ordered by the domain name. The cursor can't be closed because it is needed in the calling activity. return domainsDatabase.rawQuery("SELECT $ID, $DOMAIN_NAME FROM $DOMAINS_TABLE ORDER BY $DOMAIN_NAME ASC", null) } + + // This method is used to convert the old domain settings switches to spinners. + private fun convertFromSwitchToSpinner(systemDefault: Boolean, currentDatabaseInteger: Int): Int { + // Return the new spinner integer. + return if ((!systemDefault && (currentDatabaseInteger == 0)) || + (systemDefault && (currentDatabaseInteger == 1))) // The system default is currently selected. + SYSTEM_DEFAULT + else if (currentDatabaseInteger == 0) // The switch is currently disabled and that is not the system default. + DISABLED + else // The switch is currently enabled and that is not the system default. + ENABLED + } fun getDomainNameCursorOrderedByDomainExcept(databaseId: Int): Cursor { // Get a readable database handle. @@ -376,9 +461,9 @@ class DomainsDatabaseHelper(private val appContext: Context) : SQLiteOpenHelper( domainsDatabase.close() } - fun updateDomain(databaseId: Int, domainName: String, javaScript: Boolean, cookies: Boolean, domStorage: Boolean, formData: Boolean, easyList: Boolean, easyPrivacy: Boolean, fanboysAnnoyance: Boolean, - fanboysSocialBlocking: Boolean, ultraList: Boolean, ultraPrivacy: Boolean, blockAllThirdPartyRequests: Boolean, userAgent: String, fontSize: Int, - swipeToRefresh: Int, webViewTheme: Int, wideViewport: Int, displayImages: Int, pinnedSslCertificate: Boolean, pinnedIpAddresses: Boolean) { + fun updateDomain(databaseId: Int, domainName: String, javaScript: Int, cookies: Int, domStorage: Int, formData: Int, easyList: Int, easyPrivacy: Int, fanboysAnnoyance: Int, fanboysSocialBlocking: Int, + ultraList: Int, ultraPrivacy: Int, blockAllThirdPartyRequests: Int, userAgent: String, fontSize: Int, swipeToRefresh: Int, webViewTheme: Int, wideViewport: Int, displayImages: Int, + pinnedSslCertificate: Boolean, pinnedIpAddresses: Boolean) { // Instantiate a content values. val domainContentValues = ContentValues() @@ -467,4 +552,4 @@ class DomainsDatabaseHelper(private val appContext: Context) : SQLiteOpenHelper( // Close the database handle. domainsDatabase.close() } -} \ No newline at end of file +} diff --git a/app/src/main/java/com/stoutner/privacybrowser/helpers/ImportExportDatabaseHelper.kt b/app/src/main/java/com/stoutner/privacybrowser/helpers/ImportExportDatabaseHelper.kt index d1648f01..55729ff2 100644 --- a/app/src/main/java/com/stoutner/privacybrowser/helpers/ImportExportDatabaseHelper.kt +++ b/app/src/main/java/com/stoutner/privacybrowser/helpers/ImportExportDatabaseHelper.kt @@ -34,11 +34,15 @@ import java.io.FileOutputStream import java.io.InputStream import java.io.OutputStream +// Define the public constants. +const val EXPORT_SUCCESSFUL = "A" +const val IMPORT_SUCCESSFUL = "B" +const val IMPORT_EXPORT_SCHEMA_VERSION = 17 + // Define the private class constants. private const val ALLOW_SCREENSHOTS = "allow_screenshots" private const val AMP_REDIRECTS = "amp_redirects" private const val APP_THEME = "app_theme" -private const val BLOCK_ALL_THIRD_PARTY_REQUESTS = "block_all_third_party_requests" private const val BOTTOM_APP_BAR = "bottom_app_bar" private const val CLEAR_CACHE = "clear_cache" private const val CLEAR_COOKIES = "clear_cookies" @@ -46,7 +50,6 @@ private const val CLEAR_DOM_STORAGE = "clear_dom_storage" private const val CLEAR_EVERYTHING = "clear_everything" private const val CLEAR_FORM_DATA = "clear_form_data" // Clear form data can be removed once the minimum API >= 26. private const val CLEAR_LOGCAT = "clear_logcat" -private const val COOKIES = "cookies" private const val CUSTOM_USER_AGENT = "custom_user_agent" private const val DISPLAY_ADDITIONAL_APP_BAR_ICONS = "display_additional_app_bar_icons" private const val DISPLAY_WEBPAGE_IMAGES = "display_webpage_images" @@ -56,38 +59,27 @@ private const val EASYLIST = "easylist" private const val EASYPRIVACY = "easyprivacy" private const val FANBOYS_ANNOYANCE_LIST = "fanboys_annoyance_list" private const val FANBOYS_SOCIAL_BLOCKING_LIST = "fanboys_social_blocking_list" -private const val FONT_SIZE = "font_size" private const val FULL_SCREEN_BROWSING_MODE = "full_screen_browsing_mode" private const val HIDE_APP_BAR = "hide_app_bar" private const val HOMEPAGE = "homepage" -private const val ID = "_id" private const val INCOGNITO_MODE = "incognito_mode" private const val JAVASCRIPT = "javascript" private const val OPEN_INTENTS_IN_NEW_TAB = "open_intents_in_new_tab" +private const val PREFERENCES_BLOCK_ALL_THIRD_PARTY_REQUESTS = "block_all_third_party_requests" +private const val PREFERENCES_FONT_SIZE = "font_size" private const val PREFERENCES_TABLE = "preferences" +private const val PREFERENCES_USER_AGENT = "user_agent" private const val PROXY = "proxy" private const val PROXY_CUSTOM_URL = "proxy_custom_url" private const val SAVE_FORM_DATA = "save_form_data" private const val SEARCH = "search" private const val SEARCH_CUSTOM_URL = "search_custom_url" private const val SCROLL_APP_BAR = "scroll_app_bar" -private const val SWIPE_TO_REFRESH = "swipe_to_refresh" +private const val PREFERENCES_SWIPE_TO_REFRESH = "swipe_to_refresh" private const val TRACKING_QUERIES = "tracking_queries" -private const val ULTRALIST = "ultralist" private const val ULTRAPRIVACY = "ultraprivacy" -private const val USER_AGENT = "user_agent" -private const val WEBVIEW_THEME = "webview_theme" -private const val WIDE_VIEWPORT = "wide_viewport" class ImportExportDatabaseHelper { - // Define the public companion object constants. These can be moved to public class constants once the entire project has migrated to Kotlin. - companion object { - // Define the public class constants. - const val EXPORT_SUCCESSFUL = "Export Successful" - const val IMPORT_SUCCESSFUL = "Import Successful" - const val SCHEMA_VERSION = 16 - } - fun importUnencrypted(importFileInputStream: InputStream, context: Context): String { return try { // Create a temporary import file. @@ -140,17 +132,17 @@ class ImportExportDatabaseHelper { // In the meantime, a new column must be created with the new name. There is no need to delete the old column on the temporary import database. // Create the new font size column. - importDatabase.execSQL("ALTER TABLE $PREFERENCES_TABLE ADD COLUMN $FONT_SIZE TEXT") + importDatabase.execSQL("ALTER TABLE $PREFERENCES_TABLE ADD COLUMN $PREFERENCES_FONT_SIZE TEXT") // Populate the preferences table with the current font size value. - importDatabase.execSQL("UPDATE $PREFERENCES_TABLE SET $FONT_SIZE = default_font_size") + importDatabase.execSQL("UPDATE $PREFERENCES_TABLE SET $PREFERENCES_FONT_SIZE = default_font_size") } // Upgrade from schema version 3, first used in Privacy Browser 2.15, to schema version 4, first used in Privacy Browser 2.16. if (importDatabaseVersion < 4) { // Add the Pinned IP Addresses columns to the domains table. - importDatabase.execSQL("ALTER TABLE ${DomainsDatabaseHelper.DOMAINS_TABLE} ADD COLUMN ${DomainsDatabaseHelper.PINNED_IP_ADDRESSES} BOOLEAN") - importDatabase.execSQL("ALTER TABLE ${DomainsDatabaseHelper.DOMAINS_TABLE} ADD COLUMN ${DomainsDatabaseHelper.IP_ADDRESSES} TEXT") + importDatabase.execSQL("ALTER TABLE $DOMAINS_TABLE ADD COLUMN $PINNED_IP_ADDRESSES BOOLEAN") + importDatabase.execSQL("ALTER TABLE $DOMAINS_TABLE ADD COLUMN $IP_ADDRESSES TEXT") } // Upgrade from schema version 4, first used in Privacy Browser 2.16, to schema version 5, first used in Privacy Browser 2.17. @@ -199,7 +191,7 @@ class ImportExportDatabaseHelper { // Previously this upgrade added `facebook_click_ids` to the Preferences table. But that is now removed in schema version 15. // Add the wide viewport column to the domains table. - importDatabase.execSQL("ALTER TABLE ${DomainsDatabaseHelper.DOMAINS_TABLE} ADD COLUMN ${DomainsDatabaseHelper.WIDE_VIEWPORT} INTEGER") + importDatabase.execSQL("ALTER TABLE $DOMAINS_TABLE ADD COLUMN $WIDE_VIEWPORT INTEGER") // Add the Google Analytics, Twitter AMP redirects, and wide viewport columns to the preferences table. importDatabase.execSQL("ALTER TABLE $PREFERENCES_TABLE ADD COLUMN google_analytics BOOLEAN") @@ -235,7 +227,7 @@ class ImportExportDatabaseHelper { // Upgrade from schema version 7, first used in Privacy Browser 3.1, to schema version 8, first used in Privacy Browser 3.2. if (importDatabaseVersion < 8) { // Add the UltraList column to the tables. - importDatabase.execSQL("ALTER TABLE ${DomainsDatabaseHelper.DOMAINS_TABLE} ADD COLUMN ${DomainsDatabaseHelper.ULTRALIST} BOOLEAN") + importDatabase.execSQL("ALTER TABLE $DOMAINS_TABLE ADD COLUMN $ULTRALIST INTEGER") importDatabase.execSQL("ALTER TABLE $PREFERENCES_TABLE ADD COLUMN $ULTRALIST BOOLEAN") // Get the current preference values. @@ -245,10 +237,10 @@ class ImportExportDatabaseHelper { // This can switch to using the variables directly once the API >= 30. // if (ultraList) { - importDatabase.execSQL("UPDATE ${DomainsDatabaseHelper.DOMAINS_TABLE} SET ${DomainsDatabaseHelper.ULTRALIST} = 1") + importDatabase.execSQL("UPDATE $DOMAINS_TABLE SET $ULTRALIST = 1") importDatabase.execSQL("UPDATE $PREFERENCES_TABLE SET $ULTRALIST = 1") } else { - importDatabase.execSQL("UPDATE ${DomainsDatabaseHelper.DOMAINS_TABLE} SET ${DomainsDatabaseHelper.ULTRALIST} = 0") + importDatabase.execSQL("UPDATE $DOMAINS_TABLE SET $ULTRALIST = 0") importDatabase.execSQL("UPDATE $PREFERENCES_TABLE SET $ULTRALIST = 0") } } @@ -310,7 +302,7 @@ class ImportExportDatabaseHelper { } // Add the WebView theme to the domains table. This defaults to 0, which is `System default`, so a separate step isn't needed to populate the database. - importDatabase.execSQL("ALTER TABLE ${DomainsDatabaseHelper.DOMAINS_TABLE} ADD COLUMN ${DomainsDatabaseHelper.WEBVIEW_THEME} INTEGER") + importDatabase.execSQL("ALTER TABLE $DOMAINS_TABLE ADD COLUMN $WEBVIEW_THEME INTEGER") // Add the WebView theme to the preferences table. importDatabase.execSQL("ALTER TABLE $PREFERENCES_TABLE ADD COLUMN $WEBVIEW_THEME TEXT") @@ -353,11 +345,11 @@ class ImportExportDatabaseHelper { // In the meantime, a new column must be created with the new name. There is no need to delete the old column on the temporary import database. // Create the new cookies columns. - importDatabase.execSQL("ALTER TABLE ${DomainsDatabaseHelper.DOMAINS_TABLE} ADD COLUMN ${DomainsDatabaseHelper.COOKIES} BOOLEAN") + importDatabase.execSQL("ALTER TABLE $DOMAINS_TABLE ADD COLUMN $COOKIES INTEGER") importDatabase.execSQL("ALTER TABLE $PREFERENCES_TABLE ADD COLUMN $COOKIES BOOLEAN") // Copy the data from the old cookies columns to the new ones. - importDatabase.execSQL("UPDATE ${DomainsDatabaseHelper.DOMAINS_TABLE} SET ${DomainsDatabaseHelper.COOKIES} = enablefirstpartycookies") + importDatabase.execSQL("UPDATE $DOMAINS_TABLE SET $COOKIES = enablefirstpartycookies") importDatabase.execSQL("UPDATE $PREFERENCES_TABLE SET $COOKIES = first_party_cookies") // Create the new download with external app and bottom app bar columns. @@ -435,16 +427,92 @@ class ImportExportDatabaseHelper { importBookmarksCursor.moveToNext() } + // Upgrade from schema version 16, first used in Privacy Browser 3.12, to schema version 17, first used in Privacy Browser 3.15. + if (importDatabaseVersion < 16) { + // Get the current switch default values. + val javaScriptDefaultValue = sharedPreferences.getBoolean(context.getString(R.string.javascript_key), false) + val cookiesDefaultValue = sharedPreferences.getBoolean(context.getString(R.string.cookies_key), false) + val domStorageDefaultValue = sharedPreferences.getBoolean(context.getString(R.string.dom_storage_key), false) + val formDataDefaultValue = sharedPreferences.getBoolean(context.getString(R.string.save_form_data_key), false) + val easyListDefaultValue = sharedPreferences.getBoolean(context.getString(R.string.easylist_key), true) + val easyPrivacyDefaultValue = sharedPreferences.getBoolean(context.getString(R.string.easyprivacy_key), true) + val fanboysAnnoyanceListDefaultValue = sharedPreferences.getBoolean(context.getString(R.string.fanboys_annoyance_list_key), true) + val fanboysSocialBlockingListDefaultValue = sharedPreferences.getBoolean(context.getString(R.string.fanboys_social_blocking_list), true) + val ultraListDefaultValue = sharedPreferences.getBoolean(context.getString(R.string.ultralist_key), true) + val ultraPrivacyDefaultValue = sharedPreferences.getBoolean(context.getString(R.string.ultraprivacy_key), true) + val blockAllThirdPartyRequestsDefaultValue = sharedPreferences.getBoolean(context.getString(R.string.block_all_third_party_requests_key), false) + + // Get a domains cursor. + val importDomainsConversionCursor = importDatabase.rawQuery("SELECT * FROM $DOMAINS_TABLE", null) + + // Get the domains column indexes. + val javaScriptColumnIndex = importDomainsConversionCursor.getColumnIndexOrThrow(ENABLE_JAVASCRIPT) + val cookiesColumnIndex = importDomainsConversionCursor.getColumnIndexOrThrow(COOKIES) + val domStorageColumnIndex = importDomainsConversionCursor.getColumnIndexOrThrow(ENABLE_DOM_STORAGE) + val formDataColumnIndex = importDomainsConversionCursor.getColumnIndexOrThrow(ENABLE_FORM_DATA) + val easyListColumnIndex = importDomainsConversionCursor.getColumnIndexOrThrow(ENABLE_EASYLIST) + val easyPrivacyColumnIndex = importDomainsConversionCursor.getColumnIndexOrThrow(ENABLE_EASYPRIVACY) + val fanboysAnnoyanceListColumnIndex = importDomainsConversionCursor.getColumnIndexOrThrow(ENABLE_FANBOYS_ANNOYANCE_LIST) + val fanboysSocialBlockingListColumnIndex = importDomainsConversionCursor.getColumnIndexOrThrow(ENABLE_FANBOYS_SOCIAL_BLOCKING_LIST) + val ultraListColumnIndex = importDomainsConversionCursor.getColumnIndexOrThrow(ULTRALIST) + val ultraPrivacyColumnIndex = importDomainsConversionCursor.getColumnIndexOrThrow(ENABLE_ULTRAPRIVACY) + val blockAllThirdPartyRequestsColumnIndex = importDomainsConversionCursor.getColumnIndexOrThrow(BLOCK_ALL_THIRD_PARTY_REQUESTS) + + // Convert the domain from the switch booleans to the spinner integers. + for (i in 0 until importDomainsConversionCursor.count) { + // Move to the current record. + importDomainsConversionCursor.moveToPosition(i) + + // Get the domain current values. + val javaScriptDomainCurrentValue = importDomainsConversionCursor.getInt(javaScriptColumnIndex) + val cookiesDomainCurrentValue = importDomainsConversionCursor.getInt(cookiesColumnIndex) + val domStorageDomainCurrentValue = importDomainsConversionCursor.getInt(domStorageColumnIndex) + val formDataDomainCurrentValue = importDomainsConversionCursor.getInt(formDataColumnIndex) + val easyListDomainCurrentValue = importDomainsConversionCursor.getInt(easyListColumnIndex) + val easyPrivacyDomainCurrentValue = importDomainsConversionCursor.getInt(easyPrivacyColumnIndex) + val fanboysAnnoyanceListCurrentValue = importDomainsConversionCursor.getInt(fanboysAnnoyanceListColumnIndex) + val fanboysSocialBlockingListCurrentValue = importDomainsConversionCursor.getInt(fanboysSocialBlockingListColumnIndex) + val ultraListCurrentValue = importDomainsConversionCursor.getInt(ultraListColumnIndex) + val ultraPrivacyCurrentValue = importDomainsConversionCursor.getInt(ultraPrivacyColumnIndex) + val blockAllThirdPartyRequestsCurrentValue = importDomainsConversionCursor.getInt(blockAllThirdPartyRequestsColumnIndex) + + // Instantiate a domain content values. + val domainContentValues = ContentValues() + + // Populate the domain content values. + domainContentValues.put(ENABLE_JAVASCRIPT, convertFromSwitchToSpinner(javaScriptDefaultValue, javaScriptDomainCurrentValue)) + domainContentValues.put(COOKIES, convertFromSwitchToSpinner(cookiesDefaultValue, cookiesDomainCurrentValue)) + domainContentValues.put(ENABLE_DOM_STORAGE, convertFromSwitchToSpinner(domStorageDefaultValue, domStorageDomainCurrentValue)) + domainContentValues.put(ENABLE_FORM_DATA, convertFromSwitchToSpinner(formDataDefaultValue, formDataDomainCurrentValue)) + domainContentValues.put(ENABLE_EASYLIST, convertFromSwitchToSpinner(easyListDefaultValue, easyListDomainCurrentValue)) + domainContentValues.put(ENABLE_EASYPRIVACY, convertFromSwitchToSpinner(easyPrivacyDefaultValue, easyPrivacyDomainCurrentValue)) + domainContentValues.put(ENABLE_FANBOYS_ANNOYANCE_LIST, convertFromSwitchToSpinner(fanboysAnnoyanceListDefaultValue, fanboysAnnoyanceListCurrentValue)) + domainContentValues.put(ENABLE_FANBOYS_SOCIAL_BLOCKING_LIST, convertFromSwitchToSpinner(fanboysSocialBlockingListDefaultValue, fanboysSocialBlockingListCurrentValue)) + domainContentValues.put(ULTRALIST, convertFromSwitchToSpinner(ultraListDefaultValue, ultraListCurrentValue)) + domainContentValues.put(ENABLE_ULTRAPRIVACY, convertFromSwitchToSpinner(ultraPrivacyDefaultValue, ultraPrivacyCurrentValue)) + domainContentValues.put(BLOCK_ALL_THIRD_PARTY_REQUESTS, convertFromSwitchToSpinner(blockAllThirdPartyRequestsDefaultValue, blockAllThirdPartyRequestsCurrentValue)) + + // Get the current database ID. + val currentDatabaseId = importDomainsConversionCursor.getInt(importDomainsConversionCursor.getColumnIndexOrThrow(ID)) + + // Update the row for the specified database ID. + importDatabase.update(DOMAINS_TABLE, domainContentValues, "$ID = $currentDatabaseId", null) + } + + // Close the cursor. + importDomainsConversionCursor.close() + } + // Close the bookmarks cursor and database. importBookmarksCursor.close() bookmarksDatabaseHelper.close() // Get a cursor for the domains table. - val importDomainsCursor = importDatabase.rawQuery("SELECT * FROM ${DomainsDatabaseHelper.DOMAINS_TABLE} ORDER BY ${DomainsDatabaseHelper.DOMAIN_NAME} ASC", null) + val importDomainsCursor = importDatabase.rawQuery("SELECT * FROM $DOMAINS_TABLE ORDER BY $DOMAIN_NAME ASC", null) // Delete the current domains database. - context.deleteDatabase(DomainsDatabaseHelper.DOMAINS_DATABASE) + context.deleteDatabase(DOMAINS_DATABASE) // Create a new domains database. val domainsDatabaseHelper = DomainsDatabaseHelper(context) @@ -458,44 +526,35 @@ class ImportExportDatabaseHelper { val domainContentValues = ContentValues() // Populate the domain content values. - domainContentValues.put(DomainsDatabaseHelper.DOMAIN_NAME, importDomainsCursor.getString(importDomainsCursor.getColumnIndexOrThrow(DomainsDatabaseHelper.DOMAIN_NAME))) - domainContentValues.put(DomainsDatabaseHelper.ENABLE_JAVASCRIPT, importDomainsCursor.getInt(importDomainsCursor.getColumnIndexOrThrow(DomainsDatabaseHelper.ENABLE_JAVASCRIPT))) - domainContentValues.put(DomainsDatabaseHelper.COOKIES, importDomainsCursor.getInt(importDomainsCursor.getColumnIndexOrThrow(DomainsDatabaseHelper.COOKIES))) - domainContentValues.put(DomainsDatabaseHelper.ENABLE_DOM_STORAGE, importDomainsCursor.getInt(importDomainsCursor.getColumnIndexOrThrow(DomainsDatabaseHelper.ENABLE_DOM_STORAGE))) - domainContentValues.put(DomainsDatabaseHelper.ENABLE_FORM_DATA, importDomainsCursor.getInt(importDomainsCursor.getColumnIndexOrThrow(DomainsDatabaseHelper.ENABLE_FORM_DATA))) - domainContentValues.put(DomainsDatabaseHelper.ENABLE_EASYLIST, importDomainsCursor.getInt(importDomainsCursor.getColumnIndexOrThrow(DomainsDatabaseHelper.ENABLE_EASYLIST))) - domainContentValues.put(DomainsDatabaseHelper.ENABLE_EASYPRIVACY, importDomainsCursor.getInt(importDomainsCursor.getColumnIndexOrThrow(DomainsDatabaseHelper.ENABLE_EASYPRIVACY))) - domainContentValues.put(DomainsDatabaseHelper.ENABLE_FANBOYS_ANNOYANCE_LIST, - importDomainsCursor.getInt(importDomainsCursor.getColumnIndexOrThrow(DomainsDatabaseHelper.ENABLE_FANBOYS_ANNOYANCE_LIST))) - domainContentValues.put(DomainsDatabaseHelper.ENABLE_FANBOYS_SOCIAL_BLOCKING_LIST, - importDomainsCursor.getInt(importDomainsCursor.getColumnIndexOrThrow(DomainsDatabaseHelper.ENABLE_FANBOYS_SOCIAL_BLOCKING_LIST))) - domainContentValues.put(DomainsDatabaseHelper.ULTRALIST, importDomainsCursor.getInt(importDomainsCursor.getColumnIndexOrThrow(DomainsDatabaseHelper.ULTRALIST))) - domainContentValues.put(DomainsDatabaseHelper.ENABLE_ULTRAPRIVACY, importDomainsCursor.getInt(importDomainsCursor.getColumnIndexOrThrow(DomainsDatabaseHelper.ENABLE_ULTRAPRIVACY))) - domainContentValues.put(DomainsDatabaseHelper.BLOCK_ALL_THIRD_PARTY_REQUESTS, - importDomainsCursor.getInt(importDomainsCursor.getColumnIndexOrThrow(DomainsDatabaseHelper.BLOCK_ALL_THIRD_PARTY_REQUESTS))) - domainContentValues.put(DomainsDatabaseHelper.USER_AGENT, importDomainsCursor.getString(importDomainsCursor.getColumnIndexOrThrow(DomainsDatabaseHelper.USER_AGENT))) - domainContentValues.put(DomainsDatabaseHelper.FONT_SIZE, importDomainsCursor.getInt(importDomainsCursor.getColumnIndexOrThrow(DomainsDatabaseHelper.FONT_SIZE))) - domainContentValues.put(DomainsDatabaseHelper.SWIPE_TO_REFRESH, importDomainsCursor.getInt(importDomainsCursor.getColumnIndexOrThrow(DomainsDatabaseHelper.SWIPE_TO_REFRESH))) - domainContentValues.put(DomainsDatabaseHelper.WEBVIEW_THEME, importDomainsCursor.getInt(importDomainsCursor.getColumnIndexOrThrow(DomainsDatabaseHelper.WEBVIEW_THEME))) - domainContentValues.put(DomainsDatabaseHelper.WIDE_VIEWPORT, importDomainsCursor.getInt(importDomainsCursor.getColumnIndexOrThrow(DomainsDatabaseHelper.WIDE_VIEWPORT))) - domainContentValues.put(DomainsDatabaseHelper.DISPLAY_IMAGES, importDomainsCursor.getInt(importDomainsCursor.getColumnIndexOrThrow(DomainsDatabaseHelper.DISPLAY_IMAGES))) - domainContentValues.put(DomainsDatabaseHelper.PINNED_SSL_CERTIFICATE, importDomainsCursor.getInt(importDomainsCursor.getColumnIndexOrThrow(DomainsDatabaseHelper.PINNED_SSL_CERTIFICATE))) - domainContentValues.put(DomainsDatabaseHelper.SSL_ISSUED_TO_COMMON_NAME, - importDomainsCursor.getString(importDomainsCursor.getColumnIndexOrThrow(DomainsDatabaseHelper.SSL_ISSUED_TO_COMMON_NAME))) - domainContentValues.put(DomainsDatabaseHelper.SSL_ISSUED_TO_ORGANIZATION, - importDomainsCursor.getString(importDomainsCursor.getColumnIndexOrThrow(DomainsDatabaseHelper.SSL_ISSUED_TO_ORGANIZATION))) - domainContentValues.put(DomainsDatabaseHelper.SSL_ISSUED_TO_ORGANIZATIONAL_UNIT, - importDomainsCursor.getString(importDomainsCursor.getColumnIndexOrThrow(DomainsDatabaseHelper.SSL_ISSUED_TO_ORGANIZATIONAL_UNIT))) - domainContentValues.put(DomainsDatabaseHelper.SSL_ISSUED_BY_COMMON_NAME, - importDomainsCursor.getString(importDomainsCursor.getColumnIndexOrThrow(DomainsDatabaseHelper.SSL_ISSUED_BY_COMMON_NAME))) - domainContentValues.put(DomainsDatabaseHelper.SSL_ISSUED_BY_ORGANIZATION, - importDomainsCursor.getString(importDomainsCursor.getColumnIndexOrThrow(DomainsDatabaseHelper.SSL_ISSUED_BY_ORGANIZATION))) - domainContentValues.put(DomainsDatabaseHelper.SSL_ISSUED_BY_ORGANIZATIONAL_UNIT, - importDomainsCursor.getString(importDomainsCursor.getColumnIndexOrThrow(DomainsDatabaseHelper.SSL_ISSUED_BY_ORGANIZATIONAL_UNIT))) - domainContentValues.put(DomainsDatabaseHelper.SSL_START_DATE, importDomainsCursor.getLong(importDomainsCursor.getColumnIndexOrThrow(DomainsDatabaseHelper.SSL_START_DATE))) - domainContentValues.put(DomainsDatabaseHelper.SSL_END_DATE, importDomainsCursor.getLong(importDomainsCursor.getColumnIndexOrThrow(DomainsDatabaseHelper.SSL_END_DATE))) - domainContentValues.put(DomainsDatabaseHelper.PINNED_IP_ADDRESSES, importDomainsCursor.getInt(importDomainsCursor.getColumnIndexOrThrow(DomainsDatabaseHelper.PINNED_IP_ADDRESSES))) - domainContentValues.put(DomainsDatabaseHelper.IP_ADDRESSES, importDomainsCursor.getString(importDomainsCursor.getColumnIndexOrThrow(DomainsDatabaseHelper.IP_ADDRESSES))) + domainContentValues.put(DOMAIN_NAME, importDomainsCursor.getString(importDomainsCursor.getColumnIndexOrThrow(DOMAIN_NAME))) + domainContentValues.put(ENABLE_JAVASCRIPT, importDomainsCursor.getInt(importDomainsCursor.getColumnIndexOrThrow(ENABLE_JAVASCRIPT))) + domainContentValues.put(COOKIES, importDomainsCursor.getInt(importDomainsCursor.getColumnIndexOrThrow(COOKIES))) + domainContentValues.put(ENABLE_DOM_STORAGE, importDomainsCursor.getInt(importDomainsCursor.getColumnIndexOrThrow(ENABLE_DOM_STORAGE))) + domainContentValues.put(ENABLE_FORM_DATA, importDomainsCursor.getInt(importDomainsCursor.getColumnIndexOrThrow(ENABLE_FORM_DATA))) + domainContentValues.put(ENABLE_EASYLIST, importDomainsCursor.getInt(importDomainsCursor.getColumnIndexOrThrow(ENABLE_EASYLIST))) + domainContentValues.put(ENABLE_EASYPRIVACY, importDomainsCursor.getInt(importDomainsCursor.getColumnIndexOrThrow(ENABLE_EASYPRIVACY))) + domainContentValues.put(ENABLE_FANBOYS_ANNOYANCE_LIST, importDomainsCursor.getInt(importDomainsCursor.getColumnIndexOrThrow(ENABLE_FANBOYS_ANNOYANCE_LIST))) + domainContentValues.put(ENABLE_FANBOYS_SOCIAL_BLOCKING_LIST, importDomainsCursor.getInt(importDomainsCursor.getColumnIndexOrThrow(ENABLE_FANBOYS_SOCIAL_BLOCKING_LIST))) + domainContentValues.put(ULTRALIST, importDomainsCursor.getInt(importDomainsCursor.getColumnIndexOrThrow(ULTRALIST))) + domainContentValues.put(ENABLE_ULTRAPRIVACY, importDomainsCursor.getInt(importDomainsCursor.getColumnIndexOrThrow(ENABLE_ULTRAPRIVACY))) + domainContentValues.put(BLOCK_ALL_THIRD_PARTY_REQUESTS, importDomainsCursor.getInt(importDomainsCursor.getColumnIndexOrThrow(BLOCK_ALL_THIRD_PARTY_REQUESTS))) + domainContentValues.put(USER_AGENT, importDomainsCursor.getString(importDomainsCursor.getColumnIndexOrThrow(USER_AGENT))) + domainContentValues.put(FONT_SIZE, importDomainsCursor.getInt(importDomainsCursor.getColumnIndexOrThrow(FONT_SIZE))) + domainContentValues.put(SWIPE_TO_REFRESH, importDomainsCursor.getInt(importDomainsCursor.getColumnIndexOrThrow(SWIPE_TO_REFRESH))) + domainContentValues.put(WEBVIEW_THEME, importDomainsCursor.getInt(importDomainsCursor.getColumnIndexOrThrow(WEBVIEW_THEME))) + domainContentValues.put(WIDE_VIEWPORT, importDomainsCursor.getInt(importDomainsCursor.getColumnIndexOrThrow(WIDE_VIEWPORT))) + domainContentValues.put(DISPLAY_IMAGES, importDomainsCursor.getInt(importDomainsCursor.getColumnIndexOrThrow(DISPLAY_IMAGES))) + domainContentValues.put(PINNED_SSL_CERTIFICATE, importDomainsCursor.getInt(importDomainsCursor.getColumnIndexOrThrow(PINNED_SSL_CERTIFICATE))) + domainContentValues.put(SSL_ISSUED_TO_COMMON_NAME, importDomainsCursor.getString(importDomainsCursor.getColumnIndexOrThrow(SSL_ISSUED_TO_COMMON_NAME))) + domainContentValues.put(SSL_ISSUED_TO_ORGANIZATION, importDomainsCursor.getString(importDomainsCursor.getColumnIndexOrThrow(SSL_ISSUED_TO_ORGANIZATION))) + domainContentValues.put(SSL_ISSUED_TO_ORGANIZATIONAL_UNIT, importDomainsCursor.getString(importDomainsCursor.getColumnIndexOrThrow(SSL_ISSUED_TO_ORGANIZATIONAL_UNIT))) + domainContentValues.put(SSL_ISSUED_BY_COMMON_NAME, importDomainsCursor.getString(importDomainsCursor.getColumnIndexOrThrow(SSL_ISSUED_BY_COMMON_NAME))) + domainContentValues.put(SSL_ISSUED_BY_ORGANIZATION, importDomainsCursor.getString(importDomainsCursor.getColumnIndexOrThrow(SSL_ISSUED_BY_ORGANIZATION))) + domainContentValues.put(SSL_ISSUED_BY_ORGANIZATIONAL_UNIT, importDomainsCursor.getString(importDomainsCursor.getColumnIndexOrThrow(SSL_ISSUED_BY_ORGANIZATIONAL_UNIT))) + domainContentValues.put(SSL_START_DATE, importDomainsCursor.getLong(importDomainsCursor.getColumnIndexOrThrow(SSL_START_DATE))) + domainContentValues.put(SSL_END_DATE, importDomainsCursor.getLong(importDomainsCursor.getColumnIndexOrThrow(SSL_END_DATE))) + domainContentValues.put(PINNED_IP_ADDRESSES, importDomainsCursor.getInt(importDomainsCursor.getColumnIndexOrThrow(PINNED_IP_ADDRESSES))) + domainContentValues.put(IP_ADDRESSES, importDomainsCursor.getString(importDomainsCursor.getColumnIndexOrThrow(IP_ADDRESSES))) // Insert the content values into the domains database. domainsDatabaseHelper.addDomain(domainContentValues) @@ -521,7 +580,7 @@ class ImportExportDatabaseHelper { .putBoolean(COOKIES, importPreferencesCursor.getInt(importPreferencesCursor.getColumnIndexOrThrow(COOKIES)) == 1) .putBoolean(DOM_STORAGE, importPreferencesCursor.getInt(importPreferencesCursor.getColumnIndexOrThrow(DOM_STORAGE)) == 1) .putBoolean(SAVE_FORM_DATA, importPreferencesCursor.getInt(importPreferencesCursor.getColumnIndexOrThrow(SAVE_FORM_DATA)) == 1) // Save form data can be removed once the minimum API >= 26. - .putString(USER_AGENT, importPreferencesCursor.getString(importPreferencesCursor.getColumnIndexOrThrow(USER_AGENT))) + .putString(PREFERENCES_USER_AGENT, importPreferencesCursor.getString(importPreferencesCursor.getColumnIndexOrThrow(PREFERENCES_USER_AGENT))) .putString(CUSTOM_USER_AGENT, importPreferencesCursor.getString(importPreferencesCursor.getColumnIndexOrThrow(CUSTOM_USER_AGENT))) .putBoolean(INCOGNITO_MODE, importPreferencesCursor.getInt(importPreferencesCursor.getColumnIndexOrThrow(INCOGNITO_MODE)) == 1) .putBoolean(ALLOW_SCREENSHOTS, importPreferencesCursor.getInt(importPreferencesCursor.getColumnIndexOrThrow(ALLOW_SCREENSHOTS)) == 1) @@ -531,7 +590,7 @@ class ImportExportDatabaseHelper { .putBoolean(FANBOYS_SOCIAL_BLOCKING_LIST, importPreferencesCursor.getInt(importPreferencesCursor.getColumnIndexOrThrow(FANBOYS_SOCIAL_BLOCKING_LIST)) == 1) .putBoolean(ULTRALIST, importPreferencesCursor.getInt(importPreferencesCursor.getColumnIndexOrThrow(ULTRALIST)) == 1) .putBoolean(ULTRAPRIVACY, importPreferencesCursor.getInt(importPreferencesCursor.getColumnIndexOrThrow(ULTRAPRIVACY)) == 1) - .putBoolean(BLOCK_ALL_THIRD_PARTY_REQUESTS, importPreferencesCursor.getInt(importPreferencesCursor.getColumnIndexOrThrow(BLOCK_ALL_THIRD_PARTY_REQUESTS)) == 1) + .putBoolean(PREFERENCES_BLOCK_ALL_THIRD_PARTY_REQUESTS, importPreferencesCursor.getInt(importPreferencesCursor.getColumnIndexOrThrow(PREFERENCES_BLOCK_ALL_THIRD_PARTY_REQUESTS)) == 1) .putBoolean(TRACKING_QUERIES, importPreferencesCursor.getInt(importPreferencesCursor.getColumnIndexOrThrow(TRACKING_QUERIES)) == 1) .putBoolean(AMP_REDIRECTS, importPreferencesCursor.getInt(importPreferencesCursor.getColumnIndexOrThrow(AMP_REDIRECTS)) == 1) .putString(SEARCH, importPreferencesCursor.getString(importPreferencesCursor.getColumnIndexOrThrow(SEARCH))) @@ -547,9 +606,9 @@ class ImportExportDatabaseHelper { .putBoolean(CLEAR_LOGCAT, importPreferencesCursor.getInt(importPreferencesCursor.getColumnIndexOrThrow(CLEAR_LOGCAT)) == 1) .putBoolean(CLEAR_CACHE, importPreferencesCursor.getInt(importPreferencesCursor.getColumnIndexOrThrow(CLEAR_CACHE)) == 1) .putString(HOMEPAGE, importPreferencesCursor.getString(importPreferencesCursor.getColumnIndexOrThrow(HOMEPAGE))) - .putString(FONT_SIZE, importPreferencesCursor.getString(importPreferencesCursor.getColumnIndexOrThrow(FONT_SIZE))) + .putString(PREFERENCES_FONT_SIZE, importPreferencesCursor.getString(importPreferencesCursor.getColumnIndexOrThrow(PREFERENCES_FONT_SIZE))) .putBoolean(OPEN_INTENTS_IN_NEW_TAB, importPreferencesCursor.getInt(importPreferencesCursor.getColumnIndexOrThrow(OPEN_INTENTS_IN_NEW_TAB)) == 1) - .putBoolean(SWIPE_TO_REFRESH, importPreferencesCursor.getInt(importPreferencesCursor.getColumnIndexOrThrow(SWIPE_TO_REFRESH)) == 1) + .putBoolean(PREFERENCES_SWIPE_TO_REFRESH, importPreferencesCursor.getInt(importPreferencesCursor.getColumnIndexOrThrow(PREFERENCES_SWIPE_TO_REFRESH)) == 1) .putBoolean(DOWNLOAD_WITH_EXTERNAL_APP, importPreferencesCursor.getInt(importPreferencesCursor.getColumnIndexOrThrow(DOWNLOAD_WITH_EXTERNAL_APP)) == 1) .putBoolean(SCROLL_APP_BAR, importPreferencesCursor.getInt(importPreferencesCursor.getColumnIndexOrThrow(SCROLL_APP_BAR)) == 1) .putBoolean(BOTTOM_APP_BAR, importPreferencesCursor.getInt(importPreferencesCursor.getColumnIndexOrThrow(BOTTOM_APP_BAR)) == 1) @@ -584,7 +643,7 @@ class ImportExportDatabaseHelper { val temporaryExportDatabase = SQLiteDatabase.openOrCreateDatabase(temporaryExportFile, null) // Set the temporary export database version number. - temporaryExportDatabase.version = SCHEMA_VERSION + temporaryExportDatabase.version = IMPORT_EXPORT_SCHEMA_VERSION // Create the temporary export database bookmarks table. @@ -625,7 +684,7 @@ class ImportExportDatabaseHelper { // Create the temporary export database domains table. - temporaryExportDatabase.execSQL(DomainsDatabaseHelper.CREATE_DOMAINS_TABLE) + temporaryExportDatabase.execSQL(CREATE_DOMAINS_TABLE) // Open the domains database. val domainsDatabaseHelper = DomainsDatabaseHelper(context) @@ -642,41 +701,38 @@ class ImportExportDatabaseHelper { val domainContentValues = ContentValues() // Populate the domain content values. - domainContentValues.put(DomainsDatabaseHelper.DOMAIN_NAME, domainsCursor.getString(domainsCursor.getColumnIndexOrThrow(DomainsDatabaseHelper.DOMAIN_NAME))) - domainContentValues.put(DomainsDatabaseHelper.ENABLE_JAVASCRIPT, domainsCursor.getInt(domainsCursor.getColumnIndexOrThrow(DomainsDatabaseHelper.ENABLE_JAVASCRIPT))) - domainContentValues.put(DomainsDatabaseHelper.COOKIES, domainsCursor.getInt(domainsCursor.getColumnIndexOrThrow(DomainsDatabaseHelper.COOKIES))) - domainContentValues.put(DomainsDatabaseHelper.ENABLE_DOM_STORAGE, domainsCursor.getInt(domainsCursor.getColumnIndexOrThrow(DomainsDatabaseHelper.ENABLE_DOM_STORAGE))) - domainContentValues.put(DomainsDatabaseHelper.ENABLE_FORM_DATA, domainsCursor.getInt(domainsCursor.getColumnIndexOrThrow(DomainsDatabaseHelper.ENABLE_FORM_DATA))) - domainContentValues.put(DomainsDatabaseHelper.ENABLE_EASYLIST, domainsCursor.getInt(domainsCursor.getColumnIndexOrThrow(DomainsDatabaseHelper.ENABLE_EASYLIST))) - domainContentValues.put(DomainsDatabaseHelper.ENABLE_EASYPRIVACY, domainsCursor.getInt(domainsCursor.getColumnIndexOrThrow(DomainsDatabaseHelper.ENABLE_EASYPRIVACY))) - domainContentValues.put(DomainsDatabaseHelper.ENABLE_FANBOYS_ANNOYANCE_LIST, domainsCursor.getInt(domainsCursor.getColumnIndexOrThrow(DomainsDatabaseHelper.ENABLE_FANBOYS_ANNOYANCE_LIST))) - domainContentValues.put(DomainsDatabaseHelper.ENABLE_FANBOYS_SOCIAL_BLOCKING_LIST, - domainsCursor.getInt(domainsCursor.getColumnIndexOrThrow(DomainsDatabaseHelper.ENABLE_FANBOYS_SOCIAL_BLOCKING_LIST))) - domainContentValues.put(DomainsDatabaseHelper.ULTRALIST, domainsCursor.getInt(domainsCursor.getColumnIndexOrThrow(DomainsDatabaseHelper.ULTRALIST))) - domainContentValues.put(DomainsDatabaseHelper.ENABLE_ULTRAPRIVACY, domainsCursor.getInt(domainsCursor.getColumnIndexOrThrow(DomainsDatabaseHelper.ENABLE_ULTRAPRIVACY))) - domainContentValues.put(DomainsDatabaseHelper.BLOCK_ALL_THIRD_PARTY_REQUESTS, domainsCursor.getInt(domainsCursor.getColumnIndexOrThrow(DomainsDatabaseHelper.BLOCK_ALL_THIRD_PARTY_REQUESTS))) - domainContentValues.put(DomainsDatabaseHelper.USER_AGENT, domainsCursor.getString(domainsCursor.getColumnIndexOrThrow(DomainsDatabaseHelper.USER_AGENT))) - domainContentValues.put(DomainsDatabaseHelper.FONT_SIZE, domainsCursor.getInt(domainsCursor.getColumnIndexOrThrow(DomainsDatabaseHelper.FONT_SIZE))) - domainContentValues.put(DomainsDatabaseHelper.SWIPE_TO_REFRESH, domainsCursor.getInt(domainsCursor.getColumnIndexOrThrow(DomainsDatabaseHelper.SWIPE_TO_REFRESH))) - domainContentValues.put(DomainsDatabaseHelper.WEBVIEW_THEME, domainsCursor.getInt(domainsCursor.getColumnIndexOrThrow(DomainsDatabaseHelper.WEBVIEW_THEME))) - domainContentValues.put(DomainsDatabaseHelper.WIDE_VIEWPORT, domainsCursor.getInt(domainsCursor.getColumnIndexOrThrow(DomainsDatabaseHelper.WIDE_VIEWPORT))) - domainContentValues.put(DomainsDatabaseHelper.DISPLAY_IMAGES, domainsCursor.getInt(domainsCursor.getColumnIndexOrThrow(DomainsDatabaseHelper.DISPLAY_IMAGES))) - domainContentValues.put(DomainsDatabaseHelper.PINNED_SSL_CERTIFICATE, domainsCursor.getInt(domainsCursor.getColumnIndexOrThrow(DomainsDatabaseHelper.PINNED_SSL_CERTIFICATE))) - domainContentValues.put(DomainsDatabaseHelper.SSL_ISSUED_TO_COMMON_NAME, domainsCursor.getString(domainsCursor.getColumnIndexOrThrow(DomainsDatabaseHelper.SSL_ISSUED_TO_COMMON_NAME))) - domainContentValues.put(DomainsDatabaseHelper.SSL_ISSUED_TO_ORGANIZATION, domainsCursor.getString(domainsCursor.getColumnIndexOrThrow(DomainsDatabaseHelper.SSL_ISSUED_TO_ORGANIZATION))) - domainContentValues.put(DomainsDatabaseHelper.SSL_ISSUED_TO_ORGANIZATIONAL_UNIT, - domainsCursor.getString(domainsCursor.getColumnIndexOrThrow(DomainsDatabaseHelper.SSL_ISSUED_TO_ORGANIZATIONAL_UNIT))) - domainContentValues.put(DomainsDatabaseHelper.SSL_ISSUED_BY_COMMON_NAME, domainsCursor.getString(domainsCursor.getColumnIndexOrThrow(DomainsDatabaseHelper.SSL_ISSUED_BY_COMMON_NAME))) - domainContentValues.put(DomainsDatabaseHelper.SSL_ISSUED_BY_ORGANIZATION, domainsCursor.getString(domainsCursor.getColumnIndexOrThrow(DomainsDatabaseHelper.SSL_ISSUED_BY_ORGANIZATION))) - domainContentValues.put(DomainsDatabaseHelper.SSL_ISSUED_BY_ORGANIZATIONAL_UNIT, - domainsCursor.getString(domainsCursor.getColumnIndexOrThrow(DomainsDatabaseHelper.SSL_ISSUED_BY_ORGANIZATIONAL_UNIT))) - domainContentValues.put(DomainsDatabaseHelper.SSL_START_DATE, domainsCursor.getLong(domainsCursor.getColumnIndexOrThrow(DomainsDatabaseHelper.SSL_START_DATE))) - domainContentValues.put(DomainsDatabaseHelper.SSL_END_DATE, domainsCursor.getLong(domainsCursor.getColumnIndexOrThrow(DomainsDatabaseHelper.SSL_END_DATE))) - domainContentValues.put(DomainsDatabaseHelper.PINNED_IP_ADDRESSES, domainsCursor.getInt(domainsCursor.getColumnIndexOrThrow(DomainsDatabaseHelper.PINNED_IP_ADDRESSES))) - domainContentValues.put(DomainsDatabaseHelper.IP_ADDRESSES, domainsCursor.getString(domainsCursor.getColumnIndexOrThrow(DomainsDatabaseHelper.IP_ADDRESSES))) + domainContentValues.put(DOMAIN_NAME, domainsCursor.getString(domainsCursor.getColumnIndexOrThrow(DOMAIN_NAME))) + domainContentValues.put(ENABLE_JAVASCRIPT, domainsCursor.getInt(domainsCursor.getColumnIndexOrThrow(ENABLE_JAVASCRIPT))) + domainContentValues.put(COOKIES, domainsCursor.getInt(domainsCursor.getColumnIndexOrThrow(COOKIES))) + domainContentValues.put(ENABLE_DOM_STORAGE, domainsCursor.getInt(domainsCursor.getColumnIndexOrThrow(ENABLE_DOM_STORAGE))) + domainContentValues.put(ENABLE_FORM_DATA, domainsCursor.getInt(domainsCursor.getColumnIndexOrThrow(ENABLE_FORM_DATA))) + domainContentValues.put(ENABLE_EASYLIST, domainsCursor.getInt(domainsCursor.getColumnIndexOrThrow(ENABLE_EASYLIST))) + domainContentValues.put(ENABLE_EASYPRIVACY, domainsCursor.getInt(domainsCursor.getColumnIndexOrThrow(ENABLE_EASYPRIVACY))) + domainContentValues.put(ENABLE_FANBOYS_ANNOYANCE_LIST, domainsCursor.getInt(domainsCursor.getColumnIndexOrThrow(ENABLE_FANBOYS_ANNOYANCE_LIST))) + domainContentValues.put(ENABLE_FANBOYS_SOCIAL_BLOCKING_LIST, domainsCursor.getInt(domainsCursor.getColumnIndexOrThrow(ENABLE_FANBOYS_SOCIAL_BLOCKING_LIST))) + domainContentValues.put(ULTRALIST, domainsCursor.getInt(domainsCursor.getColumnIndexOrThrow(ULTRALIST))) + domainContentValues.put(ENABLE_ULTRAPRIVACY, domainsCursor.getInt(domainsCursor.getColumnIndexOrThrow(ENABLE_ULTRAPRIVACY))) + domainContentValues.put(BLOCK_ALL_THIRD_PARTY_REQUESTS, domainsCursor.getInt(domainsCursor.getColumnIndexOrThrow(BLOCK_ALL_THIRD_PARTY_REQUESTS))) + domainContentValues.put(USER_AGENT, domainsCursor.getString(domainsCursor.getColumnIndexOrThrow(USER_AGENT))) + domainContentValues.put(FONT_SIZE, domainsCursor.getInt(domainsCursor.getColumnIndexOrThrow(FONT_SIZE))) + domainContentValues.put(SWIPE_TO_REFRESH, domainsCursor.getInt(domainsCursor.getColumnIndexOrThrow(SWIPE_TO_REFRESH))) + domainContentValues.put(WEBVIEW_THEME, domainsCursor.getInt(domainsCursor.getColumnIndexOrThrow(WEBVIEW_THEME))) + domainContentValues.put(WIDE_VIEWPORT, domainsCursor.getInt(domainsCursor.getColumnIndexOrThrow(WIDE_VIEWPORT))) + domainContentValues.put(DISPLAY_IMAGES, domainsCursor.getInt(domainsCursor.getColumnIndexOrThrow(DISPLAY_IMAGES))) + domainContentValues.put(PINNED_SSL_CERTIFICATE, domainsCursor.getInt(domainsCursor.getColumnIndexOrThrow(PINNED_SSL_CERTIFICATE))) + domainContentValues.put(SSL_ISSUED_TO_COMMON_NAME, domainsCursor.getString(domainsCursor.getColumnIndexOrThrow(SSL_ISSUED_TO_COMMON_NAME))) + domainContentValues.put(SSL_ISSUED_TO_ORGANIZATION, domainsCursor.getString(domainsCursor.getColumnIndexOrThrow(SSL_ISSUED_TO_ORGANIZATION))) + domainContentValues.put(SSL_ISSUED_TO_ORGANIZATIONAL_UNIT, domainsCursor.getString(domainsCursor.getColumnIndexOrThrow(SSL_ISSUED_TO_ORGANIZATIONAL_UNIT))) + domainContentValues.put(SSL_ISSUED_BY_COMMON_NAME, domainsCursor.getString(domainsCursor.getColumnIndexOrThrow(SSL_ISSUED_BY_COMMON_NAME))) + domainContentValues.put(SSL_ISSUED_BY_ORGANIZATION, domainsCursor.getString(domainsCursor.getColumnIndexOrThrow(SSL_ISSUED_BY_ORGANIZATION))) + domainContentValues.put(SSL_ISSUED_BY_ORGANIZATIONAL_UNIT, domainsCursor.getString(domainsCursor.getColumnIndexOrThrow(SSL_ISSUED_BY_ORGANIZATIONAL_UNIT))) + domainContentValues.put(SSL_START_DATE, domainsCursor.getLong(domainsCursor.getColumnIndexOrThrow(SSL_START_DATE))) + domainContentValues.put(SSL_END_DATE, domainsCursor.getLong(domainsCursor.getColumnIndexOrThrow(SSL_END_DATE))) + domainContentValues.put(PINNED_IP_ADDRESSES, domainsCursor.getInt(domainsCursor.getColumnIndexOrThrow(PINNED_IP_ADDRESSES))) + domainContentValues.put(IP_ADDRESSES, domainsCursor.getString(domainsCursor.getColumnIndexOrThrow(IP_ADDRESSES))) // Insert the content values into the temporary export database. - temporaryExportDatabase.insert(DomainsDatabaseHelper.DOMAINS_TABLE, null, domainContentValues) + temporaryExportDatabase.insert(DOMAINS_TABLE, null, domainContentValues) // Advance to the next record. domainsCursor.moveToNext() @@ -694,7 +750,7 @@ class ImportExportDatabaseHelper { "$COOKIES BOOLEAN, " + "$DOM_STORAGE BOOLEAN, " + "$SAVE_FORM_DATA BOOLEAN, " + - "$USER_AGENT TEXT, " + + "$PREFERENCES_USER_AGENT TEXT, " + "$CUSTOM_USER_AGENT TEXT, " + "$INCOGNITO_MODE BOOLEAN, " + "$ALLOW_SCREENSHOTS BOOLEAN, " + @@ -704,7 +760,7 @@ class ImportExportDatabaseHelper { "$FANBOYS_SOCIAL_BLOCKING_LIST BOOLEAN, " + "$ULTRALIST BOOLEAN, " + "$ULTRAPRIVACY BOOLEAN, " + - "$BLOCK_ALL_THIRD_PARTY_REQUESTS BOOLEAN, " + + "$PREFERENCES_BLOCK_ALL_THIRD_PARTY_REQUESTS BOOLEAN, " + "$TRACKING_QUERIES BOOLEAN, " + "$AMP_REDIRECTS BOOLEAN, " + "$SEARCH TEXT, " + @@ -720,9 +776,9 @@ class ImportExportDatabaseHelper { "$CLEAR_LOGCAT BOOLEAN, " + "$CLEAR_CACHE BOOLEAN, " + "$HOMEPAGE TEXT, " + - "$FONT_SIZE TEXT, " + + "$PREFERENCES_FONT_SIZE TEXT, " + "$OPEN_INTENTS_IN_NEW_TAB BOOLEAN, " + - "$SWIPE_TO_REFRESH BOOLEAN, " + + "$PREFERENCES_SWIPE_TO_REFRESH BOOLEAN, " + "$DOWNLOAD_WITH_EXTERNAL_APP BOOLEAN, " + "$SCROLL_APP_BAR BOOLEAN, " + "$BOTTOM_APP_BAR BOOLEAN, " + @@ -746,7 +802,7 @@ class ImportExportDatabaseHelper { preferencesContentValues.put(COOKIES, sharedPreferences.getBoolean(COOKIES, false)) preferencesContentValues.put(DOM_STORAGE, sharedPreferences.getBoolean(DOM_STORAGE, false)) preferencesContentValues.put(SAVE_FORM_DATA, sharedPreferences.getBoolean(SAVE_FORM_DATA, false)) // Save form data can be removed once the minimum API >= 26. - preferencesContentValues.put(USER_AGENT, sharedPreferences.getString(USER_AGENT, context.getString(R.string.user_agent_default_value))) + preferencesContentValues.put(PREFERENCES_USER_AGENT, sharedPreferences.getString(PREFERENCES_USER_AGENT, context.getString(R.string.user_agent_default_value))) preferencesContentValues.put(CUSTOM_USER_AGENT, sharedPreferences.getString(CUSTOM_USER_AGENT, context.getString(R.string.custom_user_agent_default_value))) preferencesContentValues.put(INCOGNITO_MODE, sharedPreferences.getBoolean(INCOGNITO_MODE, false)) preferencesContentValues.put(ALLOW_SCREENSHOTS, sharedPreferences.getBoolean(ALLOW_SCREENSHOTS, false)) @@ -756,7 +812,7 @@ class ImportExportDatabaseHelper { preferencesContentValues.put(FANBOYS_SOCIAL_BLOCKING_LIST, sharedPreferences.getBoolean(FANBOYS_SOCIAL_BLOCKING_LIST, true)) preferencesContentValues.put(ULTRALIST, sharedPreferences.getBoolean(ULTRALIST, true)) preferencesContentValues.put(ULTRAPRIVACY, sharedPreferences.getBoolean(ULTRAPRIVACY, true)) - preferencesContentValues.put(BLOCK_ALL_THIRD_PARTY_REQUESTS, sharedPreferences.getBoolean(BLOCK_ALL_THIRD_PARTY_REQUESTS, false)) + preferencesContentValues.put(PREFERENCES_BLOCK_ALL_THIRD_PARTY_REQUESTS, sharedPreferences.getBoolean(PREFERENCES_BLOCK_ALL_THIRD_PARTY_REQUESTS, false)) preferencesContentValues.put(TRACKING_QUERIES, sharedPreferences.getBoolean(TRACKING_QUERIES, true)) preferencesContentValues.put(AMP_REDIRECTS, sharedPreferences.getBoolean(AMP_REDIRECTS, true)) preferencesContentValues.put(SEARCH, sharedPreferences.getString(SEARCH, context.getString(R.string.search_default_value))) @@ -772,9 +828,9 @@ class ImportExportDatabaseHelper { preferencesContentValues.put(CLEAR_LOGCAT, sharedPreferences.getBoolean(CLEAR_LOGCAT, true)) preferencesContentValues.put(CLEAR_CACHE, sharedPreferences.getBoolean(CLEAR_CACHE, true)) preferencesContentValues.put(HOMEPAGE, sharedPreferences.getString(HOMEPAGE, context.getString(R.string.homepage_default_value))) - preferencesContentValues.put(FONT_SIZE, sharedPreferences.getString(FONT_SIZE, context.getString(R.string.font_size_default_value))) + preferencesContentValues.put(PREFERENCES_FONT_SIZE, sharedPreferences.getString(PREFERENCES_FONT_SIZE, context.getString(R.string.font_size_default_value))) preferencesContentValues.put(OPEN_INTENTS_IN_NEW_TAB, sharedPreferences.getBoolean(OPEN_INTENTS_IN_NEW_TAB, true)) - preferencesContentValues.put(SWIPE_TO_REFRESH, sharedPreferences.getBoolean(SWIPE_TO_REFRESH, true)) + preferencesContentValues.put(PREFERENCES_SWIPE_TO_REFRESH, sharedPreferences.getBoolean(PREFERENCES_SWIPE_TO_REFRESH, true)) preferencesContentValues.put(DOWNLOAD_WITH_EXTERNAL_APP, sharedPreferences.getBoolean(DOWNLOAD_WITH_EXTERNAL_APP, false)) preferencesContentValues.put(SCROLL_APP_BAR, sharedPreferences.getBoolean(SCROLL_APP_BAR, true)) preferencesContentValues.put(BOTTOM_APP_BAR, sharedPreferences.getBoolean(BOTTOM_APP_BAR, false)) @@ -827,4 +883,16 @@ class ImportExportDatabaseHelper { exception.toString() } } + + // This method is used to convert the old domain settings switches to spinners. + private fun convertFromSwitchToSpinner(systemDefault: Boolean, currentDatabaseInteger: Int): Int { + // Return the new spinner integer. + return if ((!systemDefault && (currentDatabaseInteger == 0)) || + (systemDefault && (currentDatabaseInteger == 1))) // The system default is currently selected. + SYSTEM_DEFAULT + else if (currentDatabaseInteger == 0) // The switch is currently disabled and that is not the system default. + DISABLED + else // The switch is currently enabled and that is not the system default. + ENABLED + } } diff --git a/app/src/main/res/layout/domain_settings_fragment.xml b/app/src/main/res/layout/domain_settings_fragment.xml index aaa5ecfd..a5190478 100644 --- a/app/src/main/res/layout/domain_settings_fragment.xml +++ b/app/src/main/res/layout/domain_settings_fragment.xml @@ -85,341 +85,484 @@ + android:orientation="vertical" + android:padding="12dp" > + + - - - + + + + + + + + android:layout_marginStart="45dp" + android:layout_marginEnd="36dp" + android:textSize="13sp" /> + android:orientation="vertical" + android:padding="12dp" > - - - + + + android:text="@string/cookies" > + + + + + + + + android:orientation="vertical" + android:padding="12dp" > - - - + + + android:text="@string/dom_storage" > + + + + + + + - + + android:orientation="vertical" + android:padding="12dp" > - - - + + + android:orientation="horizontal" > + + + + + + + + android:orientation="vertical" + android:padding="12dp" > - + + - - + + + + + + + + android:layout_marginStart="45dp" + android:layout_marginEnd="36dp" + android:textSize="13sp" /> + android:orientation="vertical" + android:padding="12dp" > - - - + + + android:orientation="horizontal" > + + + + + + + + android:orientation="vertical" + android:padding="12dp" > - - - + + + android:orientation="horizontal" > + + + + + + + + android:orientation="vertical" + android:padding="12dp" > - - - + + + android:orientation="horizontal" > + + + + + + + + android:orientation="vertical" + android:padding="12dp" > - - - + + + + + + + + + + android:layout_marginStart="45dp" + android:layout_marginEnd="36dp" + android:textSize="13sp" /> + android:orientation="vertical" + android:padding="12dp" > + + - - - + + + + + + + + android:layout_marginStart="45dp" + android:layout_marginEnd="36dp" + android:textSize="13sp" /> + android:orientation="vertical" + android:padding="12dp" > - - - + + + android:orientation="horizontal" > + + + + + + + @@ -539,7 +682,8 @@ + android:text="@string/swipe_to_refresh" + tools:ignore="TooManyViews" /> + android:layout_marginEnd="12dp" > Domain name Domain deleted *. may be prepended to a domain to include all subdomains (eg. *.stoutner.com) + + System default + JavaScript enabled + JavaScript disabled + + + System default + Cookies enabled + Cookies disabled + + + System default + DOM storage enabled + DOM storage disabled + + + System default + Form data enabled + Form data disabled + + + System default + EasyList enabled + EasyList disabled + + + System default + EasyPrivacy enabled + EasyPrivacy disabled + + + System default + Fanboy’s Annoyance List enabled + Fanboy’s Annoyance List disabled + + + System default + Fanboy’s Social Blocking List enabled + Fanboy’s Social Blocking List disabled + + + System default + UltraList enabled + UltraList disabled + + + System default + UltraPrivacy enabled + UltraPrivacy disabled + + + System default + Block all third-party requests enabled + Block all third-party requests disabled + System default Custom font size diff --git a/build.gradle b/build.gradle index e8aaa5de..64d9b31b 100644 --- a/build.gradle +++ b/build.gradle @@ -26,7 +26,7 @@ buildscript { } dependencies { - classpath 'com.android.tools.build:gradle:8.0.1' + classpath 'com.android.tools.build:gradle:8.0.2' classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:1.8.10" // NOTE: Do not place your application dependencies here; they belong diff --git a/gradle.properties b/gradle.properties index e360d698..edf379e7 100644 --- a/gradle.properties +++ b/gradle.properties @@ -38,6 +38,8 @@ android.useAndroidX=true # Use the experimental configuration cache, which can speed up the build process in nothing in the configuration has changed. org.gradle.unsafe.configuration-cache=true +# Use non-transitive R classes, which speed up the build process when the configuration has not changed. +android.nonTransitiveRClass=true + android.defaults.buildfeatures.buildconfig=true -android.nonTransitiveRClass=false android.nonFinalResIds=false