X-Git-Url: https://gitweb.stoutner.com/?a=blobdiff_plain;f=app%2Fsrc%2Fmain%2Fjava%2Fcom%2Fstoutner%2Fprivacybrowser%2Factivities%2FMainWebViewActivity.java;h=d3951989c25a1cdcaf6c93a3c0578a37767f094d;hb=900dbde5275bc5cda428e6d69d30f664c294b13f;hp=2ca1f0fb52d7d700a62c150a79e79cf873fab57a;hpb=1de1331606f26046a683449d978ef6d7e1cdc3a6;p=PrivacyBrowserAndroid.git 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 2ca1f0fb..d3951989 100644 --- a/app/src/main/java/com/stoutner/privacybrowser/activities/MainWebViewActivity.java +++ b/app/src/main/java/com/stoutner/privacybrowser/activities/MainWebViewActivity.java @@ -107,6 +107,7 @@ import java.io.InputStreamReader; import java.io.UnsupportedEncodingException; import java.net.MalformedURLException; import java.net.URL; +import java.net.URLDecoder; import java.net.URLEncoder; import java.util.HashMap; import java.util.HashSet; @@ -209,7 +210,7 @@ public class MainWebViewActivity extends AppCompatActivity implements Navigation // `proxyThroughOrbot` is used in `onCreate()` and `applySettings()` private boolean proxyThroughOrbot; - // `currentDomain` is used in `onCreate() and `applyDomainSettings()`. + // `currentDomain` is used in `onCreate(), `onNavigationItemSelected()`, and `applyDomainSettings()`. private String currentDomain; // `pendingUrl` is used in `onCreate()` and `applySettings()` @@ -253,7 +254,7 @@ public class MainWebViewActivity extends AppCompatActivity implements Navigation @SuppressLint("SetJavaScriptEnabled") protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); - setContentView(R.layout.drawerlayout); + setContentView(R.layout.main_drawerlayout); // Get a handle for `inputMethodManager`. inputMethodManager = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE); @@ -266,12 +267,12 @@ public class MainWebViewActivity extends AppCompatActivity implements Navigation // This is needed to get rid of the Android Studio warning that `appBar` might be null. assert appBar != null; - // Add the custom url_app_bar layout, which shows the favoriteIcon, urlTextBar, and progressBar. + // Add the custom `url_app_bar` layout, which shows the favorite icon and the URL text bar. appBar.setCustomView(R.layout.url_app_bar); appBar.setDisplayOptions(ActionBar.DISPLAY_SHOW_CUSTOM); // Set the "go" button on the keyboard to load the URL in urlTextBox. - urlTextBox = (EditText) appBar.getCustomView().findViewById(R.id.urlTextBox); + urlTextBox = (EditText) appBar.getCustomView().findViewById(R.id.url_edittext); urlTextBox.setOnKeyListener(new View.OnKeyListener() { @Override public boolean onKey(View v, int keyCode, KeyEvent event) { @@ -334,7 +335,7 @@ public class MainWebViewActivity extends AppCompatActivity implements Navigation drawerLayout = (DrawerLayout) findViewById(R.id.drawerlayout); rootCoordinatorLayout = (CoordinatorLayout) findViewById(R.id.root_coordinatorlayout); mainWebViewRelativeLayout = (RelativeLayout) findViewById(R.id.main_webview_relativelayout); - mainWebView = (WebView) findViewById(R.id.mainWebView); + mainWebView = (WebView) findViewById(R.id.main_webview); findOnPageLinearLayout = (LinearLayout) findViewById(R.id.find_on_page_linearlayout); findOnPageEditText = (EditText) findViewById(R.id.find_on_page_edittext); fullScreenVideoFrameLayout = (FrameLayout) findViewById(R.id.full_screen_video_framelayout); @@ -392,7 +393,7 @@ public class MainWebViewActivity extends AppCompatActivity implements Navigation BannerAd.reloadAfterRotate(adView, getApplicationContext(), getString(R.string.ad_id)); // Reinitialize the `adView` variable, as the `View` will have been removed and re-added by `BannerAd.reloadAfterRotate()`. - adView = findViewById(R.id.adView); + adView = findViewById(R.id.adview); } // Remove the translucent navigation bar flag if it is set. @@ -482,7 +483,7 @@ public class MainWebViewActivity extends AppCompatActivity implements Navigation }); // Implement swipe to refresh - swipeRefreshLayout = (SwipeRefreshLayout) findViewById(R.id.swipeRefreshLayout); + swipeRefreshLayout = (SwipeRefreshLayout) findViewById(R.id.swipe_refreshlayout); swipeRefreshLayout.setColorSchemeResources(R.color.blue_700); swipeRefreshLayout.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() { @Override @@ -520,13 +521,15 @@ public class MainWebViewActivity extends AppCompatActivity implements Navigation @Override public void onDrawerStateChanged(int newState) { - // Update the `Back`, `Forward`, and `History` menu items every time the drawer opens. - navigationBackMenuItem.setEnabled(mainWebView.canGoBack()); - navigationForwardMenuItem.setEnabled(mainWebView.canGoForward()); - navigationHistoryMenuItem.setEnabled((mainWebView.canGoBack() || mainWebView.canGoForward())); + if ((newState == DrawerLayout.STATE_SETTLING) || (newState == DrawerLayout.STATE_DRAGGING)) { // The drawer is opening or closing. + // Update the `Back`, `Forward`, and `History` menu items. + navigationBackMenuItem.setEnabled(mainWebView.canGoBack()); + 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. - inputMethodManager.hideSoftInputFromWindow(mainWebView.getWindowToken(), 0); + // Hide the keyboard so we can see the navigation menu. `0` indicates no additional flags. + inputMethodManager.hideSoftInputFromWindow(mainWebView.getWindowToken(), 0); + } } }); @@ -641,11 +644,27 @@ public class MainWebViewActivity extends AppCompatActivity implements Navigation public void onPageFinished(WebView view, String url) { // Check to see if we are waiting on Orbot. if (pendingUrl.isEmpty()) { // we are not waiting on Orbot, so we need to process the URL. - formattedUrlString = url; + // Check to see if `WebView` has set `url` to be `about:blank`. + if (url.equals("about:blank")) { // `WebView` is blank, so `formattedUrlString` should be `""` and `urlTextBox` should display a hint. + // Set `formattedUrlString` to `""`. + formattedUrlString = ""; - // Only update urlTextBox if the user is not typing in it. - if (!urlTextBox.hasFocus()) { + // Update `urlTextBox`. urlTextBox.setText(formattedUrlString); + + // Request focus for `urlTextBox`. + urlTextBox.requestFocus(); + + // Display the keyboard. + inputMethodManager.showSoftInput(urlTextBox, 0); + } else { // `WebView` has loaded a webpage. + // Set `formattedUrlString`. + formattedUrlString = url; + + // Only update `urlTextBox` if the user is not typing in it. + if (!urlTextBox.hasFocus()) { + urlTextBox.setText(formattedUrlString); + } } // Store the SSL certificate so it can be accessed from `ViewSslCertificateDialog`. @@ -665,11 +684,13 @@ public class MainWebViewActivity extends AppCompatActivity implements Navigation } }); + // Get a handle for the progress bar. + final ProgressBar progressBar = (ProgressBar) findViewById(R.id.progress_bar); + mainWebView.setWebChromeClient(new WebChromeClient() { // Update the progress bar when a page is loading. @Override public void onProgressChanged(WebView view, int progress) { - ProgressBar progressBar = (ProgressBar) appBar.getCustomView().findViewById(R.id.progressBar); progressBar.setProgress(progress); if (progress < 100) { progressBar.setVisibility(View.VISIBLE); @@ -688,7 +709,7 @@ public class MainWebViewActivity extends AppCompatActivity implements Navigation favoriteIcon = icon; // Place the favorite icon in the appBar. - ImageView imageViewFavoriteIcon = (ImageView) appBar.getCustomView().findViewById(R.id.favoriteIcon); + ImageView imageViewFavoriteIcon = (ImageView) appBar.getCustomView().findViewById(R.id.favorite_icon); imageViewFavoriteIcon.setImageBitmap(Bitmap.createScaledBitmap(icon, 64, 64, true)); } @@ -745,7 +766,7 @@ public class MainWebViewActivity extends AppCompatActivity implements Navigation BannerAd.reloadAfterRotate(adView, getApplicationContext(), getString(R.string.ad_id)); // Reinitialize the `adView` variable, as the `View` will have been removed and re-added by `BannerAd.reloadAfterRotate()`. - adView = findViewById(R.id.adView); + adView = findViewById(R.id.adview); } } }); @@ -793,7 +814,7 @@ public class MainWebViewActivity extends AppCompatActivity implements Navigation inFullScreenBrowsingMode = false; // Initialize AdView for the free flavor. - adView = findViewById(R.id.adView); + adView = findViewById(R.id.adview); // Initialize the privacy settings variables. javaScriptEnabled = false; @@ -995,11 +1016,11 @@ public class MainWebViewActivity extends AppCompatActivity implements Navigation // Display a `Snackbar`. if (javaScriptEnabled) { // JavaScrip is enabled. - Snackbar.make(findViewById(R.id.mainWebView), R.string.javascript_enabled, Snackbar.LENGTH_SHORT).show(); + Snackbar.make(findViewById(R.id.main_webview), R.string.javascript_enabled, Snackbar.LENGTH_SHORT).show(); } else if (firstPartyCookiesEnabled) { // JavaScript is disabled, but first-party cookies are enabled. - Snackbar.make(findViewById(R.id.mainWebView), R.string.javascript_disabled, Snackbar.LENGTH_SHORT).show(); + Snackbar.make(findViewById(R.id.main_webview), R.string.javascript_disabled, Snackbar.LENGTH_SHORT).show(); } else { // Privacy mode. - Snackbar.make(findViewById(R.id.mainWebView), R.string.privacy_mode, Snackbar.LENGTH_SHORT).show(); + Snackbar.make(findViewById(R.id.main_webview), R.string.privacy_mode, Snackbar.LENGTH_SHORT).show(); } // Reload the WebView. @@ -1021,11 +1042,11 @@ public class MainWebViewActivity extends AppCompatActivity implements Navigation // Display a `Snackbar`. if (firstPartyCookiesEnabled) { // First-party cookies are enabled. - Snackbar.make(findViewById(R.id.mainWebView), R.string.first_party_cookies_enabled, Snackbar.LENGTH_SHORT).show(); + Snackbar.make(findViewById(R.id.main_webview), R.string.first_party_cookies_enabled, Snackbar.LENGTH_SHORT).show(); } else if (javaScriptEnabled){ // JavaScript is still enabled. - Snackbar.make(findViewById(R.id.mainWebView), R.string.first_party_cookies_disabled, Snackbar.LENGTH_SHORT).show(); + Snackbar.make(findViewById(R.id.main_webview), R.string.first_party_cookies_disabled, Snackbar.LENGTH_SHORT).show(); } else { // Privacy mode. - Snackbar.make(findViewById(R.id.mainWebView), R.string.privacy_mode, Snackbar.LENGTH_SHORT).show(); + Snackbar.make(findViewById(R.id.main_webview), R.string.privacy_mode, Snackbar.LENGTH_SHORT).show(); } // Reload the WebView. @@ -1045,9 +1066,9 @@ public class MainWebViewActivity extends AppCompatActivity implements Navigation // Display a `Snackbar`. if (thirdPartyCookiesEnabled) { - Snackbar.make(findViewById(R.id.mainWebView), R.string.third_party_cookies_enabled, Snackbar.LENGTH_SHORT).show(); + Snackbar.make(findViewById(R.id.main_webview), R.string.third_party_cookies_enabled, Snackbar.LENGTH_SHORT).show(); } else { - Snackbar.make(findViewById(R.id.mainWebView), R.string.third_party_cookies_disabled, Snackbar.LENGTH_SHORT).show(); + Snackbar.make(findViewById(R.id.main_webview), R.string.third_party_cookies_disabled, Snackbar.LENGTH_SHORT).show(); } // Reload the WebView. @@ -1070,9 +1091,9 @@ public class MainWebViewActivity extends AppCompatActivity implements Navigation // Display a `Snackbar`. if (domStorageEnabled) { - Snackbar.make(findViewById(R.id.mainWebView), R.string.dom_storage_enabled, Snackbar.LENGTH_SHORT).show(); + Snackbar.make(findViewById(R.id.main_webview), R.string.dom_storage_enabled, Snackbar.LENGTH_SHORT).show(); } else { - Snackbar.make(findViewById(R.id.mainWebView), R.string.dom_storage_disabled, Snackbar.LENGTH_SHORT).show(); + Snackbar.make(findViewById(R.id.main_webview), R.string.dom_storage_disabled, Snackbar.LENGTH_SHORT).show(); } // Reload the WebView. @@ -1091,9 +1112,9 @@ public class MainWebViewActivity extends AppCompatActivity implements Navigation // Display a `Snackbar`. if (saveFormDataEnabled) { - Snackbar.make(findViewById(R.id.mainWebView), R.string.form_data_enabled, Snackbar.LENGTH_SHORT).show(); + Snackbar.make(findViewById(R.id.main_webview), R.string.form_data_enabled, Snackbar.LENGTH_SHORT).show(); } else { - Snackbar.make(findViewById(R.id.mainWebView), R.string.form_data_disabled, Snackbar.LENGTH_SHORT).show(); + Snackbar.make(findViewById(R.id.main_webview), R.string.form_data_disabled, Snackbar.LENGTH_SHORT).show(); } // Update the privacy icon. `true` runs `invalidateOptionsMenu` as the last step. @@ -1109,19 +1130,19 @@ public class MainWebViewActivity extends AppCompatActivity implements Navigation } else { cookieManager.removeAllCookies(null); } - Snackbar.make(findViewById(R.id.mainWebView), R.string.cookies_deleted, Snackbar.LENGTH_SHORT).show(); + Snackbar.make(findViewById(R.id.main_webview), R.string.cookies_deleted, Snackbar.LENGTH_SHORT).show(); return true; case R.id.clearDomStorage: WebStorage webStorage = WebStorage.getInstance(); webStorage.deleteAllData(); - Snackbar.make(findViewById(R.id.mainWebView), R.string.dom_storage_deleted, Snackbar.LENGTH_SHORT).show(); + Snackbar.make(findViewById(R.id.main_webview), R.string.dom_storage_deleted, Snackbar.LENGTH_SHORT).show(); return true; case R.id.clearFormData: WebViewDatabase mainWebViewDatabase = WebViewDatabase.getInstance(this); mainWebViewDatabase.clearFormData(); - Snackbar.make(findViewById(R.id.mainWebView), R.string.form_data_deleted, Snackbar.LENGTH_SHORT).show(); + Snackbar.make(findViewById(R.id.main_webview), R.string.form_data_deleted, Snackbar.LENGTH_SHORT).show(); return true; case R.id.fontSizeFiftyPercent: @@ -1269,12 +1290,18 @@ public class MainWebViewActivity extends AppCompatActivity implements Navigation break; case R.id.settings: + // Reset `currentDomain` so that domain settings are reapplied after returning to `MainWebViewActivity`. + currentDomain = ""; + // Launch `SettingsActivity`. Intent settingsIntent = new Intent(this, SettingsActivity.class); startActivity(settingsIntent); break; case R.id.domains: + // Reset `currentDomain` so that domain settings are reapplied after returning to `MainWebViewActivity`. + currentDomain = ""; + // Launch `DomainsActivity`. Intent domainsIntent = new Intent(this, DomainsActivity.class); startActivity(domainsIntent); @@ -1376,7 +1403,7 @@ public class MainWebViewActivity extends AppCompatActivity implements Navigation BannerAd.reloadAfterRotate(adView, getApplicationContext(), getString(R.string.ad_id)); // Reinitialize the `adView` variable, as the `View` will have been removed and re-added by `BannerAd.reloadAfterRotate()`. - adView = findViewById(R.id.adView); + adView = findViewById(R.id.adview); } // `invalidateOptionsMenu` should recalculate the number of action buttons from the menu to display on the app bar, but it doesn't because of the this bug: https://code.google.com/p/android/issues/detail?id=20493#c8 @@ -1778,9 +1805,6 @@ public class MainWebViewActivity extends AppCompatActivity implements Navigation // Get the text from urlTextBox and convert it to a string. trim() removes white spaces from the beginning and end of the string. String unformattedUrlString = urlTextBox.getText().toString().trim(); - URL unformattedUrl = null; - Uri.Builder formattedUri = new Uri.Builder(); - // Check to see if unformattedUrlString is a valid URL. Otherwise, convert it into a Duck Duck Go search. if (Patterns.WEB_URL.matcher(unformattedUrlString).matches()) { // Add http:// at the beginning if it is missing. Otherwise the app will segfault. @@ -1788,6 +1812,9 @@ public class MainWebViewActivity extends AppCompatActivity implements Navigation unformattedUrlString = "http://" + unformattedUrlString; } + // Initialize `unformattedUrl`. + URL unformattedUrl = null; + // Convert unformattedUrlString to a URL, then to a URI, and then back to a string, which sanitizes the input and adds in any missing components. try { unformattedUrl = new URL(unformattedUrlString); @@ -1795,17 +1822,21 @@ public class MainWebViewActivity extends AppCompatActivity implements Navigation e.printStackTrace(); } - // The ternary operator (? :) makes sure that a null pointer exception is not thrown, which would happen if .get was called on a null value. + // The ternary operator (? :) makes sure that a null pointer exception is not thrown, which would happen if `.get` was called on a `null` value. final String scheme = unformattedUrl != null ? unformattedUrl.getProtocol() : null; final String authority = unformattedUrl != null ? unformattedUrl.getAuthority() : null; final String path = unformattedUrl != null ? unformattedUrl.getPath() : null; final String query = unformattedUrl != null ? unformattedUrl.getQuery() : null; final String fragment = unformattedUrl != null ? unformattedUrl.getRef() : null; + // Build the URI. + Uri.Builder formattedUri = new Uri.Builder(); formattedUri.scheme(scheme).authority(authority).path(path).query(query).fragment(fragment); - formattedUrlString = formattedUri.build().toString(); + + // Decode `formattedUri` as a `String` in `UTF-8`. + formattedUrlString = URLDecoder.decode(formattedUri.build().toString(), "UTF-8"); } else { - // Sanitize the search input and convert it to a DuckDuckGo search. + // Sanitize the search input and convert it to a search. final String encodedUrlString = URLEncoder.encode(unformattedUrlString, "UTF-8"); // Use the correct search URL. @@ -1841,7 +1872,7 @@ public class MainWebViewActivity extends AppCompatActivity implements Navigation String hostname = uri.getHost(); // Only apply the domain settings if `hostname` is not the same as `currentDomain`. This allows the user to set temporary settings for JavaScript, Cookies, DOM Storage, etc. - if (!hostname.equals(currentDomain)) { + if (hostname != null && !hostname.equals(currentDomain)) { // Set the new `hostname` as the `currentDomain`. currentDomain = hostname; @@ -1891,7 +1922,7 @@ public class MainWebViewActivity extends AppCompatActivity implements Navigation hostname = hostname.substring(hostname.indexOf(".") + 1); } - FrameLayout urlAppBarFrameLayout = (FrameLayout) findViewById(R.id.url_app_bar_framelayout); + RelativeLayout urlAppBarRelativeLayout = (RelativeLayout) findViewById(R.id.url_app_bar_relativelayout); if (hostHasDomainSettings) { // The url we are loading has custom domain settings. // Get a cursor for the current host and move it to the first position. @@ -1932,7 +1963,7 @@ 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. - urlAppBarFrameLayout.setBackground(getResources().getDrawable(R.drawable.url_bar_background_green)); + urlAppBarRelativeLayout.setBackground(getResources().getDrawable(R.drawable.url_bar_background_green)); } else { // The URL we are loading does not have custom domain settings. Load the defaults. // Get the shared preference values. `this` references the current context. SharedPreferences sharedPreferences = PreferenceManager.getDefaultSharedPreferences(this); @@ -1978,7 +2009,7 @@ public class MainWebViewActivity extends AppCompatActivity implements Navigation } // Set a transparent background on `urlTextBox`. We have to use the deprecated `.getDrawable()` until the minimum API >= 21. - urlAppBarFrameLayout.setBackgroundDrawable(getResources().getDrawable(R.drawable.url_bar_background_transparent)); + urlAppBarRelativeLayout.setBackgroundDrawable(getResources().getDrawable(R.drawable.url_bar_background_transparent)); } // Close `domainsDatabaseHelper`. @@ -2161,7 +2192,7 @@ public class MainWebViewActivity extends AppCompatActivity implements Navigation BannerAd.reloadAfterRotate(adView, getApplicationContext(), getString(R.string.ad_id)); // Reinitialize the `adView` variable, as the `View` will have been removed and re-added by `BannerAd.reloadAfterRotate()`. - adView = findViewById(R.id.adView); + adView = findViewById(R.id.adview); } // Remove the translucent navigation bar flag if it is set.