]> gitweb.stoutner.com Git - PrivacyBrowserAndroid.git/blob - app/src/main/java/com/stoutner/privacybrowser/helpers/ImportExportDatabaseHelper.java
Add import and export of settings. https://redmine.stoutner.com/issues/23
[PrivacyBrowserAndroid.git] / app / src / main / java / com / stoutner / privacybrowser / helpers / ImportExportDatabaseHelper.java
1 /*
2  * Copyright © 2018 Soren Stoutner <soren@stoutner.com>.
3  *
4  * This file is part of Privacy Browser <https://www.stoutner.com/privacy-browser>.
5  *
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.
10  *
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.
15  *
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/>.
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.preference.PreferenceManager;
28
29 import java.io.File;
30
31 public class ImportExportDatabaseHelper {
32     public static final String EXPORT_SUCCESSFUL = "Export Successful";
33     public static final String IMPORT_SUCCESSFUL = "Import Successful";
34
35     private static final int SCHEMA_VERSION = 1;
36     private static final String PREFERENCES_TABLE = "preferences";
37
38     // The preferences constants.
39     private static final String _ID = "_id";
40     private static final String JAVASCRIPT = "javascript";
41     private static final String FIRST_PARTY_COOKIES = "first_party_cookies";
42     private static final String THIRD_PARTY_COOKIES = "third_party_cookies";
43     private static final String DOM_STORAGE = "dom_storage";
44     private static final String SAVE_FORM_DATA = "save_form_data";
45     private static final String USER_AGENT = "user_agent";
46     private static final String CUSTOM_USER_AGENT = "custom_user_agent";
47     private static final String INCOGNITO_MODE = "incognito_mode";
48     private static final String DO_NOT_TRACK = "do_not_track";
49     private static final String ALLOW_SCREENSHOTS = "allow_screenshots";
50     private static final String EASYLIST = "easylist";
51     private static final String EASYPRIVACY = "easyprivacy";
52     private static final String FANBOYS_ANNOYANCE_LIST = "fanboys_annoyance_list";
53     private static final String FANBOYS_SOCIAL_BLOCKING_LIST = "fanboys_social_blocking_list";
54     private static final String ULTRAPRIVACY = "ultraprivacy";
55     private static final String BLOCK_ALL_THIRD_PARTY_REQUESTS = "block_all_third_party_requests";
56     private static final String PROXY_THROUGH_ORBOT = "proxy_through_orbot";
57     private static final String TOR_HOMEPAGE = "tor_homepage";
58     private static final String TOR_SEARCH = "tor_search";
59     private static final String TOR_SEARCH_CUSTOM_URL = "tor_search_custom_url";
60     private static final String SEARCH = "search";
61     private static final String SEARCH_CUSTOM_URL = "search_custom_url";
62     private static final String FULL_SCREEN_BROWSING_MODE = "full_screen_browsing_mode";
63     private static final String HIDE_SYSTEM_BARS = "hide_system_bars";
64     private static final String TRANSLUCENT_NAVIGATION_BAR = "translucent_navigation_bar";
65     private static final String CLEAR_EVERYTHING = "clear_everything";
66     private static final String CLEAR_COOKIES = "clear_cookies";
67     private static final String CLEAR_DOM_STORAGE = "clear_dom_storage";
68     private static final String CLEAR_FORM_DATA = "clear_form_data";
69     private static final String CLEAR_CACHE = "clear_cache";
70     private static final String HOMEPAGE = "homepage";
71     private static final String DEFAULT_FONT_SIZE = "default_font_size";
72     private static final String SWIPE_TO_REFRESH = "swipe_to_refresh";
73     private static final String DISPLAY_ADDITIONAL_APP_BAR_ICONS = "display_additional_app_bar_icons";
74     private static final String DARK_THEME = "dark_theme";
75     private static final String NIGHT_MODE = "night_mode";
76     private static final String DISPLAY_WEBPAGE_IMAGES = "display_webpage_images";
77
78     public String exportUnencrypted(File databaseFile, Context context) {
79         try {
80             // Delete the current file if it exists.
81             if (databaseFile.exists()) {
82                 //noinspection ResultOfMethodCallIgnored
83                 databaseFile.delete();
84             }
85
86             // Create the export database.
87             SQLiteDatabase exportDatabase = SQLiteDatabase.openOrCreateDatabase(databaseFile, null);
88
89             // Set the export database version number.
90             exportDatabase.setVersion(SCHEMA_VERSION);
91
92             // Create the export database domains table.
93             exportDatabase.execSQL(DomainsDatabaseHelper.CREATE_DOMAINS_TABLE);
94
95             // Open the domains database.  The `0` specifies the database version, but that is ignored and set instead using a constant in `DomainsDatabaseHelper`.
96             DomainsDatabaseHelper domainsDatabaseHelper = new DomainsDatabaseHelper(context, null, null, 0);
97
98             // Get a full domains database cursor.
99             Cursor domainsCursor = domainsDatabaseHelper.getCompleteCursorOrderedByDomain();
100
101             // Move to the first domain.
102             domainsCursor.moveToFirst();
103
104             // Copy the data from the domains cursor into the export database.
105             for (int i = 0; i < domainsCursor.getCount(); i++) {
106                 // Extract the record from the cursor and store the data in a ContentValues.
107                 ContentValues domainsContentValues = new ContentValues();
108                 domainsContentValues.put(DomainsDatabaseHelper.DOMAIN_NAME, domainsCursor.getString(domainsCursor.getColumnIndex(DomainsDatabaseHelper.DOMAIN_NAME)));
109                 domainsContentValues.put(DomainsDatabaseHelper.ENABLE_JAVASCRIPT, domainsCursor.getInt(domainsCursor.getColumnIndex(DomainsDatabaseHelper.ENABLE_JAVASCRIPT)));
110                 domainsContentValues.put(DomainsDatabaseHelper.ENABLE_FIRST_PARTY_COOKIES, domainsCursor.getInt(domainsCursor.getColumnIndex(DomainsDatabaseHelper.ENABLE_FIRST_PARTY_COOKIES)));
111                 domainsContentValues.put(DomainsDatabaseHelper.ENABLE_THIRD_PARTY_COOKIES, domainsCursor.getInt(domainsCursor.getColumnIndex(DomainsDatabaseHelper.ENABLE_THIRD_PARTY_COOKIES)));
112                 domainsContentValues.put(DomainsDatabaseHelper.ENABLE_DOM_STORAGE, domainsCursor.getInt(domainsCursor.getColumnIndex(DomainsDatabaseHelper.ENABLE_DOM_STORAGE)));
113                 domainsContentValues.put(DomainsDatabaseHelper.ENABLE_FORM_DATA, domainsCursor.getInt(domainsCursor.getColumnIndex(DomainsDatabaseHelper.ENABLE_FORM_DATA)));
114                 domainsContentValues.put(DomainsDatabaseHelper.ENABLE_EASYLIST, domainsCursor.getInt(domainsCursor.getColumnIndex(DomainsDatabaseHelper.ENABLE_EASYLIST)));
115                 domainsContentValues.put(DomainsDatabaseHelper.ENABLE_EASYPRIVACY, domainsCursor.getInt(domainsCursor.getColumnIndex(DomainsDatabaseHelper.ENABLE_EASYPRIVACY)));
116                 domainsContentValues.put(DomainsDatabaseHelper.ENABLE_FANBOYS_ANNOYANCE_LIST, domainsCursor.getInt(domainsCursor.getColumnIndex(DomainsDatabaseHelper.ENABLE_FANBOYS_ANNOYANCE_LIST)));
117                 domainsContentValues.put(DomainsDatabaseHelper.ENABLE_FANBOYS_SOCIAL_BLOCKING_LIST, domainsCursor.getInt(domainsCursor.getColumnIndex(DomainsDatabaseHelper.ENABLE_FANBOYS_SOCIAL_BLOCKING_LIST)));
118                 domainsContentValues.put(DomainsDatabaseHelper.ENABLE_ULTRAPRIVACY, domainsCursor.getInt(domainsCursor.getColumnIndex(DomainsDatabaseHelper.ENABLE_ULTRAPRIVACY)));
119                 domainsContentValues.put(DomainsDatabaseHelper.BLOCK_ALL_THIRD_PARTY_REQUESTS, domainsCursor.getInt(domainsCursor.getColumnIndex(DomainsDatabaseHelper.BLOCK_ALL_THIRD_PARTY_REQUESTS)));
120                 domainsContentValues.put(DomainsDatabaseHelper.USER_AGENT, domainsCursor.getString(domainsCursor.getColumnIndex(DomainsDatabaseHelper.USER_AGENT)));
121                 domainsContentValues.put(DomainsDatabaseHelper.FONT_SIZE, domainsCursor.getInt(domainsCursor.getColumnIndex(DomainsDatabaseHelper.FONT_SIZE)));
122                 domainsContentValues.put(DomainsDatabaseHelper.SWIPE_TO_REFRESH, domainsCursor.getInt(domainsCursor.getColumnIndex(DomainsDatabaseHelper.SWIPE_TO_REFRESH)));
123                 domainsContentValues.put(DomainsDatabaseHelper.NIGHT_MODE, domainsCursor.getInt(domainsCursor.getColumnIndex(DomainsDatabaseHelper.NIGHT_MODE)));
124                 domainsContentValues.put(DomainsDatabaseHelper.DISPLAY_IMAGES, domainsCursor.getInt(domainsCursor.getColumnIndex(DomainsDatabaseHelper.DISPLAY_IMAGES)));
125                 domainsContentValues.put(DomainsDatabaseHelper.PINNED_SSL_CERTIFICATE, domainsCursor.getInt(domainsCursor.getColumnIndex(DomainsDatabaseHelper.PINNED_SSL_CERTIFICATE)));
126                 domainsContentValues.put(DomainsDatabaseHelper.SSL_ISSUED_TO_COMMON_NAME, domainsCursor.getString(domainsCursor.getColumnIndex(DomainsDatabaseHelper.SSL_ISSUED_TO_COMMON_NAME)));
127                 domainsContentValues.put(DomainsDatabaseHelper.SSL_ISSUED_TO_ORGANIZATION, domainsCursor.getString(domainsCursor.getColumnIndex(DomainsDatabaseHelper.SSL_ISSUED_TO_ORGANIZATION)));
128                 domainsContentValues.put(DomainsDatabaseHelper.SSL_ISSUED_TO_ORGANIZATIONAL_UNIT, domainsCursor.getString(domainsCursor.getColumnIndex(DomainsDatabaseHelper.SSL_ISSUED_TO_ORGANIZATIONAL_UNIT)));
129                 domainsContentValues.put(DomainsDatabaseHelper.SSL_ISSUED_BY_COMMON_NAME, domainsCursor.getString(domainsCursor.getColumnIndex(DomainsDatabaseHelper.SSL_ISSUED_BY_COMMON_NAME)));
130                 domainsContentValues.put(DomainsDatabaseHelper.SSL_ISSUED_BY_ORGANIZATION, domainsCursor.getString(domainsCursor.getColumnIndex(DomainsDatabaseHelper.SSL_ISSUED_BY_ORGANIZATION)));
131                 domainsContentValues.put(DomainsDatabaseHelper.SSL_ISSUED_BY_ORGANIZATIONAL_UNIT, domainsCursor.getString(domainsCursor.getColumnIndex(DomainsDatabaseHelper.SSL_ISSUED_BY_ORGANIZATIONAL_UNIT)));
132                 domainsContentValues.put(DomainsDatabaseHelper.SSL_START_DATE, domainsCursor.getLong(domainsCursor.getColumnIndex(DomainsDatabaseHelper.SSL_START_DATE)));
133                 domainsContentValues.put(DomainsDatabaseHelper.SSL_END_DATE, domainsCursor.getLong(domainsCursor.getColumnIndex(DomainsDatabaseHelper.SSL_END_DATE)));
134
135                 // Insert the record into the export database.
136                 exportDatabase.insert(DomainsDatabaseHelper.DOMAINS_TABLE, null, domainsContentValues);
137
138                 // Advance to the next record.
139                 domainsCursor.moveToNext();
140             }
141
142             // Close the domains database.
143             domainsCursor.close();
144             domainsDatabaseHelper.close();
145
146
147             // Create the export database bookmarks table.
148             exportDatabase.execSQL(BookmarksDatabaseHelper.CREATE_BOOKMARKS_TABLE);
149
150             // Open the bookmarks database.  The `0` specifies the database version, but that is ignored and set instead using a constant in `BookmarksDatabaseHelper`.
151             BookmarksDatabaseHelper bookmarksDatabaseHelper = new BookmarksDatabaseHelper(context, null, null, 0);
152
153             // Get a full bookmarks cursor.
154             Cursor bookmarksCursor = bookmarksDatabaseHelper.getAllBookmarksCursor();
155
156             // Move to the first bookmark.
157             bookmarksCursor.moveToFirst();
158
159             // Copy the data from the bookmarks cursor into the export database.
160             for (int i = 0; i < bookmarksCursor.getCount(); i++) {
161                 // Extract the record from the cursor and store the data in a ContentValues.
162                 ContentValues bookmarksContentValues = new ContentValues();
163                 bookmarksContentValues.put(BookmarksDatabaseHelper.BOOKMARK_NAME, bookmarksCursor.getString(bookmarksCursor.getColumnIndex(BookmarksDatabaseHelper.BOOKMARK_NAME)));
164                 bookmarksContentValues.put(BookmarksDatabaseHelper.BOOKMARK_URL, bookmarksCursor.getString(bookmarksCursor.getColumnIndex(BookmarksDatabaseHelper.BOOKMARK_URL)));
165                 bookmarksContentValues.put(BookmarksDatabaseHelper.PARENT_FOLDER, bookmarksCursor.getString(bookmarksCursor.getColumnIndex(BookmarksDatabaseHelper.PARENT_FOLDER)));
166                 bookmarksContentValues.put(BookmarksDatabaseHelper.DISPLAY_ORDER, bookmarksCursor.getInt(bookmarksCursor.getColumnIndex(BookmarksDatabaseHelper.DISPLAY_ORDER)));
167                 bookmarksContentValues.put(BookmarksDatabaseHelper.IS_FOLDER, bookmarksCursor.getInt(bookmarksCursor.getColumnIndex(BookmarksDatabaseHelper.IS_FOLDER)));
168                 bookmarksContentValues.put(BookmarksDatabaseHelper.FAVORITE_ICON, bookmarksCursor.getBlob(bookmarksCursor.getColumnIndex(BookmarksDatabaseHelper.FAVORITE_ICON)));
169
170                 // Insert the record into the export database.
171                 exportDatabase.insert(BookmarksDatabaseHelper.BOOKMARKS_TABLE, null, bookmarksContentValues);
172
173                 // Advance to the next record.
174                 bookmarksCursor.moveToNext();
175             }
176
177             // Close the bookmarks database.
178             bookmarksCursor.close();
179             bookmarksDatabaseHelper.close();
180
181
182             // Prepare the preferences table SQL creation string.
183             String CREATE_PREFERENCES_TABLE = "CREATE TABLE " + PREFERENCES_TABLE + " (" +
184                     _ID + " INTEGER PRIMARY KEY, " +
185                     JAVASCRIPT + " BOOLEAN, " +
186                     FIRST_PARTY_COOKIES + " BOOLEAN, " +
187                     THIRD_PARTY_COOKIES + " BOOLEAN, " +
188                     DOM_STORAGE + " BOOLEAN, " +
189                     SAVE_FORM_DATA + " BOOLEAN, " +
190                     USER_AGENT + " TEXT, " +
191                     CUSTOM_USER_AGENT + " TEXT, " +
192                     INCOGNITO_MODE + " BOOLEAN, " +
193                     DO_NOT_TRACK + " BOOLEAN, " +
194                     ALLOW_SCREENSHOTS + " BOOLEAN, " +
195                     EASYLIST + " BOOLEAN, " +
196                     EASYPRIVACY + " BOOLEAN, " +
197                     FANBOYS_ANNOYANCE_LIST + " BOOLEAN, " +
198                     FANBOYS_SOCIAL_BLOCKING_LIST + " BOOLEAN, " +
199                     ULTRAPRIVACY + " BOOLEAN, " +
200                     BLOCK_ALL_THIRD_PARTY_REQUESTS + " BOOLEAN, " +
201                     PROXY_THROUGH_ORBOT + " BOOLEAN, " +
202                     TOR_HOMEPAGE + " TEXT, " +
203                     TOR_SEARCH + " TEXT, " +
204                     TOR_SEARCH_CUSTOM_URL + " TEXT, " +
205                     SEARCH + " TEXT, " +
206                     SEARCH_CUSTOM_URL + " TEXT, " +
207                     FULL_SCREEN_BROWSING_MODE + " BOOLEAN, " +
208                     HIDE_SYSTEM_BARS + " BOOLEAN, " +
209                     TRANSLUCENT_NAVIGATION_BAR + " BOOLEAN, " +
210                     CLEAR_EVERYTHING + " BOOLEAN, " +
211                     CLEAR_COOKIES + " BOOLEAN, " +
212                     CLEAR_DOM_STORAGE + " BOOLEAN, " +
213                     CLEAR_FORM_DATA + " BOOLEAN, " +
214                     CLEAR_CACHE + " BOOLEAN, " +
215                     HOMEPAGE + " TEXT, " +
216                     DEFAULT_FONT_SIZE + " TEXT, " +
217                     SWIPE_TO_REFRESH + " BOOLEAN, " +
218                     DISPLAY_ADDITIONAL_APP_BAR_ICONS + " BOOLEAN, " +
219                     DARK_THEME + " BOOLEAN, " +
220                     NIGHT_MODE + " BOOLEAN, " +
221                     DISPLAY_WEBPAGE_IMAGES + " BOOLEAN)";
222
223             // Create the export database preferences table.
224             exportDatabase.execSQL(CREATE_PREFERENCES_TABLE);
225
226             // Get a handle for the shared preference.
227             SharedPreferences sharedPreferences = PreferenceManager.getDefaultSharedPreferences(context);
228
229             // Create a ContentValues with the preferences information.
230             ContentValues preferencesContentValues = new ContentValues();
231             preferencesContentValues.put(JAVASCRIPT, sharedPreferences.getBoolean("javascript_enabled", false));
232             preferencesContentValues.put(FIRST_PARTY_COOKIES, sharedPreferences.getBoolean("first_party_cookies_enabled", false));
233             preferencesContentValues.put(THIRD_PARTY_COOKIES, sharedPreferences.getBoolean("third_party_cookies_enabled", false));
234             preferencesContentValues.put(DOM_STORAGE, sharedPreferences.getBoolean("dom_storage_enabled", false));
235             preferencesContentValues.put(SAVE_FORM_DATA, sharedPreferences.getBoolean("save_form_data_enabled", false));  // Save form data can be removed once the minimum API >= 26.
236             preferencesContentValues.put(USER_AGENT, sharedPreferences.getString("user_agent", "Privacy Browser"));
237             preferencesContentValues.put(CUSTOM_USER_AGENT, sharedPreferences.getString("custom_user_agent", "PrivacyBrowser/1.0"));
238             preferencesContentValues.put(INCOGNITO_MODE, sharedPreferences.getBoolean("incognito_mode", false));
239             preferencesContentValues.put(DO_NOT_TRACK, sharedPreferences.getBoolean("do_not_track", false));
240             preferencesContentValues.put(ALLOW_SCREENSHOTS, sharedPreferences.getBoolean("allow_screenshots", false));
241             preferencesContentValues.put(EASYLIST, sharedPreferences.getBoolean("easylist", true));
242             preferencesContentValues.put(EASYPRIVACY, sharedPreferences.getBoolean("easyprivacy", true));
243             preferencesContentValues.put(FANBOYS_ANNOYANCE_LIST, sharedPreferences.getBoolean("fanboy_annoyance_list", true));
244             preferencesContentValues.put(FANBOYS_SOCIAL_BLOCKING_LIST, sharedPreferences.getBoolean("fanboy_social_blocking_list", true));
245             preferencesContentValues.put(ULTRAPRIVACY, sharedPreferences.getBoolean("ultraprivacy", true));
246             preferencesContentValues.put(BLOCK_ALL_THIRD_PARTY_REQUESTS, sharedPreferences.getBoolean("block_all_third_party_requests", false));
247             preferencesContentValues.put(PROXY_THROUGH_ORBOT, sharedPreferences.getBoolean("proxy_through_orbot", false));
248             preferencesContentValues.put(TOR_HOMEPAGE, sharedPreferences.getString("tor_homepage", "http://ulrn6sryqaifefld.onion/"));
249             preferencesContentValues.put(TOR_SEARCH, sharedPreferences.getString("tor_search", "http://ulrn6sryqaifefld.onion/?q="));
250             preferencesContentValues.put(TOR_SEARCH_CUSTOM_URL, sharedPreferences.getString("tor_search_custom_url", ""));
251             preferencesContentValues.put(SEARCH, sharedPreferences.getString("search", "https://searx.me/?q="));
252             preferencesContentValues.put(SEARCH_CUSTOM_URL, sharedPreferences.getString("search_custom_url", ""));
253             preferencesContentValues.put(FULL_SCREEN_BROWSING_MODE, sharedPreferences.getBoolean("full_screen_browsing_mode", false));
254             preferencesContentValues.put(HIDE_SYSTEM_BARS, sharedPreferences.getBoolean("hide_system_bars", false));
255             preferencesContentValues.put(TRANSLUCENT_NAVIGATION_BAR, sharedPreferences.getBoolean("translucent_navigation_bar", true));
256             preferencesContentValues.put(CLEAR_EVERYTHING, sharedPreferences.getBoolean("clear_everything", true));
257             preferencesContentValues.put(CLEAR_COOKIES, sharedPreferences.getBoolean("clear_cookies", true));
258             preferencesContentValues.put(CLEAR_DOM_STORAGE, sharedPreferences.getBoolean("clear_dom_storage", true));
259             preferencesContentValues.put(CLEAR_FORM_DATA, sharedPreferences.getBoolean("clear_form_data", true));  // Clear form data can be removed once the minimum API >= 26.
260             preferencesContentValues.put(CLEAR_CACHE, sharedPreferences.getBoolean("clear_cache", true));
261             preferencesContentValues.put(HOMEPAGE, sharedPreferences.getString("homepage", "https://searx.me"));
262             preferencesContentValues.put(DEFAULT_FONT_SIZE, sharedPreferences.getString("default_font_size", "100"));
263             preferencesContentValues.put(SWIPE_TO_REFRESH, sharedPreferences.getBoolean("swipe_to_refresh", true));
264             preferencesContentValues.put(DISPLAY_ADDITIONAL_APP_BAR_ICONS, sharedPreferences.getBoolean("display_additional_app_bar_icons", false));
265             preferencesContentValues.put(DARK_THEME, sharedPreferences.getBoolean("dark_theme", false));
266             preferencesContentValues.put(NIGHT_MODE, sharedPreferences.getBoolean("night_mode", false));
267             preferencesContentValues.put(DISPLAY_WEBPAGE_IMAGES, sharedPreferences.getBoolean("display_webpage_images", true));
268
269             // Insert the preferences into the export database.
270             exportDatabase.insert(PREFERENCES_TABLE, null, preferencesContentValues);
271
272             // Close the export database.
273             exportDatabase.close();
274
275             // Convert the database file to a string.
276             String databaseString = databaseFile.toString();
277
278             // Create strings for the temporary database files.
279             String journalFileString = databaseString + "-journal";
280
281             // Get `Files` for the temporary database files.
282             File journalFile = new File(journalFileString);
283
284             // Delete the Journal file if it exists.
285             if (journalFile.exists()) {
286                 //noinspection ResultOfMethodCallIgnored
287                 journalFile.delete();
288             }
289
290             // Export successful.
291             return EXPORT_SUCCESSFUL;
292         } catch (Exception exception) {
293             // Return the export error.
294             return exception.toString();
295         }
296     }
297
298     public String importUnencrypted(File databaseFile, Context context){
299         try {
300             // Convert the database file to a string.  Once API >= 27 the file can be opened directly.
301             String databaseString = databaseFile.toString();
302
303             // Open the import database.
304             SQLiteDatabase importDatabase = SQLiteDatabase.openDatabase(databaseString, null, SQLiteDatabase.OPEN_READONLY);
305
306             // Get a cursor for the domains table.
307             Cursor importDomainsCursor = importDatabase.rawQuery("SELECT * FROM " + DomainsDatabaseHelper.DOMAINS_TABLE + " ORDER BY " + DomainsDatabaseHelper.DOMAIN_NAME + " ASC", null);
308
309             // Delete the current domains database.
310             context.deleteDatabase(DomainsDatabaseHelper.DOMAINS_DATABASE);
311
312             // Create a new domains database.  The `0` specifies the database version, but that is ignored and set instead using a constant in `DomainsDatabaseHelper`.
313             DomainsDatabaseHelper domainsDatabaseHelper = new DomainsDatabaseHelper(context, null, null, 0);
314
315             // Move to the first domain.
316             importDomainsCursor.moveToFirst();
317
318             // Copy the data from the import domains cursor into the domains database.
319             for (int i = 0; i < importDomainsCursor.getCount(); i++) {
320                 // Extract the record from the cursor and store the data in a ContentValues.
321                 ContentValues domainsContentValues = new ContentValues();
322                 domainsContentValues.put(DomainsDatabaseHelper.DOMAIN_NAME, importDomainsCursor.getString(importDomainsCursor.getColumnIndex(DomainsDatabaseHelper.DOMAIN_NAME)));
323                 domainsContentValues.put(DomainsDatabaseHelper.ENABLE_JAVASCRIPT, importDomainsCursor.getInt(importDomainsCursor.getColumnIndex(DomainsDatabaseHelper.ENABLE_JAVASCRIPT)));
324                 domainsContentValues.put(DomainsDatabaseHelper.ENABLE_FIRST_PARTY_COOKIES, importDomainsCursor.getInt(importDomainsCursor.getColumnIndex(DomainsDatabaseHelper.ENABLE_FIRST_PARTY_COOKIES)));
325                 domainsContentValues.put(DomainsDatabaseHelper.ENABLE_THIRD_PARTY_COOKIES, importDomainsCursor.getInt(importDomainsCursor.getColumnIndex(DomainsDatabaseHelper.ENABLE_THIRD_PARTY_COOKIES)));
326                 domainsContentValues.put(DomainsDatabaseHelper.ENABLE_DOM_STORAGE, importDomainsCursor.getInt(importDomainsCursor.getColumnIndex(DomainsDatabaseHelper.ENABLE_DOM_STORAGE)));
327                 domainsContentValues.put(DomainsDatabaseHelper.ENABLE_FORM_DATA, importDomainsCursor.getInt(importDomainsCursor.getColumnIndex(DomainsDatabaseHelper.ENABLE_FORM_DATA)));
328                 domainsContentValues.put(DomainsDatabaseHelper.ENABLE_EASYLIST, importDomainsCursor.getInt(importDomainsCursor.getColumnIndex(DomainsDatabaseHelper.ENABLE_EASYLIST)));
329                 domainsContentValues.put(DomainsDatabaseHelper.ENABLE_EASYPRIVACY, importDomainsCursor.getInt(importDomainsCursor.getColumnIndex(DomainsDatabaseHelper.ENABLE_EASYPRIVACY)));
330                 domainsContentValues.put(DomainsDatabaseHelper.ENABLE_FANBOYS_ANNOYANCE_LIST,
331                         importDomainsCursor.getInt(importDomainsCursor.getColumnIndex(DomainsDatabaseHelper.ENABLE_FANBOYS_ANNOYANCE_LIST)));
332                 domainsContentValues.put(DomainsDatabaseHelper.ENABLE_FANBOYS_SOCIAL_BLOCKING_LIST,
333                         importDomainsCursor.getInt(importDomainsCursor.getColumnIndex(DomainsDatabaseHelper.ENABLE_FANBOYS_SOCIAL_BLOCKING_LIST)));
334                 domainsContentValues.put(DomainsDatabaseHelper.ENABLE_ULTRAPRIVACY, importDomainsCursor.getInt(importDomainsCursor.getColumnIndex(DomainsDatabaseHelper.ENABLE_ULTRAPRIVACY)));
335                 domainsContentValues.put(DomainsDatabaseHelper.BLOCK_ALL_THIRD_PARTY_REQUESTS,
336                         importDomainsCursor.getInt(importDomainsCursor.getColumnIndex(DomainsDatabaseHelper.BLOCK_ALL_THIRD_PARTY_REQUESTS)));
337                 domainsContentValues.put(DomainsDatabaseHelper.USER_AGENT, importDomainsCursor.getString(importDomainsCursor.getColumnIndex(DomainsDatabaseHelper.USER_AGENT)));
338                 domainsContentValues.put(DomainsDatabaseHelper.FONT_SIZE, importDomainsCursor.getInt(importDomainsCursor.getColumnIndex(DomainsDatabaseHelper.FONT_SIZE)));
339                 domainsContentValues.put(DomainsDatabaseHelper.SWIPE_TO_REFRESH, importDomainsCursor.getInt(importDomainsCursor.getColumnIndex(DomainsDatabaseHelper.SWIPE_TO_REFRESH)));
340                 domainsContentValues.put(DomainsDatabaseHelper.NIGHT_MODE, importDomainsCursor.getInt(importDomainsCursor.getColumnIndex(DomainsDatabaseHelper.NIGHT_MODE)));
341                 domainsContentValues.put(DomainsDatabaseHelper.DISPLAY_IMAGES, importDomainsCursor.getInt(importDomainsCursor.getColumnIndex(DomainsDatabaseHelper.DISPLAY_IMAGES)));
342                 domainsContentValues.put(DomainsDatabaseHelper.PINNED_SSL_CERTIFICATE, importDomainsCursor.getInt(importDomainsCursor.getColumnIndex(DomainsDatabaseHelper.PINNED_SSL_CERTIFICATE)));
343                 domainsContentValues.put(DomainsDatabaseHelper.SSL_ISSUED_TO_COMMON_NAME, importDomainsCursor.getString(importDomainsCursor.getColumnIndex(DomainsDatabaseHelper.SSL_ISSUED_TO_COMMON_NAME)));
344                 domainsContentValues.put(DomainsDatabaseHelper.SSL_ISSUED_TO_ORGANIZATION, importDomainsCursor.getString(importDomainsCursor.getColumnIndex(DomainsDatabaseHelper.SSL_ISSUED_TO_ORGANIZATION)));
345                 domainsContentValues.put(DomainsDatabaseHelper.SSL_ISSUED_TO_ORGANIZATIONAL_UNIT,
346                         importDomainsCursor.getString(importDomainsCursor.getColumnIndex(DomainsDatabaseHelper.SSL_ISSUED_TO_ORGANIZATIONAL_UNIT)));
347                 domainsContentValues.put(DomainsDatabaseHelper.SSL_ISSUED_BY_COMMON_NAME, importDomainsCursor.getString(importDomainsCursor.getColumnIndex(DomainsDatabaseHelper.SSL_ISSUED_BY_COMMON_NAME)));
348                 domainsContentValues.put(DomainsDatabaseHelper.SSL_ISSUED_BY_ORGANIZATION, importDomainsCursor.getString(importDomainsCursor.getColumnIndex(DomainsDatabaseHelper.SSL_ISSUED_BY_ORGANIZATION)));
349                 domainsContentValues.put(DomainsDatabaseHelper.SSL_ISSUED_BY_ORGANIZATIONAL_UNIT,
350                         importDomainsCursor.getString(importDomainsCursor.getColumnIndex(DomainsDatabaseHelper.SSL_ISSUED_BY_ORGANIZATIONAL_UNIT)));
351                 domainsContentValues.put(DomainsDatabaseHelper.SSL_START_DATE, importDomainsCursor.getLong(importDomainsCursor.getColumnIndex(DomainsDatabaseHelper.SSL_START_DATE)));
352                 domainsContentValues.put(DomainsDatabaseHelper.SSL_END_DATE, importDomainsCursor.getLong(importDomainsCursor.getColumnIndex(DomainsDatabaseHelper.SSL_END_DATE)));
353
354                 // Insert the record into the export database.
355                 domainsDatabaseHelper.addDomain(domainsContentValues);
356
357                 // Advance to the next record.
358                 importDomainsCursor.moveToNext();
359             }
360
361             // Close the domains cursor.
362             importDomainsCursor.close();
363
364             // Close the domains database.
365             domainsDatabaseHelper.close();
366
367
368             // Get a cursor for the bookmarks table.
369             Cursor importBookmarksCursor = importDatabase.rawQuery("SELECT * FROM " + BookmarksDatabaseHelper.BOOKMARKS_TABLE, null);
370
371             // Delete the current bookmarks database.
372             context.deleteDatabase(BookmarksDatabaseHelper.BOOKMARKS_DATABASE);
373
374             // Create a new bookmarks database.  The `0` specifies the database version, but that is ignored and set instead using a constant in `BookmarksDatabaseHelper`.
375             BookmarksDatabaseHelper bookmarksDatabaseHelper = new BookmarksDatabaseHelper(context, null, null, 0);
376
377             // Move to the first bookmark.
378             importBookmarksCursor.moveToFirst();
379
380             // Copy the data from the import bookmarks cursor into the bookmarks database.
381             for (int i = 0; i < importBookmarksCursor.getCount(); i++) {
382                 // Extract the record from the cursor and store the data in a ContentValues.
383                 ContentValues bookmarksContentValues = new ContentValues();
384                 bookmarksContentValues.put(BookmarksDatabaseHelper.BOOKMARK_NAME, importBookmarksCursor.getString(importBookmarksCursor.getColumnIndex(BookmarksDatabaseHelper.BOOKMARK_NAME)));
385                 bookmarksContentValues.put(BookmarksDatabaseHelper.BOOKMARK_URL, importBookmarksCursor.getString(importBookmarksCursor.getColumnIndex(BookmarksDatabaseHelper.BOOKMARK_URL)));
386                 bookmarksContentValues.put(BookmarksDatabaseHelper.PARENT_FOLDER, importBookmarksCursor.getString(importBookmarksCursor.getColumnIndex(BookmarksDatabaseHelper.PARENT_FOLDER)));
387                 bookmarksContentValues.put(BookmarksDatabaseHelper.DISPLAY_ORDER, importBookmarksCursor.getInt(importBookmarksCursor.getColumnIndex(BookmarksDatabaseHelper.DISPLAY_ORDER)));
388                 bookmarksContentValues.put(BookmarksDatabaseHelper.IS_FOLDER, importBookmarksCursor.getInt(importBookmarksCursor.getColumnIndex(BookmarksDatabaseHelper.IS_FOLDER)));
389                 bookmarksContentValues.put(BookmarksDatabaseHelper.FAVORITE_ICON, importBookmarksCursor.getBlob(importBookmarksCursor.getColumnIndex(BookmarksDatabaseHelper.FAVORITE_ICON)));
390
391                 // Insert the record into the export database.
392                 bookmarksDatabaseHelper.createBookmark(bookmarksContentValues);
393
394                 // Advance to the next record.
395                 importBookmarksCursor.moveToNext();
396             }
397
398             // Close the bookmarks cursor.
399             importBookmarksCursor.close();
400
401             // Close the bookmarks database.
402             bookmarksDatabaseHelper.close();
403
404
405             // Get a handle for the shared preference.
406             SharedPreferences sharedPreferences = PreferenceManager.getDefaultSharedPreferences(context);
407
408             // Get a cursor for the bookmarks table.
409             Cursor importPreferencesCursor = importDatabase.rawQuery("SELECT * FROM " + PREFERENCES_TABLE, null);
410
411             // Move to the first preference.
412             importPreferencesCursor.moveToFirst();
413
414             // Import the preference data.
415             sharedPreferences.edit()
416                     .putBoolean("javascript_enabled", importPreferencesCursor.getInt(importPreferencesCursor.getColumnIndex(JAVASCRIPT)) == 1)
417                     .putBoolean("first_party_cookies_enabled", importPreferencesCursor.getInt(importPreferencesCursor.getColumnIndex(FIRST_PARTY_COOKIES)) == 1)
418                     .putBoolean("third_party_cookies_enabled", importPreferencesCursor.getInt(importPreferencesCursor.getColumnIndex(THIRD_PARTY_COOKIES)) == 1)
419                     .putBoolean("dom_storage_enabled", importPreferencesCursor.getInt(importPreferencesCursor.getColumnIndex(DOM_STORAGE)) == 1)
420                     // Save form data can be removed once the minimum API >= 26.
421                     .putBoolean("save_form_data_enabled", importPreferencesCursor.getInt(importPreferencesCursor.getColumnIndex(SAVE_FORM_DATA)) == 1)
422                     .putString("user_agent", importPreferencesCursor.getString(importPreferencesCursor.getColumnIndex(USER_AGENT)))
423                     .putString("custom_user_agent", importPreferencesCursor.getString(importPreferencesCursor.getColumnIndex(CUSTOM_USER_AGENT)))
424                     .putBoolean("incognito_mode", importPreferencesCursor.getInt(importPreferencesCursor.getColumnIndex(INCOGNITO_MODE)) == 1)
425                     .putBoolean("do_not_track", importPreferencesCursor.getInt(importPreferencesCursor.getColumnIndex(DO_NOT_TRACK)) == 1)
426                     .putBoolean("allow_screenshots", importPreferencesCursor.getInt(importPreferencesCursor.getColumnIndex(ALLOW_SCREENSHOTS)) == 1)
427                     .putBoolean("easylist", importPreferencesCursor.getInt(importPreferencesCursor.getColumnIndex(EASYLIST)) == 1)
428                     .putBoolean("easyprivacy", importPreferencesCursor.getInt(importPreferencesCursor.getColumnIndex(EASYPRIVACY)) == 1)
429                     .putBoolean("fanboy_annoyance_list", importPreferencesCursor.getInt(importPreferencesCursor.getColumnIndex(FANBOYS_ANNOYANCE_LIST)) == 1)
430                     .putBoolean("fanboy_social_blocking_list", importPreferencesCursor.getInt(importPreferencesCursor.getColumnIndex(FANBOYS_SOCIAL_BLOCKING_LIST)) == 1)
431                     .putBoolean("ultraprivacy", importPreferencesCursor.getInt(importPreferencesCursor.getColumnIndex(ULTRAPRIVACY)) == 1)
432                     .putBoolean("block_all_third_party_requests", importPreferencesCursor.getInt(importPreferencesCursor.getColumnIndex(BLOCK_ALL_THIRD_PARTY_REQUESTS)) == 1)
433                     .putBoolean("proxy_through_orbot", importPreferencesCursor.getInt(importPreferencesCursor.getColumnIndex(PROXY_THROUGH_ORBOT)) == 1)
434                     .putString("tor_homepage", importPreferencesCursor.getString(importPreferencesCursor.getColumnIndex(TOR_HOMEPAGE)))
435                     .putString("tor_search", importPreferencesCursor.getString(importPreferencesCursor.getColumnIndex(TOR_SEARCH)))
436                     .putString("tor_search_custom_url", importPreferencesCursor.getString(importPreferencesCursor.getColumnIndex(TOR_SEARCH_CUSTOM_URL)))
437                     .putString("search", importPreferencesCursor.getString(importPreferencesCursor.getColumnIndex(SEARCH)))
438                     .putString("search_custom_url", importPreferencesCursor.getString(importPreferencesCursor.getColumnIndex(SEARCH_CUSTOM_URL)))
439                     .putBoolean("full_screen_browsing_mode", importPreferencesCursor.getInt(importPreferencesCursor.getColumnIndex(FULL_SCREEN_BROWSING_MODE)) == 1)
440                     .putBoolean("hide_system_bars", importPreferencesCursor.getInt(importPreferencesCursor.getColumnIndex(HIDE_SYSTEM_BARS)) == 1)
441                     .putBoolean("translucent_navigation_bar", importPreferencesCursor.getInt(importPreferencesCursor.getColumnIndex(TRANSLUCENT_NAVIGATION_BAR)) == 1)
442                     .putBoolean("clear_everything", importPreferencesCursor.getInt(importPreferencesCursor.getColumnIndex(CLEAR_EVERYTHING)) == 1)
443                     .putBoolean("clear_cookies", importPreferencesCursor.getInt(importPreferencesCursor.getColumnIndex(CLEAR_COOKIES)) == 1)
444                     .putBoolean("clear_dom_storage", importPreferencesCursor.getInt(importPreferencesCursor.getColumnIndex(CLEAR_DOM_STORAGE)) == 1)
445                     // Clear form data can be removed once the minimum API >= 26.
446                     .putBoolean("clear_form_data", importPreferencesCursor.getInt(importPreferencesCursor.getColumnIndex(CLEAR_FORM_DATA)) == 1)
447                     .putBoolean("clear_cache", importPreferencesCursor.getInt(importPreferencesCursor.getColumnIndex(CLEAR_CACHE)) == 1)
448                     .putString("homepage", importPreferencesCursor.getString(importPreferencesCursor.getColumnIndex(HOMEPAGE)))
449                     .putString("default_font_size", importPreferencesCursor.getString(importPreferencesCursor.getColumnIndex(DEFAULT_FONT_SIZE)))
450                     .putBoolean("swipe_to_refresh", importPreferencesCursor.getInt(importPreferencesCursor.getColumnIndex(SWIPE_TO_REFRESH)) == 1)
451                     .putBoolean("display_additional_app_bar_icons", importPreferencesCursor.getInt(importPreferencesCursor.getColumnIndex(DISPLAY_ADDITIONAL_APP_BAR_ICONS)) == 1)
452                     .putBoolean("dark_theme", importPreferencesCursor.getInt(importPreferencesCursor.getColumnIndex(DARK_THEME)) == 1)
453                     .putBoolean("night_mode", importPreferencesCursor.getInt(importPreferencesCursor.getColumnIndex(NIGHT_MODE)) == 1)
454                     .putBoolean("display_webpage_images", importPreferencesCursor.getInt(importPreferencesCursor.getColumnIndex(DISPLAY_WEBPAGE_IMAGES)) == 1).apply();
455
456             // Close the preferences cursor.
457             importPreferencesCursor.close();
458
459
460             // Close the import database.
461             importDatabase.close();
462
463             // Create strings for the temporary database files.
464             String shmFileString = databaseString + "-shm";
465             String walFileString = databaseString + "-wal";
466             String journalFileString = databaseString + "-journal";
467
468             // Get `Files` for the temporary database files.
469             File shmFile = new File(shmFileString);
470             File walFile = new File(walFileString);
471             File journalFile = new File(journalFileString);
472
473             // Delete the Shared Memory file if it exists.
474             if (shmFile.exists()) {
475                 //noinspection ResultOfMethodCallIgnored
476                 shmFile.delete();
477             }
478
479             // Delete the Write Ahead Log file if it exists.
480             if (walFile.exists()) {
481                 //noinspection ResultOfMethodCallIgnored
482                 walFile.delete();
483             }
484
485             // Delete the Journal file if it exists.
486             if (journalFile.exists()) {
487                 //noinspection ResultOfMethodCallIgnored
488                 journalFile.delete();
489             }
490
491             // Import successful.
492             return IMPORT_SUCCESSFUL;
493         } catch (Exception exception) {
494             // Return the import error.
495             return exception.toString();
496         }
497     }
498 }