OLD | NEW |
1 // Copyright 2012 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 package org.chromium.net; | 5 package org.chromium.net; |
6 | 6 |
7 import android.content.BroadcastReceiver; | 7 import android.content.BroadcastReceiver; |
8 import android.content.Context; | 8 import android.content.Context; |
9 import android.content.Intent; | 9 import android.content.Intent; |
10 import android.content.IntentFilter; | 10 import android.content.IntentFilter; |
11 import android.net.Proxy; | 11 import android.net.Proxy; |
12 import android.net.Uri; | 12 import android.net.Uri; |
13 import android.os.Build; | 13 import android.os.Build; |
| 14 import android.os.Handler; |
| 15 import android.os.Looper; |
14 import android.text.TextUtils; | 16 import android.text.TextUtils; |
15 import android.util.Log; | 17 import android.util.Log; |
16 | 18 |
| 19 import org.chromium.base.BuildConfig; |
17 import org.chromium.base.ContextUtils; | 20 import org.chromium.base.ContextUtils; |
18 import org.chromium.base.annotations.CalledByNative; | 21 import org.chromium.base.annotations.CalledByNative; |
19 import org.chromium.base.annotations.JNINamespace; | 22 import org.chromium.base.annotations.JNINamespace; |
20 import org.chromium.base.annotations.NativeClassQualifiedName; | 23 import org.chromium.base.annotations.NativeClassQualifiedName; |
21 | 24 |
22 import java.lang.reflect.InvocationTargetException; | 25 import java.lang.reflect.InvocationTargetException; |
23 import java.lang.reflect.Method; | 26 import java.lang.reflect.Method; |
24 | 27 |
25 /** | 28 /** |
26 * This class partners with native ProxyConfigServiceAndroid to listen for | 29 * This class partners with native ProxyConfigServiceAndroid to listen for |
27 * proxy change notifications from Android. | 30 * proxy change notifications from Android. |
28 */ | 31 */ |
29 @JNINamespace("net") | 32 @JNINamespace("net") |
30 public class ProxyChangeListener { | 33 public class ProxyChangeListener { |
31 private static final String TAG = "ProxyChangeListener"; | 34 private static final String TAG = "ProxyChangeListener"; |
32 private static boolean sEnabled = true; | 35 private static boolean sEnabled = true; |
33 | 36 |
| 37 private final Looper mLooper; |
| 38 private final Handler mHandler; |
| 39 |
34 private long mNativePtr; | 40 private long mNativePtr; |
35 private ProxyReceiver mProxyReceiver; | 41 private ProxyReceiver mProxyReceiver; |
36 private Delegate mDelegate; | 42 private Delegate mDelegate; |
37 | 43 |
38 private static class ProxyConfig { | 44 private static class ProxyConfig { |
39 public ProxyConfig(String host, int port, String pacUrl, String[] exclus
ionList) { | 45 public ProxyConfig(String host, int port, String pacUrl, String[] exclus
ionList) { |
40 mHost = host; | 46 mHost = host; |
41 mPort = port; | 47 mPort = port; |
42 mPacUrl = pacUrl; | 48 mPacUrl = pacUrl; |
43 mExclusionList = exclusionList; | 49 mExclusionList = exclusionList; |
44 } | 50 } |
45 public final String mHost; | 51 public final String mHost; |
46 public final int mPort; | 52 public final int mPort; |
47 public final String mPacUrl; | 53 public final String mPacUrl; |
48 public final String[] mExclusionList; | 54 public final String[] mExclusionList; |
49 } | 55 } |
50 | 56 |
51 /** | 57 /** |
52 * The delegate for ProxyChangeListener. Use for testing. | 58 * The delegate for ProxyChangeListener. Use for testing. |
53 */ | 59 */ |
54 public interface Delegate { | 60 public interface Delegate { |
55 public void proxySettingsChanged(); | 61 public void proxySettingsChanged(); |
56 } | 62 } |
57 | 63 |
58 private ProxyChangeListener() {} | 64 private ProxyChangeListener() { |
| 65 mLooper = Looper.myLooper(); |
| 66 mHandler = new Handler(mLooper); |
| 67 } |
59 | 68 |
60 public static void setEnabled(boolean enabled) { | 69 public static void setEnabled(boolean enabled) { |
61 sEnabled = enabled; | 70 sEnabled = enabled; |
62 } | 71 } |
63 | 72 |
64 public void setDelegateForTesting(Delegate delegate) { | 73 public void setDelegateForTesting(Delegate delegate) { |
65 mDelegate = delegate; | 74 mDelegate = delegate; |
66 } | 75 } |
67 | 76 |
68 @CalledByNative | 77 @CalledByNative |
69 public static ProxyChangeListener create() { | 78 public static ProxyChangeListener create() { |
70 return new ProxyChangeListener(); | 79 return new ProxyChangeListener(); |
71 } | 80 } |
72 | 81 |
73 @CalledByNative | 82 @CalledByNative |
74 public static String getProperty(String property) { | 83 public static String getProperty(String property) { |
75 return System.getProperty(property); | 84 return System.getProperty(property); |
76 } | 85 } |
77 | 86 |
78 @CalledByNative | 87 @CalledByNative |
79 public void start(long nativePtr) { | 88 public void start(long nativePtr) { |
| 89 assertOnThread(); |
80 assert mNativePtr == 0; | 90 assert mNativePtr == 0; |
81 mNativePtr = nativePtr; | 91 mNativePtr = nativePtr; |
82 registerReceiver(); | 92 registerReceiver(); |
83 } | 93 } |
84 | 94 |
85 @CalledByNative | 95 @CalledByNative |
86 public void stop() { | 96 public void stop() { |
| 97 assertOnThread(); |
87 mNativePtr = 0; | 98 mNativePtr = 0; |
88 unregisterReceiver(); | 99 unregisterReceiver(); |
89 } | 100 } |
90 | 101 |
91 private class ProxyReceiver extends BroadcastReceiver { | 102 private class ProxyReceiver extends BroadcastReceiver { |
92 @Override | 103 @Override |
93 public void onReceive(Context context, Intent intent) { | 104 public void onReceive(Context context, final Intent intent) { |
94 if (intent.getAction().equals(Proxy.PROXY_CHANGE_ACTION)) { | 105 if (intent.getAction().equals(Proxy.PROXY_CHANGE_ACTION)) { |
95 proxySettingsChanged(extractNewProxy(intent)); | 106 runOnThread(new Runnable() { |
| 107 @Override |
| 108 public void run() { |
| 109 proxySettingsChanged(ProxyReceiver.this, extractNewProxy
(intent)); |
| 110 } |
| 111 }); |
96 } | 112 } |
97 } | 113 } |
98 | 114 |
99 // Extract a ProxyConfig object from the supplied Intent's extra data | 115 // Extract a ProxyConfig object from the supplied Intent's extra data |
100 // bundle. The android.net.ProxyProperties class is not exported from | 116 // bundle. The android.net.ProxyProperties class is not exported from |
101 // the Android SDK, so we have to use reflection to get at it and invoke | 117 // the Android SDK, so we have to use reflection to get at it and invoke |
102 // methods on it. If we fail, return an empty proxy config (meaning | 118 // methods on it. If we fail, return an empty proxy config (meaning |
103 // 'direct'). | 119 // 'direct'). |
104 // TODO(sgurun): once android.net.ProxyInfo is public, rewrite this. | 120 // TODO(sgurun): once android.net.ProxyInfo is public, rewrite this. |
105 private ProxyConfig extractNewProxy(Intent intent) { | 121 private ProxyConfig extractNewProxy(Intent intent) { |
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
166 } catch (InvocationTargetException ex) { | 182 } catch (InvocationTargetException ex) { |
167 Log.e(TAG, "Using no proxy configuration due to exception:" + ex
); | 183 Log.e(TAG, "Using no proxy configuration due to exception:" + ex
); |
168 return null; | 184 return null; |
169 } catch (NullPointerException ex) { | 185 } catch (NullPointerException ex) { |
170 Log.e(TAG, "Using no proxy configuration due to exception:" + ex
); | 186 Log.e(TAG, "Using no proxy configuration due to exception:" + ex
); |
171 return null; | 187 return null; |
172 } | 188 } |
173 } | 189 } |
174 } | 190 } |
175 | 191 |
176 private void proxySettingsChanged(ProxyConfig cfg) { | 192 private void proxySettingsChanged(ProxyReceiver proxyReceiver, ProxyConfig c
fg) { |
177 if (!sEnabled) { | 193 if (!sEnabled |
| 194 // Once execution begins on the correct thread, make sure unregi
sterReceiver() |
| 195 // hasn't been called in the mean time. Ignore the changed signa
l if |
| 196 // unregisterReceiver() was called. |
| 197 || proxyReceiver != mProxyReceiver) { |
178 return; | 198 return; |
179 } | 199 } |
180 if (mDelegate != null) { | 200 if (mDelegate != null) { |
181 mDelegate.proxySettingsChanged(); | 201 mDelegate.proxySettingsChanged(); |
182 } | 202 } |
183 if (mNativePtr == 0) { | 203 if (mNativePtr == 0) { |
184 return; | 204 return; |
185 } | 205 } |
186 // Note that this code currently runs on a MESSAGE_LOOP_UI thread, but | 206 // Note that this code currently runs on a MESSAGE_LOOP_UI thread, but |
187 // the C++ code must run the callbacks on the network thread. | 207 // the C++ code must run the callbacks on the network thread. |
(...skipping 16 matching lines...) Expand all Loading... |
204 } | 224 } |
205 | 225 |
206 private void unregisterReceiver() { | 226 private void unregisterReceiver() { |
207 if (mProxyReceiver == null) { | 227 if (mProxyReceiver == null) { |
208 return; | 228 return; |
209 } | 229 } |
210 ContextUtils.getApplicationContext().unregisterReceiver(mProxyReceiver); | 230 ContextUtils.getApplicationContext().unregisterReceiver(mProxyReceiver); |
211 mProxyReceiver = null; | 231 mProxyReceiver = null; |
212 } | 232 } |
213 | 233 |
| 234 private boolean onThread() { |
| 235 return mLooper == Looper.myLooper(); |
| 236 } |
| 237 |
| 238 private void assertOnThread() { |
| 239 if (BuildConfig.DCHECK_IS_ON && !onThread()) { |
| 240 throw new IllegalStateException("Must be called on ProxyChangeListen
er thread."); |
| 241 } |
| 242 } |
| 243 |
| 244 private void runOnThread(Runnable r) { |
| 245 if (onThread()) { |
| 246 r.run(); |
| 247 } else { |
| 248 mHandler.post(r); |
| 249 } |
| 250 } |
| 251 |
214 /** | 252 /** |
215 * See net/proxy/proxy_config_service_android.cc | 253 * See net/proxy/proxy_config_service_android.cc |
216 */ | 254 */ |
217 @NativeClassQualifiedName("ProxyConfigServiceAndroid::JNIDelegate") | 255 @NativeClassQualifiedName("ProxyConfigServiceAndroid::JNIDelegate") |
218 private native void nativeProxySettingsChangedTo(long nativePtr, | 256 private native void nativeProxySettingsChangedTo(long nativePtr, |
219 String host, | 257 String host, |
220 int port, | 258 int port, |
221 String pacUrl, | 259 String pacUrl, |
222 String[] exclusionList); | 260 String[] exclusionList); |
223 @NativeClassQualifiedName("ProxyConfigServiceAndroid::JNIDelegate") | 261 @NativeClassQualifiedName("ProxyConfigServiceAndroid::JNIDelegate") |
224 private native void nativeProxySettingsChanged(long nativePtr); | 262 private native void nativeProxySettingsChanged(long nativePtr); |
225 } | 263 } |
OLD | NEW |