diff --git a/app/src/main/java/com/github/dfa/diaspora_android/activity/MainActivity.java b/app/src/main/java/com/github/dfa/diaspora_android/activity/MainActivity.java index ca01035f..6f7741fe 100644 --- a/app/src/main/java/com/github/dfa/diaspora_android/activity/MainActivity.java +++ b/app/src/main/java/com/github/dfa/diaspora_android/activity/MainActivity.java @@ -68,6 +68,7 @@ import com.github.dfa.diaspora_android.fragment.HashtagListFragment; import com.github.dfa.diaspora_android.fragment.PodSelectionFragment; import com.github.dfa.diaspora_android.listener.WebUserProfileChangedListener; import com.github.dfa.diaspora_android.receiver.OpenExternalLinkReceiver; +import com.github.dfa.diaspora_android.util.ProxyHandler; import com.github.dfa.diaspora_android.receiver.UpdateTitleReceiver; import com.github.dfa.diaspora_android.ui.BadgeDrawable; import com.github.dfa.diaspora_android.util.AppLog; @@ -77,7 +78,6 @@ import com.github.dfa.diaspora_android.util.WebHelper; import butterknife.BindView; import butterknife.ButterKnife; -import butterknife.OnClick; public class MainActivity extends AppCompatActivity implements NavigationView.OnNavigationItemSelectedListener, WebUserProfileChangedListener, CustomTabActivityHelper.ConnectionCallback { @@ -161,6 +161,7 @@ public class MainActivity extends AppCompatActivity urls = new DiasporaUrlHelper(appSettings); customTabActivityHelper = new CustomTabActivityHelper(); customTabActivityHelper.setConnectionCallback(this); + ProxyHandler.getInstance().updateProxySettings(this); fm = getSupportFragmentManager(); setupUI(); diff --git a/app/src/main/java/com/github/dfa/diaspora_android/activity/SettingsActivity.java b/app/src/main/java/com/github/dfa/diaspora_android/activity/SettingsActivity.java index af1f3860..5b45bbd0 100644 --- a/app/src/main/java/com/github/dfa/diaspora_android/activity/SettingsActivity.java +++ b/app/src/main/java/com/github/dfa/diaspora_android/activity/SettingsActivity.java @@ -18,7 +18,10 @@ */ package com.github.dfa.diaspora_android.activity; +import android.app.AlarmManager; import android.app.AlertDialog; +import android.app.PendingIntent; +import android.content.Context; import android.content.DialogInterface; import android.content.Intent; import android.content.SharedPreferences; @@ -35,20 +38,23 @@ import android.view.MenuItem; import com.github.dfa.diaspora_android.App; import com.github.dfa.diaspora_android.R; import com.github.dfa.diaspora_android.data.AppSettings; +import com.github.dfa.diaspora_android.util.ProxyHandler; import com.github.dfa.diaspora_android.util.AppLog; /** * @author vanitas */ public class SettingsActivity extends AppCompatActivity { - private boolean activityRestartRequired; - + private ProxyHandler.ProxySettings oldProxySettings; + private AppSettings appSettings; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); ActionBar toolbar = getSupportActionBar(); if (toolbar != null) toolbar.setDisplayHomeAsUpEnabled(true); + this.appSettings = new AppSettings(this); + oldProxySettings = appSettings.getProxySettings(); getFragmentManager().beginTransaction().replace(android.R.id.content, new SettingsFragment()).commit(); } @@ -63,10 +69,6 @@ public class SettingsActivity extends AppCompatActivity { } } - private void setActivityRestartRequired() { - this.activityRestartRequired = true; - } - public static class SettingsFragment extends PreferenceFragment implements SharedPreferences.OnSharedPreferenceChangeListener { private SharedPreferences sharedPreferences; @@ -94,15 +96,6 @@ public class SettingsActivity extends AppCompatActivity { @Override public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) { updatePreference(findPreference(key)); - if (key != null && isAdded() && (key.equals(getString(R.string.pref_key__font_size)) || - key.equals(getString(R.string.pref_key__load_images)) || - key.equals(getString(R.string.pref_key__intellihide_toolbars)) || - key.equals(getString(R.string.pref_key__http_proxy_enabled)) || - key.equals(getString(R.string.pref_key__http_proxy_host)) || - key.equals(getString(R.string.pref_key__http_proxy_port)) || - key.startsWith("pref_key__visibility_nav__"))) { - ((SettingsActivity) getActivity()).setActivityRestartRequired(); - } } private void updatePreference(Preference preference) { @@ -198,11 +191,21 @@ public class SettingsActivity extends AppCompatActivity { @Override protected void onStop() { - super.onStop(); - if (activityRestartRequired) { - Intent intent = new Intent(this, MainActivity.class); - intent.setAction(MainActivity.ACTION_RELOAD_ACTIVITY); - startActivity(intent); + ProxyHandler.ProxySettings newProxySettings = appSettings.getProxySettings(); + if(!oldProxySettings.equals(newProxySettings)) { + AppLog.d(this, "ProxySettings changed."); + //Proxy on-off? => Restart app + if(oldProxySettings.isEnabled() && !newProxySettings.isEnabled()) { + Intent restartActivity = new Intent(SettingsActivity.this, MainActivity.class); + PendingIntent pendingIntent = PendingIntent.getActivity(SettingsActivity.this, 12374, restartActivity, PendingIntent.FLAG_CANCEL_CURRENT); + AlarmManager mgr = (AlarmManager) SettingsActivity.this.getSystemService(Context.ALARM_SERVICE); + mgr.set(AlarmManager.RTC, System.currentTimeMillis() + 100, pendingIntent); + System.exit(0); + } //Proxy changed? => Update + else { + ProxyHandler.getInstance().updateProxySettings(this); + } } + super.onStop(); } } diff --git a/app/src/main/java/com/github/dfa/diaspora_android/data/AppSettings.java b/app/src/main/java/com/github/dfa/diaspora_android/data/AppSettings.java index 8d0160dd..6cb84890 100644 --- a/app/src/main/java/com/github/dfa/diaspora_android/data/AppSettings.java +++ b/app/src/main/java/com/github/dfa/diaspora_android/data/AppSettings.java @@ -23,6 +23,7 @@ import android.content.Context; import android.content.SharedPreferences; import com.github.dfa.diaspora_android.R; +import com.github.dfa.diaspora_android.util.ProxyHandler; /** * Settings @@ -259,6 +260,10 @@ public class AppSettings { setInt(prefApp, R.string.pref_key__http_proxy_port, value); } + public ProxyHandler.ProxySettings getProxySettings() { + return new ProxyHandler.ProxySettings(isProxyEnabled(), getProxyHost(), getProxyPort()); + } + public boolean isIntellihideToolbars() { return getBoolean(prefApp, R.string.pref_key__intellihide_toolbars, false); } diff --git a/app/src/main/java/com/github/dfa/diaspora_android/fragment/BrowserFragment.java b/app/src/main/java/com/github/dfa/diaspora_android/fragment/BrowserFragment.java index 70ee1054..fab00027 100644 --- a/app/src/main/java/com/github/dfa/diaspora_android/fragment/BrowserFragment.java +++ b/app/src/main/java/com/github/dfa/diaspora_android/fragment/BrowserFragment.java @@ -19,9 +19,6 @@ package com.github.dfa.diaspora_android.fragment; import android.Manifest; -import android.app.AlarmManager; -import android.app.PendingIntent; -import android.content.Context; import android.content.DialogInterface; import android.content.Intent; import android.content.pm.PackageManager; @@ -29,7 +26,6 @@ import android.graphics.Bitmap; import android.net.Uri; import android.os.Bundle; import android.os.Environment; -import android.os.StrictMode; import android.support.design.widget.Snackbar; import android.support.v7.app.AlertDialog; import android.view.LayoutInflater; @@ -40,16 +36,16 @@ import android.view.ViewGroup; import android.webkit.WebSettings; import android.webkit.WebView; import android.widget.ProgressBar; -import android.widget.Toast; import com.github.dfa.diaspora_android.App; import com.github.dfa.diaspora_android.R; import com.github.dfa.diaspora_android.activity.MainActivity; import com.github.dfa.diaspora_android.data.AppSettings; +import com.github.dfa.diaspora_android.util.ProxyHandler; import com.github.dfa.diaspora_android.ui.ContextMenuWebView; +import com.github.dfa.diaspora_android.util.AppLog; import com.github.dfa.diaspora_android.webview.CustomWebViewClient; import com.github.dfa.diaspora_android.webview.ProgressBarWebChromeClient; -import com.github.dfa.diaspora_android.util.AppLog; import java.io.File; import java.io.FileOutputStream; @@ -60,9 +56,6 @@ import java.text.SimpleDateFormat; import java.util.Date; import java.util.Locale; -import info.guardianproject.netcipher.NetCipher; -import info.guardianproject.netcipher.webkit.WebkitProxy; - /** * Fragment with a webView and a ProgressBar. * This Fragment retains its instance. @@ -102,21 +95,13 @@ public class BrowserFragment extends CustomFragment { if(this.webView == null) { this.webView = (ContextMenuWebView) view.findViewById(R.id.webView); this.applyWebViewSettings(); + ProxyHandler.getInstance().addWebView(webView); } if(this.progressBar == null) { this.progressBar = (ProgressBar) view.findViewById(R.id.progressBar); } - if (appSettings.isProxyEnabled()) { - if (!setProxy(appSettings.getProxyHost(), appSettings.getProxyPort())) { - AppLog.e(this, "Could not enable Proxy"); - Toast.makeText(getContext(), R.string.toast_set_proxy_failed, Toast.LENGTH_SHORT).show(); - } - } else if (appSettings.wasProxyEnabled()) { - resetProxy(); - } - if(pendingUrl != null) { loadUrl(pendingUrl); pendingUrl = null; @@ -160,86 +145,6 @@ public class BrowserFragment extends CustomFragment { webView.setWebChromeClient(new ProgressBarWebChromeClient(webView, progressBar)); } - /** - * Set proxy according to arguments. host must not be "" or null, port must be positive. - * Return true on success and update appSettings' proxy related values. - * - * @param host proxy host (eg. localhost or 127.0.0.1) - * @param port proxy port (eg. 8118) - * @return success - * @throws IllegalArgumentException if arguments do not fit specifications above - */ - private boolean setProxy(final String host, final int port) { - AppLog.i(this, "StreamFragment.setProxy()"); - if (host != null && !host.equals("") && port >= 0) { - AppLog.i(this, "Set proxy to "+host+":"+port); - //Temporary change thread policy - AppLog.v(this, "Set temporary ThreadPolicy"); - StrictMode.ThreadPolicy old = StrictMode.getThreadPolicy(); - StrictMode.ThreadPolicy tmp = new StrictMode.ThreadPolicy.Builder().permitAll().build(); - StrictMode.setThreadPolicy(tmp); - - AppLog.v(this, "Apply NetCipher proxy settings"); - NetCipher.setProxy(host, port); //Proxy for HttpsUrlConnections - try { - //Proxy for the webview - AppLog.v(this, "Apply Webkit proxy settings"); - WebkitProxy.setProxy(MainActivity.class.getName(), getContext().getApplicationContext(), null, host, port); - } catch (Exception e) { - AppLog.e(this, "Could not apply WebKit proxy settings:\n"+e.toString()); - } - AppLog.v(this, "Save changes in appSettings"); - appSettings.setProxyEnabled(true); - appSettings.setProxyWasEnabled(true); - - AppLog.v(this, "Reset old ThreadPolicy"); - StrictMode.setThreadPolicy(old); - AppLog.i(this, "Success! Reload WebView"); - webView.reload(); - return true; - } else { - AppLog.e(this, "Invalid proxy configuration. Host: "+host+" Port: "+port+"\nRefuse to set proxy"); - return false; - } - } - - @SuppressWarnings("unused") - private boolean setProxy() { - return setProxy(appSettings.getProxyHost(), appSettings.getProxyPort()); - } - - private void resetProxy() { - AppLog.i(this, "StreamFragment.resetProxy()"); - AppLog.v(this, "write changes to appSettings"); - appSettings.setProxyEnabled(false); - appSettings.setProxyWasEnabled(false); - - //Temporary change thread policy - AppLog.v(this, "Set temporary ThreadPolicy"); - StrictMode.ThreadPolicy old = StrictMode.getThreadPolicy(); - StrictMode.ThreadPolicy tmp = new StrictMode.ThreadPolicy.Builder().permitAll().build(); - StrictMode.setThreadPolicy(tmp); - - AppLog.v(this, "clear NetCipher proxy"); - NetCipher.clearProxy(); - try { - AppLog.v(this, "clear WebKit proxy"); - WebkitProxy.resetProxy(MainActivity.class.getName(), getContext()); - } catch (Exception e) { - AppLog.e(this, "Could not clear WebKit proxy:\n"+e.toString()); - } - AppLog.v(this, "Reset old ThreadPolicy"); - StrictMode.setThreadPolicy(old); - - //Restart app - AppLog.i(this, "Success! Restart app due to proxy reset"); - Intent restartActivity = new Intent(getContext(), MainActivity.class); - PendingIntent pendingIntent = PendingIntent.getActivity(getContext(), 12374, restartActivity, PendingIntent.FLAG_CANCEL_CURRENT); - AlarmManager mgr = (AlarmManager) getActivity().getSystemService(Context.ALARM_SERVICE); - mgr.set(AlarmManager.RTC, System.currentTimeMillis() + 100, pendingIntent); - System.exit(0); - } - @SuppressWarnings("ResultOfMethodCallIgnored") protected boolean makeScreenshotOfWebView(boolean hasToShareScreenshot) { AppLog.i(this, "StreamFragment.makeScreenshotOfWebView()"); diff --git a/app/src/main/java/com/github/dfa/diaspora_android/util/ProxyHandler.java b/app/src/main/java/com/github/dfa/diaspora_android/util/ProxyHandler.java new file mode 100644 index 00000000..a2cbf924 --- /dev/null +++ b/app/src/main/java/com/github/dfa/diaspora_android/util/ProxyHandler.java @@ -0,0 +1,135 @@ +/* + This file is part of the Diaspora for Android. + + Diaspora for Android is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + Diaspora for Android is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with the Diaspora for Android. + + If not, see . + */ +package com.github.dfa.diaspora_android.util; + +import android.content.Context; +import android.os.StrictMode; +import android.webkit.WebView; + +import com.github.dfa.diaspora_android.activity.MainActivity; +import com.github.dfa.diaspora_android.data.AppSettings; + +import java.util.ArrayList; + +import info.guardianproject.netcipher.NetCipher; +import info.guardianproject.netcipher.webkit.WebkitProxy; + +/** + * Proxy Handler that applies proxy settings of the app to webviews etc. + * Created by vanitas on 10.10.16. + */ + +public class ProxyHandler { + private static ProxyHandler instance; + private ArrayList webViews; + + + private ProxyHandler() { + /* Singleton, yo? */ + this.webViews = new ArrayList<>(); + } + + public static ProxyHandler getInstance() { + if(instance == null) { + instance = new ProxyHandler(); + } + return instance; + } + + public void updateProxySettings(Context context) { + AppLog.d(this, "UpdateProxySettings()"); + AppSettings appSettings = new AppSettings(context); + StrictMode.ThreadPolicy old = StrictMode.getThreadPolicy(); + StrictMode.ThreadPolicy tmp = new StrictMode.ThreadPolicy.Builder().permitAll().build(); + StrictMode.setThreadPolicy(tmp); + if (appSettings.isProxyEnabled()) { + //Update NetCipher + NetCipher.setProxy(appSettings.getProxyHost(), appSettings.getProxyPort()); + //Update webviews + for (WebView wv : webViews) { + if (wv != null) { + try { + WebkitProxy.setProxy(MainActivity.class.getName(), context.getApplicationContext(), wv, appSettings.getProxyHost(), appSettings.getProxyPort()); + } catch (Exception e) { + e.printStackTrace(); + } + } + } + } + StrictMode.setThreadPolicy(old); + } + + public void addWebView(WebView wv) { + AppLog.d(this, "AddWebView"); + if(wv != null && !webViews.contains(wv)) { + webViews.add(wv); + updateWebViewProxySettings(wv, wv.getContext()); + } + } + + private void updateWebViewProxySettings(WebView wv, Context context) { + AppLog.d(this, "UpdateWebViewProxySettings()"); + AppSettings appSettings = new AppSettings(context); + StrictMode.ThreadPolicy old = StrictMode.getThreadPolicy(); + StrictMode.ThreadPolicy tmp = new StrictMode.ThreadPolicy.Builder().permitAll().build(); + StrictMode.setThreadPolicy(tmp); + if(appSettings.isProxyEnabled()) { + if (wv != null) { + try { + WebkitProxy.setProxy(MainActivity.class.getName(), context.getApplicationContext(), wv, appSettings.getProxyHost(), appSettings.getProxyPort()); + } catch (Exception e) { + e.printStackTrace(); + } + } + } + StrictMode.setThreadPolicy(old); + } + + public static class ProxySettings { + private final boolean enabled; + private final String host; + private final int port; + + public ProxySettings(boolean enabled, String host, int port) { + this.enabled = enabled; + this.host = host; + this.port = port; + } + + public boolean isEnabled() { + return enabled; + } + + public String getHost() { + return host; + } + + public int getPort() { + return port; + } + + @Override + public boolean equals(Object other) { + return (other instanceof ProxySettings) && + enabled == ((ProxySettings) other).isEnabled() && + host.equals(((ProxySettings) other).getHost()) && + port == ((ProxySettings) other).getPort(); + } + } +}