Improve proxy
This commit is contained in:
parent
67ab25a60a
commit
bb158d821d
|
@ -16,6 +16,7 @@ package app.fedilab.android.activities;
|
|||
|
||||
import android.Manifest;
|
||||
import android.annotation.SuppressLint;
|
||||
import android.content.Context;
|
||||
import android.content.DialogInterface;
|
||||
import android.content.Intent;
|
||||
import android.content.SharedPreferences;
|
||||
|
@ -149,7 +150,7 @@ public class LoginActivity extends BaseActivity {
|
|||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
final String response = new HttpsConnection(LoginActivity.this, instance).post(Helper.instanceWithProtocol(instance) + action, 30, parameters, null);
|
||||
final String response = new HttpsConnection(LoginActivity.this, instance).post(Helper.instanceWithProtocol(LoginActivity.this, instance) + action, 30, parameters, null);
|
||||
JSONObject resobj;
|
||||
try {
|
||||
resobj = new JSONObject(response);
|
||||
|
@ -542,9 +543,9 @@ public class LoginActivity extends BaseActivity {
|
|||
try {
|
||||
String response;
|
||||
if( socialNetwork == UpdateAccountInfoAsyncTask.SOCIAL.PEERTUBE)
|
||||
response = new HttpsConnection(LoginActivity.this, instance).get(Helper.instanceWithProtocol(instance) + actionToken, 30, parameters, null );
|
||||
response = new HttpsConnection(LoginActivity.this, instance).get(Helper.instanceWithProtocol(getApplicationContext(),instance) + actionToken, 30, parameters, null );
|
||||
else
|
||||
response = new HttpsConnection(LoginActivity.this, instance).post(Helper.instanceWithProtocol(instance) + actionToken, 30, parameters, null );
|
||||
response = new HttpsConnection(LoginActivity.this, instance).post(Helper.instanceWithProtocol(getApplicationContext(), instance) + actionToken, 30, parameters, null );
|
||||
runOnUiThread(new Runnable() {
|
||||
public void run() {
|
||||
JSONObject resobj;
|
||||
|
@ -647,9 +648,9 @@ public class LoginActivity extends BaseActivity {
|
|||
try {
|
||||
String response;
|
||||
if( socialNetwork != UpdateAccountInfoAsyncTask.SOCIAL.GNU)
|
||||
response = new HttpsConnection(LoginActivity.this, instance).post(Helper.instanceWithProtocol(instance) + finalOauthUrl, 30, parameters, null );
|
||||
response = new HttpsConnection(LoginActivity.this, instance).post(Helper.instanceWithProtocol(getApplicationContext(),instance) + finalOauthUrl, 30, parameters, null );
|
||||
else {
|
||||
response = new HttpsConnection(LoginActivity.this, instance).get(Helper.instanceWithProtocol(instance) + finalOauthUrl, 30, null, basicAuth);
|
||||
response = new HttpsConnection(LoginActivity.this, instance).get(Helper.instanceWithProtocol(getApplicationContext(),instance) + finalOauthUrl, 30, null, basicAuth);
|
||||
}
|
||||
runOnUiThread(new Runnable() {
|
||||
public void run() {
|
||||
|
@ -751,7 +752,7 @@ public class LoginActivity extends BaseActivity {
|
|||
i.putExtra("instance", instance);
|
||||
startActivity(i);
|
||||
}else{
|
||||
String url = redirectUserToAuthorizeAndLogin(socialNetwork, client_id, instance);
|
||||
String url = redirectUserToAuthorizeAndLogin(getApplicationContext(), socialNetwork, client_id, instance);
|
||||
|
||||
|
||||
Helper.openBrowser(LoginActivity.this, url);
|
||||
|
@ -848,13 +849,13 @@ public class LoginActivity extends BaseActivity {
|
|||
}
|
||||
|
||||
|
||||
public static String redirectUserToAuthorizeAndLogin(UpdateAccountInfoAsyncTask.SOCIAL socialNetwork, String clientId, String instance) {
|
||||
public static String redirectUserToAuthorizeAndLogin(Context context, UpdateAccountInfoAsyncTask.SOCIAL socialNetwork, String clientId, String instance) {
|
||||
String queryString = Helper.CLIENT_ID + "="+ clientId;
|
||||
queryString += "&" + Helper.REDIRECT_URI + "="+ Uri.encode(Helper.REDIRECT_CONTENT_WEB);
|
||||
queryString += "&" + Helper.RESPONSE_TYPE +"=code";
|
||||
if( socialNetwork != UpdateAccountInfoAsyncTask.SOCIAL.PIXELFED )
|
||||
queryString += "&" + Helper.SCOPE +"=" + Helper.OAUTH_SCOPES;
|
||||
return Helper.instanceWithProtocol(instance) + Helper.EP_AUTHORIZE + "?" + queryString;
|
||||
return Helper.instanceWithProtocol(context, instance) + Helper.EP_AUTHORIZE + "?" + queryString;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -55,6 +55,7 @@ import app.fedilab.android.sqlite.DomainBlockDAO;
|
|||
import app.fedilab.android.sqlite.Sqlite;
|
||||
import app.fedilab.android.webview.MastalabWebChromeClient;
|
||||
import app.fedilab.android.webview.MastalabWebViewClient;
|
||||
import app.fedilab.android.webview.ProxyHelper;
|
||||
import es.dmoral.toasty.Toasty;
|
||||
import app.fedilab.android.R;
|
||||
|
||||
|
@ -111,6 +112,15 @@ public class WebviewActivity extends BaseActivity {
|
|||
FrameLayout webview_container = findViewById(R.id.webview_container);
|
||||
final ViewGroup videoLayout = findViewById(R.id.videoLayout); // Your own view, read class comments
|
||||
webView.getSettings().setJavaScriptEnabled(true);
|
||||
|
||||
|
||||
boolean proxyEnabled = sharedpreferences.getBoolean(Helper.SET_PROXY_ENABLED, false);
|
||||
if( proxyEnabled ){
|
||||
String host = sharedpreferences.getString(Helper.SET_PROXY_HOST, "127.0.0.1");
|
||||
int port = sharedpreferences.getInt(Helper.SET_PROXY_PORT, 8118);
|
||||
ProxyHelper.setProxy(getApplicationContext(), webView,host, port,WebviewActivity.class.getName());
|
||||
}
|
||||
|
||||
MastalabWebChromeClient mastalabWebChromeClient = new MastalabWebChromeClient(WebviewActivity.this, webView, webview_container, videoLayout);
|
||||
mastalabWebChromeClient.setOnToggledFullscreen(new MastalabWebChromeClient.ToggledFullscreenCallback() {
|
||||
@Override
|
||||
|
|
|
@ -42,10 +42,13 @@ import android.widget.Toast;
|
|||
import org.json.JSONException;
|
||||
import org.json.JSONObject;
|
||||
|
||||
import java.net.InetSocketAddress;
|
||||
import java.net.Proxy;
|
||||
import java.util.HashMap;
|
||||
|
||||
import app.fedilab.android.client.HttpsConnection;
|
||||
import app.fedilab.android.helper.Helper;
|
||||
import app.fedilab.android.webview.ProxyHelper;
|
||||
import es.dmoral.toasty.Toasty;
|
||||
import app.fedilab.android.R;
|
||||
import app.fedilab.android.asynctasks.UpdateAccountInfoAsyncTask;
|
||||
|
@ -129,6 +132,12 @@ public class WebviewConnectActivity extends BaseActivity {
|
|||
}
|
||||
});
|
||||
|
||||
boolean proxyEnabled = sharedpreferences.getBoolean(Helper.SET_PROXY_ENABLED, false);
|
||||
if( proxyEnabled ){
|
||||
String host = sharedpreferences.getString(Helper.SET_PROXY_HOST, "127.0.0.1");
|
||||
int port = sharedpreferences.getInt(Helper.SET_PROXY_PORT, 8118);
|
||||
ProxyHelper.setProxy(getApplicationContext(), webView,host, port,WebviewConnectActivity.class.getName());
|
||||
}
|
||||
|
||||
webView.setWebViewClient(new WebViewClient() {
|
||||
@SuppressWarnings("deprecation")
|
||||
|
@ -156,7 +165,7 @@ public class WebviewConnectActivity extends BaseActivity {
|
|||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
final String response = new HttpsConnection(WebviewConnectActivity.this, instance).post(Helper.instanceWithProtocol(instance) + action, 30, parameters, null);
|
||||
final String response = new HttpsConnection(WebviewConnectActivity.this, instance).post(Helper.instanceWithProtocol(getApplicationContext(), instance) + action, 30, parameters, null);
|
||||
JSONObject resobj;
|
||||
try {
|
||||
resobj = new JSONObject(response);
|
||||
|
@ -179,7 +188,7 @@ public class WebviewConnectActivity extends BaseActivity {
|
|||
}
|
||||
|
||||
});
|
||||
webView.loadUrl(LoginActivity.redirectUserToAuthorizeAndLogin(social, clientId, instance));
|
||||
webView.loadUrl(LoginActivity.redirectUserToAuthorizeAndLogin(getApplicationContext(), social, clientId, instance));
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -41,7 +41,7 @@ public class RetrieveRemoteDataAsyncTask extends AsyncTask<Void, Void, Void> {
|
|||
|
||||
|
||||
public RetrieveRemoteDataAsyncTask(Context context, String username, String instance, OnRetrieveRemoteAccountInterface onRetrieveRemoteAccountInterface){
|
||||
this.url = Helper.instanceWithProtocol(instance) + "/@" + username;
|
||||
this.url = Helper.instanceWithProtocol(context, instance) + "/@" + username;
|
||||
this.listener = onRetrieveRemoteAccountInterface;
|
||||
this.contextReference = new WeakReference<>(context);
|
||||
}
|
||||
|
|
|
@ -20,6 +20,7 @@ import android.content.SharedPreferences;
|
|||
import android.database.sqlite.SQLiteDatabase;
|
||||
import android.os.Bundle;
|
||||
import android.support.v4.content.LocalBroadcastManager;
|
||||
import android.util.Log;
|
||||
|
||||
|
||||
import com.google.gson.JsonArray;
|
||||
|
@ -179,10 +180,35 @@ public class API {
|
|||
}
|
||||
|
||||
public InstanceNodeInfo getNodeInfo(String domain){
|
||||
|
||||
//Try to guess URL scheme for the onion instance
|
||||
String scheme = "https";
|
||||
if( domain.endsWith(".onion")){
|
||||
try {
|
||||
new HttpsConnection(context, domain).get("http://" + domain, 30, null, null);
|
||||
SharedPreferences sharedpreferences = context.getSharedPreferences(Helper.APP_PREFS, Context.MODE_PRIVATE);
|
||||
SharedPreferences.Editor editor = sharedpreferences.edit();
|
||||
editor.putString(Helper.SET_ONION_SCHEME + domain, "http");
|
||||
scheme = "http";
|
||||
editor.apply();
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
} catch (NoSuchAlgorithmException e) {
|
||||
e.printStackTrace();
|
||||
} catch (KeyManagementException e) {
|
||||
e.printStackTrace();
|
||||
} catch (HttpsConnection.HttpsConnectionException e) {
|
||||
SharedPreferences sharedpreferences = context.getSharedPreferences(Helper.APP_PREFS, Context.MODE_PRIVATE);
|
||||
SharedPreferences.Editor editor = sharedpreferences.edit();
|
||||
editor.putString(Helper.SET_ONION_SCHEME + domain, "https");
|
||||
editor.apply();
|
||||
}
|
||||
}
|
||||
Log.v(Helper.TAG,"scheme: " + scheme);
|
||||
String response;
|
||||
InstanceNodeInfo instanceNodeInfo = new InstanceNodeInfo();
|
||||
try {
|
||||
response = new HttpsConnection(context, domain).get("https://" + domain + "/.well-known/nodeinfo", 30, null, null);
|
||||
response = new HttpsConnection(context, domain).get(scheme+"://" + domain + "/.well-known/nodeinfo", 30, null, null);
|
||||
JSONArray jsonArray = new JSONObject(response).getJSONArray("links");
|
||||
ArrayList<NodeInfo> nodeInfos = new ArrayList<>();
|
||||
try {
|
||||
|
@ -229,7 +255,7 @@ public class API {
|
|||
e.printStackTrace();
|
||||
} catch (HttpsConnection.HttpsConnectionException e) {
|
||||
try {
|
||||
response = new HttpsConnection(context, this.instance).get("https://" + domain + "/api/v1/instance", 30, null, null);
|
||||
response = new HttpsConnection(context, this.instance).get(scheme+"://" + domain + "/api/v1/instance", 30, null, null);
|
||||
JSONObject jsonObject = new JSONObject(response);
|
||||
instanceNodeInfo.setName("MASTODON");
|
||||
instanceNodeInfo.setVersion(jsonObject.getString("version"));
|
||||
|
@ -4961,10 +4987,10 @@ public class API {
|
|||
|
||||
|
||||
private String getAbsoluteUrl(String action) {
|
||||
return Helper.instanceWithProtocol(this.instance) + "/api/v1" + action;
|
||||
return Helper.instanceWithProtocol(this.context, this.instance) + "/api/v1" + action;
|
||||
}
|
||||
private String getAbsoluteUr2l(String action) {
|
||||
return Helper.instanceWithProtocol(this.instance) + "/api/v2" + action;
|
||||
return Helper.instanceWithProtocol(this.context, this.instance) + "/api/v2" + action;
|
||||
}
|
||||
private String getAbsoluteUrlRemote(String remote, String action) {
|
||||
return "https://" + remote + "/api/v1" + action;
|
||||
|
|
|
@ -2357,7 +2357,7 @@ public class GNUAPI {
|
|||
|
||||
|
||||
private String getAbsoluteUrl(String action) {
|
||||
return Helper.instanceWithProtocol(this.instance) + "/api" + action;
|
||||
return Helper.instanceWithProtocol(this.context, this.instance) + "/api" + action;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -14,6 +14,7 @@ package app.fedilab.android.client;
|
|||
* You should have received a copy of the GNU General Public License along with Fedilab; if not,
|
||||
* see <http://www.gnu.org/licenses>. */
|
||||
|
||||
import android.annotation.SuppressLint;
|
||||
import android.content.Context;
|
||||
import android.content.SharedPreferences;
|
||||
import android.database.sqlite.SQLiteDatabase;
|
||||
|
@ -54,7 +55,9 @@ import java.util.Scanner;
|
|||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import javax.net.ssl.HostnameVerifier;
|
||||
import javax.net.ssl.HttpsURLConnection;
|
||||
import javax.net.ssl.SSLSession;
|
||||
|
||||
import app.fedilab.android.R;
|
||||
import app.fedilab.android.activities.MainActivity;
|
||||
|
@ -122,6 +125,16 @@ public class HttpsConnection {
|
|||
}
|
||||
|
||||
}
|
||||
|
||||
if( instance != null && instance.endsWith(".onion")) {
|
||||
HttpsURLConnection.setDefaultHostnameVerifier(new HostnameVerifier() {
|
||||
@SuppressLint("BadHostnameVerifier")
|
||||
@Override
|
||||
public boolean verify(String arg0, SSLSession arg1) {
|
||||
return true;
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -2265,7 +2265,7 @@ public class PeertubeAPI {
|
|||
|
||||
|
||||
private String getAbsoluteUrl(String action) {
|
||||
return Helper.instanceWithProtocol(this.instance) + "/api/v1" + action;
|
||||
return Helper.instanceWithProtocol(this.context, this.instance) + "/api/v1" + action;
|
||||
}
|
||||
private String getAbsoluteUrlRemote(String remote, String action) {
|
||||
return "https://" + remote + "/api/v1" + action;
|
||||
|
|
|
@ -36,28 +36,31 @@ public class TLSSocketFactory extends SSLSocketFactory {
|
|||
|
||||
public TLSSocketFactory(String instance) throws KeyManagementException, NoSuchAlgorithmException {
|
||||
|
||||
sslContext = SSLContext.getInstance("TLS");
|
||||
|
||||
if( instance == null || !instance.endsWith(".onion")) {
|
||||
sslContext = SSLContext.getInstance("TLS");
|
||||
isOnion = false;
|
||||
sslContext.init(null, null, null);
|
||||
}else{
|
||||
sslContext = SSLContext.getInstance("SSL");
|
||||
isOnion = true;
|
||||
TrustManager tm = new X509TrustManager() {
|
||||
@SuppressLint("TrustAllX509TrustManager")
|
||||
public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException {
|
||||
}
|
||||
|
||||
@SuppressLint("TrustAllX509TrustManager")
|
||||
public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException {
|
||||
}
|
||||
|
||||
public X509Certificate[] getAcceptedIssuers() {
|
||||
return null;
|
||||
}
|
||||
TrustManager[] trustAllCerts = new TrustManager[]{
|
||||
new X509TrustManager() {
|
||||
public java.security.cert.X509Certificate[] getAcceptedIssuers() {
|
||||
return null;
|
||||
}
|
||||
public void checkClientTrusted(
|
||||
java.security.cert.X509Certificate[] certs, String authType) {
|
||||
}
|
||||
public void checkServerTrusted(
|
||||
java.security.cert.X509Certificate[] certs, String authType) {
|
||||
}
|
||||
}
|
||||
};
|
||||
sslContext.init(null, new TrustManager[]{tm}, null);
|
||||
sslContext.init(null, trustAllCerts, null);
|
||||
|
||||
}
|
||||
Log.v(Helper.TAG,instance + " -> " + isOnion);
|
||||
sSLSocketFactory = sslContext.getSocketFactory();
|
||||
|
||||
}
|
||||
|
|
|
@ -327,7 +327,7 @@ public class Helper {
|
|||
public static final String SET_BLUR_SENSITIVE = "set_blur_sensitive";
|
||||
public static final String SET_LONG_PRESS_MEDIA = "set_long_press_media";
|
||||
public static final String SET_DISPLAY_TIMELINE_IN_LIST = "set_display_timeline_in_list";
|
||||
|
||||
public static final String SET_ONION_SCHEME = "set_onion_scheme";
|
||||
public static final int S_NO = 0;
|
||||
static final int S_512KO = 1;
|
||||
public static final int S_1MO = 2;
|
||||
|
@ -1232,16 +1232,19 @@ public class Helper {
|
|||
}
|
||||
|
||||
public static String getLiveInstanceWithProtocol(Context context) {
|
||||
return instanceWithProtocol(getLiveInstance(context));
|
||||
return instanceWithProtocol(context, getLiveInstance(context));
|
||||
}
|
||||
|
||||
public static String instanceWithProtocol(String instance){
|
||||
public static String instanceWithProtocol(Context context, String instance){
|
||||
if( instance == null)
|
||||
return null;
|
||||
if( instance.endsWith(".onion"))
|
||||
return "http://" + instance;
|
||||
else
|
||||
if( instance.endsWith(".onion")) {
|
||||
SharedPreferences sharedpreferences = context.getSharedPreferences(Helper.APP_PREFS, Context.MODE_PRIVATE);
|
||||
String scheme = sharedpreferences.getString(SET_ONION_SCHEME+instance, "http");
|
||||
return scheme + "://" + instance;
|
||||
}else {
|
||||
return "https://" + instance;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -17,10 +17,12 @@ package app.fedilab.android.webview;
|
|||
import android.annotation.SuppressLint;
|
||||
import android.app.Activity;
|
||||
import android.graphics.Bitmap;
|
||||
import android.net.http.SslError;
|
||||
import android.support.v7.app.ActionBar;
|
||||
import android.support.v7.app.AppCompatActivity;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.webkit.SslErrorHandler;
|
||||
import android.webkit.WebResourceResponse;
|
||||
import android.webkit.WebView;
|
||||
import android.webkit.WebViewClient;
|
||||
|
@ -34,6 +36,7 @@ import java.util.List;
|
|||
|
||||
import app.fedilab.android.R;
|
||||
import app.fedilab.android.activities.WebviewActivity;
|
||||
import app.fedilab.android.helper.Helper;
|
||||
|
||||
/**
|
||||
* Created by Thomas on 25/06/2017.
|
||||
|
@ -104,6 +107,16 @@ public class MastalabWebViewClient extends WebViewClient {
|
|||
return this.domains;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onReceivedSslError(WebView view, SslErrorHandler handler, SslError error) {
|
||||
String instance = Helper.getLiveInstance(activity);
|
||||
if( instance != null && instance.endsWith(".onion")) {
|
||||
handler.proceed();
|
||||
}else{
|
||||
super.onReceivedSslError(view, handler, error);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPageStarted (WebView view, String url, Bitmap favicon) {
|
||||
super.onPageStarted(view, url, favicon);
|
||||
|
|
|
@ -0,0 +1,177 @@
|
|||
package app.fedilab.android.webview;
|
||||
/* Copyright 2019 Thomas Schneider
|
||||
*
|
||||
* This file is a part of Fedilab
|
||||
*
|
||||
* This program 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.
|
||||
*
|
||||
* Fedilab 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 Fedilab; if not,
|
||||
* see <http://www.gnu.org/licenses>. */
|
||||
import android.annotation.SuppressLint;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.net.Proxy;
|
||||
import android.os.Build;
|
||||
import android.os.Parcelable;
|
||||
import android.util.ArrayMap;
|
||||
import android.webkit.WebView;
|
||||
|
||||
import java.lang.reflect.Constructor;
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Method;
|
||||
|
||||
public class ProxyHelper {
|
||||
|
||||
|
||||
|
||||
public static void setProxy(Context context, WebView webview, String host, int port, String applicationClassName) {
|
||||
|
||||
if (Build.VERSION.SDK_INT <= 18) {
|
||||
setProxyJB(webview, host, port);
|
||||
}
|
||||
// 4.4 (KK) & 5.0 (Lollipop)
|
||||
else {
|
||||
setProxyKKPlus(context, webview, host, port, applicationClassName);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@SuppressWarnings("all")
|
||||
private static boolean setProxyICS(WebView webview, String host, int port) {
|
||||
try
|
||||
{
|
||||
Class jwcjb = Class.forName("android.webkit.JWebCoreJavaBridge");
|
||||
Class params[] = new Class[1];
|
||||
params[0] = Class.forName("android.net.ProxyProperties");
|
||||
Method updateProxyInstance = jwcjb.getDeclaredMethod("updateProxy", params);
|
||||
|
||||
Class wv = Class.forName("android.webkit.WebView");
|
||||
Field mWebViewCoreField = wv.getDeclaredField("mWebViewCore");
|
||||
Object mWebViewCoreFieldInstance = getFieldValueSafely(mWebViewCoreField, webview);
|
||||
|
||||
Class wvc = Class.forName("android.webkit.WebViewCore");
|
||||
Field mBrowserFrameField = wvc.getDeclaredField("mBrowserFrame");
|
||||
Object mBrowserFrame = getFieldValueSafely(mBrowserFrameField, mWebViewCoreFieldInstance);
|
||||
|
||||
Class bf = Class.forName("android.webkit.BrowserFrame");
|
||||
Field sJavaBridgeField = bf.getDeclaredField("sJavaBridge");
|
||||
Object sJavaBridge = getFieldValueSafely(sJavaBridgeField, mBrowserFrame);
|
||||
|
||||
Class ppclass = Class.forName("android.net.ProxyProperties");
|
||||
Class pparams[] = new Class[3];
|
||||
pparams[0] = String.class;
|
||||
pparams[1] = int.class;
|
||||
pparams[2] = String.class;
|
||||
Constructor ppcont = ppclass.getConstructor(pparams);
|
||||
|
||||
updateProxyInstance.invoke(sJavaBridge, ppcont.newInstance(host, port, null));
|
||||
return true;
|
||||
}
|
||||
catch (Exception ex) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set Proxy for Android 4.1 - 4.3.
|
||||
*/
|
||||
@SuppressWarnings("all")
|
||||
private static boolean setProxyJB(WebView webview, String host, int port) {
|
||||
|
||||
try {
|
||||
Class wvcClass = Class.forName("android.webkit.WebViewClassic");
|
||||
Class wvParams[] = new Class[1];
|
||||
wvParams[0] = Class.forName("android.webkit.WebView");
|
||||
Method fromWebView = wvcClass.getDeclaredMethod("fromWebView", wvParams);
|
||||
Object webViewClassic = fromWebView.invoke(null, webview);
|
||||
|
||||
Class wv = Class.forName("android.webkit.WebViewClassic");
|
||||
Field mWebViewCoreField = wv.getDeclaredField("mWebViewCore");
|
||||
Object mWebViewCoreFieldInstance = getFieldValueSafely(mWebViewCoreField, webViewClassic);
|
||||
|
||||
Class wvc = Class.forName("android.webkit.WebViewCore");
|
||||
Field mBrowserFrameField = wvc.getDeclaredField("mBrowserFrame");
|
||||
Object mBrowserFrame = getFieldValueSafely(mBrowserFrameField, mWebViewCoreFieldInstance);
|
||||
|
||||
Class bf = Class.forName("android.webkit.BrowserFrame");
|
||||
Field sJavaBridgeField = bf.getDeclaredField("sJavaBridge");
|
||||
Object sJavaBridge = getFieldValueSafely(sJavaBridgeField, mBrowserFrame);
|
||||
|
||||
Class ppclass = Class.forName("android.net.ProxyProperties");
|
||||
Class pparams[] = new Class[3];
|
||||
pparams[0] = String.class;
|
||||
pparams[1] = int.class;
|
||||
pparams[2] = String.class;
|
||||
Constructor ppcont = ppclass.getConstructor(pparams);
|
||||
|
||||
Class jwcjb = Class.forName("android.webkit.JWebCoreJavaBridge");
|
||||
Class params[] = new Class[1];
|
||||
params[0] = Class.forName("android.net.ProxyProperties");
|
||||
Method updateProxyInstance = jwcjb.getDeclaredMethod("updateProxy", params);
|
||||
|
||||
updateProxyInstance.invoke(sJavaBridge, ppcont.newInstance(host, port, null));
|
||||
} catch (Exception ex) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
// from https://stackoverflow.com/questions/19979578/android-webview-set-proxy-programatically-kitkat
|
||||
@SuppressLint("NewApi")
|
||||
@SuppressWarnings("all")
|
||||
private static void setProxyKKPlus(Context appContext, WebView webView, String host, int port, String applicationClassName) {
|
||||
|
||||
System.setProperty("http.proxyHost", host);
|
||||
System.setProperty("http.proxyPort", port + "");
|
||||
System.setProperty("https.proxyHost", host);
|
||||
System.setProperty("https.proxyPort", port + "");
|
||||
try {
|
||||
Class applictionCls = Class.forName("android.app.Application");
|
||||
Field loadedApkField = applictionCls.getDeclaredField("mLoadedApk");
|
||||
loadedApkField.setAccessible(true);
|
||||
Object loadedApk = loadedApkField.get(appContext);
|
||||
Class loadedApkCls = Class.forName("android.app.LoadedApk");
|
||||
Field receiversField = loadedApkCls.getDeclaredField("mReceivers");
|
||||
receiversField.setAccessible(true);
|
||||
ArrayMap receivers = (ArrayMap) receiversField.get(loadedApk);
|
||||
for (Object receiverMap : receivers.values()) {
|
||||
for (Object rec : ((ArrayMap) receiverMap).keySet()) {
|
||||
Class clazz = rec.getClass();
|
||||
if (clazz.getName().contains("ProxyChangeListener")) {
|
||||
Method onReceiveMethod = clazz.getDeclaredMethod("onReceive", Context.class, Intent.class);
|
||||
Intent intent = new Intent(Proxy.PROXY_CHANGE_ACTION);
|
||||
|
||||
onReceiveMethod.invoke(rec, appContext, intent);
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (ClassNotFoundException e) {
|
||||
e.printStackTrace();
|
||||
} catch (NoSuchFieldException e) {
|
||||
e.printStackTrace();
|
||||
} catch (IllegalAccessException e) {
|
||||
e.printStackTrace();
|
||||
} catch (IllegalArgumentException e) {
|
||||
e.printStackTrace();
|
||||
} catch (NoSuchMethodException e) {
|
||||
e.printStackTrace();
|
||||
} catch (InvocationTargetException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
private static Object getFieldValueSafely(Field field, Object classInstance) throws IllegalArgumentException, IllegalAccessException {
|
||||
boolean oldAccessibleValue = field.isAccessible();
|
||||
field.setAccessible(true);
|
||||
Object result = field.get(classInstance);
|
||||
field.setAccessible(oldAccessibleValue);
|
||||
return result;
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue