import android.provider.DocumentsContract;
import android.provider.OpenableColumns;
import android.text.Editable;
-import android.text.Spanned;
import android.text.TextWatcher;
import android.text.style.ForegroundColorSpan;
import android.util.Patterns;
// The action bar drawer toggle is initialized in `onCreate()` and used in `onResume()`.
private ActionBarDrawerToggle actionBarDrawerToggle;
- // The color spans are used in `onCreate()` and `highlightUrlText()`.
- private ForegroundColorSpan redColorSpan;
- private ForegroundColorSpan initialGrayColorSpan;
- private ForegroundColorSpan finalGrayColorSpan;
-
// `bookmarksCursor` is used in `onDestroy()`, `onOptionsItemSelected()`, `onCreateBookmark()`, `onCreateBookmarkFolder()`, `onSaveEditBookmark()`, `onSaveEditBookmarkFolder()`, and `loadBookmarksFolder()`.
private Cursor bookmarksCursor;
private boolean displayAdditionalAppBarIcons;
private boolean displayingFullScreenVideo;
private boolean downloadWithExternalApp;
+ private ForegroundColorSpan finalGrayColorSpan;
private boolean fullScreenBrowsingModeEnabled;
private boolean hideAppBar;
- private boolean incognitoModeEnabled;
private boolean inFullScreenBrowsingMode;
+ private boolean incognitoModeEnabled;
+ private ForegroundColorSpan initialGrayColorSpan;
private boolean loadingNewIntent;
private BroadcastReceiver orbotStatusBroadcastReceiver;
private boolean reapplyAppSettingsOnRestart;
private boolean reapplyDomainSettingsOnRestart;
+ private ForegroundColorSpan redColorSpan;
private boolean sanitizeAmpRedirects;
private boolean sanitizeTrackingQueries;
private boolean scrollAppBar;
// Remove the formatting from the URL edit text when the user is editing the text.
urlEditText.setOnFocusChangeListener((View v, boolean hasFocus) -> {
if (hasFocus) { // The user is editing the URL text box.
- // Remove the highlighting.
+ // Remove the syntax highlighting.
urlEditText.getText().removeSpan(redColorSpan);
urlEditText.getText().removeSpan(initialGrayColorSpan);
urlEditText.getText().removeSpan(finalGrayColorSpan);
// Move to the beginning of the string.
urlEditText.setSelection(0);
- // Reapply the highlighting.
- highlightUrlText();
+ // Reapply the syntax highlighting.
+ UrlHelper.highlightSyntax(urlEditText, initialGrayColorSpan, finalGrayColorSpan, redColorSpan);
}
});
}
}
- private void highlightUrlText() {
- // Only highlight the URL text if the box is not currently selected.
- if (!urlEditText.hasFocus()) {
- // Get the URL string.
- String urlString = urlEditText.getText().toString();
-
- // Highlight the URL according to the protocol.
- if (urlString.startsWith("file://") || urlString.startsWith("content://")) { // This is a file or content URL.
- // De-emphasize everything before the file name.
- urlEditText.getText().setSpan(initialGrayColorSpan, 0, urlString.lastIndexOf("/") + 1,Spanned.SPAN_INCLUSIVE_INCLUSIVE);
- } else { // This is a web URL.
- // Get the index of the `/` immediately after the domain name.
- int endOfDomainName = urlString.indexOf("/", (urlString.indexOf("//") + 2));
-
- // Create a base URL string.
- String baseUrl;
-
- // Get the base URL.
- if (endOfDomainName > 0) { // There is at least one character after the base URL.
- // Get the base URL.
- baseUrl = urlString.substring(0, endOfDomainName);
- } else { // There are no characters after the base URL.
- // Set the base URL to be the entire URL string.
- baseUrl = urlString;
- }
-
- // Get the index of the last `.` in the domain.
- int lastDotIndex = baseUrl.lastIndexOf(".");
-
- // Get the index of the penultimate `.` in the domain.
- int penultimateDotIndex = baseUrl.lastIndexOf(".", lastDotIndex - 1);
-
- // Markup the beginning of the URL.
- if (urlString.startsWith("http://")) { // Highlight the protocol of connections that are not encrypted.
- urlEditText.getText().setSpan(redColorSpan, 0, 7, Spanned.SPAN_INCLUSIVE_INCLUSIVE);
-
- // De-emphasize subdomains.
- if (penultimateDotIndex > 0) { // There is more than one subdomain in the domain name.
- urlEditText.getText().setSpan(initialGrayColorSpan, 7, penultimateDotIndex + 1, Spanned.SPAN_INCLUSIVE_INCLUSIVE);
- }
- } else if (urlString.startsWith("https://")) { // De-emphasize the protocol of connections that are encrypted.
- if (penultimateDotIndex > 0) { // There is more than one subdomain in the domain name.
- // De-emphasize the protocol and the additional subdomains.
- urlEditText.getText().setSpan(initialGrayColorSpan, 0, penultimateDotIndex + 1, Spanned.SPAN_INCLUSIVE_INCLUSIVE);
- } else { // There is only one subdomain in the domain name.
- // De-emphasize only the protocol.
- urlEditText.getText().setSpan(initialGrayColorSpan, 0, 8, Spanned.SPAN_INCLUSIVE_INCLUSIVE);
- }
- }
-
- // De-emphasize the text after the domain name.
- if (endOfDomainName > 0) {
- urlEditText.getText().setSpan(finalGrayColorSpan, endOfDomainName, urlString.length(), Spanned.SPAN_INCLUSIVE_INCLUSIVE);
- }
- }
- }
- }
-
private void loadBookmarksFolder() {
// Update the bookmarks cursor with the contents of the bookmarks database for the current folder.
bookmarksCursor = bookmarksDatabaseHelper.getBookmarksByDisplayOrder(currentBookmarksFolder);
// Display the current URL in the URL text box.
urlEditText.setText(url);
- // Highlight the URL text.
- highlightUrlText();
+ // Highlight the URL syntax.
+ UrlHelper.highlightSyntax(urlEditText, initialGrayColorSpan, finalGrayColorSpan, redColorSpan);
}
} else { // A new intent is being loaded.
// Reset the loading new intent tracker.
// Display the formatted URL text.
urlEditText.setText(url);
- // Apply text highlighting to the URL text box.
- highlightUrlText();
+ // Highlight the URL syntax.
+ UrlHelper.highlightSyntax(urlEditText, initialGrayColorSpan, finalGrayColorSpan, redColorSpan);
// Hide the keyboard.
inputMethodManager.hideSoftInputFromWindow(nestedScrollWebView.getWindowToken(), 0);
// Display the final URL. Getting the URL from the WebView instead of using the one provided by `onPageFinished()` makes websites like YouTube function correctly.
urlEditText.setText(sanitizedUrl);
- // Apply text highlighting to the URL.
- highlightUrlText();
+ // Highlight the URL syntax.
+ UrlHelper.highlightSyntax(urlEditText, initialGrayColorSpan, finalGrayColorSpan, redColorSpan);
}
// Only populate the title text view if the tab has been fully created.
import android.os.Build
import android.os.Bundle
import android.text.SpannableStringBuilder
-import android.text.Spanned
import android.text.style.ForegroundColorSpan
import android.util.TypedValue
import android.view.KeyEvent
import com.stoutner.privacybrowser.dialogs.UntrustedSslCertificateDialog
import com.stoutner.privacybrowser.dialogs.UntrustedSslCertificateDialog.UntrustedSslCertificateListener
import com.stoutner.privacybrowser.helpers.ProxyHelper
+import com.stoutner.privacybrowser.helpers.UrlHelper
import com.stoutner.privacybrowser.viewmodelfactories.WebViewSourceFactory
import com.stoutner.privacybrowser.viewmodels.WebViewSource
redColorSpan = ForegroundColorSpan(getColor(R.color.red_text))
// Apply text highlighting to the URL.
- highlightUrlText()
+ UrlHelper.highlightSyntax(urlEditText, initialGrayColorSpan, finalGrayColorSpan, redColorSpan)
// Get a handle for the input method manager, which is used to hide the keyboard.
val inputMethodManager = (getSystemService(INPUT_METHOD_SERVICE) as InputMethodManager)
urlEditText.setSelection(0)
// Reapply the highlighting.
- highlightUrlText()
+ UrlHelper.highlightSyntax(urlEditText, initialGrayColorSpan, finalGrayColorSpan, redColorSpan)
}
}
webViewSource.updateSource(urlEditText.text.toString(), true)
}
- private fun highlightUrlText() {
- // Get a handle for the URL edit text.
- val urlEditText = findViewById<EditText>(R.id.url_edittext)
-
- // Get the URL string.
- val urlString = urlEditText.text.toString()
-
- // Highlight the URL according to the protocol.
- if (urlString.startsWith("file://")) { // This is a file URL.
- // De-emphasize only the protocol.
- urlEditText.text.setSpan(initialGrayColorSpan, 0, 7, Spanned.SPAN_INCLUSIVE_INCLUSIVE)
- } else if (urlString.startsWith("content://")) {
- // De-emphasize only the protocol.
- urlEditText.text.setSpan(initialGrayColorSpan, 0, 10, Spanned.SPAN_INCLUSIVE_INCLUSIVE)
- } else { // This is a web URL.
- // Get the index of the `/` immediately after the domain name.
- val endOfDomainName = urlString.indexOf("/", urlString.indexOf("//") + 2)
-
- // Get the base URL.
- val baseUrl = if (endOfDomainName > 0) { // There is at least one character after the base URL.
- // Get the base URL.
- urlString.substring(0, endOfDomainName)
- } else { // There are no characters after the base URL.
- // Set the base URL to be the entire URL string.
- urlString
- }
-
- // Get the index of the last `.` in the domain.
- val lastDotIndex = baseUrl.lastIndexOf(".")
-
- // Get the index of the penultimate `.` in the domain.
- val penultimateDotIndex = baseUrl.lastIndexOf(".", lastDotIndex - 1)
-
- // Markup the beginning of the URL.
- if (urlString.startsWith("http://")) { // Highlight the protocol of connections that are not encrypted.
- urlEditText.text.setSpan(redColorSpan, 0, 7, Spanned.SPAN_INCLUSIVE_INCLUSIVE)
-
- // De-emphasize subdomains.
- if (penultimateDotIndex > 0) { // There is more than one subdomain in the domain name.
- urlEditText.text.setSpan(initialGrayColorSpan, 7, penultimateDotIndex + 1, Spanned.SPAN_INCLUSIVE_INCLUSIVE)
- }
- } else if (urlString.startsWith("https://")) { // De-emphasize the protocol of connections that are encrypted.
- if (penultimateDotIndex > 0) { // There is more than one subdomain in the domain name.
- // De-emphasize the protocol and the additional subdomains.
- urlEditText.text.setSpan(initialGrayColorSpan, 0, penultimateDotIndex + 1, Spanned.SPAN_INCLUSIVE_INCLUSIVE)
- } else { // There is only one subdomain in the domain name.
- // De-emphasize only the protocol.
- urlEditText.text.setSpan(initialGrayColorSpan, 0, 8, Spanned.SPAN_INCLUSIVE_INCLUSIVE)
- }
- }
-
- // De-emphasize the text after the domain name.
- if (endOfDomainName > 0) {
- urlEditText.text.setSpan(finalGrayColorSpan, endOfDomainName, urlString.length, Spanned.SPAN_INCLUSIVE_INCLUSIVE)
- }
- }
- }
-
private fun updateLayout(urlString: String) {
if (urlString.startsWith("content://")) { // This is a content URL.
// Hide the unused text views.
import android.content.Context
import android.net.Uri
+import android.text.Spanned
+import android.text.style.ForegroundColorSpan
import android.webkit.CookieManager
import android.webkit.MimeTypeMap
+import android.widget.EditText
import com.stoutner.privacybrowser.R
-import java.lang.Exception
import java.net.HttpURLConnection
import java.net.URL
import java.text.NumberFormat
// Return the formatted file size.
return formattedFileSize
}
+
+ @JvmStatic
+ fun highlightSyntax(urlEditText: EditText, initialGrayColorSpan: ForegroundColorSpan, finalGrayColorSpan: ForegroundColorSpan, redColorSpan: ForegroundColorSpan) {
+ // Get the URL string.
+ val urlString: String = urlEditText.text.toString()
+
+ // Highlight the URL according to the protocol.
+ if (urlString.startsWith("file://") || urlString.startsWith("content://")) { // This is a file or content URL.
+ // De-emphasize everything before the file name.
+ urlEditText.text.setSpan(initialGrayColorSpan, 0, urlString.lastIndexOf("/") + 1, Spanned.SPAN_INCLUSIVE_INCLUSIVE)
+ } else { // This is a web URL.
+ // Get the index of the `/` immediately after the domain name.
+ val endOfDomainName = urlString.indexOf("/", urlString.indexOf("//") + 2)
+
+ // Get the base URL.
+ val baseUrl: String = if (endOfDomainName > 0) // There is at least one character after the base URL.
+ urlString.substring(0, endOfDomainName)
+ else // There are no characters after the base URL.
+ urlString
+
+ // Get the index of the last `.` in the domain.
+ val lastDotIndex = baseUrl.lastIndexOf(".")
+
+ // Get the index of the penultimate `.` in the domain.
+ val penultimateDotIndex = baseUrl.lastIndexOf(".", lastDotIndex - 1)
+
+ // Markup the beginning of the URL.
+ if (urlString.startsWith("http://")) { // The protocol is not encrypted.
+ // Highlight the protocol in red.
+ urlEditText.text.setSpan(redColorSpan, 0, 7, Spanned.SPAN_INCLUSIVE_INCLUSIVE)
+
+ // De-emphasize subdomains.
+ if (penultimateDotIndex > 0) // There is more than one subdomain in the domain name.
+ urlEditText.text.setSpan(initialGrayColorSpan, 7, penultimateDotIndex + 1, Spanned.SPAN_INCLUSIVE_INCLUSIVE)
+ } else if (urlString.startsWith("https://")) { // The protocol is encrypted.
+ // De-emphasize the protocol of connections that are encrypted.
+ if (penultimateDotIndex > 0) // There is more than one subdomain in the domain name. De-emphasize the protocol and the additional subdomains.
+ urlEditText.text.setSpan(initialGrayColorSpan, 0, penultimateDotIndex + 1, Spanned.SPAN_INCLUSIVE_INCLUSIVE)
+ else // There is only one subdomain in the domain name. De-emphasize only the protocol.
+ urlEditText.text.setSpan(initialGrayColorSpan, 0, 8, Spanned.SPAN_INCLUSIVE_INCLUSIVE)
+ }
+
+ // De-emphasize the text after the domain name.
+ if (endOfDomainName > 0)
+ urlEditText.text.setSpan(finalGrayColorSpan, endOfDomainName, urlString.length, Spanned.SPAN_INCLUSIVE_INCLUSIVE)
+ }
+ }
}