com.dwdesign.tweetings.util.WebViewProxySettings.java Source code

Java tutorial

Introduction

Here is the source code for com.dwdesign.tweetings.util.WebViewProxySettings.java

Source

/*
 *            Tweetings - Twitter client for Android
 * 
 * Copyright (C) 2012 Psiphon
 *
 * Copyright (C) 2012-2013 RBD Solutions Limited <apps@tweetings.net>
 * Copyright (C) 2012 Mariotaku Lee <mariotaku.lee@gmail.com>
 *
 * 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.
 *
 * This program 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 this program.  If not, see <http://www.gnu.org/licenses/>.
 */

package com.dwdesign.tweetings.util;

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

import org.apache.http.HttpHost;

import android.content.Context;
import android.util.Log;
import android.webkit.WebView;

/**
 * Utility class for setting WebKit proxy used by Android WebView
 */
public class WebViewProxySettings {

    public static void resetProxy(WebView webView) {
        final Context context = webView.getContext();
        try {
            final Object requestQueueObject = getRequestQueue(context);
            if (requestQueueObject != null) {
                setDeclaredField(requestQueueObject, "mProxyHost", null);
            }
        } catch (final Exception e) {
            Log.e("ProxySettings", "Exception resetting WebKit proxy: " + e.toString());
        }
    }

    public static boolean setProxy(WebView webView, String host, int port) {
        final Context context = webView.getContext();
        // PSIPHON: added support for Android 4.x WebView proxy
        try {
            final Class<?> webViewCoreClass = Class.forName("android.webkit.WebViewCore");
            final Class<?> proxyPropertiesClass = Class.forName("android.net.ProxyProperties");
            if (webViewCoreClass != null && proxyPropertiesClass != null) {
                final Method m = webViewCoreClass.getDeclaredMethod("sendStaticMessage", Integer.TYPE,
                        Object.class);
                final Constructor<?> c = proxyPropertiesClass.getConstructor(String.class, Integer.TYPE,
                        String.class);

                if (m != null && c != null) {
                    m.setAccessible(true);
                    c.setAccessible(true);
                    final Object properties = c.newInstance(host, port, null);

                    // android.webkit.WebViewCore.EventHub.PROXY_CHANGED = 193;
                    m.invoke(null, 193, properties);
                    return true;
                }
            }
        } catch (final Exception e) {
            Log.e("ProxySettings",
                    "Exception setting WebKit proxy through android.net.ProxyProperties: " + e.toString());
        }

        try {
            final Object requestQueueObject = getRequestQueue(context);
            if (requestQueueObject != null) {
                // Create Proxy config object and set it into request Q
                final HttpHost httpHost = new HttpHost(host, port, "http");
                setDeclaredField(requestQueueObject, "mProxyHost", httpHost);
                // Log.d("Webkit Setted Proxy to: " + host + ":" + port);
                return true;
            }
        } catch (final Exception e) {
            Log.e("ProxySettings",
                    "Exception setting WebKit proxy through android.webkit.Network: " + e.toString());
        }

        return false;
    }

    private static Object getDeclaredField(Object obj, String name)
            throws SecurityException, NoSuchFieldException, IllegalArgumentException, IllegalAccessException {
        final Field f = obj.getClass().getDeclaredField(name);
        f.setAccessible(true);
        return f.get(obj);
    }

    @SuppressWarnings("rawtypes")
    private static Object getNetworkInstance(Context context) throws ClassNotFoundException {
        final Class networkClass = Class.forName("android.webkit.Network");
        return networkClass;
    }

    private static Object getRequestQueue(Context context) throws Exception {
        final Object networkClass = getNetworkInstance(context);
        if (networkClass != null) {
            final Object networkObj = invokeMethod(networkClass, "getInstance", new Object[] { context },
                    Context.class);
            if (networkObj != null)
                return getDeclaredField(networkObj, "mRequestQueue");
        }
        return null;
    }

    @SuppressWarnings("rawtypes")
    private static Object invokeMethod(Object object, String methodName, Object[] params, Class... types)
            throws Exception {
        final Class<?> c = object instanceof Class ? (Class) object : object.getClass();

        if (types != null) {
            final Method method = c.getMethod(methodName, types);
            return method.invoke(object, params);
        } else {
            final Method method = c.getMethod(methodName);
            return method.invoke(object);
        }
    }

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

}