1
0
Fork 0
mirror of https://github.com/gsantner/dandelion synced 2024-09-27 18:29:37 +02:00

Fixed applying proxy settings

This commit is contained in:
vanitasvitae 2016-10-10 17:47:04 +02:00
parent c09618f191
commit f49877b792
Signed by: vanitasvitae
GPG key ID: DCCFB3302C9E4615
5 changed files with 168 additions and 119 deletions

View file

@ -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.fragment.PodSelectionFragment;
import com.github.dfa.diaspora_android.listener.WebUserProfileChangedListener; import com.github.dfa.diaspora_android.listener.WebUserProfileChangedListener;
import com.github.dfa.diaspora_android.receiver.OpenExternalLinkReceiver; 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.receiver.UpdateTitleReceiver;
import com.github.dfa.diaspora_android.ui.BadgeDrawable; import com.github.dfa.diaspora_android.ui.BadgeDrawable;
import com.github.dfa.diaspora_android.util.AppLog; 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.BindView;
import butterknife.ButterKnife; import butterknife.ButterKnife;
import butterknife.OnClick;
public class MainActivity extends AppCompatActivity public class MainActivity extends AppCompatActivity
implements NavigationView.OnNavigationItemSelectedListener, WebUserProfileChangedListener, CustomTabActivityHelper.ConnectionCallback { implements NavigationView.OnNavigationItemSelectedListener, WebUserProfileChangedListener, CustomTabActivityHelper.ConnectionCallback {
@ -161,6 +161,7 @@ public class MainActivity extends AppCompatActivity
urls = new DiasporaUrlHelper(appSettings); urls = new DiasporaUrlHelper(appSettings);
customTabActivityHelper = new CustomTabActivityHelper(); customTabActivityHelper = new CustomTabActivityHelper();
customTabActivityHelper.setConnectionCallback(this); customTabActivityHelper.setConnectionCallback(this);
ProxyHandler.getInstance().updateProxySettings(this);
fm = getSupportFragmentManager(); fm = getSupportFragmentManager();
setupUI(); setupUI();

View file

@ -18,7 +18,10 @@
*/ */
package com.github.dfa.diaspora_android.activity; package com.github.dfa.diaspora_android.activity;
import android.app.AlarmManager;
import android.app.AlertDialog; import android.app.AlertDialog;
import android.app.PendingIntent;
import android.content.Context;
import android.content.DialogInterface; import android.content.DialogInterface;
import android.content.Intent; import android.content.Intent;
import android.content.SharedPreferences; 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.App;
import com.github.dfa.diaspora_android.R; import com.github.dfa.diaspora_android.R;
import com.github.dfa.diaspora_android.data.AppSettings; import com.github.dfa.diaspora_android.data.AppSettings;
import com.github.dfa.diaspora_android.util.ProxyHandler;
import com.github.dfa.diaspora_android.util.AppLog; import com.github.dfa.diaspora_android.util.AppLog;
/** /**
* @author vanitas * @author vanitas
*/ */
public class SettingsActivity extends AppCompatActivity { public class SettingsActivity extends AppCompatActivity {
private boolean activityRestartRequired; private ProxyHandler.ProxySettings oldProxySettings;
private AppSettings appSettings;
@Override @Override
public void onCreate(Bundle savedInstanceState) { public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState); super.onCreate(savedInstanceState);
ActionBar toolbar = getSupportActionBar(); ActionBar toolbar = getSupportActionBar();
if (toolbar != null) if (toolbar != null)
toolbar.setDisplayHomeAsUpEnabled(true); toolbar.setDisplayHomeAsUpEnabled(true);
this.appSettings = new AppSettings(this);
oldProxySettings = appSettings.getProxySettings();
getFragmentManager().beginTransaction().replace(android.R.id.content, new SettingsFragment()).commit(); 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 { public static class SettingsFragment extends PreferenceFragment implements SharedPreferences.OnSharedPreferenceChangeListener {
private SharedPreferences sharedPreferences; private SharedPreferences sharedPreferences;
@ -94,15 +96,6 @@ public class SettingsActivity extends AppCompatActivity {
@Override @Override
public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) { public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) {
updatePreference(findPreference(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) { private void updatePreference(Preference preference) {
@ -198,11 +191,21 @@ public class SettingsActivity extends AppCompatActivity {
@Override @Override
protected void onStop() { protected void onStop() {
super.onStop(); ProxyHandler.ProxySettings newProxySettings = appSettings.getProxySettings();
if (activityRestartRequired) { if(!oldProxySettings.equals(newProxySettings)) {
Intent intent = new Intent(this, MainActivity.class); AppLog.d(this, "ProxySettings changed.");
intent.setAction(MainActivity.ACTION_RELOAD_ACTIVITY); //Proxy on-off? => Restart app
startActivity(intent); 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();
}
} }

View file

@ -23,6 +23,7 @@ import android.content.Context;
import android.content.SharedPreferences; import android.content.SharedPreferences;
import com.github.dfa.diaspora_android.R; import com.github.dfa.diaspora_android.R;
import com.github.dfa.diaspora_android.util.ProxyHandler;
/** /**
* Settings * Settings
@ -259,6 +260,10 @@ public class AppSettings {
setInt(prefApp, R.string.pref_key__http_proxy_port, value); setInt(prefApp, R.string.pref_key__http_proxy_port, value);
} }
public ProxyHandler.ProxySettings getProxySettings() {
return new ProxyHandler.ProxySettings(isProxyEnabled(), getProxyHost(), getProxyPort());
}
public boolean isIntellihideToolbars() { public boolean isIntellihideToolbars() {
return getBoolean(prefApp, R.string.pref_key__intellihide_toolbars, false); return getBoolean(prefApp, R.string.pref_key__intellihide_toolbars, false);
} }

View file

@ -19,9 +19,6 @@
package com.github.dfa.diaspora_android.fragment; package com.github.dfa.diaspora_android.fragment;
import android.Manifest; import android.Manifest;
import android.app.AlarmManager;
import android.app.PendingIntent;
import android.content.Context;
import android.content.DialogInterface; import android.content.DialogInterface;
import android.content.Intent; import android.content.Intent;
import android.content.pm.PackageManager; import android.content.pm.PackageManager;
@ -29,7 +26,6 @@ import android.graphics.Bitmap;
import android.net.Uri; import android.net.Uri;
import android.os.Bundle; import android.os.Bundle;
import android.os.Environment; import android.os.Environment;
import android.os.StrictMode;
import android.support.design.widget.Snackbar; import android.support.design.widget.Snackbar;
import android.support.v7.app.AlertDialog; import android.support.v7.app.AlertDialog;
import android.view.LayoutInflater; import android.view.LayoutInflater;
@ -40,16 +36,16 @@ import android.view.ViewGroup;
import android.webkit.WebSettings; import android.webkit.WebSettings;
import android.webkit.WebView; import android.webkit.WebView;
import android.widget.ProgressBar; import android.widget.ProgressBar;
import android.widget.Toast;
import com.github.dfa.diaspora_android.App; import com.github.dfa.diaspora_android.App;
import com.github.dfa.diaspora_android.R; import com.github.dfa.diaspora_android.R;
import com.github.dfa.diaspora_android.activity.MainActivity; import com.github.dfa.diaspora_android.activity.MainActivity;
import com.github.dfa.diaspora_android.data.AppSettings; 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.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.CustomWebViewClient;
import com.github.dfa.diaspora_android.webview.ProgressBarWebChromeClient; import com.github.dfa.diaspora_android.webview.ProgressBarWebChromeClient;
import com.github.dfa.diaspora_android.util.AppLog;
import java.io.File; import java.io.File;
import java.io.FileOutputStream; import java.io.FileOutputStream;
@ -60,9 +56,6 @@ import java.text.SimpleDateFormat;
import java.util.Date; import java.util.Date;
import java.util.Locale; import java.util.Locale;
import info.guardianproject.netcipher.NetCipher;
import info.guardianproject.netcipher.webkit.WebkitProxy;
/** /**
* Fragment with a webView and a ProgressBar. * Fragment with a webView and a ProgressBar.
* This Fragment retains its instance. * This Fragment retains its instance.
@ -102,21 +95,13 @@ public class BrowserFragment extends CustomFragment {
if(this.webView == null) { if(this.webView == null) {
this.webView = (ContextMenuWebView) view.findViewById(R.id.webView); this.webView = (ContextMenuWebView) view.findViewById(R.id.webView);
this.applyWebViewSettings(); this.applyWebViewSettings();
ProxyHandler.getInstance().addWebView(webView);
} }
if(this.progressBar == null) { if(this.progressBar == null) {
this.progressBar = (ProgressBar) view.findViewById(R.id.progressBar); 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) { if(pendingUrl != null) {
loadUrl(pendingUrl); loadUrl(pendingUrl);
pendingUrl = null; pendingUrl = null;
@ -160,86 +145,6 @@ public class BrowserFragment extends CustomFragment {
webView.setWebChromeClient(new ProgressBarWebChromeClient(webView, progressBar)); 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") @SuppressWarnings("ResultOfMethodCallIgnored")
protected boolean makeScreenshotOfWebView(boolean hasToShareScreenshot) { protected boolean makeScreenshotOfWebView(boolean hasToShareScreenshot) {
AppLog.i(this, "StreamFragment.makeScreenshotOfWebView()"); AppLog.i(this, "StreamFragment.makeScreenshotOfWebView()");

View file

@ -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 <http://www.gnu.org/licenses/>.
*/
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<WebView> 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();
}
}
}