/**
* Copyright 2015-2016 Soren Stoutner <soren@stoutner.com>.
*
- * This file is part of Privacy Browser.
+ * This file is part of Privacy Browser <https://www.stoutner.com/privacy-browser>.
*
* Privacy Browser is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
package com.stoutner.privacybrowser;
import android.annotation.SuppressLint;
-import android.annotation.TargetApi;
import android.app.Activity;
import android.app.DownloadManager;
import android.content.Intent;
import android.content.SharedPreferences;
+import android.content.res.Configuration;
import android.graphics.Bitmap;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import android.preference.PreferenceManager;
+import android.support.design.widget.NavigationView;
+import android.support.design.widget.Snackbar;
import android.support.v4.app.DialogFragment;
+import android.support.v4.view.GravityCompat;
+import android.support.v4.widget.DrawerLayout;
+import android.support.v4.widget.SwipeRefreshLayout;
import android.support.v7.app.ActionBar;
+import android.support.v7.app.ActionBarDrawerToggle;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.app.AppCompatDialogFragment;
import android.support.v7.widget.Toolbar;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
-import android.view.Window;
import android.view.inputmethod.InputMethodManager;
import android.webkit.CookieManager;
import android.webkit.DownloadListener;
import android.widget.FrameLayout;
import android.widget.ImageView;
import android.widget.ProgressBar;
-import android.widget.Toast;
+
import java.io.UnsupportedEncodingException;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLEncoder;
// 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 MainWebViewActivity extends AppCompatActivity implements CreateHomeScreenShortcut.CreateHomeScreenSchortcutListener {
+public class MainWebViewActivity extends AppCompatActivity implements NavigationView.OnNavigationItemSelectedListener, CreateHomeScreenShortcut.CreateHomeScreenSchortcutListener {
// favoriteIcon is public static so it can be accessed from CreateHomeScreenShortcut.
public static Bitmap favoriteIcon;
- // mainWebView is public static so it can be accessed from AboutDialog. It is also used in onCreate(), onOptionsItemSelected(), and loadUrlFromTextBox().
+ // mainWebView is public static so it can be accessed from SettingsFragment. It is also used in onCreate(), onOptionsItemSelected(), onNavigationItemSelected(), and loadUrlFromTextBox().
public static WebView mainWebView;
- // mainMenu is used in onCreateOptionsMenu() and onOptionsItemSelected().
- private Menu mainMenu;
+ // mainMenu is public static so it can be accessed from SettingsFragment. It is also used in onCreateOptionsMenu() and onOptionsItemSelected().
+ public static Menu mainMenu;
+ // cookieManager is public static so it can be accessed from SettingsFragment. It is also used in onCreate(), onOptionsItemSelected(), and onNavigationItemSelected().
+ public static CookieManager cookieManager;
+ // javaScriptEnabled is public static so it can be accessed from SettingsFragment. It is also used in onCreate(), onCreateOptionsMenu(), onOptionsItemSelected(), and loadUrlFromTextBox().
+ public static boolean javaScriptEnabled;
+ // firstPartyCookiesEnabled is public static so it can be accessed from SettingsFragment. It is also used in onCreate(), onCreateOptionsMenu(), onPrepareOptionsMenu(), and onOptionsItemSelected().
+ public static boolean firstPartyCookiesEnabled;
+ // thirdPartyCookiesEnabled is used in onCreate(), onCreateOptionsMenu(), onPrepareOptionsMenu(), and onOptionsItemSelected().
+ public static boolean thirdPartyCookiesEnabled;
+ // domStorageEnabled is public static so it can be accessed from SettingsFragment. It is also used in onCreate(), onCreateOptionsMenu(), and onOptionsItemSelected().
+ public static boolean domStorageEnabled;
+ // javaScriptDisabledSearchURL is public static so it can be accessed from SettingsFragment. It is also used in onCreate() and loadURLFromTextBox().
+ public static String javaScriptDisabledSearchURL;
+ // javaScriptEnabledSearchURL is public static so it can be accessed from SettingsFragment. It is also used in onCreate() and loadURLFromTextBox().
+ public static String javaScriptEnabledSearchURL;
+ // homepage is public static so it can be accessed from SettingsFragment. It is also used in onCreate() and onOptionsItemSelected().
+ public static String homepage;
+ // swipeToRefresh is public static so it can be accessed from SettingsFragment. It is also used in onCreate().
+ public static SwipeRefreshLayout swipeToRefresh;
+ // swipeToRefreshEnabled is public static so it can be accessed from SettingsFragment. It is also used in onCreate().
+ public static boolean swipeToRefreshEnabled;
+
+ // drawerToggle is used in onCreate(), onPostCreate(), onConfigurationChanged(), onNewIntent(), and onNavigationItemSelected().
+ private ActionBarDrawerToggle drawerToggle;
+ // drawerLayout is used in onCreate(), onNewIntent(), and onBackPressed().
+ private DrawerLayout drawerLayout;
// formattedUrlString is used in onCreate(), onOptionsItemSelected(), onCreateHomeScreenShortcutCreate(), and loadUrlFromTextBox().
private String formattedUrlString;
- // homepage is used in onCreate() and onOptionsItemSelected().
- private String homepage;
- // javaScriptEnabled is used in onCreate(), onCreateOptionsMenu(), onOptionsItemSelected(), and loadUrlFromTextBox().
- private boolean javaScriptEnabled;
- // domStorageEnabled is used in onCreate(), onCreateOptionsMenu(), and onOptionsItemSelected().
- private boolean domStorageEnabled;
-
- /* saveFormDataEnabled does nothing until database storage is implemented.
- // saveFormDataEnabled is used in onCreate(), onCreateOptionsMenu(), and onOptionsItemSelected().
- private boolean saveFormDataEnabled;
- */
-
- // cookieManager is used in onCreate() and onOptionsItemSelected().
- private CookieManager cookieManager;
- // cookiesEnabled is used in onCreate(), onCreateOptionsMenu(), and onOptionsItemSelected().
- private boolean cookiesEnabled;
-
+ // privacyIcon is used in onCreateOptionsMenu() and updatePrivacyIcon().
+ private MenuItem privacyIcon;
// urlTextBox is used in onCreate(), onOptionsItemSelected(), and loadUrlFromTextBox().
private EditText urlTextBox;
+ // adView is used in onCreate() and onConfigurationChanged().
+ private View adView;
@Override
- // Remove Android Studio's warning about the dangers of using SetJavaScriptEnabled.
+ // 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")
protected void onCreate(Bundle savedInstanceState) {
- // Window.FEATURE_ACTION_BAR_OVERLAY must be enabled to set the app bar to HideOnContentScroll. It must be set before any content is added to the activity.
- if (Build.VERSION.SDK_INT >= 11) {
- requestWindowFeature(Window.FEATURE_ACTION_BAR_OVERLAY);
- }
-
super.onCreate(savedInstanceState);
- setContentView(R.layout.activity_webview);
+ setContentView(R.layout.main_coordinatorlayout);
// We need to use the SupportActionBar from android.support.v7.app.ActionBar until the minimum API is >= 21.
Toolbar supportAppBar = (Toolbar) findViewById(R.id.appBar);
setSupportActionBar(supportAppBar);
+ final ActionBar appBar = getSupportActionBar();
+
+ // This is needed to get rid of the Android Studio warning that appBar might be null.
+ assert appBar != null;
+
+ // Add the custom url_bar layout, which shows the favoriteIcon, urlTextBar, and progressBar.
+ appBar.setCustomView(R.layout.url_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.setOnKeyListener(new View.OnKeyListener() {
+ public boolean onKey(View v, int keyCode, KeyEvent event) {
+ // If the event is a key-down event on the "enter" button, load the URL.
+ if ((event.getAction() == KeyEvent.ACTION_DOWN) && (keyCode == KeyEvent.KEYCODE_ENTER)) {
+ // Load the URL into the mainWebView and consume the event.
+ try {
+ loadUrlFromTextBox();
+ } catch (UnsupportedEncodingException e) {
+ e.printStackTrace();
+ }
+ // If the enter key was pressed, consume the event.
+ return true;
+ } else {
+ // If any other key was pressed, do not consume the event.
+ return false;
+ }
+ }
+ });
final FrameLayout fullScreenVideoFrameLayout = (FrameLayout) findViewById(R.id.fullScreenVideoFrameLayout);
- final Activity mainWebViewActivity = this;
- // We need to use the SupportActionBar from android.support.v7.app.ActionBar until the minimum API is >= 21.
- final ActionBar appBar = getSupportActionBar();
+
+ // Implement swipe to refresh
+ swipeToRefresh = (SwipeRefreshLayout) findViewById(R.id.swipeRefreshLayout);
+ assert swipeToRefresh != null; //This assert removes the incorrect warning on the following line that swipeToRefresh might be null.
+ swipeToRefresh.setColorSchemeResources(R.color.blue);
+ swipeToRefresh.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() {
+ @Override
+ public void onRefresh() {
+ mainWebView.reload();
+ }
+ });
mainWebView = (WebView) findViewById(R.id.mainWebView);
- if (appBar != null) {
- /* TODO Enable app bar scrolling.
- // Scroll the app bar, but only if the API supports overlay mode (>= 11).
- if (Build.VERSION.SDK_INT >= 11) {
- appBar.setHideOnContentScrollEnabled(true);
- }
- */
-
- // Remove the title from the app bar.
- appBar.setDisplayShowTitleEnabled(false);
-
- // Add the custom url_bar layout, which shows the favoriteIcon, urlTextBar, and progressBar.
- appBar.setCustomView(R.layout.url_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.setOnKeyListener(new View.OnKeyListener() {
- public boolean onKey(View v, int keyCode, KeyEvent event) {
- // If the event is a key-down event on the "enter" button, load the URL.
- if ((event.getAction() == KeyEvent.ACTION_DOWN) && (keyCode == KeyEvent.KEYCODE_ENTER)) {
- // Load the URL into the mainWebView and consume the event.
- try {
- loadUrlFromTextBox();
- } catch (UnsupportedEncodingException e) {
- e.printStackTrace();
- }
- // If the enter key was pressed, consume the event.
- return true;
- } else {
- // If any other key was pressed, do not consume the event.
- return false;
- }
- }
- });
- }
+ // Create the navigation drawer.
+ drawerLayout = (DrawerLayout) findViewById(R.id.drawerLayout);
+ // The DrawerTitle identifies the drawer in accessibility mode.
+ drawerLayout.setDrawerTitle(GravityCompat.START, getString(R.string.navigation_drawer));
+
+ // Listen for touches on the navigation menu.
+ final NavigationView navigationView = (NavigationView) findViewById(R.id.navigationView);
+ assert navigationView != null; // This assert removes the incorrect warning on the following line that navigationView might be null.
+ navigationView.setNavigationItemSelectedListener(this);
+
+ // 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);
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.
return true;
}
- /* These errors do not provide any useful information and clutter the screen.
- public void onReceivedError(WebView view, WebResourceRequest request, WebResourceError error) {
- Toast.makeText(mainWebViewActivity, "Error loading " + request + " Error: " + error, Toast.LENGTH_SHORT).show();
- }
- */
-
// Update the URL in urlTextBox when the page starts to load.
@Override
public void onPageStarted(WebView view, String url, Bitmap favicon) {
@Override
public void onPageFinished(WebView view, String url) {
formattedUrlString = url;
- urlTextBox.setText(formattedUrlString);
+
+ // Only update urlTextBox if the user is not typing in it.
+ if (!urlTextBox.hasFocus()) {
+ urlTextBox.setText(formattedUrlString);
+ }
}
});
progressBar.setVisibility(View.VISIBLE);
} else {
progressBar.setVisibility(View.GONE);
+
+ //Stop the SwipeToRefresh indicator if it is running
+ swipeToRefresh.setRefreshing(false);
}
}
}
appBar.hide();
}
+ // Show the fullScreenVideoFrameLayout.
+ assert fullScreenVideoFrameLayout != null; //This assert removes the incorrect warning on the following line that fullScreenVideoFrameLayout might be null.
fullScreenVideoFrameLayout.addView(view);
fullScreenVideoFrameLayout.setVisibility(View.VISIBLE);
+ // Hide the mainWebView.
mainWebView.setVisibility(View.GONE);
+ // Hide the ad if this is the free flavor.
+ BannerAd.hideAd(adView);
+
/* SYSTEM_UI_FLAG_HIDE_NAVIGATION hides the navigation bars on the bottom or right of the screen.
- ** SYSTEM_UI_FLAG_FULLSCREEN hides the status bar across the top of the screen.
- ** SYSTEM_UI_FLAG_IMMERSIVE_STICKY makes the navigation and status bars ghosted overlays and automatically rehides them.
- */
+ * SYSTEM_UI_FLAG_FULLSCREEN hides the status bar across the top of the screen.
+ * SYSTEM_UI_FLAG_IMMERSIVE_STICKY makes the navigation and status bars ghosted overlays and automatically rehides them.
+ */
// Set the one flag supported by API >= 14.
- if (Build.VERSION.SDK_INT >= 14) {
- view.setSystemUiVisibility(View.SYSTEM_UI_FLAG_HIDE_NAVIGATION);
- }
+ view.setSystemUiVisibility(View.SYSTEM_UI_FLAG_HIDE_NAVIGATION);
// Set the two flags that are supported by API >= 16.
if (Build.VERSION.SDK_INT >= 16) {
appBar.show();
}
+ // Show the mainWebView.
mainWebView.setVisibility(View.VISIBLE);
+ // Show the ad if this is the free flavor.
+ BannerAd.showAd(adView);
+
+ // Hide the fullScreenVideoFrameLayout.
+ assert fullScreenVideoFrameLayout != null; //This assert removes the incorrect warning on the following line that fullScreenVideoFrameLayout might be null.
fullScreenVideoFrameLayout.removeAllViews();
fullScreenVideoFrameLayout.setVisibility(View.GONE);
}
// Add the URL as the description for the download.
requestUri.setDescription(url);
- // Show the download notification after the download is completed if the API is 11 or greater.
- if (Build.VERSION.SDK_INT >= 11) {
- requestUri.setNotificationVisibility(DownloadManager.Request.VISIBILITY_VISIBLE_NOTIFY_COMPLETED);
- }
+ // Show the download notification after the download is completed.
+ requestUri.setNotificationVisibility(DownloadManager.Request.VISIBILITY_VISIBLE_NOTIFY_COMPLETED);
+ // Initiate the download and display a Snackbar.
downloadManager.enqueue(requestUri);
- Toast.makeText(mainWebViewActivity, "Download started", Toast.LENGTH_SHORT).show();
+ Snackbar.make(findViewById(R.id.mainWebView), R.string.download_started, Snackbar.LENGTH_SHORT).show();
}
});
// Allow pinch to zoom.
mainWebView.getSettings().setBuiltInZoomControls(true);
- // Hide zoom controls if the API is 11 or greater.
- if (Build.VERSION.SDK_INT >= 11) {
- mainWebView.getSettings().setDisplayZoomControls(false);
- }
+ // Hide zoom controls.
+ mainWebView.getSettings().setDisplayZoomControls(false);
+
// Initialize the default preference values the first time the program is run.
PreferenceManager.setDefaultValues(this, R.xml.preferences, false);
// Get the shared preference values.
SharedPreferences savedPreferences = PreferenceManager.getDefaultSharedPreferences(this);
- // Set JavaScript initial status.
+ // Set JavaScript initial status. The default value is false.
javaScriptEnabled = savedPreferences.getBoolean("javascript_enabled", false);
mainWebView.getSettings().setJavaScriptEnabled(javaScriptEnabled);
- // Set DOM storage initial status.
+ // Initialize cookieManager.
+ cookieManager = CookieManager.getInstance();
+
+ // Set cookies initial status. The default value is false.
+ firstPartyCookiesEnabled = savedPreferences.getBoolean("first_party_cookies_enabled", false);
+ cookieManager.setAcceptCookie(firstPartyCookiesEnabled);
+
+ // Set third-party cookies initial status if API >= 21. The default value is false.
+ if (Build.VERSION.SDK_INT >= 21) {
+ thirdPartyCookiesEnabled = savedPreferences.getBoolean("third_party_cookies_enabled", false);
+ cookieManager.setAcceptThirdPartyCookies(mainWebView, thirdPartyCookiesEnabled);
+ }
+
+ // Set DOM storage initial status. The default value is false.
domStorageEnabled = savedPreferences.getBoolean("dom_storage_enabled", false);
mainWebView.getSettings().setDomStorageEnabled(domStorageEnabled);
- /* Save Form Data does nothing until database storage is implemented.
- // Set Save Form Data initial status.
- saveFormDataEnabled = true;
- mainWebView.getSettings().setSaveFormData(saveFormDataEnabled);
- */
+ // Set the user agent initial status.
+ String userAgentString = savedPreferences.getString("user_agent", "Default user agent");
+ switch (userAgentString) {
+ case "Default user agent":
+ // Do nothing.
+ break;
- // Set cookies initial status.
- cookiesEnabled = savedPreferences.getBoolean("cookies_enabled", false);
- cookieManager = CookieManager.getInstance();
- cookieManager.setAcceptCookie(cookiesEnabled);
+ case "Custom user agent":
+ // Set the custom user agent on mainWebView, The default is "PrivacyBrowser/1.0".
+ mainWebView.getSettings().setUserAgentString(savedPreferences.getString("custom_user_agent", "PrivacyBrowser/1.0"));
+ break;
+
+ default:
+ // Set the selected user agent on mainWebView. The default is "PrivacyBrowser/1.0".
+ mainWebView.getSettings().setUserAgentString(savedPreferences.getString("user_agent", "PrivacyBrowser/1.0"));
+ break;
+ }
+
+ // Set the initial string for JavaScript disabled search.
+ if (savedPreferences.getString("javascript_disabled_search", "https://duckduckgo.com/html/?q=").equals("Custom URL")) {
+ // Get the custom URL string. The default is "".
+ javaScriptDisabledSearchURL = savedPreferences.getString("javascript_disabled_search_custom_url", "");
+ } else {
+ // Use the string from javascript_disabled_search.
+ javaScriptDisabledSearchURL = savedPreferences.getString("javascript_disabled_search", "https://duckduckgo.com/html/?q=");
+ }
- // Set hompage initial status.
+ // Set the initial string for JavaScript enabled search.
+ if (savedPreferences.getString("javascript_enabled_search", "https://duckduckgo.com/?q=").equals("Custom URL")) {
+ // Get the custom URL string. The default is "".
+ javaScriptEnabledSearchURL = savedPreferences.getString("javascript_enabled_search_custom_url", "");
+ } else {
+ // Use the string from javascript_enabled_search.
+ javaScriptEnabledSearchURL = savedPreferences.getString("javascript_enabled_search", "https://duckduckgo.com/?q=");
+ }
+
+
+ // Set homepage initial status. The default value is "https://www.duckduckgo.com".
homepage = savedPreferences.getString("homepage", "https://www.duckduckgo.com");
+ // Set swipe to refresh initial status. The default is true.
+ swipeToRefreshEnabled = savedPreferences.getBoolean("swipe_to_refresh_enabled", true);
+ swipeToRefresh.setEnabled(swipeToRefreshEnabled);
+
+
// Get the intent information that started the app.
final Intent intent = getIntent();
// Load the initial website.
mainWebView.loadUrl(formattedUrlString);
+
+ // 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);
}
+
@Override
protected void onNewIntent(Intent intent) {
// Sets the new intent as the activity intent, so that any future getIntent()s pick up this one instead of creating a new activity.
formattedUrlString = intentUriData.toString();
}
+ // Close the navigation drawer if it is open.
+ if (drawerLayout.isDrawerVisible(GravityCompat.START)) {
+ drawerLayout.closeDrawer(GravityCompat.START);
+ }
+
// Load the website.
mainWebView.loadUrl(formattedUrlString);
+
+ // Clear the keyboard if displayed and remove the focus on the urlTextBar if it has it.
+ mainWebView.requestFocus();
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
- getMenuInflater().inflate(R.menu.menu_webview, menu);
+ getMenuInflater().inflate(R.menu.menu_options, menu);
// Set mainMenu so it can be used by onOptionsItemSelected.
mainMenu = menu;
+ // Initialize privacyIcon
+ privacyIcon = menu.findItem(R.id.toggleJavaScript);
+
// Get MenuItems for checkable menu items.
- MenuItem toggleJavaScript = menu.findItem(R.id.toggleJavaScript);
+ MenuItem toggleFirstPartyCookies = menu.findItem(R.id.toggleFirstPartyCookies);
+ MenuItem toggleThirdPartyCookies = menu.findItem(R.id.toggleThirdPartyCookies);
MenuItem toggleDomStorage = menu.findItem(R.id.toggleDomStorage);
- /* toggleSaveFormData does nothing until database storage is implemented.
- MenuItem toggleSaveFormData = menu.findItem(R.id.toggleSaveFormData);
- */
- MenuItem toggleCookies = menu.findItem(R.id.toggleCookies);
- // Set the initial icon for toggleJavaScript
- if (javaScriptEnabled) {
- toggleJavaScript.setIcon(R.drawable.javascript_enabled);
- } else {
- if (domStorageEnabled || cookiesEnabled) {
- toggleJavaScript.setIcon(R.drawable.warning);
- } else {
- toggleJavaScript.setIcon(R.drawable.privacy_mode);
- }
- }
+ // Set the initial status of the privacy icon.
+ updatePrivacyIcon();
// Set the initial status of the menu item checkboxes.
+ toggleFirstPartyCookies.setChecked(firstPartyCookiesEnabled);
+ toggleThirdPartyCookies.setChecked(thirdPartyCookiesEnabled);
toggleDomStorage.setChecked(domStorageEnabled);
- /* toggleSaveFormData does nothing until database storage is implemented.
- toggleSaveFormData.setChecked(saveFormDataEnabled);
- */
- toggleCookies.setChecked(cookiesEnabled);
return true;
}
@Override
public boolean onPrepareOptionsMenu(Menu menu) {
+ // Only enable Third-Party Cookies if SDK >= 21 and First-Party Cookies are enabled.
+ MenuItem toggleThirdPartyCookies = menu.findItem(R.id.toggleThirdPartyCookies);
+ if ((Build.VERSION.SDK_INT >= 21) && firstPartyCookiesEnabled) {
+ toggleThirdPartyCookies.setEnabled(true);
+ } else {
+ toggleThirdPartyCookies.setEnabled(false);
+ }
+
// Enable Clear Cookies if there are any.
MenuItem clearCookies = menu.findItem(R.id.clearCookies);
clearCookies.setEnabled(cookieManager.hasCookies());
- // Enable Back if canGoBack().
- MenuItem back = menu.findItem(R.id.back);
- back.setEnabled(mainWebView.canGoBack());
-
- // Enable forward if canGoForward().
- MenuItem forward = menu.findItem(R.id.forward);
- forward.setEnabled(mainWebView.canGoForward());
-
// Run all the other default commands.
super.onPrepareOptionsMenu(menu);
}
@Override
- // @TargetApi(11) turns off the errors regarding copy and paste, which are removed from view in menu_webview.xml for lower version of Android.
- @TargetApi(11)
// Remove Android Studio's warning about the dangers of using SetJavaScriptEnabled.
@SuppressLint("SetJavaScriptEnabled")
// removeAllCookies is deprecated, but it is required for API < 21.
public boolean onOptionsItemSelected(MenuItem menuItem) {
int menuItemId = menuItem.getItemId();
- // Some options need to update the drawable for toggleJavaScript.
- MenuItem toggleJavaScript = mainMenu.findItem(R.id.toggleJavaScript);
-
// Set the commands that relate to the menu entries.
switch (menuItemId) {
case R.id.toggleJavaScript:
- if (javaScriptEnabled) {
- javaScriptEnabled = false;
- mainWebView.getSettings().setJavaScriptEnabled(false);
- mainWebView.reload();
+ // Switch the status of javaScriptEnabled.
+ javaScriptEnabled = !javaScriptEnabled;
+
+ // Apply the new JavaScript status.
+ mainWebView.getSettings().setJavaScriptEnabled(javaScriptEnabled);
- // Update the toggleJavaScript icon and display a toast message.
- if (domStorageEnabled || cookiesEnabled) {
- menuItem.setIcon(R.drawable.warning);
- if (domStorageEnabled && cookiesEnabled) {
- Toast.makeText(getApplicationContext(), "JavaScript disabled, DOM Storage and Cookies still enabled", Toast.LENGTH_SHORT).show();
- } else {
- if (domStorageEnabled) {
- Toast.makeText(getApplicationContext(), "JavaScript disabled, DOM Storage still enabled", Toast.LENGTH_SHORT).show();
- } else {
- Toast.makeText(getApplicationContext(), "JavaScript disabled, Cookies still enabled", Toast.LENGTH_SHORT).show();
- }
- }
+ // Update the privacy icon.
+ updatePrivacyIcon();
+
+ // Display a Snackbar.
+ if (javaScriptEnabled) {
+ Snackbar.make(findViewById(R.id.mainWebView), R.string.javascript_enabled, Snackbar.LENGTH_SHORT).show();
+ } else {
+ if (domStorageEnabled || firstPartyCookiesEnabled) {
+ Snackbar.make(findViewById(R.id.mainWebView), R.string.javascript_disabled, Snackbar.LENGTH_SHORT).show();
} else {
- menuItem.setIcon(R.drawable.privacy_mode);
- Toast.makeText(getApplicationContext(), "Privacy Mode", Toast.LENGTH_SHORT).show();
+ Snackbar.make(findViewById(R.id.mainWebView), R.string.privacy_mode, Snackbar.LENGTH_SHORT).show();
}
- } else {
- javaScriptEnabled = true;
- menuItem.setIcon(R.drawable.javascript_enabled);
- mainWebView.getSettings().setJavaScriptEnabled(true);
- mainWebView.reload();
- Toast.makeText(getApplicationContext(), "JavaScript enabled", Toast.LENGTH_SHORT).show();
}
+
+ // Reload the WebView.
+ mainWebView.reload();
return true;
- case R.id.toggleDomStorage:
- if (domStorageEnabled) {
- domStorageEnabled = false;
- menuItem.setChecked(false);
- mainWebView.getSettings().setDomStorageEnabled(false);
- mainWebView.reload();
+ case R.id.toggleFirstPartyCookies:
+ // Switch the status of firstPartyCookiesEnabled.
+ firstPartyCookiesEnabled = !firstPartyCookiesEnabled;
- // Update the toggleJavaScript icon and display a toast message if appropriate.
- if (!javaScriptEnabled && !cookiesEnabled) {
- toggleJavaScript.setIcon(R.drawable.privacy_mode);
- Toast.makeText(getApplicationContext(), "Privacy Mode", Toast.LENGTH_SHORT).show();
- } else {
- if (cookiesEnabled) {
- toggleJavaScript.setIcon(R.drawable.warning);
- Toast.makeText(getApplicationContext(), "Cookies still enabled", Toast.LENGTH_SHORT).show();
- } // Else Do nothing because JavaScript is enabled.
- }
- } else {
- domStorageEnabled = true;
- menuItem.setChecked(true);
- mainWebView.getSettings().setDomStorageEnabled(true);
- mainWebView.reload();
+ // Update the menu checkbox.
+ menuItem.setChecked(firstPartyCookiesEnabled);
- // Update the toggleJavaScript icon if appropriate.
- if (!javaScriptEnabled) {
- toggleJavaScript.setIcon(R.drawable.warning);
- } // Else Do nothing because JavaScript is enabled.
+ // Apply the new cookie status.
+ cookieManager.setAcceptCookie(firstPartyCookiesEnabled);
- Toast.makeText(getApplicationContext(), "DOM Storage enabled", Toast.LENGTH_SHORT).show();
- }
+ // Update the privacy icon.
+ updatePrivacyIcon();
+
+ // Reload the WebView.
+ mainWebView.reload();
return true;
- /* toggleSaveFormData does nothing until database storage is implemented.
- case R.id.toggleSaveFormData:
- if (saveFormDataEnabled) {
- saveFormDataEnabled = false;
- menuItem.setChecked(false);
- mainWebView.getSettings().setSaveFormData(false);
- mainWebView.reload();
- } else {
- saveFormDataEnabled = true;
- menuItem.setChecked(true);
- mainWebView.getSettings().setSaveFormData(true);
+ case R.id.toggleThirdPartyCookies:
+ if (Build.VERSION.SDK_INT >= 21) {
+ // Switch the status of thirdPartyCookiesEnabled.
+ thirdPartyCookiesEnabled = !thirdPartyCookiesEnabled;
+
+ // Update the menu checkbox.
+ menuItem.setChecked(thirdPartyCookiesEnabled);
+
+ // Apply the new cookie status.
+ cookieManager.setAcceptThirdPartyCookies(mainWebView, thirdPartyCookiesEnabled);
+
+ // Reload the WebView.
mainWebView.reload();
- }
+ } // Else do nothing because SDK < 21.
return true;
- */
- case R.id.toggleCookies:
- if (cookiesEnabled) {
- cookiesEnabled = false;
- menuItem.setChecked(false);
- cookieManager.setAcceptCookie(false);
- mainWebView.reload();
+ case R.id.toggleDomStorage:
+ // Switch the status of domStorageEnabled.
+ domStorageEnabled = !domStorageEnabled;
- // Update the toggleJavaScript icon and display a toast message if appropriate.
- if (!javaScriptEnabled && !domStorageEnabled) {
- toggleJavaScript.setIcon(R.drawable.privacy_mode);
- Toast.makeText(getApplicationContext(), "Privacy Mode", Toast.LENGTH_SHORT).show();
- } else {
- if (domStorageEnabled) {
- toggleJavaScript.setIcon(R.drawable.warning);
- Toast.makeText(getApplicationContext(), "DOM Storage still enabled", Toast.LENGTH_SHORT).show();
- } // Else Do nothing because JavaScript is enabled.
- }
- } else {
- cookiesEnabled = true;
- menuItem.setChecked(true);
- cookieManager.setAcceptCookie(true);
- mainWebView.reload();
+ // Update the menu checkbox.
+ menuItem.setChecked(domStorageEnabled);
- // Update the toggleJavaScript icon if appropriate.
- if (!javaScriptEnabled) {
- toggleJavaScript.setIcon(R.drawable.warning);
- } // Else Do nothing because JavaScript is enabled.
+ // Apply the new DOM Storage status.
+ mainWebView.getSettings().setDomStorageEnabled(domStorageEnabled);
- Toast.makeText(getApplicationContext(), "Cookies enabled", Toast.LENGTH_SHORT).show();
- }
- return true;
+ // Update the privacy icon.
+ updatePrivacyIcon();
- case R.id.clearDomStorage:
- WebStorage webStorage = WebStorage.getInstance();
- webStorage.deleteAllData();
- Toast.makeText(getApplicationContext(), "DOM storage deleted", Toast.LENGTH_SHORT).show();
+ // Reload the WebView.
+ mainWebView.reload();
return true;
case R.id.clearCookies:
} else {
cookieManager.removeAllCookies(null);
}
- Toast.makeText(getApplicationContext(), "Cookies deleted", Toast.LENGTH_SHORT).show();
+ Snackbar.make(findViewById(R.id.mainWebView), 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();
+ return true;
+
+ case R.id.share:
+ Intent shareIntent = new Intent();
+ shareIntent.setAction(Intent.ACTION_SEND);
+ shareIntent.putExtra(Intent.EXTRA_TEXT, urlTextBox.getText().toString());
+ shareIntent.setType("text/plain");
+ startActivity(Intent.createChooser(shareIntent, "Share URL"));
return true;
case R.id.addToHomescreen:
//Everything else will be handled by CreateHomeScreenShortcut and the associated listeners below.
return true;
- case R.id.downloads:
- // Launch the system Download Manager.
- Intent downloadManangerIntent = new Intent(DownloadManager.ACTION_VIEW_DOWNLOADS);
+ case R.id.refresh:
+ mainWebView.reload();
+ return true;
- // Launch as a new task so that Download Manager and Privacy Browser show as separate windows in the recent tasks list.
- downloadManangerIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+ default:
+ // Don't consume the event.
+ return super.onOptionsItemSelected(menuItem);
+ }
+ }
- startActivity(downloadManangerIntent);
- return true;
+ @Override
+ // removeAllCookies is deprecated, but it is required for API < 21.
+ @SuppressWarnings("deprecation")
+ public boolean onNavigationItemSelected(MenuItem menuItem) {
+ int menuItemId = menuItem.getItemId();
+ switch (menuItemId) {
case R.id.home:
mainWebView.loadUrl(homepage);
- return true;
-
- case R.id.refresh:
- mainWebView.reload();
- return true;
+ break;
case R.id.back:
- mainWebView.goBack();
- return true;
+ if (mainWebView.canGoBack()) {
+ mainWebView.goBack();
+ }
+ break;
case R.id.forward:
- mainWebView.goForward();
- return true;
+ if (mainWebView.canGoForward()) {
+ mainWebView.goForward();
+ }
+ break;
- case R.id.share:
- Intent shareIntent = new Intent();
- shareIntent.setAction(Intent.ACTION_SEND);
- shareIntent.putExtra(Intent.EXTRA_TEXT, urlTextBox.getText().toString());
- shareIntent.setType("text/plain");
- startActivity(Intent.createChooser(shareIntent, "Share URL"));
- return true;
+ case R.id.downloads:
+ // Launch the system Download Manager.
+ Intent downloadManagerIntent = new Intent(DownloadManager.ACTION_VIEW_DOWNLOADS);
+
+ // Launch as a new task so that Download Manager and Privacy Browser show as separate windows in the recent tasks list.
+ downloadManagerIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+
+ startActivity(downloadManagerIntent);
+ break;
case R.id.settings:
// Launch SettingsActivity.
- Intent intent = new Intent(this, SettingsActivity.class);
- startActivity(intent);
- return true;
+ Intent settingsIntent = new Intent(this, SettingsActivity.class);
+ startActivity(settingsIntent);
+ break;
case R.id.about:
- // Show the AboutDialog AlertDialog and name this instance aboutDialog.
- AppCompatDialogFragment aboutDialog = new AboutDialog();
- aboutDialog.show(getSupportFragmentManager(), "aboutDialog");
- return true;
+ // Launch AboutActivity.
+ Intent aboutIntent = new Intent(this, AboutActivity.class);
+ startActivity(aboutIntent);
+ break;
case R.id.clearAndExit:
// Clear DOM storage.
cookieManager.removeAllCookie();
}
+ // Clear cache. The argument of "true" includes disk files.
+ mainWebView.clearCache(true);
+
+ // Clear the back/forward history.
+ mainWebView.clearHistory();
+
// Destroy the internal state of the webview.
mainWebView.destroy();
} else {
finish();
}
- return true;
+ break;
default:
- return super.onOptionsItemSelected(menuItem);
+ break;
}
+
+ // Close the navigation drawer.
+ drawerLayout.closeDrawer(GravityCompat.START);
+ return true;
+ }
+
+ @Override
+ public void onPostCreate(Bundle savedInstanceState) {
+ super.onPostCreate(savedInstanceState);
+
+ // Sync the state of the DrawerToggle after onRestoreInstanceState has finished.
+ drawerToggle.syncState();
+ }
+
+ @Override
+ public void onConfigurationChanged(Configuration newConfig) {
+ super.onConfigurationChanged(newConfig);
+
+ // Reload the ad if this is the free flavor.
+ BannerAd.reloadAfterRotate(adView, getApplicationContext(), getString(R.string.ad_id));
+
+ // Reinitialize the adView variable, as the View will have been removed and re-added in the free flavor by BannerAd.reloadAfterRotate().
+ adView = findViewById(R.id.adView);
}
@Override
sendBroadcast(placeBookmarkShortcut);
}
- // Override onBackPressed so that if mainWebView can go back it does when the system back button is pressed.
+ // Override onBackPressed to handle the navigation drawer and mainWebView.
@Override
public void onBackPressed() {
final WebView mainWebView = (WebView) findViewById(R.id.mainWebView);
- if (mainWebView.canGoBack()) {
- mainWebView.goBack();
+ // 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);
} else {
- super.onBackPressed();
+ // Load the previous URL if available.
+ assert mainWebView != null; //This assert removes the incorrect warning on the following line that mainWebView might be null.
+ if (mainWebView.canGoBack()) {
+ mainWebView.goBack();
+ } else {
+ // Pass onBackPressed to the system.
+ super.onBackPressed();
+ }
}
}
- public void loadUrlFromTextBox() throws UnsupportedEncodingException {
+ @Override
+ public void onPause() {
+ // We need to pause the adView or it will continue to consume resources in the background on the free flavor.
+ BannerAd.pauseAd(adView);
+
+ super.onPause();
+ }
+
+ @Override
+ public void onResume() {
+ super.onResume();
+
+ // We need to resume the adView for the free flavor.
+ BannerAd.resumeAd(adView);
+ }
+
+ private void loadUrlFromTextBox() throws UnsupportedEncodingException {
// Get the text from urlTextBox and convert it to a string.
String unformattedUrlString = urlTextBox.getText().toString();
URL unformattedUrl = null;
// Use the correct search URL based on javaScriptEnabled.
if (javaScriptEnabled) {
- formattedUrlString = "https://duckduckgo.com/?q=" + encodedUrlString;
- } else {
- formattedUrlString = "https://duckduckgo.com/html/?q=" + encodedUrlString;
+ formattedUrlString = javaScriptEnabledSearchURL + encodedUrlString;
+ } else { // JavaScript is disabled.
+ formattedUrlString = javaScriptDisabledSearchURL + encodedUrlString;
}
}
InputMethodManager inputMethodManager = (InputMethodManager) getSystemService(Activity.INPUT_METHOD_SERVICE);
inputMethodManager.hideSoftInputFromWindow(mainWebView.getWindowToken(), 0);
}
+
+ private void updatePrivacyIcon() {
+ if (javaScriptEnabled) {
+ privacyIcon.setIcon(R.drawable.javascript_enabled);
+ } else {
+ if (domStorageEnabled || firstPartyCookiesEnabled) {
+ privacyIcon.setIcon(R.drawable.warning);
+ } else {
+ privacyIcon.setIcon(R.drawable.privacy_mode);
+ }
+ }
+ }
}