2 * Copyright © 2017-2023 Soren Stoutner <soren@stoutner.com>.
4 * This file is part of Privacy Browser Android <https://www.stoutner.com/privacy-browser-android>.
6 * Privacy Browser Android is free software: you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation, either version 3 of the License, or
9 * (at your option) any later version.
11 * Privacy Browser Android is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with Privacy Browser Android. If not, see <http://www.gnu.org/licenses/>.
20 package com.stoutner.privacybrowser.helpers
22 import android.content.ContentValues
23 import android.content.Context
24 import android.database.Cursor
25 import android.database.DatabaseUtils
26 import android.database.sqlite.SQLiteDatabase
27 import android.database.sqlite.SQLiteOpenHelper
29 import androidx.preference.PreferenceManager
31 import com.stoutner.privacybrowser.R
33 // Define the class constants.
34 private const val SCHEMA_VERSION = 16
36 // Define the public database constants.
37 const val DOMAINS_DATABASE = "domains.db"
38 const val DOMAINS_TABLE = "domains"
40 // Define the public spinner constants.
41 const val SYSTEM_DEFAULT = 0
43 const val DISABLED = 2
44 const val LIGHT_THEME = 1
45 const val DARK_THEME = 2
47 // Define the public schema constants.
48 const val BLOCK_ALL_THIRD_PARTY_REQUESTS = "blockallthirdpartyrequests"
49 const val COOKIES = "cookies"
50 const val DISPLAY_IMAGES = "displayimages"
51 const val DOMAIN_NAME = "domainname"
52 const val ENABLE_DOM_STORAGE = "enabledomstorage"
53 const val ENABLE_EASYLIST = "enableeasylist"
54 const val ENABLE_EASYPRIVACY = "enableeasyprivacy"
55 const val ENABLE_FANBOYS_ANNOYANCE_LIST = "enablefanboysannoyancelist"
56 const val ENABLE_FANBOYS_SOCIAL_BLOCKING_LIST = "enablefanboyssocialblockinglist"
57 const val ENABLE_FORM_DATA = "enableformdata" // Form data can be removed once the minimum API >= 26.
58 const val ENABLE_JAVASCRIPT = "enablejavascript"
59 const val ENABLE_ULTRAPRIVACY = "enableultraprivacy"
60 const val FONT_SIZE = "fontsize"
62 const val IP_ADDRESSES = "ip_addresses"
63 const val PINNED_IP_ADDRESSES = "pinned_ip_addresses"
64 const val PINNED_SSL_CERTIFICATE = "pinnedsslcertificate"
65 const val SSL_END_DATE = "sslenddate"
66 const val SSL_START_DATE = "sslstartdate"
67 const val SSL_ISSUED_BY_COMMON_NAME = "sslissuedbycommonname"
68 const val SSL_ISSUED_BY_ORGANIZATION = "sslissuedbyorganization"
69 const val SSL_ISSUED_BY_ORGANIZATIONAL_UNIT = "sslissuedbyorganizationalunit"
70 const val SSL_ISSUED_TO_COMMON_NAME = "sslissuedtocommonname"
71 const val SSL_ISSUED_TO_ORGANIZATION = "sslissuedtoorganization"
72 const val SSL_ISSUED_TO_ORGANIZATIONAL_UNIT = "sslissuedtoorganizationalunit"
73 const val SWIPE_TO_REFRESH = "swipetorefresh"
74 const val ULTRALIST = "ultralist"
75 const val USER_AGENT = "useragent"
76 const val WEBVIEW_THEME = "webview_theme"
77 const val WIDE_VIEWPORT = "wide_viewport"
79 // Define the public table creation constant.
80 const val CREATE_DOMAINS_TABLE = "CREATE TABLE $DOMAINS_TABLE (" +
81 "$ID INTEGER PRIMARY KEY, " +
82 "$DOMAIN_NAME TEXT, " +
83 "$ENABLE_JAVASCRIPT INTEGER, " +
84 "$COOKIES INTEGER, " +
85 "$ENABLE_DOM_STORAGE INTEGER, " +
86 "$ENABLE_FORM_DATA INTEGER, " +
87 "$ENABLE_EASYLIST INTEGER, " +
88 "$ENABLE_EASYPRIVACY INTEGER, " +
89 "$ENABLE_FANBOYS_ANNOYANCE_LIST INTEGER, " +
90 "$ENABLE_FANBOYS_SOCIAL_BLOCKING_LIST INTEGER, " +
91 "$ULTRALIST INTEGER, " +
92 "$ENABLE_ULTRAPRIVACY INTEGER, " +
93 "$BLOCK_ALL_THIRD_PARTY_REQUESTS INTEGER, " +
94 "$USER_AGENT TEXT, " +
95 "$FONT_SIZE INTEGER, " +
96 "$SWIPE_TO_REFRESH INTEGER, " +
97 "$WEBVIEW_THEME INTEGER, " +
98 "$WIDE_VIEWPORT INTEGER, " +
99 "$DISPLAY_IMAGES INTEGER, " +
100 "$PINNED_SSL_CERTIFICATE BOOLEAN, " +
101 "$SSL_ISSUED_TO_COMMON_NAME TEXT, " +
102 "$SSL_ISSUED_TO_ORGANIZATION TEXT, " +
103 "$SSL_ISSUED_TO_ORGANIZATIONAL_UNIT TEXT, " +
104 "$SSL_ISSUED_BY_COMMON_NAME TEXT, " +
105 "$SSL_ISSUED_BY_ORGANIZATION TEXT, " +
106 "$SSL_ISSUED_BY_ORGANIZATIONAL_UNIT TEXT, " +
107 "$SSL_START_DATE INTEGER, " +
108 "$SSL_END_DATE INTEGER, " +
109 "$PINNED_IP_ADDRESSES BOOLEAN, " +
110 "$IP_ADDRESSES TEXT)"
112 class DomainsDatabaseHelper(private val appContext: Context) : SQLiteOpenHelper(appContext, DOMAINS_DATABASE, null, SCHEMA_VERSION) {
113 override fun onCreate(domainsDatabase: SQLiteDatabase) {
114 // Create the domains table.
115 domainsDatabase.execSQL(CREATE_DOMAINS_TABLE)
118 override fun onUpgrade(domainsDatabase: SQLiteDatabase, oldVersion: Int, newVersion: Int) {
119 // Get a handle for the shared preference.
120 val sharedPreferences = PreferenceManager.getDefaultSharedPreferences(appContext)
122 // Upgrade from schema version 1, first used in Privacy Browser 2.0, to schema version 2, first used in Privacy Browser 2.3.
123 if (oldVersion < 2) {
124 // Add the display images column.
125 domainsDatabase.execSQL("ALTER TABLE $DOMAINS_TABLE ADD COLUMN $DISPLAY_IMAGES INTEGER")
128 // Upgrade from schema version 2, first used in Privacy Browser 2.3, to schema version 3, first used in Privacy Browser 2.5.
129 if (oldVersion < 3) {
130 // Add the SSL certificate columns.
131 domainsDatabase.execSQL("ALTER TABLE $DOMAINS_TABLE ADD COLUMN $PINNED_SSL_CERTIFICATE BOOLEAN")
132 domainsDatabase.execSQL("ALTER TABLE $DOMAINS_TABLE ADD COLUMN $SSL_ISSUED_TO_COMMON_NAME TEXT")
133 domainsDatabase.execSQL("ALTER TABLE $DOMAINS_TABLE ADD COLUMN $SSL_ISSUED_TO_ORGANIZATION TEXT")
134 domainsDatabase.execSQL("ALTER TABLE $DOMAINS_TABLE ADD COLUMN $SSL_ISSUED_TO_ORGANIZATIONAL_UNIT TEXT")
135 domainsDatabase.execSQL("ALTER TABLE $DOMAINS_TABLE ADD COLUMN $SSL_ISSUED_BY_COMMON_NAME TEXT")
136 domainsDatabase.execSQL("ALTER TABLE $DOMAINS_TABLE ADD COLUMN $SSL_ISSUED_BY_ORGANIZATION TEXT")
137 domainsDatabase.execSQL("ALTER TABLE $DOMAINS_TABLE ADD COLUMN $SSL_ISSUED_BY_ORGANIZATIONAL_UNIT TEXT")
138 domainsDatabase.execSQL("ALTER TABLE $DOMAINS_TABLE ADD COLUMN $SSL_START_DATE INTEGER")
139 domainsDatabase.execSQL("ALTER TABLE $DOMAINS_TABLE ADD COLUMN $SSL_END_DATE INTEGER")
142 // Upgrade from schema version 3, first used in Privacy Browser 2.5, to schema version 4, first used in Privacy Browser 2.6.
143 if (oldVersion < 4) {
144 // Add the night mode column.
145 domainsDatabase.execSQL("ALTER TABLE $DOMAINS_TABLE ADD COLUMN nightmode INTEGER")
148 // Upgrade from schema version 4, first used in Privacy Browser 2.6, to schema version 5, first used in Privacy Browser 2.9.
149 if (oldVersion < 5) {
150 // Add the block lists columns.
151 domainsDatabase.execSQL("ALTER TABLE $DOMAINS_TABLE ADD COLUMN $ENABLE_EASYLIST BOOLEAN")
152 domainsDatabase.execSQL("ALTER TABLE $DOMAINS_TABLE ADD COLUMN $ENABLE_EASYPRIVACY BOOLEAN")
153 domainsDatabase.execSQL("ALTER TABLE $DOMAINS_TABLE ADD COLUMN $ENABLE_FANBOYS_ANNOYANCE_LIST BOOLEAN")
154 domainsDatabase.execSQL("ALTER TABLE $DOMAINS_TABLE ADD COLUMN $ENABLE_FANBOYS_SOCIAL_BLOCKING_LIST BOOLEAN")
156 // Get the default filter list settings.
157 val easyListEnabled = sharedPreferences.getBoolean(appContext.getString(R.string.easylist_key), true)
158 val easyPrivacyEnabled = sharedPreferences.getBoolean(appContext.getString(R.string.easyprivacy_key), true)
159 val fanboyAnnoyanceListEnabled = sharedPreferences.getBoolean(appContext.getString(R.string.fanboys_annoyance_list_key), true)
160 val fanboySocialBlockingListEnabled = sharedPreferences.getBoolean(appContext.getString(R.string.fanboys_social_blocking_list_key), true)
162 // Set EasyList for existing rows according to the current system-wide default.
163 // This can switch to using the variables directly once the API >= 30. <https://www.sqlite.org/datatype3.html#boolean_datatype>
164 // <https://developer.android.com/reference/android/database/sqlite/package-summary>
165 if (easyListEnabled) {
166 domainsDatabase.execSQL("UPDATE $DOMAINS_TABLE SET $ENABLE_EASYLIST = 1")
168 domainsDatabase.execSQL("UPDATE $DOMAINS_TABLE SET $ENABLE_EASYLIST = 0")
171 // Set EasyPrivacy for existing rows according to the current system-wide default.
172 if (easyPrivacyEnabled) {
173 domainsDatabase.execSQL("UPDATE $DOMAINS_TABLE SET $ENABLE_EASYPRIVACY = 1")
175 domainsDatabase.execSQL("UPDATE $DOMAINS_TABLE SET $ENABLE_EASYPRIVACY = 0")
178 // Set Fanboy's Annoyance List for existing rows according to the current system-wide default.
179 if (fanboyAnnoyanceListEnabled) {
180 domainsDatabase.execSQL("UPDATE $DOMAINS_TABLE SET $ENABLE_FANBOYS_ANNOYANCE_LIST = 1")
182 domainsDatabase.execSQL("UPDATE $DOMAINS_TABLE SET $ENABLE_FANBOYS_ANNOYANCE_LIST = 0")
185 // Set Fanboy's Social Blocking List for existing rows according to the current system-wide default.
186 if (fanboySocialBlockingListEnabled) {
187 domainsDatabase.execSQL("UPDATE $DOMAINS_TABLE SET $ENABLE_FANBOYS_SOCIAL_BLOCKING_LIST = 1")
189 domainsDatabase.execSQL("UPDATE $DOMAINS_TABLE SET $ENABLE_FANBOYS_SOCIAL_BLOCKING_LIST = 0")
193 // Upgrade from schema version 5, first used in Privacy Browser 2.9, to schema version 6, first used in Privacy Browser 2.11.
194 if (oldVersion < 6) {
195 // Add the swipe to refresh column. This defaults to `0`, which is `System default`, so a separate step isn't needed to populate the column.
196 domainsDatabase.execSQL("ALTER TABLE $DOMAINS_TABLE ADD COLUMN $SWIPE_TO_REFRESH INTEGER")
199 // Upgrade from schema version 6, first used in Privacy Browser 2.11, to schema version 7, first used in Privacy Browser 2.12.
200 if (oldVersion < 7) {
201 // Add the block all third-party requests column. This defaults to `0`, which is off, so a separate step isn't needed to populate the column.
202 domainsDatabase.execSQL("ALTER TABLE $DOMAINS_TABLE ADD COLUMN $BLOCK_ALL_THIRD_PARTY_REQUESTS BOOLEAN")
205 // Upgrade from schema version 7, first used in Privacy Browser 2.12, to schema version 8, first used in Privacy Browser 2.12.
206 // For some reason (lack of planning or attention to detail), the 2.12 update included two schema version jumps.
207 if (oldVersion < 8) {
208 // Add the UltraPrivacy column.
209 domainsDatabase.execSQL("ALTER TABLE $DOMAINS_TABLE ADD COLUMN $ENABLE_ULTRAPRIVACY BOOLEAN")
211 // Enable it for all existing rows.
212 domainsDatabase.execSQL("UPDATE $DOMAINS_TABLE SET $ENABLE_ULTRAPRIVACY = 1")
215 // Upgrade from schema version 8, first used in Privacy Browser 2.12, to schema version 9, first used in Privacy Browser 2.16.
216 if (oldVersion < 9) {
217 // Add the pinned IP addresses columns. These default to `0` and `""`, so a separate step isn't needed to populate the columns.
218 domainsDatabase.execSQL("ALTER TABLE $DOMAINS_TABLE ADD COLUMN $PINNED_IP_ADDRESSES BOOLEAN")
219 domainsDatabase.execSQL("ALTER TABLE $DOMAINS_TABLE ADD COLUMN $IP_ADDRESSES TEXT")
222 // Upgrade from schema version 9, first used in Privacy Browser 2.16, to schema version 10, first used in Privacy Browser 3.1.
223 if (oldVersion < 10) {
224 // Add the wide viewport column. This defaults to `0`, which is `System default`, so a separate step isn't needed to populate the column.
225 domainsDatabase.execSQL("ALTER TABLE $DOMAINS_TABLE ADD COLUMN $WIDE_VIEWPORT INTEGER")
228 // Upgrade from schema version 10, first used in Privacy Browser 3.1, to schema version 11, first used in Privacy Browser 3.2.
229 if (oldVersion < 11) {
230 // Add the UltraList column.
231 domainsDatabase.execSQL("ALTER TABLE $DOMAINS_TABLE ADD COLUMN $ULTRALIST BOOLEAN")
233 // Enable it for all existing rows.
234 domainsDatabase.execSQL("UPDATE $DOMAINS_TABLE SET $ULTRALIST = 1")
237 // Upgrade from schema version 11, first used in Privacy Browser 3.2, to schema version 12, first used in Privacy Browser 3.5.
238 if (oldVersion < 12) {
239 // Add the WebView theme column. This defaults to `0`, which is `System default`, so a separate step isn't needed to populate the column.
240 domainsDatabase.execSQL("ALTER TABLE $DOMAINS_TABLE ADD COLUMN $WEBVIEW_THEME INTEGER")
242 // `night_mode` was removed.
243 // SQLite amazingly only added a command to drop a column in version 3.35.0. <https://www.sqlite.org/changes.html>
244 // It will be a while before that is supported in Android. <https://developer.android.com/reference/android/database/sqlite/package-summary>
245 // Although a new table could be created and all the data copied to it, I think I will just leave the old night mode column. It will be wiped out the next time an import is run.
248 // Upgrade from schema version 12, first used in Privacy Browser 3.5, to schema version 13, first used in Privacy Browser 3.8.
249 if (oldVersion < 13) {
250 // Add the cookies column.
251 domainsDatabase.execSQL("ALTER TABLE $DOMAINS_TABLE ADD COLUMN $COOKIES BOOLEAN")
253 // Copy the data from the old column to the new one.
254 domainsDatabase.execSQL("UPDATE $DOMAINS_TABLE SET $COOKIES = enablefirstpartycookies")
257 // Upgrade from schema version 13, first used in Privacy Browser 3.8, to schema version 14, first used in Privacy Browser 3.11.
258 // This upgrade used to add the X-Requested-With header, but that was removed in schema version 15.
260 // Upgrade from schema version 14, first used in Privacy Browser 3.11, to schema version 15, first used in Privacy Browser 3.12.
261 // This upgrade removed `x_requested_with_header`.
262 // SQLite amazingly only added a command to drop a column in version 3.35.0. <https://www.sqlite.org/changes.html>
263 // It will be a while before that is supported in Android. <https://developer.android.com/reference/android/database/sqlite/package-summary>
264 // 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.
266 // Upgrade from schema version 15, first used in Privacy Browser 3.12, to schema version 16, first used in Privacy Browser 3.15.
267 if (oldVersion < 16) {
268 // Get the current switch default values.
269 val javaScriptDefaultValue = sharedPreferences.getBoolean(appContext.getString(R.string.javascript_key), false)
270 val cookiesDefaultValue = sharedPreferences.getBoolean(appContext.getString(R.string.cookies_key), false)
271 val domStorageDefaultValue = sharedPreferences.getBoolean(appContext.getString(R.string.dom_storage_key), false)
272 val formDataDefaultValue = sharedPreferences.getBoolean(appContext.getString(R.string.save_form_data_key), false)
273 val easyListDefaultValue = sharedPreferences.getBoolean(appContext.getString(R.string.easylist_key), true)
274 val easyPrivacyDefaultValue = sharedPreferences.getBoolean(appContext.getString(R.string.easyprivacy_key), true)
275 val fanboysAnnoyanceListDefaultValue = sharedPreferences.getBoolean(appContext.getString(R.string.fanboys_annoyance_list_key), true)
276 val fanboysSocialBlockingListDefaultValue = sharedPreferences.getBoolean(appContext.getString(R.string.fanboys_social_blocking_list), true)
277 val ultraListDefaultValue = sharedPreferences.getBoolean(appContext.getString(R.string.ultralist_key), true)
278 val ultraPrivacyDefaultValue = sharedPreferences.getBoolean(appContext.getString(R.string.ultraprivacy_key), true)
279 val blockAllThirdPartyRequestsDefaultValue = sharedPreferences.getBoolean(appContext.getString(R.string.block_all_third_party_requests_key), false)
281 // Get a domains cursor.
282 val domainsCursor = domainsDatabase.rawQuery("SELECT * FROM $DOMAINS_TABLE", null)
284 // Get the domains column indexes.
285 val javaScriptColumnIndex = domainsCursor.getColumnIndexOrThrow(ENABLE_JAVASCRIPT)
286 val cookiesColumnIndex = domainsCursor.getColumnIndexOrThrow(COOKIES)
287 val domStorageColumnIndex = domainsCursor.getColumnIndexOrThrow(ENABLE_DOM_STORAGE)
288 val formDataColumnIndex = domainsCursor.getColumnIndexOrThrow(ENABLE_FORM_DATA)
289 val easyListColumnIndex = domainsCursor.getColumnIndexOrThrow(ENABLE_EASYLIST)
290 val easyPrivacyColumnIndex = domainsCursor.getColumnIndexOrThrow(ENABLE_EASYPRIVACY)
291 val fanboysAnnoyanceListColumnIndex = domainsCursor.getColumnIndexOrThrow(ENABLE_FANBOYS_ANNOYANCE_LIST)
292 val fanboysSocialBlockingListColumnIndex = domainsCursor.getColumnIndexOrThrow(ENABLE_FANBOYS_SOCIAL_BLOCKING_LIST)
293 val ultraListColumnIndex = domainsCursor.getColumnIndexOrThrow(ULTRALIST)
294 val ultraPrivacyColumnIndex = domainsCursor.getColumnIndexOrThrow(ENABLE_ULTRAPRIVACY)
295 val blockAllThirdPartyRequestsColumnIndex = domainsCursor.getColumnIndexOrThrow(BLOCK_ALL_THIRD_PARTY_REQUESTS)
297 // Convert the domain from the switch booleans to the spinner integers.
298 for (i in 0 until domainsCursor.count) {
299 // Move to the current record.
300 domainsCursor.moveToPosition(i)
302 // Get the domain current values.
303 val javaScriptDomainCurrentValue = domainsCursor.getInt(javaScriptColumnIndex)
304 val cookiesDomainCurrentValue = domainsCursor.getInt(cookiesColumnIndex)
305 val domStorageDomainCurrentValue = domainsCursor.getInt(domStorageColumnIndex)
306 val formDataDomainCurrentValue = domainsCursor.getInt(formDataColumnIndex)
307 val easyListDomainCurrentValue = domainsCursor.getInt(easyListColumnIndex)
308 val easyPrivacyDomainCurrentValue = domainsCursor.getInt(easyPrivacyColumnIndex)
309 val fanboysAnnoyanceListCurrentValue = domainsCursor.getInt(fanboysAnnoyanceListColumnIndex)
310 val fanboysSocialBlockingListCurrentValue = domainsCursor.getInt(fanboysSocialBlockingListColumnIndex)
311 val ultraListCurrentValue = domainsCursor.getInt(ultraListColumnIndex)
312 val ultraPrivacyCurrentValue = domainsCursor.getInt(ultraPrivacyColumnIndex)
313 val blockAllThirdPartyRequestsCurrentValue = domainsCursor.getInt(blockAllThirdPartyRequestsColumnIndex)
315 // Instantiate a domain content values.
316 val domainContentValues = ContentValues()
318 // Populate the domain content values.
319 domainContentValues.put(ENABLE_JAVASCRIPT, convertFromSwitchToSpinner(javaScriptDefaultValue, javaScriptDomainCurrentValue))
320 domainContentValues.put(COOKIES, convertFromSwitchToSpinner(cookiesDefaultValue, cookiesDomainCurrentValue))
321 domainContentValues.put(ENABLE_DOM_STORAGE, convertFromSwitchToSpinner(domStorageDefaultValue, domStorageDomainCurrentValue))
322 domainContentValues.put(ENABLE_FORM_DATA, convertFromSwitchToSpinner(formDataDefaultValue, formDataDomainCurrentValue))
323 domainContentValues.put(ENABLE_EASYLIST, convertFromSwitchToSpinner(easyListDefaultValue, easyListDomainCurrentValue))
324 domainContentValues.put(ENABLE_EASYPRIVACY, convertFromSwitchToSpinner(easyPrivacyDefaultValue, easyPrivacyDomainCurrentValue))
325 domainContentValues.put(ENABLE_FANBOYS_ANNOYANCE_LIST, convertFromSwitchToSpinner(fanboysAnnoyanceListDefaultValue, fanboysAnnoyanceListCurrentValue))
326 domainContentValues.put(ENABLE_FANBOYS_SOCIAL_BLOCKING_LIST, convertFromSwitchToSpinner(fanboysSocialBlockingListDefaultValue, fanboysSocialBlockingListCurrentValue))
327 domainContentValues.put(ULTRALIST, convertFromSwitchToSpinner(ultraListDefaultValue, ultraListCurrentValue))
328 domainContentValues.put(ENABLE_ULTRAPRIVACY, convertFromSwitchToSpinner(ultraPrivacyDefaultValue, ultraPrivacyCurrentValue))
329 domainContentValues.put(BLOCK_ALL_THIRD_PARTY_REQUESTS, convertFromSwitchToSpinner(blockAllThirdPartyRequestsDefaultValue, blockAllThirdPartyRequestsCurrentValue))
331 // Get the current database ID.
332 val currentDatabaseId = domainsCursor.getInt(domainsCursor.getColumnIndexOrThrow(ID))
334 // Update the row for the specified database ID.
335 domainsDatabase.update(DOMAINS_TABLE, domainContentValues, "$ID = $currentDatabaseId", null)
339 domainsCursor.close()
343 val completeCursorOrderedByDomain: Cursor
345 // Get a readable database handle.
346 val domainsDatabase = this.readableDatabase
348 // Return everything in the domains table ordered by the domain name. The cursor can't be closed because it is needed in the calling activity.
349 return domainsDatabase.rawQuery("SELECT * FROM $DOMAINS_TABLE ORDER BY $DOMAIN_NAME ASC", null)
352 val domainNameCursorOrderedByDomain: Cursor
354 // Get a readable database handle.
355 val domainsDatabase = this.readableDatabase
357 // 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.
358 return domainsDatabase.rawQuery("SELECT $ID, $DOMAIN_NAME FROM $DOMAINS_TABLE ORDER BY $DOMAIN_NAME ASC", null)
361 // This method is used to convert the old domain settings switches to spinners.
362 private fun convertFromSwitchToSpinner(systemDefault: Boolean, currentDatabaseInteger: Int): Int {
363 // Return the new spinner integer.
364 return if ((!systemDefault && (currentDatabaseInteger == 0)) ||
365 (systemDefault && (currentDatabaseInteger == 1))) // The system default is currently selected.
367 else if (currentDatabaseInteger == 0) // The switch is currently disabled and that is not the system default.
369 else // The switch is currently enabled and that is not the system default.
373 fun getDomainNameCursorOrderedByDomainExcept(databaseId: Int): Cursor {
374 // Get a readable database handle.
375 val domainsDatabase = this.readableDatabase
377 // Return a cursor with the database IDs and domain names except for the specified ID ordered by domain name. The cursor can't be closed because it is needed in the calling activity.
378 return domainsDatabase.rawQuery("SELECT $ID, $DOMAIN_NAME FROM $DOMAINS_TABLE WHERE $ID IS NOT $databaseId ORDER BY $DOMAIN_NAME ASC", null)
381 fun getCursorForId(databaseId: Int): Cursor {
382 // Get a readable database handle.
383 val domainsDatabase = this.readableDatabase
385 // Return a cursor for the specified database ID. The cursor can't be closed because it is needed in the calling activity.
386 return domainsDatabase.rawQuery("SELECT * FROM $DOMAINS_TABLE WHERE $ID = $databaseId", null)
389 fun getCursorForDomainName(domainName: String): Cursor {
390 // Get a readable database handle.
391 val domainsDatabase = this.readableDatabase
393 // SQL escape the domain name.
394 val sqlEscapedDomainName = DatabaseUtils.sqlEscapeString(domainName)
396 // Return a cursor for the requested domain name. The cursor can't be closed because it is needed in the calling activity.
397 return domainsDatabase.rawQuery("SELECT * FROM $DOMAINS_TABLE WHERE $DOMAIN_NAME = $sqlEscapedDomainName", null)
400 fun addDomain(domainName: String): Int {
401 // Instantiate a content values.
402 val domainContentValues = ContentValues()
404 // Get a handle for the shared preference.
405 val sharedPreferences = PreferenceManager.getDefaultSharedPreferences(appContext)
407 // Get the default settings.
408 val javaScript = sharedPreferences.getBoolean(appContext.getString(R.string.javascript_key), false)
409 val cookies = sharedPreferences.getBoolean(appContext.getString(R.string.cookies_key), false)
410 val domStorage = sharedPreferences.getBoolean(appContext.getString(R.string.dom_storage_key), false)
411 val saveFormData = sharedPreferences.getBoolean(appContext.getString(R.string.save_form_data_key), false) // Form data can be removed once the minimum API >= 26.
412 val easyList = sharedPreferences.getBoolean(appContext.getString(R.string.easylist_key), true)
413 val easyPrivacy = sharedPreferences.getBoolean(appContext.getString(R.string.easyprivacy_key), true)
414 val fanboyAnnoyanceList = sharedPreferences.getBoolean(appContext.getString(R.string.fanboys_annoyance_list_key), true)
415 val fanboySocialBlockingList = sharedPreferences.getBoolean(appContext.getString(R.string.fanboys_social_blocking_list_key), true)
416 val ultraList = sharedPreferences.getBoolean(appContext.getString(R.string.ultralist_key), true)
417 val ultraPrivacy = sharedPreferences.getBoolean(appContext.getString(R.string.ultraprivacy_key), true)
418 val blockAllThirdPartyRequests = sharedPreferences.getBoolean(appContext.getString(R.string.block_all_third_party_requests_key), false)
420 // Create entries for the database fields. The ID is created automatically. The pinned SSL certificate information is not created unless added by the user.
421 domainContentValues.put(DOMAIN_NAME, domainName)
422 domainContentValues.put(ENABLE_JAVASCRIPT, javaScript)
423 domainContentValues.put(COOKIES, cookies)
424 domainContentValues.put(ENABLE_DOM_STORAGE, domStorage)
425 domainContentValues.put(ENABLE_FORM_DATA, saveFormData) // Form data can be removed once the minimum API >= 26.
426 domainContentValues.put(ENABLE_EASYLIST, easyList)
427 domainContentValues.put(ENABLE_EASYPRIVACY, easyPrivacy)
428 domainContentValues.put(ENABLE_FANBOYS_ANNOYANCE_LIST, fanboyAnnoyanceList)
429 domainContentValues.put(ENABLE_FANBOYS_SOCIAL_BLOCKING_LIST, fanboySocialBlockingList)
430 domainContentValues.put(ULTRALIST, ultraList)
431 domainContentValues.put(ENABLE_ULTRAPRIVACY, ultraPrivacy)
432 domainContentValues.put(BLOCK_ALL_THIRD_PARTY_REQUESTS, blockAllThirdPartyRequests)
433 domainContentValues.put(USER_AGENT, appContext.getString(R.string.system_default_user_agent))
434 domainContentValues.put(FONT_SIZE, 0)
435 domainContentValues.put(SWIPE_TO_REFRESH, 0)
436 domainContentValues.put(WEBVIEW_THEME, 0)
437 domainContentValues.put(WIDE_VIEWPORT, 0)
438 domainContentValues.put(DISPLAY_IMAGES, 0)
440 // Get a writable database handle.
441 val domainsDatabase = this.writableDatabase
443 // Insert a new row and store the resulting database ID.
444 val newDomainDatabaseId = domainsDatabase.insert(DOMAINS_TABLE, null, domainContentValues).toInt()
446 // Close the database handle.
447 domainsDatabase.close()
449 // Return the new domain database ID.
450 return newDomainDatabaseId
453 fun addDomain(contentValues: ContentValues) {
454 // Get a writable database handle.
455 val domainsDatabase = this.writableDatabase
457 // Add the new domain.
458 domainsDatabase.insert(DOMAINS_TABLE, null, contentValues)
460 // Close the database handle.
461 domainsDatabase.close()
464 fun updateDomain(databaseId: Int, domainName: String, javaScript: Int, cookies: Int, domStorage: Int, formData: Int, easyList: Int, easyPrivacy: Int, fanboysAnnoyance: Int, fanboysSocialBlocking: Int,
465 ultraList: Int, ultraPrivacy: Int, blockAllThirdPartyRequests: Int, userAgent: String, fontSize: Int, swipeToRefresh: Int, webViewTheme: Int, wideViewport: Int, displayImages: Int,
466 pinnedSslCertificate: Boolean, pinnedIpAddresses: Boolean) {
468 // Instantiate a content values.
469 val domainContentValues = ContentValues()
471 // Add entries for each field in the database.
472 domainContentValues.put(DOMAIN_NAME, domainName)
473 domainContentValues.put(ENABLE_JAVASCRIPT, javaScript)
474 domainContentValues.put(COOKIES, cookies)
475 domainContentValues.put(ENABLE_DOM_STORAGE, domStorage)
476 domainContentValues.put(ENABLE_FORM_DATA, formData) // Form data can be removed once the minimum API >= 26.
477 domainContentValues.put(ENABLE_EASYLIST, easyList)
478 domainContentValues.put(ENABLE_EASYPRIVACY, easyPrivacy)
479 domainContentValues.put(ENABLE_FANBOYS_ANNOYANCE_LIST, fanboysAnnoyance)
480 domainContentValues.put(ENABLE_FANBOYS_SOCIAL_BLOCKING_LIST, fanboysSocialBlocking)
481 domainContentValues.put(ULTRALIST, ultraList)
482 domainContentValues.put(ENABLE_ULTRAPRIVACY, ultraPrivacy)
483 domainContentValues.put(BLOCK_ALL_THIRD_PARTY_REQUESTS, blockAllThirdPartyRequests)
484 domainContentValues.put(USER_AGENT, userAgent)
485 domainContentValues.put(FONT_SIZE, fontSize)
486 domainContentValues.put(SWIPE_TO_REFRESH, swipeToRefresh)
487 domainContentValues.put(WEBVIEW_THEME, webViewTheme)
488 domainContentValues.put(WIDE_VIEWPORT, wideViewport)
489 domainContentValues.put(DISPLAY_IMAGES, displayImages)
490 domainContentValues.put(PINNED_SSL_CERTIFICATE, pinnedSslCertificate)
491 domainContentValues.put(PINNED_IP_ADDRESSES, pinnedIpAddresses)
493 // Get a writable database handle.
494 val domainsDatabase = this.writableDatabase
496 // Update the row for the specified database ID.
497 domainsDatabase.update(DOMAINS_TABLE, domainContentValues, "$ID = $databaseId", null)
499 // Close the database handle.
500 domainsDatabase.close()
503 fun updatePinnedSslCertificate(databaseId: Int, sslIssuedToCommonName: String, sslIssuedToOrganization: String, sslIssuedToOrganizationalUnit: String, sslIssuedByCommonName: String,
504 sslIssuedByOrganization: String, sslIssuedByOrganizationalUnit: String, sslStartDate: Long, sslEndDate: Long) {
505 // Instantiate a content values.
506 val pinnedSslCertificateContentValues = ContentValues()
508 // Add entries for each field in the certificate.
509 pinnedSslCertificateContentValues.put(SSL_ISSUED_TO_COMMON_NAME, sslIssuedToCommonName)
510 pinnedSslCertificateContentValues.put(SSL_ISSUED_TO_ORGANIZATION, sslIssuedToOrganization)
511 pinnedSslCertificateContentValues.put(SSL_ISSUED_TO_ORGANIZATIONAL_UNIT, sslIssuedToOrganizationalUnit)
512 pinnedSslCertificateContentValues.put(SSL_ISSUED_BY_COMMON_NAME, sslIssuedByCommonName)
513 pinnedSslCertificateContentValues.put(SSL_ISSUED_BY_ORGANIZATION, sslIssuedByOrganization)
514 pinnedSslCertificateContentValues.put(SSL_ISSUED_BY_ORGANIZATIONAL_UNIT, sslIssuedByOrganizationalUnit)
515 pinnedSslCertificateContentValues.put(SSL_START_DATE, sslStartDate)
516 pinnedSslCertificateContentValues.put(SSL_END_DATE, sslEndDate)
518 // Get a writable database handle.
519 val domainsDatabase = this.writableDatabase
521 // Update the row for the specified database ID.
522 domainsDatabase.update(DOMAINS_TABLE, pinnedSslCertificateContentValues, "$ID = $databaseId", null)
524 // Close the database handle.
525 domainsDatabase.close()
528 fun updatePinnedIpAddresses(databaseId: Int, ipAddresses: String) {
529 // Instantiate a content values.
530 val pinnedIpAddressesContentValues = ContentValues()
532 // Add the IP addresses to the content values.
533 pinnedIpAddressesContentValues.put(IP_ADDRESSES, ipAddresses)
535 // Get a writable database handle.
536 val domainsDatabase = this.writableDatabase
538 // Update the row for the database ID.
539 domainsDatabase.update(DOMAINS_TABLE, pinnedIpAddressesContentValues, "$ID = $databaseId", null)
541 // Close the database handle.
542 domainsDatabase.close()
545 fun deleteDomain(databaseId: Int) {
546 // Get a writable database handle.
547 val domainsDatabase = this.writableDatabase
549 // Delete the row for the specified database ID.
550 domainsDatabase.delete(DOMAINS_TABLE, "$ID = $databaseId", null)
552 // Close the database handle.
553 domainsDatabase.close()