X-Git-Url: https://gitweb.stoutner.com/?a=blobdiff_plain;f=app%2Fsrc%2Fmain%2Fjava%2Fcom%2Fstoutner%2Fprivacybrowser%2Factivities%2FMainWebView.java;h=000cfad6e5899b85dd7b470fb0409ba94cd8cfab;hb=c3ec2515bf9a49d4561efc47f5d21106f15cb286;hp=e5296732f487000d0e380aac68531241b9d3ec12;hpb=743982f883eab347e4029f8a3be760f780b14da1;p=PrivacyBrowserAndroid.git diff --git a/app/src/main/java/com/stoutner/privacybrowser/activities/MainWebView.java b/app/src/main/java/com/stoutner/privacybrowser/activities/MainWebView.java index e5296732..000cfad6 100644 --- a/app/src/main/java/com/stoutner/privacybrowser/activities/MainWebView.java +++ b/app/src/main/java/com/stoutner/privacybrowser/activities/MainWebView.java @@ -70,6 +70,7 @@ import android.webkit.DownloadListener; import android.webkit.SslErrorHandler; import android.webkit.WebBackForwardList; import android.webkit.WebChromeClient; +import android.webkit.WebResourceResponse; import android.webkit.WebStorage; import android.webkit.WebView; import android.webkit.WebViewClient; @@ -93,19 +94,25 @@ import com.stoutner.privacybrowser.dialogs.SslCertificateError; import com.stoutner.privacybrowser.dialogs.UrlHistory; import com.stoutner.privacybrowser.dialogs.ViewSslCertificate; +import java.io.BufferedReader; +import java.io.ByteArrayInputStream; +import java.io.IOException; +import java.io.InputStreamReader; import java.io.UnsupportedEncodingException; import java.net.MalformedURLException; import java.net.URL; import java.net.URLEncoder; import java.util.HashMap; +import java.util.HashSet; import java.util.Map; +import java.util.Set; // We need to use AppCompatActivity from android.support.v7.app.AppCompatActivity to have access to the SupportActionBar until the minimum API is >= 21. public class MainWebView extends AppCompatActivity implements NavigationView.OnNavigationItemSelectedListener, CreateHomeScreenShortcut.CreateHomeScreenSchortcutListener, SslCertificateError.SslCertificateErrorListener, DownloadFile.DownloadFileListener, DownloadImage.DownloadImageListener, UrlHistory.UrlHistoryListener { // `appBar` is public static so it can be accessed from `OrbotProxyHelper`. - // It is also used in `onCreate()`, `onOptionsItemSelected()`, and `closeFindOnPage()`. + // It is also used in `onCreate()`, `onOptionsItemSelected()`, `closeFindOnPage()`, and `applySettings()`. public static ActionBar appBar; // `favoriteIcon` is public static so it can be accessed from `CreateHomeScreenShortcut`, `Bookmarks`, `CreateBookmark`, `CreateBookmarkFolder`, and `EditBookmark`. @@ -130,9 +137,6 @@ public class MainWebView extends AppCompatActivity implements NavigationView.OnN // 'mainWebView' is used in `onCreate()`, `onOptionsItemSelected()`, `onNavigationItemSelected()`, `onRestart()`, `onCreateContextMenu()`, `findPreviousOnPage()`, `findNextOnPage()`, `closeFindOnPage()`, and `loadUrlFromTextBox()`. private WebView mainWebView; - // `findOnPageEditText` is used in `onCreate()`, `onOptionsItemSelected()`, and `closeFindOnPage()`. - private EditText findOnPageEditText; - // `fullScreenVideoFrameLayout` is used in `onCreate()` and `onConfigurationChanged()`. private FrameLayout fullScreenVideoFrameLayout; @@ -173,21 +177,36 @@ public class MainWebView extends AppCompatActivity implements NavigationView.OnN // `javaScriptEnabledSearchURL` is used in `loadURLFromTextBox()` and `applySettings()`. private String javaScriptEnabledSearchURL; + // `adBlockerEnabled` is used in `onCreate()` and `applySettings()`. + private boolean adBlockerEnabled; + // `fullScreenBrowsingModeEnabled` is used in `onCreate()` and `applySettings()`. private boolean fullScreenBrowsingModeEnabled; + // `inFullScreenBrowsingMode` is used in `onCreate()` and `applySettings()`. + private boolean inFullScreenBrowsingMode; + // `hideSystemBarsOnFullscreen` is used in `onCreate()` and `applySettings()`. private boolean hideSystemBarsOnFullscreen; // `translucentNavigationBarOnFullscreen` is used in `onCreate()` and `applySettings()`. private boolean translucentNavigationBarOnFullscreen; + // `findOnPageLinearLayout` is used in `onCreate()`, `onOptionsItemSelected()`, and `closeFindOnPage()`. + private LinearLayout findOnPageLinearLayout; + + // `findOnPageEditText` is used in `onCreate()`, `onOptionsItemSelected()`, and `closeFindOnPage()`. + private EditText findOnPageEditText; + // `mainMenu` is used in `onCreateOptionsMenu()` and `updatePrivacyIcons()`. private Menu mainMenu; // `drawerToggle` is used in `onCreate()`, `onPostCreate()`, `onConfigurationChanged()`, `onNewIntent()`, and `onNavigationItemSelected()`. private ActionBarDrawerToggle drawerToggle; + // `supportAppBar` is used in `onCreate()`, `onOptionsItemSelected()`, and `closeFindOnPage()`. + private Toolbar supportAppBar; + // `urlTextBox` is used in `onCreate()`, `onOptionsItemSelected()`, and `loadUrlFromTextBox()`. private EditText urlTextBox; @@ -200,6 +219,9 @@ public class MainWebView extends AppCompatActivity implements NavigationView.OnN // `inputMethodManager` is used in `onOptionsItemSelected()`, `loadUrlFromTextBox()`, and `closeFindOnPage()`. private InputMethodManager inputMethodManager; + // `mainWebViewRelativeLayout` is used in `onCreate()` and `onNavigationItemSelected()`. + private RelativeLayout mainWebViewRelativeLayout; + @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") @@ -211,7 +233,7 @@ public class MainWebView extends AppCompatActivity implements NavigationView.OnN inputMethodManager = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE); // We need to use the `SupportActionBar` from `android.support.v7.app.ActionBar` until the minimum API is >= 21. - Toolbar supportAppBar = (Toolbar) findViewById(R.id.app_bar); + supportAppBar = (Toolbar) findViewById(R.id.app_bar); setSupportActionBar(supportAppBar); appBar = getSupportActionBar(); @@ -247,7 +269,9 @@ public class MainWebView extends AppCompatActivity implements NavigationView.OnN // Get handles for views that need to be accessed. 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); + 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); @@ -257,7 +281,10 @@ public class MainWebView extends AppCompatActivity implements NavigationView.OnN @Override public boolean onDoubleTap(MotionEvent event) { if (fullScreenBrowsingModeEnabled) { // Only process the double-tap if full screen browsing mode is enabled. - if (appBar.isShowing()) { // If `appBar` is visible, switch to full screen mode. + // Toggle `inFullScreenBrowsingMode`. + inFullScreenBrowsingMode = !inFullScreenBrowsingMode; + + if (inFullScreenBrowsingMode) { // Switch to full screen mode. // Hide the `appBar`. appBar.hide(); @@ -274,10 +301,10 @@ public class MainWebView extends AppCompatActivity implements NavigationView.OnN // Remove the translucent status bar overlay on the `Drawer Layout`, which is special and needs its own command. drawerLayout.setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN); - /* SYSTEM_UI_FLAG_FULLSCREEN hides the status bar at the top of the screen. - * SYSTEM_UI_FLAG_HIDE_NAVIGATION hides the navigation bar on the bottom or right of the screen. - * SYSTEM_UI_FLAG_IMMERSIVE_STICKY makes the status and navigation bars translucent and automatically rehides them after they are shown. - */ + /* SYSTEM_UI_FLAG_FULLSCREEN hides the status bar at the top of the screen. + * SYSTEM_UI_FLAG_HIDE_NAVIGATION hides the navigation bar on the bottom or right of the screen. + * SYSTEM_UI_FLAG_IMMERSIVE_STICKY makes the status and navigation bars translucent and automatically rehides them after they are shown. + */ rootCoordinatorLayout.setSystemUiVisibility(View.SYSTEM_UI_FLAG_FULLSCREEN | View.SYSTEM_UI_FLAG_HIDE_NAVIGATION | View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY); // Set `rootCoordinatorLayout` to fill the whole screen. @@ -442,6 +469,28 @@ public class MainWebView extends AppCompatActivity implements NavigationView.OnN // drawerToggle creates the hamburger icon at the start of the AppBar. drawerToggle = new ActionBarDrawerToggle(this, drawerLayout, supportAppBar, R.string.open_navigation_drawer, R.string.close_navigation_drawer); + // Initialize `adServerSet`. + final Set adServersSet = new HashSet<>(); + + // Load the list of ad servers into memory. + try { + // Load `pgl.yoyo.org_adservers.txt` into a `BufferedReader`. + BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(getAssets().open("pgl.yoyo.org_adservers.txt"))); + + // Create a string for storing each ad server. + String adServer; + + // Populate `adServersSet`. + while ((adServer = bufferedReader.readLine()) != null) { + adServersSet.add(adServer); + } + + // Close `bufferedReader`. + bufferedReader.close(); + } catch (IOException ioException) { + // We're pretty sure the asset exists, so we don't need to worry about the `IOException` ever being thrown. + } + mainWebView.setWebViewClient(new WebViewClient() { // `shouldOverrideUrlLoading` makes this `WebView` the default handler for URLs inside the app, so that links are not kicked out to other apps. // We have to use the deprecated `shouldOverrideUrlLoading` until API >= 24. @@ -468,6 +517,41 @@ public class MainWebView extends AppCompatActivity implements NavigationView.OnN } } + // Block ads. We have to use the deprecated `shouldInterceptRequest` until minimum API >= 21. + @SuppressWarnings("deprecation") + @Override + public WebResourceResponse shouldInterceptRequest(WebView view, String url){ + if (adBlockerEnabled) { // Block ads. + // Extract the host from `url`. + Uri requestUri = Uri.parse(url); + String requestHost = requestUri.getHost(); + + // Create a variable to track if this is an ad server. + boolean requestHostIsAdServer = false; + + // Check all the subdomains of `requestHost`. + while (requestHost.contains(".")) { + if (adServersSet.contains(requestHost)) { + requestHostIsAdServer = true; + } + + // Strip out the lowest subdomain of `requestHost`. + requestHost = requestHost.substring(requestHost.indexOf(".") + 1); + } + + if (requestHostIsAdServer) { // It is an ad server. + // Return an empty `WebResourceResponse`. + return new WebResourceResponse("text/plain", "utf8", new ByteArrayInputStream("".getBytes())); + } else { // It is not an ad server. + // `return null` loads the requested resource. + return null; + } + } else { // Ad blocking is disabled. + // `return null` loads the requested resource. + return null; + } + } + // Update the URL in urlTextBox when the page starts to load. @Override public void onPageStarted(WebView view, String url, Bitmap favicon) { @@ -638,6 +722,9 @@ public class MainWebView extends AppCompatActivity implements NavigationView.OnN favoriteIcon = favoriteIconBitmapDrawable.getBitmap(); } + // Initialize `inFullScreenBrowsingMode`, which is always false at this point because Privacy Browser never starts in full screen browsing mode. + inFullScreenBrowsingMode = false; + // Initialize AdView for the free flavor and request an ad. If this is not the free flavor BannerAd.requestAd() does nothing. adView = findViewById(R.id.adView); BannerAd.requestAd(adView); @@ -978,11 +1065,9 @@ public class MainWebView extends AppCompatActivity implements NavigationView.OnN case R.id.find_on_page: // Hide the URL app bar. - Toolbar appBarToolbar = (Toolbar) findViewById(R.id.app_bar); - appBarToolbar.setVisibility(View.GONE); + supportAppBar.setVisibility(View.GONE); // Show the Find on Page `RelativeLayout`. - LinearLayout findOnPageLinearLayout = (LinearLayout) findViewById(R.id.find_on_page_linearlayout); findOnPageLinearLayout.setVisibility(View.VISIBLE); // Display the keyboard. We have to wait 200 ms before running the command to work around a bug in Android. @@ -1136,7 +1221,6 @@ public class MainWebView extends AppCompatActivity implements NavigationView.OnN customHeaders.clear(); // Detach all views from `mainWebViewRelativeLayout`. - RelativeLayout mainWebViewRelativeLayout = (RelativeLayout) findViewById(R.id.mainWebViewRelativeLayout); mainWebViewRelativeLayout.removeAllViews(); // Destroy the internal state of `mainWebView`. @@ -1608,12 +1692,10 @@ public class MainWebView extends AppCompatActivity implements NavigationView.OnN mainWebView.clearMatches(); // Hide the Find on Page `RelativeLayout`. - LinearLayout findOnPageLinearLayout = (LinearLayout) findViewById(R.id.find_on_page_linearlayout); findOnPageLinearLayout.setVisibility(View.GONE); // Show the URL app bar. - Toolbar appBarToolbar = (Toolbar) findViewById(R.id.app_bar); - appBarToolbar.setVisibility(View.VISIBLE); + supportAppBar.setVisibility(View.VISIBLE); // Hide the keyboard so we can see the webpage. `0` indicates no additional flags. inputMethodManager.hideSoftInputFromWindow(mainWebView.getWindowToken(), 0); @@ -1633,7 +1715,8 @@ public class MainWebView extends AppCompatActivity implements NavigationView.OnN String homepageString = sharedPreferences.getString("homepage", "https://www.duckduckgo.com"); String defaultFontSizeString = sharedPreferences.getString("default_font_size", "100"); swipeToRefreshEnabled = sharedPreferences.getBoolean("swipe_to_refresh_enabled", false); - boolean doNotTrackEnabled = sharedPreferences.getBoolean("do_not_track", true); + adBlockerEnabled = sharedPreferences.getBoolean("block_ads", true); + boolean doNotTrackEnabled = sharedPreferences.getBoolean("do_not_track", false); boolean proxyThroughOrbot = sharedPreferences.getBoolean("proxy_through_orbot", false); fullScreenBrowsingModeEnabled = sharedPreferences.getBoolean("enable_full_screen_browsing_mode", false); hideSystemBarsOnFullscreen = sharedPreferences.getBoolean("hide_system_bars", false); @@ -1713,7 +1796,7 @@ public class MainWebView extends AppCompatActivity implements NavigationView.OnN } // If we are in full screen mode update the `SYSTEM_UI` flags. - if (!appBar.isShowing()) { + if (inFullScreenBrowsingMode) { if (hideSystemBarsOnFullscreen) { // Hide everything. // Remove the translucent navigation setting if it is currently flagged. getWindow().clearFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION);