 Issue 4705284891082752:
  Proxy configurators  (Closed)
    
  
    Issue 4705284891082752:
  Proxy configurators  (Closed) 
  | Index: src/org/adblockplus/android/configurators/ReflectionProxyConfigurator.java | 
| diff --git a/src/org/adblockplus/android/configurators/ReflectionProxyConfigurator.java b/src/org/adblockplus/android/configurators/ReflectionProxyConfigurator.java | 
| new file mode 100644 | 
| index 0000000000000000000000000000000000000000..6260796f69cad293d97ed20f07856adb7220fca4 | 
| --- /dev/null | 
| +++ b/src/org/adblockplus/android/configurators/ReflectionProxyConfigurator.java | 
| @@ -0,0 +1,234 @@ | 
| +/* | 
| + * This file is part of Adblock Plus <http://adblockplus.org/>, | 
| + * Copyright (C) 2006-2014 Eyeo GmbH | 
| + * | 
| + * Adblock Plus is free software: you can redistribute it and/or modify | 
| + * it under the terms of the GNU General Public License version 3 as | 
| + * published by the Free Software Foundation. | 
| + * | 
| + * Adblock Plus 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 Adblock Plus. If not, see <http://www.gnu.org/licenses/>. | 
| + */ | 
| + | 
| +package org.adblockplus.android.configurators; | 
| + | 
| +import java.net.InetAddress; | 
| + | 
| +import org.adblockplus.android.compat.CompatibilityException; | 
| +import org.adblockplus.android.compat.LinkProperties; | 
| +import org.adblockplus.android.compat.ProxyProperties; | 
| + | 
| +import android.content.BroadcastReceiver; | 
| +import android.content.Context; | 
| +import android.content.Intent; | 
| +import android.content.IntentFilter; | 
| +import android.net.ConnectivityManager; | 
| +import android.net.NetworkInfo; | 
| +import android.os.Parcelable; | 
| + | 
| +/** | 
| + * Proxy registrator using {@code android.net.LinkProperties} via reflection. | 
| + * | 
| + * @author rjeschke | 
| + */ | 
| +public class ReflectionProxyConfigurator implements ProxyConfigurator | 
| 
Felix Dahlke
2014/08/19 09:06:00
Maybe we should rather call this "NativeProxyConfi
 
René Jeschke
2014/08/19 10:41:33
k, why not ;-)
 | 
