Fix scrolling of the bottom app bar. https://redmine.stoutner.com/issues/791
authorSoren Stoutner <soren@stoutner.com>
Fri, 31 Dec 2021 22:08:17 +0000 (15:08 -0700)
committerSoren Stoutner <soren@stoutner.com>
Fri, 31 Dec 2021 22:08:17 +0000 (15:08 -0700)
30 files changed:
app/build.gradle
app/src/main/assets/de/about_changelog.html
app/src/main/java/com/stoutner/privacybrowser/activities/BookmarksActivity.java
app/src/main/java/com/stoutner/privacybrowser/activities/BookmarksDatabaseViewActivity.java
app/src/main/java/com/stoutner/privacybrowser/activities/DomainsActivity.java
app/src/main/java/com/stoutner/privacybrowser/activities/LogcatActivity.kt
app/src/main/java/com/stoutner/privacybrowser/activities/MainWebViewActivity.java
app/src/main/java/com/stoutner/privacybrowser/activities/ViewSourceActivity.kt
app/src/main/java/com/stoutner/privacybrowser/asynctasks/SaveAboutVersionImage.java
app/src/main/java/com/stoutner/privacybrowser/asynctasks/SaveUrl.java
app/src/main/java/com/stoutner/privacybrowser/asynctasks/SaveWebpageImage.java
app/src/main/java/com/stoutner/privacybrowser/dialogs/EditBookmarkDatabaseViewDialog.kt
app/src/main/java/com/stoutner/privacybrowser/dialogs/EditBookmarkDialog.kt
app/src/main/java/com/stoutner/privacybrowser/dialogs/EditBookmarkFolderDatabaseViewDialog.kt
app/src/main/java/com/stoutner/privacybrowser/dialogs/EditBookmarkFolderDialog.kt
app/src/main/java/com/stoutner/privacybrowser/dialogs/MoveToFolderDialog.kt
app/src/main/java/com/stoutner/privacybrowser/fragments/AboutVersionFragment.kt
app/src/main/java/com/stoutner/privacybrowser/fragments/DomainSettingsFragment.java
app/src/main/java/com/stoutner/privacybrowser/fragments/SettingsFragment.java
app/src/main/java/com/stoutner/privacybrowser/helpers/BlocklistHelper.java
app/src/main/java/com/stoutner/privacybrowser/helpers/BookmarksDatabaseHelper.java
app/src/main/java/com/stoutner/privacybrowser/helpers/ImportExportDatabaseHelper.java
app/src/main/java/com/stoutner/privacybrowser/helpers/ProxyHelper.java [deleted file]
app/src/main/java/com/stoutner/privacybrowser/helpers/ProxyHelper.kt [new file with mode: 0644]
app/src/main/java/com/stoutner/privacybrowser/views/NestedScrollWebView.kt
app/src/main/res/layout/main_framelayout_bottom_appbar.xml
app/src/main/res/layout/main_framelayout_top_appbar.xml
app/src/main/res/values/strings.xml
build.gradle
fastlane/metadata/android/de-DE/changelogs/57.txt

