*
* Download cookie code contributed 2017 Hendrik Knackstedt. Copyright assigned to Soren Stoutner <soren@stoutner.com>.
*
- * This file is part of Privacy Browser Android <https://www.stoutner.com/privacy-browser-android>.
+ * This file is part of Privacy Browser Android <https://www.stoutner.com/privacy-browser-android/>.
*
* Privacy Browser Android is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
// Declare the public static variables.
lateinit var appBarLayout: AppBarLayout
+ lateinit var defaultFavoriteIconBitmap : Bitmap
}
// Declare the class variables.
private lateinit var findOnPageLinearLayout: LinearLayout
private lateinit var fullScreenVideoFrameLayout: FrameLayout
private lateinit var initialGrayColorSpan: ForegroundColorSpan
+ private lateinit var inputMethodManager: InputMethodManager
private lateinit var navigationBackMenuItem: MenuItem
private lateinit var navigationForwardMenuItem: MenuItem
private lateinit var navigationHistoryMenuItem: MenuItem
// Update the bookmarks drawer pinned image view.
updateBookmarksDrawerPinnedImageView()
+ // Get the default favorite icon drawable.
+ val favoriteIconDrawable = AppCompatResources.getDrawable(this, R.drawable.world)
+
+ // Cast the favorite icon drawable to a bitmap drawable.
+ val favoriteIconBitmapDrawable = (favoriteIconDrawable as BitmapDrawable?)!!
+
+ // Store the default favorite icon bitmap.
+ defaultFavoriteIconBitmap = favoriteIconBitmapDrawable.bitmap
+
// Initialize the app.
initializeApp()
exitFullScreenVideo()
// It shouldn't be possible for the currentWebView to be null, but crash logs indicate it sometimes happens.
} else if (currentWebView != null && currentWebView!!.canGoBack()) { // There is at least one item in the current WebView history.
- // Get the current web back forward list.
- val webBackForwardList = currentWebView!!.copyBackForwardList()
-
- // Get the previous entry data.
- val previousUrl = webBackForwardList.getItemAtIndex(webBackForwardList.currentIndex - 1).url
- val previousFavoriteIcon = webBackForwardList.getItemAtIndex(webBackForwardList.currentIndex - 1).favicon
-
- // Apply the domain settings.
- applyDomainSettings(currentWebView!!, previousUrl, resetTab = false, reloadWebsite = false, loadUrl = false)
-
- // Get the current tab.
- val tab = tabLayout.getTabAt(tabLayout.selectedTabPosition)!!
-
- // Get the custom view from the tab.
- val tabView = tab.customView!!
-
- // Get the favorite icon image view from the tab.
- val tabFavoriteIconImageView = tabView.findViewById<ImageView>(R.id.favorite_icon_imageview)
-
- // Set the previous favorite icon if it isn't null.
- if (previousFavoriteIcon != null)
- tabFavoriteIconImageView.setImageBitmap(Bitmap.createScaledBitmap(previousFavoriteIcon, 64, 64, true))
-
- // Go back.
- currentWebView!!.goBack()
-
- // Update the URL edit text after a delay.
- updateUrlEditTextAfterDelay()
+ // Navigate back one page.
+ navigateHistory(-1)
} else { // Close the current tab.
// A view is required because the method is also called by an XML `onClick`.
closeTab(null)
// Set the focus on the find on page edit text.
findOnPageEditText.requestFocus()
- // Get a handle for the input method manager.
- val inputMethodManager = (getSystemService(INPUT_METHOD_SERVICE) as InputMethodManager)
-
// Display the keyboard. `0` sets no input flags.
inputMethodManager.showSoftInput(findOnPageEditText, 0)
}, 200)
R.id.back -> { // Back.
// Check if the WebView can go back.
if (currentWebView!!.canGoBack()) {
- // Get the current web back forward list.
- val webBackForwardList = currentWebView!!.copyBackForwardList()
-
- // Get the previous entry data.
- val previousUrl = webBackForwardList.getItemAtIndex(webBackForwardList.currentIndex - 1).url
- val previousFavoriteIcon = webBackForwardList.getItemAtIndex(webBackForwardList.currentIndex - 1).favicon!!
-
- // Apply the domain settings.
- applyDomainSettings(currentWebView!!, previousUrl, resetTab = false, reloadWebsite = false, loadUrl = false)
-
- // Get the current tab.
- val tab = tabLayout.getTabAt(tabLayout.selectedTabPosition)!!
-
- // Get the custom view from the tab.
- val tabView = tab.customView!!
-
- // Get the favorite icon image view from the tab.
- val tabFavoriteIconImageView = tabView.findViewById<ImageView>(R.id.favorite_icon_imageview)
-
- // Set the previous favorite icon.
- tabFavoriteIconImageView.setImageBitmap(Bitmap.createScaledBitmap(previousFavoriteIcon, 64, 64, true))
-
- // Load the previous website in the history.
- currentWebView!!.goBack()
-
- // Update the URL edit text after a delay.
- updateUrlEditTextAfterDelay()
+ // Navigate back one page.
+ navigateHistory(-1)
}
}
R.id.forward -> { // Forward.
// Check if the WebView can go forward.
if (currentWebView!!.canGoForward()) {
- // Get the current web back forward list.
- val webBackForwardList = currentWebView!!.copyBackForwardList()
-
- // Get the next entry data.
- val nextUrl = webBackForwardList.getItemAtIndex(webBackForwardList.currentIndex + 1).url
- val nextFavoriteIcon = webBackForwardList.getItemAtIndex(webBackForwardList.currentIndex + 1).favicon!!
-
- // Apply the domain settings.
- applyDomainSettings(currentWebView!!, nextUrl, resetTab = false, reloadWebsite = false, loadUrl = false)
-
- // Get the current tab.
- val tab = tabLayout.getTabAt(tabLayout.selectedTabPosition)!!
-
- // Get the custom view from the tab.
- val tabView = tab.customView!!
-
- // Get the favorite icon image view from the tab.
- val tabFavoriteIconImageView = tabView.findViewById<ImageView>(R.id.favorite_icon_imageview)
-
- // Set the next favorite icon.
- tabFavoriteIconImageView.setImageBitmap(Bitmap.createScaledBitmap(nextFavoriteIcon, 64, 64, true))
-
- // Load the next website in the history.
- currentWebView!!.goForward()
-
- // Update the URL edit text after a delay.
- updateUrlEditTextAfterDelay()
+ // Navigate forward one page.
+ navigateHistory(+1)
}
}
nestedScrollWebView.clearPinnedSslCertificate()
nestedScrollWebView.pinnedIpAddresses = ""
- // Reset the favorite icon if specified.
+ // Reset the tab if specified.
if (resetTab) {
// Initialize the favorite icon.
- nestedScrollWebView.initializeFavoriteIcon()
+ nestedScrollWebView.resetFavoriteIcon()
// Get the current page position.
val currentPagePosition = webViewStateAdapter!!.getPositionForId(nestedScrollWebView.webViewFragmentId)
nestedScrollWebView.previousWebpageTitle = tabTitleTextView.text.toString()
// Set the default favorite icon as the favorite icon for this tab.
- tabFavoriteIconImageView.setImageBitmap(Bitmap.createScaledBitmap(nestedScrollWebView.getFavoriteIcon(), 64, 64, true))
+ tabFavoriteIconImageView.setImageBitmap(Bitmap.createScaledBitmap(nestedScrollWebView.getFavoriteIcon(), 128, 128, true))
// Set the loading title text.
tabTitleTextView.setText(R.string.loading)
// Show the toolbar.
toolbar.visibility = View.VISIBLE
- // Get a handle for the input method manager.
- val inputMethodManager = (getSystemService(INPUT_METHOD_SERVICE) as InputMethodManager)
-
// Hide the keyboard.
inputMethodManager.hideSoftInputFromWindow(toolbar.windowToken, 0)
}
}
}
- override fun createBookmark(dialogFragment: DialogFragment, favoriteIconBitmap: Bitmap) {
+ override fun createBookmark(dialogFragment: DialogFragment) {
// Get the dialog.
val dialog = dialogFragment.dialog!!
// Get the views from the dialog fragment.
- val createBookmarkNameEditText = dialog.findViewById<EditText>(R.id.create_bookmark_name_edittext)
- val createBookmarkUrlEditText = dialog.findViewById<EditText>(R.id.create_bookmark_url_edittext)
+ val webpageFavoriteIconRadioButton = dialog.findViewById<RadioButton>(R.id.webpage_favorite_icon_radiobutton)
+ val webpageFavoriteIconImageView = dialog.findViewById<ImageView>(R.id.webpage_favorite_icon_imageview)
+ val customIconImageView = dialog.findViewById<ImageView>(R.id.custom_icon_imageview)
+ val bookmarkNameEditText = dialog.findViewById<EditText>(R.id.bookmark_name_edittext)
+ val bookmarkUrlEditText = dialog.findViewById<EditText>(R.id.bookmark_url_edittext)
// Extract the strings from the edit texts.
- val bookmarkNameString = createBookmarkNameEditText.text.toString()
- val bookmarkUrlString = createBookmarkUrlEditText.text.toString()
+ val bookmarkNameString = bookmarkNameEditText.text.toString()
+ val bookmarkUrlString = bookmarkUrlEditText.text.toString()
+
+ // Get the selected favorite icon drawable.
+ val favoriteIconDrawable = if (webpageFavoriteIconRadioButton.isChecked) // Use the webpage favorite icon.
+ webpageFavoriteIconImageView.drawable
+ else // Use the custom icon.
+ customIconImageView.drawable
+
+ // Cast the favorite icon bitmap to a bitmap drawable
+ val favoriteIconBitmapDrawable = favoriteIconDrawable as BitmapDrawable
+
+ // Convert the favorite icon bitmap drawable to a bitmap.
+ val favoriteIconBitmap = favoriteIconBitmapDrawable.bitmap
// Create a favorite icon byte array output stream.
val favoriteIconByteArrayOutputStream = ByteArrayOutputStream()
bookmarksListView.setSelection(newBookmarkDisplayOrder)
}
- override fun createBookmarkFolder(dialogFragment: DialogFragment, favoriteIconBitmap: Bitmap) {
+ override fun createBookmarkFolder(dialogFragment: DialogFragment) {
// Get the dialog.
val dialog = dialogFragment.dialog!!
// Get handles for the views in the dialog fragment.
+ val defaultFolderIconRadioButton = dialog.findViewById<RadioButton>(R.id.default_folder_icon_radiobutton)
+ val defaultFolderIconImageView = dialog.findViewById<ImageView>(R.id.default_folder_icon_imageview)
+ val webpageFavoriteIconRadioButton = dialog.findViewById<RadioButton>(R.id.webpage_favorite_icon_radiobutton)
+ val webpageFavoriteIconImageView = dialog.findViewById<ImageView>(R.id.webpage_favorite_icon_imageview)
+ val customIconImageView = dialog.findViewById<ImageView>(R.id.custom_icon_imageview)
val folderNameEditText = dialog.findViewById<EditText>(R.id.folder_name_edittext)
- val defaultIconRadioButton = dialog.findViewById<RadioButton>(R.id.default_icon_radiobutton)
- val defaultIconImageView = dialog.findViewById<ImageView>(R.id.default_icon_imageview)
// Get new folder name string.
val folderNameString = folderNameEditText.text.toString()
// Set the folder icon bitmap according to the dialog.
- val folderIconBitmap: Bitmap = if (defaultIconRadioButton.isChecked) { // Use the default folder icon.
- // Get the default folder icon drawable.
- val folderIconDrawable = defaultIconImageView.drawable
-
- // Convert the folder icon drawable to a bitmap drawable.
- val folderIconBitmapDrawable = folderIconDrawable as BitmapDrawable
-
- // Convert the folder icon bitmap drawable to a bitmap.
- folderIconBitmapDrawable.bitmap
- } else { // Use the WebView favorite icon.
- // Copy the favorite icon bitmap to the folder icon bitmap.
- favoriteIconBitmap
- }
+ val folderIconDrawable = if (defaultFolderIconRadioButton.isChecked) // Use the default folder icon.
+ defaultFolderIconImageView.drawable
+ else if (webpageFavoriteIconRadioButton.isChecked) // Use the webpage favorite icon.
+ webpageFavoriteIconImageView.drawable
+ else // Use the custom icon.
+ customIconImageView.drawable
+
+ // Cast the folder icon bitmap to a bitmap drawable.
+ val folderIconBitmapDrawable = folderIconDrawable as BitmapDrawable
+
+ // Convert the folder icon bitmap drawable to a bitmap.
+ val folderIconBitmap = folderIconBitmapDrawable.bitmap
// Create a folder icon byte array output stream.
val folderIconByteArrayOutputStream = ByteArrayOutputStream()
@SuppressLint("ClickableViewAccessibility")
private fun initializeApp() {
// Get a handle for the input method.
- val inputMethodManager = (getSystemService(INPUT_METHOD_SERVICE) as InputMethodManager)
+ inputMethodManager = (getSystemService(INPUT_METHOD_SERVICE) as InputMethodManager)
// Initialize the color spans for highlighting the URLs.
initialGrayColorSpan = ForegroundColorSpan(getColor(R.color.gray_500))
// Search for the string on the page whenever a character changes in the find on page edit text.
findOnPageEditText.addTextChangedListener(object : TextWatcher {
- override fun beforeTextChanged(s: CharSequence, start: Int, count: Int, after: Int) {}
+ override fun beforeTextChanged(charSequence: CharSequence, start: Int, count: Int, after: Int) {
+ // Do nothing.
+ }
- override fun onTextChanged(s: CharSequence, start: Int, before: Int, count: Int) {}
+ override fun onTextChanged(charSequence: CharSequence, start: Int, before: Int, count: Int) {
+ // Do nothing.
+ }
- override fun afterTextChanged(s: Editable) {
+ override fun afterTextChanged(editable: Editable) {
// Search for the text in the WebView if it is not null. Sometimes on resume after a period of non-use the WebView will be null.
currentWebView?.findAllAsync(findOnPageEditText.text.toString())
}
}
}
- // Get a handle for the input method manager.
- val inputMethodManager = getSystemService(INPUT_METHOD_SERVICE) as InputMethodManager
-
// Set the app bar scrolling.
nestedScrollWebView.isNestedScrollingEnabled = scrollAppBar
val tabFavoriteIconImageView = tabView.findViewById<ImageView>(R.id.favorite_icon_imageview)
// Display the favorite icon in the tab.
- tabFavoriteIconImageView.setImageBitmap(Bitmap.createScaledBitmap(icon, 64, 64, true))
+ tabFavoriteIconImageView.setImageBitmap(Bitmap.createScaledBitmap(icon, 128, 128, true))
}
}
}
// Instantiate an HTTP authentication dialog.
val httpAuthenticationDialogFragment = HttpAuthenticationDialog.displayDialog(host, realm, nestedScrollWebView.webViewFragmentId)
- // Show the HTTP authentication dialog.
- httpAuthenticationDialogFragment.show(supportFragmentManager, getString(R.string.http_authentication))
+ // Try to show the dialog. WebView can receive an HTTP authentication request even after the app has been paused. Attempting to display a dialog in that state leads to a crash.
+ try {
+ // Show the HTTP authentication dialog.
+ httpAuthenticationDialogFragment.show(supportFragmentManager, getString(R.string.http_authentication))
+ } catch (exception: Exception) { // The dialog could not be shown.
+ // Add the dialog to the pending dialog array list. It will be displayed in `onStart()`.
+ pendingDialogsArrayList.add(PendingDialogDataClass(httpAuthenticationDialogFragment, getString(R.string.http_authentication)))
+ }
}
override fun onPageStarted(webView: WebView, url: String, favicon: Bitmap?) {
// Instantiate an SSL certificate error alert dialog.
val sslCertificateErrorDialogFragment = SslCertificateErrorDialog.displayDialog(error, nestedScrollWebView.webViewFragmentId)
- // Try to show the dialog. The SSL error handler continues to function even when the WebView is paused. Attempting to display a dialog in that state leads to a crash.
+ // Try to show the dialog. The SSL error handler continues to function even when the app has been stopped. Attempting to display a dialog in that state leads to a crash.
try {
// Show the SSL certificate error dialog.
sslCertificateErrorDialogFragment.show(supportFragmentManager, getString(R.string.ssl_certificate_error))
loadUrl(currentWebView!!, urlString)
}
- override fun navigateHistory(url: String, steps: Int) {
+ override fun navigateHistory(steps: Int) {
+ // Get the current web back forward list.
+ val webBackForwardList = currentWebView!!.copyBackForwardList()
+
+ // Calculate the target index.
+ val targetIndex = webBackForwardList.currentIndex + steps
+
+ // Get the previous entry data.
+ val previousUrl = webBackForwardList.getItemAtIndex(targetIndex).url
+ val previousFavoriteIcon = webBackForwardList.getItemAtIndex(targetIndex).favicon
+
// Apply the domain settings.
- applyDomainSettings(currentWebView!!, url, resetTab = false, reloadWebsite = false, loadUrl = false)
+ applyDomainSettings(currentWebView!!, previousUrl, resetTab = false, reloadWebsite = false, loadUrl = false)
+
+ // Get the current tab.
+ val tab = tabLayout.getTabAt(tabLayout.selectedTabPosition)!!
+
+ // Get the custom view from the tab.
+ val tabView = tab.customView!!
+
+ // Get the favorite icon image view from the tab.
+ val tabFavoriteIconImageView = tabView.findViewById<ImageView>(R.id.favorite_icon_imageview)
+
+ // Store the previous favorite icon.
+ if (previousFavoriteIcon == null)
+ currentWebView!!.setFavoriteIcon(defaultFavoriteIconBitmap)
+ else
+ currentWebView!!.setFavoriteIcon(previousFavoriteIcon)
+
+ // Display the previous favorite icon in the tab.
+ tabFavoriteIconImageView.setImageBitmap(Bitmap.createScaledBitmap(currentWebView!!.getFavoriteIcon(), 128, 128, true))
// Load the history entry.
currentWebView!!.goBackOrForward(steps)
- // Update the URL edit text after a delay.
- updateUrlEditTextAfterDelay()
+ // Create a handler to update the URL edit box.
+ val urlEditTextUpdateHandler = Handler(Looper.getMainLooper())
+
+ // Create a runnable to update the URL edit box.
+ val urlEditTextUpdateRunnable = Runnable {
+ // Update the URL edit text.
+ urlEditText.setText(currentWebView!!.url)
+
+ // Disable the wide viewport if the source is being viewed.
+ if (currentWebView!!.url!!.startsWith("view-source:"))
+ currentWebView!!.settings.useWideViewPort = false
+ }
+
+ // Update the URL edit text after 50 milliseconds, so that the WebView has enough time to navigate to the new URL.
+ urlEditTextUpdateHandler.postDelayed(urlEditTextUpdateRunnable, 50)
}
override fun openFile(dialogFragment: DialogFragment) {
}
override fun pinnedErrorGoBack() {
- // Get the current web back forward list.
- val webBackForwardList = currentWebView!!.copyBackForwardList()
-
- // Get the previous entry URL.
- val previousUrl = webBackForwardList.getItemAtIndex(webBackForwardList.currentIndex - 1).url
-
- // Apply the domain settings.
- applyDomainSettings(currentWebView!!, previousUrl, resetTab = false, reloadWebsite = false, loadUrl = false)
-
- // Go back.
- currentWebView!!.goBack()
-
- // Update the URL edit text after a delay.
- updateUrlEditTextAfterDelay()
+ // Navigate back one page.
+ navigateHistory(-1)
}
private fun sanitizeUrl(urlString: String): String {
// Update the privacy icons. `true` redraws the icons in the app bar.
updatePrivacyIcons(true)
- // Get a handle for the input method manager.
- val inputMethodManager = (getSystemService(INPUT_METHOD_SERVICE) as InputMethodManager)
-
// Get the current URL.
val urlString = currentWebView!!.url
invalidateOptionsMenu()
}
}
-
- fun updateUrlEditTextAfterDelay() {
- // Create a handler to update the URL edit box.
- val urlEditTextUpdateHandler = Handler(Looper.getMainLooper())
-
- // Create a runnable to update the URL edit box.
- val urlEditTextUpdateRunnable = Runnable {
- // Update the URL edit text.
- urlEditText.setText(currentWebView!!.url)
-
- // Disable the wide viewport if the source is being viewed.
- if (currentWebView!!.url!!.startsWith("view-source:"))
- currentWebView!!.settings.useWideViewPort = false
- }
-
- // Update the URL edit text after 50 milliseconds, so that the WebView has enough time to navigate to the new URL.
- urlEditTextUpdateHandler.postDelayed(urlEditTextUpdateRunnable, 50)
- }
}