Rietveld Code Review Tool
Help | Bug tracker | Discussion group | Source code

Unified Diff: src/org/adblockplus/android/configurators/NativeProxyConfigurator.java

Issue 4705284891082752: Proxy configurators (Closed)
Patch Set: Removed command bridge Created Aug. 21, 2014, 7:48 a.m.
Use n/p to move between diff chunks; N/P to move between comments.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: src/org/adblockplus/android/configurators/NativeProxyConfigurator.java
diff --git a/src/org/adblockplus/android/configurators/NativeProxyConfigurator.java b/src/org/adblockplus/android/configurators/NativeProxyConfigurator.java
new file mode 100644
index 0000000000000000000000000000000000000000..f39a270e199969cb74974d82b8ad315bec8fc289
--- /dev/null
+++ b/src/org/adblockplus/android/configurators/NativeProxyConfigurator.java
@@ -0,0 +1,232 @@
+/*
+ * 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 setting native proxy using {@code android.net.LinkProperties} via reflection.
+ */
+public class NativeProxyConfigurator implements ProxyConfigurator
+{
+ private final Context context;
+ private final WiFiChangeReceiver wiFiChangeReceiver;
+ private ProxyProperties proxyProperties;
+ private boolean isRegistered = false;
+
+ public NativeProxyConfigurator(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.
Felix Dahlke 2014/08/24 11:51:19 Should rather be "We're" instead of "I'm" :). Or j
René Jeschke 2014/08/24 11:54:14 Done.
+ 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;
Felix Dahlke 2014/08/24 11:51:19 Why not just "return false" here and "return true"
René Jeschke 2014/08/24 11:54:14 Done.
+ }
+ }
+ }
+
+ 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.isRegistered = this.registerProxy(this.proxyProperties);
+ }
+
+ @Override
+ public void unregisterProxy()
+ {
+ this.proxyProperties = null;
+ this.isRegistered = false;
+ this.registerProxy(this.proxyProperties);
+ }
+
+ @Override
+ public void shutdown()
+ {
+ this.context.unregisterReceiver(this.wiFiChangeReceiver);
+ }
+
+ @Override
+ public ProxyRegistrationType getType()
+ {
+ return ProxyRegistrationType.NATIVE;
+ }
+
+ @Override
+ public boolean isRegistered()
+ {
+ return this.isRegistered;
+ }
+
+ @Override
+ public boolean isSticky()
+ {
+ return false;
+ }
+
+ @Override
+ public String toString()
+ {
+ return "[ProxyConfigurator: " + this.getType() + "]";
+ }
+
+ private final static class WiFiChangeReceiver extends BroadcastReceiver
+ {
+ private final NativeProxyConfigurator configurator;
+
+ private WiFiChangeReceiver(final NativeProxyConfigurator 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();
+ }
+ }
+ }
+ }
+}

Powered by Google App Engine
This is Rietveld