| +{ | 
| + private final Context context; | 
| + private final WiFiChangeReceiver wiFiChangeReceiver; | 
| + private ProxyProperties proxyProperties = null; | 
| + | 
| + public ReflectionProxyConfigurator(final Context context) | 
| + { | 
| + this.context = context; | 
| + this.wiFiChangeReceiver = new WiFiChangeReceiver(this); | 
| + } | 
| + | 
| + /** | 
| + * Reliably checks for setHttpProxy hack using {@code android.net.wifi.LINK_CONFIGURATION_CHANGED}. | 
| + * | 
| + * @param context | 
| + * The context used for querying the {@code ConnectivityManager} | 
| + * @return {@code true} if we can set a WiFi proxy using this method | 
| + */ | 
| + public static boolean canUse(final Context context) | 
| + { | 
| + try | 
| + { | 
| + final ConnectivityManager conMan = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE); | 
| + final NetworkInfo ni = conMan.getActiveNetworkInfo(); | 
| + | 
| + final Object lp; | 
| + | 
| + // Check if we're currently running on WiFi | 
| + if (ni != null && ni.getType() == ConnectivityManager.TYPE_WIFI) | 
| + { | 
| + // I'm using reflection directly here to keep this method self-contained. | 
| + lp = conMan.getClass() | 
| + .getMethod("getActiveLinkProperties") | 
| + .invoke(conMan); | 
| + } | 
| + else | 
| + // We're not running on WiFi so get the last used WiFi link properties | 
| + { | 
| + // I'm using reflection directly here to keep this method self-contained. | 
| + lp = conMan.getClass() | 
| + .getMethod("getLinkProperties", int.class) | 
| + .invoke(conMan, ConnectivityManager.TYPE_WIFI); | 
| + } | 
| + | 
| + if (lp == null) | 
| + { | 
| + // Is this even possible? | 
| + throw new IllegalStateException("No WiFi?"); | 
| + } | 
| + | 
| + context.sendBroadcast( | 
| + new Intent("android.net.wifi.LINK_CONFIGURATION_CHANGED") | 
| + .putExtra("linkProperties", (Parcelable) lp)); | 
| + } | 
| + catch (final Throwable t) | 
| + { | 
| + return false; | 
| + } | 
| + | 
| + return true; | 
| + } | 
| + | 
| + @Override | 
| + public boolean initialize() | 
| + { | 
| + if (canUse(this.context)) | 
| + { | 
| + this.context.registerReceiver(this.wiFiChangeReceiver, new IntentFilter(ConnectivityManager.CONNECTIVITY_ACTION)); | 
| + return true; | 
| + } | 
| + | 
| + return false; | 
| + } | 
| + | 
| + private boolean sendIntent(final LinkProperties lp, final ProxyProperties proxyProperties) | 
| + { | 
| + boolean success = true; | 
| + | 
| + final ConnectivityManager conMan = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE); | 
| + final NetworkInfo ni = conMan.getActiveNetworkInfo(); | 
| + | 
| + if (ni != null && ni.getType() == ConnectivityManager.TYPE_WIFI) | 
| + { | 
| + final Intent intent = new Intent("android.net.wifi.LINK_CONFIGURATION_CHANGED"); | 
| + | 
| + if (lp.isValid()) | 
| + { | 
| + try | 
| + { | 
| + lp.setHttpProxy(proxyProperties); | 
| + intent.putExtra("linkProperties", (Parcelable) lp.getLinkProperties()); | 
| + context.sendBroadcast(intent); | 
| + } | 
| + catch (final Exception e) | 
| + { | 
| + // Catch all, again | 
| + success = false; | 
| + } | 
| + } | 
| + } | 
| + | 
| + return success; | 
| + } | 
| + | 
| + private boolean registerProxy(final ProxyProperties proxyProperties) | 
| + { | 
| + try | 
| + { | 
| + final ConnectivityManager conMan = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE); | 
| + | 
| + return this.sendIntent(LinkProperties.getActiveLinkProperties(conMan), proxyProperties); | 
| + } | 
| + catch (final CompatibilityException e) | 
| + { | 
| + return false; | 
| + } | 
| + } | 
| + | 
| + private boolean reRegisterProxy() | 
| + { | 
| + return this.registerProxy(this.proxyProperties); | 
| + } | 
| + | 
| + @Override | 
| + public boolean registerProxy(final InetAddress address, final int port) | 
| + { | 
| + this.proxyProperties = new ProxyProperties(address.getHostName(), port, ""); | 
| + | 
| + return this.registerProxy(this.proxyProperties); | 
| + } | 
| + | 
| + @Override | 
| + public void unregisterProxy() | 
| + { | 
| + this.proxyProperties = null; | 
| + | 
| + this.registerProxy(this.proxyProperties); | 
| + } | 
| + | 
| + @Override | 
| + public void shutdown() | 
| + { | 
| + this.context.unregisterReceiver(this.wiFiChangeReceiver); | 
| + } | 
| + | 
| + @Override | 
| + public ProxyRegistrationType getType() | 
| + { | 
| + return ProxyRegistrationType.REFLECTION; | 
| + } | 
| + | 
| + @Override | 
| + public boolean isRegistered() | 
| + { | 
| + // TODO Auto-generated method stub | 
| + return false; | 
| + } | 
| + | 
| + @Override | 
| + public boolean isSticky() | 
| + { | 
| + return false; | 
| + } | 
| + | 
| + @Override | 
| + public String toString() | 
| + { | 
| + return "[ProxyConfigurator: " + this.getType() + "]"; | 
| + } | 
| + | 
| + private final static class WiFiChangeReceiver extends BroadcastReceiver | 
| + { | 
| + private final ReflectionProxyConfigurator configurator; | 
| + | 
| + private WiFiChangeReceiver(final ReflectionProxyConfigurator configurator) | 
| + { | 
| + this.configurator = configurator; | 
| + } | 
| + | 
| + @Override | 
| + public void onReceive(final Context context, final Intent intent) | 
| + { | 
| + if (ConnectivityManager.CONNECTIVITY_ACTION.equals(intent.getAction())) | 
| + { | 
| + final ConnectivityManager connectivityManager = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE); | 
| + final NetworkInfo ni = connectivityManager.getActiveNetworkInfo(); | 
| + | 
| + if (ni != null && ni.getType() == ConnectivityManager.TYPE_WIFI && ni.isAvailable() && ni.isConnected()) | 
| + { | 
| + this.configurator.reRegisterProxy(); | 
| + } | 
| + } | 
| + } | 
| + } | 
| +} |