diff --git a/app/build.gradle b/app/build.gradle
index a2e167e4..f8aee685 100644
--- a/app/build.gradle
+++ b/app/build.gradle
@@ -37,6 +37,7 @@ dependencies {
// More libraries
compile 'com.getbase:floatingactionbutton:1.9.1'
compile 'com.jakewharton:butterknife:8.0.1'
+ compile 'info.guardianproject.netcipher:netcipher:1.2.1'
apt 'com.jakewharton:butterknife-compiler:8.0.1'
}
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 f4a64846..04240c73 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
@@ -23,7 +23,9 @@ import android.Manifest;
import android.animation.ObjectAnimator;
import android.annotation.SuppressLint;
import android.app.Activity;
+import android.app.AlarmManager;
import android.app.AlertDialog;
+import android.app.PendingIntent;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.DialogInterface;
@@ -32,9 +34,11 @@ import android.content.IntentFilter;
import android.content.pm.PackageManager;
import android.graphics.Bitmap;
import android.net.Uri;
+import android.os.AsyncTask;
import android.os.Bundle;
import android.os.Environment;
import android.os.Handler;
+import android.os.StrictMode;
import android.provider.MediaStore;
import android.support.annotation.NonNull;
import android.support.design.widget.CollapsingToolbarLayout;
@@ -46,6 +50,7 @@ import android.support.v4.widget.SwipeRefreshLayout;
import android.support.v7.app.ActionBarDrawerToggle;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.ActionMenuView;
+import android.support.v7.widget.SwitchCompat;
import android.support.v7.widget.Toolbar;
import android.text.Html;
import android.text.SpannableString;
@@ -66,6 +71,7 @@ import android.webkit.WebChromeClient;
import android.webkit.WebSettings;
import android.webkit.WebView;
import android.widget.EditText;
+import android.widget.FrameLayout;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.ProgressBar;
@@ -97,6 +103,8 @@ import java.util.Locale;
import butterknife.BindView;
import butterknife.ButterKnife;
import butterknife.OnClick;
+import info.guardianproject.netcipher.NetCipher;
+import info.guardianproject.netcipher.web.WebkitProxy;
public class MainActivity extends AppCompatActivity
implements NavigationView.OnNavigationItemSelectedListener, WebUserProfileChangedListener {
@@ -216,6 +224,11 @@ public class MainActivity extends AppCompatActivity
if (android.os.Build.VERSION.SDK_INT >= 21)
webSettings.setMixedContentMode(WebSettings.MIXED_CONTENT_ALWAYS_ALLOW);
+ //Set proxy
+ if(appSettings.isProxyEnabled()) {
+ if(!setProxy()) Toast.makeText(this, R.string.toast_set_proxy_failed, Toast.LENGTH_LONG).show();
+ }
+
/*
* WebViewClient
*/
@@ -885,7 +898,7 @@ public class MainActivity extends AppCompatActivity
case R.id.nav_aspects: {
if (Helpers.isOnline(MainActivity.this)) {
- // webView.loadUrl("https://" + podDomain + "/aspects");
+ // webView.loadUrl("https://" + podDomain + "/aspects");
Helpers.showAspectList(webView, app);
setTitle(R.string.title_aspects);
} else {
@@ -946,7 +959,8 @@ public class MainActivity extends AppCompatActivity
case R.id.nav_settings_app: {
final CharSequence[] options = {getString(R.string.settings_font), getString(R.string.settings_view), appSettings.isLoadImages() ?
- getString(R.string.settings_images_switch_off) : getString(R.string.settings_images_switch_on), getString(R.string.jb_pod)};
+ getString(R.string.settings_images_switch_off) : getString(R.string.settings_images_switch_on), getString(R.string.jb_pod),
+ getString(R.string.settings_proxy)};
if (Helpers.isOnline(MainActivity.this)) {
new AlertDialog.Builder(MainActivity.this)
@@ -979,6 +993,33 @@ public class MainActivity extends AppCompatActivity
})
.show();
break;
+ case 4:
+ final AlertDialog.Builder dialogBuilder = new AlertDialog.Builder(MainActivity.this);
+ final View dialogLayout = getLayoutInflater().inflate(R.layout.proxy_configuration_dialog, null);
+ final SwitchCompat enabled_toggle = (SwitchCompat) dialogLayout.findViewById(R.id.proxy_toggle);
+ final EditText host_edit = (EditText) dialogLayout.findViewById(R.id.proxy_host_edit);
+ final EditText port_edit = (EditText) dialogLayout.findViewById(R.id.proxy_port_edit);
+
+ enabled_toggle.setChecked(appSettings.isProxyEnabled());
+ host_edit.setText(appSettings.getProxyHost());
+ port_edit.setText(""+appSettings.getProxyPort());
+ dialogBuilder.setView(dialogLayout).setTitle(R.string.settings_proxy)
+ .setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() {
+ @Override
+ public void onClick(DialogInterface dialog, int which) {
+ boolean proxyEnabled = enabled_toggle.isChecked();
+ String host = host_edit.getText().toString();
+ int port = Integer.parseInt(port_edit.getText().toString());
+
+ if(proxyEnabled) {
+ if(!setProxy(host, port)) {
+ Toast.makeText(MainActivity.this, R.string.toast_set_proxy_failed,Toast.LENGTH_SHORT).show();
+ }
+ }
+ else resetProxy();
+ }
+ }).setNegativeButton(android.R.string.cancel, null).show();
+ break;
}
}
}).show();
@@ -1069,4 +1110,66 @@ public class MainActivity extends AppCompatActivity
grantResults);
}
}
+
+ /**
+ * 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) {
+ if(host != null && !host.equals("") && port >=0) {
+ //Temporary change thread policy
+ StrictMode.ThreadPolicy old = StrictMode.getThreadPolicy();
+ StrictMode.ThreadPolicy tmp = new StrictMode.ThreadPolicy.Builder().permitAll().build();
+ StrictMode.setThreadPolicy(tmp);
+
+ NetCipher.setProxy(host, port); //Proxy for HttpsUrlConnections
+ try {
+ //Proxy for the webview
+ WebkitProxy.setProxy(MainActivity.class.getName(), getApplicationContext(), null, host, port);
+ } catch (Exception e) { /*Nothing we can do*/ }
+
+ appSettings.setProxyEnabled(true);
+ appSettings.setProxyHost(host);
+ appSettings.setProxyPort(port);
+
+ StrictMode.setThreadPolicy(old);
+ webView.reload();
+ return true;
+ } else {
+ return false;
+ }
+ }
+
+ private boolean setProxy() {
+ return setProxy(appSettings.getProxyHost(), appSettings.getProxyPort());
+ }
+
+ private void resetProxy() {
+ appSettings.setProxyEnabled(false);
+
+ //Temporary change thread policy
+ StrictMode.ThreadPolicy old = StrictMode.getThreadPolicy();
+ StrictMode.ThreadPolicy tmp = new StrictMode.ThreadPolicy.Builder().permitAll().build();
+ StrictMode.setThreadPolicy(tmp);
+
+ NetCipher.clearProxy();
+ try{
+ WebkitProxy.resetProxy(MainActivity.class.getName(), this);
+ } catch (Exception e) {
+ //Nothing we can do.
+ }
+
+ StrictMode.setThreadPolicy(old);
+
+ //Restart app
+ Intent restartActivity = new Intent(this, MainActivity.class);
+ PendingIntent pendingIntent = PendingIntent.getActivity(this, 12374, restartActivity, PendingIntent.FLAG_CANCEL_CURRENT);
+ AlarmManager mgr = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
+ mgr.set(AlarmManager.RTC, System.currentTimeMillis() + 100, pendingIntent);
+ System.exit(0);
+ }
}
\ No newline at end of file
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 fe4e3178..77cc3ed7 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
@@ -70,6 +70,9 @@ public class AppSettings {
private static final String PODUSERPROFILE_ID = "podUserProfile_guid";
private static final String PODDOMAIN = "podDomain";
private static final String PODUSERPROFILE_ASPECTS = "podUserProfile_aspects";
+ private static final String PROXY_ENABLED = "isProxyEnabled";
+ private static final String PROXY_HOST = "proxyHost";
+ private static final String PROXY_PORT = "proxyPort";
}
@@ -150,4 +153,41 @@ public class AppSettings {
}
return aspects;
}
+
+ public void setProxyEnabled(boolean enabled) {
+ //commit instead of apply because the app is likely to be killed before apply is called.
+ prefApp.edit().putBoolean(PREF.PROXY_ENABLED, enabled).commit();
+ }
+
+ /**
+ * Default return value: false
+ * @return whether proxy is enabled or not
+ */
+ public boolean isProxyEnabled() {
+ return prefApp.getBoolean(PREF.PROXY_ENABLED, false);
+ }
+
+ public void setProxyHost(String host) {
+ setString(prefApp, PREF.PROXY_HOST, host);
+ }
+
+ /**
+ * Default value: ""
+ * @return proxy host
+ */
+ public String getProxyHost() {
+ return prefApp.getString(PREF.PROXY_HOST, "");
+ }
+
+ public void setProxyPort(int port) {
+ setInt(prefApp, PREF.PROXY_PORT, port);
+ }
+
+ /**
+ * Default value: 0
+ * @return proxy port
+ */
+ public int getProxyPort() {
+ return prefApp.getInt(PREF.PROXY_PORT, 0);
+ }
}
diff --git a/app/src/main/res/layout/proxy_configuration_dialog.xml b/app/src/main/res/layout/proxy_configuration_dialog.xml
new file mode 100644
index 00000000..75bc4330
--- /dev/null
+++ b/app/src/main/res/layout/proxy_configuration_dialog.xml
@@ -0,0 +1,52 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml
index 33c428cd..78f62f41 100644
--- a/app/src/main/res/values/strings.xml
+++ b/app/src/main/res/values/strings.xml
@@ -78,6 +78,10 @@
Do load images
Do not load images
Change view
+ Proxy
+ Enabled
+ Host
+ Port
Share link as text
Share screenshot of webpage
Take screenshot of webpage
@@ -218,4 +222,6 @@
https://
Share…
#DiasporaForAndroid
+
+ Warning: Could not set network proxy…