1 // Copyright 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 package org.chromium.net;
7 import android.content.BroadcastReceiver;
8 import android.content.Context;
9 import android.content.Intent;
10 import android.content.IntentFilter;
11 import android.net.Proxy;
12 import android.os.Build;
13 import android.util.Log;
15 import org.chromium.base.CalledByNative;
16 import org.chromium.base.JNINamespace;
17 import org.chromium.base.NativeClassQualifiedName;
19 import java.lang.reflect.InvocationTargetException;
20 import java.lang.reflect.Method;
23 * This class partners with native ProxyConfigServiceAndroid to listen for
24 * proxy change notifications from Android.
27 public class ProxyChangeListener {
28 private static final String TAG = "ProxyChangeListener";
29 private static boolean sEnabled = true;
31 private long mNativePtr;
32 private Context mContext;
33 private ProxyReceiver mProxyReceiver;
34 private Delegate mDelegate;
36 private static class ProxyConfig {
37 public ProxyConfig(String host, int port) {
41 public final String mHost;
42 public final int mPort;
45 public interface Delegate {
46 public void proxySettingsChanged();
49 private ProxyChangeListener(Context context) {
53 public static void setEnabled(boolean enabled) {
57 public void setDelegateForTesting(Delegate delegate) {
62 public static ProxyChangeListener create(Context context) {
63 return new ProxyChangeListener(context);
67 public static String getProperty(String property) {
68 return System.getProperty(property);
72 public void start(long nativePtr) {
73 assert mNativePtr == 0;
74 mNativePtr = nativePtr;
84 private class ProxyReceiver extends BroadcastReceiver {
86 public void onReceive(Context context, Intent intent) {
87 if (intent.getAction().equals(Proxy.PROXY_CHANGE_ACTION)) {
88 proxySettingsChanged(extractNewProxy(intent));
92 // Extract a ProxyConfig object from the supplied Intent's extra data
93 // bundle. The android.net.ProxyProperties class is not exported from
94 // tne Android SDK, so we have to use reflection to get at it and invoke
95 // methods on it. If we fail, return an empty proxy config (meaning
97 // TODO(sgurun): once android.net.ProxyInfo is public, rewrite this.
98 private ProxyConfig extractNewProxy(Intent intent) {
100 final String GET_HOST_NAME = "getHost";
101 final String GET_PORT_NAME = "getPort";
102 Object props = intent.getExtras().get("proxy");
107 if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.KITKAT) {
108 className = "android.net.ProxyProperties";
110 className = "android.net.ProxyInfo";
113 Class<?> cls = Class.forName(className);
114 Method getHostMethod = cls.getDeclaredMethod(GET_HOST_NAME);
115 Method getPortMethod = cls.getDeclaredMethod(GET_PORT_NAME);
117 String host = (String) getHostMethod.invoke(props);
118 int port = (Integer) getPortMethod.invoke(props);
120 return new ProxyConfig(host, port);
121 } catch (ClassNotFoundException ex) {
122 Log.e(TAG, "Using no proxy configuration due to exception:" + ex);
124 } catch (NoSuchMethodException ex) {
125 Log.e(TAG, "Using no proxy configuration due to exception:" + ex);
127 } catch (IllegalAccessException ex) {
128 Log.e(TAG, "Using no proxy configuration due to exception:" + ex);
130 } catch (InvocationTargetException ex) {
131 Log.e(TAG, "Using no proxy configuration due to exception:" + ex);
133 } catch (NullPointerException ex) {
134 Log.e(TAG, "Using no proxy configuration due to exception:" + ex);
140 private void proxySettingsChanged(ProxyConfig cfg) {
144 if (mDelegate != null) {
145 mDelegate.proxySettingsChanged();
147 if (mNativePtr == 0) {
150 // Note that this code currently runs on a MESSAGE_LOOP_UI thread, but
151 // the C++ code must run the callbacks on the network thread.
153 nativeProxySettingsChangedTo(mNativePtr, cfg.mHost, cfg.mPort);
155 nativeProxySettingsChanged(mNativePtr);
159 private void registerReceiver() {
160 if (mProxyReceiver != null) {
163 IntentFilter filter = new IntentFilter();
164 filter.addAction(Proxy.PROXY_CHANGE_ACTION);
165 mProxyReceiver = new ProxyReceiver();
166 mContext.getApplicationContext().registerReceiver(mProxyReceiver, filter);
169 private void unregisterReceiver() {
170 if (mProxyReceiver == null) {
173 mContext.unregisterReceiver(mProxyReceiver);
174 mProxyReceiver = null;
178 * See net/proxy/proxy_config_service_android.cc
180 @NativeClassQualifiedName("ProxyConfigServiceAndroid::JNIDelegate")
181 private native void nativeProxySettingsChangedTo(long nativePtr,
184 @NativeClassQualifiedName("ProxyConfigServiceAndroid::JNIDelegate")
185 private native void nativeProxySettingsChanged(long nativePtr);