From: Soren Stoutner Date: Fri, 31 Dec 2021 22:08:17 +0000 (-0700) Subject: Fix scrolling of the bottom app bar. https://redmine.stoutner.com/issues/791 X-Git-Tag: v3.10~9 X-Git-Url: https://gitweb.stoutner.com/?p=PrivacyBrowserAndroid.git;a=commitdiff_plain;h=484f0b0f0143c53a4722cee3a31e714df0c8c49a Fix scrolling of the bottom app bar. https://redmine.stoutner.com/issues/791 --- diff --git a/app/build.gradle b/app/build.gradle index e314f99d..571e6528 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -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' diff --git a/app/src/main/assets/de/about_changelog.html b/app/src/main/assets/de/about_changelog.html index f7673d2d..4214c4d7 100644 --- a/app/src/main/assets/de/about_changelog.html +++ b/app/src/main/assets/de/about_changelog.html @@ -36,11 +36,11 @@

3.9 (version code 57)

27. November 2021 - Mindest-API 19, Ziel-API 31

diff --git a/app/src/main/java/com/stoutner/privacybrowser/activities/BookmarksActivity.java b/app/src/main/java/com/stoutner/privacybrowser/activities/BookmarksActivity.java index 9e33c0d2..20dd5965 100644 --- a/app/src/main/java/com/stoutner/privacybrowser/activities/BookmarksActivity.java +++ b/app/src/main/java/com/stoutner/privacybrowser/activities/BookmarksActivity.java @@ -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); diff --git a/app/src/main/java/com/stoutner/privacybrowser/activities/BookmarksDatabaseViewActivity.java b/app/src/main/java/com/stoutner/privacybrowser/activities/BookmarksDatabaseViewActivity.java index 13fedf04..483b769f 100644 --- a/app/src/main/java/com/stoutner/privacybrowser/activities/BookmarksDatabaseViewActivity.java +++ b/app/src/main/java/com/stoutner/privacybrowser/activities/BookmarksDatabaseViewActivity.java @@ -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(); diff --git a/app/src/main/java/com/stoutner/privacybrowser/activities/DomainsActivity.java b/app/src/main/java/com/stoutner/privacybrowser/activities/DomainsActivity.java index c8e8e07c..f4a1e79b 100644 --- a/app/src/main/java/com/stoutner/privacybrowser/activities/DomainsActivity.java +++ b/app/src/main/java/com/stoutner/privacybrowser/activities/DomainsActivity.java @@ -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(); diff --git a/app/src/main/java/com/stoutner/privacybrowser/activities/LogcatActivity.kt b/app/src/main/java/com/stoutner/privacybrowser/activities/LogcatActivity.kt index 71623cd7..9c6e5de1 100644 --- a/app/src/main/java/com/stoutner/privacybrowser/activities/LogcatActivity.kt +++ b/app/src/main/java/com/stoutner/privacybrowser/activities/LogcatActivity.kt @@ -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() diff --git a/app/src/main/java/com/stoutner/privacybrowser/activities/MainWebViewActivity.java b/app/src/main/java/com/stoutner/privacybrowser/activities/MainWebViewActivity.java index 00a64e20..d4463643 100644 --- a/app/src/main/java/com/stoutner/privacybrowser/activities/MainWebViewActivity.java +++ b/app/src/main/java/com/stoutner/privacybrowser/activities/MainWebViewActivity.java @@ -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 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 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. diff --git a/app/src/main/java/com/stoutner/privacybrowser/activities/ViewSourceActivity.kt b/app/src/main/java/com/stoutner/privacybrowser/activities/ViewSourceActivity.kt index 759b79c0..ad2c0982 100644 --- a/app/src/main/java/com/stoutner/privacybrowser/activities/ViewSourceActivity.kt +++ b/app/src/main/java/com/stoutner/privacybrowser/activities/ViewSourceActivity.kt @@ -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" diff --git a/app/src/main/java/com/stoutner/privacybrowser/asynctasks/SaveAboutVersionImage.java b/app/src/main/java/com/stoutner/privacybrowser/asynctasks/SaveAboutVersionImage.java index 1fef50dc..c65c0eb4 100644 --- a/app/src/main/java/com/stoutner/privacybrowser/asynctasks/SaveAboutVersionImage.java +++ b/app/src/main/java/com/stoutner/privacybrowser/asynctasks/SaveAboutVersionImage.java @@ -69,7 +69,7 @@ public class SaveAboutVersionImage extends AsyncTask { 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(); diff --git a/app/src/main/java/com/stoutner/privacybrowser/asynctasks/SaveUrl.java b/app/src/main/java/com/stoutner/privacybrowser/asynctasks/SaveUrl.java index 6a4671bc..aaa4ce2b 100644 --- a/app/src/main/java/com/stoutner/privacybrowser/asynctasks/SaveUrl.java +++ b/app/src/main/java/com/stoutner/privacybrowser/asynctasks/SaveUrl.java @@ -80,7 +80,7 @@ public class SaveUrl extends AsyncTask { 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(); diff --git a/app/src/main/java/com/stoutner/privacybrowser/asynctasks/SaveWebpageImage.java b/app/src/main/java/com/stoutner/privacybrowser/asynctasks/SaveWebpageImage.java index f4b43d6c..bd374be3 100644 --- a/app/src/main/java/com/stoutner/privacybrowser/asynctasks/SaveWebpageImage.java +++ b/app/src/main/java/com/stoutner/privacybrowser/asynctasks/SaveWebpageImage.java @@ -69,7 +69,7 @@ public class SaveWebpageImage extends AsyncTask { 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(); diff --git a/app/src/main/java/com/stoutner/privacybrowser/dialogs/EditBookmarkDatabaseViewDialog.kt b/app/src/main/java/com/stoutner/privacybrowser/dialogs/EditBookmarkDatabaseViewDialog.kt index 377e0e8a..ea2d7929 100644 --- a/app/src/main/java/com/stoutner/privacybrowser/dialogs/EditBookmarkDatabaseViewDialog.kt +++ b/app/src/main/java/com/stoutner/privacybrowser/dialogs/EditBookmarkDatabaseViewDialog.kt @@ -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 diff --git a/app/src/main/java/com/stoutner/privacybrowser/dialogs/EditBookmarkDialog.kt b/app/src/main/java/com/stoutner/privacybrowser/dialogs/EditBookmarkDialog.kt index baa53cc3..56381fcc 100644 --- a/app/src/main/java/com/stoutner/privacybrowser/dialogs/EditBookmarkDialog.kt +++ b/app/src/main/java/com/stoutner/privacybrowser/dialogs/EditBookmarkDialog.kt @@ -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) diff --git a/app/src/main/java/com/stoutner/privacybrowser/dialogs/EditBookmarkFolderDatabaseViewDialog.kt b/app/src/main/java/com/stoutner/privacybrowser/dialogs/EditBookmarkFolderDatabaseViewDialog.kt index 5d6fe922..41b7de22 100644 --- a/app/src/main/java/com/stoutner/privacybrowser/dialogs/EditBookmarkFolderDatabaseViewDialog.kt +++ b/app/src/main/java/com/stoutner/privacybrowser/dialogs/EditBookmarkFolderDatabaseViewDialog.kt @@ -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(",") diff --git a/app/src/main/java/com/stoutner/privacybrowser/dialogs/EditBookmarkFolderDialog.kt b/app/src/main/java/com/stoutner/privacybrowser/dialogs/EditBookmarkFolderDialog.kt index 2a4bc9f3..86c521af 100644 --- a/app/src/main/java/com/stoutner/privacybrowser/dialogs/EditBookmarkFolderDialog.kt +++ b/app/src/main/java/com/stoutner/privacybrowser/dialogs/EditBookmarkFolderDialog.kt @@ -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) diff --git a/app/src/main/java/com/stoutner/privacybrowser/dialogs/MoveToFolderDialog.kt b/app/src/main/java/com/stoutner/privacybrowser/dialogs/MoveToFolderDialog.kt index f07f346a..575d581e 100644 --- a/app/src/main/java/com/stoutner/privacybrowser/dialogs/MoveToFolderDialog.kt +++ b/app/src/main/java/com/stoutner/privacybrowser/dialogs/MoveToFolderDialog.kt @@ -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(R.id.move_to_folder_icon) diff --git a/app/src/main/java/com/stoutner/privacybrowser/fragments/AboutVersionFragment.kt b/app/src/main/java/com/stoutner/privacybrowser/fragments/AboutVersionFragment.kt index 2e99ff2e..d2e9790b 100644 --- a/app/src/main/java/com/stoutner/privacybrowser/fragments/AboutVersionFragment.kt +++ b/app/src/main/java/com/stoutner/privacybrowser/fragments/AboutVersionFragment.kt @@ -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() diff --git a/app/src/main/java/com/stoutner/privacybrowser/fragments/DomainSettingsFragment.java b/app/src/main/java/com/stoutner/privacybrowser/fragments/DomainSettingsFragment.java index d2809b54..e26853c8 100644 --- a/app/src/main/java/com/stoutner/privacybrowser/fragments/DomainSettingsFragment.java +++ b/app/src/main/java/com/stoutner/privacybrowser/fragments/DomainSettingsFragment.java @@ -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. diff --git a/app/src/main/java/com/stoutner/privacybrowser/fragments/SettingsFragment.java b/app/src/main/java/com/stoutner/privacybrowser/fragments/SettingsFragment.java index 306f1e2c..a43e30bd 100644 --- a/app/src/main/java/com/stoutner/privacybrowser/fragments/SettingsFragment.java +++ b/app/src/main/java/com/stoutner/privacybrowser/fragments/SettingsFragment.java @@ -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 { diff --git a/app/src/main/java/com/stoutner/privacybrowser/helpers/BlocklistHelper.java b/app/src/main/java/com/stoutner/privacybrowser/helpers/BlocklistHelper.java index 913cc0b1..5ee2a98b 100644 --- a/app/src/main/java/com/stoutner/privacybrowser/helpers/BlocklistHelper.java +++ b/app/src/main/java/com/stoutner/privacybrowser/helpers/BlocklistHelper.java @@ -1,5 +1,5 @@ /* - * Copyright © 2018-2019 Soren Stoutner . + * Copyright © 2018-2019,2021 Soren Stoutner . * * This file is part of 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]}; diff --git a/app/src/main/java/com/stoutner/privacybrowser/helpers/BookmarksDatabaseHelper.java b/app/src/main/java/com/stoutner/privacybrowser/helpers/BookmarksDatabaseHelper.java index 8fe4be9c..0bc200c4 100644 --- a/app/src/main/java/com/stoutner/privacybrowser/helpers/BookmarksDatabaseHelper.java +++ b/app/src/main/java/com/stoutner/privacybrowser/helpers/BookmarksDatabaseHelper.java @@ -1,5 +1,5 @@ /* - * Copyright © 2016-2020 Soren Stoutner . + * Copyright © 2016-2021 Soren Stoutner . * * This file is part of 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; diff --git a/app/src/main/java/com/stoutner/privacybrowser/helpers/ImportExportDatabaseHelper.java b/app/src/main/java/com/stoutner/privacybrowser/helpers/ImportExportDatabaseHelper.java index c8638e08..bff5f9f1 100644 --- a/app/src/main/java/com/stoutner/privacybrowser/helpers/ImportExportDatabaseHelper.java +++ b/app/src/main/java/com/stoutner/privacybrowser/helpers/ImportExportDatabaseHelper.java @@ -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 index 04e40e9b..00000000 --- a/app/src/main/java/com/stoutner/privacybrowser/helpers/ProxyHelper.java +++ /dev/null @@ -1,315 +0,0 @@ -/* - * Copyright © 2016-2020 Soren Stoutner . - * - * This file is part of 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 . - */ - -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 index 00000000..0cc51058 --- /dev/null +++ b/app/src/main/java/com/stoutner/privacybrowser/helpers/ProxyHelper.kt @@ -0,0 +1,311 @@ +/* + * Copyright © 2016-2021 Soren Stoutner . + * + * This file is part of 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 . + */ + +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 diff --git a/app/src/main/java/com/stoutner/privacybrowser/views/NestedScrollWebView.kt b/app/src/main/java/com/stoutner/privacybrowser/views/NestedScrollWebView.kt index cd00f067..01e96048 100644 --- a/app/src/main/java/com/stoutner/privacybrowser/views/NestedScrollWebView.kt +++ b/app/src/main/java/com/stoutner/privacybrowser/views/NestedScrollWebView.kt @@ -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") diff --git a/app/src/main/res/layout/main_framelayout_bottom_appbar.xml b/app/src/main/res/layout/main_framelayout_bottom_appbar.xml index e78bcc30..521c03f8 100644 --- a/app/src/main/res/layout/main_framelayout_bottom_appbar.xml +++ b/app/src/main/res/layout/main_framelayout_bottom_appbar.xml @@ -36,160 +36,153 @@ 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" > - - + android:layout_height="match_parent" > - + android:layout_width="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" /> + + - - + + + + + + android:orientation="horizontal" + android:visibility="gone" > - - - - - - - - - - - - - - + - - - - - - - - - - - - - - - - - - + + - - + android:layout_width="wrap_content" + android:layout_marginStart="4dp" + android:layout_marginEnd="4dp" + android:text="@string/zero_of_zero" /> + + + + + + + + + + + + + + diff --git a/app/src/main/res/layout/main_framelayout_top_appbar.xml b/app/src/main/res/layout/main_framelayout_top_appbar.xml index 73201e53..3a49a5e3 100644 --- a/app/src/main/res/layout/main_framelayout_top_appbar.xml +++ b/app/src/main/res/layout/main_framelayout_top_appbar.xml @@ -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" > diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 5bf453a7..40ce96db 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -668,6 +668,8 @@ clear_logcat download_with_external_app display_additional_app_bar_icons + proxy_custom_url + scroll_app_bar System default diff --git a/build.gradle b/build.gradle index 2e3d98b1..319c598f 100644 --- a/build.gradle +++ b/build.gradle @@ -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 diff --git a/fastlane/metadata/android/de-DE/changelogs/57.txt b/fastlane/metadata/android/de-DE/changelogs/57.txt index e8c3c3e3..8da20ff7 100644 --- a/fastlane/metadata/android/de-DE/changelogs/57.txt +++ b/fastlane/metadata/android/de-DE/changelogs/57.txt @@ -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