index e314f99de9f7ad8cf2c4874eb079f18e77a6b6eb..571e65286a99265eaedaa57250aa87372624c681 100644 (file)
@@ -79,7 +79,7 @@ dependencies {
     implementation 'androidx.webkit:webkit:1.4.0'
 
     // Include the Kotlin standard library.  This should be the same version number listed in project build.gradle.
-    implementation 'org.jetbrains.kotlin:kotlin-stdlib-jdk8:1.6.0'
+    implementation 'org.jetbrains.kotlin:kotlin-stdlib-jdk8:1.6.10'
 
     // Include the Google material library.
     implementation 'com.google.android.material:material:1.4.0'
index f7673d2d49191b4d9103aa35c8bc0e84d7195ce6..4214c4d7d4e850b6115d9797339b53bac02b9a61 100644 (file)
         <h3><a href="https://www.stoutner.com/privacy-browser-3-9/">3.9</a> (version code 57)</h3>
         <p><a href="https://gitweb.stoutner.com/?p=PrivacyBrowser.git;a=commitdiff;h=392f2726cd21539c5ec89e0d09d2e7d7922bebad">27. November 2021</a> - Mindest-API 19, Ziel-API 31</p>
         <ul>
-            <li>Simplify the <a href="https://redmine.stoutner.com/issues/769">save dialogs</a>.</li>
-            <li>Display the saved file name in the <a href="https://redmine.stoutner.com/issues/695">save snackbars</a>.</li>
-            <li>Change the <a href="https://redmine.stoutner.com/issues/748">short app name</a> from <code>Privacy</code> to <code>Browser</code>.</li>
-            <li>Fix a crash if a <a href="https://redmine.stoutner.com/issues/765">drawer is opened</a> while the app is restarted.</li>
-            <li>Bump the <a href="https://redmine.stoutner.com/issues/776">target API</a> to 31 (Android 12).</li>
+            <li><a href="https://redmine.stoutner.com/issues/769">"Speichern"-Dialog</a> vereinfacht.</li>
+            <li>Anzeige des Dateinamens in der <a href="https://redmine.stoutner.com/issues/695">Informationsleiste beim Speichern von Dateien</a> implementiert.</li>
+            <li><a href="https://redmine.stoutner.com/issues/748">Kurz-Name der App</a> von <code>Privatsphäre</code> in <code>Browser</code> geändert.</li>
+            <li>Fehler beseitig, wenn <a href="https://redmine.stoutner.com/issues/765">die App-Leiste</a> beim Neustart der Anwendung geöffnet war.</li>
+            <li><a href="https://redmine.stoutner.com/issues/776">Ziel-API</a> auf 31 (Android 12) angehoben.</li>
             <li>Aktualisierte deutsche Übersetzung von Bernhard G. Keller.</li>
         </ul>
 
index 9e33c0d22caecc15b2fc7e092c27a9591953551b..20dd59652b47652000f33e71349b57da30627827 100644 (file)
@@ -209,9 +209,9 @@ public class BookmarksActivity extends AppCompatActivity implements CreateBookma
             bookmarkCursor.moveToFirst();
 
             // Act upon the bookmark according to the type.
-            if (bookmarkCursor.getInt(bookmarkCursor.getColumnIndex(BookmarksDatabaseHelper.IS_FOLDER)) == 1) {  // The selected bookmark is a folder.
+            if (bookmarkCursor.getInt(bookmarkCursor.getColumnIndexOrThrow(BookmarksDatabaseHelper.IS_FOLDER)) == 1) {  // The selected bookmark is a folder.
                 // Update the current folder.
-                currentFolder = bookmarkCursor.getString(bookmarkCursor.getColumnIndex(BookmarksDatabaseHelper.BOOKMARK_NAME));
+                currentFolder = bookmarkCursor.getString(bookmarkCursor.getColumnIndexOrThrow(BookmarksDatabaseHelper.BOOKMARK_NAME));
 
                 // Load the new folder.
                 loadFolder();
@@ -359,7 +359,7 @@ public class BookmarksActivity extends AppCompatActivity implements CreateBookma
                             bookmarksCursor.moveToPosition(i);
 
                             // Update the display order only if it is not correct in the database.
-                            if (bookmarksCursor.getInt(bookmarksCursor.getColumnIndex(BookmarksDatabaseHelper.DISPLAY_ORDER)) != i) {
+                            if (bookmarksCursor.getInt(bookmarksCursor.getColumnIndexOrThrow(BookmarksDatabaseHelper.DISPLAY_ORDER)) != i) {
                                 bookmarksDatabaseHelper.updateDisplayOrder(currentBookmarkDatabaseId, i);
                             }
                         }
@@ -409,7 +409,7 @@ public class BookmarksActivity extends AppCompatActivity implements CreateBookma
                             bookmarksCursor.moveToPosition(i);
 
                             // Update the display order only if it is not correct in the database.
-                            if (bookmarksCursor.getInt(bookmarksCursor.getColumnIndex(BookmarksDatabaseHelper.DISPLAY_ORDER)) != i) {
+                            if (bookmarksCursor.getInt(bookmarksCursor.getColumnIndexOrThrow(BookmarksDatabaseHelper.DISPLAY_ORDER)) != i) {
                                 bookmarksDatabaseHelper.updateDisplayOrder(currentBookmarkDatabaseId, i);
                             }
                         }
@@ -449,15 +449,15 @@ public class BookmarksActivity extends AppCompatActivity implements CreateBookma
                     bookmarksCursor.moveToPosition(selectedBookmarkPosition);
 
                     // Find out if this bookmark is a folder.
-                    boolean isFolder = (bookmarksCursor.getInt(bookmarksCursor.getColumnIndex(BookmarksDatabaseHelper.IS_FOLDER)) == 1);
+                    boolean isFolder = (bookmarksCursor.getInt(bookmarksCursor.getColumnIndexOrThrow(BookmarksDatabaseHelper.IS_FOLDER)) == 1);
 
                     // Get the selected bookmark database ID.
-                    int databaseId = bookmarksCursor.getInt(bookmarksCursor.getColumnIndex(BookmarksDatabaseHelper._ID));
+                    int databaseId = bookmarksCursor.getInt(bookmarksCursor.getColumnIndexOrThrow(BookmarksDatabaseHelper._ID));
 
                     // Show the edit bookmark or edit bookmark folder dialog.
                     if (isFolder) {
                         // Save the current folder name, which is used in `onSaveBookmarkFolder()`.
-                        oldFolderNameString = bookmarksCursor.getString(bookmarksCursor.getColumnIndex(BookmarksDatabaseHelper.BOOKMARK_NAME));
+                        oldFolderNameString = bookmarksCursor.getString(bookmarksCursor.getColumnIndexOrThrow(BookmarksDatabaseHelper.BOOKMARK_NAME));
 
                         // Instantiate the edit bookmark folder dialog.
                         DialogFragment editFolderDialog = EditBookmarkFolderDialog.folderDatabaseId(databaseId, favoriteIconBitmap);
@@ -550,7 +550,7 @@ public class BookmarksActivity extends AppCompatActivity implements CreateBookma
                                             bookmarksCursor.moveToPosition(i);
 
                                             // Update the display order only if it is not correct in the database.
-                                            if (bookmarksCursor.getInt(bookmarksCursor.getColumnIndex(BookmarksDatabaseHelper.DISPLAY_ORDER)) != i) {
+                                            if (bookmarksCursor.getInt(bookmarksCursor.getColumnIndexOrThrow(BookmarksDatabaseHelper.DISPLAY_ORDER)) != i) {
                                                 bookmarksDatabaseHelper.updateDisplayOrder(currentBookmarkDatabaseId, i);
                                             }
                                         }
@@ -1056,7 +1056,7 @@ public class BookmarksActivity extends AppCompatActivity implements CreateBookma
             folderCursor.moveToPosition(i);
 
             // Get the database ID of the item.
-            int itemDatabaseId = folderCursor.getInt(folderCursor.getColumnIndex(BookmarksDatabaseHelper._ID));
+            int itemDatabaseId = folderCursor.getInt(folderCursor.getColumnIndexOrThrow(BookmarksDatabaseHelper._ID));
 
             // If this is a folder, recursively count the contents first.
             if (bookmarksDatabaseHelper.isFolder(itemDatabaseId)) {
@@ -1085,7 +1085,7 @@ public class BookmarksActivity extends AppCompatActivity implements CreateBookma
             folderCursor.moveToPosition(i);
 
             // Get the database ID of the item.
-            int itemDatabaseId = folderCursor.getInt(folderCursor.getColumnIndex(BookmarksDatabaseHelper._ID));
+            int itemDatabaseId = folderCursor.getInt(folderCursor.getColumnIndexOrThrow(BookmarksDatabaseHelper._ID));
 
             // If this is a folder, recursively delete the contents first.
             if (bookmarksDatabaseHelper.isFolder(itemDatabaseId)) {
@@ -1187,7 +1187,7 @@ public class BookmarksActivity extends AppCompatActivity implements CreateBookma
                 TextView bookmarkNameTextView = view.findViewById(R.id.bookmark_name);
 
                 // Get the favorite icon byte array from the `Cursor`.
-                byte[] favoriteIconByteArray = cursor.getBlob(cursor.getColumnIndex(BookmarksDatabaseHelper.FAVORITE_ICON));
+                byte[] favoriteIconByteArray = cursor.getBlob(cursor.getColumnIndexOrThrow(BookmarksDatabaseHelper.FAVORITE_ICON));
 
                 // Convert the byte array to a `Bitmap` beginning at the first byte and ending at the last.
                 Bitmap favoriteIconBitmap = BitmapFactory.decodeByteArray(favoriteIconByteArray, 0, favoriteIconByteArray.length);
@@ -1196,11 +1196,11 @@ public class BookmarksActivity extends AppCompatActivity implements CreateBookma
                 bookmarkFavoriteIcon.setImageBitmap(favoriteIconBitmap);
 
                 // Get the bookmark name from the cursor and display it in `bookmarkNameTextView`.
-                String bookmarkNameString = cursor.getString(cursor.getColumnIndex(BookmarksDatabaseHelper.BOOKMARK_NAME));
+                String bookmarkNameString = cursor.getString(cursor.getColumnIndexOrThrow(BookmarksDatabaseHelper.BOOKMARK_NAME));
                 bookmarkNameTextView.setText(bookmarkNameString);
 
                 // Make the font bold for folders.
-                if (cursor.getInt(cursor.getColumnIndex(BookmarksDatabaseHelper.IS_FOLDER)) == 1) {
+                if (cursor.getInt(cursor.getColumnIndexOrThrow(BookmarksDatabaseHelper.IS_FOLDER)) == 1) {
                     bookmarkNameTextView.setTypeface(Typeface.DEFAULT_BOLD);
                 } else {  // Reset the font to default for normal bookmarks.
                     bookmarkNameTextView.setTypeface(Typeface.DEFAULT);
index 13fedf04d450dfbd1274426b189de562fe59edfc..483b769f42dbf7de71b761c70961372c71fb110f 100644 (file)
@@ -203,7 +203,7 @@ public class BookmarksDatabaseViewActivity extends AppCompatActivity implements
 
 
                     // Get the folder icon byte array from the cursor.
-                    byte[] folderIconByteArray = cursor.getBlob(cursor.getColumnIndex(BookmarksDatabaseHelper.FAVORITE_ICON));
+                    byte[] folderIconByteArray = cursor.getBlob(cursor.getColumnIndexOrThrow(BookmarksDatabaseHelper.FAVORITE_ICON));
 
                     // Convert the byte array to a bitmap beginning at the first byte and ending at the last.
                     Bitmap folderIconBitmap = BitmapFactory.decodeByteArray(folderIconByteArray, 0, folderIconByteArray.length);
@@ -223,7 +223,7 @@ public class BookmarksDatabaseViewActivity extends AppCompatActivity implements
                 }
 
                 // Set the text view to display the folder name.
-                spinnerItemTextView.setText(cursor.getString(cursor.getColumnIndex(BookmarksDatabaseHelper.BOOKMARK_NAME)));
+                spinnerItemTextView.setText(cursor.getString(cursor.getColumnIndexOrThrow(BookmarksDatabaseHelper.BOOKMARK_NAME)));
             }
         };
 
@@ -293,15 +293,15 @@ public class BookmarksDatabaseViewActivity extends AppCompatActivity implements
 
             @Override
             public void bindView(View view, Context context, Cursor cursor) {
-                boolean isFolder = (cursor.getInt(cursor.getColumnIndex(BookmarksDatabaseHelper.IS_FOLDER)) == 1);
+                boolean isFolder = (cursor.getInt(cursor.getColumnIndexOrThrow(BookmarksDatabaseHelper.IS_FOLDER)) == 1);
 
                 // Get the database ID from the `Cursor` and display it in `bookmarkDatabaseIdTextView`.
-                int bookmarkDatabaseId = cursor.getInt(cursor.getColumnIndex(BookmarksDatabaseHelper._ID));
+                int bookmarkDatabaseId = cursor.getInt(cursor.getColumnIndexOrThrow(BookmarksDatabaseHelper._ID));
                 TextView bookmarkDatabaseIdTextView = view.findViewById(R.id.bookmarks_databaseview_database_id);
                 bookmarkDatabaseIdTextView.setText(String.valueOf(bookmarkDatabaseId));
 
                 // Get the favorite icon byte array from the `Cursor`.
-                byte[] favoriteIconByteArray = cursor.getBlob(cursor.getColumnIndex(BookmarksDatabaseHelper.FAVORITE_ICON));
+                byte[] favoriteIconByteArray = cursor.getBlob(cursor.getColumnIndexOrThrow(BookmarksDatabaseHelper.FAVORITE_ICON));
                 // Convert the byte array to a `Bitmap` beginning at the beginning at the first byte and ending at the last.
                 Bitmap favoriteIconBitmap = BitmapFactory.decodeByteArray(favoriteIconByteArray, 0, favoriteIconByteArray.length);
                 // Display the bitmap in `bookmarkFavoriteIcon`.
@@ -309,7 +309,7 @@ public class BookmarksDatabaseViewActivity extends AppCompatActivity implements
                 bookmarkFavoriteIcon.setImageBitmap(favoriteIconBitmap);
 
                 // Get the bookmark name from the `Cursor` and display it in `bookmarkNameTextView`.
-                String bookmarkNameString = cursor.getString(cursor.getColumnIndex(BookmarksDatabaseHelper.BOOKMARK_NAME));
+                String bookmarkNameString = cursor.getString(cursor.getColumnIndexOrThrow(BookmarksDatabaseHelper.BOOKMARK_NAME));
                 TextView bookmarkNameTextView = view.findViewById(R.id.bookmarks_databaseview_bookmark_name);
                 bookmarkNameTextView.setText(bookmarkNameString);
 
@@ -322,7 +322,7 @@ public class BookmarksDatabaseViewActivity extends AppCompatActivity implements
                 }
 
                 // Get the bookmark URL form the `Cursor` and display it in `bookmarkUrlTextView`.
-                String bookmarkUrlString = cursor.getString(cursor.getColumnIndex(BookmarksDatabaseHelper.BOOKMARK_URL));
+                String bookmarkUrlString = cursor.getString(cursor.getColumnIndexOrThrow(BookmarksDatabaseHelper.BOOKMARK_URL));
                 TextView bookmarkUrlTextView = view.findViewById(R.id.bookmarks_databaseview_bookmark_url);
                 bookmarkUrlTextView.setText(bookmarkUrlString);
 
@@ -334,12 +334,12 @@ public class BookmarksDatabaseViewActivity extends AppCompatActivity implements
                 }
 
                 // Get the display order from the `Cursor` and display it in `bookmarkDisplayOrderTextView`.
-                int bookmarkDisplayOrder = cursor.getInt(cursor.getColumnIndex(BookmarksDatabaseHelper.DISPLAY_ORDER));
+                int bookmarkDisplayOrder = cursor.getInt(cursor.getColumnIndexOrThrow(BookmarksDatabaseHelper.DISPLAY_ORDER));
                 TextView bookmarkDisplayOrderTextView = view.findViewById(R.id.bookmarks_databaseview_display_order);
                 bookmarkDisplayOrderTextView.setText(String.valueOf(bookmarkDisplayOrder));
 
                 // Get the parent folder from the `Cursor` and display it in `bookmarkParentFolder`.
-                String bookmarkParentFolder = cursor.getString(cursor.getColumnIndex(BookmarksDatabaseHelper.PARENT_FOLDER));
+                String bookmarkParentFolder = cursor.getString(cursor.getColumnIndexOrThrow(BookmarksDatabaseHelper.PARENT_FOLDER));
                 ImageView parentFolderImageView = view.findViewById(R.id.bookmarks_databaseview_parent_folder_icon);
                 TextView bookmarkParentFolderTextView = view.findViewById(R.id.bookmarks_databaseview_parent_folder);
 
@@ -377,7 +377,7 @@ public class BookmarksDatabaseViewActivity extends AppCompatActivity implements
             // Show the edit bookmark or edit bookmark folder dialog.
             if (bookmarksDatabaseHelper.isFolder(databaseId)) {
                 // Save the current folder name, which is used in `onSaveBookmarkFolder()`.
-                oldFolderNameString = bookmarksCursor.getString(bookmarksCursor.getColumnIndex(BookmarksDatabaseHelper.BOOKMARK_NAME));
+                oldFolderNameString = bookmarksCursor.getString(bookmarksCursor.getColumnIndexOrThrow(BookmarksDatabaseHelper.BOOKMARK_NAME));
 
                 // Show the edit bookmark folder dialog.
                 DialogFragment editBookmarkFolderDatabaseViewDialog = EditBookmarkFolderDatabaseViewDialog.folderDatabaseId(databaseId, favoriteIconBitmap);
@@ -472,7 +472,7 @@ public class BookmarksDatabaseViewActivity extends AppCompatActivity implements
                             // Get the position of the folder in the bookmarks cursor.
                             while ((folderPosition < 0) && (bookmarksCursor.getPosition() < bookmarksCursor.getCount())) {
                                 // Check if the folder database ID matches the bookmark database ID.
-                                if (folderDatabaseId == bookmarksCursor.getInt((bookmarksCursor.getColumnIndex(BookmarksDatabaseHelper._ID)))) {
+                                if (folderDatabaseId == bookmarksCursor.getInt(bookmarksCursor.getColumnIndexOrThrow(BookmarksDatabaseHelper._ID))) {
                                     // Get the folder position.
                                     folderPosition = bookmarksCursor.getPosition();
 
@@ -772,7 +772,7 @@ public class BookmarksDatabaseViewActivity extends AppCompatActivity implements
 
         while (folderCursor.getPosition() < folderCursor.getCount()) {
             // Get the bookmark database ID.
-            int bookmarkId = folderCursor.getInt(folderCursor.getColumnIndex(BookmarksDatabaseHelper._ID));
+            int bookmarkId = folderCursor.getInt(folderCursor.getColumnIndexOrThrow(BookmarksDatabaseHelper._ID));
 
             // Move the bookmarks cursor to the first position.
             bookmarksCursor.moveToFirst();
@@ -783,7 +783,7 @@ public class BookmarksDatabaseViewActivity extends AppCompatActivity implements
             // Get the position of this bookmark in the bookmarks cursor.
             while ((bookmarkPosition < 0) && (bookmarksCursor.getPosition() < bookmarksCursor.getCount())) {
                 // Check if the bookmark IDs match.
-                if (bookmarkId == bookmarksCursor.getInt(bookmarksCursor.getColumnIndex(BookmarksDatabaseHelper._ID))) {
+                if (bookmarkId == bookmarksCursor.getInt(bookmarksCursor.getColumnIndexOrThrow(BookmarksDatabaseHelper._ID))) {
                     // Get the bookmark position.
                     bookmarkPosition = bookmarksCursor.getPosition();
 
index c8e8e07c78ccb55af0b3f73b7961a226cfeaea29..f4a1e79b8a2bb7a6c6a6139e0a4912f2b66a81cd 100644 (file)
@@ -452,7 +452,7 @@ public class DomainsActivity extends AppCompatActivity implements AddDomainDialo
                     @Override
                     public void bindView(View view, Context context, Cursor cursor) {
                         // Get the domain name string.
-                        String domainNameString = cursor.getString(cursor.getColumnIndex(DomainsDatabaseHelper.DOMAIN_NAME));
+                        String domainNameString = cursor.getString(cursor.getColumnIndexOrThrow(DomainsDatabaseHelper.DOMAIN_NAME));
 
                         // Get a handle for the domain name text view.
                         TextView domainNameTextView = view.findViewById(R.id.domain_name_textview);
@@ -507,7 +507,7 @@ public class DomainsActivity extends AppCompatActivity implements AddDomainDialo
                                             @Override
                                             public void bindView(View view, Context context, Cursor cursor) {
                                                 /// Get the domain name string.
-                                                String domainNameString = cursor.getString(cursor.getColumnIndex(DomainsDatabaseHelper.DOMAIN_NAME));
+                                                String domainNameString = cursor.getString(cursor.getColumnIndexOrThrow(DomainsDatabaseHelper.DOMAIN_NAME));
 
                                                 // Get a handle for the domain name text view.
                                                 TextView domainNameTextView = view.findViewById(R.id.domain_name_textview);
@@ -868,7 +868,7 @@ public class DomainsActivity extends AppCompatActivity implements AddDomainDialo
             @Override
             public void bindView(View view, Context context, Cursor cursor) {
                 // Set the domain name.
-                String domainNameString = cursor.getString(cursor.getColumnIndex(DomainsDatabaseHelper.DOMAIN_NAME));
+                String domainNameString = cursor.getString(cursor.getColumnIndexOrThrow(DomainsDatabaseHelper.DOMAIN_NAME));
                 TextView domainNameTextView = view.findViewById(R.id.domain_name_textview);
                 domainNameTextView.setText(domainNameString);
             }
@@ -891,7 +891,7 @@ public class DomainsActivity extends AppCompatActivity implements AddDomainDialo
                 domainsCursor.moveToPosition(i);
 
                 // Get the database ID for this position.
-                int currentDatabaseId = domainsCursor.getInt(domainsCursor.getColumnIndex(DomainsDatabaseHelper._ID));
+                int currentDatabaseId = domainsCursor.getInt(domainsCursor.getColumnIndexOrThrow(DomainsDatabaseHelper._ID));
 
                 // Set `highlightedDomainPosition` if the database ID for this matches `highlightedDomainDatabaseId`.
                 if (highlightedDomainDatabaseId == currentDatabaseId) {
@@ -904,7 +904,7 @@ public class DomainsActivity extends AppCompatActivity implements AddDomainDialo
 
             // Get the database ID for the highlighted domain.
             domainsCursor.moveToPosition(highlightedDomainPosition);
-            currentDomainDatabaseId = domainsCursor.getInt(domainsCursor.getColumnIndex(DomainsDatabaseHelper._ID));
+            currentDomainDatabaseId = domainsCursor.getInt(domainsCursor.getColumnIndexOrThrow(DomainsDatabaseHelper._ID));
 
             // Create an arguments bundle.
             Bundle argumentsBundle = new Bundle();
index 71623cd7c3b3e4785639c27be5b143b0ea6a6f7f..9c6e5de181b27d8e15b8960948d7f2b17cc23af1 100644 (file)
@@ -90,7 +90,7 @@ class LogcatActivity : AppCompatActivity() {
                     contentResolverCursor.moveToFirst()
 
                     // Get the file name from the cursor.
-                    fileNameString = contentResolverCursor.getString(contentResolverCursor.getColumnIndex(OpenableColumns.DISPLAY_NAME))
+                    fileNameString = contentResolverCursor.getString(contentResolverCursor.getColumnIndexOrThrow(OpenableColumns.DISPLAY_NAME))
 
                     // Close the cursor.
                     contentResolverCursor.close()
index 00a64e2098f2a093f6cdd2e6a87266337821c3ed..d44636432e2057a9d321fb4facf72b95e9e89fd7 100644 (file)
@@ -21,6 +21,7 @@
 
 package com.stoutner.privacybrowser.activities;
 
+import android.animation.ObjectAnimator;
 import android.annotation.SuppressLint;
 import android.app.Activity;
 import android.app.Dialog;
@@ -170,7 +171,6 @@ import java.net.URLEncoder;
 import java.text.NumberFormat;
 
 import java.util.ArrayList;
-import java.util.Calendar;
 import java.util.Date;
 import java.util.HashMap;
 import java.util.HashSet;
@@ -186,24 +186,19 @@ public class MainWebViewActivity extends AppCompatActivity implements CreateBook
         PinnedMismatchDialog.PinnedMismatchListener, PopulateBlocklists.PopulateBlocklistsListener, SaveDialog.SaveListener, UrlHistoryDialog.NavigateHistoryListener,
         WebViewTabFragment.NewTabListener {
 
-    // The executor service handles background tasks.  It is accessed from `ViewSourceActivity`.
+    // Define the public static variables.
     public static ExecutorService executorService = Executors.newFixedThreadPool(4);
-
-    // `orbotStatus` is public static so it can be accessed from `OrbotProxyHelper`.  It is also used in `onCreate()`, `onResume()`, and `applyProxy()`.
     public static String orbotStatus = "unknown";
-
-    // The WebView pager adapter is accessed from `HttpAuthenticationDialog`, `PinnedMismatchDialog`, and `SslCertificateErrorDialog`.  It is also used in `onCreate()`, `onResume()`, and `addTab()`.
-    public static WebViewPagerAdapter webViewPagerAdapter;
-
-    // `restartFromBookmarksActivity` is public static so it can be accessed from `BookmarksActivity`.  It is also used in `onRestart()`.
-    public static boolean restartFromBookmarksActivity;
-
-    // Define the public static variables.
     public static ArrayList<PendingDialog> pendingDialogsArrayList =  new ArrayList<>();
+    public static String proxyMode = ProxyHelper.NONE;
 
-    // `currentBookmarksFolder` is public static so it can be accessed from `BookmarksActivity`.  It is also used in `onCreate()`, `onBackPressed()`, `onCreateBookmark()`, `onCreateBookmarkFolder()`,
-    // `onSaveEditBookmark()`, `onSaveEditBookmarkFolder()`, and `loadBookmarksFolder()`.
+    // Declare the public static variables.
     public static String currentBookmarksFolder;
+    public static boolean restartFromBookmarksActivity;
+    public static WebViewPagerAdapter webViewPagerAdapter;
+
+    // Declare the public static views.
+    public static AppBarLayout appBarLayout;
 
     // The user agent constants are public static so they can be accessed from `SettingsFragment`, `DomainsActivity`, and `DomainSettingsFragment`.
     public final static int UNRECOGNIZED_USER_AGENT = -1;
@@ -217,11 +212,6 @@ public class MainWebViewActivity extends AppCompatActivity implements CreateBook
     private final int BROWSE_FILE_UPLOAD_REQUEST_CODE = 0;
     public final static int BROWSE_OPEN_REQUEST_CODE = 1;
 
-    // The proxy mode is public static so it can be accessed from `ProxyHelper()`.
-    // It is also used in `onRestart()`, `onPrepareOptionsMenu()`, `onOptionsItemSelected()`, `applyAppSettings()`, and `applyProxy()`.
-    // It will be updated in `applyAppSettings()`, but it needs to be initialized here or the first run of `onPrepareOptionsMenu()` crashes.
-    public static String proxyMode = ProxyHelper.NONE;
-
     // Define the saved instance state constants.
     private final String SAVED_STATE_ARRAY_LIST = "saved_state_array_list";
     private final String SAVED_NESTED_SCROLL_WEBVIEW_STATE_ARRAY_LIST = "saved_nested_scroll_webview_state_array_list";
@@ -264,10 +254,6 @@ public class MainWebViewActivity extends AppCompatActivity implements CreateBook
     private ForegroundColorSpan initialGrayColorSpan;
     private ForegroundColorSpan finalGrayColorSpan;
 
-    // `bookmarksDatabaseHelper` is used in `onCreate()`, `onDestroy`, `onOptionsItemSelected()`, `onCreateBookmark()`, `onCreateBookmarkFolder()`, `onSaveEditBookmark()`, `onSaveEditBookmarkFolder()`,
-    // and `loadBookmarksFolder()`.
-    private BookmarksDatabaseHelper bookmarksDatabaseHelper;
-
     // `bookmarksCursor` is used in `onDestroy()`, `onOptionsItemSelected()`, `onCreateBookmark()`, `onCreateBookmarkFolder()`, `onSaveEditBookmark()`, `onSaveEditBookmarkFolder()`, and `loadBookmarksFolder()`.
     private Cursor bookmarksCursor;
 
@@ -291,30 +277,31 @@ public class MainWebViewActivity extends AppCompatActivity implements CreateBook
     private boolean sanitizeTwitterAmpRedirects;
 
     // Declare the class variables
-    private BroadcastReceiver orbotStatusBroadcastReceiver;
-    private String webViewDefaultUserAgent;
-    private boolean incognitoModeEnabled;
-    private boolean fullScreenBrowsingModeEnabled;
-    private boolean inFullScreenBrowsingMode;
+    private BookmarksDatabaseHelper bookmarksDatabaseHelper;
+    private boolean bottomAppBar;
+    private boolean displayingFullScreenVideo;
     private boolean downloadWithExternalApp;
+    private boolean fullScreenBrowsingModeEnabled;
     private boolean hideAppBar;
-    private boolean scrollAppBar;
-    private boolean bottomAppBar;
+    private boolean incognitoModeEnabled;
+    private boolean inFullScreenBrowsingMode;
     private boolean loadingNewIntent;
-    private boolean reapplyDomainSettingsOnRestart;
+    private BroadcastReceiver orbotStatusBroadcastReceiver;
+    private ProxyHelper proxyHelper;
     private boolean reapplyAppSettingsOnRestart;
-    private boolean displayingFullScreenVideo;
+    private boolean reapplyDomainSettingsOnRestart;
+    private boolean scrollAppBar;
     private boolean waitingForProxy;
+    private String webViewDefaultUserAgent;
 
     // Define the class variables.
-    private long lastScrollUpdate = 0;
+    private ObjectAnimator objectAnimator = new ObjectAnimator();
     private String saveUrlString = "";
 
     // Declare the class views.
     private FrameLayout rootFrameLayout;
     private DrawerLayout drawerLayout;
     private CoordinatorLayout coordinatorLayout;
-    private AppBarLayout appBarLayout;
     private Toolbar toolbar;
     private RelativeLayout urlRelativeLayout;
     private EditText urlEditText;
@@ -443,7 +430,7 @@ public class MainWebViewActivity extends AppCompatActivity implements CreateBook
                                             contentResolverCursor.moveToFirst();
 
                                             // Get the file name from the cursor.
-                                            fileNameString = contentResolverCursor.getString(contentResolverCursor.getColumnIndex(OpenableColumns.DISPLAY_NAME));
+                                            fileNameString = contentResolverCursor.getString(contentResolverCursor.getColumnIndexOrThrow(OpenableColumns.DISPLAY_NAME));
 
                                             // Close the cursor.
                                             contentResolverCursor.close();
@@ -616,6 +603,9 @@ public class MainWebViewActivity extends AppCompatActivity implements CreateBook
         // Store up to 100 tabs in memory.
         webViewPager.setOffscreenPageLimit(100);
 
+        // Instantiate the proxy helper.
+        proxyHelper = new ProxyHelper();
+
         // Initialize the app.
         initializeApp();
 
@@ -3158,7 +3148,7 @@ public class MainWebViewActivity extends AppCompatActivity implements CreateBook
                 orbotStatus = intent.getStringExtra("org.torproject.android.intent.extra.STATUS");
 
                 // If Privacy Browser is waiting on the proxy, load the website now that Orbot is connected.
-                if ((orbotStatus != null) && orbotStatus.equals("ON") && waitingForProxy) {
+                if ((orbotStatus != null) && orbotStatus.equals(ProxyHelper.ORBOT_STATUS_ON) && waitingForProxy) {
                     // Reset the waiting for proxy status.
                     waitingForProxy = false;
 
@@ -3369,17 +3359,8 @@ public class MainWebViewActivity extends AppCompatActivity implements CreateBook
 
         // Implement swipe to refresh.
         swipeRefreshLayout.setOnRefreshListener(() -> {
-            // Check the visibility of the bottom app bar.  Sometimes it is hidden if the WebView is the same size as the visible screen.
-            if (bottomAppBar && scrollAppBar && (appBarLayout.getVisibility() == View.GONE)) {  // The bottom app bar is currently hidden.
-                // Show the app bar.
-                appBarLayout.setVisibility(View.VISIBLE);
-
-                // Disable the refreshing animation.
-                swipeRefreshLayout.setRefreshing(false);
-            } else {  // A bottom app bar is not currently hidden.
-                // Reload the website.
-                currentWebView.reload();
-            }
+            // Reload the website.
+            currentWebView.reload();
         });
 
         // Store the default progress view offsets for use later in `initializeWebView()`.
@@ -3425,15 +3406,15 @@ public class MainWebViewActivity extends AppCompatActivity implements CreateBook
             bookmarkCursor.moveToFirst();
 
             // Act upon the bookmark according to the type.
-            if (bookmarkCursor.getInt(bookmarkCursor.getColumnIndex(BookmarksDatabaseHelper.IS_FOLDER)) == 1) {  // The selected bookmark is a folder.
+            if (bookmarkCursor.getInt(bookmarkCursor.getColumnIndexOrThrow(BookmarksDatabaseHelper.IS_FOLDER)) == 1) {  // The selected bookmark is a folder.
                 // Store the new folder name in `currentBookmarksFolder`.
-                currentBookmarksFolder = bookmarkCursor.getString(bookmarkCursor.getColumnIndex(BookmarksDatabaseHelper.BOOKMARK_NAME));
+                currentBookmarksFolder = bookmarkCursor.getString(bookmarkCursor.getColumnIndexOrThrow(BookmarksDatabaseHelper.BOOKMARK_NAME));
 
                 // Load the new folder.
                 loadBookmarksFolder();
             } else {  // The selected bookmark is not a folder.
                 // Load the bookmark URL.
-                loadUrl(currentWebView, bookmarkCursor.getString(bookmarkCursor.getColumnIndex(BookmarksDatabaseHelper.BOOKMARK_URL)));
+                loadUrl(currentWebView, bookmarkCursor.getString(bookmarkCursor.getColumnIndexOrThrow(BookmarksDatabaseHelper.BOOKMARK_URL)));
 
                 // Close the bookmarks drawer.
                 drawerLayout.closeDrawer(GravityCompat.END);
@@ -3453,7 +3434,7 @@ public class MainWebViewActivity extends AppCompatActivity implements CreateBook
             // Check to see if the bookmark is a folder.
             if (isFolder) {  // The bookmark is a folder.
                 // Save the current folder name, which is used in `onSaveEditBookmarkFolder()`.
-                oldFolderNameString = bookmarksCursor.getString(bookmarksCursor.getColumnIndex(BookmarksDatabaseHelper.BOOKMARK_NAME));
+                oldFolderNameString = bookmarksCursor.getString(bookmarksCursor.getColumnIndexOrThrow(BookmarksDatabaseHelper.BOOKMARK_NAME));
 
                 // Instantiate the edit folder bookmark dialog.
                 DialogFragment editBookmarkFolderDialog = EditBookmarkFolderDialog.folderDatabaseId(databaseId, currentWebView.getFavoriteOrDefaultIcon());
@@ -3468,7 +3449,7 @@ public class MainWebViewActivity extends AppCompatActivity implements CreateBook
                 bookmarkCursor.moveToFirst();
 
                 // Load the bookmark in a new tab but do not switch to the tab or close the drawer.
-                addNewTab(bookmarkCursor.getString(bookmarkCursor.getColumnIndex(BookmarksDatabaseHelper.BOOKMARK_URL)), false);
+                addNewTab(bookmarkCursor.getString(bookmarkCursor.getColumnIndexOrThrow(BookmarksDatabaseHelper.BOOKMARK_URL)), false);
 
                 // Display a snackbar.
                 Snackbar.make(currentWebView, R.string.bookmark_opened_in_background, Snackbar.LENGTH_SHORT).show();
@@ -3549,7 +3530,7 @@ public class MainWebViewActivity extends AppCompatActivity implements CreateBook
         fullScreenBrowsingModeEnabled = sharedPreferences.getBoolean("full_screen_browsing_mode", false);
         downloadWithExternalApp = sharedPreferences.getBoolean(getString(R.string.download_with_external_app_key), false);
         hideAppBar = sharedPreferences.getBoolean("hide_app_bar", true);
-        scrollAppBar = sharedPreferences.getBoolean("scroll_app_bar", true);
+        scrollAppBar = sharedPreferences.getBoolean(getString(R.string.scroll_app_bar_key), true);
 
         // Apply the saved proxy mode if the app has been restarted.
         if (savedProxyMode != null) {
@@ -3752,14 +3733,14 @@ public class MainWebViewActivity extends AppCompatActivity implements CreateBook
             Set<String> domainSettingsSet = new HashSet<>();
 
             // Get the domain name column index.
-            int domainNameColumnIndex = domainNameCursor.getColumnIndex(DomainsDatabaseHelper.DOMAIN_NAME);
+            int domainNameColumnIndex = domainNameCursor.getColumnIndexOrThrow(DomainsDatabaseHelper.DOMAIN_NAME);
 
             // Populate `domainSettingsSet`.
             for (int i = 0; i < domainNameCursor.getCount(); i++) {
-                // Move `domainsCursor` to the current row.
+                // Move the domains cursor to the current row.
                 domainNameCursor.moveToPosition(i);
 
-                // Store the domain name in `domainSettingsSet`.
+                // Store the domain name in the domain settings set.
                 domainSettingsSet.add(domainNameCursor.getString(domainNameColumnIndex));
             }
 
@@ -3823,37 +3804,37 @@ public class MainWebViewActivity extends AppCompatActivity implements CreateBook
                 currentDomainSettingsCursor.moveToFirst();
 
                 // Get the settings from the cursor.
-                nestedScrollWebView.setDomainSettingsDatabaseId(currentDomainSettingsCursor.getInt(currentDomainSettingsCursor.getColumnIndex(DomainsDatabaseHelper._ID)));
-                nestedScrollWebView.getSettings().setJavaScriptEnabled(currentDomainSettingsCursor.getInt(currentDomainSettingsCursor.getColumnIndex(DomainsDatabaseHelper.ENABLE_JAVASCRIPT)) == 1);
-                nestedScrollWebView.setAcceptCookies(currentDomainSettingsCursor.getInt(currentDomainSettingsCursor.getColumnIndex(DomainsDatabaseHelper.COOKIES)) == 1);
-                nestedScrollWebView.getSettings().setDomStorageEnabled(currentDomainSettingsCursor.getInt(currentDomainSettingsCursor.getColumnIndex(DomainsDatabaseHelper.ENABLE_DOM_STORAGE)) == 1);
+                nestedScrollWebView.setDomainSettingsDatabaseId(currentDomainSettingsCursor.getInt(currentDomainSettingsCursor.getColumnIndexOrThrow(DomainsDatabaseHelper._ID)));
+                nestedScrollWebView.getSettings().setJavaScriptEnabled(currentDomainSettingsCursor.getInt(currentDomainSettingsCursor.getColumnIndexOrThrow(DomainsDatabaseHelper.ENABLE_JAVASCRIPT)) == 1);
+                nestedScrollWebView.setAcceptCookies(currentDomainSettingsCursor.getInt(currentDomainSettingsCursor.getColumnIndexOrThrow(DomainsDatabaseHelper.COOKIES)) == 1);
+                nestedScrollWebView.getSettings().setDomStorageEnabled(currentDomainSettingsCursor.getInt(currentDomainSettingsCursor.getColumnIndexOrThrow(DomainsDatabaseHelper.ENABLE_DOM_STORAGE)) == 1);
                 // Form data can be removed once the minimum API >= 26.
-                boolean saveFormData = (currentDomainSettingsCursor.getInt(currentDomainSettingsCursor.getColumnIndex(DomainsDatabaseHelper.ENABLE_FORM_DATA)) == 1);
-                nestedScrollWebView.setEasyListEnabled(currentDomainSettingsCursor.getInt(currentDomainSettingsCursor.getColumnIndex(DomainsDatabaseHelper.ENABLE_EASYLIST)) == 1);
-                nestedScrollWebView.setEasyPrivacyEnabled(currentDomainSettingsCursor.getInt(currentDomainSettingsCursor.getColumnIndex(DomainsDatabaseHelper.ENABLE_EASYPRIVACY)) == 1);
-                nestedScrollWebView.setFanboysAnnoyanceListEnabled(currentDomainSettingsCursor.getInt(currentDomainSettingsCursor.getColumnIndex(DomainsDatabaseHelper.ENABLE_FANBOYS_ANNOYANCE_LIST)) == 1);
-                nestedScrollWebView.setFanboysSocialBlockingListEnabled(currentDomainSettingsCursor.getInt(currentDomainSettingsCursor.getColumnIndex(
+                boolean saveFormData = (currentDomainSettingsCursor.getInt(currentDomainSettingsCursor.getColumnIndexOrThrow(DomainsDatabaseHelper.ENABLE_FORM_DATA)) == 1);
+                nestedScrollWebView.setEasyListEnabled(currentDomainSettingsCursor.getInt(currentDomainSettingsCursor.getColumnIndexOrThrow(DomainsDatabaseHelper.ENABLE_EASYLIST)) == 1);
+                nestedScrollWebView.setEasyPrivacyEnabled(currentDomainSettingsCursor.getInt(currentDomainSettingsCursor.getColumnIndexOrThrow(DomainsDatabaseHelper.ENABLE_EASYPRIVACY)) == 1);
+                nestedScrollWebView.setFanboysAnnoyanceListEnabled(currentDomainSettingsCursor.getInt(currentDomainSettingsCursor.getColumnIndexOrThrow(DomainsDatabaseHelper.ENABLE_FANBOYS_ANNOYANCE_LIST)) == 1);
+                nestedScrollWebView.setFanboysSocialBlockingListEnabled(currentDomainSettingsCursor.getInt(currentDomainSettingsCursor.getColumnIndexOrThrow(
                         DomainsDatabaseHelper.ENABLE_FANBOYS_SOCIAL_BLOCKING_LIST)) == 1);
-                nestedScrollWebView.setUltraListEnabled(currentDomainSettingsCursor.getInt(currentDomainSettingsCursor.getColumnIndex(DomainsDatabaseHelper.ULTRALIST)) == 1);
-                nestedScrollWebView.setUltraPrivacyEnabled(currentDomainSettingsCursor.getInt(currentDomainSettingsCursor.getColumnIndex(DomainsDatabaseHelper.ENABLE_ULTRAPRIVACY)) == 1);
-                nestedScrollWebView.setBlockAllThirdPartyRequests(currentDomainSettingsCursor.getInt(currentDomainSettingsCursor.getColumnIndex(DomainsDatabaseHelper.BLOCK_ALL_THIRD_PARTY_REQUESTS)) == 1);
-                String userAgentName = currentDomainSettingsCursor.getString(currentDomainSettingsCursor.getColumnIndex(DomainsDatabaseHelper.USER_AGENT));
-                int fontSize = currentDomainSettingsCursor.getInt(currentDomainSettingsCursor.getColumnIndex(DomainsDatabaseHelper.FONT_SIZE));
-                int swipeToRefreshInt = currentDomainSettingsCursor.getInt(currentDomainSettingsCursor.getColumnIndex(DomainsDatabaseHelper.SWIPE_TO_REFRESH));
-                int webViewThemeInt = currentDomainSettingsCursor.getInt(currentDomainSettingsCursor.getColumnIndex(DomainsDatabaseHelper.WEBVIEW_THEME));
-                int wideViewportInt = currentDomainSettingsCursor.getInt(currentDomainSettingsCursor.getColumnIndex(DomainsDatabaseHelper.WIDE_VIEWPORT));
-                int displayWebpageImagesInt = currentDomainSettingsCursor.getInt(currentDomainSettingsCursor.getColumnIndex(DomainsDatabaseHelper.DISPLAY_IMAGES));
-                boolean pinnedSslCertificate = (currentDomainSettingsCursor.getInt(currentDomainSettingsCursor.getColumnIndex(DomainsDatabaseHelper.PINNED_SSL_CERTIFICATE)) == 1);
-                String pinnedSslIssuedToCName = currentDomainSettingsCursor.getString(currentDomainSettingsCursor.getColumnIndex(DomainsDatabaseHelper.SSL_ISSUED_TO_COMMON_NAME));
-                String pinnedSslIssuedToOName = currentDomainSettingsCursor.getString(currentDomainSettingsCursor.getColumnIndex(DomainsDatabaseHelper.SSL_ISSUED_TO_ORGANIZATION));
-                String pinnedSslIssuedToUName = currentDomainSettingsCursor.getString(currentDomainSettingsCursor.getColumnIndex(DomainsDatabaseHelper.SSL_ISSUED_TO_ORGANIZATIONAL_UNIT));
-                String pinnedSslIssuedByCName = currentDomainSettingsCursor.getString(currentDomainSettingsCursor.getColumnIndex(DomainsDatabaseHelper.SSL_ISSUED_BY_COMMON_NAME));
-                String pinnedSslIssuedByOName = currentDomainSettingsCursor.getString(currentDomainSettingsCursor.getColumnIndex(DomainsDatabaseHelper.SSL_ISSUED_BY_ORGANIZATION));
-                String pinnedSslIssuedByUName = currentDomainSettingsCursor.getString(currentDomainSettingsCursor.getColumnIndex(DomainsDatabaseHelper.SSL_ISSUED_BY_ORGANIZATIONAL_UNIT));
-                Date pinnedSslStartDate = new Date(currentDomainSettingsCursor.getLong(currentDomainSettingsCursor.getColumnIndex(DomainsDatabaseHelper.SSL_START_DATE)));
-                Date pinnedSslEndDate = new Date(currentDomainSettingsCursor.getLong(currentDomainSettingsCursor.getColumnIndex(DomainsDatabaseHelper.SSL_END_DATE)));
-                boolean pinnedIpAddresses = (currentDomainSettingsCursor.getInt(currentDomainSettingsCursor.getColumnIndex(DomainsDatabaseHelper.PINNED_IP_ADDRESSES)) == 1);
-                String pinnedHostIpAddresses = currentDomainSettingsCursor.getString(currentDomainSettingsCursor.getColumnIndex(DomainsDatabaseHelper.IP_ADDRESSES));
+                nestedScrollWebView.setUltraListEnabled(currentDomainSettingsCursor.getInt(currentDomainSettingsCursor.getColumnIndexOrThrow(DomainsDatabaseHelper.ULTRALIST)) == 1);
+                nestedScrollWebView.setUltraPrivacyEnabled(currentDomainSettingsCursor.getInt(currentDomainSettingsCursor.getColumnIndexOrThrow(DomainsDatabaseHelper.ENABLE_ULTRAPRIVACY)) == 1);
+                nestedScrollWebView.setBlockAllThirdPartyRequests(currentDomainSettingsCursor.getInt(currentDomainSettingsCursor.getColumnIndexOrThrow(DomainsDatabaseHelper.BLOCK_ALL_THIRD_PARTY_REQUESTS)) == 1);
+                String userAgentName = currentDomainSettingsCursor.getString(currentDomainSettingsCursor.getColumnIndexOrThrow(DomainsDatabaseHelper.USER_AGENT));
+                int fontSize = currentDomainSettingsCursor.getInt(currentDomainSettingsCursor.getColumnIndexOrThrow(DomainsDatabaseHelper.FONT_SIZE));
+                int swipeToRefreshInt = currentDomainSettingsCursor.getInt(currentDomainSettingsCursor.getColumnIndexOrThrow(DomainsDatabaseHelper.SWIPE_TO_REFRESH));
+                int webViewThemeInt = currentDomainSettingsCursor.getInt(currentDomainSettingsCursor.getColumnIndexOrThrow(DomainsDatabaseHelper.WEBVIEW_THEME));
+                int wideViewportInt = currentDomainSettingsCursor.getInt(currentDomainSettingsCursor.getColumnIndexOrThrow(DomainsDatabaseHelper.WIDE_VIEWPORT));
+                int displayWebpageImagesInt = currentDomainSettingsCursor.getInt(currentDomainSettingsCursor.getColumnIndexOrThrow(DomainsDatabaseHelper.DISPLAY_IMAGES));
+                boolean pinnedSslCertificate = (currentDomainSettingsCursor.getInt(currentDomainSettingsCursor.getColumnIndexOrThrow(DomainsDatabaseHelper.PINNED_SSL_CERTIFICATE)) == 1);
+                String pinnedSslIssuedToCName = currentDomainSettingsCursor.getString(currentDomainSettingsCursor.getColumnIndexOrThrow(DomainsDatabaseHelper.SSL_ISSUED_TO_COMMON_NAME));
+                String pinnedSslIssuedToOName = currentDomainSettingsCursor.getString(currentDomainSettingsCursor.getColumnIndexOrThrow(DomainsDatabaseHelper.SSL_ISSUED_TO_ORGANIZATION));
+                String pinnedSslIssuedToUName = currentDomainSettingsCursor.getString(currentDomainSettingsCursor.getColumnIndexOrThrow(DomainsDatabaseHelper.SSL_ISSUED_TO_ORGANIZATIONAL_UNIT));
+                String pinnedSslIssuedByCName = currentDomainSettingsCursor.getString(currentDomainSettingsCursor.getColumnIndexOrThrow(DomainsDatabaseHelper.SSL_ISSUED_BY_COMMON_NAME));
+                String pinnedSslIssuedByOName = currentDomainSettingsCursor.getString(currentDomainSettingsCursor.getColumnIndexOrThrow(DomainsDatabaseHelper.SSL_ISSUED_BY_ORGANIZATION));
+                String pinnedSslIssuedByUName = currentDomainSettingsCursor.getString(currentDomainSettingsCursor.getColumnIndexOrThrow(DomainsDatabaseHelper.SSL_ISSUED_BY_ORGANIZATIONAL_UNIT));
+                Date pinnedSslStartDate = new Date(currentDomainSettingsCursor.getLong(currentDomainSettingsCursor.getColumnIndexOrThrow(DomainsDatabaseHelper.SSL_START_DATE)));
+                Date pinnedSslEndDate = new Date(currentDomainSettingsCursor.getLong(currentDomainSettingsCursor.getColumnIndexOrThrow(DomainsDatabaseHelper.SSL_END_DATE)));
+                boolean pinnedIpAddresses = (currentDomainSettingsCursor.getInt(currentDomainSettingsCursor.getColumnIndexOrThrow(DomainsDatabaseHelper.PINNED_IP_ADDRESSES)) == 1);
+                String pinnedHostIpAddresses = currentDomainSettingsCursor.getString(currentDomainSettingsCursor.getColumnIndexOrThrow(DomainsDatabaseHelper.IP_ADDRESSES));
 
                 // Close the current host domain settings cursor.
                 currentDomainSettingsCursor.close();
@@ -4170,8 +4151,8 @@ public class MainWebViewActivity extends AppCompatActivity implements CreateBook
     }
 
     private void applyProxy(boolean reloadWebViews) {
-        // Set the proxy according to the mode.  `this` refers to the current activity where an alert dialog might be displayed.
-        ProxyHelper.setProxy(getApplicationContext(), appBarLayout, proxyMode);
+        // Set the proxy according to the mode.
+        proxyHelper.setProxy(getApplicationContext(), appBarLayout, proxyMode);
 
         // Reset the waiting for proxy tracker.
         waitingForProxy = false;
@@ -4212,7 +4193,7 @@ public class MainWebViewActivity extends AppCompatActivity implements CreateBook
                     packageManager.getPackageInfo("org.torproject.android", 0);
 
                     // Check to see if the proxy is ready.
-                    if (!orbotStatus.equals("ON")) {  // Orbot is not ready.
+                    if (!orbotStatus.equals(ProxyHelper.ORBOT_STATUS_ON)) {  // Orbot is not ready.
                         // Set the waiting for proxy status.
                         waitingForProxy = true;
 
@@ -4441,7 +4422,7 @@ public class MainWebViewActivity extends AppCompatActivity implements CreateBook
                 TextView bookmarkNameTextView = view.findViewById(R.id.bookmark_name);
 
                 // Get the favorite icon byte array from the cursor.
-                byte[] favoriteIconByteArray = cursor.getBlob(cursor.getColumnIndex(BookmarksDatabaseHelper.FAVORITE_ICON));
+                byte[] favoriteIconByteArray = cursor.getBlob(cursor.getColumnIndexOrThrow(BookmarksDatabaseHelper.FAVORITE_ICON));
 
                 // Convert the byte array to a `Bitmap` beginning at the first byte and ending at the last.
                 Bitmap favoriteIconBitmap = BitmapFactory.decodeByteArray(favoriteIconByteArray, 0, favoriteIconByteArray.length);
@@ -4450,11 +4431,11 @@ public class MainWebViewActivity extends AppCompatActivity implements CreateBook
                 bookmarkFavoriteIcon.setImageBitmap(favoriteIconBitmap);
 
                 // Get the bookmark name from the cursor and display it in `bookmarkNameTextView`.
-                String bookmarkNameString = cursor.getString(cursor.getColumnIndex(BookmarksDatabaseHelper.BOOKMARK_NAME));
+                String bookmarkNameString = cursor.getString(cursor.getColumnIndexOrThrow(BookmarksDatabaseHelper.BOOKMARK_NAME));
                 bookmarkNameTextView.setText(bookmarkNameString);
 
                 // Make the font bold for folders.
-                if (cursor.getInt(cursor.getColumnIndex(BookmarksDatabaseHelper.IS_FOLDER)) == 1) {
+                if (cursor.getInt(cursor.getColumnIndexOrThrow(BookmarksDatabaseHelper.IS_FOLDER)) == 1) {
                     bookmarkNameTextView.setTypeface(Typeface.DEFAULT_BOLD);
                 } else {  // Reset the font to default for normal bookmarks.
                     bookmarkNameTextView.setTypeface(Typeface.DEFAULT);
@@ -4700,8 +4681,12 @@ public class MainWebViewActivity extends AppCompatActivity implements CreateBook
         webViewPagerAdapter.addPage(newTabNumber, webViewPager, url, moveToTab);
 
         // Show the app bar if it is at the bottom of the screen and the new tab is taking focus.
-        if (bottomAppBar && moveToTab) {
-            appBarLayout.setVisibility(View.VISIBLE);
+        if (bottomAppBar && moveToTab && (appBarLayout.getTranslationY() != 0)) {
+            // Animate the bottom app bar onto the screen.
+            objectAnimator = ObjectAnimator.ofFloat(appBarLayout, "translationY", 0);
+
+            // Make it so.
+            objectAnimator.start();
         }
     }
 
@@ -5136,7 +5121,7 @@ public class MainWebViewActivity extends AppCompatActivity implements CreateBook
         assert inputMethodManager != null;
 
         // Set the app bar scrolling.
-        nestedScrollWebView.setNestedScrollingEnabled(sharedPreferences.getBoolean("scroll_app_bar", true));
+        nestedScrollWebView.setNestedScrollingEnabled(scrollAppBar);
 
         // Allow pinch to zoom.
         nestedScrollWebView.getSettings().setBuiltInZoomControls(true);
@@ -5331,16 +5316,21 @@ public class MainWebViewActivity extends AppCompatActivity implements CreateBook
                     swipeRefreshLayout.setEnabled(false);
                 }
 
-                //  Set the visibility of the bottom app bar.
-                if (bottomAppBar && scrollAppBar && (Calendar.getInstance().getTimeInMillis() - lastScrollUpdate > 100)) {
-                    if (scrollY - oldScrollY > 25) {  // The WebView was scrolled down.
-                        appBarLayout.setVisibility(View.GONE);
-                    } else if (scrollY - oldScrollY < -25) {  // The WebView was scrolled up.
-                        appBarLayout.setVisibility(View.VISIBLE);
-                    }
+                //  Scroll the bottom app bar if enabled.
+                if (bottomAppBar && scrollAppBar && !objectAnimator.isRunning()) {
+                    if (scrollY < oldScrollY) {  // The WebView was scrolled down.
+                        // Animate the bottom app bar onto the screen.
+                        objectAnimator = ObjectAnimator.ofFloat(appBarLayout, "translationY", 0);
+
+                        // Make it so.
+                        objectAnimator.start();
+                    } else if (scrollY > oldScrollY) {  // The WebView was scrolled up.
+                        // Animate the bottom app bar off the screen.
+                        objectAnimator = ObjectAnimator.ofFloat(appBarLayout, "translationY", appBarLayout.getHeight());
 
-                    // Update the last scroll update variable.  This prevents the app bar from flashing on and off at the bottom of the screen.
-                    lastScrollUpdate = Calendar.getInstance().getTimeInMillis();
+                        // Make it so.
+                        objectAnimator.start();
+                    }
                 }
 
                 // Reinforce the system UI visibility flags if in full screen browsing mode.
index 759b79c0fb00ebbbe91fc20bb21e002392c4bfb7..ad2c09821b6ab9757245cea74e62396623f8d950 100644 (file)
@@ -58,7 +58,7 @@ import com.stoutner.privacybrowser.viewmodels.WebViewSource
 
 import java.util.Locale
 
-// Declare the public constants.
+// Define the public constants.
 const val CURRENT_URL = "current_url"
 const val USER_AGENT = "user_agent"
 
index 1fef50dcd77005271ee30422ab3847809f066145..c65c0eb4396c05dc17cf1125ade131b3e6195db4 100644 (file)
@@ -69,7 +69,7 @@ public class SaveAboutVersionImage extends AsyncTask<Void, Void, String> {
             contentResolverCursor.moveToFirst();
 
             // Get the file name from the cursor.
-            fileNameString = contentResolverCursor.getString(contentResolverCursor.getColumnIndex(OpenableColumns.DISPLAY_NAME));
+            fileNameString = contentResolverCursor.getString(contentResolverCursor.getColumnIndexOrThrow(OpenableColumns.DISPLAY_NAME));
 
             // Close the cursor.
             contentResolverCursor.close();
index 6a4671bc7e20b478c9ed4d014efaf0cd3f86dcff..aaa4ce2bf67c171fc96e73eefc60491f3e5f2831 100644 (file)
@@ -80,7 +80,7 @@ public class SaveUrl extends AsyncTask<String, Long, String> {
             contentResolverCursor.moveToFirst();
 
             // Get the file name from the cursor.
-            fileNameString = contentResolverCursor.getString(contentResolverCursor.getColumnIndex(OpenableColumns.DISPLAY_NAME));
+            fileNameString = contentResolverCursor.getString(contentResolverCursor.getColumnIndexOrThrow(OpenableColumns.DISPLAY_NAME));
 
             // Close the cursor.
             contentResolverCursor.close();
index f4b43d6c2d00d89cb1bef464e15b6bb3e502a1e4..bd374be39b48851b379340344048bff4c96daae5 100644 (file)
@@ -69,7 +69,7 @@ public class SaveWebpageImage extends AsyncTask<Void, Void, String> {
             contentResolverCursor.moveToFirst();
 
             // Get the file name from the cursor.
-            fileNameString = contentResolverCursor.getString(contentResolverCursor.getColumnIndex(OpenableColumns.DISPLAY_NAME));
+            fileNameString = contentResolverCursor.getString(contentResolverCursor.getColumnIndexOrThrow(OpenableColumns.DISPLAY_NAME));
 
             // Close the cursor.
             contentResolverCursor.close();
index 377e0e8a8e384a82858d27a8918b464e5617aee9..ea2d792987c6ae3ddd1a62d0328931624b2c5140 100644 (file)
@@ -185,15 +185,15 @@ class EditBookmarkDatabaseViewDialog : DialogFragment() {
         saveButton = alertDialog.getButton(AlertDialog.BUTTON_POSITIVE)
 
         // Store the current bookmark values.
-        val currentBookmarkName = bookmarkCursor.getString(bookmarkCursor.getColumnIndex(BookmarksDatabaseHelper.BOOKMARK_NAME))
-        val currentUrl = bookmarkCursor.getString(bookmarkCursor.getColumnIndex(BookmarksDatabaseHelper.BOOKMARK_URL))
-        val currentDisplayOrder = bookmarkCursor.getInt(bookmarkCursor.getColumnIndex(BookmarksDatabaseHelper.DISPLAY_ORDER))
+        val currentBookmarkName = bookmarkCursor.getString(bookmarkCursor.getColumnIndexOrThrow(BookmarksDatabaseHelper.BOOKMARK_NAME))
+        val currentUrl = bookmarkCursor.getString(bookmarkCursor.getColumnIndexOrThrow(BookmarksDatabaseHelper.BOOKMARK_URL))
+        val currentDisplayOrder = bookmarkCursor.getInt(bookmarkCursor.getColumnIndexOrThrow(BookmarksDatabaseHelper.DISPLAY_ORDER))
 
         // Set the database ID.
-        databaseIdTextView.text = bookmarkCursor.getInt(bookmarkCursor.getColumnIndex(BookmarksDatabaseHelper._ID)).toString()
+        databaseIdTextView.text = bookmarkCursor.getInt(bookmarkCursor.getColumnIndexOrThrow(BookmarksDatabaseHelper._ID)).toString()
 
         // Get the current favorite icon byte array from the cursor.
-        val currentIconByteArray = bookmarkCursor.getBlob(bookmarkCursor.getColumnIndex(BookmarksDatabaseHelper.FAVORITE_ICON))
+        val currentIconByteArray = bookmarkCursor.getBlob(bookmarkCursor.getColumnIndexOrThrow(BookmarksDatabaseHelper.FAVORITE_ICON))
 
         // Convert the byte array to a bitmap beginning at the first byte and ending at the last.
         val currentIconBitmap = BitmapFactory.decodeByteArray(currentIconByteArray, 0, currentIconByteArray.size)
@@ -236,7 +236,7 @@ class EditBookmarkDatabaseViewDialog : DialogFragment() {
                     spinnerItemImageView.setImageDrawable(ContextCompat.getDrawable(context, R.drawable.folder_gray))
                 } else {  // A user folder
                     // Get the folder icon byte array.
-                    val folderIconByteArray = cursor.getBlob(cursor.getColumnIndex(BookmarksDatabaseHelper.FAVORITE_ICON))
+                    val folderIconByteArray = cursor.getBlob(cursor.getColumnIndexOrThrow(BookmarksDatabaseHelper.FAVORITE_ICON))
 
                     // Convert the byte array to a bitmap beginning at the first byte and ending at the last.
                     val folderIconBitmap = BitmapFactory.decodeByteArray(folderIconByteArray, 0, folderIconByteArray.size)
@@ -246,7 +246,7 @@ class EditBookmarkDatabaseViewDialog : DialogFragment() {
                 }
 
                 // Set the text view to display the folder name.
-                spinnerItemTextView.text = cursor.getString(cursor.getColumnIndex(BookmarksDatabaseHelper.BOOKMARK_NAME))
+                spinnerItemTextView.text = cursor.getString(cursor.getColumnIndexOrThrow(BookmarksDatabaseHelper.BOOKMARK_NAME))
             }
         }
 
@@ -257,12 +257,12 @@ class EditBookmarkDatabaseViewDialog : DialogFragment() {
         folderSpinner.adapter = foldersCursorAdapter
 
         // Get the parent folder name.
-        val parentFolder = bookmarkCursor.getString(bookmarkCursor.getColumnIndex(BookmarksDatabaseHelper.PARENT_FOLDER))
+        val parentFolder = bookmarkCursor.getString(bookmarkCursor.getColumnIndexOrThrow(BookmarksDatabaseHelper.PARENT_FOLDER))
 
         // Select the current folder in the spinner if the bookmark isn't in the home folder.
         if (parentFolder != "") {
             // Get the database ID of the parent folder.
-            val folderDatabaseId = bookmarksDatabaseHelper.getFolderDatabaseId(bookmarkCursor.getString(bookmarkCursor.getColumnIndex(BookmarksDatabaseHelper.PARENT_FOLDER)))
+            val folderDatabaseId = bookmarksDatabaseHelper.getFolderDatabaseId(bookmarkCursor.getString(bookmarkCursor.getColumnIndexOrThrow(BookmarksDatabaseHelper.PARENT_FOLDER)))
 
             // Initialize the parent folder position and the iteration variable.
             var parentFolderPosition = 0
@@ -288,7 +288,7 @@ class EditBookmarkDatabaseViewDialog : DialogFragment() {
         val currentFolderDatabaseId = folderSpinner.selectedItemId.toInt()
 
         // Populate the display order edit text.
-        displayOrderEditText.setText(bookmarkCursor.getInt(bookmarkCursor.getColumnIndex(BookmarksDatabaseHelper.DISPLAY_ORDER)).toString())
+        displayOrderEditText.setText(bookmarkCursor.getInt(bookmarkCursor.getColumnIndexOrThrow(BookmarksDatabaseHelper.DISPLAY_ORDER)).toString())
 
         // Initially disable the save button.
         saveButton.isEnabled = false
index baa53cc3abeadb4ad972b15b3fb5f511a4f82da6..56381fcc933282224baf8639a4f43fe4d61cc2ec 100644 (file)
@@ -170,7 +170,7 @@ class EditBookmarkDialog : DialogFragment() {
         saveButton = alertDialog.getButton(AlertDialog.BUTTON_POSITIVE)
 
         // Get the current favorite icon byte array from the cursor.
-        val currentIconByteArray = bookmarkCursor.getBlob(bookmarkCursor.getColumnIndex(BookmarksDatabaseHelper.FAVORITE_ICON))
+        val currentIconByteArray = bookmarkCursor.getBlob(bookmarkCursor.getColumnIndexOrThrow(BookmarksDatabaseHelper.FAVORITE_ICON))
 
         // Convert the byte array to a bitmap beginning at the first byte and ending at the last.
         val currentIconBitmap = BitmapFactory.decodeByteArray(currentIconByteArray, 0, currentIconByteArray.size)
@@ -182,8 +182,8 @@ class EditBookmarkDialog : DialogFragment() {
         webpageFavoriteIconImageView.setImageBitmap(favoriteIconBitmap)
 
         // Store the current bookmark name and URL.
-        val currentName = bookmarkCursor.getString(bookmarkCursor.getColumnIndex(BookmarksDatabaseHelper.BOOKMARK_NAME))
-        val currentUrl = bookmarkCursor.getString(bookmarkCursor.getColumnIndex(BookmarksDatabaseHelper.BOOKMARK_URL))
+        val currentName = bookmarkCursor.getString(bookmarkCursor.getColumnIndexOrThrow(BookmarksDatabaseHelper.BOOKMARK_NAME))
+        val currentUrl = bookmarkCursor.getString(bookmarkCursor.getColumnIndexOrThrow(BookmarksDatabaseHelper.BOOKMARK_URL))
 
         // Populate the edit texts.
         nameEditText.setText(currentName)
index 5d6fe9227b8490cbe2b21f7854164840df171cdf..41b7de225c53c6c1ad24ac798dce56988cdde264 100644 (file)
@@ -179,15 +179,15 @@ class EditBookmarkFolderDatabaseViewDialog : DialogFragment() {
         saveButton = alertDialog.getButton(AlertDialog.BUTTON_POSITIVE)
 
         // Store the current folder values.
-        val currentFolderName = folderCursor.getString(folderCursor.getColumnIndex(BookmarksDatabaseHelper.BOOKMARK_NAME))
-        val currentDisplayOrder = folderCursor.getInt(folderCursor.getColumnIndex(BookmarksDatabaseHelper.DISPLAY_ORDER))
-        val parentFolder = folderCursor.getString(folderCursor.getColumnIndex(BookmarksDatabaseHelper.PARENT_FOLDER))
+        val currentFolderName = folderCursor.getString(folderCursor.getColumnIndexOrThrow(BookmarksDatabaseHelper.BOOKMARK_NAME))
+        val currentDisplayOrder = folderCursor.getInt(folderCursor.getColumnIndexOrThrow(BookmarksDatabaseHelper.DISPLAY_ORDER))
+        val parentFolder = folderCursor.getString(folderCursor.getColumnIndexOrThrow(BookmarksDatabaseHelper.PARENT_FOLDER))
 
         // Populate the database ID text view.
-        databaseIdTextView.text = folderCursor.getInt(folderCursor.getColumnIndex(BookmarksDatabaseHelper._ID)).toString()
+        databaseIdTextView.text = folderCursor.getInt(folderCursor.getColumnIndexOrThrow(BookmarksDatabaseHelper._ID)).toString()
 
         // Get the current favorite icon byte array from the cursor.
-        val currentIconByteArray = folderCursor.getBlob(folderCursor.getColumnIndex(BookmarksDatabaseHelper.FAVORITE_ICON))
+        val currentIconByteArray = folderCursor.getBlob(folderCursor.getColumnIndexOrThrow(BookmarksDatabaseHelper.FAVORITE_ICON))
 
         // Convert the byte array to a bitmap beginning at the first byte and ending at the last.
         val currentIconBitmap = BitmapFactory.decodeByteArray(currentIconByteArray, 0, currentIconByteArray.size)
@@ -232,7 +232,7 @@ class EditBookmarkFolderDatabaseViewDialog : DialogFragment() {
                     spinnerItemImageView.setImageDrawable(ContextCompat.getDrawable(context, R.drawable.folder_gray))
                 } else {  // Set a user folder icon.
                     // Get the folder icon byte array.
-                    val folderIconByteArray = cursor.getBlob(cursor.getColumnIndex(BookmarksDatabaseHelper.FAVORITE_ICON))
+                    val folderIconByteArray = cursor.getBlob(cursor.getColumnIndexOrThrow(BookmarksDatabaseHelper.FAVORITE_ICON))
 
                     // Convert the byte array to a bitmap beginning at the first byte and ending at the last.
                     val folderIconBitmap = BitmapFactory.decodeByteArray(folderIconByteArray, 0, folderIconByteArray.size)
@@ -242,7 +242,7 @@ class EditBookmarkFolderDatabaseViewDialog : DialogFragment() {
                 }
 
                 // Set the text view to display the folder name.
-                spinnerItemTextView.text = cursor.getString(cursor.getColumnIndex(BookmarksDatabaseHelper.BOOKMARK_NAME))
+                spinnerItemTextView.text = cursor.getString(cursor.getColumnIndexOrThrow(BookmarksDatabaseHelper.BOOKMARK_NAME))
             }
         }
 
@@ -255,7 +255,7 @@ class EditBookmarkFolderDatabaseViewDialog : DialogFragment() {
         // Select the current folder in the spinner if the bookmark isn't in the "Home Folder".
         if (parentFolder != "") {
             // Get the database ID of the parent folder as a long.
-            val parentFolderDatabaseId = bookmarksDatabaseHelper.getFolderDatabaseId(folderCursor.getString(folderCursor.getColumnIndex(BookmarksDatabaseHelper.PARENT_FOLDER))).toLong()
+            val parentFolderDatabaseId = bookmarksDatabaseHelper.getFolderDatabaseId(folderCursor.getString(folderCursor.getColumnIndexOrThrow(BookmarksDatabaseHelper.PARENT_FOLDER))).toLong()
 
             // Initialize the parent folder position and the iteration variable.
             var parentFolderPosition = 0
@@ -281,7 +281,7 @@ class EditBookmarkFolderDatabaseViewDialog : DialogFragment() {
         val currentParentFolderDatabaseId = parentFolderSpinner.selectedItemId.toInt()
 
         // Populate the display order edit text.
-        displayOrderEditText.setText(folderCursor.getInt(folderCursor.getColumnIndex(BookmarksDatabaseHelper.DISPLAY_ORDER)).toString())
+        displayOrderEditText.setText(folderCursor.getInt(folderCursor.getColumnIndexOrThrow(BookmarksDatabaseHelper.DISPLAY_ORDER)).toString())
 
         // Initially disable the edit button.
         saveButton.isEnabled = false
@@ -462,7 +462,7 @@ class EditBookmarkFolderDatabaseViewDialog : DialogFragment() {
             subfoldersCursor.moveToPosition(i)
 
             // Get the name of the subfolder.
-            val subfolderName = subfoldersCursor.getString(subfoldersCursor.getColumnIndex(BookmarksDatabaseHelper.BOOKMARK_NAME))
+            val subfolderName = subfoldersCursor.getString(subfoldersCursor.getColumnIndexOrThrow(BookmarksDatabaseHelper.BOOKMARK_NAME))
 
             // Add a comma to the end of the existing string.
             currentAndSubfolderStringBuilder.append(",")
index 2a4bc9f347e01f7d6fc92b2a0e9157b0cfe74662..86c521afca4278c2b24df829f7c9fbb44bee66af 100644 (file)
@@ -172,7 +172,7 @@ class EditBookmarkFolderDialog : DialogFragment() {
         saveButton = alertDialog.getButton(AlertDialog.BUTTON_POSITIVE)
 
         // Get the current favorite icon byte array from the cursor.
-        val currentIconByteArray = folderCursor.getBlob(folderCursor.getColumnIndex(BookmarksDatabaseHelper.FAVORITE_ICON))
+        val currentIconByteArray = folderCursor.getBlob(folderCursor.getColumnIndexOrThrow(BookmarksDatabaseHelper.FAVORITE_ICON))
 
         // Convert the byte array to a bitmap beginning at the first byte and ending at the last.
         val currentIconBitmap = BitmapFactory.decodeByteArray(currentIconByteArray, 0, currentIconByteArray.size)
@@ -184,7 +184,7 @@ class EditBookmarkFolderDialog : DialogFragment() {
         webpageFavoriteIconImageView.setImageBitmap(favoriteIconBitmap)
 
         // Get the current folder name.
-        currentFolderName = folderCursor.getString(folderCursor.getColumnIndex(BookmarksDatabaseHelper.BOOKMARK_NAME))
+        currentFolderName = folderCursor.getString(folderCursor.getColumnIndexOrThrow(BookmarksDatabaseHelper.BOOKMARK_NAME))
 
         // Display the current folder name.
         folderNameEditText.setText(currentFolderName)
index f07f346ac687f67531c98c8b64731bd2bb1daed8..575d581e039e9d95c5de6530e077dc6e7759086d 100644 (file)
@@ -272,7 +272,7 @@ class MoveToFolderDialog : DialogFragment() {
             subfoldersCursor.moveToPosition(i)
 
             // Get the name of the subfolder.
-            val subfolderName = subfoldersCursor.getString(subfoldersCursor.getColumnIndex(BookmarksDatabaseHelper.BOOKMARK_NAME))
+            val subfolderName = subfoldersCursor.getString(subfoldersCursor.getColumnIndexOrThrow(BookmarksDatabaseHelper.BOOKMARK_NAME))
 
             // Add the subfolder to except folders.
             exceptFolders.append(",")
@@ -293,8 +293,8 @@ class MoveToFolderDialog : DialogFragment() {
 
             override fun bindView(view: View, context: Context, cursor: Cursor) {
                 // Get the data from the cursor.
-                val folderIconByteArray = cursor.getBlob(cursor.getColumnIndex(BookmarksDatabaseHelper.FAVORITE_ICON))
-                val folderName = cursor.getString(cursor.getColumnIndex(BookmarksDatabaseHelper.BOOKMARK_NAME))
+                val folderIconByteArray = cursor.getBlob(cursor.getColumnIndexOrThrow(BookmarksDatabaseHelper.FAVORITE_ICON))
+                val folderName = cursor.getString(cursor.getColumnIndexOrThrow(BookmarksDatabaseHelper.BOOKMARK_NAME))
 
                 // Get handles for the views.
                 val folderIconImageView = view.findViewById<ImageView>(R.id.move_to_folder_icon)
index 2e99ff2ef76776416dcd2ab6434587364309bd79..d2e9790b426e8fc928f4c7e420bde8d4be4c5019 100644 (file)
@@ -182,7 +182,7 @@ class AboutVersionFragment : Fragment() {
                     contentResolverCursor.moveToFirst()
 
                     // Get the file name from the cursor.
-                    fileNameString = contentResolverCursor.getString(contentResolverCursor.getColumnIndex(OpenableColumns.DISPLAY_NAME))
+                    fileNameString = contentResolverCursor.getString(contentResolverCursor.getColumnIndexOrThrow(OpenableColumns.DISPLAY_NAME))
 
                     // Close the cursor.
                     contentResolverCursor.close()
index d2809b541097aa2ea3cf538ce2920faeb5083e33..e26853c856e63ea162e87c22e8958c14c56417f6 100644 (file)
@@ -209,45 +209,45 @@ public class DomainSettingsFragment extends Fragment {
         domainCursor.moveToFirst();
 
         // Save the cursor entries as variables.
-        String domainNameString = domainCursor.getString(domainCursor.getColumnIndex(DomainsDatabaseHelper.DOMAIN_NAME));
-        int javaScriptInt = domainCursor.getInt(domainCursor.getColumnIndex(DomainsDatabaseHelper.ENABLE_JAVASCRIPT));
-        int cookiesInt = domainCursor.getInt(domainCursor.getColumnIndex(DomainsDatabaseHelper.COOKIES));
-        int domStorageInt = domainCursor.getInt(domainCursor.getColumnIndex(DomainsDatabaseHelper.ENABLE_DOM_STORAGE));
-        int formDataInt = domainCursor.getInt(domainCursor.getColumnIndex(DomainsDatabaseHelper.ENABLE_FORM_DATA));  // Form data can be remove once the minimum API >= 26.
-        int easyListInt = domainCursor.getInt(domainCursor.getColumnIndex(DomainsDatabaseHelper.ENABLE_EASYLIST));
-        int easyPrivacyInt = domainCursor.getInt(domainCursor.getColumnIndex(DomainsDatabaseHelper.ENABLE_EASYPRIVACY));
-        int fanboysAnnoyanceListInt = domainCursor.getInt(domainCursor.getColumnIndex(DomainsDatabaseHelper.ENABLE_FANBOYS_ANNOYANCE_LIST));
-        int fanboysSocialBlockingListInt = domainCursor.getInt(domainCursor.getColumnIndex(DomainsDatabaseHelper.ENABLE_FANBOYS_SOCIAL_BLOCKING_LIST));
-        int ultraListInt = domainCursor.getInt(domainCursor.getColumnIndex(DomainsDatabaseHelper.ULTRALIST));
-        int ultraPrivacyInt = domainCursor.getInt(domainCursor.getColumnIndex(DomainsDatabaseHelper.ENABLE_ULTRAPRIVACY));
-        int blockAllThirdPartyRequestsInt = domainCursor.getInt(domainCursor.getColumnIndex(DomainsDatabaseHelper.BLOCK_ALL_THIRD_PARTY_REQUESTS));
-        String currentUserAgentName = domainCursor.getString(domainCursor.getColumnIndex(DomainsDatabaseHelper.USER_AGENT));
-        int fontSizeInt = domainCursor.getInt(domainCursor.getColumnIndex(DomainsDatabaseHelper.FONT_SIZE));
-        int swipeToRefreshInt = domainCursor.getInt(domainCursor.getColumnIndex(DomainsDatabaseHelper.SWIPE_TO_REFRESH));
-        int webViewThemeInt = domainCursor.getInt(domainCursor.getColumnIndex(DomainsDatabaseHelper.WEBVIEW_THEME));
-        int wideViewportInt = domainCursor.getInt(domainCursor.getColumnIndex(DomainsDatabaseHelper.WIDE_VIEWPORT));
-        int displayImagesInt = domainCursor.getInt(domainCursor.getColumnIndex(DomainsDatabaseHelper.DISPLAY_IMAGES));
-        int pinnedSslCertificateInt = domainCursor.getInt(domainCursor.getColumnIndex(DomainsDatabaseHelper.PINNED_SSL_CERTIFICATE));
-        String savedSslIssuedToCNameString = domainCursor.getString(domainCursor.getColumnIndex(DomainsDatabaseHelper.SSL_ISSUED_TO_COMMON_NAME));
-        String savedSslIssuedToONameString = domainCursor.getString(domainCursor.getColumnIndex(DomainsDatabaseHelper.SSL_ISSUED_TO_ORGANIZATION));
-        String savedSslIssuedToUNameString = domainCursor.getString(domainCursor.getColumnIndex(DomainsDatabaseHelper.SSL_ISSUED_TO_ORGANIZATIONAL_UNIT));
-        String savedSslIssuedByCNameString = domainCursor.getString(domainCursor.getColumnIndex(DomainsDatabaseHelper.SSL_ISSUED_BY_COMMON_NAME));
-        String savedSslIssuedByONameString = domainCursor.getString(domainCursor.getColumnIndex(DomainsDatabaseHelper.SSL_ISSUED_BY_ORGANIZATION));
-        String savedSslIssuedByUNameString = domainCursor.getString(domainCursor.getColumnIndex(DomainsDatabaseHelper.SSL_ISSUED_BY_ORGANIZATIONAL_UNIT));
-        int pinnedIpAddressesInt = domainCursor.getInt(domainCursor.getColumnIndex(DomainsDatabaseHelper.PINNED_IP_ADDRESSES));
-        String savedIpAddresses = domainCursor.getString(domainCursor.getColumnIndex(DomainsDatabaseHelper.IP_ADDRESSES));
+        String domainNameString = domainCursor.getString(domainCursor.getColumnIndexOrThrow(DomainsDatabaseHelper.DOMAIN_NAME));
+        int javaScriptInt = domainCursor.getInt(domainCursor.getColumnIndexOrThrow(DomainsDatabaseHelper.ENABLE_JAVASCRIPT));
+        int cookiesInt = domainCursor.getInt(domainCursor.getColumnIndexOrThrow(DomainsDatabaseHelper.COOKIES));
+        int domStorageInt = domainCursor.getInt(domainCursor.getColumnIndexOrThrow(DomainsDatabaseHelper.ENABLE_DOM_STORAGE));
+        int formDataInt = domainCursor.getInt(domainCursor.getColumnIndexOrThrow(DomainsDatabaseHelper.ENABLE_FORM_DATA));  // Form data can be remove once the minimum API >= 26.
+        int easyListInt = domainCursor.getInt(domainCursor.getColumnIndexOrThrow(DomainsDatabaseHelper.ENABLE_EASYLIST));
+        int easyPrivacyInt = domainCursor.getInt(domainCursor.getColumnIndexOrThrow(DomainsDatabaseHelper.ENABLE_EASYPRIVACY));
+        int fanboysAnnoyanceListInt = domainCursor.getInt(domainCursor.getColumnIndexOrThrow(DomainsDatabaseHelper.ENABLE_FANBOYS_ANNOYANCE_LIST));
+        int fanboysSocialBlockingListInt = domainCursor.getInt(domainCursor.getColumnIndexOrThrow(DomainsDatabaseHelper.ENABLE_FANBOYS_SOCIAL_BLOCKING_LIST));
+        int ultraListInt = domainCursor.getInt(domainCursor.getColumnIndexOrThrow(DomainsDatabaseHelper.ULTRALIST));
+        int ultraPrivacyInt = domainCursor.getInt(domainCursor.getColumnIndexOrThrow(DomainsDatabaseHelper.ENABLE_ULTRAPRIVACY));
+        int blockAllThirdPartyRequestsInt = domainCursor.getInt(domainCursor.getColumnIndexOrThrow(DomainsDatabaseHelper.BLOCK_ALL_THIRD_PARTY_REQUESTS));
+        String currentUserAgentName = domainCursor.getString(domainCursor.getColumnIndexOrThrow(DomainsDatabaseHelper.USER_AGENT));
+        int fontSizeInt = domainCursor.getInt(domainCursor.getColumnIndexOrThrow(DomainsDatabaseHelper.FONT_SIZE));
+        int swipeToRefreshInt = domainCursor.getInt(domainCursor.getColumnIndexOrThrow(DomainsDatabaseHelper.SWIPE_TO_REFRESH));
+        int webViewThemeInt = domainCursor.getInt(domainCursor.getColumnIndexOrThrow(DomainsDatabaseHelper.WEBVIEW_THEME));
+        int wideViewportInt = domainCursor.getInt(domainCursor.getColumnIndexOrThrow(DomainsDatabaseHelper.WIDE_VIEWPORT));
+        int displayImagesInt = domainCursor.getInt(domainCursor.getColumnIndexOrThrow(DomainsDatabaseHelper.DISPLAY_IMAGES));
+        int pinnedSslCertificateInt = domainCursor.getInt(domainCursor.getColumnIndexOrThrow(DomainsDatabaseHelper.PINNED_SSL_CERTIFICATE));
+        String savedSslIssuedToCNameString = domainCursor.getString(domainCursor.getColumnIndexOrThrow(DomainsDatabaseHelper.SSL_ISSUED_TO_COMMON_NAME));
+        String savedSslIssuedToONameString = domainCursor.getString(domainCursor.getColumnIndexOrThrow(DomainsDatabaseHelper.SSL_ISSUED_TO_ORGANIZATION));
+        String savedSslIssuedToUNameString = domainCursor.getString(domainCursor.getColumnIndexOrThrow(DomainsDatabaseHelper.SSL_ISSUED_TO_ORGANIZATIONAL_UNIT));
+        String savedSslIssuedByCNameString = domainCursor.getString(domainCursor.getColumnIndexOrThrow(DomainsDatabaseHelper.SSL_ISSUED_BY_COMMON_NAME));
+        String savedSslIssuedByONameString = domainCursor.getString(domainCursor.getColumnIndexOrThrow(DomainsDatabaseHelper.SSL_ISSUED_BY_ORGANIZATION));
+        String savedSslIssuedByUNameString = domainCursor.getString(domainCursor.getColumnIndexOrThrow(DomainsDatabaseHelper.SSL_ISSUED_BY_ORGANIZATIONAL_UNIT));
+        int pinnedIpAddressesInt = domainCursor.getInt(domainCursor.getColumnIndexOrThrow(DomainsDatabaseHelper.PINNED_IP_ADDRESSES));
+        String savedIpAddresses = domainCursor.getString(domainCursor.getColumnIndexOrThrow(DomainsDatabaseHelper.IP_ADDRESSES));
 
         // Initialize the saved SSL certificate date variables.
         Date savedSslStartDate = null;
         Date savedSslEndDate = null;
 
         // Only get the saved SSL certificate dates from the cursor if they are not set to `0`.
-        if (domainCursor.getLong(domainCursor.getColumnIndex(DomainsDatabaseHelper.SSL_START_DATE)) != 0) {
-            savedSslStartDate = new Date(domainCursor.getLong(domainCursor.getColumnIndex(DomainsDatabaseHelper.SSL_START_DATE)));
+        if (domainCursor.getLong(domainCursor.getColumnIndexOrThrow(DomainsDatabaseHelper.SSL_START_DATE)) != 0) {
+            savedSslStartDate = new Date(domainCursor.getLong(domainCursor.getColumnIndexOrThrow(DomainsDatabaseHelper.SSL_START_DATE)));
         }
 
-        if (domainCursor.getLong(domainCursor.getColumnIndex(DomainsDatabaseHelper.SSL_END_DATE)) != 0) {
-            savedSslEndDate = new Date(domainCursor.getLong(domainCursor.getColumnIndex(DomainsDatabaseHelper.SSL_END_DATE)));
+        if (domainCursor.getLong(domainCursor.getColumnIndexOrThrow(DomainsDatabaseHelper.SSL_END_DATE)) != 0) {
+            savedSslEndDate = new Date(domainCursor.getLong(domainCursor.getColumnIndexOrThrow(DomainsDatabaseHelper.SSL_END_DATE)));
         }
 
         // Create array adapters for the spinners.
index 306f1e2c57a0c3465e718f21f62a5432e152a48f..a43e30bd82279d0b9689dbe20e0cd4015e8d3961 100644 (file)
@@ -143,7 +143,7 @@ public class SettingsFragment extends PreferenceFragmentCompat {
         searchPreference = findPreference("search");
         searchCustomURLPreference = findPreference("search_custom_url");
         proxyPreference = findPreference("proxy");
-        proxyCustomUrlPreference = findPreference("proxy_custom_url");
+        proxyCustomUrlPreference = findPreference(getString(R.string.proxy_custom_url_key));
         fullScreenBrowsingModePreference = findPreference("full_screen_browsing_mode");
         hideAppBarPreference = findPreference("hide_app_bar");
         clearEverythingPreference = findPreference("clear_everything");
@@ -157,7 +157,7 @@ public class SettingsFragment extends PreferenceFragmentCompat {
         openIntentsInNewTabPreference = findPreference("open_intents_in_new_tab");
         swipeToRefreshPreference = findPreference("swipe_to_refresh");
         downloadWithExternalAppPreference = findPreference(getString(R.string.download_with_external_app_key));
-        scrollAppBarPreference = findPreference("scroll_app_bar");
+        scrollAppBarPreference = findPreference(getString(R.string.scroll_app_bar_key));
         bottomAppBarPreference = findPreference(getString(R.string.bottom_app_bar_key));
         displayAdditionalAppBarIconsPreference = findPreference(getString(R.string.display_additional_app_bar_icons_key));
         appThemePreference = findPreference("app_theme");
@@ -333,10 +333,10 @@ public class SettingsFragment extends PreferenceFragmentCompat {
         }
 
         // Set the summary text for the custom proxy URL.
-        proxyCustomUrlPreference.setSummary(sharedPreferences.getString("proxy_custom_url", getString(R.string.proxy_custom_url_default_value)));
+        proxyCustomUrlPreference.setSummary(sharedPreferences.getString(getString(R.string.proxy_custom_url_key), getString(R.string.proxy_custom_url_default_value)));
 
         // Only enable the custom proxy URL if a custom proxy is selected.
-        proxyCustomUrlPreference.setEnabled(proxyString.equals("Custom"));
+        proxyCustomUrlPreference.setEnabled(proxyString.equals(ProxyHelper.CUSTOM));
 
 
         // Set the status of the clear and exit preferences.
@@ -689,7 +689,7 @@ public class SettingsFragment extends PreferenceFragmentCompat {
         }
 
         // Set the Proxy icons according to the theme and status.
-        if (proxyString.equals("None")) {  // Proxying is disabled.
+        if (proxyString.equals(ProxyHelper.NONE)) {  // Proxying is disabled.
             if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {  // Dark theme.
                 // Set the main proxy icon to be disabled.
                 proxyPreference.setIcon(R.drawable.proxy_disabled_night);
@@ -877,7 +877,7 @@ public class SettingsFragment extends PreferenceFragmentCompat {
         }
 
         // Set the scroll app bar preference icon.
-        if (sharedPreferences.getBoolean("scroll_app_bar", true)) {
+        if (sharedPreferences.getBoolean(getString(R.string.scroll_app_bar_key), true)) {
             if (currentThemeStatus == Configuration.UI_MODE_NIGHT_NO) {
                 scrollAppBarPreference.setIcon(R.drawable.app_bar_enabled_day);
             } else {
@@ -1458,10 +1458,10 @@ public class SettingsFragment extends PreferenceFragmentCompat {
                     }
 
                     // Update the status of the custom URL preference.
-                    proxyCustomUrlPreference.setEnabled(currentProxyString.equals("Custom"));
+                    proxyCustomUrlPreference.setEnabled(currentProxyString.equals(ProxyHelper.CUSTOM));
 
                     // Update the icons.
-                    if (currentProxyString.equals("None")) {  // Proxying is disabled.
+                    if (currentProxyString.equals(ProxyHelper.NONE)) {  // Proxying is disabled.
                         if (currentThemeStatus == Configuration.UI_MODE_NIGHT_YES) {  // Dark theme.
                             // Set the main proxy icon to be disabled
                             proxyPreference.setIcon(R.drawable.proxy_disabled_night);
@@ -1502,7 +1502,7 @@ public class SettingsFragment extends PreferenceFragmentCompat {
 
                 case "proxy_custom_url":
                     // Set the summary text for the proxy custom URL.
-                    proxyCustomUrlPreference.setSummary(sharedPreferences.getString("proxy_custom_url", context.getString(R.string.proxy_custom_url_default_value)));
+                    proxyCustomUrlPreference.setSummary(sharedPreferences.getString(context.getString(R.string.proxy_custom_url_key), context.getString(R.string.proxy_custom_url_default_value)));
                     break;
 
                 case "full_screen_browsing_mode":
@@ -1770,7 +1770,7 @@ public class SettingsFragment extends PreferenceFragmentCompat {
 
                 case "scroll_app_bar":
                     // Update the icon.
-                    if (sharedPreferences.getBoolean("scroll_app_bar", true)) {
+                    if (sharedPreferences.getBoolean(context.getString(R.string.scroll_app_bar_key), true)) {
                         if (currentThemeStatus == Configuration.UI_MODE_NIGHT_NO) {
                             scrollAppBarPreference.setIcon(R.drawable.app_bar_enabled_day);
                         } else {
index 913cc0b1c775e24ba69689f6b45b402694ba7b52..5ee2a98b2fa12e984c63531ab8e8d5207a766a3b 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright © 2018-2019 Soren Stoutner <soren@stoutner.com>.
+ * Copyright © 2018-2019,2021 Soren Stoutner <soren@stoutner.com>.
  *
  * This file is part of Privacy Browser <https://www.stoutner.com/privacy-browser>.
  *
@@ -1634,7 +1634,7 @@ public class BlocklistHelper {
 
         // Process the white lists.
         // Main white list.
-        for (String[] whitelistEntry : blocklist.get(Integer.valueOf(MAIN_WHITELIST))) {
+        for (String[] whitelistEntry : blocklist.get(Integer.parseInt(MAIN_WHITELIST))) {
             switch (whitelistEntry.length) {
                 case 2:  // There is one entry.
                     if (resourceUrl.contains(whitelistEntry[0])) {
@@ -1660,7 +1660,7 @@ public class BlocklistHelper {
         }
 
         // Final white list.
-        for (String[] whitelistEntry : blocklist.get(Integer.valueOf(FINAL_WHITELIST))) {
+        for (String[] whitelistEntry : blocklist.get(Integer.parseInt(FINAL_WHITELIST))) {
             if (whitelistEntry.length == 2) {  // There is one entry.
                 if (resourceUrl.contains(whitelistEntry[0])) {
                     // Return a whitelist match request allowed.
@@ -1677,7 +1677,7 @@ public class BlocklistHelper {
         // Only check the domain lists if the current domain is not null (like `about:blank`).
         if (currentDomain != null) {
             // Domain white list.
-            for (String[] whitelistEntry : blocklist.get(Integer.valueOf(DOMAIN_WHITELIST))) {
+            for (String[] whitelistEntry : blocklist.get(Integer.parseInt(DOMAIN_WHITELIST))) {
                 switch (whitelistEntry.length) {
                     case 3:  // There is one entry.
                         if (currentDomain.endsWith(whitelistEntry[0]) && resourceUrl.contains(whitelistEntry[1])) {
@@ -1714,7 +1714,7 @@ public class BlocklistHelper {
             }
 
             // Domain initial white list.
-            for (String[] whitelistEntry : blocklist.get(Integer.valueOf(DOMAIN_INITIAL_WHITELIST))) {
+            for (String[] whitelistEntry : blocklist.get(Integer.parseInt(DOMAIN_INITIAL_WHITELIST))) {
                 switch (whitelistEntry.length) {
                     case 3:  // There is one entry.
                         if (currentDomain.endsWith(whitelistEntry[0]) && resourceUrl.startsWith(whitelistEntry[1])) {
@@ -1742,7 +1742,7 @@ public class BlocklistHelper {
             }
 
             // Domain final white list.
-            for (String[] whitelistEntry : blocklist.get(Integer.valueOf(DOMAIN_FINAL_WHITELIST))) {
+            for (String[] whitelistEntry : blocklist.get(Integer.parseInt(DOMAIN_FINAL_WHITELIST))) {
                 switch (whitelistEntry.length) {
                     case 3:  // There is one entry;
                         if (currentDomain.endsWith(whitelistEntry[0]) && resourceUrl.endsWith(whitelistEntry[1])) {
@@ -1765,7 +1765,7 @@ public class BlocklistHelper {
         // Only check the third-party white lists if this is a third-party request.
         if (isThirdPartyRequest) {
             // Third-party white list.
-            for (String[] whitelistEntry : blocklist.get(Integer.valueOf(THIRD_PARTY_WHITELIST))) {
+            for (String[] whitelistEntry : blocklist.get(Integer.parseInt(THIRD_PARTY_WHITELIST))) {
                 switch (whitelistEntry.length) {
                     case 2:  // There is one entry
                         if (resourceUrl.contains(whitelistEntry[0])) {
@@ -1809,7 +1809,7 @@ public class BlocklistHelper {
             }
 
             // Third-party domain white list.
-            for (String[] whitelistEntry : blocklist.get(Integer.valueOf(THIRD_PARTY_DOMAIN_WHITELIST))) {
+            for (String[] whitelistEntry : blocklist.get(Integer.parseInt(THIRD_PARTY_DOMAIN_WHITELIST))) {
                 if (whitelistEntry.length == 3) {  // There is one entry.
                     if (currentDomain.endsWith(whitelistEntry[0]) && resourceUrl.contains(whitelistEntry[1])) {
                         // Return a whitelist match request allowed.
@@ -1825,7 +1825,7 @@ public class BlocklistHelper {
             }
 
             // Third-party domain initial white list.
-            for (String[] whitelistEntry : blocklist.get(Integer.valueOf(THIRD_PARTY_DOMAIN_INITIAL_WHITELIST))) {
+            for (String[] whitelistEntry : blocklist.get(Integer.parseInt(THIRD_PARTY_DOMAIN_INITIAL_WHITELIST))) {
                 if (whitelistEntry.length == 3) {  // There is one entry.
                     if (currentDomain.endsWith(whitelistEntry[0]) && resourceUrl.startsWith(whitelistEntry[1])) {
                         // Return a whitelist match request allowed.
@@ -1843,7 +1843,7 @@ public class BlocklistHelper {
 
         // Process the black lists.
         // Main black list.
-        for (String[] blacklistEntry : blocklist.get(Integer.valueOf(MAIN_BLACKLIST))) {
+        for (String[] blacklistEntry : blocklist.get(Integer.parseInt(MAIN_BLACKLIST))) {
             switch (blacklistEntry.length) {
                 case 2:  // There is one entry.
                     if (resourceUrl.contains(blacklistEntry[0])) {
@@ -1886,7 +1886,7 @@ public class BlocklistHelper {
         }
 
         // Initial black list.
-        for (String[] blacklistEntry : blocklist.get(Integer.valueOf(INITIAL_BLACKLIST))) {
+        for (String[] blacklistEntry : blocklist.get(Integer.parseInt(INITIAL_BLACKLIST))) {
             if (blacklistEntry.length == 2) {  // There is one entry.
                 if (resourceUrl.startsWith(blacklistEntry[0])) {
                     // Return a blacklist match request blocked.
@@ -1901,7 +1901,7 @@ public class BlocklistHelper {
         }
 
         // Final black list.
-        for (String[] blacklistEntry : blocklist.get(Integer.valueOf(FINAL_BLACKLIST))) {
+        for (String[] blacklistEntry : blocklist.get(Integer.parseInt(FINAL_BLACKLIST))) {
             switch (blacklistEntry.length) {
                 case 2:  // There is one entry.
                     if (resourceUrl.endsWith(blacklistEntry[0])) {
@@ -1929,7 +1929,7 @@ public class BlocklistHelper {
         // Only check the domain lists if the current domain is not null (like `about:blank`).
         if (currentDomain != null) {
             // Domain black list.
-            for (String[] blacklistEntry : blocklist.get(Integer.valueOf(DOMAIN_BLACKLIST))) {
+            for (String[] blacklistEntry : blocklist.get(Integer.parseInt(DOMAIN_BLACKLIST))) {
                 switch (blacklistEntry.length) {
                     case 3:  // There is one entry.
                         if (currentDomain.endsWith(blacklistEntry[0]) && resourceUrl.contains(blacklistEntry[1])) {
@@ -1957,7 +1957,7 @@ public class BlocklistHelper {
             }
 
             // Domain initial black list.
-            for (String[] blacklistEntry : blocklist.get(Integer.valueOf(DOMAIN_INITIAL_BLACKLIST))) {
+            for (String[] blacklistEntry : blocklist.get(Integer.parseInt(DOMAIN_INITIAL_BLACKLIST))) {
                 // Store the entry in the resource request log.
                 if (currentDomain.endsWith(blacklistEntry[0]) && resourceUrl.startsWith(blacklistEntry[1])) {
                     // Return a blacklist match request blocked.
@@ -1966,7 +1966,7 @@ public class BlocklistHelper {
             }
 
             // Domain final black list.
-            for (String[] blacklistEntry : blocklist.get(Integer.valueOf(DOMAIN_FINAL_BLACKLIST))) {
+            for (String[] blacklistEntry : blocklist.get(Integer.parseInt(DOMAIN_FINAL_BLACKLIST))) {
                 switch (blacklistEntry.length) {
                     case 3:  // There is one entry.
                         if (currentDomain.endsWith(blacklistEntry[0]) && resourceUrl.endsWith(blacklistEntry[1])) {
@@ -1986,7 +1986,7 @@ public class BlocklistHelper {
             }
 
             // Domain regular expression black list.
-            for (String[] blacklistEntry : blocklist.get(Integer.valueOf(DOMAIN_REGULAR_EXPRESSION_BLACKLIST))) {
+            for (String[] blacklistEntry : blocklist.get(Integer.parseInt(DOMAIN_REGULAR_EXPRESSION_BLACKLIST))) {
                 if (currentDomain.endsWith(blacklistEntry[0]) && Pattern.matches(blacklistEntry[1], resourceUrl)) {
                     // Return a blacklist match request blocked.
                     return new String[] {REQUEST_BLOCKED, resourceUrl, BLOCK_LIST_NAME_STRING, DOMAIN_REGULAR_EXPRESSION_BLACKLIST, blacklistEntry[0] + "\n" + blacklistEntry[1], blacklistEntry[2]};
@@ -1997,7 +1997,7 @@ public class BlocklistHelper {
         // Only check the third-party black lists if this is a third-party request.
         if (isThirdPartyRequest) {
             // Third-party black list.
-            for (String[] blacklistEntry : blocklist.get(Integer.valueOf(THIRD_PARTY_BLACKLIST))) {
+            for (String[] blacklistEntry : blocklist.get(Integer.parseInt(THIRD_PARTY_BLACKLIST))) {
                 switch (blacklistEntry.length) {
                     case 2:  // There is one entry.
                         if (resourceUrl.contains(blacklistEntry[0])) {
@@ -2032,7 +2032,7 @@ public class BlocklistHelper {
             }
 
             // Third-party initial black list.
-            for (String[] blacklistEntry : blocklist.get(Integer.valueOf(THIRD_PARTY_INITIAL_BLACKLIST))) {
+            for (String[] blacklistEntry : blocklist.get(Integer.parseInt(THIRD_PARTY_INITIAL_BLACKLIST))) {
                 if (blacklistEntry.length == 2) {  // There is one entry.
                     if (resourceUrl.startsWith(blacklistEntry[0])) {
                         // Return a blacklist match request blocked.
@@ -2047,7 +2047,7 @@ public class BlocklistHelper {
             }
 
             // Third-party domain black list.
-            for (String[] blacklistEntry : blocklist.get(Integer.valueOf(THIRD_PARTY_DOMAIN_BLACKLIST))) {
+            for (String[] blacklistEntry : blocklist.get(Integer.parseInt(THIRD_PARTY_DOMAIN_BLACKLIST))) {
                 if (blacklistEntry.length == 3) {  // There is one entry.
                     if (currentDomain.endsWith(blacklistEntry[0]) && resourceUrl.contains(blacklistEntry[1])) {
                         // Return a blacklist match request blocked.
@@ -2063,7 +2063,7 @@ public class BlocklistHelper {
             }
 
             // Third-party domain initial black list.
-            for (String[] blacklistEntry : blocklist.get(Integer.valueOf(THIRD_PARTY_DOMAIN_INITIAL_BLACKLIST))) {
+            for (String[] blacklistEntry : blocklist.get(Integer.parseInt(THIRD_PARTY_DOMAIN_INITIAL_BLACKLIST))) {
                 switch (blacklistEntry.length) {
                     case 3:  // There is one entry.
                         if (currentDomain.endsWith(blacklistEntry[0]) && resourceUrl.startsWith(blacklistEntry[1])) {
@@ -2091,7 +2091,7 @@ public class BlocklistHelper {
             }
 
             // Third-party regular expression black list.
-            for (String[] blacklistEntry : blocklist.get(Integer.valueOf(THIRD_PARTY_REGULAR_EXPRESSION_BLACKLIST))) {
+            for (String[] blacklistEntry : blocklist.get(Integer.parseInt(THIRD_PARTY_REGULAR_EXPRESSION_BLACKLIST))) {
                 if (Pattern.matches(blacklistEntry[0], resourceUrl)) {
                     // Return a blacklist match request blocked.
                     return new String[] {REQUEST_BLOCKED, resourceUrl, BLOCK_LIST_NAME_STRING, THIRD_PARTY_REGULAR_EXPRESSION_BLACKLIST, blacklistEntry[0], blacklistEntry[1]};
@@ -2099,7 +2099,7 @@ public class BlocklistHelper {
             }
 
             // Third-party domain regular expression black list.
-            for (String[] blacklistEntry : blocklist.get(Integer.valueOf(THIRD_PARTY_DOMAIN_REGULAR_EXPRESSION_BLACKLIST))) {
+            for (String[] blacklistEntry : blocklist.get(Integer.parseInt(THIRD_PARTY_DOMAIN_REGULAR_EXPRESSION_BLACKLIST))) {
                 if (currentDomain.endsWith(blacklistEntry[0]) && Pattern.matches(blacklistEntry[1], resourceUrl)) {
                     // Return a blacklist match request blocked.
                     return new String[] {REQUEST_BLOCKED, resourceUrl, BLOCK_LIST_NAME_STRING, THIRD_PARTY_DOMAIN_REGULAR_EXPRESSION_BLACKLIST, blacklistEntry[0] + "\n" + blacklistEntry[1], blacklistEntry[2]};
@@ -2108,7 +2108,7 @@ public class BlocklistHelper {
         }
 
         // Regular expression black list.
-        for (String[] blacklistEntry : blocklist.get(Integer.valueOf(REGULAR_EXPRESSION_BLACKLIST))) {
+        for (String[] blacklistEntry : blocklist.get(Integer.parseInt(REGULAR_EXPRESSION_BLACKLIST))) {
             if (Pattern.matches(blacklistEntry[0], resourceUrl)) {
                 // Return a blacklist match request blocked.
                 return new String[] {REQUEST_BLOCKED, resourceUrl, BLOCK_LIST_NAME_STRING, REGULAR_EXPRESSION_BLACKLIST, blacklistEntry[0], blacklistEntry[1]};
index 8fe4be9cab056f55f0c229371db53ce123f3b140..0bc200c4468d10fa7d8f34e5bf25698669f31137 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright © 2016-2020 Soren Stoutner <soren@stoutner.com>.
+ * Copyright © 2016-2021 Soren Stoutner <soren@stoutner.com>.
  *
  * This file is part of Privacy Browser <https://www.stoutner.com/privacy-browser>.
  *
@@ -147,7 +147,7 @@ public class BookmarksDatabaseHelper extends SQLiteOpenHelper {
 
         // Get the folder name.
         folderCursor.moveToFirst();
-        String folderName = folderCursor.getString(folderCursor.getColumnIndex(BOOKMARK_NAME));
+        String folderName = folderCursor.getString(folderCursor.getColumnIndexOrThrow(BOOKMARK_NAME));
 
         // Close the cursor and the database handle.
         folderCursor.close();
@@ -175,7 +175,7 @@ public class BookmarksDatabaseHelper extends SQLiteOpenHelper {
 
         // Get the database ID.
         folderCursor.moveToFirst();
-        int databaseId = folderCursor.getInt(folderCursor.getColumnIndex(_ID));
+        int databaseId = folderCursor.getInt(folderCursor.getColumnIndexOrThrow(_ID));
 
         // Close the cursor and the database handle.
         folderCursor.close();
@@ -255,7 +255,7 @@ public class BookmarksDatabaseHelper extends SQLiteOpenHelper {
         bookmarkCursor.moveToFirst();
 
         // Store the name of the parent folder.
-        String parentFolder = bookmarkCursor.getString(bookmarkCursor.getColumnIndex(PARENT_FOLDER));
+        String parentFolder = bookmarkCursor.getString(bookmarkCursor.getColumnIndexOrThrow(PARENT_FOLDER));
 
         // Close the cursor.
         bookmarkCursor.close();
@@ -277,7 +277,7 @@ public class BookmarksDatabaseHelper extends SQLiteOpenHelper {
         bookmarkCursor.moveToFirst();
 
         // Store the name of the parent folder.
-        String parentFolder = bookmarkCursor.getString(bookmarkCursor.getColumnIndex(PARENT_FOLDER));
+        String parentFolder = bookmarkCursor.getString(bookmarkCursor.getColumnIndexOrThrow(PARENT_FOLDER));
 
         // Close the cursor.
         bookmarkCursor.close();
@@ -509,7 +509,7 @@ public class BookmarksDatabaseHelper extends SQLiteOpenHelper {
 
         // Ascertain if this database ID is a folder.
         folderCursor.moveToFirst();
-        boolean isFolder = (folderCursor.getInt(folderCursor.getColumnIndex(IS_FOLDER)) == 1);
+        boolean isFolder = (folderCursor.getInt(folderCursor.getColumnIndexOrThrow(IS_FOLDER)) == 1);
 
         // Close the cursor and the database handle.
         folderCursor.close();
@@ -767,7 +767,7 @@ public class BookmarksDatabaseHelper extends SQLiteOpenHelper {
             newFolderCursor.moveToLast();
 
             // Set the display order to be one greater that the last bookmark.
-            displayOrder = newFolderCursor.getInt(newFolderCursor.getColumnIndex(DISPLAY_ORDER)) + 1;
+            displayOrder = newFolderCursor.getInt(newFolderCursor.getColumnIndexOrThrow(DISPLAY_ORDER)) + 1;
         } else {  // There are no bookmarks in the new folder.
             // Set the display order to be `0`.
             displayOrder = 0;
index c8638e08dd4e1eff1599661f16dc4dd55b961c7f..bff5f9f193e49fc753dce79eb3726aca7ced1215 100644 (file)
@@ -387,12 +387,12 @@ public class ImportExportDatabaseHelper {
             for (int i = 0; i < importBookmarksCursor.getCount(); i++) {
                 // Extract the record from the cursor and store the data in a ContentValues.
                 ContentValues bookmarksContentValues = new ContentValues();
-                bookmarksContentValues.put(BookmarksDatabaseHelper.BOOKMARK_NAME, importBookmarksCursor.getString(importBookmarksCursor.getColumnIndex(BookmarksDatabaseHelper.BOOKMARK_NAME)));
-                bookmarksContentValues.put(BookmarksDatabaseHelper.BOOKMARK_URL, importBookmarksCursor.getString(importBookmarksCursor.getColumnIndex(BookmarksDatabaseHelper.BOOKMARK_URL)));
-                bookmarksContentValues.put(BookmarksDatabaseHelper.PARENT_FOLDER, importBookmarksCursor.getString(importBookmarksCursor.getColumnIndex(BookmarksDatabaseHelper.PARENT_FOLDER)));
-                bookmarksContentValues.put(BookmarksDatabaseHelper.DISPLAY_ORDER, importBookmarksCursor.getInt(importBookmarksCursor.getColumnIndex(BookmarksDatabaseHelper.DISPLAY_ORDER)));
-                bookmarksContentValues.put(BookmarksDatabaseHelper.IS_FOLDER, importBookmarksCursor.getInt(importBookmarksCursor.getColumnIndex(BookmarksDatabaseHelper.IS_FOLDER)));
-                bookmarksContentValues.put(BookmarksDatabaseHelper.FAVORITE_ICON, importBookmarksCursor.getBlob(importBookmarksCursor.getColumnIndex(BookmarksDatabaseHelper.FAVORITE_ICON)));
+                bookmarksContentValues.put(BookmarksDatabaseHelper.BOOKMARK_NAME, importBookmarksCursor.getString(importBookmarksCursor.getColumnIndexOrThrow(BookmarksDatabaseHelper.BOOKMARK_NAME)));
+                bookmarksContentValues.put(BookmarksDatabaseHelper.BOOKMARK_URL, importBookmarksCursor.getString(importBookmarksCursor.getColumnIndexOrThrow(BookmarksDatabaseHelper.BOOKMARK_URL)));
+                bookmarksContentValues.put(BookmarksDatabaseHelper.PARENT_FOLDER, importBookmarksCursor.getString(importBookmarksCursor.getColumnIndexOrThrow(BookmarksDatabaseHelper.PARENT_FOLDER)));
+                bookmarksContentValues.put(BookmarksDatabaseHelper.DISPLAY_ORDER, importBookmarksCursor.getInt(importBookmarksCursor.getColumnIndexOrThrow(BookmarksDatabaseHelper.DISPLAY_ORDER)));
+                bookmarksContentValues.put(BookmarksDatabaseHelper.IS_FOLDER, importBookmarksCursor.getInt(importBookmarksCursor.getColumnIndexOrThrow(BookmarksDatabaseHelper.IS_FOLDER)));
+                bookmarksContentValues.put(BookmarksDatabaseHelper.FAVORITE_ICON, importBookmarksCursor.getBlob(importBookmarksCursor.getColumnIndexOrThrow(BookmarksDatabaseHelper.FAVORITE_ICON)));
 
                 // Insert the record into the export database.
                 bookmarksDatabaseHelper.createBookmark(bookmarksContentValues);
@@ -424,40 +424,44 @@ public class ImportExportDatabaseHelper {
             for (int i = 0; i < importDomainsCursor.getCount(); i++) {
                 // Extract the record from the cursor and store the data in a ContentValues.
                 ContentValues domainsContentValues = new ContentValues();
-                domainsContentValues.put(DomainsDatabaseHelper.DOMAIN_NAME, importDomainsCursor.getString(importDomainsCursor.getColumnIndex(DomainsDatabaseHelper.DOMAIN_NAME)));
-                domainsContentValues.put(DomainsDatabaseHelper.ENABLE_JAVASCRIPT, importDomainsCursor.getInt(importDomainsCursor.getColumnIndex(DomainsDatabaseHelper.ENABLE_JAVASCRIPT)));
-                domainsContentValues.put(DomainsDatabaseHelper.COOKIES, importDomainsCursor.getInt(importDomainsCursor.getColumnIndex(DomainsDatabaseHelper.COOKIES)));
-                domainsContentValues.put(DomainsDatabaseHelper.ENABLE_DOM_STORAGE, importDomainsCursor.getInt(importDomainsCursor.getColumnIndex(DomainsDatabaseHelper.ENABLE_DOM_STORAGE)));
-                domainsContentValues.put(DomainsDatabaseHelper.ENABLE_FORM_DATA, importDomainsCursor.getInt(importDomainsCursor.getColumnIndex(DomainsDatabaseHelper.ENABLE_FORM_DATA)));
-                domainsContentValues.put(DomainsDatabaseHelper.ENABLE_EASYLIST, importDomainsCursor.getInt(importDomainsCursor.getColumnIndex(DomainsDatabaseHelper.ENABLE_EASYLIST)));
-                domainsContentValues.put(DomainsDatabaseHelper.ENABLE_EASYPRIVACY, importDomainsCursor.getInt(importDomainsCursor.getColumnIndex(DomainsDatabaseHelper.ENABLE_EASYPRIVACY)));
+                domainsContentValues.put(DomainsDatabaseHelper.DOMAIN_NAME, importDomainsCursor.getString(importDomainsCursor.getColumnIndexOrThrow(DomainsDatabaseHelper.DOMAIN_NAME)));
+                domainsContentValues.put(DomainsDatabaseHelper.ENABLE_JAVASCRIPT, importDomainsCursor.getInt(importDomainsCursor.getColumnIndexOrThrow(DomainsDatabaseHelper.ENABLE_JAVASCRIPT)));
+                domainsContentValues.put(DomainsDatabaseHelper.COOKIES, importDomainsCursor.getInt(importDomainsCursor.getColumnIndexOrThrow(DomainsDatabaseHelper.COOKIES)));
+                domainsContentValues.put(DomainsDatabaseHelper.ENABLE_DOM_STORAGE, importDomainsCursor.getInt(importDomainsCursor.getColumnIndexOrThrow(DomainsDatabaseHelper.ENABLE_DOM_STORAGE)));
+                domainsContentValues.put(DomainsDatabaseHelper.ENABLE_FORM_DATA, importDomainsCursor.getInt(importDomainsCursor.getColumnIndexOrThrow(DomainsDatabaseHelper.ENABLE_FORM_DATA)));
+                domainsContentValues.put(DomainsDatabaseHelper.ENABLE_EASYLIST, importDomainsCursor.getInt(importDomainsCursor.getColumnIndexOrThrow(DomainsDatabaseHelper.ENABLE_EASYLIST)));
+                domainsContentValues.put(DomainsDatabaseHelper.ENABLE_EASYPRIVACY, importDomainsCursor.getInt(importDomainsCursor.getColumnIndexOrThrow(DomainsDatabaseHelper.ENABLE_EASYPRIVACY)));
                 domainsContentValues.put(DomainsDatabaseHelper.ENABLE_FANBOYS_ANNOYANCE_LIST,
-                        importDomainsCursor.getInt(importDomainsCursor.getColumnIndex(DomainsDatabaseHelper.ENABLE_FANBOYS_ANNOYANCE_LIST)));
+                        importDomainsCursor.getInt(importDomainsCursor.getColumnIndexOrThrow(DomainsDatabaseHelper.ENABLE_FANBOYS_ANNOYANCE_LIST)));
                 domainsContentValues.put(DomainsDatabaseHelper.ENABLE_FANBOYS_SOCIAL_BLOCKING_LIST,
-                        importDomainsCursor.getInt(importDomainsCursor.getColumnIndex(DomainsDatabaseHelper.ENABLE_FANBOYS_SOCIAL_BLOCKING_LIST)));
-                domainsContentValues.put(DomainsDatabaseHelper.ULTRALIST, importDomainsCursor.getInt(importDomainsCursor.getColumnIndex(DomainsDatabaseHelper.ULTRALIST)));
-                domainsContentValues.put(DomainsDatabaseHelper.ENABLE_ULTRAPRIVACY, importDomainsCursor.getInt(importDomainsCursor.getColumnIndex(DomainsDatabaseHelper.ENABLE_ULTRAPRIVACY)));
+                        importDomainsCursor.getInt(importDomainsCursor.getColumnIndexOrThrow(DomainsDatabaseHelper.ENABLE_FANBOYS_SOCIAL_BLOCKING_LIST)));
+                domainsContentValues.put(DomainsDatabaseHelper.ULTRALIST, importDomainsCursor.getInt(importDomainsCursor.getColumnIndexOrThrow(DomainsDatabaseHelper.ULTRALIST)));
+                domainsContentValues.put(DomainsDatabaseHelper.ENABLE_ULTRAPRIVACY, importDomainsCursor.getInt(importDomainsCursor.getColumnIndexOrThrow(DomainsDatabaseHelper.ENABLE_ULTRAPRIVACY)));
                 domainsContentValues.put(DomainsDatabaseHelper.BLOCK_ALL_THIRD_PARTY_REQUESTS,
-                        importDomainsCursor.getInt(importDomainsCursor.getColumnIndex(DomainsDatabaseHelper.BLOCK_ALL_THIRD_PARTY_REQUESTS)));
-                domainsContentValues.put(DomainsDatabaseHelper.USER_AGENT, importDomainsCursor.getString(importDomainsCursor.getColumnIndex(DomainsDatabaseHelper.USER_AGENT)));
-                domainsContentValues.put(DomainsDatabaseHelper.FONT_SIZE, importDomainsCursor.getInt(importDomainsCursor.getColumnIndex(DomainsDatabaseHelper.FONT_SIZE)));
-                domainsContentValues.put(DomainsDatabaseHelper.SWIPE_TO_REFRESH, importDomainsCursor.getInt(importDomainsCursor.getColumnIndex(DomainsDatabaseHelper.SWIPE_TO_REFRESH)));
-                domainsContentValues.put(DomainsDatabaseHelper.WEBVIEW_THEME, importDomainsCursor.getInt(importDomainsCursor.getColumnIndex(DomainsDatabaseHelper.WEBVIEW_THEME)));
-                domainsContentValues.put(DomainsDatabaseHelper.WIDE_VIEWPORT, importDomainsCursor.getInt(importDomainsCursor.getColumnIndex(DomainsDatabaseHelper.WIDE_VIEWPORT)));
-                domainsContentValues.put(DomainsDatabaseHelper.DISPLAY_IMAGES, importDomainsCursor.getInt(importDomainsCursor.getColumnIndex(DomainsDatabaseHelper.DISPLAY_IMAGES)));
-                domainsContentValues.put(DomainsDatabaseHelper.PINNED_SSL_CERTIFICATE, importDomainsCursor.getInt(importDomainsCursor.getColumnIndex(DomainsDatabaseHelper.PINNED_SSL_CERTIFICATE)));
-                domainsContentValues.put(DomainsDatabaseHelper.SSL_ISSUED_TO_COMMON_NAME, importDomainsCursor.getString(importDomainsCursor.getColumnIndex(DomainsDatabaseHelper.SSL_ISSUED_TO_COMMON_NAME)));
-                domainsContentValues.put(DomainsDatabaseHelper.SSL_ISSUED_TO_ORGANIZATION, importDomainsCursor.getString(importDomainsCursor.getColumnIndex(DomainsDatabaseHelper.SSL_ISSUED_TO_ORGANIZATION)));
+                        importDomainsCursor.getInt(importDomainsCursor.getColumnIndexOrThrow(DomainsDatabaseHelper.BLOCK_ALL_THIRD_PARTY_REQUESTS)));
+                domainsContentValues.put(DomainsDatabaseHelper.USER_AGENT, importDomainsCursor.getString(importDomainsCursor.getColumnIndexOrThrow(DomainsDatabaseHelper.USER_AGENT)));
+                domainsContentValues.put(DomainsDatabaseHelper.FONT_SIZE, importDomainsCursor.getInt(importDomainsCursor.getColumnIndexOrThrow(DomainsDatabaseHelper.FONT_SIZE)));
+                domainsContentValues.put(DomainsDatabaseHelper.SWIPE_TO_REFRESH, importDomainsCursor.getInt(importDomainsCursor.getColumnIndexOrThrow(DomainsDatabaseHelper.SWIPE_TO_REFRESH)));
+                domainsContentValues.put(DomainsDatabaseHelper.WEBVIEW_THEME, importDomainsCursor.getInt(importDomainsCursor.getColumnIndexOrThrow(DomainsDatabaseHelper.WEBVIEW_THEME)));
+                domainsContentValues.put(DomainsDatabaseHelper.WIDE_VIEWPORT, importDomainsCursor.getInt(importDomainsCursor.getColumnIndexOrThrow(DomainsDatabaseHelper.WIDE_VIEWPORT)));
+                domainsContentValues.put(DomainsDatabaseHelper.DISPLAY_IMAGES, importDomainsCursor.getInt(importDomainsCursor.getColumnIndexOrThrow(DomainsDatabaseHelper.DISPLAY_IMAGES)));
+                domainsContentValues.put(DomainsDatabaseHelper.PINNED_SSL_CERTIFICATE, importDomainsCursor.getInt(importDomainsCursor.getColumnIndexOrThrow(DomainsDatabaseHelper.PINNED_SSL_CERTIFICATE)));
+                domainsContentValues.put(DomainsDatabaseHelper.SSL_ISSUED_TO_COMMON_NAME,
+                        importDomainsCursor.getString(importDomainsCursor.getColumnIndexOrThrow(DomainsDatabaseHelper.SSL_ISSUED_TO_COMMON_NAME)));
+                domainsContentValues.put(DomainsDatabaseHelper.SSL_ISSUED_TO_ORGANIZATION,
+                        importDomainsCursor.getString(importDomainsCursor.getColumnIndexOrThrow(DomainsDatabaseHelper.SSL_ISSUED_TO_ORGANIZATION)));
                 domainsContentValues.put(DomainsDatabaseHelper.SSL_ISSUED_TO_ORGANIZATIONAL_UNIT,
-                        importDomainsCursor.getString(importDomainsCursor.getColumnIndex(DomainsDatabaseHelper.SSL_ISSUED_TO_ORGANIZATIONAL_UNIT)));
-                domainsContentValues.put(DomainsDatabaseHelper.SSL_ISSUED_BY_COMMON_NAME, importDomainsCursor.getString(importDomainsCursor.getColumnIndex(DomainsDatabaseHelper.SSL_ISSUED_BY_COMMON_NAME)));
-                domainsContentValues.put(DomainsDatabaseHelper.SSL_ISSUED_BY_ORGANIZATION, importDomainsCursor.getString(importDomainsCursor.getColumnIndex(DomainsDatabaseHelper.SSL_ISSUED_BY_ORGANIZATION)));
+                        importDomainsCursor.getString(importDomainsCursor.getColumnIndexOrThrow(DomainsDatabaseHelper.SSL_ISSUED_TO_ORGANIZATIONAL_UNIT)));
+                domainsContentValues.put(DomainsDatabaseHelper.SSL_ISSUED_BY_COMMON_NAME,
+                        importDomainsCursor.getString(importDomainsCursor.getColumnIndexOrThrow(DomainsDatabaseHelper.SSL_ISSUED_BY_COMMON_NAME)));
+                domainsContentValues.put(DomainsDatabaseHelper.SSL_ISSUED_BY_ORGANIZATION,
+                        importDomainsCursor.getString(importDomainsCursor.getColumnIndexOrThrow(DomainsDatabaseHelper.SSL_ISSUED_BY_ORGANIZATION)));
                 domainsContentValues.put(DomainsDatabaseHelper.SSL_ISSUED_BY_ORGANIZATIONAL_UNIT,
-                        importDomainsCursor.getString(importDomainsCursor.getColumnIndex(DomainsDatabaseHelper.SSL_ISSUED_BY_ORGANIZATIONAL_UNIT)));
-                domainsContentValues.put(DomainsDatabaseHelper.SSL_START_DATE, importDomainsCursor.getLong(importDomainsCursor.getColumnIndex(DomainsDatabaseHelper.SSL_START_DATE)));
-                domainsContentValues.put(DomainsDatabaseHelper.SSL_END_DATE, importDomainsCursor.getLong(importDomainsCursor.getColumnIndex(DomainsDatabaseHelper.SSL_END_DATE)));
-                domainsContentValues.put(DomainsDatabaseHelper.PINNED_IP_ADDRESSES, importDomainsCursor.getInt(importDomainsCursor.getColumnIndex(DomainsDatabaseHelper.PINNED_IP_ADDRESSES)));
-                domainsContentValues.put(DomainsDatabaseHelper.IP_ADDRESSES, importDomainsCursor.getString(importDomainsCursor.getColumnIndex(DomainsDatabaseHelper.IP_ADDRESSES)));
+                        importDomainsCursor.getString(importDomainsCursor.getColumnIndexOrThrow(DomainsDatabaseHelper.SSL_ISSUED_BY_ORGANIZATIONAL_UNIT)));
+                domainsContentValues.put(DomainsDatabaseHelper.SSL_START_DATE, importDomainsCursor.getLong(importDomainsCursor.getColumnIndexOrThrow(DomainsDatabaseHelper.SSL_START_DATE)));
+                domainsContentValues.put(DomainsDatabaseHelper.SSL_END_DATE, importDomainsCursor.getLong(importDomainsCursor.getColumnIndexOrThrow(DomainsDatabaseHelper.SSL_END_DATE)));
+                domainsContentValues.put(DomainsDatabaseHelper.PINNED_IP_ADDRESSES, importDomainsCursor.getInt(importDomainsCursor.getColumnIndexOrThrow(DomainsDatabaseHelper.PINNED_IP_ADDRESSES)));
+                domainsContentValues.put(DomainsDatabaseHelper.IP_ADDRESSES, importDomainsCursor.getString(importDomainsCursor.getColumnIndexOrThrow(DomainsDatabaseHelper.IP_ADDRESSES)));
 
                 // Insert the record into the export database.
                 domainsDatabaseHelper.addDomain(domainsContentValues);
@@ -481,50 +485,50 @@ public class ImportExportDatabaseHelper {
 
             // Import the preference data.
             sharedPreferences.edit()
-                    .putBoolean(JAVASCRIPT, importPreferencesCursor.getInt(importPreferencesCursor.getColumnIndex(JAVASCRIPT)) == 1)
-                    .putBoolean(COOKIES, importPreferencesCursor.getInt(importPreferencesCursor.getColumnIndex(COOKIES)) == 1)
-                    .putBoolean(DOM_STORAGE, importPreferencesCursor.getInt(importPreferencesCursor.getColumnIndex(DOM_STORAGE)) == 1)
+                    .putBoolean(JAVASCRIPT, importPreferencesCursor.getInt(importPreferencesCursor.getColumnIndexOrThrow(JAVASCRIPT)) == 1)
+                    .putBoolean(COOKIES, importPreferencesCursor.getInt(importPreferencesCursor.getColumnIndexOrThrow(COOKIES)) == 1)
+                    .putBoolean(DOM_STORAGE, importPreferencesCursor.getInt(importPreferencesCursor.getColumnIndexOrThrow(DOM_STORAGE)) == 1)
                     // Save form data can be removed once the minimum API >= 26.
-                    .putBoolean(SAVE_FORM_DATA, importPreferencesCursor.getInt(importPreferencesCursor.getColumnIndex(SAVE_FORM_DATA)) == 1)
-                    .putString(USER_AGENT, importPreferencesCursor.getString(importPreferencesCursor.getColumnIndex(USER_AGENT)))
-                    .putString(CUSTOM_USER_AGENT, importPreferencesCursor.getString(importPreferencesCursor.getColumnIndex(CUSTOM_USER_AGENT)))
-                    .putBoolean(INCOGNITO_MODE, importPreferencesCursor.getInt(importPreferencesCursor.getColumnIndex(INCOGNITO_MODE)) == 1)
-                    .putBoolean(ALLOW_SCREENSHOTS, importPreferencesCursor.getInt(importPreferencesCursor.getColumnIndex(ALLOW_SCREENSHOTS)) == 1)
-                    .putBoolean(EASYLIST, importPreferencesCursor.getInt(importPreferencesCursor.getColumnIndex(EASYLIST)) == 1)
-                    .putBoolean(EASYPRIVACY, importPreferencesCursor.getInt(importPreferencesCursor.getColumnIndex(EASYPRIVACY)) == 1)
-                    .putBoolean(FANBOYS_ANNOYANCE_LIST, importPreferencesCursor.getInt(importPreferencesCursor.getColumnIndex(FANBOYS_ANNOYANCE_LIST)) == 1)
-                    .putBoolean(FANBOYS_SOCIAL_BLOCKING_LIST, importPreferencesCursor.getInt(importPreferencesCursor.getColumnIndex(FANBOYS_SOCIAL_BLOCKING_LIST)) == 1)
-                    .putBoolean(ULTRALIST, importPreferencesCursor.getInt(importPreferencesCursor.getColumnIndex(ULTRALIST)) == 1)
-                    .putBoolean(ULTRAPRIVACY, importPreferencesCursor.getInt(importPreferencesCursor.getColumnIndex(ULTRAPRIVACY)) == 1)
-                    .putBoolean(BLOCK_ALL_THIRD_PARTY_REQUESTS, importPreferencesCursor.getInt(importPreferencesCursor.getColumnIndex(BLOCK_ALL_THIRD_PARTY_REQUESTS)) == 1)
-                    .putBoolean(GOOGLE_ANALYTICS, importPreferencesCursor.getInt(importPreferencesCursor.getColumnIndex(GOOGLE_ANALYTICS)) == 1)
-                    .putBoolean(FACEBOOK_CLICK_IDS, importPreferencesCursor.getInt(importPreferencesCursor.getColumnIndex(FACEBOOK_CLICK_IDS)) == 1)
-                    .putBoolean(TWITTER_AMP_REDIRECTS, importPreferencesCursor.getInt(importPreferencesCursor.getColumnIndex(TWITTER_AMP_REDIRECTS)) == 1)
-                    .putString(SEARCH, importPreferencesCursor.getString(importPreferencesCursor.getColumnIndex(SEARCH)))
-                    .putString(SEARCH_CUSTOM_URL, importPreferencesCursor.getString(importPreferencesCursor.getColumnIndex(SEARCH_CUSTOM_URL)))
-                    .putString(PROXY, importPreferencesCursor.getString(importPreferencesCursor.getColumnIndex(PROXY)))
-                    .putString(PROXY_CUSTOM_URL, importPreferencesCursor.getString(importPreferencesCursor.getColumnIndex(PROXY_CUSTOM_URL)))
-                    .putBoolean(FULL_SCREEN_BROWSING_MODE, importPreferencesCursor.getInt(importPreferencesCursor.getColumnIndex(FULL_SCREEN_BROWSING_MODE)) == 1)
-                    .putBoolean(HIDE_APP_BAR, importPreferencesCursor.getInt(importPreferencesCursor.getColumnIndex(HIDE_APP_BAR)) == 1)
-                    .putBoolean(CLEAR_EVERYTHING, importPreferencesCursor.getInt(importPreferencesCursor.getColumnIndex(CLEAR_EVERYTHING)) == 1)
-                    .putBoolean(CLEAR_COOKIES, importPreferencesCursor.getInt(importPreferencesCursor.getColumnIndex(CLEAR_COOKIES)) == 1)
-                    .putBoolean(CLEAR_DOM_STORAGE, importPreferencesCursor.getInt(importPreferencesCursor.getColumnIndex(CLEAR_DOM_STORAGE)) == 1)
+                    .putBoolean(SAVE_FORM_DATA, importPreferencesCursor.getInt(importPreferencesCursor.getColumnIndexOrThrow(SAVE_FORM_DATA)) == 1)
+                    .putString(USER_AGENT, importPreferencesCursor.getString(importPreferencesCursor.getColumnIndexOrThrow(USER_AGENT)))
+                    .putString(CUSTOM_USER_AGENT, importPreferencesCursor.getString(importPreferencesCursor.getColumnIndexOrThrow(CUSTOM_USER_AGENT)))
+                    .putBoolean(INCOGNITO_MODE, importPreferencesCursor.getInt(importPreferencesCursor.getColumnIndexOrThrow(INCOGNITO_MODE)) == 1)
+                    .putBoolean(ALLOW_SCREENSHOTS, importPreferencesCursor.getInt(importPreferencesCursor.getColumnIndexOrThrow(ALLOW_SCREENSHOTS)) == 1)
+                    .putBoolean(EASYLIST, importPreferencesCursor.getInt(importPreferencesCursor.getColumnIndexOrThrow(EASYLIST)) == 1)
+                    .putBoolean(EASYPRIVACY, importPreferencesCursor.getInt(importPreferencesCursor.getColumnIndexOrThrow(EASYPRIVACY)) == 1)
+                    .putBoolean(FANBOYS_ANNOYANCE_LIST, importPreferencesCursor.getInt(importPreferencesCursor.getColumnIndexOrThrow(FANBOYS_ANNOYANCE_LIST)) == 1)
+                    .putBoolean(FANBOYS_SOCIAL_BLOCKING_LIST, importPreferencesCursor.getInt(importPreferencesCursor.getColumnIndexOrThrow(FANBOYS_SOCIAL_BLOCKING_LIST)) == 1)
+                    .putBoolean(ULTRALIST, importPreferencesCursor.getInt(importPreferencesCursor.getColumnIndexOrThrow(ULTRALIST)) == 1)
+                    .putBoolean(ULTRAPRIVACY, importPreferencesCursor.getInt(importPreferencesCursor.getColumnIndexOrThrow(ULTRAPRIVACY)) == 1)
+                    .putBoolean(BLOCK_ALL_THIRD_PARTY_REQUESTS, importPreferencesCursor.getInt(importPreferencesCursor.getColumnIndexOrThrow(BLOCK_ALL_THIRD_PARTY_REQUESTS)) == 1)
+                    .putBoolean(GOOGLE_ANALYTICS, importPreferencesCursor.getInt(importPreferencesCursor.getColumnIndexOrThrow(GOOGLE_ANALYTICS)) == 1)
+                    .putBoolean(FACEBOOK_CLICK_IDS, importPreferencesCursor.getInt(importPreferencesCursor.getColumnIndexOrThrow(FACEBOOK_CLICK_IDS)) == 1)
+                    .putBoolean(TWITTER_AMP_REDIRECTS, importPreferencesCursor.getInt(importPreferencesCursor.getColumnIndexOrThrow(TWITTER_AMP_REDIRECTS)) == 1)
+                    .putString(SEARCH, importPreferencesCursor.getString(importPreferencesCursor.getColumnIndexOrThrow(SEARCH)))
+                    .putString(SEARCH_CUSTOM_URL, importPreferencesCursor.getString(importPreferencesCursor.getColumnIndexOrThrow(SEARCH_CUSTOM_URL)))
+                    .putString(PROXY, importPreferencesCursor.getString(importPreferencesCursor.getColumnIndexOrThrow(PROXY)))
+                    .putString(PROXY_CUSTOM_URL, importPreferencesCursor.getString(importPreferencesCursor.getColumnIndexOrThrow(PROXY_CUSTOM_URL)))
+                    .putBoolean(FULL_SCREEN_BROWSING_MODE, importPreferencesCursor.getInt(importPreferencesCursor.getColumnIndexOrThrow(FULL_SCREEN_BROWSING_MODE)) == 1)
+                    .putBoolean(HIDE_APP_BAR, importPreferencesCursor.getInt(importPreferencesCursor.getColumnIndexOrThrow(HIDE_APP_BAR)) == 1)
+                    .putBoolean(CLEAR_EVERYTHING, importPreferencesCursor.getInt(importPreferencesCursor.getColumnIndexOrThrow(CLEAR_EVERYTHING)) == 1)
+                    .putBoolean(CLEAR_COOKIES, importPreferencesCursor.getInt(importPreferencesCursor.getColumnIndexOrThrow(CLEAR_COOKIES)) == 1)
+                    .putBoolean(CLEAR_DOM_STORAGE, importPreferencesCursor.getInt(importPreferencesCursor.getColumnIndexOrThrow(CLEAR_DOM_STORAGE)) == 1)
                     // Clear form data can be removed once the minimum API >= 26.
-                    .putBoolean(CLEAR_FORM_DATA, importPreferencesCursor.getInt(importPreferencesCursor.getColumnIndex(CLEAR_FORM_DATA)) == 1)
-                    .putBoolean(CLEAR_LOGCAT, importPreferencesCursor.getInt(importPreferencesCursor.getColumnIndex(CLEAR_LOGCAT)) == 1)
-                    .putBoolean(CLEAR_CACHE, importPreferencesCursor.getInt(importPreferencesCursor.getColumnIndex(CLEAR_CACHE)) == 1)
-                    .putString(HOMEPAGE, importPreferencesCursor.getString(importPreferencesCursor.getColumnIndex(HOMEPAGE)))
-                    .putString(FONT_SIZE, importPreferencesCursor.getString(importPreferencesCursor.getColumnIndex(FONT_SIZE)))
-                    .putBoolean(OPEN_INTENTS_IN_NEW_TAB, importPreferencesCursor.getInt(importPreferencesCursor.getColumnIndex(OPEN_INTENTS_IN_NEW_TAB)) == 1)
-                    .putBoolean(SWIPE_TO_REFRESH, importPreferencesCursor.getInt(importPreferencesCursor.getColumnIndex(SWIPE_TO_REFRESH)) == 1)
-                    .putBoolean(DOWNLOAD_WITH_EXTERNAL_APP, importPreferencesCursor.getInt(importPreferencesCursor.getColumnIndex(DOWNLOAD_WITH_EXTERNAL_APP)) == 1)
-                    .putBoolean(SCROLL_APP_BAR, importPreferencesCursor.getInt(importPreferencesCursor.getColumnIndex(SCROLL_APP_BAR)) == 1)
-                    .putBoolean(BOTTOM_APP_BAR, importPreferencesCursor.getInt(importPreferencesCursor.getColumnIndex(BOTTOM_APP_BAR)) == 1)
-                    .putBoolean(DISPLAY_ADDITIONAL_APP_BAR_ICONS, importPreferencesCursor.getInt(importPreferencesCursor.getColumnIndex(DISPLAY_ADDITIONAL_APP_BAR_ICONS)) == 1)
-                    .putString(APP_THEME, importPreferencesCursor.getString(importPreferencesCursor.getColumnIndex(APP_THEME)))
-                    .putString(WEBVIEW_THEME, importPreferencesCursor.getString(importPreferencesCursor.getColumnIndex(WEBVIEW_THEME)))
-                    .putBoolean(WIDE_VIEWPORT, importPreferencesCursor.getInt(importPreferencesCursor.getColumnIndex(WIDE_VIEWPORT)) == 1)
-                    .putBoolean(DISPLAY_WEBPAGE_IMAGES, importPreferencesCursor.getInt(importPreferencesCursor.getColumnIndex(DISPLAY_WEBPAGE_IMAGES)) == 1)
+                    .putBoolean(CLEAR_FORM_DATA, importPreferencesCursor.getInt(importPreferencesCursor.getColumnIndexOrThrow(CLEAR_FORM_DATA)) == 1)
+                    .putBoolean(CLEAR_LOGCAT, importPreferencesCursor.getInt(importPreferencesCursor.getColumnIndexOrThrow(CLEAR_LOGCAT)) == 1)
+                    .putBoolean(CLEAR_CACHE, importPreferencesCursor.getInt(importPreferencesCursor.getColumnIndexOrThrow(CLEAR_CACHE)) == 1)
+                    .putString(HOMEPAGE, importPreferencesCursor.getString(importPreferencesCursor.getColumnIndexOrThrow(HOMEPAGE)))
+                    .putString(FONT_SIZE, importPreferencesCursor.getString(importPreferencesCursor.getColumnIndexOrThrow(FONT_SIZE)))
+                    .putBoolean(OPEN_INTENTS_IN_NEW_TAB, importPreferencesCursor.getInt(importPreferencesCursor.getColumnIndexOrThrow(OPEN_INTENTS_IN_NEW_TAB)) == 1)
+                    .putBoolean(SWIPE_TO_REFRESH, importPreferencesCursor.getInt(importPreferencesCursor.getColumnIndexOrThrow(SWIPE_TO_REFRESH)) == 1)
+                    .putBoolean(DOWNLOAD_WITH_EXTERNAL_APP, importPreferencesCursor.getInt(importPreferencesCursor.getColumnIndexOrThrow(DOWNLOAD_WITH_EXTERNAL_APP)) == 1)
+                    .putBoolean(SCROLL_APP_BAR, importPreferencesCursor.getInt(importPreferencesCursor.getColumnIndexOrThrow(SCROLL_APP_BAR)) == 1)
+                    .putBoolean(BOTTOM_APP_BAR, importPreferencesCursor.getInt(importPreferencesCursor.getColumnIndexOrThrow(BOTTOM_APP_BAR)) == 1)
+                    .putBoolean(DISPLAY_ADDITIONAL_APP_BAR_ICONS, importPreferencesCursor.getInt(importPreferencesCursor.getColumnIndexOrThrow(DISPLAY_ADDITIONAL_APP_BAR_ICONS)) == 1)
+                    .putString(APP_THEME, importPreferencesCursor.getString(importPreferencesCursor.getColumnIndexOrThrow(APP_THEME)))
+                    .putString(WEBVIEW_THEME, importPreferencesCursor.getString(importPreferencesCursor.getColumnIndexOrThrow(WEBVIEW_THEME)))
+                    .putBoolean(WIDE_VIEWPORT, importPreferencesCursor.getInt(importPreferencesCursor.getColumnIndexOrThrow(WIDE_VIEWPORT)) == 1)
+                    .putBoolean(DISPLAY_WEBPAGE_IMAGES, importPreferencesCursor.getInt(importPreferencesCursor.getColumnIndexOrThrow(DISPLAY_WEBPAGE_IMAGES)) == 1)
                     .apply();
 
             // Close the preferences cursor.
@@ -572,12 +576,12 @@ public class ImportExportDatabaseHelper {
             for (int i = 0; i < bookmarksCursor.getCount(); i++) {
                 // Extract the record from the cursor and store the data in a ContentValues.
                 ContentValues bookmarksContentValues = new ContentValues();
-                bookmarksContentValues.put(BookmarksDatabaseHelper.BOOKMARK_NAME, bookmarksCursor.getString(bookmarksCursor.getColumnIndex(BookmarksDatabaseHelper.BOOKMARK_NAME)));
-                bookmarksContentValues.put(BookmarksDatabaseHelper.BOOKMARK_URL, bookmarksCursor.getString(bookmarksCursor.getColumnIndex(BookmarksDatabaseHelper.BOOKMARK_URL)));
-                bookmarksContentValues.put(BookmarksDatabaseHelper.PARENT_FOLDER, bookmarksCursor.getString(bookmarksCursor.getColumnIndex(BookmarksDatabaseHelper.PARENT_FOLDER)));
-                bookmarksContentValues.put(BookmarksDatabaseHelper.DISPLAY_ORDER, bookmarksCursor.getInt(bookmarksCursor.getColumnIndex(BookmarksDatabaseHelper.DISPLAY_ORDER)));
-                bookmarksContentValues.put(BookmarksDatabaseHelper.IS_FOLDER, bookmarksCursor.getInt(bookmarksCursor.getColumnIndex(BookmarksDatabaseHelper.IS_FOLDER)));
-                bookmarksContentValues.put(BookmarksDatabaseHelper.FAVORITE_ICON, bookmarksCursor.getBlob(bookmarksCursor.getColumnIndex(BookmarksDatabaseHelper.FAVORITE_ICON)));
+                bookmarksContentValues.put(BookmarksDatabaseHelper.BOOKMARK_NAME, bookmarksCursor.getString(bookmarksCursor.getColumnIndexOrThrow(BookmarksDatabaseHelper.BOOKMARK_NAME)));
+                bookmarksContentValues.put(BookmarksDatabaseHelper.BOOKMARK_URL, bookmarksCursor.getString(bookmarksCursor.getColumnIndexOrThrow(BookmarksDatabaseHelper.BOOKMARK_URL)));
+                bookmarksContentValues.put(BookmarksDatabaseHelper.PARENT_FOLDER, bookmarksCursor.getString(bookmarksCursor.getColumnIndexOrThrow(BookmarksDatabaseHelper.PARENT_FOLDER)));
+                bookmarksContentValues.put(BookmarksDatabaseHelper.DISPLAY_ORDER, bookmarksCursor.getInt(bookmarksCursor.getColumnIndexOrThrow(BookmarksDatabaseHelper.DISPLAY_ORDER)));
+                bookmarksContentValues.put(BookmarksDatabaseHelper.IS_FOLDER, bookmarksCursor.getInt(bookmarksCursor.getColumnIndexOrThrow(BookmarksDatabaseHelper.IS_FOLDER)));
+                bookmarksContentValues.put(BookmarksDatabaseHelper.FAVORITE_ICON, bookmarksCursor.getBlob(bookmarksCursor.getColumnIndexOrThrow(BookmarksDatabaseHelper.FAVORITE_ICON)));
 
                 // Insert the record into the temporary export database.
                 temporaryExportDatabase.insert(BookmarksDatabaseHelper.BOOKMARKS_TABLE, null, bookmarksContentValues);
@@ -607,35 +611,38 @@ public class ImportExportDatabaseHelper {
             for (int i = 0; i < domainsCursor.getCount(); i++) {
                 // Extract the record from the cursor and store the data in a ContentValues.
                 ContentValues domainsContentValues = new ContentValues();
-                domainsContentValues.put(DomainsDatabaseHelper.DOMAIN_NAME, domainsCursor.getString(domainsCursor.getColumnIndex(DomainsDatabaseHelper.DOMAIN_NAME)));
-                domainsContentValues.put(DomainsDatabaseHelper.ENABLE_JAVASCRIPT, domainsCursor.getInt(domainsCursor.getColumnIndex(DomainsDatabaseHelper.ENABLE_JAVASCRIPT)));
-                domainsContentValues.put(DomainsDatabaseHelper.COOKIES, domainsCursor.getInt(domainsCursor.getColumnIndex(DomainsDatabaseHelper.COOKIES)));
-                domainsContentValues.put(DomainsDatabaseHelper.ENABLE_DOM_STORAGE, domainsCursor.getInt(domainsCursor.getColumnIndex(DomainsDatabaseHelper.ENABLE_DOM_STORAGE)));
-                domainsContentValues.put(DomainsDatabaseHelper.ENABLE_FORM_DATA, domainsCursor.getInt(domainsCursor.getColumnIndex(DomainsDatabaseHelper.ENABLE_FORM_DATA)));
-                domainsContentValues.put(DomainsDatabaseHelper.ENABLE_EASYLIST, domainsCursor.getInt(domainsCursor.getColumnIndex(DomainsDatabaseHelper.ENABLE_EASYLIST)));
-                domainsContentValues.put(DomainsDatabaseHelper.ENABLE_EASYPRIVACY, domainsCursor.getInt(domainsCursor.getColumnIndex(DomainsDatabaseHelper.ENABLE_EASYPRIVACY)));
-                domainsContentValues.put(DomainsDatabaseHelper.ENABLE_FANBOYS_ANNOYANCE_LIST, domainsCursor.getInt(domainsCursor.getColumnIndex(DomainsDatabaseHelper.ENABLE_FANBOYS_ANNOYANCE_LIST)));
-                domainsContentValues.put(DomainsDatabaseHelper.ENABLE_FANBOYS_SOCIAL_BLOCKING_LIST, domainsCursor.getInt(domainsCursor.getColumnIndex(DomainsDatabaseHelper.ENABLE_FANBOYS_SOCIAL_BLOCKING_LIST)));
-                domainsContentValues.put(DomainsDatabaseHelper.ULTRALIST, domainsCursor.getInt(domainsCursor.getColumnIndex(DomainsDatabaseHelper.ULTRALIST)));
-                domainsContentValues.put(DomainsDatabaseHelper.ENABLE_ULTRAPRIVACY, domainsCursor.getInt(domainsCursor.getColumnIndex(DomainsDatabaseHelper.ENABLE_ULTRAPRIVACY)));
-                domainsContentValues.put(DomainsDatabaseHelper.BLOCK_ALL_THIRD_PARTY_REQUESTS, domainsCursor.getInt(domainsCursor.getColumnIndex(DomainsDatabaseHelper.BLOCK_ALL_THIRD_PARTY_REQUESTS)));
-                domainsContentValues.put(DomainsDatabaseHelper.USER_AGENT, domainsCursor.getString(domainsCursor.getColumnIndex(DomainsDatabaseHelper.USER_AGENT)));
-                domainsContentValues.put(DomainsDatabaseHelper.FONT_SIZE, domainsCursor.getInt(domainsCursor.getColumnIndex(DomainsDatabaseHelper.FONT_SIZE)));
-                domainsContentValues.put(DomainsDatabaseHelper.SWIPE_TO_REFRESH, domainsCursor.getInt(domainsCursor.getColumnIndex(DomainsDatabaseHelper.SWIPE_TO_REFRESH)));
-                domainsContentValues.put(DomainsDatabaseHelper.WEBVIEW_THEME, domainsCursor.getInt(domainsCursor.getColumnIndex(DomainsDatabaseHelper.WEBVIEW_THEME)));
-                domainsContentValues.put(DomainsDatabaseHelper.WIDE_VIEWPORT, domainsCursor.getInt(domainsCursor.getColumnIndex(DomainsDatabaseHelper.WIDE_VIEWPORT)));
-                domainsContentValues.put(DomainsDatabaseHelper.DISPLAY_IMAGES, domainsCursor.getInt(domainsCursor.getColumnIndex(DomainsDatabaseHelper.DISPLAY_IMAGES)));
-                domainsContentValues.put(DomainsDatabaseHelper.PINNED_SSL_CERTIFICATE, domainsCursor.getInt(domainsCursor.getColumnIndex(DomainsDatabaseHelper.PINNED_SSL_CERTIFICATE)));
-                domainsContentValues.put(DomainsDatabaseHelper.SSL_ISSUED_TO_COMMON_NAME, domainsCursor.getString(domainsCursor.getColumnIndex(DomainsDatabaseHelper.SSL_ISSUED_TO_COMMON_NAME)));
-                domainsContentValues.put(DomainsDatabaseHelper.SSL_ISSUED_TO_ORGANIZATION, domainsCursor.getString(domainsCursor.getColumnIndex(DomainsDatabaseHelper.SSL_ISSUED_TO_ORGANIZATION)));
-                domainsContentValues.put(DomainsDatabaseHelper.SSL_ISSUED_TO_ORGANIZATIONAL_UNIT, domainsCursor.getString(domainsCursor.getColumnIndex(DomainsDatabaseHelper.SSL_ISSUED_TO_ORGANIZATIONAL_UNIT)));
-                domainsContentValues.put(DomainsDatabaseHelper.SSL_ISSUED_BY_COMMON_NAME, domainsCursor.getString(domainsCursor.getColumnIndex(DomainsDatabaseHelper.SSL_ISSUED_BY_COMMON_NAME)));
-                domainsContentValues.put(DomainsDatabaseHelper.SSL_ISSUED_BY_ORGANIZATION, domainsCursor.getString(domainsCursor.getColumnIndex(DomainsDatabaseHelper.SSL_ISSUED_BY_ORGANIZATION)));
-                domainsContentValues.put(DomainsDatabaseHelper.SSL_ISSUED_BY_ORGANIZATIONAL_UNIT, domainsCursor.getString(domainsCursor.getColumnIndex(DomainsDatabaseHelper.SSL_ISSUED_BY_ORGANIZATIONAL_UNIT)));
-                domainsContentValues.put(DomainsDatabaseHelper.SSL_START_DATE, domainsCursor.getLong(domainsCursor.getColumnIndex(DomainsDatabaseHelper.SSL_START_DATE)));
-                domainsContentValues.put(DomainsDatabaseHelper.SSL_END_DATE, domainsCursor.getLong(domainsCursor.getColumnIndex(DomainsDatabaseHelper.SSL_END_DATE)));
-                domainsContentValues.put(DomainsDatabaseHelper.PINNED_IP_ADDRESSES, domainsCursor.getInt(domainsCursor.getColumnIndex(DomainsDatabaseHelper.PINNED_IP_ADDRESSES)));
-                domainsContentValues.put(DomainsDatabaseHelper.IP_ADDRESSES, domainsCursor.getString(domainsCursor.getColumnIndex(DomainsDatabaseHelper.IP_ADDRESSES)));
+                domainsContentValues.put(DomainsDatabaseHelper.DOMAIN_NAME, domainsCursor.getString(domainsCursor.getColumnIndexOrThrow(DomainsDatabaseHelper.DOMAIN_NAME)));
+                domainsContentValues.put(DomainsDatabaseHelper.ENABLE_JAVASCRIPT, domainsCursor.getInt(domainsCursor.getColumnIndexOrThrow(DomainsDatabaseHelper.ENABLE_JAVASCRIPT)));
+                domainsContentValues.put(DomainsDatabaseHelper.COOKIES, domainsCursor.getInt(domainsCursor.getColumnIndexOrThrow(DomainsDatabaseHelper.COOKIES)));
+                domainsContentValues.put(DomainsDatabaseHelper.ENABLE_DOM_STORAGE, domainsCursor.getInt(domainsCursor.getColumnIndexOrThrow(DomainsDatabaseHelper.ENABLE_DOM_STORAGE)));
+                domainsContentValues.put(DomainsDatabaseHelper.ENABLE_FORM_DATA, domainsCursor.getInt(domainsCursor.getColumnIndexOrThrow(DomainsDatabaseHelper.ENABLE_FORM_DATA)));
+                domainsContentValues.put(DomainsDatabaseHelper.ENABLE_EASYLIST, domainsCursor.getInt(domainsCursor.getColumnIndexOrThrow(DomainsDatabaseHelper.ENABLE_EASYLIST)));
+                domainsContentValues.put(DomainsDatabaseHelper.ENABLE_EASYPRIVACY, domainsCursor.getInt(domainsCursor.getColumnIndexOrThrow(DomainsDatabaseHelper.ENABLE_EASYPRIVACY)));
+                domainsContentValues.put(DomainsDatabaseHelper.ENABLE_FANBOYS_ANNOYANCE_LIST, domainsCursor.getInt(domainsCursor.getColumnIndexOrThrow(DomainsDatabaseHelper.ENABLE_FANBOYS_ANNOYANCE_LIST)));
+                domainsContentValues.put(DomainsDatabaseHelper.ENABLE_FANBOYS_SOCIAL_BLOCKING_LIST,
+                        domainsCursor.getInt(domainsCursor.getColumnIndexOrThrow(DomainsDatabaseHelper.ENABLE_FANBOYS_SOCIAL_BLOCKING_LIST)));
+                domainsContentValues.put(DomainsDatabaseHelper.ULTRALIST, domainsCursor.getInt(domainsCursor.getColumnIndexOrThrow(DomainsDatabaseHelper.ULTRALIST)));
+                domainsContentValues.put(DomainsDatabaseHelper.ENABLE_ULTRAPRIVACY, domainsCursor.getInt(domainsCursor.getColumnIndexOrThrow(DomainsDatabaseHelper.ENABLE_ULTRAPRIVACY)));
+                domainsContentValues.put(DomainsDatabaseHelper.BLOCK_ALL_THIRD_PARTY_REQUESTS, domainsCursor.getInt(domainsCursor.getColumnIndexOrThrow(DomainsDatabaseHelper.BLOCK_ALL_THIRD_PARTY_REQUESTS)));
+                domainsContentValues.put(DomainsDatabaseHelper.USER_AGENT, domainsCursor.getString(domainsCursor.getColumnIndexOrThrow(DomainsDatabaseHelper.USER_AGENT)));
+                domainsContentValues.put(DomainsDatabaseHelper.FONT_SIZE, domainsCursor.getInt(domainsCursor.getColumnIndexOrThrow(DomainsDatabaseHelper.FONT_SIZE)));
+                domainsContentValues.put(DomainsDatabaseHelper.SWIPE_TO_REFRESH, domainsCursor.getInt(domainsCursor.getColumnIndexOrThrow(DomainsDatabaseHelper.SWIPE_TO_REFRESH)));
+                domainsContentValues.put(DomainsDatabaseHelper.WEBVIEW_THEME, domainsCursor.getInt(domainsCursor.getColumnIndexOrThrow(DomainsDatabaseHelper.WEBVIEW_THEME)));
+                domainsContentValues.put(DomainsDatabaseHelper.WIDE_VIEWPORT, domainsCursor.getInt(domainsCursor.getColumnIndexOrThrow(DomainsDatabaseHelper.WIDE_VIEWPORT)));
+                domainsContentValues.put(DomainsDatabaseHelper.DISPLAY_IMAGES, domainsCursor.getInt(domainsCursor.getColumnIndexOrThrow(DomainsDatabaseHelper.DISPLAY_IMAGES)));
+                domainsContentValues.put(DomainsDatabaseHelper.PINNED_SSL_CERTIFICATE, domainsCursor.getInt(domainsCursor.getColumnIndexOrThrow(DomainsDatabaseHelper.PINNED_SSL_CERTIFICATE)));
+                domainsContentValues.put(DomainsDatabaseHelper.SSL_ISSUED_TO_COMMON_NAME, domainsCursor.getString(domainsCursor.getColumnIndexOrThrow(DomainsDatabaseHelper.SSL_ISSUED_TO_COMMON_NAME)));
+                domainsContentValues.put(DomainsDatabaseHelper.SSL_ISSUED_TO_ORGANIZATION, domainsCursor.getString(domainsCursor.getColumnIndexOrThrow(DomainsDatabaseHelper.SSL_ISSUED_TO_ORGANIZATION)));
+                domainsContentValues.put(DomainsDatabaseHelper.SSL_ISSUED_TO_ORGANIZATIONAL_UNIT,
+                        domainsCursor.getString(domainsCursor.getColumnIndexOrThrow(DomainsDatabaseHelper.SSL_ISSUED_TO_ORGANIZATIONAL_UNIT)));
+                domainsContentValues.put(DomainsDatabaseHelper.SSL_ISSUED_BY_COMMON_NAME, domainsCursor.getString(domainsCursor.getColumnIndexOrThrow(DomainsDatabaseHelper.SSL_ISSUED_BY_COMMON_NAME)));
+                domainsContentValues.put(DomainsDatabaseHelper.SSL_ISSUED_BY_ORGANIZATION, domainsCursor.getString(domainsCursor.getColumnIndexOrThrow(DomainsDatabaseHelper.SSL_ISSUED_BY_ORGANIZATION)));
+                domainsContentValues.put(DomainsDatabaseHelper.SSL_ISSUED_BY_ORGANIZATIONAL_UNIT,
+                        domainsCursor.getString(domainsCursor.getColumnIndexOrThrow(DomainsDatabaseHelper.SSL_ISSUED_BY_ORGANIZATIONAL_UNIT)));
+                domainsContentValues.put(DomainsDatabaseHelper.SSL_START_DATE, domainsCursor.getLong(domainsCursor.getColumnIndexOrThrow(DomainsDatabaseHelper.SSL_START_DATE)));
+                domainsContentValues.put(DomainsDatabaseHelper.SSL_END_DATE, domainsCursor.getLong(domainsCursor.getColumnIndexOrThrow(DomainsDatabaseHelper.SSL_END_DATE)));
+                domainsContentValues.put(DomainsDatabaseHelper.PINNED_IP_ADDRESSES, domainsCursor.getInt(domainsCursor.getColumnIndexOrThrow(DomainsDatabaseHelper.PINNED_IP_ADDRESSES)));
+                domainsContentValues.put(DomainsDatabaseHelper.IP_ADDRESSES, domainsCursor.getString(domainsCursor.getColumnIndexOrThrow(DomainsDatabaseHelper.IP_ADDRESSES)));
 
                 // Insert the record into the temporary export database.
                 temporaryExportDatabase.insert(DomainsDatabaseHelper.DOMAINS_TABLE, null, domainsContentValues);
diff --git a/app/src/main/java/com/stoutner/privacybrowser/helpers/ProxyHelper.java b/app/src/main/java/com/stoutner/privacybrowser/helpers/ProxyHelper.java
deleted file mode 100644 (file)
index 04e40e9..0000000
+++ /dev/null
@@ -1,315 +0,0 @@
-/*
- * Copyright © 2016-2020 Soren Stoutner <soren@stoutner.com>.
- *
- * This file is part of Privacy Browser <https://www.stoutner.com/privacy-browser>.
- *
- * Privacy Browser is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * Privacy Browser is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with Privacy Browser.  If not, see <http://www.gnu.org/licenses/>.
- */
-
-package com.stoutner.privacybrowser.helpers;
-
-import android.annotation.SuppressLint;
-import android.content.Context;
-import android.content.Intent;
-import android.content.SharedPreferences;
-import android.net.Uri;
-import android.os.Build;
-import android.os.Parcelable;
-import android.util.ArrayMap;
-import android.view.View;
-
-import androidx.preference.PreferenceManager;
-import androidx.webkit.ProxyConfig;
-import androidx.webkit.ProxyController;
-import androidx.webkit.WebViewFeature;
-
-import com.google.android.material.snackbar.Snackbar;
-
-import com.stoutner.privacybrowser.R;
-import com.stoutner.privacybrowser.activities.MainWebViewActivity;
-
-import java.lang.reflect.Field;
-import java.lang.reflect.InvocationTargetException;
-import java.lang.reflect.Method;
-import java.net.InetSocketAddress;
-import java.net.Proxy;
-import java.net.SocketAddress;
-import java.util.concurrent.Executor;
-
-public class ProxyHelper {
-    public static final String NONE = "None";
-    public static final String TOR = "Tor";
-    public static final String I2P = "I2P";
-    public static final String CUSTOM = "Custom";
-
-    public static void setProxy(Context context, View activityView, String proxyMode) {
-        // Initialize the proxy host and port strings.
-        String proxyHost = "0";
-        String proxyPort = "0";
-
-        // Create a proxy config builder.
-        ProxyConfig.Builder proxyConfigBuilder = new ProxyConfig.Builder();
-
-        // Run the commands that correlate to the proxy mode.
-        switch (proxyMode) {
-            case NONE:
-                // Clear the proxy values.
-                System.clearProperty("proxyHost");
-                System.clearProperty("proxyHost");
-                break;
-
-            case TOR:
-                // Update the proxy host and port strings.  These can be removed once the minimum API >= 21.
-                proxyHost = "localhost";
-                proxyPort = "8118";
-
-                // Set the proxy values.  These can be removed once the minimum API >= 21.
-                System.setProperty("proxyHost", proxyHost);
-                System.setProperty("proxyPort", proxyPort);
-
-                // Add the proxy to the builder.  The proxy config builder can use a SOCKS proxy.
-                proxyConfigBuilder.addProxyRule("socks://localhost:9050");
-
-                // Ask Orbot to connect if its current status is not `"ON"`.
-                if (!MainWebViewActivity.orbotStatus.equals("ON")) {
-                    // Create an intent to request Orbot to start.
-                    Intent orbotIntent = new Intent("org.torproject.android.intent.action.START");
-
-                    // Send the intent to the Orbot package.
-                    orbotIntent.setPackage("org.torproject.android");
-
-                    // Request a status response be sent back to this package.
-                    orbotIntent.putExtra("org.torproject.android.intent.extra.PACKAGE_NAME", context.getPackageName());
-
-                    // Make it so.
-                    context.sendBroadcast(orbotIntent);
-                }
-                break;
-
-            case I2P:
-                // Update the proxy host and port strings.  These can be removed once the minimum API >= 21.
-                proxyHost = "localhost";
-                proxyPort = "4444";
-
-                // Set the proxy values.  These can be removed once the minimum API >= 21.
-                System.setProperty("proxyHost", proxyHost);
-                System.setProperty("proxyPort", proxyPort);
-
-                // Add the proxy to the builder.
-                proxyConfigBuilder.addProxyRule("http://localhost:4444");
-                break;
-
-            case CUSTOM:
-                // Get a handle for the shared preferences.
-                SharedPreferences sharedPreferences = PreferenceManager.getDefaultSharedPreferences(context);
-
-                // Get the custom proxy URL string.
-                String customProxyUrlString = sharedPreferences.getString("proxy_custom_url", context.getString(R.string.proxy_custom_url_default_value));
-
-                // Parse the custom proxy URL.
-                try {
-                    // Convert the custom proxy URL string to a URI.
-                    Uri customProxyUri = Uri.parse(customProxyUrlString);
-
-                    // Get the proxy host and port strings from the shared preferences.  These can be removed once the minimum API >= 21.
-                    proxyHost = customProxyUri.getHost();
-                    proxyPort = String.valueOf(customProxyUri.getPort());
-
-                    // Set the proxy values.  These can be removed once the minimum API >= 21.
-                    System.setProperty("proxyHost", proxyHost);
-                    System.setProperty("proxyPort", proxyPort);
-
-                    // Add the proxy to the builder.
-                    proxyConfigBuilder.addProxyRule(customProxyUrlString);
-                } catch (Exception exception){  // The custom proxy URL is invalid.
-                    // Display a Snackbar.
-                    Snackbar.make(activityView, R.string.custom_proxy_invalid, Snackbar.LENGTH_LONG).show();
-                }
-                break;
-        }
-
-        // Apply the proxy settings
-        if (WebViewFeature.isFeatureSupported(WebViewFeature.PROXY_OVERRIDE)) {  // The fancy new proxy config can be used because the API >= 21.
-            // Convert the proxy config builder into a proxy config.
-            ProxyConfig proxyConfig = proxyConfigBuilder.build();
-
-            // Get the proxy controller.
-            ProxyController proxyController = ProxyController.getInstance();
-
-            // Applying a proxy requires an executor.
-            Executor executor = runnable -> {
-                // Do nothing.
-            };
-
-            // Applying a proxy requires a runnable.
-            Runnable runnable = () -> {
-                // Do nothing.
-            };
-
-            // Apply the proxy settings.
-            if (proxyMode.equals(NONE)) {  // Remove the proxy.
-                proxyController.clearProxyOverride(executor, runnable);
-            } else {  // Apply the proxy.
-                try {
-                    // Apply the proxy.
-                    proxyController.setProxyOverride(proxyConfig, executor, runnable);
-                } catch (IllegalArgumentException exception) {  // The proxy config is invalid.
-                    // Display a Snackbar.
-                    Snackbar.make(activityView, R.string.custom_proxy_invalid, Snackbar.LENGTH_LONG).show();
-                }
-            }
-        } else {  // The old proxy method must be used, either because an old WebView is installed or because the API == 19;
-            // Get a handle for the shared preferences.
-            SharedPreferences sharedPreferences = PreferenceManager.getDefaultSharedPreferences(context);
-
-            // Check to make sure a SOCKS proxy is not selected.
-            if (proxyMode.equals(CUSTOM) && sharedPreferences.getString("proxy_custom_url", context.getString(R.string.proxy_custom_url_default_value)).startsWith("socks://")) {
-                // Display a Snackbar.
-                Snackbar.make(activityView, R.string.socks_proxies_do_not_work_on_kitkat, Snackbar.LENGTH_LONG).show();
-            } else {  // Use reflection to apply the new proxy values.
-                try {
-                    // Get the application and APK classes.  Suppress the lint warning that reflection may not always work in the future and on all devices.
-                    Class applicationClass = Class.forName("android.app.Application");
-                    @SuppressLint("PrivateApi") Class loadedApkClass = Class.forName("android.app.LoadedApk");
-
-                    // Get the declared fields.  Suppress the lint warning that `mLoadedApk` cannot be resolved.
-                    @SuppressWarnings("JavaReflectionMemberAccess") Field methodLoadedApkField = applicationClass.getDeclaredField("mLoadedApk");
-                    Field methodReceiversField = loadedApkClass.getDeclaredField("mReceivers");
-
-                    // Allow the values to be changed.
-                    methodLoadedApkField.setAccessible(true);
-                    methodReceiversField.setAccessible(true);
-
-                    // Get the APK object.
-                    Object methodLoadedApkObject = methodLoadedApkField.get(context);
-
-                    // Get an array map of the receivers.
-                    ArrayMap receivers = (ArrayMap) methodReceiversField.get(methodLoadedApkObject);
-
-                    // Set the proxy if the receivers has at least one entry.
-                    if (receivers != null) {
-                        for (Object receiverMap : receivers.values()) {
-                            for (Object receiver : ((ArrayMap) receiverMap).keySet()) {
-                                // Get the receiver class.
-                                // `Class<?>`, which is an `unbounded wildcard parameterized type`, must be used instead of `Class`, which is a `raw type`.  Otherwise, `receiveClass.getDeclaredMethod()` is unhappy.
-                                Class<?> receiverClass = receiver.getClass();
-
-                                // Apply the new proxy settings to any classes whose names contain `ProxyChangeListener`.
-                                if (receiverClass.getName().contains("ProxyChangeListener")) {
-                                    // Get the `onReceive` method from the class.
-                                    Method onReceiveMethod = receiverClass.getDeclaredMethod("onReceive", Context.class, Intent.class);
-
-                                    // Create a proxy change intent.
-                                    Intent proxyChangeIntent = new Intent(android.net.Proxy.PROXY_CHANGE_ACTION);
-
-                                    if (Build.VERSION.SDK_INT >= 21) {
-                                        // Get a proxy info class.
-                                        // `Class<?>`, which is an `unbounded wildcard parameterized type`, must be used instead of `Class`, which is a `raw type`.  Otherwise, `proxyInfoClass.getMethod()` is unhappy.
-                                        Class<?> proxyInfoClass = Class.forName("android.net.ProxyInfo");
-
-                                        // Get the build direct proxy method from the proxy info class.
-                                        Method buildDirectProxyMethod = proxyInfoClass.getMethod("buildDirectProxy", String.class, Integer.TYPE);
-
-                                        // Populate a proxy info object with the new proxy information.
-                                        Object proxyInfoObject = buildDirectProxyMethod.invoke(proxyInfoClass, proxyHost, Integer.valueOf(proxyPort));
-
-                                        // Add the proxy info object into the proxy change intent.
-                                        proxyChangeIntent.putExtra("proxy", (Parcelable) proxyInfoObject);
-                                    }
-
-                                    // Pass the proxy change intent to the `onReceive` method of the receiver class.
-                                    onReceiveMethod.invoke(receiver, context, proxyChangeIntent);
-                                }
-                            }
-                        }
-                    }
-                } catch (ClassNotFoundException | NoSuchFieldException | IllegalAccessException | NoSuchMethodException | InvocationTargetException exception) {
-                    // Do nothing.
-                }
-            }
-        }
-    }
-
-    public Proxy getCurrentProxy(Context context) {
-        // Define a proxy variable.
-        Proxy proxy;
-
-        // Get the proxy according to the current proxy mode.
-        switch (MainWebViewActivity.proxyMode) {
-            case (ProxyHelper.TOR):
-                if (Build.VERSION.SDK_INT >= 21) {
-                    // Use localhost port 9050 as the socket address.
-                    SocketAddress torSocketAddress = InetSocketAddress.createUnresolved("localhost", 9050);
-
-                    // Create a SOCKS proxy.
-                    proxy = new Proxy(Proxy.Type.SOCKS, torSocketAddress);
-                } else {
-                    // Use localhost port 8118 as the socket address.
-                    SocketAddress oldTorSocketAddress = InetSocketAddress.createUnresolved("localhost", 8118);
-
-                    // Create an HTTP proxy.
-                    proxy = new Proxy(Proxy.Type.HTTP, oldTorSocketAddress);
-                }
-                break;
-
-            case (ProxyHelper.I2P):
-                // Use localhost port 4444 as the socket address.
-                SocketAddress i2pSocketAddress = InetSocketAddress.createUnresolved("localhost", 4444);
-
-                // Create an HTTP proxy.
-                proxy = new Proxy(Proxy.Type.HTTP, i2pSocketAddress);
-                break;
-
-            case (ProxyHelper.CUSTOM):
-                // Get the shared preferences.
-                SharedPreferences sharedPreferences = PreferenceManager.getDefaultSharedPreferences(context);
-
-                // Get the custom proxy URL string.
-                String customProxyUrlString = sharedPreferences.getString("proxy_custom_url", context.getString(R.string.proxy_custom_url_default_value));
-
-                // Parse the custom proxy URL.
-                try {
-                    // Convert the custom proxy URL string to a URI.
-                    Uri customProxyUri = Uri.parse(customProxyUrlString);
-
-                    // Get the custom socket address.
-                    SocketAddress customSocketAddress = InetSocketAddress.createUnresolved(customProxyUri.getHost(), customProxyUri.getPort());
-
-                    // Get the custom proxy scheme.
-                    String customProxyScheme = customProxyUri.getScheme();
-
-                    // Create a proxy according to the scheme.
-                    if ((customProxyScheme != null) && customProxyScheme.startsWith("socks")) {  // A SOCKS proxy is specified.
-                        // Create a SOCKS proxy.
-                        proxy = new Proxy(Proxy.Type.SOCKS, customSocketAddress);
-                    } else {  // A SOCKS proxy is not specified.
-                        // Create an HTTP proxy.
-                        proxy = new Proxy(Proxy.Type.HTTP, customSocketAddress);
-                    }
-                } catch (Exception exception) {  // The custom proxy cannot be parsed.
-                    // Disable the proxy.
-                    proxy = Proxy.NO_PROXY;
-                }
-                break;
-
-            default:  // No proxy is in use.
-                // Create a direct proxy.
-                proxy = Proxy.NO_PROXY;
-                break;
-        }
-
-        // Return the proxy.
-        return proxy;
-    }
-}
\ No newline at end of file
diff --git a/app/src/main/java/com/stoutner/privacybrowser/helpers/ProxyHelper.kt b/app/src/main/java/com/stoutner/privacybrowser/helpers/ProxyHelper.kt
new file mode 100644 (file)
index 0000000..0cc5105
--- /dev/null
@@ -0,0 +1,311 @@
+/*
+ * Copyright © 2016-2021 Soren Stoutner <soren@stoutner.com>.
+ *
+ * This file is part of Privacy Browser <https://www.stoutner.com/privacy-browser>.
+ *
+ * Privacy Browser is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Privacy Browser is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Privacy Browser.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+package com.stoutner.privacybrowser.helpers
+
+import android.annotation.SuppressLint
+import android.content.Context
+import android.content.Intent
+import android.net.Uri
+import android.os.Build
+import android.os.Parcelable
+import android.util.ArrayMap
+import android.view.View
+
+import androidx.preference.PreferenceManager
+import androidx.webkit.ProxyConfig
+import androidx.webkit.ProxyController
+import androidx.webkit.WebViewFeature
+
+import com.stoutner.privacybrowser.R
+import com.stoutner.privacybrowser.activities.MainWebViewActivity
+
+import com.google.android.material.snackbar.Snackbar
+
+import java.lang.Exception
+import java.lang.IllegalArgumentException
+import java.lang.reflect.InvocationTargetException
+import java.net.InetSocketAddress
+import java.net.Proxy
+import java.net.SocketAddress
+
+class ProxyHelper {
+    companion object {
+        // Define the public companion object constants.  These can be moved to public class constants once the entire project has migrated to Kotlin.
+        const val NONE = "None"
+        const val TOR = "Tor"
+        const val I2P = "I2P"
+        const val CUSTOM = "Custom"
+        const val ORBOT_STATUS_ON = "ON"
+    }
+
+    fun setProxy(context: Context, activityView: View, proxyMode: String) {
+        // Initialize the proxy host and port strings.
+        var proxyHost = "0"
+        var proxyPort = "0"
+
+        // Create a proxy config builder.
+        val proxyConfigBuilder = ProxyConfig.Builder()
+
+        // Run the commands that correlate to the proxy mode.
+        when (proxyMode) {
+            NONE -> {
+                // Clear the proxy values.
+                System.clearProperty("proxyHost")
+                System.clearProperty("proxyPort")
+            }
+
+            TOR -> {
+                // Update the proxy host and port strings.  These can be removed once the minimum API >= 21.
+                proxyHost = "localhost"
+                proxyPort = "8118"
+
+                // Set the proxy values.  These can be removed once the minimum API >= 21.
+                System.setProperty("proxyHost", proxyHost)
+                System.setProperty("proxyPort", proxyPort)
+
+                // Add the proxy to the builder.  The proxy config builder can use a SOCKS proxy.
+                proxyConfigBuilder.addProxyRule("socks://localhost:9050")
+
+                // Ask Orbot to connect if its current status is not `"ON"`.
+                if (MainWebViewActivity.orbotStatus != ORBOT_STATUS_ON) {
+                    // Create an intent to request Orbot to start.
+                    val orbotIntent = Intent("org.torproject.android.intent.action.START")
+
+                    // Send the intent to the Orbot package.
+                    orbotIntent.setPackage("org.torproject.android")
+
+                    // Request a status response be sent back to this package.
+                    orbotIntent.putExtra("org.torproject.android.intent.extra.PACKAGE_NAME", context.packageName)
+
+                    // Make it so.
+                    context.sendBroadcast(orbotIntent)
+                }
+            }
+
+            I2P -> {
+                // Update the proxy host and port strings.  These can be removed once the minimum API >= 21.
+                proxyHost = "localhost"
+                proxyPort = "4444"
+
+                // Set the proxy values.  These can be removed once the minimum API >= 21.
+                System.setProperty("proxyHost", proxyHost)
+                System.setProperty("proxyPort", proxyPort)
+
+                // Add the proxy to the builder.
+                proxyConfigBuilder.addProxyRule("http://localhost:4444")
+            }
+
+            CUSTOM -> {
+                // Get a handle for the shared preferences.
+                val sharedPreferences = PreferenceManager.getDefaultSharedPreferences(context)
+
+                // Get the custom proxy URL string.
+                val customProxyUrlString = sharedPreferences.getString(context.getString(R.string.proxy_custom_url_key), context.getString(R.string.proxy_custom_url_default_value))
+
+                // Parse the custom proxy URL.
+                try {
+                    // Convert the custom proxy URL string to a URI.
+                    val customProxyUri = Uri.parse(customProxyUrlString)
+
+                    // Get the proxy host and port strings from the shared preferences.  These can be removed once the minimum API >= 21.
+                    proxyHost = customProxyUri.host!!
+                    proxyPort = customProxyUri.port.toString()
+
+                    // Set the proxy values.  These can be removed once the minimum API >= 21.
+                    System.setProperty("proxyHost", proxyHost)
+                    System.setProperty("proxyPort", proxyPort)
+
+                    // Add the proxy to the builder.
+                    proxyConfigBuilder.addProxyRule(customProxyUrlString!!)
+                } catch (exception: Exception) {  // The custom proxy URL is invalid.
+                    // Display a Snackbar.
+                    Snackbar.make(activityView, R.string.custom_proxy_invalid, Snackbar.LENGTH_LONG).show()
+                }
+            }
+        }
+
+        // Apply the proxy settings
+        if (WebViewFeature.isFeatureSupported(WebViewFeature.PROXY_OVERRIDE)) {  // The fancy new proxy config can be used because the API >= 21.
+            // Convert the proxy config builder into a proxy config.
+            val proxyConfig = proxyConfigBuilder.build()
+
+            // Get the proxy controller.
+            val proxyController = ProxyController.getInstance()
+
+            // Apply the proxy settings.
+            if (proxyMode == NONE) {  // Remove the proxy.  A default executor and runnable are used.
+                proxyController.clearProxyOverride({}, {})
+            } else {  // Apply the proxy.
+                try {
+                    // Apply the proxy.  A default executor and runnable are used.
+                    proxyController.setProxyOverride(proxyConfig, {}, {})
+                } catch (exception: IllegalArgumentException) {  // The proxy config is invalid.
+                    // Display a Snackbar.
+                    Snackbar.make(activityView, R.string.custom_proxy_invalid, Snackbar.LENGTH_LONG).show()
+                }
+            }
+        } else {  // The old proxy method must be used, either because an old WebView is installed or because the API == 19;
+            // Get a handle for the shared preferences.
+            val sharedPreferences = PreferenceManager.getDefaultSharedPreferences(context)
+
+            // Check to make sure a SOCKS proxy is not selected.
+            if ((proxyMode == CUSTOM) &&
+                sharedPreferences.getString(context.getString(R.string.proxy_custom_url_key), context.getString(R.string.proxy_custom_url_default_value))!!.startsWith("socks://")) {
+                // Display a Snackbar.
+                Snackbar.make(activityView, R.string.socks_proxies_do_not_work_on_kitkat, Snackbar.LENGTH_LONG).show()
+            } else {  // Use reflection to apply the new proxy values.
+                try {
+                    // Get the application and APK classes.
+                    val applicationClass = Class.forName("android.app.Application")
+
+                    // Suppress the lint warning that reflection may not always work in the future and on all devices.
+                    @SuppressLint("PrivateApi") val loadedApkClass = Class.forName("android.app.LoadedApk")
+
+                    // Get the declared fields.  Suppress the lint that it is discouraged to access private APIs.
+                    @SuppressLint("DiscouragedPrivateApi") val methodLoadedApkField = applicationClass.getDeclaredField("mLoadedApk")
+                    @SuppressLint("DiscouragedPrivateApi") val methodReceiversField = loadedApkClass.getDeclaredField("mReceivers")
+
+                    // Allow the values to be changed.
+                    methodLoadedApkField.isAccessible = true
+                    methodReceiversField.isAccessible = true
+
+                    // Get the APK object.
+                    val methodLoadedApkObject = methodLoadedApkField[context]
+
+                    // Get an array map of the receivers.
+                    val receivers = methodReceiversField[methodLoadedApkObject] as ArrayMap<*, *>
+
+                    // Set the proxy.
+                    for (receiverMap in receivers.values) {
+                        for (receiver in (receiverMap as ArrayMap<*, *>).keys) {
+                            // Get the receiver class.
+                            // `Class<*>`, which is an `unbounded wildcard parameterized type`, must be used instead of `Class`, which is a `raw type`.  Otherwise, `receiveClass.getDeclaredMethod()` is unhappy.
+                            val receiverClass: Class<*> = receiver.javaClass
+
+                            // Apply the new proxy settings to any classes whose names contain `ProxyChangeListener`.
+                            if (receiverClass.name.contains("ProxyChangeListener")) {
+                                // Get the `onReceive` method from the class.
+                                val onReceiveMethod = receiverClass.getDeclaredMethod("onReceive", Context::class.java, Intent::class.java)
+
+                                // Create a proxy change intent.
+                                val proxyChangeIntent = Intent(android.net.Proxy.PROXY_CHANGE_ACTION)
+
+                                // Set the proxy for API >= 21.
+                                if (Build.VERSION.SDK_INT >= 21) {
+                                    // Get the proxy info class.
+                                    val proxyInfoClass = Class.forName("android.net.ProxyInfo")
+
+                                    // Get the build direct proxy method from the proxy info class.
+                                    val buildDirectProxyMethod = proxyInfoClass.getMethod("buildDirectProxy", String::class.java, Integer.TYPE)
+
+                                    // Populate a proxy info object with the new proxy information.
+                                    val proxyInfoObject = buildDirectProxyMethod.invoke(proxyInfoClass, proxyHost, Integer.valueOf(proxyPort))
+
+                                    // Add the proxy info object into the proxy change intent.
+                                    proxyChangeIntent.putExtra("proxy", proxyInfoObject as Parcelable)
+                                }
+
+                                // Pass the proxy change intent to the `onReceive` method of the receiver class.
+                                onReceiveMethod.invoke(receiver, context, proxyChangeIntent)
+                            }
+                        }
+                    }
+                } catch (exception: ClassNotFoundException) {
+                    // Do nothing.
+                } catch (exception: NoSuchFieldException) {
+                    // Do nothing.
+                } catch (exception: IllegalAccessException) {
+                    // Do nothing.
+                } catch (exception: NoSuchMethodException) {
+                    // Do nothing.
+                } catch (exception: InvocationTargetException) {
+                    // Do nothing.
+                }
+            }
+        }
+    }
+
+    fun getCurrentProxy(context: Context): Proxy {
+        // Get the proxy according to the current proxy mode.
+        val proxy = when (MainWebViewActivity.proxyMode) {
+            TOR -> if (Build.VERSION.SDK_INT >= 21) {
+                // Use localhost port 9050 as the socket address.
+                val torSocketAddress: SocketAddress = InetSocketAddress.createUnresolved("localhost", 9050)
+
+                // Create a SOCKS proxy.
+                Proxy(Proxy.Type.SOCKS, torSocketAddress)
+            } else {
+                // Use localhost port 8118 as the socket address.
+                val oldTorSocketAddress: SocketAddress = InetSocketAddress.createUnresolved("localhost", 8118)
+
+                // Create an HTTP proxy.
+                Proxy(Proxy.Type.HTTP, oldTorSocketAddress)
+            }
+
+            I2P -> {
+                // Use localhost port 4444 as the socket address.
+                val i2pSocketAddress: SocketAddress = InetSocketAddress.createUnresolved("localhost", 4444)
+
+                // Create an HTTP proxy.
+                Proxy(Proxy.Type.HTTP, i2pSocketAddress)
+            }
+
+            CUSTOM -> {
+                // Get the shared preferences.
+                val sharedPreferences = PreferenceManager.getDefaultSharedPreferences(context)
+
+                // Get the custom proxy URL string.
+                val customProxyUrlString = sharedPreferences.getString(context.getString(R.string.proxy_custom_url_key), context.getString(R.string.proxy_custom_url_default_value))
+
+                // Parse the custom proxy URL.
+                try {
+                    // Convert the custom proxy URL string to a URI.
+                    val customProxyUri = Uri.parse(customProxyUrlString)
+
+                    // Get the custom socket address.
+                    val customSocketAddress: SocketAddress = InetSocketAddress.createUnresolved(customProxyUri.host, customProxyUri.port)
+
+                    // Get the custom proxy scheme.
+                    val customProxyScheme = customProxyUri.scheme
+
+                    // Create a proxy according to the scheme.
+                    if (customProxyScheme != null && customProxyScheme.startsWith("socks")) {  // A SOCKS proxy is specified.
+                        // Create a SOCKS proxy.
+                        Proxy(Proxy.Type.SOCKS, customSocketAddress)
+                    } else {  // A SOCKS proxy is not specified.
+                        // Create an HTTP proxy.
+                        Proxy(Proxy.Type.HTTP, customSocketAddress)
+                    }
+                } catch (exception: Exception) {  // The custom proxy cannot be parsed.
+                    // Disable the proxy.
+                    Proxy.NO_PROXY
+                }
+            }
+
+            else -> {
+                // Create a direct proxy.
+                Proxy.NO_PROXY
+            }
+        }
+
+        // Return the proxy.
+        return proxy
+    }
+}
\ No newline at end of file
index cd00f067cd6a68273afc113eeac2234d9033042d..01e960489ebb67ff63c768c47155d97f2f7f9936 100644 (file)
@@ -19,6 +19,7 @@
 
 package com.stoutner.privacybrowser.views
 
+import android.animation.ObjectAnimator
 import android.annotation.SuppressLint
 import android.content.Context
 import android.graphics.Bitmap
@@ -36,6 +37,7 @@ import androidx.core.view.NestedScrollingChildHelper
 import androidx.core.view.ViewCompat
 
 import com.stoutner.privacybrowser.R
+import com.stoutner.privacybrowser.activities.MainWebViewActivity
 
 import java.util.Collections
 import java.util.Date
@@ -78,9 +80,8 @@ private const val FONT_SIZE = "font_size"
 // NestedScrollWebView extends WebView to handle nested scrolls (scrolling the app bar off the screen).  It also stores extra information about the state of the WebView used by Privacy Browser.
 class NestedScrollWebView @JvmOverloads constructor(context: Context, attributeSet: AttributeSet? = null, defaultStyle: Int = android.R.attr.webViewStyle) : WebView(context, attributeSet, defaultStyle),
     NestedScrollingChild2 {
-
     companion object {
-        // Define the public companion object blocklists constants.
+        // Define the public companion object constants.  These can be moved to public class constants once the entire project has migrated to Kotlin.
         const val BLOCKED_REQUESTS = 0
         const val EASYLIST = 1
         const val EASYPRIVACY = 2
@@ -312,6 +313,19 @@ class NestedScrollWebView @JvmOverloads constructor(context: Context, attributeS
         return computeVerticalScrollRange()
     }
 
+    override fun onOverScrolled(scrollX: Int, scrollY: Int, clampedX: Boolean, clampedY: Boolean) {
+        // Run the default commands.
+        super.onOverScrolled(scrollX, scrollY, clampedX, clampedY)
+
+        // Display the bottom app bar if it has been hidden and the WebView was over-scrolled at the top of the screen.
+        if ((MainWebViewActivity.appBarLayout.translationY != 0f) && (scrollY == 0) && clampedY) {
+            // Animate the bottom app bar onto the screen.
+            val objectAnimator = ObjectAnimator.ofFloat(MainWebViewActivity.appBarLayout, "translationY", 0f)
+
+            // Make it so.
+            objectAnimator.start()
+        }
+    }
 
     // Handle touches.
     @SuppressLint("ClickableViewAccessibility")
index e78bcc306c7887c72bded25c077f8ea610e36114..521c03f8b78ef11f2f29f5d9ebfad07b47735046 100644 (file)
             android:id="@+id/coordinatorlayout"
             android:layout_height="match_parent"
             android:layout_width="match_parent"
-            android:layout_below="@id/adview"
             android:focusable="true"
             android:focusableInTouchMode="true" >
 
-                <!-- `app:layout_dodgeInsetEdges="bottom"` as a child of a coordinator layout moves the view above snackbars. -->
-                <RelativeLayout
-                    android:layout_height="match_parent"
+                <androidx.swiperefreshlayout.widget.SwipeRefreshLayout
+                    android:id="@+id/swiperefreshlayout"
                     android:layout_width="match_parent"
-                    app:layout_dodgeInsetEdges="bottom" >
+                    android:layout_height="match_parent" >
 
-                    <androidx.swiperefreshlayout.widget.SwipeRefreshLayout
-                        android:id="@+id/swiperefreshlayout"
-                        android:layout_width="match_parent"
+                    <com.stoutner.privacybrowser.views.NoSwipeViewPager
+                        android:id="@+id/webviewpager"
                         android:layout_height="match_parent"
-                        android:layout_above="@id/appbar_layout" >
+                        android:layout_width="match_parent" />
+                </androidx.swiperefreshlayout.widget.SwipeRefreshLayout>
+
+                <!-- The app bar theme must be specified here because the activity uses a `NoActionBar` theme.  The background is set programmatically based on the proxy status.
+                    `app:layout_dodgeInsetEdges="bottom"` as a child of a coordinator layout moves the view above snackbars.-->
+                <com.google.android.material.appbar.AppBarLayout
+                    android:id="@+id/appbar_layout"
+                    android:layout_height="wrap_content"
+                    android:layout_width="match_parent"
+                    android:theme="@style/PrivacyBrowserAppBar"
+                    android:layout_gravity="bottom"
+                    app:layout_dodgeInsetEdges="bottom" >
 
-                        <com.stoutner.privacybrowser.views.NoSwipeViewPager
-                            android:id="@+id/webviewpager"
+                    <!-- The tab linear layout.  It sets the background to the right of the add tab button.
+                        It is initially `visibility="gone"` so it doesn't display while the blocklists are loading. -->
+                    <LinearLayout
+                        android:id="@+id/tabs_linearlayout"
+                        android:layout_height="wrap_content"
+                        android:layout_width="wrap_content"
+                        android:orientation="horizontal"
+                        android:visibility="gone" >
+
+                        <!-- `android:background="?attr/selectableItemBackground"` adds a ripple animation on touch. -->
+                        <ImageView
                             android:layout_height="match_parent"
-                            android:layout_width="match_parent" />
-                    </androidx.swiperefreshlayout.widget.SwipeRefreshLayout>
+                            android:layout_width="wrap_content"
+                            android:layout_gravity="center_vertical"
+                            android:paddingStart="10dp"
+                            android:paddingEnd="10dp"
+                            android:src="@drawable/close_day"
+                            android:background="?attr/selectableItemBackground"
+                            android:onClick="closeTab"
+                            android:contentDescription="@string/close_tab"
+                            app:tint="?attr/addTabIconTintColor" />
+
+                        <com.google.android.material.tabs.TabLayout
+                            android:id="@+id/tablayout"
+                            android:layout_height="wrap_content"
+                            android:layout_width="0dp"
+                            android:layout_weight="1"
+                            app:tabMode="scrollable" />
 
-                    <!-- The app bar theme must be specified here because the activity uses a `NoActionBar` theme.  The background is set programmatically based on the proxy status. -->
-                    <com.google.android.material.appbar.AppBarLayout
-                        android:id="@+id/appbar_layout"
+                        <!-- `android:background="?attr/selectableItemBackground"` adds a ripple animation on touch. -->
+                        <ImageView
+                            android:layout_height="match_parent"
+                            android:layout_width="wrap_content"
+                            android:layout_gravity="center_vertical"
+                            android:paddingStart="10dp"
+                            android:paddingEnd="10dp"
+                            android:src="@drawable/add"
+                            android:background="?attr/selectableItemBackground"
+                            android:onClick="addTab"
+                            android:contentDescription="@string/add_tab"
+                            app:tint="?attr/addTabIconTintColor" />
+                    </LinearLayout>
+
+                    <!-- The find on page linear layout.  It is initially `visibility="gone"` so it doesn't display while the blocklists are loading. -->
+                    <LinearLayout
+                        android:id="@+id/find_on_page_linearlayout"
                         android:layout_height="wrap_content"
                         android:layout_width="match_parent"
-                        android:theme="@style/PrivacyBrowserAppBar"
-                        android:layout_alignParentBottom="true" >
+                        android:orientation="horizontal"
+                        android:visibility="gone" >
 
-                        <!-- The tab linear layout.  It sets the background to the right of the add tab button.
-                            It is initially `visibility="gone"` so it doesn't display while the blocklists are loading. -->
-                        <LinearLayout
-                            android:id="@+id/tabs_linearlayout"
-                            android:layout_height="wrap_content"
-                            android:layout_width="wrap_content"
-                            android:orientation="horizontal"
-                            android:visibility="gone" >
-
-                            <!-- `android:background="?attr/selectableItemBackground"` adds a ripple animation on touch. -->
-                            <ImageView
-                                android:layout_height="match_parent"
-                                android:layout_width="wrap_content"
-                                android:layout_gravity="center_vertical"
-                                android:paddingStart="10dp"
-                                android:paddingEnd="10dp"
-                                android:src="@drawable/close_day"
-                                android:background="?attr/selectableItemBackground"
-                                android:onClick="closeTab"
-                                android:contentDescription="@string/close_tab"
-                                app:tint="?attr/addTabIconTintColor" />
-
-                            <com.google.android.material.tabs.TabLayout
-                                android:id="@+id/tablayout"
-                                android:layout_height="wrap_content"
-                                android:layout_width="0dp"
-                                android:layout_weight="1"
-                                app:tabMode="scrollable" />
-
-                            <!-- `android:background="?attr/selectableItemBackground"` adds a ripple animation on touch. -->
-                            <ImageView
-                                android:layout_height="match_parent"
-                                android:layout_width="wrap_content"
-                                android:layout_gravity="center_vertical"
-                                android:paddingStart="10dp"
-                                android:paddingEnd="10dp"
-                                android:src="@drawable/add"
-                                android:background="?attr/selectableItemBackground"
-                                android:onClick="addTab"
-                                android:contentDescription="@string/add_tab"
-                                app:tint="?attr/addTabIconTintColor" />
-                        </LinearLayout>
-
-                        <!-- The find on page linear layout.  It is initially `visibility="gone"` so it doesn't display while the blocklists are loading. -->
-                        <LinearLayout
-                            android:id="@+id/find_on_page_linearlayout"
+                        <!-- `android:imeOptions="actionDone"` sets the keyboard to have a `check mark` key instead of a `new line` key. -->
+                        <EditText
+                            android:id="@+id/find_on_page_edittext"
                             android:layout_height="wrap_content"
-                            android:layout_width="match_parent"
-                            android:orientation="horizontal"
-                            android:visibility="gone" >
-
-                            <!-- `android:imeOptions="actionDone"` sets the keyboard to have a `check mark` key instead of a `new line` key. -->
-                            <EditText
-                                android:id="@+id/find_on_page_edittext"
-                                android:layout_height="wrap_content"
-                                android:layout_width="0dp"
-                                android:layout_weight="1"
-                                android:layout_marginStart="8dp"
-                                android:layout_marginEnd="4dp"
-                                android:hint="@string/find_on_page"
-                                android:lines="1"
-                                android:imeOptions="actionDone"
-                                android:inputType="text"
-                                tools:ignore="Autofill" />
-
-                            <TextView
-                                android:id="@+id/find_on_page_count_textview"
-                                android:layout_height="wrap_content"
-                                android:layout_width="wrap_content"
-                                android:layout_marginStart="4dp"
-                                android:layout_marginEnd="4dp"
-                                android:text="@string/zero_of_zero" />
-
-                            <!-- `android:background="?attr/selectableItemBackground"` adds a ripple animation on touch. -->
-                            <ImageView
-                                android:id="@+id/find_previous"
-                                android:src="@drawable/previous"
-                                android:layout_width="35dp"
-                                android:layout_height="35dp"
-                                android:layout_marginStart="4dp"
-                                android:layout_marginEnd="4dp"
-                                android:layout_gravity="center_vertical"
-                                android:background="?attr/selectableItemBackground"
-                                android:contentDescription="@string/previous"
-                                android:onClick="findPreviousOnPage"
-                                app:tint="?attr/findOnPageIconTintColor" />
-
-                            <!-- `android:background="?attr/selectableItemBackground"` adds a ripple animation on touch. -->
-                            <ImageView
-                                android:id="@+id/find_next"
-                                android:src="@drawable/next"
-                                android:layout_width="35dp"
-                                android:layout_height="35dp"
-                                android:layout_marginStart="4dp"
-                                android:layout_marginEnd="4dp"
-                                android:layout_gravity="center_vertical"
-                                android:background="?attr/selectableItemBackground"
-                                android:contentDescription="@string/next"
-                                android:onClick="findNextOnPage"
-                                app:tint="?attr/findOnPageIconTintColor" />
-
-                            <!-- `android:background="?attr/selectableItemBackground"` adds a ripple animation on touch. -->
-                            <ImageView
-                                android:id="@+id/close_find"
-                                android:src="@drawable/close_day"
-                                android:layout_width="35dp"
-                                android:layout_height="35dp"
-                                android:layout_marginStart="4dp"
-                                android:layout_marginEnd="8dp"
-                                android:layout_gravity="center_vertical"
-                                android:background="?attr/selectableItemBackground"
-                                android:contentDescription="@string/close"
-                                android:onClick="closeFindOnPage"
-                                app:tint="?attr/findOnPageIconTintColor" />
-                        </LinearLayout>
-
-                        <!-- The toolbar.  It is initially `visibility="gone"` so it doesn't display while the blocklists are loading. -->
-                        <androidx.appcompat.widget.Toolbar
-                            android:id="@+id/toolbar"
+                            android:layout_width="0dp"
+                            android:layout_weight="1"
+                            android:layout_marginStart="8dp"
+                            android:layout_marginEnd="4dp"
+                            android:hint="@string/find_on_page"
+                            android:lines="1"
+                            android:imeOptions="actionDone"
+                            android:inputType="text"
+                            tools:ignore="Autofill" />
+
+                        <TextView
+                            android:id="@+id/find_on_page_count_textview"
                             android:layout_height="wrap_content"
-                            android:layout_width="match_parent"
-                            android:visibility="gone" />
-                    </com.google.android.material.appbar.AppBarLayout>
-                </RelativeLayout>
+                            android:layout_width="wrap_content"
+                            android:layout_marginStart="4dp"
+                            android:layout_marginEnd="4dp"
+                            android:text="@string/zero_of_zero" />
+
+                        <!-- `android:background="?attr/selectableItemBackground"` adds a ripple animation on touch. -->
+                        <ImageView
+                            android:id="@+id/find_previous"
+                            android:src="@drawable/previous"
+                            android:layout_width="35dp"
+                            android:layout_height="35dp"
+                            android:layout_marginStart="4dp"
+                            android:layout_marginEnd="4dp"
+                            android:layout_gravity="center_vertical"
+                            android:background="?attr/selectableItemBackground"
+                            android:contentDescription="@string/previous"
+                            android:onClick="findPreviousOnPage"
+                            app:tint="?attr/findOnPageIconTintColor" />
+
+                        <!-- `android:background="?attr/selectableItemBackground"` adds a ripple animation on touch. -->
+                        <ImageView
+                            android:id="@+id/find_next"
+                            android:src="@drawable/next"
+                            android:layout_width="35dp"
+                            android:layout_height="35dp"
+                            android:layout_marginStart="4dp"
+                            android:layout_marginEnd="4dp"
+                            android:layout_gravity="center_vertical"
+                            android:background="?attr/selectableItemBackground"
+                            android:contentDescription="@string/next"
+                            android:onClick="findNextOnPage"
+                            app:tint="?attr/findOnPageIconTintColor" />
+
+                        <!-- `android:background="?attr/selectableItemBackground"` adds a ripple animation on touch. -->
+                        <ImageView
+                            android:id="@+id/close_find"
+                            android:src="@drawable/close_day"
+                            android:layout_width="35dp"
+                            android:layout_height="35dp"
+                            android:layout_marginStart="4dp"
+                            android:layout_marginEnd="8dp"
+                            android:layout_gravity="center_vertical"
+                            android:background="?attr/selectableItemBackground"
+                            android:contentDescription="@string/close"
+                            android:onClick="closeFindOnPage"
+                            app:tint="?attr/findOnPageIconTintColor" />
+                    </LinearLayout>
+
+                    <!-- The toolbar.  It is initially `visibility="gone"` so it doesn't display while the blocklists are loading. -->
+                    <androidx.appcompat.widget.Toolbar
+                        android:id="@+id/toolbar"
+                        android:layout_height="wrap_content"
+                        android:layout_width="match_parent"
+                        android:visibility="gone" />
+                </com.google.android.material.appbar.AppBarLayout>
         </androidx.coordinatorlayout.widget.CoordinatorLayout>
 
         <!-- The navigation drawer. -->
index 73201e53e6d10922e7bd1a89972f77d81cbfa884..3a49a5e370b1b2810a30e669dcbd54b1fde12990 100644 (file)
@@ -36,7 +36,6 @@
             android:id="@+id/coordinatorlayout"
             android:layout_height="match_parent"
             android:layout_width="match_parent"
-            android:layout_above="@id/adview"
             android:focusable="true"
             android:focusableInTouchMode="true" >
 
index 5bf453a7f89cb1e8fee130f42b8dd054bbc247da..40ce96db2f7b492eb823935ae18065a5924b221d 100644 (file)
     <string name="clear_logcat_key" translatable="false">clear_logcat</string>
     <string name="download_with_external_app_key" translatable="false">download_with_external_app</string>
     <string name="display_additional_app_bar_icons_key" translatable="false">display_additional_app_bar_icons</string>
+    <string name="proxy_custom_url_key" translatable="false">proxy_custom_url</string>
+    <string name="scroll_app_bar_key" translatable="false">scroll_app_bar</string>
 
     <!-- Non-translatable preference default values. -->
     <string name="app_theme_default_value" translatable="false">System default</string>
index 2e3d98b18f84f2442e36a5c42c9411d4da0aa0b8..319c598f0752b4d4927201db785c57ca4c2017b5 100644 (file)
@@ -26,8 +26,8 @@ buildscript {
     }
 
     dependencies {
-        classpath 'com.android.tools.build:gradle:7.0.3'
-        classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:1.6.0"
+        classpath 'com.android.tools.build:gradle:7.0.4'
+        classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:1.6.10"
 
         // NOTE: Do not place your application dependencies here; they belong
         // in the individual module build.gradle files
index e8c3c3e3a75b10ba2b0e32f34aed6e58ac2a6d9b..8da20ff7ab91070ae7197d4eda0ef963f16b544d 100644 (file)
@@ -1,5 +1,6 @@
-• Simplify the save dialogs.
-• Display the saved file name in the save snackbars.
-• Change the short app name from Privacy to Browser.
-• Fix a crash if a drawer is opened while the app is restarted.
-• Bump the target API to 31 (Android 12).
\ No newline at end of file
+• "Speichern"-Dialog vereinfacht.
+• Anzeige des Dateinamens in der Informationsleiste beim Speichern von Dateien implementiert.
+• Kurz-Name der App von Privatsphäre in Browser geändert.
+• Fehler beseitig, wenn die App-Leiste beim Neustart der Anwendung geöffnet war.
+• Ziel-API auf 31 (Android 12) angehoben.
+• Aktualisierte deutsche Übersetzung von Bernhard G. Keller.
\ No newline at end of file