}
});
- // Implement swipe to refresh
- swipeRefreshLayout = findViewById(R.id.swipe_refreshlayout);
- swipeRefreshLayout.setColorSchemeResources(R.color.blue_700);
+ // Implement swipe to refresh.
+ swipeRefreshLayout = findViewById(R.id.swiperefreshlayout);
swipeRefreshLayout.setOnRefreshListener(() -> mainWebView.reload());
+ // Set the swipe to refresh color according to the theme.
+ if (darkTheme) {
+ swipeRefreshLayout.setColorSchemeResources(R.color.blue_600);
+ swipeRefreshLayout.setProgressBackgroundColorSchemeResource(R.color.gray_850);
+ } else {
+ swipeRefreshLayout.setColorSchemeResources(R.color.blue_700);
+ }
+
// `DrawerTitle` identifies the `DrawerLayouts` in accessibility mode.
drawerLayout.setDrawerTitle(GravityCompat.START, getString(R.string.navigation_drawer));
drawerLayout.setDrawerTitle(GravityCompat.END, getString(R.string.bookmarks));
// Hide the keyboard (if displayed).
inputMethodManager.hideSoftInputFromWindow(mainWebView.getWindowToken(), 0);
- // Clear the focus from from the URL text box and the WebView. This removes any text selection markers and context menues, which otherwise draw above the open drawers.
+ // Clear the focus from from the URL text box and the WebView. This removes any text selection markers and context menus, which otherwise draw above the open drawers.
urlTextBox.clearFocus();
mainWebView.clearFocus();
}
formattedUrlString = "";
// Apply the domain settings for the new URL. `applyDomainSettings` doesn't do anything if the domain has not changed.
- applyDomainSettings(url, true, false);
+ boolean userAgentChanged = applyDomainSettings(url, true, false);
- // Returning false causes the current WebView to handle the URL and prevents it from adding redirects to the history list.
- return false;
+ // Check if the user agent has changed.
+ if (userAgentChanged) {
+ // Manually load the URL. The changing of the user agent will cause WebView to reload the previous URL.
+ mainWebView.loadUrl(url, customHeaders);
+
+ // Returning true indicates that Privacy Browser is manually handling the loading of the URL.
+ return true;
+ } else {
+ // Returning false causes the current WebView to handle the URL and prevents it from adding redirects to the history list.
+ return false;
+ }
} else if (url.startsWith("mailto:")) { // Load the email address in an external email program.
// Use `ACTION_SENDTO` instead of `ACTION_SEND` so that only email programs are launched.
Intent emailIntent = new Intent(Intent.ACTION_SENDTO);
// Apply any custom domain settings if the URL was loaded by navigating history.
if (navigatingHistory) {
+ // Apply the domain settings.
+ boolean userAgentChanged = applyDomainSettings(url, true, false);
+
// Reset `navigatingHistory`.
navigatingHistory = false;
- // Apply the domain settings.
- applyDomainSettings(url, true, false);
+ // Manually load the URL if the user agent has changed, which will have caused the previous URL to be reloaded.
+ if (userAgentChanged) {
+ loadUrl(formattedUrlString);
+ }
}
// Set `urlIsLoading` to `true`, so that redirects while loading do not trigger changes in the user agent, which forces another reload of the existing page.
sslCertificate = mainWebView.getCertificate();
// Check the current website SSL certificate against the pinned SSL certificate if there is a pinned SSL certificate the user has not chosen to ignore it for this session.
- if (pinnedDomainSslCertificate && !ignorePinnedSslCertificate) {
+ // Also ignore if changes in the user agent causes an error while navigating history.
+ if (pinnedDomainSslCertificate && !ignorePinnedSslCertificate && navigatingHistory) {
// Initialize the current SSL certificate variables.
String currentWebsiteIssuedToCName = "";
String currentWebsiteIssuedToOName = "";
// `reloadWebsite` is used if returning from the Domains activity. Otherwise JavaScript might not function correctly if it is newly enabled.
// The deprecated `.getDrawable()` must be used until the minimum API >= 21.
@SuppressWarnings("deprecation")
- private void applyDomainSettings(String url, boolean resetFavoriteIcon, boolean reloadWebsite) {
+ private boolean applyDomainSettings(String url, boolean resetFavoriteIcon, boolean reloadWebsite) {
+ // Get the current user agent.
+ String initialUserAgent = mainWebView.getSettings().getUserAgentString();
+
+ // Initialize a variable to track if the user agent changes.
+ boolean userAgentChanged = false;
+
// Parse the URL into a URI.
Uri uri = Uri.parse(url);
}
}
- // Set swipe to refresh.
- switch (swipeToRefreshInt) {
- case DomainsDatabaseHelper.SWIPE_TO_REFRESH_SYSTEM_DEFAULT:
- // Set swipe to refresh according to the default.
- swipeRefreshLayout.setEnabled(defaultSwipeToRefresh);
- break;
+ // Store the applied user agent string, which is used in the View Source activity.
+ appliedUserAgentString = mainWebView.getSettings().getUserAgentString();
- case DomainsDatabaseHelper.SWIPE_TO_REFRESH_ENABLED:
- // Enable swipe to refresh.
- swipeRefreshLayout.setEnabled(true);
- break;
+ // Update the user agent change tracker.
+ userAgentChanged = !appliedUserAgentString.equals(initialUserAgent);
+ }
- case DomainsDatabaseHelper.SWIPE_TO_REFRESH_DISABLED:
- // Disable swipe to refresh.
- swipeRefreshLayout.setEnabled(false);
- }
+ // Set swipe to refresh.
+ switch (swipeToRefreshInt) {
+ case DomainsDatabaseHelper.SWIPE_TO_REFRESH_SYSTEM_DEFAULT:
+ // Set swipe to refresh according to the default.
+ swipeRefreshLayout.setEnabled(defaultSwipeToRefresh);
+ break;
- // Store the applied user agent string, which is used in the View Source activity.
- appliedUserAgentString = mainWebView.getSettings().getUserAgentString();
+ case DomainsDatabaseHelper.SWIPE_TO_REFRESH_ENABLED:
+ // Enable swipe to refresh.
+ swipeRefreshLayout.setEnabled(true);
+ break;
+
+ case DomainsDatabaseHelper.SWIPE_TO_REFRESH_DISABLED:
+ // Disable swipe to refresh.
+ swipeRefreshLayout.setEnabled(false);
}
// Set the loading of webpage images.
// Store the applied user agent string, which is used in the View Source activity.
appliedUserAgentString = mainWebView.getSettings().getUserAgentString();
+
+ // Update the user agent change tracker.
+ userAgentChanged = !appliedUserAgentString.equals(initialUserAgent);
}
// Set the loading of webpage images.
if (reloadWebsite) {
mainWebView.reload();
}
+
+ // Return the user agent changed status.
+ return userAgentChanged;
}
private void applyProxyThroughOrbot(boolean reloadWebsite) {
}
private void highlightUrlText() {
+ // Get the URL string.
String urlString = urlTextBox.getText().toString();
+ // 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.
urlTextBox.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.
+ urlTextBox.getText().setSpan(initialGrayColorSpan, 7, penultimateDotIndex + 1, Spanned.SPAN_INCLUSIVE_INCLUSIVE);
+ }
} else if (urlString.startsWith("https://")) { // De-emphasize the protocol of connections that are encrypted.
- urlTextBox.getText().setSpan(initialGrayColorSpan, 0, 8, Spanned.SPAN_INCLUSIVE_INCLUSIVE);
+ if (penultimateDotIndex > 0) { // There is more than one subdomain in the domain name.
+ // De-emphasize the protocol and the additional subdomains.
+ urlTextBox.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.
+ urlTextBox.getText().setSpan(initialGrayColorSpan, 0, 8, Spanned.SPAN_INCLUSIVE_INCLUSIVE);
+ }
}
- // Get the index of the `/` immediately after the domain name.
- int endOfDomainName = urlString.indexOf("/", (urlString.indexOf("//") + 2));
-
// De-emphasize the text after the domain name.
if (endOfDomainName > 0) {
urlTextBox.getText().setSpan(finalGrayColorSpan, endOfDomainName, urlString.length(), Spanned.SPAN_INCLUSIVE_INCLUSIVE);