X-Git-Url: https://gitweb.stoutner.com/?p=PrivacyBrowserAndroid.git;a=blobdiff_plain;f=app%2Fsrc%2Fmain%2Fjava%2Fcom%2Fstoutner%2Fprivacybrowser%2Factivities%2FMainWebViewActivity.java;h=d708132d390a075610393ac3bc5c5b7d23d73ad6;hp=f3922e0764a30af0635bd1113f58e2ff31f75a19;hb=792956e409a0a191f0e1a2da9bdc9c46941215ca;hpb=fc7bcfdefc4b555623006c2879d95ae727517b14 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 f3922e07..d708132d 100644 --- a/app/src/main/java/com/stoutner/privacybrowser/activities/MainWebViewActivity.java +++ b/app/src/main/java/com/stoutner/privacybrowser/activities/MainWebViewActivity.java @@ -60,7 +60,6 @@ import android.support.v7.app.AppCompatActivity; import android.support.v7.app.AppCompatDialogFragment; import android.support.v7.widget.Toolbar; import android.text.Editable; -import android.text.SpannableStringBuilder; import android.text.Spanned; import android.text.TextWatcher; import android.text.style.ForegroundColorSpan; @@ -123,9 +122,6 @@ import java.util.Set; public class MainWebViewActivity extends AppCompatActivity implements NavigationView.OnNavigationItemSelectedListener, CreateHomeScreenShortcutDialog.CreateHomeScreenSchortcutListener, SslCertificateErrorDialog.SslCertificateErrorListener, DownloadFileDialog.DownloadFileListener, DownloadImageDialog.DownloadImageListener, UrlHistoryDialog.UrlHistoryListener { - // `appBar` is public static so it can be accessed from `OrbotProxyHelper`. It is also used in `onCreate()`, `onOptionsItemSelected()`, `closeFindOnPage()`, and `applyAppSettings()`. - public static ActionBar appBar; - // `favoriteIconBitmap` is public static so it can be accessed from `CreateHomeScreenShortcutDialog`, `BookmarksActivity`, `CreateBookmarkDialog`, `CreateBookmarkFolderDialog`, `EditBookmarkDialog`, `EditBookmarkFolderDialog`, `ViewSslCertificateDialog`. // It is also used in `onCreate()`, `onCreateHomeScreenShortcutCreate()`, and `applyDomainSettings`. public static Bitmap favoriteIconBitmap; @@ -150,6 +146,9 @@ public class MainWebViewActivity extends AppCompatActivity implements Navigation public static boolean reloadOnRestartBoolean; + // `appBar` is used in `onCreate()`, `onOptionsItemSelected()`, `closeFindOnPage()`, and `applyAppSettings()`. + private ActionBar appBar; + // `navigatingHistory` is used in `onCreate()`, `onNavigationItemSelected()`, and `applyDomainSettings()`. private boolean navigatingHistory; @@ -266,9 +265,21 @@ public class MainWebViewActivity extends AppCompatActivity implements Navigation // `supportAppBar` is used in `onCreate()`, `onOptionsItemSelected()`, and `closeFindOnPage()`. private Toolbar supportAppBar; - // `urlTextBox` is used in `onCreate()`, `onOptionsItemSelected()`, `loadUrlFromTextBox()`, and `loadUrl()`. + // `urlTextBox` is used in `onCreate()`, `onOptionsItemSelected()`, `loadUrlFromTextBox()`, `loadUrl()`, and `highlightUrlText()`. private EditText urlTextBox; + // `redColorSpan` is used in `onCreate()` and `highlightUrlText()`. + private ForegroundColorSpan redColorSpan; + + // `initialGrayColorSpan` is sued in `onCreate()` and `highlightUrlText()`. + private ForegroundColorSpan initialGrayColorSpan; + + // `finalGrayColorSpam` is used in `onCreate()` and `highlightUrlText()`. + private ForegroundColorSpan finalGrayColorSpan; + + // `boldStyleSpan` is used in `onCreate()` and `highlightUrlText()`. + private StyleSpan boldStyleSpan; + // `adView` is used in `onCreate()` and `onConfigurationChanged()`. private View adView; @@ -281,12 +292,37 @@ public class MainWebViewActivity extends AppCompatActivity implements Navigation // `mainWebViewRelativeLayout` is used in `onCreate()` and `onNavigationItemSelected()`. private RelativeLayout mainWebViewRelativeLayout; + // `darkTheme` is used in `onCreate()`, `applyAppSettings()`, and `applyDomainSettings()`. + private boolean darkTheme; + @Override // Remove Android Studio's warning about the dangers of using SetJavaScriptEnabled. The whole premise of Privacy Browser is built around an understanding of these dangers. @SuppressLint("SetJavaScriptEnabled") + // Remove Android Studio's warning about deprecations. We have to use the deprecated `getColor()` until API >= 23. + @SuppressWarnings("deprecation") protected void onCreate(Bundle savedInstanceState) { + // Get a handle for `sharedPreferences`. `this` references the current context. + SharedPreferences sharedPreferences = PreferenceManager.getDefaultSharedPreferences(this); + + // Get the theme preference. + darkTheme = sharedPreferences.getBoolean("dark_theme", false); + + // Set the activity theme. + if (darkTheme) { + setTheme(R.style.PrivacyBrowserDark); + } else { + setTheme(R.style.PrivacyBrowserLight); + } + + // Run the default commands. super.onCreate(savedInstanceState); - setContentView(R.layout.main_drawerlayout); + + // Set the content view according to the theme.. + if (darkTheme) { + setContentView(R.layout.main_drawerlayout_dark); + } else { + setContentView(R.layout.main_drawerlayout_light); + } // Get a handle for `inputMethodManager`. inputMethodManager = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE); @@ -303,9 +339,11 @@ public class MainWebViewActivity extends AppCompatActivity implements Navigation appBar.setCustomView(R.layout.url_app_bar); appBar.setDisplayOptions(ActionBar.DISPLAY_SHOW_CUSTOM); - // Create a `ForegroundColorSpan` and `StyleSpan` for formatting of `urlTextBox`. We have to use the deprecated `getColor()` until API >= 23. - @SuppressWarnings("deprecation") final ForegroundColorSpan redColorSpan = new ForegroundColorSpan(getResources().getColor(R.color.red_a700)); - final StyleSpan boldStyleSpan = new StyleSpan(Typeface.BOLD); + // Initialize the `ForegroundColorSpans` and `StyleSpan` for highlighting `urlTextBox`. We have to use the deprecated `getColor()` until API >= 23. + redColorSpan = new ForegroundColorSpan(getResources().getColor(R.color.red_a700)); + initialGrayColorSpan = new ForegroundColorSpan(getResources().getColor(R.color.gray_500)); + finalGrayColorSpan = new ForegroundColorSpan(getResources().getColor(R.color.gray_500)); + boldStyleSpan = new StyleSpan(Typeface.BOLD); // Get a handle for `urlTextBox`. urlTextBox = (EditText) appBar.getCustomView().findViewById(R.id.url_edittext); @@ -315,15 +353,17 @@ public class MainWebViewActivity extends AppCompatActivity implements Navigation @Override public void onFocusChange(View v, boolean hasFocus) { if (hasFocus) { // The user is editing `urlTextBox`. - // Remove the formatting. + // Remove the highlighting. urlTextBox.getText().removeSpan(redColorSpan); + urlTextBox.getText().removeSpan(initialGrayColorSpan); + urlTextBox.getText().removeSpan(finalGrayColorSpan); urlTextBox.getText().removeSpan(boldStyleSpan); } else { // The user has stopped editing `urlTextBox`. - // Highlight connections that are not encrypted. - if (urlTextBox.getText().toString().startsWith("http://")) { - urlTextBox.getText().setSpan(redColorSpan, 0, 7, Spanned.SPAN_INCLUSIVE_INCLUSIVE); - urlTextBox.getText().setSpan(boldStyleSpan, 0, 7, Spanned.SPAN_INCLUSIVE_INCLUSIVE); - } + // Reapply the highlighting. + highlightUrlText(); + + // Scroll to the beginning of the text. + urlTextBox.setScrollX(0); } } }); @@ -576,7 +616,7 @@ public class MainWebViewActivity extends AppCompatActivity implements Navigation navigationForwardMenuItem.setEnabled(mainWebView.canGoForward()); navigationHistoryMenuItem.setEnabled((mainWebView.canGoBack() || mainWebView.canGoForward())); - // Hide the keyboard so we can see the navigation menu. `0` indicates no additional flags. + // Hide the keyboard (if displayed) so we can see the navigation menu. `0` indicates no additional flags. inputMethodManager.hideSoftInputFromWindow(mainWebView.getWindowToken(), 0); // Clear the focus from `urlTextBox` if it has it. @@ -688,17 +728,11 @@ public class MainWebViewActivity extends AppCompatActivity implements Navigation // We need to update `formattedUrlString` at the beginning of the load, so that if the user toggles JavaScript during the load the new website is reloaded. formattedUrlString = url; - // Setup a `formattedUrlStringBuilder` to format the text in `urlTextBox`. - SpannableStringBuilder formattedUrlStringBuilder = new SpannableStringBuilder(formattedUrlString); - - // Highlight connections that are not encrypted. - if (formattedUrlString.startsWith("http://")) { - formattedUrlStringBuilder.setSpan(redColorSpan, 0, 7, Spanned.SPAN_INCLUSIVE_INCLUSIVE); - formattedUrlStringBuilder.setSpan(boldStyleSpan, 0, 7, Spanned.SPAN_INCLUSIVE_INCLUSIVE); - } - // Display the formatted URL text. - urlTextBox.setText(formattedUrlStringBuilder); + urlTextBox.setText(formattedUrlString); + + // Apply text highlighting to `urlTextBox`. + highlightUrlText(); // Apply any custom domain settings if the URL was loaded by navigating history. if (navigatingHistory) { @@ -753,17 +787,11 @@ public class MainWebViewActivity extends AppCompatActivity implements Navigation // Only update `urlTextBox` if the user is not typing in it. if (!urlTextBox.hasFocus()) { - // Setup a `formattedUrlStringBuilder` to format the text in `urlTextBox`. - SpannableStringBuilder formattedUrlStringBuilder = new SpannableStringBuilder(formattedUrlString); - - // Highlight connections that are not encrypted. - if (formattedUrlString.startsWith("http://")) { - formattedUrlStringBuilder.setSpan(redColorSpan, 0, 7, Spanned.SPAN_INCLUSIVE_INCLUSIVE); - formattedUrlStringBuilder.setSpan(boldStyleSpan, 0, 7, Spanned.SPAN_INCLUSIVE_INCLUSIVE); - } - // Display the formatted URL text. - urlTextBox.setText(formattedUrlStringBuilder); + urlTextBox.setText(formattedUrlString); + + // Apply text highlighting to `urlTextBox`. + highlightUrlText(); } } @@ -1077,6 +1105,9 @@ public class MainWebViewActivity extends AppCompatActivity implements Navigation @Override public boolean onPrepareOptionsMenu(Menu menu) { + // Hide the keyboard (if displayed) so we can see the options menu. `0` indicates no additional flags. + inputMethodManager.hideSoftInputFromWindow(mainWebView.getWindowToken(), 0); + // Get handles for the menu items. MenuItem toggleFirstPartyCookiesMenuItem = menu.findItem(R.id.toggle_first_party_cookies); MenuItem toggleThirdPartyCookiesMenuItem = menu.findItem(R.id.toggle_third_party_cookies); @@ -2210,6 +2241,13 @@ public class MainWebViewActivity extends AppCompatActivity implements Navigation // Set the proxy. `this` refers to the current activity where an `AlertDialog` might be displayed. OrbotProxyHelper.setProxy(getApplicationContext(), this, "localhost", "8118"); + // Set the `appBar` background to indicate proxying through Orbot is enabled. `this` refers to the context. + if (darkTheme) { + appBar.setBackgroundDrawable(ContextCompat.getDrawable(this, R.color.dark_blue_30)); + } else { + appBar.setBackgroundDrawable(ContextCompat.getDrawable(this, R.color.blue_50)); + } + // Display a message to the user if we are waiting on Orbot. if (!orbotStatus.equals("ON")) { // Set `waitingForOrbot`. @@ -2237,6 +2275,13 @@ public class MainWebViewActivity extends AppCompatActivity implements Navigation // Reset the proxy to default. The host is `""` and the port is `"0"`. OrbotProxyHelper.setProxy(getApplicationContext(), this, "", "0"); + // Set the default `appBar` background. `this` refers to the context. + if (darkTheme) { + appBar.setBackgroundDrawable(ContextCompat.getDrawable(this, R.color.gray_900)); + } else { + appBar.setBackgroundDrawable(ContextCompat.getDrawable(this, R.color.gray_100)); + } + // Reset `waitingForOrbot. waitingForOrbot = false; } @@ -2436,7 +2481,11 @@ public class MainWebViewActivity extends AppCompatActivity implements Navigation } // Set a green background on `urlTextBox` to indicate that custom domain settings are being used. We have to use the deprecated `.getDrawable()` until the minimum API >= 21. - urlAppBarRelativeLayout.setBackground(getResources().getDrawable(R.drawable.url_bar_background_green)); + if (darkTheme) { + urlAppBarRelativeLayout.setBackground(getResources().getDrawable(R.drawable.url_bar_background_dark_blue)); + } else { + urlAppBarRelativeLayout.setBackground(getResources().getDrawable(R.drawable.url_bar_background_light_green)); + } } else { // The URL we are loading does not have custom domain settings. Load the defaults. // Store the values from `sharedPreferences` in variables. javaScriptEnabled = sharedPreferences.getBoolean("javascript_enabled", false); @@ -2562,4 +2611,23 @@ public class MainWebViewActivity extends AppCompatActivity implements Navigation ActivityCompat.invalidateOptionsMenu(this); } } + + private void highlightUrlText() { + String urlString = urlTextBox.getText().toString(); + + if (urlString.startsWith("http://")) { // Highlight connections that are not encrypted. + urlTextBox.getText().setSpan(redColorSpan, 0, 7, Spanned.SPAN_INCLUSIVE_INCLUSIVE); + urlTextBox.getText().setSpan(boldStyleSpan, 0, 7, Spanned.SPAN_INCLUSIVE_INCLUSIVE); + } else if (urlString.startsWith("https://")) { // Highlight connections that are encrypted. + 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); + } + } }