]> gitweb.stoutner.com Git - PrivacyBrowserAndroid.git/blob - app/src/main/java/com/stoutner/privacybrowser/helpers/DomainsDatabaseHelper.kt
53a3cbe4569c84e22202de8494ccef8b7fd06051
[PrivacyBrowserAndroid.git] / app / src / main / java / com / stoutner / privacybrowser / helpers / DomainsDatabaseHelper.kt
1 /*
2  * Copyright © 2017-2022 Soren Stoutner <soren@stoutner.com>.
3  *
4  * This file is part of Privacy Browser Android <https://www.stoutner.com/privacy-browser-android>.
5  *
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.
10  *
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.
15  *
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/>.
18  */
19
20 package com.stoutner.privacybrowser.helpers
21
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
28
29 import androidx.preference.PreferenceManager
30
31 import com.stoutner.privacybrowser.R
32
33 // The private constants.
34 private const val SCHEMA_VERSION = 13
35
36 class DomainsDatabaseHelper(private val appContext: Context) : SQLiteOpenHelper(appContext, DOMAINS_DATABASE, null, SCHEMA_VERSION) {
37     // Define the public companion object constants.  These can be moved to public class constants once the entire project has migrated to Kotlin.
38     companion object {
39         // The database constants.
40         const val DOMAINS_DATABASE = "domains.db"
41         const val DOMAINS_TABLE = "domains"
42
43         // The spinner constants.
44         const val SYSTEM_DEFAULT = 0
45         const val ENABLED = 1
46         const val DISABLED = 2
47         const val LIGHT_THEME = 1
48         const val DARK_THEME = 2
49
50         // The schema constants.
51         const val ID = "_id"
52         const val DOMAIN_NAME = "domainname"
53         const val ENABLE_JAVASCRIPT = "enablejavascript"
54         const val COOKIES = "cookies"
55         const val ENABLE_DOM_STORAGE = "enabledomstorage"
56         const val ENABLE_FORM_DATA = "enableformdata" // Form data can be removed once the minimum API >= 26.
57         const val ENABLE_EASYLIST = "enableeasylist"
58         const val ENABLE_EASYPRIVACY = "enableeasyprivacy"
59         const val ENABLE_FANBOYS_ANNOYANCE_LIST = "enablefanboysannoyancelist"
60         const val ENABLE_FANBOYS_SOCIAL_BLOCKING_LIST = "enablefanboyssocialblockinglist"
61         const val ULTRALIST = "ultralist"
62         const val ENABLE_ULTRAPRIVACY = "enableultraprivacy"
63         const val BLOCK_ALL_THIRD_PARTY_REQUESTS = "blockallthirdpartyrequests"
64         const val USER_AGENT = "useragent"
65         const val FONT_SIZE = "fontsize"
66         const val SWIPE_TO_REFRESH = "swipetorefresh"
67         const val WEBVIEW_THEME = "webview_theme"
68         const val WIDE_VIEWPORT = "wide_viewport"
69         const val DISPLAY_IMAGES = "displayimages"
70         const val PINNED_SSL_CERTIFICATE = "pinnedsslcertificate"
71         const val SSL_ISSUED_TO_COMMON_NAME = "sslissuedtocommonname"
72         const val SSL_ISSUED_TO_ORGANIZATION = "sslissuedtoorganization"
73         const val SSL_ISSUED_TO_ORGANIZATIONAL_UNIT = "sslissuedtoorganizationalunit"
74         const val SSL_ISSUED_BY_COMMON_NAME = "sslissuedbycommonname"
75         const val SSL_ISSUED_BY_ORGANIZATION = "sslissuedbyorganization"
76         const val SSL_ISSUED_BY_ORGANIZATIONAL_UNIT = "sslissuedbyorganizationalunit"
77         const val SSL_START_DATE = "sslstartdate"
78         const val SSL_END_DATE = "sslenddate"
79         const val PINNED_IP_ADDRESSES = "pinned_ip_addresses"
80         const val IP_ADDRESSES = "ip_addresses"
81
82         // The table creation constant.
83         const val CREATE_DOMAINS_TABLE = "CREATE TABLE " + DOMAINS_TABLE + " (" +
84                 ID + " INTEGER PRIMARY KEY, " +
85                 DOMAIN_NAME + " TEXT, " +
86                 ENABLE_JAVASCRIPT + " BOOLEAN, " +
87                 COOKIES + " BOOLEAN, " +
88                 ENABLE_DOM_STORAGE + " BOOLEAN, " +
89                 ENABLE_FORM_DATA + " BOOLEAN, " +
90                 ENABLE_EASYLIST + " BOOLEAN, " +
91                 ENABLE_EASYPRIVACY + " BOOLEAN, " +
92                 ENABLE_FANBOYS_ANNOYANCE_LIST + " BOOLEAN, " +
93                 ENABLE_FANBOYS_SOCIAL_BLOCKING_LIST + " BOOLEAN, " +
94                 ULTRALIST + " BOOLEAN, " +
95                 ENABLE_ULTRAPRIVACY + " BOOLEAN, " +
96                 BLOCK_ALL_THIRD_PARTY_REQUESTS + " BOOLEAN, " +
97                 USER_AGENT + " TEXT, " +
98                 FONT_SIZE + " INTEGER, " +
99                 SWIPE_TO_REFRESH + " INTEGER, " +
100                 WEBVIEW_THEME + " INTEGER, " +
101                 WIDE_VIEWPORT + " INTEGER, " +
102                 DISPLAY_IMAGES + " INTEGER, " +
103                 PINNED_SSL_CERTIFICATE + " BOOLEAN, " +
104                 SSL_ISSUED_TO_COMMON_NAME + " TEXT, " +
105                 SSL_ISSUED_TO_ORGANIZATION + " TEXT, " +
106                 SSL_ISSUED_TO_ORGANIZATIONAL_UNIT + " TEXT, " +
107                 SSL_ISSUED_BY_COMMON_NAME + " TEXT, " +
108                 SSL_ISSUED_BY_ORGANIZATION + " TEXT, " +
109                 SSL_ISSUED_BY_ORGANIZATIONAL_UNIT + " TEXT, " +
110                 SSL_START_DATE + " INTEGER, " +
111                 SSL_END_DATE + " INTEGER, " +
112                 PINNED_IP_ADDRESSES + " BOOLEAN, " +
113                 IP_ADDRESSES + " TEXT)"
114     }
115
116     override fun onCreate(domainsDatabase: SQLiteDatabase) {
117         // Create the domains table.
118         domainsDatabase.execSQL(CREATE_DOMAINS_TABLE)
119     }
120
121     override fun onUpgrade(domainsDatabase: SQLiteDatabase, oldVersion: Int, newVersion: Int) {
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")
126         }
127
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")
140         }
141
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")
146         }
147
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")
155
156             // Get a handle for the shared preference.
157             val sharedPreferences = PreferenceManager.getDefaultSharedPreferences(appContext)
158
159             // Get the default block list settings.
160             val easyListEnabled = sharedPreferences.getBoolean("easylist", true)
161             val easyPrivacyEnabled = sharedPreferences.getBoolean("easyprivacy", true)
162             val fanboyAnnoyanceListEnabled = sharedPreferences.getBoolean("fanboys_annoyance_list", true)
163             val fanboySocialBlockingListEnabled = sharedPreferences.getBoolean("fanboys_social_blocking_list", true)
164
165             // Set EasyList for existing rows according to the current system-wide default.
166             // This can switch to using the variables directly once the API >= 30.  <https://www.sqlite.org/datatype3.html#boolean_datatype>
167             // <https://developer.android.com/reference/android/database/sqlite/package-summary>
168             if (easyListEnabled) {
169                 domainsDatabase.execSQL("UPDATE $DOMAINS_TABLE SET $ENABLE_EASYLIST = 1")
170             } else {
171                 domainsDatabase.execSQL("UPDATE $DOMAINS_TABLE SET $ENABLE_EASYLIST = 0")
172             }
173
174             // Set EasyPrivacy for existing rows according to the current system-wide default.
175             if (easyPrivacyEnabled) {
176                 domainsDatabase.execSQL("UPDATE $DOMAINS_TABLE SET $ENABLE_EASYPRIVACY = 1")
177             } else {
178                 domainsDatabase.execSQL("UPDATE $DOMAINS_TABLE SET $ENABLE_EASYPRIVACY = 0")
179             }
180
181             // Set Fanboy's Annoyance List for existing rows according to the current system-wide default.
182             if (fanboyAnnoyanceListEnabled) {
183                 domainsDatabase.execSQL("UPDATE $DOMAINS_TABLE SET $ENABLE_FANBOYS_ANNOYANCE_LIST = 1")
184             } else {
185                 domainsDatabase.execSQL("UPDATE $DOMAINS_TABLE SET $ENABLE_FANBOYS_ANNOYANCE_LIST = 0")
186             }
187
188             // Set Fanboy's Social Blocking List for existing rows according to the current system-wide default.
189             if (fanboySocialBlockingListEnabled) {
190                 domainsDatabase.execSQL("UPDATE $DOMAINS_TABLE SET $ENABLE_FANBOYS_SOCIAL_BLOCKING_LIST = 1")
191             } else {
192                 domainsDatabase.execSQL("UPDATE $DOMAINS_TABLE SET $ENABLE_FANBOYS_SOCIAL_BLOCKING_LIST = 0")
193             }
194         }
195
196         // Upgrade from schema version 5, first used in Privacy Browser 2.9, to schema version 6, first used in Privacy Browser 2.11.
197         if (oldVersion < 6) {
198             // 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.
199             domainsDatabase.execSQL("ALTER TABLE $DOMAINS_TABLE ADD COLUMN $SWIPE_TO_REFRESH INTEGER")
200         }
201
202         // Upgrade from schema version 6, first used in Privacy Browser 2.11, to schema version 7, first used in Privacy Browser 2.12.
203         if (oldVersion < 7) {
204             // 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.
205             domainsDatabase.execSQL("ALTER TABLE $DOMAINS_TABLE ADD COLUMN $BLOCK_ALL_THIRD_PARTY_REQUESTS BOOLEAN")
206         }
207
208         // Upgrade from schema version 7, first used in Privacy Browser 2.12, to schema version 8, first used in Privacy Browser 2.12.
209         // For some reason (lack of planning or attention to detail), the 2.12 update included two schema version jumps.
210         if (oldVersion < 8) {
211             // Add the UltraPrivacy column.
212             domainsDatabase.execSQL("ALTER TABLE $DOMAINS_TABLE ADD COLUMN $ENABLE_ULTRAPRIVACY BOOLEAN")
213
214             // Enable it for all existing rows.
215             domainsDatabase.execSQL("UPDATE $DOMAINS_TABLE SET $ENABLE_ULTRAPRIVACY = 1")
216         }
217
218         // Upgrade from schema version 8, first used in Privacy Browser 2.12, to schema version 9, first used in Privacy Browser 2.16.
219         if (oldVersion < 9) {
220             // Add the pinned IP addresses columns.  These default to `0` and `""`, so a separate step isn't needed to populate the columns.
221             domainsDatabase.execSQL("ALTER TABLE $DOMAINS_TABLE ADD COLUMN $PINNED_IP_ADDRESSES BOOLEAN")
222             domainsDatabase.execSQL("ALTER TABLE $DOMAINS_TABLE ADD COLUMN $IP_ADDRESSES TEXT")
223         }
224
225         // Upgrade from schema version 9, first used in Privacy Browser 2.16, to schema version 10, first used in Privacy Browser 3.1.
226         if (oldVersion < 10) {
227             // Add the wide viewport column.  This defaults to `0`, which is `System default`, so a separate step isn't needed to populate the column.
228             domainsDatabase.execSQL("ALTER TABLE $DOMAINS_TABLE ADD COLUMN $WIDE_VIEWPORT INTEGER")
229         }
230
231         // Upgrade from schema version 10, first used in Privacy Browser 3.1, to schema version 11, first used in Privacy Browser 3.2.
232         if (oldVersion < 11) {
233             // Add the UltraList column.
234             domainsDatabase.execSQL("ALTER TABLE $DOMAINS_TABLE ADD COLUMN $ULTRALIST BOOLEAN")
235
236             // Enable it for all existing rows.
237             domainsDatabase.execSQL("UPDATE $DOMAINS_TABLE SET $ULTRALIST = 1")
238         }
239
240         // Upgrade from schema version 11, first used in Privacy Browser 3.2, to schema version 12, first used in Privacy Browser 3.5.
241         if (oldVersion < 12) {
242             // Add the WebView theme column.  This defaults to `0`, which is `System default`, so a separate step isn't needed to populate the column.
243             domainsDatabase.execSQL("ALTER TABLE $DOMAINS_TABLE ADD COLUMN $WEBVIEW_THEME INTEGER")
244
245             // SQLite amazingly only added a command to drop a column in version 3.35.0.  <https://www.sqlite.org/changes.html>
246             // It will be a while before that is supported in Android.  <https://developer.android.com/reference/android/database/sqlite/package-summary>
247             // 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         }
249
250         // Upgrade from schema version 12, first used in Privacy Browser 3.5, to schema version 13, first used in Privacy Browser 3.8.
251         if (oldVersion < 13) {
252             // Add the cookies column.
253             domainsDatabase.execSQL("ALTER TABLE $DOMAINS_TABLE ADD COLUMN $COOKIES BOOLEAN")
254
255             // Copy the data from the old column to the new one.
256             domainsDatabase.execSQL("UPDATE $DOMAINS_TABLE SET $COOKIES = enablefirstpartycookies")
257         }
258     }
259
260     val completeCursorOrderedByDomain: Cursor
261         get() {
262             // Get a readable database handle.
263             val domainsDatabase = this.readableDatabase
264
265             // 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.
266             return domainsDatabase.rawQuery("SELECT * FROM $DOMAINS_TABLE ORDER BY $DOMAIN_NAME ASC", null)
267         }
268
269     val domainNameCursorOrderedByDomain: Cursor
270         get() {
271             // Get a readable database handle.
272             val domainsDatabase = this.readableDatabase
273
274             // 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.
275             return domainsDatabase.rawQuery("SELECT $ID, $DOMAIN_NAME FROM $DOMAINS_TABLE ORDER BY $DOMAIN_NAME ASC", null)
276         }
277
278     fun getDomainNameCursorOrderedByDomainExcept(databaseId: Int): Cursor {
279         // Get a readable database handle.
280         val domainsDatabase = this.readableDatabase
281
282         // 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.
283         return domainsDatabase.rawQuery("SELECT $ID, $DOMAIN_NAME FROM $DOMAINS_TABLE WHERE $ID IS NOT $databaseId ORDER BY $DOMAIN_NAME ASC", null)
284     }
285
286     fun getCursorForId(databaseId: Int): Cursor {
287         // Get a readable database handle.
288         val domainsDatabase = this.readableDatabase
289
290         // Return a cursor for the specified database ID.  The cursor can't be closed because it is needed in the calling activity.
291         return domainsDatabase.rawQuery("SELECT * FROM $DOMAINS_TABLE WHERE $ID = $databaseId", null)
292     }
293
294     fun getCursorForDomainName(domainName: String): Cursor {
295         // Get a readable database handle.
296         val domainsDatabase = this.readableDatabase
297
298         // SQL escape the domain name.
299         val sqlEscapedDomainName = DatabaseUtils.sqlEscapeString(domainName)
300
301         // Return a cursor for the requested domain name.  The cursor can't be closed because it is needed in the calling activity.
302         return domainsDatabase.rawQuery("SELECT * FROM $DOMAINS_TABLE WHERE $DOMAIN_NAME = $sqlEscapedDomainName", null)
303     }
304
305     fun addDomain(domainName: String): Int {
306         // Instantiate a content values.
307         val domainContentValues = ContentValues()
308
309         // Get a handle for the shared preference.
310         val sharedPreferences = PreferenceManager.getDefaultSharedPreferences(appContext)
311
312         // Get the default settings.
313         val javaScript = sharedPreferences.getBoolean("javascript", false)
314         val cookies = sharedPreferences.getBoolean(appContext.getString(R.string.cookies_key), false)
315         val domStorage = sharedPreferences.getBoolean("dom_storage", false)
316         val saveFormData = sharedPreferences.getBoolean("save_form_data", false) // Form data can be removed once the minimum API >= 26.
317         val easyList = sharedPreferences.getBoolean("easylist", true)
318         val easyPrivacy = sharedPreferences.getBoolean("easyprivacy", true)
319         val fanboyAnnoyanceList = sharedPreferences.getBoolean("fanboys_annoyance_list", true)
320         val fanboySocialBlockingList = sharedPreferences.getBoolean("fanboys_social_blocking_list", true)
321         val ultraList = sharedPreferences.getBoolean("ultralist", true)
322         val ultraPrivacy = sharedPreferences.getBoolean("ultraprivacy", true)
323         val blockAllThirdPartyRequests = sharedPreferences.getBoolean("block_all_third_party_requests", false)
324
325         // Create entries for the database fields.  The ID is created automatically.  The pinned SSL certificate information is not created unless added by the user.
326         domainContentValues.put(DOMAIN_NAME, domainName)
327         domainContentValues.put(ENABLE_JAVASCRIPT, javaScript)
328         domainContentValues.put(COOKIES, cookies)
329         domainContentValues.put(ENABLE_DOM_STORAGE, domStorage)
330         domainContentValues.put(ENABLE_FORM_DATA, saveFormData) // Form data can be removed once the minimum API >= 26.
331         domainContentValues.put(ENABLE_EASYLIST, easyList)
332         domainContentValues.put(ENABLE_EASYPRIVACY, easyPrivacy)
333         domainContentValues.put(ENABLE_FANBOYS_ANNOYANCE_LIST, fanboyAnnoyanceList)
334         domainContentValues.put(ENABLE_FANBOYS_SOCIAL_BLOCKING_LIST, fanboySocialBlockingList)
335         domainContentValues.put(ULTRALIST, ultraList)
336         domainContentValues.put(ENABLE_ULTRAPRIVACY, ultraPrivacy)
337         domainContentValues.put(BLOCK_ALL_THIRD_PARTY_REQUESTS, blockAllThirdPartyRequests)
338         domainContentValues.put(USER_AGENT, "System default user agent")
339         domainContentValues.put(FONT_SIZE, 0)
340         domainContentValues.put(SWIPE_TO_REFRESH, 0)
341         domainContentValues.put(WEBVIEW_THEME, 0)
342         domainContentValues.put(WIDE_VIEWPORT, 0)
343         domainContentValues.put(DISPLAY_IMAGES, 0)
344
345         // Get a writable database handle.
346         val domainsDatabase = this.writableDatabase
347
348         // Insert a new row and store the resulting database ID.
349         val newDomainDatabaseId = domainsDatabase.insert(DOMAINS_TABLE, null, domainContentValues).toInt()
350
351         // Close the database handle.
352         domainsDatabase.close()
353
354         // Return the new domain database ID.
355         return newDomainDatabaseId
356     }
357
358     fun addDomain(contentValues: ContentValues) {
359         // Get a writable database handle.
360         val domainsDatabase = this.writableDatabase
361
362         // Add the new domain.
363         domainsDatabase.insert(DOMAINS_TABLE, null, contentValues)
364
365         // Close the database handle.
366         domainsDatabase.close()
367     }
368
369     fun updateDomain(databaseId: Int, domainName: String, javaScript: Boolean, cookies: Boolean, domStorage: Boolean, formData: Boolean, easyList: Boolean, easyPrivacy: Boolean, fanboysAnnoyance: Boolean,
370                      fanboysSocialBlocking: Boolean, ultraList: Boolean, ultraPrivacy: Boolean, blockAllThirdPartyRequests: Boolean, userAgent: String, fontSize: Int, swipeToRefresh: Int, webViewTheme: Int,
371                      wideViewport: Int, displayImages: Int, pinnedSslCertificate: Boolean, pinnedIpAddresses: Boolean) {
372         // Instantiate a content values.
373         val domainContentValues = ContentValues()
374
375         // Add entries for each field in the database.
376         domainContentValues.put(DOMAIN_NAME, domainName)
377         domainContentValues.put(ENABLE_JAVASCRIPT, javaScript)
378         domainContentValues.put(COOKIES, cookies)
379         domainContentValues.put(ENABLE_DOM_STORAGE, domStorage)
380         domainContentValues.put(ENABLE_FORM_DATA, formData) // Form data can be removed once the minimum API >= 26.
381         domainContentValues.put(ENABLE_EASYLIST, easyList)
382         domainContentValues.put(ENABLE_EASYPRIVACY, easyPrivacy)
383         domainContentValues.put(ENABLE_FANBOYS_ANNOYANCE_LIST, fanboysAnnoyance)
384         domainContentValues.put(ENABLE_FANBOYS_SOCIAL_BLOCKING_LIST, fanboysSocialBlocking)
385         domainContentValues.put(ULTRALIST, ultraList)
386         domainContentValues.put(ENABLE_ULTRAPRIVACY, ultraPrivacy)
387         domainContentValues.put(BLOCK_ALL_THIRD_PARTY_REQUESTS, blockAllThirdPartyRequests)
388         domainContentValues.put(USER_AGENT, userAgent)
389         domainContentValues.put(FONT_SIZE, fontSize)
390         domainContentValues.put(SWIPE_TO_REFRESH, swipeToRefresh)
391         domainContentValues.put(WEBVIEW_THEME, webViewTheme)
392         domainContentValues.put(WIDE_VIEWPORT, wideViewport)
393         domainContentValues.put(DISPLAY_IMAGES, displayImages)
394         domainContentValues.put(PINNED_SSL_CERTIFICATE, pinnedSslCertificate)
395         domainContentValues.put(PINNED_IP_ADDRESSES, pinnedIpAddresses)
396
397         // Get a writable database handle.
398         val domainsDatabase = this.writableDatabase
399
400         // Update the row for the specified database ID.
401         domainsDatabase.update(DOMAINS_TABLE, domainContentValues, "$ID = $databaseId", null)
402
403         // Close the database handle.
404         domainsDatabase.close()
405     }
406
407     fun updatePinnedSslCertificate(databaseId: Int, sslIssuedToCommonName: String, sslIssuedToOrganization: String, sslIssuedToOrganizationalUnit: String, sslIssuedByCommonName: String,
408                                    sslIssuedByOrganization: String, sslIssuedByOrganizationalUnit: String, sslStartDate: Long, sslEndDate: Long) {
409         // Instantiate a content values.
410         val pinnedSslCertificateContentValues = ContentValues()
411
412         // Add entries for each field in the certificate.
413         pinnedSslCertificateContentValues.put(SSL_ISSUED_TO_COMMON_NAME, sslIssuedToCommonName)
414         pinnedSslCertificateContentValues.put(SSL_ISSUED_TO_ORGANIZATION, sslIssuedToOrganization)
415         pinnedSslCertificateContentValues.put(SSL_ISSUED_TO_ORGANIZATIONAL_UNIT, sslIssuedToOrganizationalUnit)
416         pinnedSslCertificateContentValues.put(SSL_ISSUED_BY_COMMON_NAME, sslIssuedByCommonName)
417         pinnedSslCertificateContentValues.put(SSL_ISSUED_BY_ORGANIZATION, sslIssuedByOrganization)
418         pinnedSslCertificateContentValues.put(SSL_ISSUED_BY_ORGANIZATIONAL_UNIT, sslIssuedByOrganizationalUnit)
419         pinnedSslCertificateContentValues.put(SSL_START_DATE, sslStartDate)
420         pinnedSslCertificateContentValues.put(SSL_END_DATE, sslEndDate)
421
422         // Get a writable database handle.
423         val domainsDatabase = this.writableDatabase
424
425         // Update the row for the specified database ID.
426         domainsDatabase.update(DOMAINS_TABLE, pinnedSslCertificateContentValues, "$ID = $databaseId", null)
427
428         // Close the database handle.
429         domainsDatabase.close()
430     }
431
432     fun updatePinnedIpAddresses(databaseId: Int, ipAddresses: String) {
433         // Instantiate a content values.
434         val pinnedIpAddressesContentValues = ContentValues()
435
436         // Add the IP addresses to the content values.
437         pinnedIpAddressesContentValues.put(IP_ADDRESSES, ipAddresses)
438
439         // Get a writable database handle.
440         val domainsDatabase = this.writableDatabase
441
442         // Update the row for the database ID.
443         domainsDatabase.update(DOMAINS_TABLE, pinnedIpAddressesContentValues, "$ID = $databaseId", null)
444
445         // Close the database handle.
446         domainsDatabase.close()
447     }
448
449     fun deleteDomain(databaseId: Int) {
450         // Get a writable database handle.
451         val domainsDatabase = this.writableDatabase
452
453         // Delete the row for the specified database ID.
454         domainsDatabase.delete(DOMAINS_TABLE, "$ID = $databaseId", null)
455
456         // Close the database handle.
457         domainsDatabase.close()
458     }
459 }