diff --git a/app/src/main/java/acr/browser/lightning/activity/BrowserActivity.java b/app/src/main/java/acr/browser/lightning/activity/BrowserActivity.java
index bde3d06..f06169c 100644
--- a/app/src/main/java/acr/browser/lightning/activity/BrowserActivity.java
+++ b/app/src/main/java/acr/browser/lightning/activity/BrowserActivity.java
@@ -10,7 +10,11 @@ import android.animation.ValueAnimator.AnimatorUpdateListener;
import android.annotation.SuppressLint;
import android.app.Activity;
import android.app.AlertDialog;
-import android.content.*;
+import android.content.ClipData;
+import android.content.ClipboardManager;
+import android.content.Context;
+import android.content.DialogInterface;
+import android.content.Intent;
import android.content.res.Configuration;
import android.content.res.Resources.Theme;
import android.database.Cursor;
@@ -36,15 +40,26 @@ import android.support.v4.view.GravityCompat;
import android.support.v4.view.ViewCompat;
import android.support.v4.widget.DrawerLayout;
import android.support.v4.widget.DrawerLayout.DrawerListener;
+import android.support.v7.app.ActionBar;
+import android.support.v7.graphics.Palette;
+import android.support.v7.widget.Toolbar;
import android.text.TextUtils;
import android.util.Log;
-import android.view.*;
+import android.view.KeyEvent;
+import android.view.LayoutInflater;
+import android.view.Menu;
+import android.view.MenuItem;
+import android.view.MotionEvent;
+import android.view.View;
import android.view.View.OnClickListener;
import android.view.View.OnFocusChangeListener;
import android.view.View.OnKeyListener;
import android.view.View.OnLongClickListener;
import android.view.View.OnTouchListener;
+import android.view.ViewGroup;
import android.view.ViewGroup.LayoutParams;
+import android.view.Window;
+import android.view.WindowManager;
import android.view.animation.Animation;
import android.view.animation.Animation.AnimationListener;
import android.view.animation.AnimationUtils;
@@ -52,41 +67,68 @@ import android.view.animation.DecelerateInterpolator;
import android.view.animation.Transformation;
import android.view.inputmethod.EditorInfo;
import android.view.inputmethod.InputMethodManager;
-import android.webkit.*;
+import android.webkit.CookieManager;
+import android.webkit.CookieSyncManager;
+import android.webkit.ValueCallback;
import android.webkit.WebChromeClient.CustomViewCallback;
+import android.webkit.WebIconDatabase;
+import android.webkit.WebStorage;
+import android.webkit.WebView;
import android.webkit.WebView.HitTestResult;
-import android.widget.*;
-import android.support.v7.app.ActionBar;
-import android.support.v7.graphics.Palette;
-import android.support.v7.widget.Toolbar;
+import android.webkit.WebViewDatabase;
+import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
+import android.widget.ArrayAdapter;
+import android.widget.AutoCompleteTextView;
+import android.widget.EditText;
+import android.widget.FrameLayout;
+import android.widget.ImageButton;
+import android.widget.ImageView;
+import android.widget.LinearLayout;
+import android.widget.ListView;
+import android.widget.RelativeLayout;
+import android.widget.TextView;
import android.widget.TextView.OnEditorActionListener;
+import android.widget.Toast;
+import android.widget.VideoView;
-import acr.browser.lightning.view.AnimatedProgressBar;
-import acr.browser.lightning.database.BookmarkManager;
-import acr.browser.lightning.constant.BookmarkPage;
-import acr.browser.lightning.controller.BrowserController;
-import acr.browser.lightning.object.ClickHandler;
-import acr.browser.lightning.constant.Constants;
-import acr.browser.lightning.object.DrawerArrowDrawable;
-import acr.browser.lightning.database.HistoryDatabase;
-import acr.browser.lightning.database.HistoryItem;
-import acr.browser.lightning.constant.HistoryPage;
-import acr.browser.lightning.view.LightningView;
-import acr.browser.lightning.preference.PreferenceManager;
-import acr.browser.lightning.R;
-import acr.browser.lightning.object.SearchAdapter;
-import acr.browser.lightning.utils.Utils;
-import info.guardianproject.onionkit.ui.OrbotHelper;
-import info.guardianproject.onionkit.web.WebkitProxy;
+import net.i2p.android.ui.I2PAndroidHelper;
-import java.io.*;
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.FileWriter;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.UnsupportedEncodingException;
import java.net.HttpURLConnection;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.URL;
import java.net.URLEncoder;
-import java.util.*;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Locale;
+
+import acr.browser.lightning.R;
+import acr.browser.lightning.constant.BookmarkPage;
+import acr.browser.lightning.constant.Constants;
+import acr.browser.lightning.constant.HistoryPage;
+import acr.browser.lightning.controller.BrowserController;
+import acr.browser.lightning.database.BookmarkManager;
+import acr.browser.lightning.database.HistoryDatabase;
+import acr.browser.lightning.database.HistoryItem;
+import acr.browser.lightning.object.ClickHandler;
+import acr.browser.lightning.object.DrawerArrowDrawable;
+import acr.browser.lightning.object.SearchAdapter;
+import acr.browser.lightning.preference.PreferenceManager;
+import acr.browser.lightning.utils.Utils;
+import acr.browser.lightning.view.AnimatedProgressBar;
+import acr.browser.lightning.view.LightningView;
+import info.guardianproject.onionkit.ui.OrbotHelper;
+import info.guardianproject.onionkit.web.WebkitProxy;
public class BrowserActivity extends ThemableActivity implements BrowserController, OnClickListener {
@@ -140,6 +182,9 @@ public class BrowserActivity extends ThemableActivity implements BrowserControll
private Drawable mDeleteIcon, mRefreshIcon, mCopyIcon, mIcon;
private DrawerArrowDrawable mArrowDrawable;
+ // Helper
+ private I2PAndroidHelper mI2PHelper;
+
// Constant
private static final int API = android.os.Build.VERSION.SDK_INT;
private static final LayoutParams MATCH_PARENT = new LayoutParams(LayoutParams.MATCH_PARENT,
@@ -221,6 +266,8 @@ public class BrowserActivity extends ThemableActivity implements BrowserControll
R.id.arrow_button);
arrowButton.setOnClickListener(this);
+ mI2PHelper = new I2PAndroidHelper(this);
+
RelativeLayout back = (RelativeLayout) findViewById(R.id.action_back);
back.setOnClickListener(this);
@@ -304,7 +351,7 @@ public class BrowserActivity extends ThemableActivity implements BrowserControll
WebIconDatabase.getInstance().open(getDir("icons", MODE_PRIVATE).getPath());
}
- checkForTor();
+ checkForProxy();
}
private class SearchClass {
@@ -494,56 +541,104 @@ public class BrowserActivity extends ThemableActivity implements BrowserControll
}
/*
- * If Orbot/Tor is installed, prompt the user if they want to enable
+ * If Orbot/Tor or I2P is installed, prompt the user if they want to enable
* proxying for this session
*/
- private boolean checkForTor() {
+ private void checkForProxy() {
boolean useProxy = mPreferences.getUseProxy();
OrbotHelper oh = new OrbotHelper(this);
- if (oh.isOrbotInstalled() && !mPreferences.getCheckedForTor()) {
- mPreferences.setCheckedForTor(true);
- DialogInterface.OnClickListener dialogClickListener = new DialogInterface.OnClickListener() {
- @Override
- public void onClick(DialogInterface dialog, int which) {
- switch (which) {
- case DialogInterface.BUTTON_POSITIVE:
- mPreferences.setUseProxy(true);
- initializeTor();
- break;
- case DialogInterface.BUTTON_NEGATIVE:
- mPreferences.setUseProxy(false);
- break;
- }
- }
- };
+ final boolean orbotInstalled = oh.isOrbotInstalled();
+ boolean orbotChecked = mPreferences.getCheckedForTor();
+ boolean orbot = orbotInstalled && !orbotChecked;
+ boolean i2pInstalled = mI2PHelper.isI2PAndroidInstalled();
+ boolean i2pChecked = mPreferences.getCheckedForI2P();
+ boolean i2p = i2pInstalled && !i2pChecked;
+
+ // TODO Is the idea to show this per-session, or only once?
+ if (!useProxy && (orbot || i2p)) {
+ if (orbot) mPreferences.setCheckedForTor(true);
+ if (i2p) mPreferences.setCheckedForI2P(true);
AlertDialog.Builder builder = new AlertDialog.Builder(this);
- builder.setMessage(R.string.use_tor_prompt)
- .setPositiveButton(R.string.yes, dialogClickListener)
- .setNegativeButton(R.string.no, dialogClickListener).show();
- return true;
- } else if (oh.isOrbotInstalled() & useProxy) {
- return true;
- } else {
- mPreferences.setUseProxy(false);
- return false;
+ if (orbotInstalled && i2pInstalled) {
+ String[] proxyChoices = this.getResources().getStringArray(R.array.proxy_choices_array);
+ builder.setTitle(getResources().getString(R.string.http_proxy))
+ .setSingleChoiceItems(proxyChoices, mPreferences.getProxyChoice(),
+ new DialogInterface.OnClickListener() {
+ @Override
+ public void onClick(DialogInterface dialog, int which) {
+ mPreferences.setProxyChoice(which);
+ }
+ })
+ .setNeutralButton(getResources().getString(R.string.action_ok),
+ new DialogInterface.OnClickListener() {
+ @Override
+ public void onClick(DialogInterface dialog, int which) {
+ if (mPreferences.getUseProxy())
+ initializeProxy();
+ }
+ });
+ } else {
+ DialogInterface.OnClickListener dialogClickListener = new DialogInterface.OnClickListener() {
+ @Override
+ public void onClick(DialogInterface dialog, int which) {
+ switch (which) {
+ case DialogInterface.BUTTON_POSITIVE:
+ mPreferences.setProxyChoice(orbotInstalled ? 1 : 2);
+ initializeProxy();
+ break;
+ case DialogInterface.BUTTON_NEGATIVE:
+ mPreferences.setProxyChoice(0);
+ break;
+ }
+ }
+ };
+
+ builder.setMessage(orbotInstalled ? R.string.use_tor_prompt : R.string.use_i2p_prompt)
+ .setPositiveButton(R.string.yes, dialogClickListener)
+ .setNegativeButton(R.string.no, dialogClickListener);
+ }
+ builder.show();
}
}
/*
- * Initialize WebKit Proxying for Tor
+ * Initialize WebKit Proxying
*/
- private void initializeTor() {
+ private void initializeProxy() {
+ String host;
+ int port;
- OrbotHelper oh = new OrbotHelper(this);
- if (!oh.isOrbotRunning()) {
- oh.requestOrbotStart(this);
+ switch (mPreferences.getProxyChoice()) {
+ case 0:
+ // We shouldn't be here
+ return;
+
+ case 1:
+ OrbotHelper oh = new OrbotHelper(this);
+ if (!oh.isOrbotRunning()) {
+ oh.requestOrbotStart(this);
+ }
+ host = "localhost";
+ port = 8118;
+ break;
+
+ case 2:
+ if (!mI2PHelper.isI2PAndroidRunning()) {
+ mI2PHelper.requestI2PAndroidStart(this);
+ }
+ host = "localhost";
+ port = 4444;
+ break;
+
+ default:
+ host = mPreferences.getProxyHost();
+ port = mPreferences.getProxyPort();
}
+
try {
- String host = mPreferences.getProxyHost();
- int port = mPreferences.getProxyPort();
WebkitProxy.setProxy(BrowserApp.class.getName(), getApplicationContext(),
host, port);
} catch (Exception e) {
@@ -704,7 +799,7 @@ public class BrowserActivity extends ThemableActivity implements BrowserControll
updateCookiePreference();
if (mPreferences.getUseProxy()) {
- initializeTor();
+ initializeProxy();
} else {
try {
WebkitProxy.resetProxy(BrowserApp.class.getName(),
@@ -1369,6 +1464,12 @@ public class BrowserActivity extends ThemableActivity implements BrowserControll
}
}
+ @Override
+ protected void onStop() {
+ super.onStop();
+ mI2PHelper.unbind();
+ }
+
@Override
protected void onDestroy() {
Log.d(Constants.TAG, "onDestroy");
@@ -1378,6 +1479,15 @@ public class BrowserActivity extends ThemableActivity implements BrowserControll
super.onDestroy();
}
+ @Override
+ protected void onStart() {
+ super.onStart();
+ if (mPreferences.getProxyChoice() == 2) {
+ // Try to bind to I2P Android
+ mI2PHelper.bind();
+ }
+ }
+
@Override
protected void onResume() {
super.onResume();
diff --git a/app/src/main/java/acr/browser/lightning/activity/SettingsActivity.java b/app/src/main/java/acr/browser/lightning/activity/SettingsActivity.java
index e3a627f..cd2bf9c 100644
--- a/app/src/main/java/acr/browser/lightning/activity/SettingsActivity.java
+++ b/app/src/main/java/acr/browser/lightning/activity/SettingsActivity.java
@@ -339,7 +339,6 @@ public class SettingsActivity extends ThemableSettingsActivity {
break;
}
- mPreferences.setUseProxy(choice != 0);
mPreferences.setProxyChoice(choice);
if (choice < mProxyChoices.length)
mProxyChoiceName.setText(mProxyChoices[choice]);
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 f03651d..78375ce 100644
--- a/app/src/main/java/acr/browser/lightning/preference/PreferenceManager.java
+++ b/app/src/main/java/acr/browser/lightning/preference/PreferenceManager.java
@@ -53,6 +53,7 @@ public class PreferenceManager {
public static final String USE_PROXY_HOST = "useProxyHost";
public static final String USE_PROXY_PORT = "useProxyPort";
public static final String INITIAL_CHECK_FOR_TOR = "checkForTor";
+ public static final String INITIAL_CHECK_FOR_I2P = "checkForI2P";
}
private static PreferenceManager mInstance;
@@ -87,6 +88,10 @@ public class PreferenceManager {
return mPrefs.getBoolean(Name.INITIAL_CHECK_FOR_TOR, false);
}
+ public boolean getCheckedForI2P() {
+ return mPrefs.getBoolean(Name.INITIAL_CHECK_FOR_I2P, false);
+ }
+
public boolean getClearCacheExit() {
return mPrefs.getBoolean(Name.CLEAR_CACHE_EXIT, false);
}
@@ -271,6 +276,10 @@ public class PreferenceManager {
putBoolean(Name.INITIAL_CHECK_FOR_TOR, check);
}
+ public void setCheckedForI2P(boolean check) {
+ putBoolean(Name.INITIAL_CHECK_FOR_I2P, check);
+ }
+
public void setClearCacheExit(boolean enable) {
putBoolean(Name.CLEAR_CACHE_EXIT, enable);
}
@@ -399,11 +408,13 @@ public class PreferenceManager {
putBoolean(Name.DARK_THEME, use);
}
- public void setUseProxy(boolean enable) {
- putBoolean(Name.USE_PROXY, enable);
- }
-
+ /**
+ * 0: None. 1: Orbot. 2: I2P.
+ *
+ * @param choice the proxy to use.
+ */
public void setProxyChoice(int choice) {
+ putBoolean(Name.USE_PROXY, choice != 0);
putInt(Name.PROXY_CHOICE, choice);
}
diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml
index 3bccd84..42b77ff 100644
--- a/app/src/main/res/values/strings.xml
+++ b/app/src/main/res/values/strings.xml
@@ -165,6 +165,7 @@
- I2P
It looks like you have Orbot installed. Do you want to use Tor?
+ It looks like you have I2P installed. Do you want to use I2P?
Please install Orbot in order to proxy with Tor.
Yes
No