From 7a0c79d11ee1f0a19ebf61b37b8ebd53eee6eb57 Mon Sep 17 00:00:00 2001 From: Anthony Restaino Date: Fri, 30 Oct 2015 23:33:35 -0400 Subject: [PATCH] Add support to remove identifying headers, add support for DNT header requests --- .../fragment/GeneralSettingsFragment.java | 5 ++- .../fragment/PrivacySettingsFragment.java | 42 +++++++++++-------- .../preference/PreferenceManager.java | 18 ++++++++ .../browser/lightning/view/LightningView.java | 37 ++++++++++++---- .../lightning/view/LightningWebClient.java | 27 +++++++----- app/src/main/res/values/strings.xml | 2 + app/src/main/res/xml/preference_privacy.xml | 30 ++++++++----- 7 files changed, 114 insertions(+), 47 deletions(-) diff --git a/app/src/main/java/acr/browser/lightning/fragment/GeneralSettingsFragment.java b/app/src/main/java/acr/browser/lightning/fragment/GeneralSettingsFragment.java index 53cfa12..1272810 100644 --- a/app/src/main/java/acr/browser/lightning/fragment/GeneralSettingsFragment.java +++ b/app/src/main/java/acr/browser/lightning/fragment/GeneralSettingsFragment.java @@ -528,7 +528,10 @@ public class GeneralSettingsFragment extends LightningPreferenceFragment impleme @Override public boolean onPreferenceChange(Preference preference, Object newValue) { - boolean checked = (Boolean) newValue; + boolean checked = false; + if (newValue instanceof Boolean) { + checked = (Boolean) newValue; + } switch (preference.getKey()) { case SETTINGS_FLASH: if (!Utils.isFlashInstalled(mActivity) && checked) { diff --git a/app/src/main/java/acr/browser/lightning/fragment/PrivacySettingsFragment.java b/app/src/main/java/acr/browser/lightning/fragment/PrivacySettingsFragment.java index 2ea48aa..f678ba6 100644 --- a/app/src/main/java/acr/browser/lightning/fragment/PrivacySettingsFragment.java +++ b/app/src/main/java/acr/browser/lightning/fragment/PrivacySettingsFragment.java @@ -17,6 +17,7 @@ import android.webkit.WebView; import acr.browser.lightning.R; import acr.browser.lightning.utils.Utils; import acr.browser.lightning.utils.WebUtils; +import acr.browser.lightning.view.LightningView; public class PrivacySettingsFragment extends LightningPreferenceFragment implements Preference.OnPreferenceClickListener, Preference.OnPreferenceChangeListener { @@ -31,10 +32,10 @@ public class PrivacySettingsFragment extends LightningPreferenceFragment impleme private static final String SETTINGS_CLEARCOOKIES = "clear_cookies"; private static final String SETTINGS_CLEARWEBSTORAGE = "clear_webstorage"; private static final String SETTINGS_WEBSTORAGEEXIT = "clear_webstorage_exit"; + private static final String SETTINGS_DONOTTRACK = "do_not_track"; + private static final String SETTINGS_INVASIVEHEADERS = "remove_identifying_headers"; private Activity mActivity; - private CheckBoxPreference cblocation, cb3cookies, cbsavepasswords, cbcacheexit, cbhistoryexit, - cbcookiesexit, cbwebstorageexit; private Handler messageHandler; @Override @@ -54,13 +55,15 @@ public class PrivacySettingsFragment extends LightningPreferenceFragment impleme Preference clearcookies = findPreference(SETTINGS_CLEARCOOKIES); Preference clearwebstorage = findPreference(SETTINGS_CLEARWEBSTORAGE); - cblocation = (CheckBoxPreference) findPreference(SETTINGS_LOCATION); - cb3cookies = (CheckBoxPreference) findPreference(SETTINGS_THIRDPCOOKIES); - cbsavepasswords = (CheckBoxPreference) findPreference(SETTINGS_SAVEPASSWORD); - cbcacheexit = (CheckBoxPreference) findPreference(SETTINGS_CACHEEXIT); - cbhistoryexit = (CheckBoxPreference) findPreference(SETTINGS_HISTORYEXIT); - cbcookiesexit = (CheckBoxPreference) findPreference(SETTINGS_COOKIEEXIT); - cbwebstorageexit = (CheckBoxPreference) findPreference(SETTINGS_WEBSTORAGEEXIT); + CheckBoxPreference cblocation = (CheckBoxPreference) findPreference(SETTINGS_LOCATION); + CheckBoxPreference cb3cookies = (CheckBoxPreference) findPreference(SETTINGS_THIRDPCOOKIES); + CheckBoxPreference cbsavepasswords = (CheckBoxPreference) findPreference(SETTINGS_SAVEPASSWORD); + CheckBoxPreference cbcacheexit = (CheckBoxPreference) findPreference(SETTINGS_CACHEEXIT); + CheckBoxPreference cbhistoryexit = (CheckBoxPreference) findPreference(SETTINGS_HISTORYEXIT); + CheckBoxPreference cbcookiesexit = (CheckBoxPreference) findPreference(SETTINGS_COOKIEEXIT); + CheckBoxPreference cbwebstorageexit = (CheckBoxPreference) findPreference(SETTINGS_WEBSTORAGEEXIT); + CheckBoxPreference cbDoNotTrack = (CheckBoxPreference) findPreference(SETTINGS_DONOTTRACK); + CheckBoxPreference cbIdentifyingHeaders = (CheckBoxPreference) findPreference(SETTINGS_INVASIVEHEADERS); clearcache.setOnPreferenceClickListener(this); clearhistory.setOnPreferenceClickListener(this); @@ -74,6 +77,8 @@ public class PrivacySettingsFragment extends LightningPreferenceFragment impleme cbhistoryexit.setOnPreferenceChangeListener(this); cbcookiesexit.setOnPreferenceChangeListener(this); cbwebstorageexit.setOnPreferenceChangeListener(this); + cbDoNotTrack.setOnPreferenceChangeListener(this); + cbIdentifyingHeaders.setOnPreferenceChangeListener(this); cblocation.setChecked(mPreferenceManager.getLocationEnabled()); cbsavepasswords.setChecked(mPreferenceManager.getSavePasswordsEnabled()); @@ -82,6 +87,11 @@ public class PrivacySettingsFragment extends LightningPreferenceFragment impleme cbcookiesexit.setChecked(mPreferenceManager.getClearCookiesExitEnabled()); cb3cookies.setChecked(mPreferenceManager.getBlockThirdPartyCookiesEnabled()); cbwebstorageexit.setChecked(mPreferenceManager.getClearWebStorageExitEnabled()); + cbDoNotTrack.setChecked(mPreferenceManager.getDoNotTrackEnabled()); + cbIdentifyingHeaders.setChecked(mPreferenceManager.getRemoveIdentifyingHeadersEnabled()); + + String identifyingHeadersSummary = LightningView.HEADER_REQUESTED_WITH + ", " + LightningView.HEADER_WAP_PROFILE; + cbIdentifyingHeaders.setSummary(identifyingHeadersSummary); cb3cookies.setEnabled(Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP); @@ -194,35 +204,33 @@ public class PrivacySettingsFragment extends LightningPreferenceFragment impleme @Override public boolean onPreferenceChange(Preference preference, Object newValue) { - // switch preferences switch (preference.getKey()) { case SETTINGS_LOCATION: mPreferenceManager.setLocationEnabled((Boolean) newValue); - cblocation.setChecked((Boolean) newValue); return true; case SETTINGS_THIRDPCOOKIES: mPreferenceManager.setBlockThirdPartyCookiesEnabled((Boolean) newValue); - cb3cookies.setChecked((Boolean) newValue); return true; case SETTINGS_SAVEPASSWORD: mPreferenceManager.setSavePasswordsEnabled((Boolean) newValue); - cbsavepasswords.setChecked((Boolean) newValue); return true; case SETTINGS_CACHEEXIT: mPreferenceManager.setClearCacheExit((Boolean) newValue); - cbcacheexit.setChecked((Boolean) newValue); return true; case SETTINGS_HISTORYEXIT: mPreferenceManager.setClearHistoryExitEnabled((Boolean) newValue); - cbhistoryexit.setChecked((Boolean) newValue); return true; case SETTINGS_COOKIEEXIT: mPreferenceManager.setClearCookiesExitEnabled((Boolean) newValue); - cbcookiesexit.setChecked((Boolean) newValue); return true; case SETTINGS_WEBSTORAGEEXIT: mPreferenceManager.setClearWebStorageExitEnabled((Boolean) newValue); - cbwebstorageexit.setChecked((Boolean) newValue); + return true; + case SETTINGS_DONOTTRACK: + mPreferenceManager.setDoNotTrackEnabled((Boolean) newValue); + return true; + case SETTINGS_INVASIVEHEADERS: + mPreferenceManager.setRemoveIdentifyingHeadersEnabled((Boolean) newValue); return true; default: return false; diff --git a/app/src/main/java/acr/browser/lightning/preference/PreferenceManager.java b/app/src/main/java/acr/browser/lightning/preference/PreferenceManager.java index 401a670..f1656c2 100644 --- a/app/src/main/java/acr/browser/lightning/preference/PreferenceManager.java +++ b/app/src/main/java/acr/browser/lightning/preference/PreferenceManager.java @@ -51,6 +51,8 @@ public class PreferenceManager { public static final String TEXT_ENCODING = "textEncoding"; public static final String CLEAR_WEBSTORAGE_EXIT = "clearWebStorageExit"; public static final String SHOW_TABS_IN_DRAWER = "showTabsInDrawer"; + public static final String DO_NOT_TRACK = "doNotTrack"; + public static final String INVASIVE_HEADERS = "removeInvasiveHeaders"; public static final String USE_PROXY = "useProxy"; public static final String PROXY_CHOICE = "proxyChoice"; @@ -245,6 +247,14 @@ public class PreferenceManager { return mPrefs.getBoolean(Name.SHOW_TABS_IN_DRAWER, defaultValue); } + public boolean getDoNotTrackEnabled() { + return mPrefs.getBoolean(Name.DO_NOT_TRACK, false); + } + + public boolean getRemoveIdentifyingHeadersEnabled(){ + return mPrefs.getBoolean(Name.INVASIVE_HEADERS, false); + } + private void putBoolean(String name, boolean value) { mPrefs.edit().putBoolean(name, value).apply(); } @@ -257,6 +267,14 @@ public class PreferenceManager { mPrefs.edit().putString(name, value).apply(); } + public void setRemoveIdentifyingHeadersEnabled(boolean enabled){ + putBoolean(Name.INVASIVE_HEADERS, enabled); + } + + public void setDoNotTrackEnabled(boolean doNotTrack) { + putBoolean(Name.DO_NOT_TRACK, doNotTrack); + } + public void setShowTabsInDrawer(boolean show) { putBoolean(Name.SHOW_TABS_IN_DRAWER, show); } diff --git a/app/src/main/java/acr/browser/lightning/view/LightningView.java b/app/src/main/java/acr/browser/lightning/view/LightningView.java index 34300ee..fc27b47 100644 --- a/app/src/main/java/acr/browser/lightning/view/LightningView.java +++ b/app/src/main/java/acr/browser/lightning/view/LightningView.java @@ -18,6 +18,7 @@ import android.os.Handler; import android.os.Message; import android.support.annotation.NonNull; import android.support.annotation.Nullable; +import android.support.v4.util.ArrayMap; import android.util.Log; import android.view.GestureDetector; import android.view.GestureDetector.SimpleOnGestureListener; @@ -37,6 +38,7 @@ import java.io.File; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.lang.ref.WeakReference; +import java.util.Map; import javax.inject.Inject; @@ -58,6 +60,10 @@ import acr.browser.lightning.utils.Utils; public class LightningView { + public static final String HEADER_REQUESTED_WITH = "X-Requested-With"; + public static final String HEADER_WAP_PROFILE = "X-Wap-Profile"; + public static final String HEADER_DNT = "DNT"; + final LightningViewTitle mTitle; private WebView mWebView; final boolean mIsIncognitoTab; @@ -80,6 +86,7 @@ public class LightningView { 0, 0, 0, 1.0f, 0 // alpha }; private final WebViewHandler mWebViewHandler = new WebViewHandler(this); + private final Map mRequestHeaders = new ArrayMap<>(); @Inject Bus mEventBus; @@ -128,7 +135,7 @@ public class LightningView { if (url != null) { if (!url.trim().isEmpty()) { - mWebView.loadUrl(url); + mWebView.loadUrl(url, mRequestHeaders); } else { // don't load anything, the user is looking for a blank tab } @@ -142,11 +149,11 @@ public class LightningView { return; } if (mHomepage.startsWith("about:home")) { - mWebView.loadUrl(StartPage.getHomepage(mActivity)); + mWebView.loadUrl(StartPage.getHomepage(mActivity), mRequestHeaders); } else if (mHomepage.startsWith("about:bookmarks")) { loadBookmarkpage(); } else { - mWebView.loadUrl(mHomepage); + mWebView.loadUrl(mHomepage, mRequestHeaders); } } @@ -171,7 +178,7 @@ public class LightningView { File bookmarkWebPage = new File(mActivity.getFilesDir(), BookmarkPage.FILENAME); BrowserApp.getAppComponent().getBookmarkPage().buildBookmarkPage(null); - mWebView.loadUrl(Constants.FILE + bookmarkWebPage); + mWebView.loadUrl(Constants.FILE + bookmarkWebPage, mRequestHeaders); } @@ -182,7 +189,7 @@ public class LightningView { * if you don't have a reference to them * @param context the context in which the WebView was created */ - @SuppressLint("NewApi") + @SuppressLint({"NewApi", "SetJavaScriptEnabled"}) public synchronized void initializePreferences(@Nullable WebSettings settings, Context context) { if (settings == null && mWebView == null) { return; @@ -190,6 +197,17 @@ public class LightningView { settings = mWebView.getSettings(); } + if (mPreferences.getDoNotTrackEnabled()) { + mRequestHeaders.put(HEADER_DNT, "1"); + } else { + mRequestHeaders.remove(HEADER_DNT); + } + + if (mPreferences.getRemoveIdentifyingHeadersEnabled()) { + mRequestHeaders.put(HEADER_REQUESTED_WITH, ""); + mRequestHeaders.put(HEADER_WAP_PROFILE, ""); + } + settings.setDefaultTextEncodingName(mPreferences.getTextEncoding()); mHomepage = mPreferences.getHomepage(); setColorMode(mPreferences.getRenderingMode()); @@ -384,6 +402,11 @@ public class LightningView { } } + @NonNull + protected Map getRequestHeaders() { + return mRequestHeaders; + } + public boolean isShown() { return mWebView != null && mWebView.isShown(); } @@ -679,7 +702,7 @@ public class LightningView { } if (mWebView != null) { - mWebView.loadUrl(url); + mWebView.loadUrl(url, mRequestHeaders); } } @@ -784,7 +807,7 @@ public class LightningView { private static class WebViewHandler extends Handler { - private WeakReference mReference; + private final WeakReference mReference; public WebViewHandler(LightningView view) { mReference = new WeakReference<>(view); diff --git a/app/src/main/java/acr/browser/lightning/view/LightningWebClient.java b/app/src/main/java/acr/browser/lightning/view/LightningWebClient.java index fec911b..5e48f16 100644 --- a/app/src/main/java/acr/browser/lightning/view/LightningWebClient.java +++ b/app/src/main/java/acr/browser/lightning/view/LightningWebClient.java @@ -30,6 +30,7 @@ import java.io.ByteArrayInputStream; import java.net.URISyntaxException; import java.util.ArrayList; import java.util.List; +import java.util.Map; import acr.browser.lightning.R; import acr.browser.lightning.app.BrowserApp; @@ -41,12 +42,9 @@ import acr.browser.lightning.utils.IntentUtils; import acr.browser.lightning.utils.ProxyUtils; import acr.browser.lightning.utils.Utils; -/** - * @author Stefano Pacifici based on Anthony C. Restaino's code - * @date 2015/09/22 - */ class LightningWebClient extends WebViewClient { + private final Activity mActivity; private final LightningView mLightningView; private final UIController mUIController; @@ -152,7 +150,6 @@ class LightningWebClient extends WebViewClient { @Override public void onClick(DialogInterface dialog, int id) { handler.cancel(); - } }); AlertDialog alert = builder.create(); @@ -275,13 +272,17 @@ class LightningWebClient extends WebViewClient { return true; } + Map headers = mLightningView.getRequestHeaders(); + if (mLightningView.mIsIncognitoTab) { - return super.shouldOverrideUrlLoading(view, url); + view.loadUrl(url, headers); + return true; } if (url.startsWith("about:")) { - return super.shouldOverrideUrlLoading(view, url); + view.loadUrl(url, headers); + return true; } - if (url.contains("mailto:")) { + if (url.startsWith("mailto:")) { MailTo mailTo = MailTo.parse(url); Intent i = Utils.newEmailIntent(mailTo.getTo(), mailTo.getSubject(), mailTo.getBody(), mailTo.getCc()); @@ -292,8 +293,8 @@ class LightningWebClient extends WebViewClient { Intent intent; try { intent = Intent.parseUri(url, Intent.URI_INTENT_SCHEME); - } catch (URISyntaxException ex) { - return false; + } catch (URISyntaxException ignored) { + intent = null; } if (intent != null) { intent.addCategory(Intent.CATEGORY_BROWSABLE); @@ -309,6 +310,10 @@ class LightningWebClient extends WebViewClient { return true; } } - return mIntentUtils.startActivityForUrl(view, url); + + if (!mIntentUtils.startActivityForUrl(view, url)) { + view.loadUrl(url, headers); + } + return true; } } diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 2e7ef0e..a8ec00f 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -224,4 +224,6 @@ Hosts File Ad Blocking Source Ad Block Settings Show tabs in Navigation Drawer + Request \'Do Not Track\' + Remove Identifying Headers diff --git a/app/src/main/res/xml/preference_privacy.xml b/app/src/main/res/xml/preference_privacy.xml index bf709e3..0b74e84 100644 --- a/app/src/main/res/xml/preference_privacy.xml +++ b/app/src/main/res/xml/preference_privacy.xml @@ -5,43 +5,51 @@ + android:title="@string/location"/> + android:title="@string/third_party"/> + android:title="@string/password"/> + + + android:title="@string/cache"/> + android:title="@string/clear_history_exit"/> + android:title="@string/clear_cookies_exit"/> + android:title="@string/clear_web_storage_exit"/> + android:title="@string/clear_cache"/> + android:title="@string/title_clear_history"/> + android:title="@string/clear_cookies"/> + android:title="@string/clear_web_storage"/> \ No newline at end of file