package com.rho.webview;

import android.annotation.TargetApi;
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.util.*;

import org.apache.http.HttpHost;

import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

/**
 * Utility class for setting WebKit proxy used by Android WebView
 */
@SuppressWarnings({"unchecked", "ConstantConditions"})
public class ProxySettings {

    private static final String TAG = "ProxySettings";
    public static final String LOG_TAG = TAG;

    static final int PROXY_CHANGED = 193;

    private static Object getDeclaredField(Object obj, String name) throws SecurityException,
            NoSuchFieldException, IllegalArgumentException, IllegalAccessException {
        Field f = obj.getClass().getDeclaredField(name);
        f.setAccessible(true);
        // System.out.println(obj.getClass().getName() + "." + name + " = "+
        // out);
        return f.get(obj);
    }

    public static Object getRequestQueue(Context ctx) throws Exception {
        Object ret = null;
        Class networkClass = Class.forName("android.webkit.Network");
        if (networkClass != null) {
            Object networkObj = invokeMethod(networkClass, "getInstance", new Object[]{ctx},
                    Context.class);
            if (networkObj != null) {
                ret = getDeclaredField(networkObj, "mRequestQueue");
            }
        }
        return ret;
    }

    private static Object invokeMethod(Object object, String methodName, Object[] params,
                                       Class... types) throws Exception {
        Object out = null;
        Class c = object instanceof Class ? (Class) object : object.getClass();
        if (types != null) {
            Method method = c.getMethod(methodName, types);
            out = method.invoke(object, params);
        } else {
            Method method = c.getMethod(methodName);
            out = method.invoke(object);
        }
        // System.out.println(object.getClass().getName() + "." + methodName +
        // "() = "+ out);
        return out;
    }

    public static void resetProxy(Context ctx) throws Exception {
        Object requestQueueObject = getRequestQueue(ctx);
        if (requestQueueObject != null) {
            setDeclaredField(requestQueueObject, "mProxyHost", null);
        }
    }

    private static void setDeclaredField(Object obj, String name, Object value)
            throws SecurityException, NoSuchFieldException, IllegalArgumentException,
            IllegalAccessException {
        Field f = obj.getClass().getDeclaredField(name);
        f.setAccessible(true);
        f.set(obj, value);
    }

    /**
     * Override WebKit Proxy settings
     *
     * @param ctx  Android ApplicationContext
     * @param host
     * @param port
     * @return true if Proxy was successfully set
     */
    public static boolean setProxy(Context ctx, String host, int port) {
        boolean ret = false;
        setSystemProperties(host, port);

        try {
            if (Build.VERSION.SDK_INT > 18) {
                ret = setKitKatProxy(ctx, host, port);
            } else if (Build.VERSION.SDK_INT > 13) {
                ret = setICSProxy(host, port);
            } else {
                Object requestQueueObject = getRequestQueue(ctx);
                if (requestQueueObject != null) {
                    // Create Proxy config object and set it into request Q
                    HttpHost httpHost = new HttpHost(host, port, "http");

                    setDeclaredField(requestQueueObject, "mProxyHost", httpHost);
                    ret = true;
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return ret;
    }

    private static boolean setICSProxy(String host, int port) throws ClassNotFoundException,
            NoSuchMethodException, IllegalArgumentException, InstantiationException,
            IllegalAccessException, InvocationTargetException {
        Class webViewCoreClass = Class.forName("android.webkit.WebViewCore");
        Class proxyPropertiesClass = Class.forName("android.net.ProxyProperties");
        if (webViewCoreClass != null && proxyPropertiesClass != null) {
            Method m = webViewCoreClass.getDeclaredMethod("sendStaticMessage", Integer.TYPE,
                    Object.class);
            Constructor c = proxyPropertiesClass.getConstructor(String.class, Integer.TYPE,
                    String.class);
            m.setAccessible(true);
            c.setAccessible(true);
            Object properties = c.newInstance(host, port, null);
            m.invoke(null, PROXY_CHANGED, properties);
            return true;
        }
        return false;

    }

 
    private static boolean setKitKatProxy(Context context, String host, int port) {
        Context appContext = context.getApplicationContext();
        try {
        	System.out.println("http_proxy setKitKatProxy 1");
            Class applictionCls = appContext.getClass();
            System.out.println("http_proxy setKitKatProxy 2");
            Field loadedApkField = applictionCls.getField("mLoadedApk");
            loadedApkField.setAccessible(true);
            Object loadedApk = loadedApkField.get(appContext);
            Class loadedApkCls = Class.forName("android.app.LoadedApk");
            Field receiversField = loadedApkCls.getDeclaredField("mReceivers");
            receiversField.setAccessible(true);
            System.out.println("http_proxy setKitKatProxy 4");
            ArrayMap receivers = (ArrayMap) receiversField.get(loadedApk);
            System.out.println("http_proxy setKitKatProxy 5");
            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);

                        /*********** optional, may be need in future *************/
                        final String CLASS_NAME = "android.net.ProxyProperties";
                        Class cls = Class.forName(CLASS_NAME);
                        Constructor constructor = cls.getConstructor(String.class, Integer.TYPE, String.class);
                        constructor.setAccessible(true);
                        Object proxyProperties = constructor.newInstance(host, port, null);
                        intent.putExtra("proxy", (Parcelable) proxyProperties);
                        /*********** optional, may be need in future *************/
                        System.out.println("http_proxy setKitKatProxy 6");
                        onReceiveMethod.invoke(rec, appContext, intent);
                    }
                }
            }
            System.out.println("http_proxy setKitKatProxy 2");
            return true;
        } catch (Exception e) {
        	  System.out.println("http_proxy setKitKatProxy cattch");
            e.printStackTrace();
        }
        return false;
    }

    private static void setSystemProperties(String host, int port) {

        System.setProperty("http.proxyHost", host);
        System.setProperty("http.proxyPort", port + "");

        System.setProperty("https.proxyHost", host);
        System.setProperty("https.proxyPort", port + "");
     }
}

@@ -5126,58 +5126,8 @@
    %09
-System.out.println(%22http_proxy setKitKatProxy 1%22);
 %0A   
@@ -5195,59 +5195,8 @@
     
- System.out.println(%22http_proxy setKitKatProxy 2%22);
 %0A   
@@ -5593,58 +5593,8 @@
     
-System.out.println(%22http_proxy setKitKatProxy 4%22);
 %0A   
@@ -5680,59 +5680,8 @@
     
- System.out.println(%22http_proxy setKitKatProxy 5%22);
 %0A   
@@ -6808,60 +6808,8 @@
     
-  System.out.println(%22http_proxy setKitKatProxy 6%22);
 %0A   
@@ -6946,60 +6946,8 @@
     
-  System.out.println(%22http_proxy setKitKatProxy 2%22);
 %0A   
@@ -7013,65 +7013,8 @@
    %09
-  System.out.println(%22http_proxy setKitKatProxy cattch%22);
 %0A   

Update ProxySettings.java