Re-enable NetCipher to provide decent TLS on all Android versions
Revert "Revert netcipher to fix SNI regression" This reverts commit 6c8e726aadbe6714d6295882c5be87a7bf81a9f0. NetCipher is important for making sure that the client running on older versions of Android is not using extremely crappy default TLS settings. It also streamlines the Tor support. closes #431 https://gitlab.com/fdroid/fdroidclient/issues/431 closes #576 https://gitlab.com/fdroid/fdroidclient/issues/576
This commit is contained in:
parent
eed0070d4b
commit
38e4b38602
@ -1,3 +1,8 @@
|
|||||||
|
|
||||||
|
* add simple "Use Tor" preference
|
||||||
|
|
||||||
|
* Enable TLS v1.2 for officials repo on all devices that support it
|
||||||
|
|
||||||
### 0.98.1 (2016-02-14)
|
### 0.98.1 (2016-02-14)
|
||||||
|
|
||||||
* Fix crash when entering only a space into the search dialog
|
* Fix crash when entering only a space into the search dialog
|
||||||
|
@ -17,6 +17,7 @@ dependencies {
|
|||||||
compile 'com.google.zxing:core:3.2.1'
|
compile 'com.google.zxing:core:3.2.1'
|
||||||
compile 'eu.chainfire:libsuperuser:1.0.0.201602011018'
|
compile 'eu.chainfire:libsuperuser:1.0.0.201602011018'
|
||||||
compile 'cc.mvdan.accesspoint:library:0.1.3'
|
compile 'cc.mvdan.accesspoint:library:0.1.3'
|
||||||
|
compile 'info.guardianproject.netcipher:netcipher:1.2.1'
|
||||||
compile 'commons-net:commons-net:3.4'
|
compile 'commons-net:commons-net:3.4'
|
||||||
compile 'org.openhab.jmdns:jmdns:3.4.2'
|
compile 'org.openhab.jmdns:jmdns:3.4.2'
|
||||||
compile('ch.acra:acra:4.8.2') {
|
compile('ch.acra:acra:4.8.2') {
|
||||||
@ -71,6 +72,7 @@ if (!hasProperty('sourceDeps')) {
|
|||||||
'eu.chainfire:libsuperuser:952c5fc82f9c31d31d2b6a7054ee267dac1685fb037a254888c73c48de661eaf',
|
'eu.chainfire:libsuperuser:952c5fc82f9c31d31d2b6a7054ee267dac1685fb037a254888c73c48de661eaf',
|
||||||
'cc.mvdan.accesspoint:library:dc89a085d6bc40381078b8dd7776b12bde0dbaf8ffbcddb17ec4ebc3edecc7ba',
|
'cc.mvdan.accesspoint:library:dc89a085d6bc40381078b8dd7776b12bde0dbaf8ffbcddb17ec4ebc3edecc7ba',
|
||||||
'commons-net:commons-net:38cf2eca826b8bcdb236fc1f2e79e0c6dd8e7e0f5c44a3b8e839a1065b2fbe2e',
|
'commons-net:commons-net:38cf2eca826b8bcdb236fc1f2e79e0c6dd8e7e0f5c44a3b8e839a1065b2fbe2e',
|
||||||
|
'info.guardianproject.netcipher:netcipher:611ec5bde9d799fd57e1efec5c375f9f460de2cdda98918541decc9a7d02f2ad',
|
||||||
'org.openhab.jmdns:jmdns:7a4b34b5606bbd2aff7fdfe629edcb0416fccd367fb59a099f210b9aba4f0bce',
|
'org.openhab.jmdns:jmdns:7a4b34b5606bbd2aff7fdfe629edcb0416fccd367fb59a099f210b9aba4f0bce',
|
||||||
'com.madgag.spongycastle:pkix:6aba9b2210907a3d46dd3dcac782bb3424185290468d102d5207ebdc9796a905',
|
'com.madgag.spongycastle:pkix:6aba9b2210907a3d46dd3dcac782bb3424185290468d102d5207ebdc9796a905',
|
||||||
'com.madgag.spongycastle:prov:029f26cd6b67c06ffa05702d426d472c141789001bcb15b7262ed86c868e5643',
|
'com.madgag.spongycastle:prov:029f26cd6b67c06ffa05702d426d472c141789001bcb15b7262ed86c868e5643',
|
||||||
|
4
F-Droid/proguard-rules.pro
vendored
4
F-Droid/proguard-rules.pro
vendored
@ -10,6 +10,10 @@
|
|||||||
-dontnote android.support.**
|
-dontnote android.support.**
|
||||||
-dontnote **ILicensingService
|
-dontnote **ILicensingService
|
||||||
|
|
||||||
|
# StrongHttpsClient and its support classes are totally unused, so the
|
||||||
|
# ch.boye.httpclientandroidlib.** classes are also unneeded
|
||||||
|
-dontwarn info.guardianproject.netcipher.client.**
|
||||||
|
|
||||||
# These libraries are known to break if minification is enabled on them. They
|
# These libraries are known to break if minification is enabled on them. They
|
||||||
# use reflection to instantiate classes, for example. If the keep flags are
|
# use reflection to instantiate classes, for example. If the keep flags are
|
||||||
# removed, proguard will strip classes which are required, which may result in
|
# removed, proguard will strip classes which are required, which may result in
|
||||||
|
@ -166,6 +166,8 @@
|
|||||||
<string name="next">Next</string>
|
<string name="next">Next</string>
|
||||||
<string name="skip">Skip</string>
|
<string name="skip">Skip</string>
|
||||||
|
|
||||||
|
<string name="useTor">Use Tor</string>
|
||||||
|
<string name="useTorSummary">Force download traffic through Tor for increased privacy</string>
|
||||||
<string name="proxy">Proxy</string>
|
<string name="proxy">Proxy</string>
|
||||||
<string name="enable_proxy_title">Enable HTTP Proxy</string>
|
<string name="enable_proxy_title">Enable HTTP Proxy</string>
|
||||||
<string name="enable_proxy_summary">Configure HTTP Proxy for all network requests</string>
|
<string name="enable_proxy_summary">Configure HTTP Proxy for all network requests</string>
|
||||||
|
@ -48,6 +48,10 @@
|
|||||||
android:title="@string/local_repo_name" />
|
android:title="@string/local_repo_name" />
|
||||||
</PreferenceCategory>
|
</PreferenceCategory>
|
||||||
<PreferenceCategory android:title="@string/proxy" >
|
<PreferenceCategory android:title="@string/proxy" >
|
||||||
|
<CheckBoxPreference
|
||||||
|
android:key="useTor"
|
||||||
|
android:summary="@string/useTorSummary"
|
||||||
|
android:title="@string/useTor" />
|
||||||
<CheckBoxPreference
|
<CheckBoxPreference
|
||||||
android:defaultValue="false"
|
android:defaultValue="false"
|
||||||
android:key="enableProxy"
|
android:key="enableProxy"
|
||||||
|
@ -137,6 +137,7 @@ public class FDroid extends AppCompatActivity implements SearchView.OnQueryTextL
|
|||||||
@Override
|
@Override
|
||||||
protected void onResume() {
|
protected void onResume() {
|
||||||
super.onResume();
|
super.onResume();
|
||||||
|
FDroidApp.checkStartTor(this);
|
||||||
// AppDetails and RepoDetailsActivity set different NFC actions, so reset here
|
// AppDetails and RepoDetailsActivity set different NFC actions, so reset here
|
||||||
NfcHelper.setAndroidBeam(this, getApplication().getPackageName());
|
NfcHelper.setAndroidBeam(this, getApplication().getPackageName());
|
||||||
checkForAddRepoIntent(getIntent());
|
checkForAddRepoIntent(getIntent());
|
||||||
|
@ -63,6 +63,8 @@ import java.net.URLStreamHandlerFactory;
|
|||||||
import java.security.Security;
|
import java.security.Security;
|
||||||
import java.util.Locale;
|
import java.util.Locale;
|
||||||
|
|
||||||
|
import info.guardianproject.netcipher.NetCipher;
|
||||||
|
import info.guardianproject.netcipher.proxy.OrbotHelper;
|
||||||
import sun.net.www.protocol.bluetooth.Handler;
|
import sun.net.www.protocol.bluetooth.Handler;
|
||||||
|
|
||||||
@ReportsCrashes(mailTo = "reports@f-droid.org",
|
@ReportsCrashes(mailTo = "reports@f-droid.org",
|
||||||
@ -296,6 +298,8 @@ public class FDroidApp extends Application {
|
|||||||
startService(new Intent(FDroidApp.this, WifiStateChangeService.class));
|
startService(new Intent(FDroidApp.this, WifiStateChangeService.class));
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
configureTor(Preferences.get().isTorEnabled());
|
||||||
}
|
}
|
||||||
|
|
||||||
@TargetApi(18)
|
@TargetApi(18)
|
||||||
@ -352,4 +356,28 @@ public class FDroidApp extends Application {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static boolean useTor;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the proxy settings based on whether Tor should be enabled or not.
|
||||||
|
*/
|
||||||
|
public static void configureTor(boolean enabled) {
|
||||||
|
useTor = enabled;
|
||||||
|
if (useTor) {
|
||||||
|
NetCipher.useTor();
|
||||||
|
} else {
|
||||||
|
NetCipher.clearProxy();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void checkStartTor(Context context) {
|
||||||
|
if (useTor) {
|
||||||
|
OrbotHelper.requestStartTor(context);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static boolean isUsingTor() {
|
||||||
|
return useTor;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -25,9 +25,11 @@ public final class Preferences implements SharedPreferences.OnSharedPreferenceCh
|
|||||||
|
|
||||||
private static final String TAG = "Preferences";
|
private static final String TAG = "Preferences";
|
||||||
|
|
||||||
|
private final Context context;
|
||||||
private final SharedPreferences preferences;
|
private final SharedPreferences preferences;
|
||||||
|
|
||||||
private Preferences(Context context) {
|
private Preferences(Context context) {
|
||||||
|
this.context = context;
|
||||||
preferences = PreferenceManager.getDefaultSharedPreferences(context);
|
preferences = PreferenceManager.getDefaultSharedPreferences(context);
|
||||||
preferences.registerOnSharedPreferenceChangeListener(this);
|
preferences.registerOnSharedPreferenceChangeListener(this);
|
||||||
if (preferences.getString(PREF_LOCAL_REPO_NAME, null) == null) {
|
if (preferences.getString(PREF_LOCAL_REPO_NAME, null) == null) {
|
||||||
@ -54,6 +56,7 @@ public final class Preferences implements SharedPreferences.OnSharedPreferenceCh
|
|||||||
public static final String PREF_LOCAL_REPO_NAME = "localRepoName";
|
public static final String PREF_LOCAL_REPO_NAME = "localRepoName";
|
||||||
public static final String PREF_LOCAL_REPO_HTTPS = "localRepoHttps";
|
public static final String PREF_LOCAL_REPO_HTTPS = "localRepoHttps";
|
||||||
public static final String PREF_LANGUAGE = "language";
|
public static final String PREF_LANGUAGE = "language";
|
||||||
|
public static final String PREF_USE_TOR = "useTor";
|
||||||
public static final String PREF_ENABLE_PROXY = "enableProxy";
|
public static final String PREF_ENABLE_PROXY = "enableProxy";
|
||||||
public static final String PREF_PROXY_HOST = "proxyHost";
|
public static final String PREF_PROXY_HOST = "proxyHost";
|
||||||
public static final String PREF_PROXY_PORT = "proxyPort";
|
public static final String PREF_PROXY_PORT = "proxyPort";
|
||||||
@ -161,6 +164,16 @@ public final class Preferences implements SharedPreferences.OnSharedPreferenceCh
|
|||||||
return preferences.getString(PREF_LOCAL_REPO_NAME, getDefaultLocalRepoName());
|
return preferences.getString(PREF_LOCAL_REPO_NAME, getDefaultLocalRepoName());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This preference's default is set dynamically based on whether Orbot is
|
||||||
|
* installed. If Orbot is installed, default to using Tor, the user can still override
|
||||||
|
*/
|
||||||
|
public boolean isTorEnabled() {
|
||||||
|
// TODO enable once Orbot can auto-start after first install
|
||||||
|
//return preferences.getBoolean(PREF_USE_TOR, OrbotHelper.requestStartTor(context));
|
||||||
|
return preferences.getBoolean(PREF_USE_TOR, false);
|
||||||
|
}
|
||||||
|
|
||||||
public boolean isProxyEnabled() {
|
public boolean isProxyEnabled() {
|
||||||
return preferences.getBoolean(PREF_ENABLE_PROXY, DEFAULT_ENABLE_PROXY);
|
return preferences.getBoolean(PREF_ENABLE_PROXY, DEFAULT_ENABLE_PROXY);
|
||||||
}
|
}
|
||||||
|
@ -55,9 +55,6 @@ public class DownloaderFactory {
|
|||||||
String macAddress = url.getHost().replace("-", ":");
|
String macAddress = url.getHost().replace("-", ":");
|
||||||
return new BluetoothDownloader(context, macAddress, url, destFile);
|
return new BluetoothDownloader(context, macAddress, url, destFile);
|
||||||
}
|
}
|
||||||
if (isOnionAddress(url)) {
|
|
||||||
return new TorHttpDownloader(context, url, destFile);
|
|
||||||
}
|
|
||||||
if (isLocalFile(url)) {
|
if (isLocalFile(url)) {
|
||||||
return new LocalFileDownloader(context, url, destFile);
|
return new LocalFileDownloader(context, url, destFile);
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
package org.fdroid.fdroid.net;
|
package org.fdroid.fdroid.net;
|
||||||
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
|
import android.text.TextUtils;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
|
|
||||||
import com.nostra13.universalimageloader.core.download.BaseImageDownloader;
|
import com.nostra13.universalimageloader.core.download.BaseImageDownloader;
|
||||||
@ -22,8 +23,11 @@ import java.net.Proxy;
|
|||||||
import java.net.SocketAddress;
|
import java.net.SocketAddress;
|
||||||
import java.net.URL;
|
import java.net.URL;
|
||||||
|
|
||||||
|
import javax.net.ssl.HttpsURLConnection;
|
||||||
import javax.net.ssl.SSLHandshakeException;
|
import javax.net.ssl.SSLHandshakeException;
|
||||||
|
|
||||||
|
import info.guardianproject.netcipher.NetCipher;
|
||||||
|
|
||||||
public class HttpDownloader extends Downloader {
|
public class HttpDownloader extends Downloader {
|
||||||
private static final String TAG = "HttpDownloader";
|
private static final String TAG = "HttpDownloader";
|
||||||
|
|
||||||
@ -32,7 +36,7 @@ public class HttpDownloader extends Downloader {
|
|||||||
|
|
||||||
protected HttpURLConnection connection;
|
protected HttpURLConnection connection;
|
||||||
private Credentials credentials;
|
private Credentials credentials;
|
||||||
private int statusCode = -1;
|
private int statusCode = -1;
|
||||||
|
|
||||||
HttpDownloader(Context context, URL url, File destFile)
|
HttpDownloader(Context context, URL url, File destFile)
|
||||||
throws FileNotFoundException, MalformedURLException {
|
throws FileNotFoundException, MalformedURLException {
|
||||||
@ -52,6 +56,7 @@ public class HttpDownloader extends Downloader {
|
|||||||
* checking out that follows redirects up to a certain point. I guess though the correct way
|
* checking out that follows redirects up to a certain point. I guess though the correct way
|
||||||
* is probably to check for a loop (keep a list of all URLs redirected to and if you hit the
|
* is probably to check for a loop (keep a list of all URLs redirected to and if you hit the
|
||||||
* same one twice, bail with an exception).
|
* same one twice, bail with an exception).
|
||||||
|
*
|
||||||
* @throws IOException
|
* @throws IOException
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
@ -92,17 +97,29 @@ public class HttpDownloader extends Downloader {
|
|||||||
if (connection != null) {
|
if (connection != null) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
Preferences prefs = Preferences.get();
|
if (isSwapUrl()) {
|
||||||
if (prefs.isProxyEnabled() && !isSwapUrl()) {
|
// swap never works with a proxy, its unrouted IP on the same subnet
|
||||||
SocketAddress sa = new InetSocketAddress(prefs.getProxyHost(), prefs.getProxyPort());
|
|
||||||
Proxy proxy = new Proxy(Proxy.Type.HTTP, sa);
|
|
||||||
connection = (HttpURLConnection) sourceUrl.openConnection(proxy);
|
|
||||||
} else {
|
|
||||||
|
|
||||||
connection = (HttpURLConnection) sourceUrl.openConnection();
|
connection = (HttpURLConnection) sourceUrl.openConnection();
|
||||||
if (credentials != null) {
|
} else {
|
||||||
credentials.authenticate(connection);
|
Preferences prefs = Preferences.get();
|
||||||
|
if (prefs.isProxyEnabled()) {
|
||||||
|
// if "Use Tor" is set, NetCipher will ignore these proxy settings
|
||||||
|
SocketAddress sa = new InetSocketAddress(prefs.getProxyHost(), prefs.getProxyPort());
|
||||||
|
NetCipher.setProxy(new Proxy(Proxy.Type.HTTP, sa));
|
||||||
}
|
}
|
||||||
|
connection = NetCipher.getHttpURLConnection(sourceUrl);
|
||||||
|
}
|
||||||
|
|
||||||
|
// workaround until NetCipher supports HTTPS SNI
|
||||||
|
// https://gitlab.com/fdroid/fdroidclient/issues/431
|
||||||
|
if (connection instanceof HttpsURLConnection
|
||||||
|
&& !TextUtils.equals(sourceUrl.getHost(), "f-droid.org")
|
||||||
|
&& !TextUtils.equals(sourceUrl.getHost(), "guardianproject.info")) {
|
||||||
|
((HttpsURLConnection) connection).setSSLSocketFactory(HttpsURLConnection.getDefaultSSLSocketFactory());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (credentials != null) {
|
||||||
|
credentials.authenticate(connection);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -159,4 +176,4 @@ public class HttpDownloader extends Downloader {
|
|||||||
public void close() {
|
public void close() {
|
||||||
connection.disconnect();
|
connection.disconnect();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,28 +0,0 @@
|
|||||||
package org.fdroid.fdroid.net;
|
|
||||||
|
|
||||||
import android.content.Context;
|
|
||||||
|
|
||||||
import java.io.File;
|
|
||||||
import java.io.FileNotFoundException;
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.net.HttpURLConnection;
|
|
||||||
import java.net.InetSocketAddress;
|
|
||||||
import java.net.MalformedURLException;
|
|
||||||
import java.net.Proxy;
|
|
||||||
import java.net.SocketAddress;
|
|
||||||
import java.net.URL;
|
|
||||||
|
|
||||||
public class TorHttpDownloader extends HttpDownloader {
|
|
||||||
|
|
||||||
TorHttpDownloader(Context context, URL url, File destFile)
|
|
||||||
throws FileNotFoundException, MalformedURLException {
|
|
||||||
super(context, url, destFile);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void setupConnection() throws IOException {
|
|
||||||
SocketAddress sa = new InetSocketAddress("127.0.0.1", 8118);
|
|
||||||
Proxy tor = new Proxy(Proxy.Type.HTTP, sa);
|
|
||||||
connection = (HttpURLConnection) sourceUrl.openConnection(tor);
|
|
||||||
}
|
|
||||||
}
|
|
@ -127,6 +127,7 @@ public class ManageReposActivity extends ActionBarActivity {
|
|||||||
@Override
|
@Override
|
||||||
protected void onResume() {
|
protected void onResume() {
|
||||||
super.onResume();
|
super.onResume();
|
||||||
|
FDroidApp.checkStartTor(this);
|
||||||
|
|
||||||
/* let's see if someone is trying to send us a new repo */
|
/* let's see if someone is trying to send us a new repo */
|
||||||
addRepoFromIntent(getIntent());
|
addRepoFromIntent(getIntent());
|
||||||
|
@ -21,6 +21,9 @@ import org.fdroid.fdroid.PreferencesActivity;
|
|||||||
import org.fdroid.fdroid.R;
|
import org.fdroid.fdroid.R;
|
||||||
import org.fdroid.fdroid.installer.PrivilegedInstaller;
|
import org.fdroid.fdroid.installer.PrivilegedInstaller;
|
||||||
|
|
||||||
|
import info.guardianproject.netcipher.NetCipher;
|
||||||
|
import info.guardianproject.netcipher.proxy.OrbotHelper;
|
||||||
|
|
||||||
public class PreferencesFragment extends PreferenceFragment
|
public class PreferencesFragment extends PreferenceFragment
|
||||||
implements SharedPreferences.OnSharedPreferenceChangeListener {
|
implements SharedPreferences.OnSharedPreferenceChangeListener {
|
||||||
|
|
||||||
@ -43,10 +46,16 @@ public class PreferencesFragment extends PreferenceFragment
|
|||||||
Preferences.PREF_PROXY_PORT,
|
Preferences.PREF_PROXY_PORT,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
private static final int REQUEST_INSTALL_ORBOT = 0x1234;
|
||||||
|
private CheckBoxPreference enableProxyCheckPref;
|
||||||
|
private CheckBoxPreference useTorCheckPref;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onCreate(Bundle savedInstanceState) {
|
public void onCreate(Bundle savedInstanceState) {
|
||||||
super.onCreate(savedInstanceState);
|
super.onCreate(savedInstanceState);
|
||||||
addPreferencesFromResource(R.xml.preferences);
|
addPreferencesFromResource(R.xml.preferences);
|
||||||
|
useTorCheckPref = (CheckBoxPreference) findPreference(Preferences.PREF_USE_TOR);
|
||||||
|
enableProxyCheckPref = (CheckBoxPreference) findPreference(Preferences.PREF_ENABLE_PROXY);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void checkSummary(String key, int resId) {
|
private void checkSummary(String key, int resId) {
|
||||||
@ -279,6 +288,29 @@ public class PreferencesFragment extends PreferenceFragment
|
|||||||
|
|
||||||
initPrivilegedInstallerPreference();
|
initPrivilegedInstallerPreference();
|
||||||
initManagePrivilegedAppPreference();
|
initManagePrivilegedAppPreference();
|
||||||
|
// this pref's default is dynamically set based on whether Orbot is installed
|
||||||
|
boolean useTor = Preferences.get().isTorEnabled();
|
||||||
|
useTorCheckPref.setDefaultValue(useTor);
|
||||||
|
useTorCheckPref.setChecked(useTor);
|
||||||
|
useTorCheckPref.setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener() {
|
||||||
|
@Override
|
||||||
|
public boolean onPreferenceChange(Preference preference, Object enabled) {
|
||||||
|
if ((Boolean) enabled) {
|
||||||
|
final Activity activity = getActivity();
|
||||||
|
enableProxyCheckPref.setEnabled(false);
|
||||||
|
if (OrbotHelper.isOrbotInstalled(activity)) {
|
||||||
|
NetCipher.useTor();
|
||||||
|
} else {
|
||||||
|
Intent intent = OrbotHelper.getOrbotInstallIntent(activity);
|
||||||
|
activity.startActivityForResult(intent, REQUEST_INSTALL_ORBOT);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
enableProxyCheckPref.setEnabled(true);
|
||||||
|
NetCipher.clearProxy();
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
Loading…
x
Reference in New Issue
Block a user