Browse Source

Merge pull request #249 from str4d/i2p-android

Support I2P (and other proxies in future)
master
Anthony Restaino 9 years ago
parent
commit
a2f2fbc82b
  1. 1
      app/build.gradle
  2. 6
      app/proguard-project.txt
  3. 259
      app/src/main/java/acr/browser/lightning/activity/BrowserActivity.java
  4. 125
      app/src/main/java/acr/browser/lightning/activity/SettingsActivity.java
  5. 6
      app/src/main/java/acr/browser/lightning/constant/Constants.java
  6. 2
      app/src/main/java/acr/browser/lightning/controller/BrowserController.java
  7. 37
      app/src/main/java/acr/browser/lightning/preference/PreferenceManager.java
  8. 18
      app/src/main/java/acr/browser/lightning/view/LightningView.java
  9. 43
      app/src/main/res/layout/picker_manual_proxy.xml
  10. 30
      app/src/main/res/layout/settings.xml
  11. 14
      app/src/main/res/values/strings.xml

1
app/build.gradle

@ -39,4 +39,5 @@ dependencies { @@ -39,4 +39,5 @@ dependencies {
compile 'com.android.support:palette-v7:22.1.1'
compile 'com.android.support:appcompat-v7:22.1.1'
compile 'org.jsoup:jsoup:1.8.1'
compile 'net.i2p.android:client:0.7@aar'
}

6
app/proguard-project.txt

@ -77,3 +77,9 @@ @@ -77,3 +77,9 @@
# Don't warn about those in case this app is linking against an older
# platform version. We know about them, and they are safe.
-dontwarn android.support.**
# The I2P Java API bundled inside the I2P Android client library contains
# references to javax.naming classes that Android doesn't have. But those
# classes are never used on Android, and it is safe to ignore the warnings.
-dontwarn net.i2p.crypto.CertUtil
-dontwarn org.apache.http.conn.ssl.DefaultHostnameVerifier

259
app/src/main/java/acr/browser/lightning/activity/BrowserActivity.java

@ -10,7 +10,11 @@ import android.animation.ValueAnimator.AnimatorUpdateListener; @@ -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; @@ -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,42 +67,69 @@ import android.view.animation.DecelerateInterpolator; @@ -52,42 +67,69 @@ 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 net.i2p.android.ui.I2PAndroidHelper;
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.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.controller.BrowserController;
import acr.browser.lightning.object.ClickHandler;
import acr.browser.lightning.constant.Constants;
import acr.browser.lightning.object.DrawerArrowDrawable;
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.constant.HistoryPage;
import acr.browser.lightning.view.LightningView;
import acr.browser.lightning.preference.PreferenceManager;
import acr.browser.lightning.R;
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;
import java.io.*;
import java.net.HttpURLConnection;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.URL;
import java.net.URLEncoder;
import java.util.*;
public class BrowserActivity extends ThemableActivity implements BrowserController, OnClickListener {
// Layout
@ -140,6 +182,11 @@ public class BrowserActivity extends ThemableActivity implements BrowserControll @@ -140,6 +182,11 @@ public class BrowserActivity extends ThemableActivity implements BrowserControll
private Drawable mDeleteIcon, mRefreshIcon, mCopyIcon, mIcon;
private DrawerArrowDrawable mArrowDrawable;
// Helper
private I2PAndroidHelper mI2PHelper;
private boolean mI2PHelperBound;
private boolean mI2PProxyInitialized;
// 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 +268,8 @@ public class BrowserActivity extends ThemableActivity implements BrowserControll @@ -221,6 +268,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 +353,7 @@ public class BrowserActivity extends ThemableActivity implements BrowserControll @@ -304,7 +353,7 @@ public class BrowserActivity extends ThemableActivity implements BrowserControll
WebIconDatabase.getInstance().open(getDir("icons", MODE_PRIVATE).getPath());
}
checkForTor();
checkForProxy();
}
private class SearchClass {
@ -494,56 +543,106 @@ public class BrowserActivity extends ThemableActivity implements BrowserControll @@ -494,56 +543,106 @@ 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 ?
Constants.PROXY_ORBOT : Constants.PROXY_I2P);
initializeProxy();
break;
case DialogInterface.BUTTON_NEGATIVE:
mPreferences.setProxyChoice(Constants.NO_PROXY);
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;
switch (mPreferences.getProxyChoice()) {
case Constants.NO_PROXY:
// We shouldn't be here
return;
case Constants.PROXY_ORBOT:
OrbotHelper oh = new OrbotHelper(this);
if (!oh.isOrbotRunning()) {
oh.requestOrbotStart(this);
}
host = "localhost";
port = 8118;
break;
OrbotHelper oh = new OrbotHelper(this);
if (!oh.isOrbotRunning()) {
oh.requestOrbotStart(this);
case Constants.PROXY_I2P:
mI2PProxyInitialized = true;
if (mI2PHelperBound && !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) {
@ -552,6 +651,20 @@ public class BrowserActivity extends ThemableActivity implements BrowserControll @@ -552,6 +651,20 @@ public class BrowserActivity extends ThemableActivity implements BrowserControll
}
public boolean isProxyReady() {
if (mPreferences.getProxyChoice() == Constants.PROXY_I2P) {
if (!mI2PHelper.isI2PAndroidRunning()) {
Utils.showToast(this, getString(R.string.i2p_not_running));
return false;
} else if (!mI2PHelper.areTunnelsActive()) {
Utils.showToast(this, getString(R.string.i2p_tunnels_not_ready));
return false;
}
}
return true;
}
private boolean isTablet() {
return (getResources().getConfiguration().screenLayout & Configuration.SCREENLAYOUT_SIZE_MASK) == Configuration.SCREENLAYOUT_SIZE_XLARGE;
}
@ -704,7 +817,7 @@ public class BrowserActivity extends ThemableActivity implements BrowserControll @@ -704,7 +817,7 @@ public class BrowserActivity extends ThemableActivity implements BrowserControll
updateCookiePreference();
if (mPreferences.getUseProxy()) {
initializeTor();
initializeProxy();
} else {
try {
WebkitProxy.resetProxy(BrowserApp.class.getName(),
@ -712,6 +825,7 @@ public class BrowserActivity extends ThemableActivity implements BrowserControll @@ -712,6 +825,7 @@ public class BrowserActivity extends ThemableActivity implements BrowserControll
} catch (Exception e) {
e.printStackTrace();
}
mI2PProxyInitialized = false;
}
}
@ -1369,6 +1483,13 @@ public class BrowserActivity extends ThemableActivity implements BrowserControll @@ -1369,6 +1483,13 @@ public class BrowserActivity extends ThemableActivity implements BrowserControll
}
}
@Override
protected void onStop() {
super.onStop();
mI2PHelper.unbind();
mI2PHelperBound = false;
}
@Override
protected void onDestroy() {
Log.d(Constants.TAG, "onDestroy");
@ -1378,6 +1499,22 @@ public class BrowserActivity extends ThemableActivity implements BrowserControll @@ -1378,6 +1499,22 @@ public class BrowserActivity extends ThemableActivity implements BrowserControll
super.onDestroy();
}
@Override
protected void onStart() {
super.onStart();
if (mPreferences.getProxyChoice() == Constants.PROXY_I2P) {
// Try to bind to I2P Android
mI2PHelper.bind(new I2PAndroidHelper.Callback() {
@Override
public void onI2PAndroidBound() {
mI2PHelperBound = true;
if (mI2PProxyInitialized && !mI2PHelper.isI2PAndroidRunning())
mI2PHelper.requestI2PAndroidStart(BrowserActivity.this);
}
});
}
}
@Override
protected void onResume() {
super.onResume();

125
app/src/main/java/acr/browser/lightning/activity/SettingsActivity.java

@ -22,11 +22,15 @@ import android.widget.CheckBox; @@ -22,11 +22,15 @@ import android.widget.CheckBox;
import android.widget.CompoundButton;
import android.widget.CompoundButton.OnCheckedChangeListener;
import android.widget.EditText;
import android.widget.LinearLayout;
import android.widget.RelativeLayout;
import android.widget.TextView;
import net.i2p.android.ui.I2PAndroidHelper;
import acr.browser.lightning.R;
import acr.browser.lightning.constant.Constants;
import acr.browser.lightning.preference.PreferenceManager;
import acr.browser.lightning.R;
import acr.browser.lightning.utils.Utils;
import info.guardianproject.onionkit.ui.OrbotHelper;
@ -36,6 +40,8 @@ public class SettingsActivity extends ThemableSettingsActivity { @@ -36,6 +40,8 @@ public class SettingsActivity extends ThemableSettingsActivity {
private PreferenceManager mPreferences;
private Context mContext;
private Activity mActivity;
private CharSequence[] mProxyChoices;
private TextView mProxyChoiceName;
@Override
protected void onCreate(Bundle savedInstanceState) {
@ -69,7 +75,7 @@ public class SettingsActivity extends ThemableSettingsActivity { @@ -69,7 +75,7 @@ public class SettingsActivity extends ThemableSettingsActivity {
layoutBlockAds.setEnabled(Constants.FULL_VERSION);
RelativeLayout layoutImages = (RelativeLayout) findViewById(R.id.layoutImages);
RelativeLayout layoutEnableJS = (RelativeLayout) findViewById(R.id.layoutEnableJS);
RelativeLayout layoutOrbot = (RelativeLayout) findViewById(R.id.layoutUseOrbot);
LinearLayout layoutProxyChoice = (LinearLayout) findViewById(R.id.layoutProxyChoice);
RelativeLayout layoutColor = (RelativeLayout) findViewById(R.id.layoutColorMode);
RelativeLayout layoutBookmarks = (RelativeLayout) findViewById(R.id.layoutBookmarks);
@ -89,12 +95,19 @@ public class SettingsActivity extends ThemableSettingsActivity { @@ -89,12 +95,19 @@ public class SettingsActivity extends ThemableSettingsActivity {
boolean imagesBool = mPreferences.getBlockImagesEnabled();
boolean enableJSBool = mPreferences.getJavaScriptEnabled();
mProxyChoiceName = (TextView) findViewById(R.id.proxyChoiceName);
mProxyChoices = this.getResources().getStringArray(R.array.proxy_choices_array);
int choice = mPreferences.getProxyChoice();
if (choice == Constants.PROXY_MANUAL)
mProxyChoiceName.setText(mPreferences.getProxyHost() + ":" + mPreferences.getProxyPort());
else
mProxyChoiceName.setText(mProxyChoices[choice]);
CheckBox flash = (CheckBox) findViewById(R.id.cbFlash);
CheckBox adblock = (CheckBox) findViewById(R.id.cbAdblock);
adblock.setEnabled(Constants.FULL_VERSION);
CheckBox images = (CheckBox) findViewById(R.id.cbImageBlock);
CheckBox enablejs = (CheckBox) findViewById(R.id.cbJavascript);
CheckBox orbot = (CheckBox) findViewById(R.id.cbOrbot);
CheckBox color = (CheckBox) findViewById(R.id.cbColorMode);
images.setChecked(imagesBool);
@ -105,12 +118,11 @@ public class SettingsActivity extends ThemableSettingsActivity { @@ -105,12 +118,11 @@ public class SettingsActivity extends ThemableSettingsActivity {
flash.setChecked(false);
}
adblock.setChecked(mPreferences.getAdBlockEnabled());
orbot.setChecked(mPreferences.getUseProxy());
color.setChecked(mPreferences.getColorModeEnabled());
initCheckBox(flash, adblock, images, enablejs, orbot, color);
initCheckBox(flash, adblock, images, enablejs, color);
clickListenerForCheckBoxes(layoutFlash, layoutBlockAds, layoutImages, layoutEnableJS,
layoutOrbot, layoutColor, flash, adblock, images, enablejs, orbot, color);
layoutProxyChoice, layoutColor, flash, adblock, images, enablejs, color);
RelativeLayout general = (RelativeLayout) findViewById(R.id.layoutGeneral);
RelativeLayout display = (RelativeLayout) findViewById(R.id.layoutDisplay);
@ -127,9 +139,9 @@ public class SettingsActivity extends ThemableSettingsActivity { @@ -127,9 +139,9 @@ public class SettingsActivity extends ThemableSettingsActivity {
public void clickListenerForCheckBoxes(RelativeLayout layoutFlash,
RelativeLayout layoutBlockAds, RelativeLayout layoutImages,
RelativeLayout layoutEnableJS, RelativeLayout layoutOrbot, RelativeLayout layoutColor,
RelativeLayout layoutEnableJS, LinearLayout layoutProxyChoice, RelativeLayout layoutColor,
final CheckBox flash, final CheckBox adblock, final CheckBox images,
final CheckBox enablejs, final CheckBox orbot, final CheckBox color) {
final CheckBox enablejs, final CheckBox color) {
layoutFlash.setOnClickListener(new OnClickListener() {
@Override
@ -168,17 +180,12 @@ public class SettingsActivity extends ThemableSettingsActivity { @@ -168,17 +180,12 @@ public class SettingsActivity extends ThemableSettingsActivity {
}
});
layoutOrbot.setOnClickListener(new OnClickListener() {
layoutProxyChoice.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
if (orbot.isEnabled()) {
orbot.setChecked(!orbot.isChecked());
} else {
Utils.showToast(mContext, getResources().getString(R.string.install_orbot));
}
public void onClick(View view) {
proxyChoicePicker();
}
});
layoutColor.setOnClickListener(new OnClickListener() {
@ -191,7 +198,7 @@ public class SettingsActivity extends ThemableSettingsActivity { @@ -191,7 +198,7 @@ public class SettingsActivity extends ThemableSettingsActivity {
}
public void initCheckBox(CheckBox flash, CheckBox adblock, CheckBox images, CheckBox enablejs,
CheckBox orbot, CheckBox color) {
CheckBox color) {
flash.setEnabled(API < 19);
flash.setOnCheckedChangeListener(new OnCheckedChangeListener() {
@ -253,20 +260,7 @@ public class SettingsActivity extends ThemableSettingsActivity { @@ -253,20 +260,7 @@ public class SettingsActivity extends ThemableSettingsActivity {
}
});
OrbotHelper oh = new OrbotHelper(this);
if (!oh.isOrbotInstalled()) {
orbot.setEnabled(false);
}
orbot.setOnCheckedChangeListener(new OnCheckedChangeListener() {
@Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
mPreferences.setUseProxy(isChecked);
}
});
color.setOnCheckedChangeListener(new OnCheckedChangeListener() {
@Override
@ -309,6 +303,77 @@ public class SettingsActivity extends ThemableSettingsActivity { @@ -309,6 +303,77 @@ public class SettingsActivity extends ThemableSettingsActivity {
alert.show();
}
private void proxyChoicePicker() {
AlertDialog.Builder picker = new AlertDialog.Builder(mContext);
picker.setTitle(getResources().getString(R.string.http_proxy));
picker.setSingleChoiceItems(mProxyChoices, mPreferences.getProxyChoice(),
new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
setProxyChoice(which);
}
});
picker.setNeutralButton(getResources().getString(R.string.action_ok),
new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
}
});
picker.show();
}
private void setProxyChoice(int choice) {
switch (choice) {
case Constants.PROXY_ORBOT:
OrbotHelper oh = new OrbotHelper(this);
if (!oh.isOrbotInstalled()) {
choice = Constants.NO_PROXY;
Utils.showToast(mContext, getResources().getString(R.string.install_orbot));
}
break;
case Constants.PROXY_I2P:
I2PAndroidHelper ih = new I2PAndroidHelper(this);
if (!ih.isI2PAndroidInstalled()) {
choice = Constants.NO_PROXY;
ih.promptToInstall(this);
}
break;
case Constants.PROXY_MANUAL:
manualProxyPicker();
break;
}
mPreferences.setProxyChoice(choice);
if (choice < mProxyChoices.length)
mProxyChoiceName.setText(mProxyChoices[choice]);
}
public void manualProxyPicker() {
View v = getLayoutInflater().inflate(R.layout.picker_manual_proxy, null);
final EditText eProxyHost = (EditText) v.findViewById(R.id.proxyHost);
final EditText eProxyPort = (EditText) v.findViewById(R.id.proxyPort);
eProxyHost.setText(mPreferences.getProxyHost());
eProxyPort.setText(Integer.toString(mPreferences.getProxyPort()));
new AlertDialog.Builder(mActivity)
.setTitle(R.string.manual_proxy)
.setView(v)
.setPositiveButton(R.string.action_ok, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialogInterface, int i) {
String proxyHost = eProxyHost.getText().toString();
int proxyPort = Integer.parseInt(eProxyPort.getText().toString());
mPreferences.setProxyHost(proxyHost);
mPreferences.setProxyPort(proxyPort);
mProxyChoiceName.setText(proxyHost + ":" + proxyPort);
}
})
.show();
}
public void agentPicker() {
final AlertDialog.Builder agentStringPicker = new AlertDialog.Builder(mActivity);

6
app/src/main/java/acr/browser/lightning/constant/Constants.java

@ -38,4 +38,10 @@ public final class Constants { @@ -38,4 +38,10 @@ public final class Constants {
public static final String FILE = "file://";
public static final String FOLDER = "folder://";
public static final String TAG = "Lightning";
// These should match the order of @array/proxy_choices_array
public static final int NO_PROXY = 0;
public static final int PROXY_ORBOT = 1;
public static final int PROXY_I2P = 2;
public static final int PROXY_MANUAL = 3;
}

2
app/src/main/java/acr/browser/lightning/controller/BrowserController.java

@ -54,5 +54,7 @@ public interface BrowserController { @@ -54,5 +54,7 @@ public interface BrowserController {
boolean isIncognito();
boolean isProxyReady();
int getMenu();
}

37
app/src/main/java/acr/browser/lightning/preference/PreferenceManager.java

@ -49,9 +49,11 @@ public class PreferenceManager { @@ -49,9 +49,11 @@ public class PreferenceManager {
public static final String DEFAULT_BOOKMARKS = "defaultBookmarks";
public static final String USE_PROXY = "useProxy";
public static final String PROXY_CHOICE = "proxyChoice";
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;
@ -86,6 +88,10 @@ public class PreferenceManager { @@ -86,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);
}
@ -226,6 +232,10 @@ public class PreferenceManager { @@ -226,6 +232,10 @@ public class PreferenceManager {
return mPrefs.getBoolean(Name.USE_PROXY, false);
}
public int getProxyChoice() {
return mPrefs.getInt(Name.PROXY_CHOICE, Constants.NO_PROXY);
}
public int getUserAgentChoice() {
return mPrefs.getInt(Name.USER_AGENT, 1);
}
@ -266,6 +276,10 @@ public class PreferenceManager { @@ -266,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);
}
@ -394,8 +408,27 @@ public class PreferenceManager { @@ -394,8 +408,27 @@ public class PreferenceManager {
putBoolean(Name.DARK_THEME, use);
}
public void setUseProxy(boolean enable) {
putBoolean(Name.USE_PROXY, enable);
/**
* Valid choices:
* <ul>
* <li>{@link Constants#NO_PROXY}</li>
* <li>{@link Constants#PROXY_ORBOT}</li>
* <li>{@link Constants#PROXY_I2P}</li>
* </ul>
*
* @param choice the proxy to use.
*/
public void setProxyChoice(int choice) {
putBoolean(Name.USE_PROXY, choice != Constants.NO_PROXY);
putInt(Name.PROXY_CHOICE, choice);
}
public void setProxyHost(String proxyHost) {
putString(Name.USE_PROXY_HOST, proxyHost);
}
public void setProxyPort(int proxyPort) {
putInt(Name.USE_PROXY_PORT, proxyPort);
}
public void setUserAgentChoice(int choice) {

18
app/src/main/java/acr/browser/lightning/view/LightningView.java

@ -526,6 +526,12 @@ public class LightningView { @@ -526,6 +526,12 @@ public class LightningView {
}
public synchronized void reload() {
// Check if configured proxy is available
if (!mBrowserController.isProxyReady()) {
// User has been notified
return;
}
if (mWebView != null) {
mWebView.reload();
}
@ -611,6 +617,12 @@ public class LightningView { @@ -611,6 +617,12 @@ public class LightningView {
}
public synchronized void loadUrl(String url) {
// Check if configured proxy is available
if (!mBrowserController.isProxyReady()) {
// User has been notified
return;
}
if (mWebView != null) {
mWebView.loadUrl(url);
}
@ -815,6 +827,12 @@ public class LightningView { @@ -815,6 +827,12 @@ public class LightningView {
@Override
public boolean shouldOverrideUrlLoading(WebView view, String url) {
// Check if configured proxy is available
if (!mBrowserController.isProxyReady()) {
// User has been notified
return true;
}
if (mBrowserController.isIncognito()) {
return super.shouldOverrideUrlLoading(view, url);
}

43
app/src/main/res/layout/picker_manual_proxy.xml

@ -0,0 +1,43 @@ @@ -0,0 +1,43 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:paddingLeft="4dp"
android:paddingStart="4dp">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/host"/>
<EditText
android:id="@+id/proxyHost"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:inputType="text"/>
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/port"/>
<EditText
android:id="@+id/proxyPort"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:inputType="number"/>
</LinearLayout>
</LinearLayout>

30
app/src/main/res/layout/settings.xml

@ -1,8 +1,9 @@ @@ -1,8 +1,9 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<include layout="@layout/toolbar_settings" />
@ -159,33 +160,32 @@ @@ -159,33 +160,32 @@
android:layout_marginRight="10dp"
android:background="?attr/dividerColor" />
<RelativeLayout
android:id="@+id/layoutUseOrbot"
<LinearLayout
android:id="@+id/layoutProxyChoice"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="?attr/listChoiceBackgroundIndicator"
android:minHeight="60dp"
android:orientation="vertical"
android:paddingBottom="10dp"
android:paddingRight="10dp"
android:paddingTop="10dp" >
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_centerVertical="true"
android:paddingLeft="16dp"
android:paddingRight="60dp"
android:text="@string/enable_orbot"
android:text="@string/http_proxy"
android:textAppearance="?android:attr/textAppearanceMedium" />
<CheckBox
android:id="@+id/cbOrbot"
<TextView
android:id="@+id/proxyChoiceName"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentRight="true"
android:layout_centerVertical="true" />
</RelativeLayout>
android:paddingLeft="16dp"
android:textAppearance="?android:attr/textAppearanceSmall"
android:textColor="@color/light"
tools:text="Disabled" />
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"

14
app/src/main/res/values/strings.xml

@ -158,9 +158,21 @@ @@ -158,9 +158,21 @@
<string name="powered_by_google">Powered by Google</string>
<string name="title_adblock">AdBlock</string>
<string name="message_adblock">AdBlock is currently only available in the browser\'s paid version, Lightning Browser+. It is available to download on Google Play.</string>
<string name="enable_orbot">Enable Orbot</string>
<string name="http_proxy">HTTP proxy</string>
<string-array name="proxy_choices_array">
<item>None</item>
<item>Orbot</item>
<item>I2P</item>
<item>Manual</item>
</string-array>
<string name="manual_proxy">Manual proxy</string>
<string name="host">Host:</string>
<string name="port">Port:</string>
<string name="use_tor_prompt">It looks like you have Orbot installed. Do you want to use Tor?</string>
<string name="use_i2p_prompt">It looks like you have I2P installed. Do you want to use I2P?</string>
<string name="install_orbot">Please install Orbot in order to proxy with Tor.</string>
<string name="i2p_not_running">I2P is not running.</string>
<string name="i2p_tunnels_not_ready">I2P tunnels are not ready yet.</string>
<string name="yes">Yes</string>
<string name="no">No</string>
<string name="clear_cookies_exit">Clear cookies on exit</string>

Loading…
Cancel
Save