]> gitweb.stoutner.com Git - PrivacyBrowserAndroid.git/blob - app/src/main/java/com/stoutner/privacybrowser/helpers/DomainsDatabaseHelper.java
2455fb3295d0b0fdb82529cafbcc3c39640ade6d
[PrivacyBrowserAndroid.git] / app / src / main / java / com / stoutner / privacybrowser / helpers / DomainsDatabaseHelper.java
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.content.SharedPreferences;
25 import android.database.Cursor;
26 import android.database.sqlite.SQLiteDatabase;
27 import android.database.sqlite.SQLiteOpenHelper;
28 import android.preference.PreferenceManager;
29
30 import com.stoutner.privacybrowser.R;
31
32 public class DomainsDatabaseHelper extends SQLiteOpenHelper {
33     private static final int SCHEMA_VERSION = 13;
34     static final String DOMAINS_DATABASE = "domains.db";
35     static final String DOMAINS_TABLE = "domains";
36
37     public static final String _ID = "_id";
38     public static final String DOMAIN_NAME = "domainname";
39     public static final String ENABLE_JAVASCRIPT = "enablejavascript";
40     public static final String COOKIES = "cookies";
41     public static final String ENABLE_DOM_STORAGE = "enabledomstorage";
42     public static final String ENABLE_FORM_DATA = "enableformdata";  // Form data can be removed once the minimum API >= 26.
43     public static final String ENABLE_EASYLIST = "enableeasylist";
44     public static final String ENABLE_EASYPRIVACY = "enableeasyprivacy";
45     public static final String ENABLE_FANBOYS_ANNOYANCE_LIST = "enablefanboysannoyancelist";
46     public static final String ENABLE_FANBOYS_SOCIAL_BLOCKING_LIST = "enablefanboyssocialblockinglist";
47     public static final String ULTRALIST = "ultralist";
48     public static final String ENABLE_ULTRAPRIVACY = "enableultraprivacy";
49     public static final String BLOCK_ALL_THIRD_PARTY_REQUESTS = "blockallthirdpartyrequests";
50     public static final String USER_AGENT = "useragent";
51     public static final String FONT_SIZE = "fontsize";
52     public static final String SWIPE_TO_REFRESH = "swipetorefresh";
53     public static final String WEBVIEW_THEME = "webview_theme";
54     public static final String WIDE_VIEWPORT = "wide_viewport";
55     public static final String DISPLAY_IMAGES = "displayimages";
56     public static final String PINNED_SSL_CERTIFICATE = "pinnedsslcertificate";
57     public static final String SSL_ISSUED_TO_COMMON_NAME = "sslissuedtocommonname";
58     public static final String SSL_ISSUED_TO_ORGANIZATION = "sslissuedtoorganization";
59     public static final String SSL_ISSUED_TO_ORGANIZATIONAL_UNIT = "sslissuedtoorganizationalunit";
60     public static final String SSL_ISSUED_BY_COMMON_NAME = "sslissuedbycommonname";
61     public static final String SSL_ISSUED_BY_ORGANIZATION = "sslissuedbyorganization";
62     public static final String SSL_ISSUED_BY_ORGANIZATIONAL_UNIT = "sslissuedbyorganizationalunit";
63     public static final String SSL_START_DATE = "sslstartdate";
64     public static final String SSL_END_DATE = "sslenddate";
65     public static final String PINNED_IP_ADDRESSES = "pinned_ip_addresses";
66     public static final String IP_ADDRESSES = "ip_addresses";
67
68     // Spinner constants.
69     public static final int SYSTEM_DEFAULT = 0;
70     public static final int ENABLED = 1;
71     public static final int DISABLED = 2;
72     public static final int LIGHT_THEME = 1;
73     public static final int DARK_THEME = 2;
74
75     static final String CREATE_DOMAINS_TABLE = "CREATE TABLE " + DOMAINS_TABLE + " (" +
76             _ID + " INTEGER PRIMARY KEY, " +
77             DOMAIN_NAME + " TEXT, " +
78             ENABLE_JAVASCRIPT + " BOOLEAN, " +
79             COOKIES + " BOOLEAN, " +
80             ENABLE_DOM_STORAGE + " BOOLEAN, " +
81             ENABLE_FORM_DATA + " BOOLEAN, " +
82             ENABLE_EASYLIST + " BOOLEAN, " +
83             ENABLE_EASYPRIVACY + " BOOLEAN, " +
84             ENABLE_FANBOYS_ANNOYANCE_LIST + " BOOLEAN, " +
85             ENABLE_FANBOYS_SOCIAL_BLOCKING_LIST + " BOOLEAN, " +
86             ULTRALIST + " BOOLEAN, " +
87             ENABLE_ULTRAPRIVACY + " BOOLEAN, " +
88             BLOCK_ALL_THIRD_PARTY_REQUESTS + " BOOLEAN, " +
89             USER_AGENT + " TEXT, " +
90             FONT_SIZE + " INTEGER, " +
91             SWIPE_TO_REFRESH + " INTEGER, " +
92             WEBVIEW_THEME + " INTEGER, " +
93             WIDE_VIEWPORT + " INTEGER, " +
94             DISPLAY_IMAGES + " INTEGER, " +
95             PINNED_SSL_CERTIFICATE + " BOOLEAN, " +
96             SSL_ISSUED_TO_COMMON_NAME + " TEXT, " +
97             SSL_ISSUED_TO_ORGANIZATION + " TEXT, " +
98             SSL_ISSUED_TO_ORGANIZATIONAL_UNIT + " TEXT, " +
99             SSL_ISSUED_BY_COMMON_NAME + " TEXT, " +
100             SSL_ISSUED_BY_ORGANIZATION + " TEXT, " +
101             SSL_ISSUED_BY_ORGANIZATIONAL_UNIT + " TEXT, " +
102             SSL_START_DATE + " INTEGER, " +
103             SSL_END_DATE + " INTEGER, " +
104             PINNED_IP_ADDRESSES + " BOOLEAN, " +
105             IP_ADDRESSES + " TEXT)";
106
107     private final Context appContext;
108
109     // Initialize the database.  The lint warnings for the unused parameters are suppressed.
110     public DomainsDatabaseHelper(Context context, @SuppressWarnings("UnusedParameters") String name, SQLiteDatabase.CursorFactory cursorFactory, @SuppressWarnings("UnusedParameters") int version) {
111         super(context, DOMAINS_DATABASE, cursorFactory, SCHEMA_VERSION);
112
113         // Store a handle for the context.
114         appContext = context;
115     }
116
117     @Override
118     public void onCreate(SQLiteDatabase domainsDatabase) {
119         // Create the domains table.
120         domainsDatabase.execSQL(CREATE_DOMAINS_TABLE);
121     }
122
123     @Override
124     public void onUpgrade(SQLiteDatabase domainsDatabase, int oldVersion, int newVersion) {
125         // Upgrade the database table.
126         switch (oldVersion) {
127             // Upgrade from schema version 1.
128             case 1:
129                 // Add the display images column.
130                 domainsDatabase.execSQL("ALTER TABLE " + DOMAINS_TABLE + " ADD COLUMN " + DISPLAY_IMAGES + " INTEGER");
131
132             // Upgrade from schema version 2.
133             case 2:
134                 //  Add the SSL certificate columns.
135                 domainsDatabase.execSQL("ALTER TABLE " + DOMAINS_TABLE + " ADD COLUMN " + PINNED_SSL_CERTIFICATE + " BOOLEAN");
136                 domainsDatabase.execSQL("ALTER TABLE " + DOMAINS_TABLE + " ADD COLUMN " + SSL_ISSUED_TO_COMMON_NAME + " TEXT");
137                 domainsDatabase.execSQL("ALTER TABLE " + DOMAINS_TABLE + " ADD COLUMN " + SSL_ISSUED_TO_ORGANIZATION + " TEXT");
138                 domainsDatabase.execSQL("ALTER TABLE " + DOMAINS_TABLE + " ADD COLUMN " + SSL_ISSUED_TO_ORGANIZATIONAL_UNIT + " TEXT");
139                 domainsDatabase.execSQL("ALTER TABLE " + DOMAINS_TABLE + " ADD COLUMN " + SSL_ISSUED_BY_COMMON_NAME + " TEXT");
140                 domainsDatabase.execSQL("ALTER TABLE " + DOMAINS_TABLE + " ADD COLUMN " + SSL_ISSUED_BY_ORGANIZATION + " TEXT");
141                 domainsDatabase.execSQL("ALTER TABLE " + DOMAINS_TABLE + " ADD COLUMN " + SSL_ISSUED_BY_ORGANIZATIONAL_UNIT + " TEXT");
142                 domainsDatabase.execSQL("ALTER TABLE " + DOMAINS_TABLE + " ADD COLUMN " + SSL_START_DATE + " INTEGER");
143                 domainsDatabase.execSQL("ALTER TABLE " + DOMAINS_TABLE + " ADD COLUMN " + SSL_END_DATE + " INTEGER");
144
145             // Upgrade from schema version 3.
146             case 3:
147                 // Add the night mode column.
148                 domainsDatabase.execSQL("ALTER TABLE " + DOMAINS_TABLE + " ADD COLUMN nightmode INTEGER");
149
150             // Upgrade from schema version 4.
151             case 4:
152                 // Add the block lists columns.
153                 domainsDatabase.execSQL("ALTER TABLE " + DOMAINS_TABLE + " ADD COLUMN " + ENABLE_EASYLIST + " BOOLEAN");
154                 domainsDatabase.execSQL("ALTER TABLE " + DOMAINS_TABLE + " ADD COLUMN " + ENABLE_EASYPRIVACY + " BOOLEAN");
155                 domainsDatabase.execSQL("ALTER TABLE " + DOMAINS_TABLE + " ADD COLUMN " + ENABLE_FANBOYS_ANNOYANCE_LIST + " BOOLEAN");
156                 domainsDatabase.execSQL("ALTER TABLE " + DOMAINS_TABLE + " ADD COLUMN " + ENABLE_FANBOYS_SOCIAL_BLOCKING_LIST + " BOOLEAN");
157
158                 // Get a handle for the shared preference.
159                 SharedPreferences sharedPreferences = PreferenceManager.getDefaultSharedPreferences(appContext);
160
161                 // Get the default block list settings.
162                 boolean easyListEnabled = sharedPreferences.getBoolean("easylist", true);
163                 boolean easyPrivacyEnabled = sharedPreferences.getBoolean("easyprivacy", true);
164                 boolean fanboyAnnoyanceListEnabled = sharedPreferences.getBoolean("fanboys_annoyance_list", true);
165                 boolean fanboySocialBlockingListEnabled = sharedPreferences.getBoolean("fanboys_social_blocking_list", true);
166
167                 // Set EasyList for existing rows according to the current system-wide default.
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             // Upgrade from schema version 5.
196             case 5:
197                 // 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.
198                 domainsDatabase.execSQL("ALTER TABLE " + DOMAINS_TABLE + " ADD COLUMN " + SWIPE_TO_REFRESH + " INTEGER");
199
200             // Upgrade from schema version 6.
201             case 6:
202                 // 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.
203                 domainsDatabase.execSQL("ALTER TABLE " + DOMAINS_TABLE + " ADD COLUMN " + BLOCK_ALL_THIRD_PARTY_REQUESTS + " BOOLEAN");
204
205             // Upgrade from schema version 7.
206             case 7:
207                 // Add the UltraPrivacy column.
208                 domainsDatabase.execSQL("ALTER TABLE " + DOMAINS_TABLE + " ADD COLUMN " + ENABLE_ULTRAPRIVACY + " BOOLEAN");
209
210                 // Enable it for all existing rows.
211                 domainsDatabase.execSQL("UPDATE " + DOMAINS_TABLE + " SET " + ENABLE_ULTRAPRIVACY + " = " + 1);
212
213             // Upgrade from schema version 8.
214             case 8:
215                 // Add the pinned IP addresses columns.  These default to `0` and `""`, so a separate step isn't needed to populate the columns.
216                 domainsDatabase.execSQL("ALTER TABLE " + DOMAINS_TABLE + " ADD COLUMN " + PINNED_IP_ADDRESSES + " BOOLEAN");
217                 domainsDatabase.execSQL("ALTER TABLE " + DOMAINS_TABLE + " ADD COLUMN " + IP_ADDRESSES + " TEXT");
218
219             // Upgrade from schema version 9.
220             case 9:
221                 // Add the wide viewport column.  This defaults to `0`, which is `System default`, so a separate step isn't needed to populate the column.
222                 domainsDatabase.execSQL("ALTER TABLE " + DOMAINS_TABLE + " ADD COLUMN " + WIDE_VIEWPORT + " INTEGER");
223
224             // Upgrade from schema version 10.
225             case 10:
226                 // Add the UltraList column.
227                 domainsDatabase.execSQL("ALTER TABLE " + DOMAINS_TABLE + " ADD COLUMN " + ULTRALIST + " BOOLEAN");
228
229                 // Enable it for all existing rows.
230                 domainsDatabase.execSQL("UPDATE " + DOMAINS_TABLE + " SET " + ULTRALIST + " = " + 1);
231
232             // Upgrade from schema version 11.
233             case 11:
234                 // Add the WebView theme column.  This defaults to `0`, which is `System default`, so a separate step isn't needed to populate the column.
235                 domainsDatabase.execSQL("ALTER TABLE " + DOMAINS_TABLE + " ADD COLUMN " + WEBVIEW_THEME + " INTEGER");
236
237                 // SQLite amazingly doesn't include an easy command to delete a column.  <https://www.sqlite.org/lang_altertable.html>
238                 // 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.
239
240             // Upgrade from schema version 12.
241             case 12:
242                 // Add the cookies column.
243                 domainsDatabase.execSQL("ALTER TABLE " + DOMAINS_TABLE + " ADD COLUMN " + COOKIES + " BOOLEAN");
244
245                 // Copy the data from the old column to the new one.
246                 domainsDatabase.execSQL("UPDATE " + DOMAINS_TABLE + " SET " + COOKIES + " = enablefirstpartycookies");
247         }
248     }
249
250     Cursor getCompleteCursorOrderedByDomain() {
251         // Get a readable database handle.
252         SQLiteDatabase domainsDatabase = this.getReadableDatabase();
253
254         // Return everything in the domains table ordered by the domain name.  The second argument is `null` because there are no `selectionArgs`.
255         return domainsDatabase.rawQuery("SELECT * FROM " + DOMAINS_TABLE + " ORDER BY " + DOMAIN_NAME + " ASC", null);
256     }
257
258     public Cursor getDomainNameCursorOrderedByDomain() {
259         // Get a readable database handle.
260         SQLiteDatabase domainsDatabase = this.getReadableDatabase();
261
262         // Get everything in the domains table ordered by the domain name.
263         String GET_CURSOR_ORDERED_BY_DOMAIN = "SELECT " + _ID + ", " + DOMAIN_NAME +
264                 " FROM " + DOMAINS_TABLE +
265                 " ORDER BY " + DOMAIN_NAME + " ASC";
266
267         // Return the results as a `Cursor`.  The second argument is `null` because there are no `selectionArgs`.  The cursor can't be closed because it is needed in the calling activity.
268         return domainsDatabase.rawQuery(GET_CURSOR_ORDERED_BY_DOMAIN, null);
269     }
270
271     public Cursor getDomainNameCursorOrderedByDomainExcept(int databaseId) {
272         // Get a readable database handle.
273         SQLiteDatabase domainsDatabase = this.getReadableDatabase();
274
275         // Prepare the SQL statement to select all rows except that with `databaseId`.
276         String GET_CURSOR_ORDERED_BY_DOMAIN_EXCEPT = "SELECT " + _ID + ", " + DOMAIN_NAME +
277                 " FROM " + DOMAINS_TABLE +
278                 " WHERE " + _ID + " IS NOT " + databaseId +
279                 " ORDER BY " + DOMAIN_NAME + " ASC";
280
281         // Return the results as a `Cursor`.  The second argument is `null` because there are no `selectionArgs`.  The cursor can't be closed because it is needed in the calling activity.
282         return domainsDatabase.rawQuery(GET_CURSOR_ORDERED_BY_DOMAIN_EXCEPT, null);
283     }
284
285     public Cursor getCursorForId(int databaseId) {
286         // Get a readable database handle.
287         SQLiteDatabase domainsDatabase = this.getReadableDatabase();
288
289         // Prepare the SQL statement to get the `Cursor` for `databaseId`.
290         String GET_CURSOR_FOR_ID = "SELECT * FROM " + DOMAINS_TABLE +
291                 " WHERE " + _ID + " = " + databaseId;
292
293         // Return the results as a `Cursor`.  The second argument is `null` because there are no `selectionArgs`.  The cursor can't be closed because it is needed in the calling activity.
294         return domainsDatabase.rawQuery(GET_CURSOR_FOR_ID, null);
295     }
296
297     public Cursor getCursorForDomainName(String domainName) {
298         // Get a readable database handle.
299         SQLiteDatabase domainsDatabase = this.getReadableDatabase();
300
301         // Return a cursor for the requested domain name.
302         return domainsDatabase.query(DOMAINS_TABLE, null, DOMAIN_NAME + " = " + "\"" + domainName + "\"", null, null, null, null);
303
304     }
305
306     public int addDomain(String domainName) {
307         // Store the domain data in a `ContentValues`.
308         ContentValues domainContentValues = new ContentValues();
309
310         // Get a handle for the shared preference.
311         SharedPreferences sharedPreferences = PreferenceManager.getDefaultSharedPreferences(appContext);
312
313         // Get the default settings.
314         boolean javaScript = sharedPreferences.getBoolean("javascript", false);
315         boolean cookies = sharedPreferences.getBoolean(appContext.getString(R.string.cookies_key), false);
316         boolean domStorage = sharedPreferences.getBoolean("dom_storage", false);
317         boolean saveFormData = sharedPreferences.getBoolean("save_form_data", false);  // Form data can be removed once the minimum API >= 26.
318         boolean easyList = sharedPreferences.getBoolean("easylist", true);
319         boolean easyPrivacy = sharedPreferences.getBoolean("easyprivacy", true);
320         boolean fanboyAnnoyanceList = sharedPreferences.getBoolean("fanboys_annoyance_list", true);
321         boolean fanboySocialBlockingList = sharedPreferences.getBoolean("fanboys_social_blocking_list", true);
322         boolean ultraList = sharedPreferences.getBoolean("ultralist", true);
323         boolean ultraPrivacy = sharedPreferences.getBoolean("ultraprivacy", true);
324         boolean blockAllThirdPartyRequests = sharedPreferences.getBoolean("block_all_third_party_requests", false);
325
326         // Create entries for the database fields.  The ID is created automatically.  The pinned SSL certificate information is not created unless added by the user.
327         domainContentValues.put(DOMAIN_NAME, domainName);
328         domainContentValues.put(ENABLE_JAVASCRIPT, javaScript);
329         domainContentValues.put(COOKIES, cookies);
330         domainContentValues.put(ENABLE_DOM_STORAGE, domStorage);
331         domainContentValues.put(ENABLE_FORM_DATA, saveFormData);  // Form data can be removed once the minimum API >= 26.
332         domainContentValues.put(ENABLE_EASYLIST, easyList);
333         domainContentValues.put(ENABLE_EASYPRIVACY, easyPrivacy);
334         domainContentValues.put(ENABLE_FANBOYS_ANNOYANCE_LIST, fanboyAnnoyanceList);
335         domainContentValues.put(ENABLE_FANBOYS_SOCIAL_BLOCKING_LIST, fanboySocialBlockingList);
336         domainContentValues.put(ULTRALIST, ultraList);
337         domainContentValues.put(ENABLE_ULTRAPRIVACY, ultraPrivacy);
338         domainContentValues.put(BLOCK_ALL_THIRD_PARTY_REQUESTS, blockAllThirdPartyRequests);
339         domainContentValues.put(USER_AGENT, "System default user agent");
340         domainContentValues.put(FONT_SIZE, 0);
341         domainContentValues.put(SWIPE_TO_REFRESH, 0);
342         domainContentValues.put(WEBVIEW_THEME, 0);
343         domainContentValues.put(WIDE_VIEWPORT, 0);
344         domainContentValues.put(DISPLAY_IMAGES, 0);
345
346         // Get a writable database handle.
347         SQLiteDatabase domainsDatabase = this.getWritableDatabase();
348
349         // Insert a new row and store the resulting database ID.  The second argument is `null`, which makes it so that a completely null row cannot be created.
350         int newDomainDatabaseId  = (int) domainsDatabase.insert(DOMAINS_TABLE, null, domainContentValues);
351
352         // Close the database handle.
353         domainsDatabase.close();
354
355         // Return the new domain database ID.
356         return newDomainDatabaseId;
357     }
358
359     void addDomain(ContentValues contentValues) {
360         // Get a writable database handle.
361         SQLiteDatabase domainsDatabase = this.getWritableDatabase();
362
363         // Add the new domain.
364         domainsDatabase.insert(DOMAINS_TABLE, null, contentValues);
365
366         // Close the database handle.
367         domainsDatabase.close();
368     }
369
370     public void updateDomain(int databaseId, String domainName, boolean javaScript, boolean cookies, boolean domStorage, boolean formData, boolean easyList, boolean easyPrivacy, boolean fanboysAnnoyance,
371                              boolean fanboysSocialBlocking, boolean ultraList, boolean ultraPrivacy, boolean blockAllThirdPartyRequests, String userAgent, int fontSize, int swipeToRefresh, int webViewTheme,
372                              int wideViewport, int displayImages, boolean pinnedSslCertificate, boolean pinnedIpAddresses) {
373
374         // Store the domain data in a content values.
375         ContentValues domainContentValues = new ContentValues();
376
377         // Add entries for each field in the database.
378         domainContentValues.put(DOMAIN_NAME, domainName);
379         domainContentValues.put(ENABLE_JAVASCRIPT, javaScript);
380         domainContentValues.put(COOKIES, cookies);
381         domainContentValues.put(ENABLE_DOM_STORAGE, domStorage);
382         domainContentValues.put(ENABLE_FORM_DATA, formData);  // Form data can be removed once the minimum API >= 26.
383         domainContentValues.put(ENABLE_EASYLIST, easyList);
384         domainContentValues.put(ENABLE_EASYPRIVACY, easyPrivacy);
385         domainContentValues.put(ENABLE_FANBOYS_ANNOYANCE_LIST, fanboysAnnoyance);
386         domainContentValues.put(ENABLE_FANBOYS_SOCIAL_BLOCKING_LIST, fanboysSocialBlocking);
387         domainContentValues.put(ULTRALIST, ultraList);
388         domainContentValues.put(ENABLE_ULTRAPRIVACY, ultraPrivacy);
389         domainContentValues.put(BLOCK_ALL_THIRD_PARTY_REQUESTS, blockAllThirdPartyRequests);
390         domainContentValues.put(USER_AGENT, userAgent);
391         domainContentValues.put(FONT_SIZE, fontSize);
392         domainContentValues.put(SWIPE_TO_REFRESH, swipeToRefresh);
393         domainContentValues.put(WEBVIEW_THEME, webViewTheme);
394         domainContentValues.put(WIDE_VIEWPORT, wideViewport);
395         domainContentValues.put(DISPLAY_IMAGES, displayImages);
396         domainContentValues.put(PINNED_SSL_CERTIFICATE, pinnedSslCertificate);
397         domainContentValues.put(PINNED_IP_ADDRESSES, pinnedIpAddresses);
398
399         // Get a writable database handle.
400         SQLiteDatabase domainsDatabase = this.getWritableDatabase();
401
402         // Update the row for `databaseId`.  The last argument is `null` because there are no `whereArgs`.
403         domainsDatabase.update(DOMAINS_TABLE, domainContentValues, _ID + " = " + databaseId, null);
404
405         // Close the database handle.
406         domainsDatabase.close();
407     }
408
409     public void updatePinnedSslCertificate(int databaseId, String sslIssuedToCommonName, String sslIssuedToOrganization, String sslIssuedToOrganizationalUnit, String sslIssuedByCommonName,
410                                      String sslIssuedByOrganization, String sslIssuedByOrganizationalUnit, long sslStartDate, long sslEndDate) {
411
412         // Store the pinned SSL certificate in a content values.
413         ContentValues pinnedSslCertificateContentValues = new ContentValues();
414
415         // Add entries for each field in the certificate.
416         pinnedSslCertificateContentValues.put(SSL_ISSUED_TO_COMMON_NAME, sslIssuedToCommonName);
417         pinnedSslCertificateContentValues.put(SSL_ISSUED_TO_ORGANIZATION, sslIssuedToOrganization);
418         pinnedSslCertificateContentValues.put(SSL_ISSUED_TO_ORGANIZATIONAL_UNIT, sslIssuedToOrganizationalUnit);
419         pinnedSslCertificateContentValues.put(SSL_ISSUED_BY_COMMON_NAME, sslIssuedByCommonName);
420         pinnedSslCertificateContentValues.put(SSL_ISSUED_BY_ORGANIZATION, sslIssuedByOrganization);
421         pinnedSslCertificateContentValues.put(SSL_ISSUED_BY_ORGANIZATIONAL_UNIT, sslIssuedByOrganizationalUnit);
422         pinnedSslCertificateContentValues.put(SSL_START_DATE, sslStartDate);
423         pinnedSslCertificateContentValues.put(SSL_END_DATE, sslEndDate);
424
425         // Get a writable database handle.
426         SQLiteDatabase domainsDatabase = this.getWritableDatabase();
427
428         // Update the row for database ID.
429         domainsDatabase.update(DOMAINS_TABLE, pinnedSslCertificateContentValues, _ID + " = " + databaseId, null);
430
431         // Close the database handle.
432         domainsDatabase.close();
433     }
434
435     public void updatePinnedIpAddresses(int databaseId, String ipAddresses) {
436         // Store the pinned IP addresses in a content values.
437         ContentValues pinnedIpAddressesContentValues = new ContentValues();
438
439         // Add the IP addresses to the content values.
440         pinnedIpAddressesContentValues.put(IP_ADDRESSES, ipAddresses);
441
442         // Get a writable database handle.
443         SQLiteDatabase domainsDatabase = this.getWritableDatabase();
444
445         // Update the row for the database ID.
446         domainsDatabase.update(DOMAINS_TABLE, pinnedIpAddressesContentValues, _ID + " = " + databaseId, null);
447
448         // Close the database handle.
449         domainsDatabase.close();
450     }
451
452     public void deleteDomain(int databaseId) {
453         // Get a writable database handle.
454         SQLiteDatabase domainsDatabase = this.getWritableDatabase();
455
456         // Delete the row for `databaseId`.  The last argument is `null` because we don't need additional parameters.
457         domainsDatabase.delete(DOMAINS_TABLE, _ID + " = " + databaseId, null);
458
459         // Close the database handle.
460         domainsDatabase.close();
461     }
462 }