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

Side by Side Diff: src/org/adblockplus/android/ProxyService.java

Issue 4705284891082752: Proxy configurators (Closed)
Patch Set: Update 1 Created Aug. 19, 2014, 10:43 a.m.
Left:
Right:
Use n/p to move between diff chunks; N/P to move between comments.
Jump to:
View unified diff | Download patch
OLDNEW
1 /* 1 /*
2 * This file is part of Adblock Plus <http://adblockplus.org/>, 2 * This file is part of Adblock Plus <http://adblockplus.org/>,
3 * Copyright (C) 2006-2014 Eyeo GmbH 3 * Copyright (C) 2006-2014 Eyeo GmbH
4 * 4 *
5 * Adblock Plus is free software: you can redistribute it and/or modify 5 * Adblock Plus is free software: you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License version 3 as 6 * it under the terms of the GNU General Public License version 3 as
7 * published by the Free Software Foundation. 7 * published by the Free Software Foundation.
8 * 8 *
9 * Adblock Plus is distributed in the hope that it will be useful, 9 * Adblock Plus is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of 10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details. 12 * GNU General Public License for more details.
13 * 13 *
14 * You should have received a copy of the GNU General Public License 14 * You should have received a copy of the GNU General Public License
15 * along with Adblock Plus. If not, see <http://www.gnu.org/licenses/>. 15 * along with Adblock Plus. If not, see <http://www.gnu.org/licenses/>.
16 */ 16 */
17 17
18 package org.adblockplus.android; 18 package org.adblockplus.android;
19 19
20 import java.io.File;
21 import java.io.FileNotFoundException;
22 import java.io.IOException; 20 import java.io.IOException;
23 import java.lang.reflect.Method;
24 import java.net.InetAddress; 21 import java.net.InetAddress;
25 import java.net.ServerSocket; 22 import java.net.ServerSocket;
26 import java.util.List; 23 import java.net.UnknownHostException;
27 import java.util.Properties; 24 import java.util.Properties;
28 import java.util.concurrent.TimeoutException; 25
26 import org.adblockplus.android.configurators.ProxyConfigurator;
27 import org.adblockplus.android.configurators.ProxyConfigurators;
28 import org.adblockplus.android.configurators.ProxyRegistrationType;
29 import org.apache.commons.lang.StringUtils;
29 30
30 import sunlabs.brazil.server.Server; 31 import sunlabs.brazil.server.Server;
31 import sunlabs.brazil.util.Base64; 32 import sunlabs.brazil.util.Base64;
32 import android.annotation.SuppressLint; 33 import android.annotation.SuppressLint;
33 import android.app.Notification; 34 import android.app.Notification;
34 import android.app.NotificationManager; 35 import android.app.NotificationManager;
35 import android.app.PendingIntent; 36 import android.app.PendingIntent;
36 import android.app.Service; 37 import android.app.Service;
37 import android.content.BroadcastReceiver; 38 import android.content.BroadcastReceiver;
38 import android.content.Context; 39 import android.content.Context;
39 import android.content.Intent; 40 import android.content.Intent;
40 import android.content.IntentFilter; 41 import android.content.IntentFilter;
41 import android.content.SharedPreferences; 42 import android.content.SharedPreferences;
42 import android.content.SharedPreferences.OnSharedPreferenceChangeListener; 43 import android.content.SharedPreferences.OnSharedPreferenceChangeListener;
43 import android.content.pm.PackageManager.NameNotFoundException;
44 import android.content.res.Resources;
45 import android.net.ConnectivityManager;
46 import android.net.NetworkInfo;
47 import android.net.Proxy;
48 import android.os.Binder; 44 import android.os.Binder;
49 import android.os.Build; 45 import android.os.Build;
50 import android.os.Handler;
51 import android.os.IBinder; 46 import android.os.IBinder;
52 import android.os.StrictMode; 47 import android.os.StrictMode;
53 import android.preference.PreferenceManager; 48 import android.preference.PreferenceManager;
54 import android.support.v4.app.NotificationCompat; 49 import android.support.v4.app.NotificationCompat;
55 import android.util.Log; 50 import android.util.Log;
56 51
57 import com.stericson.RootTools.RootTools;
58 import com.stericson.RootTools.RootToolsException;
59
60 public class ProxyService extends Service implements OnSharedPreferenceChangeLis tener 52 public class ProxyService extends Service implements OnSharedPreferenceChangeLis tener
61 { 53 {
54 private static final String TAG = Utils.getTag(ProxyService.class);
55
62 private static final String LOCALHOST = "127.0.0.1"; 56 private static final String LOCALHOST = "127.0.0.1";
63 /**
64 * Indicates that system supports native proxy configuration.
65 */
66 public static final boolean NATIVE_PROXY_SUPPORTED = Build.VERSION.SDK_INT >= 12; // Honeycomb 3.1
67 57
68 static 58 private static final int[] PORT_VARIANTS = new int[] {-1, 2020, 3030, 4040, 50 50, 6060, 7070, 9090, 1234, 12345, 4321, 0};
69 {
70 RootTools.debugMode = false;
71 }
72 59
73 private static final String TAG = Utils.getTag(ProxyService.class); 60 // FIXME remove me
74 private static final boolean logRequests = false; 61 private static final boolean LOG_REQUESTS = false;
75
76 // Do not use 8080 because it is a "dirty" port, Android uses it if something goes wrong
77 // first element is reserved for previously used port
78 private static final int[] portVariants = new int[] {-1, 2020, 3030, 4040, 505 0, 6060, 7070, 9090, 1234, 12345, 4321, 0};
79
80 private static final int DEFAULT_TIMEOUT = 3000;
81 private static final int NO_TRAFFIC_TIMEOUT = 5 * 60 * 1000; // 5 minutes
82 62
83 static final int ONGOING_NOTIFICATION_ID = R.string.app_name; 63 static final int ONGOING_NOTIFICATION_ID = R.string.app_name;
64
84 private static final long POSITION_RIGHT = Build.VERSION.SDK_INT >= Build.VERS ION_CODES.GINGERBREAD ? Long.MIN_VALUE : Long.MAX_VALUE; 65 private static final long POSITION_RIGHT = Build.VERSION.SDK_INT >= Build.VERS ION_CODES.GINGERBREAD ? Long.MIN_VALUE : Long.MAX_VALUE;
85 private static final int NOTRAFFIC_NOTIFICATION_ID = R.string.app_name + 3;
86 66
87 /** 67 /**
88 * Broadcasted when service starts or stops. 68 * Broadcasted when service starts or stops.
89 */ 69 */
90 public static final String BROADCAST_STATE_CHANGED = "org.adblockplus.android. service.state"; 70 public static final String BROADCAST_STATE_CHANGED = "org.adblockplus.android. SERVICE_STATE_CHANGED";
71
91 /** 72 /**
92 * Broadcasted if proxy fails to start. 73 * Broadcasted if proxy fails to start.
93 */ 74 */
94 public static final String BROADCAST_PROXY_FAILED = "org.adblockplus.android.p roxy.failure"; 75 public static final String BROADCAST_PROXY_FAILED = "org.adblockplus.android.P ROXY_FAILURE";
95 76
96 private static final String IPTABLES_RETURN = " -t nat -m owner --uid-owner {{ UID}} -A OUTPUT -p tcp -j RETURN\n"; 77 /**
97 private static final String IPTABLES_ADD_HTTP = " -t nat -A OUTPUT -p tcp --dp ort 80 -j REDIRECT --to {{PORT}}\n"; 78 * Common command bridge
79 */
80 public static final String COMMAND_BRIDGE_ACTION = "org.adblockplus.android.CO MMAND_BRIDGE";
98 81
99 boolean hideIcon; 82 boolean hideIcon;
100 private Handler notrafficHandler;
101 83
102 protected ProxyServer proxy = null; 84 protected ProxyServer proxy = null;
85
103 protected int port; 86 protected int port;
87
104 private final Properties proxyConfiguration = new Properties(); 88 private final Properties proxyConfiguration = new Properties();
105 89
106 /** 90 private ProxyConfigurator proxyConfigurator = null;
107 * Indicates that service is working with root privileges.
108 */
109 private boolean transparent = false;
110 /**
111 * Indicates that service has autoconfigured Android proxy settings (version 3 .1+).
112 */
113 private boolean nativeProxyAutoConfigured = false;
114 /**
115 * Indicates that Android proxy settings are correctly configured (version 4.1 .2+ 4.2.2+).
116 */
117 private boolean proxyManualyConfigured = false;
118
119 private String iptables = null;
120 91
121 @SuppressLint("NewApi") 92 @SuppressLint("NewApi")
122 @Override 93 @Override
123 public void onCreate() 94 public void onCreate()
124 { 95 {
125 super.onCreate(); 96 super.onCreate();
126 97
127 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.GINGERBREAD) 98 // FIXME 'StrictMode' is API9
128 { 99 StrictMode.setThreadPolicy(new StrictMode.ThreadPolicy.Builder()
129 // Proxy is running in separate thread, it's just some resolution request during initialization. 100 .permitAll()
130 // Not worth spawning a separate thread for this. 101 .penaltyLog()
131 final StrictMode.ThreadPolicy policy = new StrictMode.ThreadPolicy.Builder ().permitNetwork().build(); 102 .build());
132 StrictMode.setThreadPolicy(policy);
133 }
134 103
135 // Get port for local proxy
136 final SharedPreferences prefs = PreferenceManager.getDefaultSharedPreference s(this); 104 final SharedPreferences prefs = PreferenceManager.getDefaultSharedPreference s(this);
137 final Resources resources = getResources();
138 105
139 // Try to read user proxy settings 106 // Try to read user proxy settings
140 String proxyHost = null; 107 String proxyHost = System.getProperty("http.proxyHost");;
141 String proxyPort = null; 108 String proxyPort = System.getProperty("http.proxyPort");
142 String proxyExcl = null; 109 final String proxyExcl = System.getProperty("http.nonProxyHosts");
143 String proxyUser = null; 110 String proxyUser = null;
144 String proxyPass = null; 111 String proxyPass = null;
145 112
146 if (NATIVE_PROXY_SUPPORTED) 113 if (proxyHost == null || proxyPort == null)
147 {
148 // Read system settings
149 proxyHost = System.getProperty("http.proxyHost");
150 proxyPort = System.getProperty("http.proxyPort");
151 proxyExcl = System.getProperty("http.nonProxyHosts");
152
153 Log.d(TAG, "PRX: " + proxyHost + ":" + proxyPort + "(" + proxyExcl + ")");
154 // not used but left for future reference
155 final String[] px = ProxySettings.getUserProxy(getApplicationContext());
156 if (px != null)
157 Log.d(TAG, "PRX: " + px[0] + ":" + px[1] + "(" + px[2] + ")");
158 }
159 else
160 { 114 {
161 // Read application settings 115 // Read application settings
162 proxyHost = prefs.getString(getString(R.string.pref_proxyhost), null); 116 proxyHost = prefs.getString(getString(R.string.pref_proxyhost), null);
163 proxyPort = prefs.getString(getString(R.string.pref_proxyport), null); 117 proxyPort = prefs.getString(getString(R.string.pref_proxyport), null);
164 proxyUser = prefs.getString(getString(R.string.pref_proxyuser), null); 118 proxyUser = prefs.getString(getString(R.string.pref_proxyuser), null);
165 proxyPass = prefs.getString(getString(R.string.pref_proxypass), null); 119 proxyPass = prefs.getString(getString(R.string.pref_proxypass), null);
166 } 120 }
167 121
168 // Check for root privileges and try to install transparent proxy 122 registerReceiver(this.proxyReceiver, new IntentFilter(ProxyService.BROADCAST _PROXY_FAILED));
169 if (RootTools.isAccessGiven()) 123 registerReceiver(this.commandBridge, new IntentFilter(ProxyService.COMMAND_B RIDGE_ACTION));
124
125 final InetAddress inetAddress;
126 try
170 { 127 {
171 try 128 inetAddress = InetAddress.getByName(LOCALHOST);
172 {
173 initIptables();
174
175 final StringBuffer cmd = new StringBuffer();
176 final int uid = getPackageManager().getPackageInfo(getPackageName(), 0). applicationInfo.uid;
177 cmd.append(iptables);
178 cmd.append(IPTABLES_RETURN.replace("{{UID}}", String.valueOf(uid)));
179 final String rules = cmd.toString();
180 RootTools.sendShell(rules, DEFAULT_TIMEOUT);
181 transparent = true;
182 }
183 catch (final FileNotFoundException e)
184 {
185 // ignore - this is "normal" case
186 }
187 catch (final NameNotFoundException e)
188 {
189 Log.e(TAG, "Failed to initialize iptables", e);
190 }
191 catch (final IOException e)
192 {
193 Log.e(TAG, "Failed to initialize iptables", e);
194 }
195 catch (final RootToolsException e)
196 {
197 Log.e(TAG, "Failed to initialize iptables", e);
198 }
199 catch (final TimeoutException e)
200 {
201 Log.e(TAG, "Failed to initialize iptables", e);
202 }
203 } 129 }
204 130 catch (final UnknownHostException e)
205 if (!transparent)
206 { 131 {
207 // Try to set native proxy 132 sendBroadcast(new Intent(BROADCAST_PROXY_FAILED)
208 nativeProxyAutoConfigured = ProxySettings.setConnectionProxy(getApplicatio nContext(), LOCALHOST, port, ""); 133 .putExtra("msg", "Could not resolve 'localhost'"));
209 134 return;
210 if (NATIVE_PROXY_SUPPORTED)
211 {
212 registerReceiver(connectionReceiver, new IntentFilter(ConnectivityManage r.CONNECTIVITY_ACTION));
213 registerReceiver(connectionReceiver, new IntentFilter(Proxy.PROXY_CHANGE _ACTION));
214 }
215 } 135 }
216 136
217 // Save current native proxy situation. The service is always started on the first run so
218 // we will always have a correct value from the box
219 final SharedPreferences.Editor editor = prefs.edit();
220 editor.putBoolean(getString(R.string.pref_proxyautoconfigured), transparent || nativeProxyAutoConfigured);
221 editor.commit();
222
223 registerReceiver(proxyReceiver, new IntentFilter(ProxyService.BROADCAST_PROX Y_FAILED));
224 registerReceiver(filterReceiver, new IntentFilter(AdblockPlus.BROADCAST_FILT ERING_CHANGE));
225 registerReceiver(filterReceiver, new IntentFilter(AdblockPlus.BROADCAST_FILT ER_MATCHES));
226
227 // Start proxy 137 // Start proxy
228 if (proxy == null) 138 if (proxy == null)
229 { 139 {
230 // Select available port and bind to it, use previously selected port by d efault 140 // Select available port and bind to it, use previously selected port by d efault
231 portVariants[0] = prefs.getInt(getString(R.string.pref_lastport), -1);
232 ServerSocket listen = null; 141 ServerSocket listen = null;
233 String msg = null; 142 String msg = null;
234 for (final int p : portVariants) 143 for (final int p : PORT_VARIANTS)
235 { 144 {
236 if (p < 0) 145 final int toCheck = (p == -1) ? prefs.getInt(getString(R.string.pref_las tport), -1) : p;
237 continue; 146
238 try 147 if (toCheck >= 0)
239 { 148 {
240 // Fix for #232, bind proxy socket to loopback only 149 try
241 listen = new ServerSocket(p, 1024, InetAddress.getByName(LOCALHOST)); 150 {
242 port = p; 151 // Fix for #232, bind proxy socket to loopback only
243 break; 152 listen = new ServerSocket(toCheck, 1024, inetAddress);
244 } 153 this.port = listen.getLocalPort();
245 catch (final IOException e) 154 break;
246 { 155 }
247 Log.e(TAG, null, e); 156 catch (final IOException e)
248 msg = e.getMessage(); 157 {
158 Log.e(TAG, null, e);
159 msg = e.getMessage();
160 }
249 } 161 }
250 } 162 }
163
251 if (listen == null) 164 if (listen == null)
252 { 165 {
253 sendBroadcast(new Intent(BROADCAST_PROXY_FAILED).putExtra("msg", msg)); 166 sendBroadcast(new Intent(BROADCAST_PROXY_FAILED).putExtra("msg", msg));
254 return; 167 return;
255 } 168 }
256 169
170 this.proxyConfigurator = ProxyConfigurators.registerProxy(this, inetAddres s, this.port);
171
172 if (this.proxyConfigurator == null)
173 {
174 sendBroadcast(new Intent(BROADCAST_PROXY_FAILED)
175 .putExtra("msg", "Failed to register proxy"));
176 return;
177 }
178
257 // Save selected port 179 // Save selected port
180 final SharedPreferences.Editor editor = prefs.edit();
181 editor.putBoolean(getString(R.string.pref_proxyautoconfigured), this.getPr oxyRegistrationType().isAutoConfigured());
258 editor.putInt(getString(R.string.pref_lastport), port); 182 editor.putInt(getString(R.string.pref_lastport), port);
259 editor.commit(); 183 editor.commit();
260 184
261 // Initialize proxy 185 // Initialize proxy
262 proxyConfiguration.put("handler", "main"); 186 proxyConfiguration.put("handler", "main");
263 proxyConfiguration.put("main.prefix", ""); 187 proxyConfiguration.put("main.prefix", "");
264 proxyConfiguration.put("main.class", "sunlabs.brazil.server.ChainHandler") ; 188 proxyConfiguration.put("main.class", "sunlabs.brazil.server.ChainHandler") ;
265 if (transparent) 189 switch (this.getProxyRegistrationType().getProxyType())
266 { 190 {
191 case HTTP:
267 proxyConfiguration.put("main.handlers", "urlmodifier adblock"); 192 proxyConfiguration.put("main.handlers", "urlmodifier adblock");
268 proxyConfiguration.put("urlmodifier.class", "org.adblockplus.brazil.Tran sparentProxyHandler"); 193 proxyConfiguration.put("urlmodifier.class", "org.adblockplus.brazil.Tran sparentProxyHandler");
269 } 194 break;
270 else 195 case HTTPS:
271 {
272 proxyConfiguration.put("main.handlers", "https adblock"); 196 proxyConfiguration.put("main.handlers", "https adblock");
273 proxyConfiguration.put("https.class", "org.adblockplus.brazil.SSLConnect ionHandler"); 197 proxyConfiguration.put("https.class", "org.adblockplus.brazil.SSLConnect ionHandler");
198 break;
199 default:
200 sendBroadcast(new Intent(BROADCAST_PROXY_FAILED)
201 .putExtra("msg", "Unsupported proxy server type: " + this.getProxyRe gistrationType().getProxyType()));
202 return;
274 } 203 }
275 proxyConfiguration.put("adblock.class", "org.adblockplus.brazil.RequestHan dler"); 204 proxyConfiguration.put("adblock.class", "org.adblockplus.brazil.RequestHan dler");
276 if (logRequests) 205 if (LOG_REQUESTS)
277 proxyConfiguration.put("adblock.proxylog", "yes"); 206 proxyConfiguration.put("adblock.proxylog", "yes");
278 207
279 configureUserProxy(proxyConfiguration, proxyHost, proxyPort, proxyExcl, pr oxyUser, proxyPass); 208 configureUserProxy(proxyConfiguration, proxyHost, proxyPort, proxyExcl, pr oxyUser, proxyPass);
280 209
281 proxy = new ProxyServer(); 210 proxy = new ProxyServer();
282 proxy.logLevel = Server.LOG_DIAGNOSTIC; 211 proxy.logLevel = Server.LOG_LOG;
283 proxy.setup(listen, proxyConfiguration.getProperty("handler"), proxyConfig uration); 212 proxy.setup(listen, proxyConfiguration.getProperty("handler"), proxyConfig uration);
284 proxy.start(); 213 proxy.start();
285 } 214 }
286 215
287 if (transparent)
288 {
289 // Redirect traffic via iptables
290 try
291 {
292 final StringBuffer cmd = new StringBuffer();
293 cmd.append(iptables);
294 cmd.append(IPTABLES_ADD_HTTP.replace("{{PORT}}", String.valueOf(port)));
295 final String rules = cmd.toString();
296 RootTools.sendShell(rules, DEFAULT_TIMEOUT);
297 }
298 catch (final FileNotFoundException e)
299 {
300 // ignore - this is "normal" case
301 }
302 catch (final IOException e)
303 {
304 Log.e(TAG, "Failed to initialize iptables", e);
305 }
306 catch (final RootToolsException e)
307 {
308 Log.e(TAG, "Failed to initialize iptables", e);
309 }
310 catch (final TimeoutException e)
311 {
312 Log.e(TAG, "Failed to initialize iptables", e);
313 }
314 }
315
316 prefs.registerOnSharedPreferenceChangeListener(this); 216 prefs.registerOnSharedPreferenceChangeListener(this);
317 217
318 // Lock service 218 // Lock service
319 hideIcon = prefs.getBoolean(getString(R.string.pref_hideicon), resources.get Boolean(R.bool.def_hideicon)); 219 hideIcon = prefs.getBoolean(getString(R.string.pref_hideicon), getResources( ).getBoolean(R.bool.def_hideicon));
320 startForeground(ONGOING_NOTIFICATION_ID, getNotification()); 220 startForeground(ONGOING_NOTIFICATION_ID, getNotification());
321 221
322 // If automatic setting of proxy was blocked, check if user has set it manua lly
323 final boolean manual = isManual();
324 if (manual && NATIVE_PROXY_SUPPORTED)
325 {
326 final ConnectivityManager connectivityManager = (ConnectivityManager) getS ystemService(Context.CONNECTIVITY_SERVICE);
327 updateNoTrafficCheck(connectivityManager);
328 }
329
330 sendStateChangedBroadcast(); 222 sendStateChangedBroadcast();
331 Log.i(TAG, "Service started"); 223 Log.i(TAG, "Service started");
332 } 224 }
333 225
334 @Override 226 @Override
335 public int onStartCommand(final Intent intent, final int flags, final int star tId) 227 public int onStartCommand(final Intent intent, final int flags, final int star tId)
336 { 228 {
337 return START_STICKY; 229 return START_STICKY;
338 } 230 }
339 231
340 @Override 232 @Override
341 public void onDestroy() 233 public void onDestroy()
342 { 234 {
343 super.onDestroy(); 235 super.onDestroy();
344 236
345 stopNoTrafficCheck(); 237 unregisterReceiver(this.proxyReceiver);
238 unregisterReceiver(this.commandBridge);
346 239
347 unregisterReceiver(filterReceiver); 240 if (this.proxyConfigurator != null)
348 unregisterReceiver(proxyReceiver);
349
350 // Stop IP redirecting
351 if (transparent)
352 { 241 {
353 new Thread() 242 this.proxyConfigurator.unregisterProxy();
354 { 243 this.proxyConfigurator.shutdown();
355 @Override
356 public void run()
357 {
358 try
359 {
360 RootTools.sendShell(iptables + " -t nat -F OUTPUT", DEFAULT_TIMEOUT) ;
361 }
362 catch (final Exception e)
363 {
364 Log.e(TAG, "Failed to clear iptables", e);
365 }
366 }
367 }.start();
368 }
369
370 if (!transparent && NATIVE_PROXY_SUPPORTED)
371 unregisterReceiver(connectionReceiver);
372
373 // Clear native proxy
374 if (nativeProxyAutoConfigured)
375 {
376 clearConnectionProxy();
377 } 244 }
378 245
379 sendBroadcast(new Intent(BROADCAST_STATE_CHANGED).putExtra("enabled", false) ); 246 sendBroadcast(new Intent(BROADCAST_STATE_CHANGED).putExtra("enabled", false) );
380 247
381 // Stop proxy server 248 // Stop proxy server
382 if (proxy != null) 249 if (proxy != null)
250 {
383 proxy.close(); 251 proxy.close();
252 proxy = null;
253 }
384 254
385 // Release service lock 255 // Release service lock
386 stopForeground(true); 256 stopForeground(true);
387 257
388 Log.i(TAG, "Service stopped"); 258 Log.i(TAG, "Service stopped");
389 } 259 }
390 260
391 /** 261 /**
392 * Restores system proxy settings via native call on Android 3.1+ devices
393 * using Java reflection.
394 */
395 private void clearConnectionProxy()
396 {
397 final String proxyHost = proxyConfiguration.getProperty("adblock.proxyHost") ;
398 final String proxyPort = proxyConfiguration.getProperty("adblock.proxyPort") ;
399 final String proxyExcl = proxyConfiguration.getProperty("adblock.proxyExcl") ;
400 int port = 0;
401 try
402 {
403 if (proxyHost != null)
404 port = Integer.valueOf(proxyPort);
405 }
406 catch (final NumberFormatException e)
407 {
408 Log.e(TAG, "Bad port setting", e);
409 }
410 ProxySettings.setConnectionProxy(getApplicationContext(), proxyHost, port, p roxyExcl);
411 }
412
413 /**
414 * Sets user proxy settings in proxy service properties. 262 * Sets user proxy settings in proxy service properties.
415 */ 263 */
416 private void configureUserProxy(final Properties config, final String proxyHos t, final String proxyPort, final String proxyExcl, final String proxyUser, final String proxyPass) 264 private void configureUserProxy(final Properties config, final String proxyHos t, final String proxyPort, final String proxyExcl,
265 final String proxyUser, final String proxyPass)
417 { 266 {
418 // Clean previous settings 267 // Clean previous settings
419 config.remove("adblock.proxyHost"); 268 config.remove("adblock.proxyHost");
420 config.remove("adblock.proxyPort"); 269 config.remove("adblock.proxyPort");
421 config.remove("adblock.auth"); 270 config.remove("adblock.auth");
422 config.remove("adblock.proxyExcl"); 271 config.remove("adblock.proxyExcl");
423 if (!transparent) 272 config.remove("https.proxyHost");
273 config.remove("https.proxyPort");
274 config.remove("https.auth");
275
276 final ProxyRegistrationType regType = this.getProxyRegistrationType();
277 if (regType == ProxyRegistrationType.NATIVE)
424 { 278 {
425 config.remove("https.proxyHost"); 279 passProxySettings(proxyHost, proxyPort, proxyExcl);
426 config.remove("https.proxyPort");
427 config.remove("https.auth");
428 } 280 }
429 281
430 if (nativeProxyAutoConfigured)
431 passProxySettings(proxyHost, proxyPort, proxyExcl);
432
433 // Check if there are any settings 282 // Check if there are any settings
434 if (proxyHost == null || "".equals(proxyHost)) 283 if (StringUtils.isEmpty(proxyHost))
284 {
435 return; 285 return;
286 }
436 287
437 // Check for dirty proxy settings - this indicated previous crash: 288 // Check for dirty proxy settings - this indicated previous crash:
438 // proxy points to ourselves 289 // proxy points to ourselves
439 // proxy port is null, 0 or not a number 290 // proxy port is null, 0 or not a number
440 // proxy is 127.0.0.1:8080 291 // proxy is 127.0.0.1:8080
441 if (proxyPort == null) 292 if (proxyPort == null)
293 {
442 return; 294 return;
443 int p = 0; 295 }
296
297 final int p;
444 try 298 try
445 { 299 {
446 p = Integer.valueOf(proxyPort); 300 p = Integer.valueOf(proxyPort);
447 } 301 }
448 catch (final NumberFormatException e) 302 catch (final NumberFormatException e)
449 { 303 {
450 return; 304 return;
451 } 305 }
452 if (p == 0 || isLocalHost(proxyHost) && (p == port || p == 8080)) 306
307 if (p == 0 || isLocalhost(proxyHost) && (p == port || p == 8080))
453 { 308 {
454 if (nativeProxyAutoConfigured) 309 if (regType == ProxyRegistrationType.NATIVE)
310 {
455 passProxySettings(null, null, null); 311 passProxySettings(null, null, null);
312 }
456 return; 313 return;
457 } 314 }
458 315
459 config.put("adblock.proxyHost", proxyHost); 316 config.put("adblock.proxyHost", proxyHost);
460 config.put("adblock.proxyPort", proxyPort); 317 config.put("adblock.proxyPort", proxyPort);
461 if (!transparent) 318 if (regType.getProxyType() == ProxyServerType.HTTPS)
462 { 319 {
463 config.put("https.proxyHost", proxyHost); 320 config.put("https.proxyHost", proxyHost);
464 config.put("https.proxyPort", proxyPort); 321 config.put("https.proxyPort", proxyPort);
465 } 322 }
466 323
467 // TODO Not implemented in our proxy but needed to restore settings 324 // TODO Not implemented in our proxy but needed to restore settings
468 if (proxyExcl != null) 325 if (proxyExcl != null)
326 {
469 config.put("adblock.proxyExcl", proxyExcl); 327 config.put("adblock.proxyExcl", proxyExcl);
328 }
470 329
471 if (proxyUser != null && !"".equals(proxyUser) && proxyPass != null && !"".e quals(proxyPass)) 330 if (StringUtils.isNotEmpty(proxyUser) && StringUtils.isNotEmpty(proxyPass))
472 { 331 {
473 // Base64 encode user:password 332 // Base64 encode user:password
474 final String proxyAuth = "Basic " + new String(Base64.encode(proxyUser + " :" + proxyPass)); 333 final String proxyAuth = "Basic " + new String(Base64.encode(proxyUser + " :" + proxyPass));
475 config.put("adblock.auth", proxyAuth); 334 config.put("adblock.auth", proxyAuth);
476 if (!transparent) 335 if (regType.getProxyType() == ProxyServerType.HTTPS)
336 {
477 config.put("https.auth", proxyAuth); 337 config.put("https.auth", proxyAuth);
338 }
478 } 339 }
479 } 340 }
480 341
342 /**
343 * Lean method to send a {@link BridgeCommand} without additional extras.
344 *
345 * @param context
346 * the context to use for sending the broadcast
347 * @param command
348 * the command
349 */
350 public static void sendBridgeCommand(final Context context, final BridgeComman d command)
351 {
352 context.sendBroadcast(
353 new Intent(COMMAND_BRIDGE_ACTION)
354 .putExtra("command", command.toString()));
355 }
356
357 /**
358 * @return {@code true} if the given host string resolves to {@code localhost}
359 */
360 public static boolean isLocalhost(final String host)
361 {
362 try
363 {
364 if (StringUtils.isEmpty(host))
365 {
366 return false;
367 }
368
369 if (host.equals("127.0.0.1") || host.equalsIgnoreCase("localhost"))
370 {
371 return true;
372 }
373
374 return InetAddress.getByName(host).isLoopbackAddress();
375 }
376 catch (final Exception e)
377 {
378 return false;
379 }
380 }
381
481 private void passProxySettings(final String proxyHost, final String proxyPort, final String proxyExcl) 382 private void passProxySettings(final String proxyHost, final String proxyPort, final String proxyExcl)
482 { 383 {
483 try 384 try
484 { 385 {
485 final CrashHandler handler = (CrashHandler) Thread.getDefaultUncaughtExcep tionHandler(); 386 final CrashHandler handler = (CrashHandler) Thread.getDefaultUncaughtExcep tionHandler();
486 handler.saveProxySettings(proxyHost, proxyPort, proxyExcl); 387 handler.saveProxySettings(proxyHost, proxyPort, proxyExcl);
487 } 388 }
488 catch (final ClassCastException e) 389 catch (final ClassCastException e)
489 { 390 {
490 // ignore - default handler in use 391 // ignore - default handler in use
491 } 392 }
492 } 393 }
493 394
494 @Override 395 @Override
495 public void onSharedPreferenceChanged(final SharedPreferences sharedPreference s, final String key) 396 public void onSharedPreferenceChanged(final SharedPreferences sharedPreference s, final String key)
496 { 397 {
497 if (!NATIVE_PROXY_SUPPORTED) 398 // TODO verify this
399 if (this.getProxyRegistrationType() != ProxyRegistrationType.NATIVE)
498 { 400 {
499 final String ketHost = getString(R.string.pref_proxyhost); 401 final String keyHost = getString(R.string.pref_proxyhost);
500 final String keyPort = getString(R.string.pref_proxyport); 402 final String keyPort = getString(R.string.pref_proxyport);
501 final String keyUser = getString(R.string.pref_proxyuser); 403 final String keyUser = getString(R.string.pref_proxyuser);
502 final String keyPass = getString(R.string.pref_proxypass); 404 final String keyPass = getString(R.string.pref_proxypass);
503 if (key.equals(ketHost) || key.equals(keyPort) || key.equals(keyUser) || k ey.equals(keyPass)) 405 if (key.equals(keyHost) || key.equals(keyPort) || key.equals(keyUser) || k ey.equals(keyPass))
504 { 406 {
505 final String proxyHost = sharedPreferences.getString(ketHost, null); 407 final String proxyHost = sharedPreferences.getString(keyHost, null);
506 final String proxyPort = sharedPreferences.getString(keyPort, null); 408 final String proxyPort = sharedPreferences.getString(keyPort, null);
507 final String proxyUser = sharedPreferences.getString(keyUser, null); 409 final String proxyUser = sharedPreferences.getString(keyUser, null);
508 final String proxyPass = sharedPreferences.getString(keyPass, null); 410 final String proxyPass = sharedPreferences.getString(keyPass, null);
509 if (proxy != null) 411 if (proxy != null)
510 { 412 {
511 configureUserProxy(proxyConfiguration, proxyHost, proxyPort, null, pro xyUser, proxyPass); 413 configureUserProxy(proxyConfiguration, proxyHost, proxyPort, null, pro xyUser, proxyPass);
512 proxy.restart(proxyConfiguration.getProperty("handler")); 414 proxy.restart(proxyConfiguration.getProperty("handler"));
513 } 415 }
514 } 416 }
515 } 417 }
516 } 418 }
517 419
518 public boolean isTransparent()
519 {
520 return transparent;
521 }
522
523 public boolean isNativeProxyAutoConfigured()
524 {
525 return nativeProxyAutoConfigured;
526 }
527
528 /**
529 * Checks if user has to set proxy settings manually
530 */
531 public boolean isManual()
532 {
533 return !transparent && !nativeProxyAutoConfigured;
534 }
535
536 /**
537 * Checks whether traffic check is pending
538 */
539 public boolean noTraffic()
540 {
541 return notrafficHandler != null;
542 }
543
544 /**
545 * Checks if specified host is local.
546 */
547 private static final boolean isLocalHost(final String host)
548 {
549 if (host == null)
550 return false;
551
552 try
553 {
554 if (host.equalsIgnoreCase("localhost"))
555 return true;
556
557 final String className = "android.net.NetworkUtils";
558 final Class<?> c = Class.forName(className);
559 /*
560 * InetAddress address = NetworkUtils.numericToInetAddress(host);
561 */
562 final Method method = c.getMethod("numericToInetAddress", String.class);
563 final InetAddress address = (InetAddress) method.invoke(null, host);
564
565 if (address.isLoopbackAddress())
566 return true;
567 }
568 catch (final Exception e)
569 {
570 Log.w(TAG, null, e);
571 }
572 return false;
573 }
574
575 /**
576 * Initializes iptables executable.
577 *
578 * @throws FileNotFoundException
579 * If iptables initialization failed due to provided reasons.
580 */
581 private void initIptables() throws IOException, RootToolsException, TimeoutExc eption, FileNotFoundException
582 {
583 if (!RootTools.isAccessGiven())
584 throw new FileNotFoundException("No root access");
585
586 final File ipt = getFileStreamPath("iptables");
587
588 if (!ipt.exists())
589 {
590 Log.e(TAG, "No iptables excutable found");
591 throw new FileNotFoundException("No iptables executable");
592 }
593
594 final String path = ipt.getAbsolutePath();
595
596 RootTools.sendShell("chmod 700 " + path, DEFAULT_TIMEOUT);
597
598 boolean compatible = false;
599 boolean version = false;
600
601 final String command = path + " --version\n" + path + " -L -t nat -n\n";
602
603 final List<String> result = RootTools.sendShell(command, DEFAULT_TIMEOUT);
604 for (final String line : result)
605 {
606 if (line.contains("OUTPUT"))
607 compatible = true;
608 if (line.contains("v1.4."))
609 version = true;
610 }
611
612 if (!compatible || !version)
613 {
614 Log.e(TAG, "Incompatible iptables excutable");
615 throw new FileNotFoundException("Incompatible iptables excutable");
616 }
617
618 iptables = path;
619 }
620
621 public List<String> getIptablesOutput()
622 {
623 if (iptables == null)
624 return null;
625
626 final String command = iptables + " -L -t nat -n\n";
627 try
628 {
629 return RootTools.sendShell(command, DEFAULT_TIMEOUT);
630 }
631 catch (final Exception e)
632 {
633 Log.e(TAG, "Failed to get iptables configuration", e);
634 return null;
635 }
636 }
637
638 /** 420 /**
639 * Raises or removes no traffic notification based on current link proxy 421 * @return the active proxy configuration's type or {@link ProxyRegistrationTy pe#UNKNOWN} if none is configured
640 * settings
641 */ 422 */
642 private void updateNoTrafficCheck(final ConnectivityManager connectivityManage r) 423 public ProxyRegistrationType getProxyRegistrationType()
643 { 424 {
644 try 425 return this.proxyConfigurator != null ? this.proxyConfigurator.getType() : P roxyRegistrationType.UNKNOWN;
645 {
646 final Object pp = ProxySettings.getActiveLinkProxy(connectivityManager);
647 final String[] userProxy = ProxySettings.getUserProxy(pp);
648 if (userProxy != null)
649 Log.i(TAG, "Proxy settings: " + userProxy[0] + ":" + userProxy[1] + "(" + userProxy[2] + ")");
650 updateNoTrafficCheck(userProxy);
651 }
652 catch (final Exception e)
653 {
654 // This should not happen
655 Log.e(TAG, null, e);
656 }
657 } 426 }
658 427
659 /** 428 /**
660 * Raises or removes no traffic notification based on the user proxy settings 429 * @return {@code true} if there is a valid proxy configurator and registratio n succeeded
661 */ 430 */
662 private void updateNoTrafficCheck(final String[] userProxy) 431 public boolean isRegistered()
663 { 432 {
664 final boolean ourProxy = userProxy != null && isLocalHost(userProxy[0]) && I nteger.valueOf(userProxy[1]) == port; 433 return this.proxyConfigurator != null && this.proxyConfigurator.isRegistered ();
665 if (ourProxy != proxyManualyConfigured)
666 {
667 proxyManualyConfigured = ourProxy;
668 sendStateChangedBroadcast();
669 }
670 if (ourProxy)
671 {
672 stopNoTrafficCheck();
673 }
674 else
675 {
676 // Initiate no traffic check
677 notrafficHandler = new Handler();
678 notrafficHandler.postDelayed(noTraffic, NO_TRAFFIC_TIMEOUT);
679 }
680 final NotificationManager notificationManager = (NotificationManager) getSys temService(NOTIFICATION_SERVICE);
681 notificationManager.notify(ONGOING_NOTIFICATION_ID, getNotification());
682 } 434 }
683 435
684 /** 436 /**
685 * Stops no traffic check and resets notification message. 437 * @return {@code true} if registration type is {@link ProxyRegistrationType#N ATIVE} and registration succeeded
686 */ 438 */
687 private void stopNoTrafficCheck() 439 public boolean isNativeProxyAutoConfigured()
688 { 440 {
689 if (notrafficHandler != null) 441 return this.getProxyRegistrationType() == ProxyRegistrationType.NATIVE && th is.isRegistered();
690 { 442 }
691 notrafficHandler.removeCallbacks(noTraffic); 443
692 sendStateChangedBroadcast(); 444 /**
693 final NotificationManager notificationManager = (NotificationManager) getS ystemService(NOTIFICATION_SERVICE); 445 * @return {@code true} if registration type is {@link ProxyRegistrationType#M ANUAL}
694 notificationManager.notify(ONGOING_NOTIFICATION_ID, getNotification()); 446 */
695 notificationManager.cancel(NOTRAFFIC_NOTIFICATION_ID); 447 public boolean isManual()
696 } 448 {
697 notrafficHandler = null; 449 return this.getProxyRegistrationType() == ProxyRegistrationType.MANUAL;
698 } 450 }
699 451
700 @SuppressLint("NewApi") 452 @SuppressLint("NewApi")
701 private Notification getNotification() 453 private Notification getNotification()
702 { 454 {
703 final boolean filtering = AdblockPlus.getApplication().isFilteringEnabled(); 455 final boolean filtering = AdblockPlus.getApplication().isFilteringEnabled();
704 456
705 int msgId = R.string.notif_waiting; 457 final int msgId;
706 if (nativeProxyAutoConfigured || proxyManualyConfigured) 458 switch(this.getProxyRegistrationType())
459 {
460 case MANUAL:
461 if (this.isRegistered())
462 {
463 msgId = filtering ? R.string.notif_wifi : R.string.notif_wifi_nofilterin g;
464 }
465 else
466 {
467 msgId = filtering ? R.string.notif_waiting : R.string.notif_wifi_nofilte ring;
468 }
469 break;
470 case NATIVE:
707 msgId = filtering ? R.string.notif_wifi : R.string.notif_wifi_nofiltering; 471 msgId = filtering ? R.string.notif_wifi : R.string.notif_wifi_nofiltering;
708 if (transparent) 472 break;
473 case IPTABLES:
474 case CYANOGENMOD:
709 msgId = R.string.notif_all; 475 msgId = R.string.notif_all;
476 break;
477 default:
478 msgId = R.string.notif_waiting;
479 break;
480 }
710 481
711 final NotificationCompat.Builder builder = new NotificationCompat.Builder(th is); 482 final NotificationCompat.Builder builder = new NotificationCompat.Builder(th is);
712 if (hideIcon && msgId != R.string.notif_waiting) 483 if (hideIcon && msgId != R.string.notif_waiting)
713 { 484 {
714 builder.setWhen(POSITION_RIGHT); 485 builder.setWhen(POSITION_RIGHT);
715 builder.setSmallIcon(R.drawable.transparent); 486 builder.setSmallIcon(R.drawable.transparent);
716 // builder.setContent(new RemoteViews(getPackageName(), R.layout.notif_hid den));
717 } 487 }
718 else 488 else
719 { 489 {
720 builder.setWhen(0); 490 builder.setWhen(0);
721 builder.setSmallIcon(R.drawable.ic_stat_blocking); 491 builder.setSmallIcon(R.drawable.ic_stat_blocking);
722 } 492 }
723 final PendingIntent contentIntent = PendingIntent.getActivity(this, 0, new I ntent(this, Preferences.class).addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent. FLAG_ACTIVITY_NEW_TASK), 0); 493 final PendingIntent contentIntent = PendingIntent.getActivity(this, 0,
494 new Intent(this, Preferences.class).addFlags(Intent.FLAG_ACTIVITY_CLEAR_ TOP | Intent.FLAG_ACTIVITY_NEW_TASK), 0);
495
724 builder.setContentIntent(contentIntent); 496 builder.setContentIntent(contentIntent);
725 builder.setContentTitle(getText(R.string.app_name)); 497 builder.setContentTitle(getText(R.string.app_name));
726 builder.setContentText(getString(msgId, port)); 498 builder.setContentText(getString(msgId, port));
727 builder.setOngoing(true); 499 builder.setOngoing(true);
728 500
729 final Notification notification = builder.getNotification(); 501 return builder.getNotification();
730 return notification;
731 } 502 }
732 503
733 public void setEmptyIcon(final boolean hide) 504 public void setEmptyIcon(final boolean hide)
734 { 505 {
735 hideIcon = hide; 506 hideIcon = hide;
736 final NotificationManager notificationManager = (NotificationManager) getSys temService(NOTIFICATION_SERVICE); 507 final NotificationManager notificationManager = (NotificationManager) getSys temService(NOTIFICATION_SERVICE);
737 notificationManager.notify(ONGOING_NOTIFICATION_ID, getNotification()); 508 notificationManager.notify(ONGOING_NOTIFICATION_ID, getNotification());
738 } 509 }
739 510
740 public void sendStateChangedBroadcast() 511 public void sendStateChangedBroadcast()
741 { 512 {
742 Log.i(TAG, "Broadcasting " + BROADCAST_STATE_CHANGED);
743 final boolean manual = isManual(); 513 final boolean manual = isManual();
744 final Intent stateIntent = new Intent(BROADCAST_STATE_CHANGED).putExtra("ena bled", true).putExtra("port", port).putExtra("manual", manual); 514 final Intent stateIntent = new Intent(BROADCAST_STATE_CHANGED)
515 .putExtra("enabled", true)
516 .putExtra("port", port)
517 .putExtra("manual", manual);
518
745 if (manual) 519 if (manual)
746 stateIntent.putExtra("configured", proxyManualyConfigured); 520 {
521 stateIntent.putExtra("configured", this.isRegistered());
522 }
523
747 sendBroadcast(stateIntent); 524 sendBroadcast(stateIntent);
748 } 525 }
749 526
750 private final IBinder binder = new LocalBinder(); 527 private final IBinder binder = new LocalBinder();
751 528
752 public final class LocalBinder extends Binder 529 public final class LocalBinder extends Binder
753 { 530 {
754 public ProxyService getService() 531 public ProxyService getService()
755 { 532 {
756 return ProxyService.this; 533 return ProxyService.this;
757 } 534 }
758 } 535 }
759 536
760 @Override 537 @Override
761 public IBinder onBind(final Intent intent) 538 public IBinder onBind(final Intent intent)
762 { 539 {
763 return binder; 540 return binder;
764 } 541 }
765 542
766 /** 543 /**
767 * Executed if no traffic is detected after a period of time. Notifies user
768 * about possible configuration problems.
769 */
770 private final Runnable noTraffic = new Runnable()
771 {
772 @Override
773 public void run()
774 {
775 // It's weird but notrafficHandler.removeCallbacks(noTraffic) does not rem ove this callback
776 if (notrafficHandler == null)
777 return;
778 // Show warning notification
779 final NotificationCompat.Builder builder = new NotificationCompat.Builder( ProxyService.this);
780 builder.setSmallIcon(R.drawable.ic_stat_warning);
781 builder.setWhen(System.currentTimeMillis());
782 builder.setAutoCancel(true);
783 final Intent intent = new Intent(ProxyService.this, ConfigurationActivity. class).addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
784 intent.putExtra("port", port);
785 final PendingIntent contentIntent = PendingIntent.getActivity(ProxyService .this, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT);
786 builder.setContentIntent(contentIntent);
787 builder.setContentTitle(getText(R.string.app_name));
788 builder.setContentText(getText(R.string.notif_notraffic));
789 final NotificationManager notificationManager = (NotificationManager) getS ystemService(NOTIFICATION_SERVICE);
790 notificationManager.notify(NOTRAFFIC_NOTIFICATION_ID, builder.getNotificat ion());
791 }
792 };
793
794 /**
795 * Stops no traffic check if traffic is detected by proxy service.
796 */
797 private final BroadcastReceiver filterReceiver = new BroadcastReceiver()
798 {
799 @Override
800 public void onReceive(final Context context, final Intent intent)
801 {
802 if (intent.getAction().equals(AdblockPlus.BROADCAST_FILTERING_CHANGE))
803 {
804 // It's rather a hack but things are happening simultaneously and we
805 // receive this broadcast despite the fact we have unsubscribed from
806 // it and notification is not removed because it is changed to new one
807 // during removal.
808 if (!isNativeProxyAutoConfigured())
809 {
810 final NotificationManager notificationManager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
811 notificationManager.notify(ONGOING_NOTIFICATION_ID, getNotification()) ;
812 }
813 }
814 if (intent.getAction().equals(AdblockPlus.BROADCAST_FILTER_MATCHES))
815 {
816 proxyManualyConfigured = true;
817 stopNoTrafficCheck();
818 }
819 }
820 };
821
822 /**
823 * Stops service if proxy fails. 544 * Stops service if proxy fails.
824 */ 545 */
825 private final BroadcastReceiver proxyReceiver = new BroadcastReceiver() 546 private final BroadcastReceiver proxyReceiver = new BroadcastReceiver()
826 { 547 {
827 @Override 548 @Override
828 public void onReceive(final Context context, final Intent intent) 549 public void onReceive(final Context context, final Intent intent)
829 { 550 {
830 if (intent.getAction().equals(ProxyService.BROADCAST_PROXY_FAILED)) 551 if (intent.getAction().equals(ProxyService.BROADCAST_PROXY_FAILED))
831 { 552 {
832 stopSelf(); 553 stopSelf();
833 } 554 }
834 } 555 }
835 }; 556 };
836 557
837 /** 558 /**
838 * Monitors system network connection settings changes and updates proxy 559 * <p>
839 * settings accordingly. 560 * A BR for simple message passing from various ProxyConfigurators.
561 * </p>
562 * <p>
563 * The purpose of this BroadcastReceiver is to allow other components to send notifications to the service and to be prepared for upcoming service
564 * refactorings.
565 * </p>
840 */ 566 */
841 private final BroadcastReceiver connectionReceiver = new BroadcastReceiver() 567 private final BroadcastReceiver commandBridge = new BroadcastReceiver()
842 { 568 {
843 @Override 569 @Override
844 public void onReceive(final Context ctx, final Intent intent) 570 public void onReceive(final Context context, final Intent intent)
845 { 571 {
846 final String action = intent.getAction(); 572 if (intent != null)
847 Log.i(TAG, "Action: " + action);
848 // Connectivity change
849 if (ConnectivityManager.CONNECTIVITY_ACTION.equals(action))
850 { 573 {
851 final ConnectivityManager connectivityManager = (ConnectivityManager) ge tSystemService(Context.CONNECTIVITY_SERVICE); 574 switch (BridgeCommand.fromString(intent.getStringExtra("command")))
852 // TODO Should we use ConnectivityManagerCompat.getNetworkInfoFromBroadc ast() instead?
853 final NetworkInfo info = connectivityManager.getActiveNetworkInfo();
854 if (info == null)
855 return;
856 final String typeName = info.getTypeName();
857 final String subtypeName = info.getSubtypeName();
858 final boolean available = info.isAvailable();
859
860 Log.i(TAG, "Network Type: " + typeName + ", subtype: " + subtypeName + " , available: " + available);
861 if (info.getType() == ConnectivityManager.TYPE_WIFI)
862 { 575 {
863 if (nativeProxyAutoConfigured) 576 case STATE_CHANGED:
864 { 577 final NotificationManager notificationManager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
865 ProxySettings.setConnectionProxy(getApplicationContext(), LOCALHOST, port, ""); 578 notificationManager.notify(ONGOING_NOTIFICATION_ID, getNotification()) ;
866 } 579 ProxyService.this.sendStateChangedBroadcast();
867 else 580 break;
868 { 581 default:
869 updateNoTrafficCheck(connectivityManager); 582 // ignore
870 } 583 break;
871 }
872 }
873 // Proxy change
874 else if (Proxy.PROXY_CHANGE_ACTION.equals(action))
875 {
876 final Object pp = intent.getParcelableExtra("proxy");
877 try
878 {
879 final String[] userProxy = ProxySettings.getUserProxy(pp);
880 if (nativeProxyAutoConfigured)
881 {
882 if (userProxy != null && Integer.valueOf(userProxy[1]) != port)
883 {
884 Log.i(TAG, "User has set new proxy: " + userProxy[0] + ":" + userP roxy[1] + "(" + userProxy[2] + ")");
885 if (proxy != null)
886 {
887 configureUserProxy(proxyConfiguration, userProxy[0], userProxy[1 ], userProxy[2], null, null);
888 proxy.restart(proxyConfiguration.getProperty("handler"));
889 }
890 }
891 }
892 else
893 {
894 Log.i(TAG, "User has set proxy: " + userProxy[0] + ":" + userProxy[1 ] + "(" + userProxy[2] + ")");
895 updateNoTrafficCheck(userProxy);
896 }
897 }
898 catch (final Exception e)
899 {
900 // This should not happen
901 Log.e(TAG, null, e);
902 } 584 }
903 } 585 }
904 } 586 }
905 }; 587 };
906 588
907 final class ProxyServer extends Server 589 final class ProxyServer extends Server
908 { 590 {
909 @Override 591 @Override
910 public void close() 592 public void close()
911 { 593 {
(...skipping 13 matching lines...) Expand all
925 @Override 607 @Override
926 public void log(final int level, final Object obj, final String message) 608 public void log(final int level, final Object obj, final String message)
927 { 609 {
928 if (level <= logLevel) 610 if (level <= logLevel)
929 { 611 {
930 Log.println(7 - level, obj != null ? obj.toString() : TAG, message); 612 Log.println(7 - level, obj != null ? obj.toString() : TAG, message);
931 } 613 }
932 } 614 }
933 } 615 }
934 } 616 }
OLDNEW
« no previous file with comments | « src/org/adblockplus/android/ProxyServerType.java ('k') | src/org/adblockplus/android/ProxySettings.java » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld