2 * Copyright © 2017 Soren Stoutner <soren@stoutner.com>.
4 * This file is part of Privacy Browser <https://www.stoutner.com/privacy-browser>.
6 * Privacy Browser 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 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. 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.sqlite.SQLiteDatabase;
26 import android.database.sqlite.SQLiteOpenHelper;
28 public class DomainsDatabaseHelper extends SQLiteOpenHelper {
29 private static final int SCHEMA_VERSION = 3;
30 private static final String DOMAINS_DATABASE = "domains.db";
31 private static final String DOMAINS_TABLE = "domains";
33 public static final String _ID = "_id";
34 public static final String DOMAIN_NAME = "domainname";
35 public static final String ENABLE_JAVASCRIPT = "enablejavascript";
36 public static final String ENABLE_FIRST_PARTY_COOKIES = "enablefirstpartycookies";
37 public static final String ENABLE_THIRD_PARTY_COOKIES = "enablethirdpartycookies";
38 public static final String ENABLE_DOM_STORAGE = "enabledomstorage";
39 public static final String ENABLE_FORM_DATA = "enableformdata";
40 public static final String USER_AGENT = "useragent";
41 public static final String FONT_SIZE = "fontsize";
42 public static final String DISPLAY_IMAGES = "displayimages";
43 public static final String PINNED_SSL_CERTIFICATE = "pinnedsslcertificate";
44 public static final String SSL_ISSUED_TO_COMMON_NAME = "sslissuedtocommonname";
45 public static final String SSL_ISSUED_TO_ORGANIZATION = "sslissuedtoorganization";
46 public static final String SSL_ISSUED_TO_ORGANIZATIONAL_UNIT = "sslissuedtoorganizationalunit";
47 public static final String SSL_ISSUED_BY_COMMON_NAME = "sslissuedbycommonname";
48 public static final String SSL_ISSUED_BY_ORGANIZATION = "sslissuedbyorganization";
49 public static final String SSL_ISSUED_BY_ORGANIZATIONAL_UNIT = "sslissuedbyorganizationalunit";
50 public static final String SSL_START_DATE = "sslstartdate";
51 public static final String SSL_END_DATE = "sslenddate";
53 public static final int DISPLAY_WEBPAGE_IMAGES_SYSTEM_DEFAULT = 0;
54 public static final int DISPLAY_WEBPAGE_IMAGES_ENABLED = 1;
55 public static final int DISPLAY_WEBPAGE_IMAGES_DISABLED = 2;
57 // Initialize the database. The lint warnings for the unused parameters are suppressed.
58 public DomainsDatabaseHelper(Context context, @SuppressWarnings("UnusedParameters") String name, SQLiteDatabase.CursorFactory cursorFactory, @SuppressWarnings("UnusedParameters") int version) {
59 super(context, DOMAINS_DATABASE, cursorFactory, SCHEMA_VERSION);
63 public void onCreate(SQLiteDatabase domainsDatabase) {
64 // Setup the SQL string to create the `domains` table.
65 String CREATE_DOMAINS_TABLE = "CREATE TABLE " + DOMAINS_TABLE + " (" +
66 _ID + " INTEGER PRIMARY KEY, " +
67 DOMAIN_NAME + " TEXT, " +
68 ENABLE_JAVASCRIPT + " BOOLEAN, " +
69 ENABLE_FIRST_PARTY_COOKIES + " BOOLEAN, " +
70 ENABLE_THIRD_PARTY_COOKIES + " BOOLEAN, " +
71 ENABLE_DOM_STORAGE + " BOOLEAN, " +
72 ENABLE_FORM_DATA + " BOOLEAN, " +
73 USER_AGENT + " TEXT, " +
74 FONT_SIZE + " INTEGER, " +
75 DISPLAY_IMAGES + " INTEGER, " +
76 PINNED_SSL_CERTIFICATE + " BOOLEAN, " +
77 SSL_ISSUED_TO_COMMON_NAME + " TEXT, " +
78 SSL_ISSUED_TO_ORGANIZATION + " TEXT, " +
79 SSL_ISSUED_TO_ORGANIZATIONAL_UNIT + " TEXT, " +
80 SSL_ISSUED_BY_COMMON_NAME + " TEXT, " +
81 SSL_ISSUED_BY_ORGANIZATION + " TEXT, " +
82 SSL_ISSUED_BY_ORGANIZATIONAL_UNIT + " TEXT, " +
83 SSL_START_DATE + " INTEGER, " +
84 SSL_END_DATE + " INTEGER);";
87 domainsDatabase.execSQL(CREATE_DOMAINS_TABLE);
91 public void onUpgrade(SQLiteDatabase domainsDatabase, int oldVersion, int newVersion) {
92 // Upgrade `DOMAINS_TABLE`.
94 // Upgrade from `SCHEMA_VERSION` 1.
96 // Add the `DISPLAY_IMAGES` column.
97 domainsDatabase.execSQL("ALTER TABLE " + DOMAINS_TABLE + " ADD COLUMN " + DISPLAY_IMAGES + " INTEGER");
99 // Upgrade from `SCHEMA_VERSION` 2.
101 // Add the SSL certificate columns.
102 domainsDatabase.execSQL("ALTER TABLE " + DOMAINS_TABLE + " ADD COLUMN " + PINNED_SSL_CERTIFICATE + " BOOLEAN");
103 domainsDatabase.execSQL("ALTER TABLE " + DOMAINS_TABLE + " ADD COLUMN " + SSL_ISSUED_TO_COMMON_NAME + " TEXT");
104 domainsDatabase.execSQL("ALTER TABLE " + DOMAINS_TABLE + " ADD COLUMN " + SSL_ISSUED_TO_ORGANIZATION + " TEXT");
105 domainsDatabase.execSQL("ALTER TABLE " + DOMAINS_TABLE + " ADD COLUMN " + SSL_ISSUED_TO_ORGANIZATIONAL_UNIT + " TEXT");
106 domainsDatabase.execSQL("ALTER TABLE " + DOMAINS_TABLE + " ADD COLUMN " + SSL_ISSUED_BY_COMMON_NAME + " TEXT");
107 domainsDatabase.execSQL("ALTER TABLE " + DOMAINS_TABLE + " ADD COLUMN " + SSL_ISSUED_BY_ORGANIZATION + " TEXT");
108 domainsDatabase.execSQL("ALTER TABLE " + DOMAINS_TABLE + " ADD COLUMN " + SSL_ISSUED_BY_ORGANIZATIONAL_UNIT + " TEXT");
109 domainsDatabase.execSQL("ALTER TABLE " + DOMAINS_TABLE + " ADD COLUMN " + SSL_START_DATE + " INTEGER");
110 domainsDatabase.execSQL("ALTER TABLE " + DOMAINS_TABLE + " ADD COLUMN " + SSL_END_DATE + " INTEGER");
114 public Cursor getDomainNameCursorOrderedByDomain() {
115 // Get a readable database handle.
116 SQLiteDatabase domainsDatabase = this.getReadableDatabase();
118 // Get everything in `DOMAINS_TABLE` ordered by `DOMAIN_NAME`.
119 final String GET_CURSOR_ORDERED_BY_DOMAIN = "SELECT " + _ID + ", " + DOMAIN_NAME +
120 " FROM " + DOMAINS_TABLE +
121 " ORDER BY " + DOMAIN_NAME + " ASC";
123 // Return the results as a `Cursor`. The second argument is `null` because there are no `selectionArgs`. We can't close the `Cursor` because we need to use it in the parent activity.
124 return domainsDatabase.rawQuery(GET_CURSOR_ORDERED_BY_DOMAIN, null);
127 public Cursor getDomainNameCursorOrderedByDomainExcept(int databaseId) {
128 // Get a readable database handle.
129 SQLiteDatabase domainsDatabase = this.getReadableDatabase();
131 // Prepare the SQL statement to select all rows except that with `databaseId`.
132 final String GET_CURSOR_ORDERED_BY_DOMAIN_EXCEPT = "SELECT " + _ID + ", " + DOMAIN_NAME +
133 " FROM " + DOMAINS_TABLE +
134 " WHERE " + _ID + " IS NOT " + databaseId +
135 " ORDER BY " + DOMAIN_NAME + " ASC";
137 // Return the results as a `Cursor`. The second argument is `null` because there are no `selectionArgs`. We can't close the `Cursor` because we need to use it in the calling activity.
138 return domainsDatabase.rawQuery(GET_CURSOR_ORDERED_BY_DOMAIN_EXCEPT, null);
141 public Cursor getCursorForId(int databaseId) {
142 // Get a readable database handle.
143 SQLiteDatabase domainsDatabase = this.getReadableDatabase();
145 // Prepare the SQL statement to get the `Cursor` for `databaseId`.
146 final String GET_CURSOR_FOR_ID = "SELECT * FROM " + DOMAINS_TABLE +
147 " WHERE " + _ID + " = " + databaseId;
149 // Return the results as a `Cursor`. The second argument is `null` because there are no `selectionArgs`. We can't close the `Cursor` because we need to use it in the calling activity.
150 return domainsDatabase.rawQuery(GET_CURSOR_FOR_ID, null);
153 public Cursor getCursorForDomainName(String domainName) {
154 // Get a readable database handle.
155 SQLiteDatabase domainsDatabase = this.getReadableDatabase();
157 // Prepare the SQL statement to get the `Cursor` for `domainName`.
158 final String GET_CURSOR_FOR_DOMAIN_NAME = "SELECT * FROM " + DOMAINS_TABLE +
159 " WHERE " + DOMAIN_NAME + " = " + "\"" + domainName + "\"";
161 // Return the results as a `Cursor`. The second argument is `null` because there are no `selectionArgs`. We can't close the `Cursor` because we need to us it in the calling activity.
162 return domainsDatabase.rawQuery(GET_CURSOR_FOR_DOMAIN_NAME, null);
165 public int addDomain(String domainName) {
166 // Store the domain data in a `ContentValues`.
167 ContentValues domainContentValues = new ContentValues();
169 // Create entries for each field in the database. The ID is created automatically.
170 domainContentValues.put(DOMAIN_NAME, domainName);
171 domainContentValues.put(ENABLE_JAVASCRIPT, false);
172 domainContentValues.put(ENABLE_FIRST_PARTY_COOKIES, false);
173 domainContentValues.put(ENABLE_THIRD_PARTY_COOKIES, false);
174 domainContentValues.put(ENABLE_DOM_STORAGE, false);
175 domainContentValues.put(ENABLE_FORM_DATA, false);
176 domainContentValues.put(USER_AGENT, "System default user agent");
177 domainContentValues.put(FONT_SIZE, 0);
178 domainContentValues.put(DISPLAY_IMAGES, 0);
180 // Get a writable database handle.
181 SQLiteDatabase domainsDatabase = this.getWritableDatabase();
183 // 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.
184 int newDomainDatabaseId = (int) domainsDatabase.insert(DOMAINS_TABLE, null, domainContentValues);
186 // Close the database handle.
187 domainsDatabase.close();
189 return newDomainDatabaseId;
192 public void updateDomainExceptCertificate(int databaseId, String domainName, boolean javaScriptEnabled, boolean firstPartyCookiesEnabled, boolean thirdPartyCookiesEnabled, boolean domStorageEnabled, boolean formDataEnabled, String userAgent, int fontSize,
193 int displayImages, boolean pinnedSslCertificate) {
194 // Store the domain data in a `ContentValues`.
195 ContentValues domainContentValues = new ContentValues();
197 // Add entries for each field in the database.
198 domainContentValues.put(DOMAIN_NAME, domainName);
199 domainContentValues.put(ENABLE_JAVASCRIPT, javaScriptEnabled);
200 domainContentValues.put(ENABLE_FIRST_PARTY_COOKIES, firstPartyCookiesEnabled);
201 domainContentValues.put(ENABLE_THIRD_PARTY_COOKIES, thirdPartyCookiesEnabled);
202 domainContentValues.put(ENABLE_DOM_STORAGE, domStorageEnabled);
203 domainContentValues.put(ENABLE_FORM_DATA, formDataEnabled);
204 domainContentValues.put(USER_AGENT, userAgent);
205 domainContentValues.put(FONT_SIZE, fontSize);
206 domainContentValues.put(DISPLAY_IMAGES, displayImages);
207 domainContentValues.put(PINNED_SSL_CERTIFICATE, pinnedSslCertificate);
209 // Get a writable database handle.
210 SQLiteDatabase domainsDatabase = this.getWritableDatabase();
212 // Update the row for `databaseId`. The last argument is `null` because there are no `whereArgs`.
213 domainsDatabase.update(DOMAINS_TABLE, domainContentValues, _ID + " = " + databaseId, null);
215 // Close the database handle.
216 domainsDatabase.close();
219 public void updateDomainWithCertificate(int databaseId, String domainName, boolean javaScriptEnabled, boolean firstPartyCookiesEnabled, boolean thirdPartyCookiesEnabled, boolean domStorageEnabled, boolean formDataEnabled, String userAgent, int fontSize,
220 int displayImages, boolean pinnedSslCertificate, String sslIssuedToCommonName, String sslIssuedToOrganization, String sslIssuedToOrganizationalUnit, String sslIssuedByCommonName, String sslIssuedByOrganization,
221 String sslIssuedByOrganizationalUnit, long sslStartDate, long sslEndDate) {
222 // Store the domain data in a `ContentValues`.
223 ContentValues domainContentValues = new ContentValues();
225 // Add entries for each field in the database.
226 domainContentValues.put(DOMAIN_NAME, domainName);
227 domainContentValues.put(ENABLE_JAVASCRIPT, javaScriptEnabled);
228 domainContentValues.put(ENABLE_FIRST_PARTY_COOKIES, firstPartyCookiesEnabled);
229 domainContentValues.put(ENABLE_THIRD_PARTY_COOKIES, thirdPartyCookiesEnabled);
230 domainContentValues.put(ENABLE_DOM_STORAGE, domStorageEnabled);
231 domainContentValues.put(ENABLE_FORM_DATA, formDataEnabled);
232 domainContentValues.put(USER_AGENT, userAgent);
233 domainContentValues.put(FONT_SIZE, fontSize);
234 domainContentValues.put(DISPLAY_IMAGES, displayImages);
235 domainContentValues.put(PINNED_SSL_CERTIFICATE, pinnedSslCertificate);
236 domainContentValues.put(SSL_ISSUED_TO_COMMON_NAME, sslIssuedToCommonName);
237 domainContentValues.put(SSL_ISSUED_TO_ORGANIZATION, sslIssuedToOrganization);
238 domainContentValues.put(SSL_ISSUED_TO_ORGANIZATIONAL_UNIT, sslIssuedToOrganizationalUnit);
239 domainContentValues.put(SSL_ISSUED_BY_COMMON_NAME, sslIssuedByCommonName);
240 domainContentValues.put(SSL_ISSUED_BY_ORGANIZATION, sslIssuedByOrganization);
241 domainContentValues.put(SSL_ISSUED_BY_ORGANIZATIONAL_UNIT, sslIssuedByOrganizationalUnit);
242 domainContentValues.put(SSL_START_DATE, sslStartDate);
243 domainContentValues.put(SSL_END_DATE, sslEndDate);
245 // Get a writable database handle.
246 SQLiteDatabase domainsDatabase = this.getWritableDatabase();
248 // Update the row for `databaseId`. The last argument is `null` because there are no `whereArgs`.
249 domainsDatabase.update(DOMAINS_TABLE, domainContentValues, _ID + " = " + databaseId, null);
251 // Close the database handle.
252 domainsDatabase.close();
255 public void updateCertificate(int databaseId, String sslIssuedToCommonName, String sslIssuedToOrganization, String sslIssuedToOrganizationalUnit, String sslIssuedByCommonName, String sslIssuedByOrganization, String sslIssuedByOrganizationalUnit,
256 long sslStartDate, long sslEndDate) {
257 // Store the domain data in a `ContentValues`.
258 ContentValues domainContentValues = new ContentValues();
260 // Add entries for each field in the certificate.
261 domainContentValues.put(SSL_ISSUED_TO_COMMON_NAME, sslIssuedToCommonName);
262 domainContentValues.put(SSL_ISSUED_TO_ORGANIZATION, sslIssuedToOrganization);
263 domainContentValues.put(SSL_ISSUED_TO_ORGANIZATIONAL_UNIT, sslIssuedToOrganizationalUnit);
264 domainContentValues.put(SSL_ISSUED_BY_COMMON_NAME, sslIssuedByCommonName);
265 domainContentValues.put(SSL_ISSUED_BY_ORGANIZATION, sslIssuedByOrganization);
266 domainContentValues.put(SSL_ISSUED_BY_ORGANIZATIONAL_UNIT, sslIssuedByOrganizationalUnit);
267 domainContentValues.put(SSL_START_DATE, sslStartDate);
268 domainContentValues.put(SSL_END_DATE, sslEndDate);
270 // Get a writable database handle.
271 SQLiteDatabase domainsDatabase = this.getWritableDatabase();
273 // Update the row for `databaseId`. The last argument is `null` because there are no `whereArgs`.
274 domainsDatabase.update(DOMAINS_TABLE, domainContentValues, _ID + " = " + databaseId, null);
276 // Close the database handle.
277 domainsDatabase.close();
280 public void deleteDomain(int databaseId) {
281 // Get a writable database handle.
282 SQLiteDatabase domainsDatabase = this.getWritableDatabase();
284 // Delete the row for `databaseId`. The last argument is `null` because we don't need additional parameters.
285 domainsDatabase.delete(DOMAINS_TABLE, _ID + " = " + databaseId, null);
287 // Close the database handle.
288 domainsDatabase.close();