/**
- * Copyright 2015-2016 Soren Stoutner <soren@stoutner.com>.
+ * Copyright 2015-2017 Soren Stoutner <soren@stoutner.com>.
*
* This file is part of Privacy Browser <https://www.stoutner.com/privacy-browser>.
*
import android.annotation.SuppressLint;
import android.app.DialogFragment;
import android.app.DownloadManager;
+import android.content.ClipData;
+import android.content.ClipboardManager;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
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;
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`.
public static SslCertificate sslCertificate;
-
// `drawerLayout` is used in `onCreate()`, `onNewIntent()`, and `onBackPressed()`.
private DrawerLayout drawerLayout;
// 'mainWebView' is used in `onCreate()`, `onOptionsItemSelected()`, `onNavigationItemSelected()`, `onRestart()`, `onCreateContextMenu()`, `findPreviousOnPage()`, `findNextOnPage()`, `closeFindOnPage()`, and `loadUrlFromTextBox()`.
private WebView mainWebView;
+ // `fullScreenVideoFrameLayout` is used in `onCreate()` and `onConfigurationChanged()`.
+ private FrameLayout fullScreenVideoFrameLayout;
+
// `swipeRefreshLayout` is used in `onCreate()`, `onPrepareOptionsMenu`, and `onRestart()`.
private SwipeRefreshLayout swipeRefreshLayout;
// `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;
// `sslErrorHandler` is used in `onCreate()`, `onSslErrorCancel()`, and `onSslErrorProceed`.
private SslErrorHandler sslErrorHandler;
- // `findOnPageEditText` is used in `onCreate()`, `onOptionsItemSelected()`, and `closeFindOnPage()`.
- private EditText findOnPageEditText;
-
// `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")
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();
// 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);
- final FrameLayout fullScreenVideoFrameLayout = (FrameLayout) findViewById(R.id.full_screen_video_framelayout);
+ fullScreenVideoFrameLayout = (FrameLayout) findViewById(R.id.full_screen_video_framelayout);
// Create a double-tap listener to toggle full-screen mode.
final GestureDetector gestureDetector = new GestureDetector(this, new GestureDetector.SimpleOnGestureListener() {
// Override `onDoubleTap()`. All other events are handled using the default settings.
@Override
public boolean onDoubleTap(MotionEvent event) {
- if (appBar.isShowing()) { // If `appBar` is visible, switch to full screen mode.
- // Hide the `appBar`.
- appBar.hide();
+ if (fullScreenBrowsingModeEnabled) { // Only process the double-tap if full screen browsing mode is enabled.
+ // Toggle `inFullScreenBrowsingMode`.
+ inFullScreenBrowsingMode = !inFullScreenBrowsingMode;
- // Hide the `BannerAd` in the free flavor.
- if (BuildConfig.FLAVOR.contentEquals("free")) {
- BannerAd.hideAd(adView);
- }
+ if (inFullScreenBrowsingMode) { // Switch to full screen mode.
+ // Hide the `appBar`.
+ appBar.hide();
- // Modify the system bars.
- if (hideSystemBarsOnFullscreen) { // Hide everything.
- // Remove the translucent overlays.
- getWindow().clearFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
-
- // 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.
- */
- 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.
- rootCoordinatorLayout.setFitsSystemWindows(false);
- } else { // Hide everything except the status and navigation bars.
- // Set `rootCoordinatorLayout` to fit under the status and navigation bars.
- rootCoordinatorLayout.setFitsSystemWindows(false);
-
- if (translucentNavigationBarOnFullscreen) { // There is an Android Support Library bug that causes an ugly scrim to print on the `Drawer Layout` when the navigation bar is displayed on the right of the screen.
- // Set the navigation bar to be translucent.
- getWindow().addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION);
+ // Hide the `BannerAd` in the free flavor.
+ if (BuildConfig.FLAVOR.contentEquals("free")) {
+ BannerAd.hideAd(adView);
}
- }
- } else { // Switch to normal viewing mode.
- // Show the `appBar`.
- appBar.show();
- // Show the `BannerAd` in the free flavor.
- if (BuildConfig.FLAVOR.contentEquals("free")) {
- // Reload the ad. Because the screen may have rotated, we need to use `reloadAfterRotate`.
- BannerAd.reloadAfterRotate(adView, getApplicationContext(), getString(R.string.ad_id));
+ // Modify the system bars.
+ if (hideSystemBarsOnFullscreen) { // Hide everything.
+ // Remove the translucent overlays.
+ getWindow().clearFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
+
+ // 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.
+ */
+ 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.
+ rootCoordinatorLayout.setFitsSystemWindows(false);
+ } else { // Hide everything except the status and navigation bars.
+ // Set `rootCoordinatorLayout` to fit under the status and navigation bars.
+ rootCoordinatorLayout.setFitsSystemWindows(false);
+
+ if (translucentNavigationBarOnFullscreen) { // There is an Android Support Library bug that causes a scrim to print on the right side of the `Drawer Layout` when the navigation bar is displayed on the right of the screen.
+ // Set the navigation bar to be translucent.
+ getWindow().addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION);
+ }
+ }
+ } else { // Switch to normal viewing mode.
+ // Show the `appBar`.
+ appBar.show();
- // Reinitialize the `adView` variable, as the `View` will have been removed and re-added by `BannerAd.reloadAfterRotate()`.
- adView = findViewById(R.id.adView);
- }
+ // Show the `BannerAd` in the free flavor.
+ if (BuildConfig.FLAVOR.contentEquals("free")) {
+ // Reload the ad. Because the screen may have rotated, we need to use `reloadAfterRotate`.
+ BannerAd.reloadAfterRotate(adView, getApplicationContext(), getString(R.string.ad_id));
- // Remove the translucent navigation bar flag if it is set.
- getWindow().clearFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION);
+ // Reinitialize the `adView` variable, as the `View` will have been removed and re-added by `BannerAd.reloadAfterRotate()`.
+ adView = findViewById(R.id.adView);
+ }
- // Add the translucent status flag if it is unset. This also resets `drawerLayout's` `View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN`.
- getWindow().addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
+ // Remove the translucent navigation bar flag if it is set.
+ getWindow().clearFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION);
- // Remove any `SYSTEM_UI` flags from `rootCoordinatorLayout`.
- rootCoordinatorLayout.setSystemUiVisibility(0);
+ // Add the translucent status flag if it is unset. This also resets `drawerLayout's` `View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN`.
+ getWindow().addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
- // Constrain `rootCoordinatorLayout` inside the status and navigation bars.
- rootCoordinatorLayout.setFitsSystemWindows(true);
- }
+ // Remove any `SYSTEM_UI` flags from `rootCoordinatorLayout`.
+ rootCoordinatorLayout.setSystemUiVisibility(0);
- // Consume the double-tap.
- return true;
+ // Constrain `rootCoordinatorLayout` inside the status and navigation bars.
+ rootCoordinatorLayout.setFitsSystemWindows(true);
+ }
+
+ // Consume the double-tap.
+ return true;
+ } else { // Do not consume the double-tap because full screen browsing mode is disabled.
+ return false;
+ }
}
});
});
// drawerToggle creates the hamburger icon at the start of the AppBar.
- drawerToggle = new ActionBarDrawerToggle(this, drawerLayout, supportAppBar, R.string.open_navigation, R.string.close_navigation);
+ drawerToggle = new ActionBarDrawerToggle(this, drawerLayout, supportAppBar, R.string.open_navigation_drawer, R.string.close_navigation_drawer);
+
+ // Initialize `adServerSet`.
+ final Set<String> 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.
@SuppressWarnings("deprecation")
@Override
public boolean shouldOverrideUrlLoading(WebView view, String url) {
- // Use an external email program if the link begins with "mailto:".
+ // Use an external email program if the link begins with `mailto:`.
if (url.startsWith("mailto:")) {
// We use `ACTION_SENDTO` instead of `ACTION_SEND` so that only email programs are launched.
Intent emailIntent = new Intent(Intent.ACTION_SENDTO);
}
}
+ // 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` if it is not `null`.
+ if (requestHost != null) {
+ 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) {
// Enter full screen video
@Override
public void onShowCustomView(View view, CustomViewCallback callback) {
- appBar.hide();
-
- // Show the fullScreenVideoFrameLayout.
- fullScreenVideoFrameLayout.addView(view);
- fullScreenVideoFrameLayout.setVisibility(View.VISIBLE);
-
- // Hide the mainWebView.
- mainWebView.setVisibility(View.GONE);
-
- // Hide the ad if this is the free flavor.
+ // Pause the ad if this is the free flavor.
if (BuildConfig.FLAVOR.contentEquals("free")) {
- BannerAd.hideAd(adView);
+ BannerAd.pauseAd(adView);
}
+ // Remove the translucent overlays.
+ getWindow().clearFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
+
+ // 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.
*/
- view.setSystemUiVisibility(View.SYSTEM_UI_FLAG_FULLSCREEN | View.SYSTEM_UI_FLAG_HIDE_NAVIGATION | View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY);
+ rootCoordinatorLayout.setSystemUiVisibility(View.SYSTEM_UI_FLAG_FULLSCREEN | View.SYSTEM_UI_FLAG_HIDE_NAVIGATION | View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY);
+
+ // Set `rootCoordinatorLayout` to fill the entire screen.
+ rootCoordinatorLayout.setFitsSystemWindows(false);
+
+ // Add `view` to `fullScreenVideoFrameLayout` and display it on the screen.
+ fullScreenVideoFrameLayout.addView(view);
+ fullScreenVideoFrameLayout.setVisibility(View.VISIBLE);
}
// Exit full screen video
public void onHideCustomView() {
- appBar.show();
+ // Hide `fullScreenVideoFrameLayout`.
+ fullScreenVideoFrameLayout.removeAllViews();
+ fullScreenVideoFrameLayout.setVisibility(View.GONE);
- // Show the mainWebView.
- mainWebView.setVisibility(View.VISIBLE);
+ // Add the translucent status flag. This also resets `drawerLayout's` `View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN`.
+ getWindow().addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS);
+
+ // Set `rootCoordinatorLayout` to fit inside the status and navigation bars. This also clears the `SYSTEM_UI` flags.
+ rootCoordinatorLayout.setFitsSystemWindows(true);
// Show the ad if this is the free flavor.
if (BuildConfig.FLAVOR.contentEquals("free")) {
- BannerAd.showAd(adView);
- }
+ // Reload the ad. Because the screen may have rotated, we need to use `reloadAfterRotate`.
+ BannerAd.reloadAfterRotate(adView, getApplicationContext(), getString(R.string.ad_id));
- // Hide the fullScreenVideoFrameLayout.
- fullScreenVideoFrameLayout.removeAllViews();
- fullScreenVideoFrameLayout.setVisibility(View.GONE);
+ // Reinitialize the `adView` variable, as the `View` will have been removed and re-added by `BannerAd.reloadAfterRotate()`.
+ adView = findViewById(R.id.adView);
+ }
}
});
// Replace the header that `WebView` creates for `X-Requested-With` with a null value. The default value is the application ID (com.stoutner.privacybrowser.standard).
customHeaders.put("X-Requested-With", "");
- // Initialize the default preference values the first time the program is run.
+ // Initialize the default preference values the first time the program is run. `this` is the context. `false` keeps this command from resetting any current preferences back to default.
PreferenceManager.setDefaultValues(this, R.xml.preferences, false);
// Apply the settings from the shared preferences.
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);
case R.id.clearFormData:
WebViewDatabase mainWebViewDatabase = WebViewDatabase.getInstance(this);
mainWebViewDatabase.clearFormData();
- mainWebView.reload();
+ Snackbar.make(findViewById(R.id.mainWebView), R.string.form_data_deleted, Snackbar.LENGTH_SHORT).show();
return true;
case R.id.fontSizeFiftyPercent:
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.
domStorage.deleteAllData();
// Clear form data.
- WebViewDatabase formData = WebViewDatabase.getInstance(this);
- formData.clearFormData();
+ WebViewDatabase webViewDatabase = WebViewDatabase.getInstance(this);
+ webViewDatabase.clearFormData();
// Clear cache. The argument of "true" includes disk files.
mainWebView.clearCache(true);
customHeaders.clear();
// Detach all views from `mainWebViewRelativeLayout`.
- RelativeLayout mainWebViewRelativeLayout = (RelativeLayout) findViewById(R.id.mainWebViewRelativeLayout);
mainWebViewRelativeLayout.removeAllViews();
// Destroy the internal state of `mainWebView`.
public void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
- // Handle the `adView` for the free version.
- if (BuildConfig.FLAVOR.contentEquals("free")) {
- // Reload the add if we are not in full screen mode.
- if (adView.isShown()) {
- // Reload the ad.
- BannerAd.reloadAfterRotate(adView, getApplicationContext(), getString(R.string.ad_id));
+ // Reload the ad for the free flavor if we are not in full screen mode.
+ if (BuildConfig.FLAVOR.contentEquals("free") && adView.isShown() && !fullScreenVideoFrameLayout.isShown()) {
+ // Reload the ad.
+ 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);
- }
+ // Reinitialize the `adView` variable, as the `View` will have been removed and re-added by `BannerAd.reloadAfterRotate()`.
+ 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
final String imageUrl;
final String linkUrl;
+ // Get a handle for the `ClipboardManager`.
+ final ClipboardManager clipboardManager = (ClipboardManager) getSystemService(CLIPBOARD_SERVICE);
+
switch (hitTestResult.getType()) {
// `SRC_ANCHOR_TYPE` is a link.
case WebView.HitTestResult.SRC_ANCHOR_TYPE:
// Set the target URL as the title of the `ContextMenu`.
menu.setHeaderTitle(linkUrl);
- // Add a `Load URL` button.
+ // Add a `Load URL` entry.
menu.add(R.string.load_url).setOnMenuItemClickListener(new MenuItem.OnMenuItemClickListener() {
@Override
public boolean onMenuItemClick(MenuItem item) {
}
});
- // Add a `Cancel` button, which by default closes the `ContextMenu`.
+ // Add a `Copy URL` entry.
+ menu.add(R.string.copy_url).setOnMenuItemClickListener(new MenuItem.OnMenuItemClickListener() {
+ @Override
+ public boolean onMenuItemClick(MenuItem item) {
+ // Save the link URL in a `ClipData`.
+ ClipData srcAnchorTypeClipData = ClipData.newPlainText(getResources().getString(R.string.url), linkUrl);
+
+ // Set the `ClipData` as the clipboard's primary clip.
+ clipboardManager.setPrimaryClip(srcAnchorTypeClipData);
+ return false;
+ }
+ });
+
+ // Add a `Cancel` entry, which by default closes the `ContextMenu`.
menu.add(R.string.cancel);
break;
// Set the target URL as the title of the `ContextMenu`.
menu.setHeaderTitle(linkUrl);
- // Add a `Write Email` button.
+ // Add a `Write Email` entry.
menu.add(R.string.write_email).setOnMenuItemClickListener(new MenuItem.OnMenuItemClickListener() {
@Override
public boolean onMenuItemClick(MenuItem item) {
}
});
- // Add a `Cancel` button, which by default closes the `ContextMenu`.
+ // Add a `Copy Email Address` entry.
+ menu.add(R.string.copy_email_address).setOnMenuItemClickListener(new MenuItem.OnMenuItemClickListener() {
+ @Override
+ public boolean onMenuItemClick(MenuItem item) {
+ // Save the email address in a `ClipData`.
+ ClipData srcEmailTypeClipData = ClipData.newPlainText(getResources().getString(R.string.email_address), linkUrl);
+
+ // Set the `ClipData` as the clipboard's primary clip.
+ clipboardManager.setPrimaryClip(srcEmailTypeClipData);
+ return false;
+ }
+ });
+
+ // Add a `Cancel` entry, which by default closes the `ContextMenu`.
menu.add(R.string.cancel);
break;
// Set the image URL as the title of the `ContextMenu`.
menu.setHeaderTitle(imageUrl);
- // Add a `View Image` button.
+ // Add a `View Image` entry.
menu.add(R.string.view_image).setOnMenuItemClickListener(new MenuItem.OnMenuItemClickListener() {
@Override
public boolean onMenuItemClick(MenuItem item) {
}
});
- // Add a `Download Image` button.
+ // Add a `Download Image` entry.
menu.add(R.string.download_image).setOnMenuItemClickListener(new MenuItem.OnMenuItemClickListener() {
@Override
public boolean onMenuItemClick(MenuItem item) {
}
});
- // Add a `Cancel` button, which by default closes the `ContextMenu`.
+ // Add a `Copy URL` entry.
+ menu.add(R.string.copy_url).setOnMenuItemClickListener(new MenuItem.OnMenuItemClickListener() {
+ @Override
+ public boolean onMenuItemClick(MenuItem item) {
+ // Save the image URL in a `ClipData`.
+ ClipData srcImageTypeClipData = ClipData.newPlainText(getResources().getString(R.string.url), imageUrl);
+
+ // Set the `ClipData` as the clipboard's primary clip.
+ clipboardManager.setPrimaryClip(srcImageTypeClipData);
+ return false;
+ }
+ });
+
+ // Add a `Cancel` entry, which by default closes the `ContextMenu`.
menu.add(R.string.cancel);
break;
// Set the image URL as the title of the `ContextMenu`.
menu.setHeaderTitle(imageUrl);
- // Add a `View Image` button.
+ // Add a `View Image` entry.
menu.add(R.string.view_image).setOnMenuItemClickListener(new MenuItem.OnMenuItemClickListener() {
@Override
public boolean onMenuItemClick(MenuItem item) {
}
});
- // Add a `Download Image` button.
+ // Add a `Download Image` entry.
menu.add(R.string.download_image).setOnMenuItemClickListener(new MenuItem.OnMenuItemClickListener() {
@Override
public boolean onMenuItemClick(MenuItem item) {
}
});
- // Add a `Cancel` button, which by default closes the `ContextMenu`.
+ // Add a `Copy URL` entry.
+ menu.add(R.string.copy_url).setOnMenuItemClickListener(new MenuItem.OnMenuItemClickListener() {
+ @Override
+ public boolean onMenuItemClick(MenuItem item) {
+ // Save the image URL in a `ClipData`.
+ ClipData srcImageAnchorTypeClipData = ClipData.newPlainText(getResources().getString(R.string.url), imageUrl);
+
+ // Set the `ClipData` as the clipboard's primary clip.
+ clipboardManager.setPrimaryClip(srcImageAnchorTypeClipData);
+ return false;
+ }
+ });
+
+ // Add a `Cancel` entry, which by default closes the `ContextMenu`.
menu.add(R.string.cancel);
break;
}
String fileName = downloadFileNameEditText.getText().toString();
// Once we have `WRITE_EXTERNAL_STORAGE` permissions we can use `setDestinationInExternalPublicDir`.
- if (Build.VERSION.SDK_INT >= 23) { // If API >= 23, set the download save in the the `DIRECTORY_DOWNLOADS` using `fileName`.
+ if (Build.VERSION.SDK_INT >= 23) { // If API >= 23, set the download location to `/sdcard/Android/data/com.stoutner.privacybrowser.standard/files` named `fileName`.
downloadRequest.setDestinationInExternalFilesDir(this, "/", fileName);
} else { // Only set the title using `fileName`.
downloadRequest.setTitle(fileName);
mainWebView.clearHistory();
}
- // Override onBackPressed to handle the navigation drawer and mainWebView.
+ // Override `onBackPressed` to handle the navigation drawer and `mainWebView`.
@Override
public void onBackPressed() {
- final WebView mainWebView = (WebView) findViewById(R.id.mainWebView);
-
// Close the navigation drawer if it is available. GravityCompat.START is the drawer on the left on Left-to-Right layout text.
if (drawerLayout.isDrawerVisible(GravityCompat.START)) {
drawerLayout.closeDrawer(GravityCompat.START);
if (mainWebView.canGoBack()) {
mainWebView.goBack();
} else {
- // Pass onBackPressed to the system.
+ // Pass `onBackPressed()` to the system.
super.onBackPressed();
}
}
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);
SharedPreferences sharedPreferences = PreferenceManager.getDefaultSharedPreferences(this);
// Store the values from `sharedPreferences` in variables.
- String userAgentString = sharedPreferences.getString("user_agent", "Default user agent");
+ String userAgentString = sharedPreferences.getString("user_agent", "PrivacyBrowser/1.0");
String customUserAgentString = sharedPreferences.getString("custom_user_agent", "PrivacyBrowser/1.0");
String javaScriptDisabledSearchString = sharedPreferences.getString("javascript_disabled_search", "https://duckduckgo.com/html/?q=");
String javaScriptDisabledCustomSearchString = sharedPreferences.getString("javascript_disabled_search_custom_url", "");
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);
translucentNavigationBarOnFullscreen = sharedPreferences.getBoolean("translucent_navigation_bar", true);
}
// 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);