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: Last batch of review issues Created Aug. 24, 2014, 11:52 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 private static final boolean LOG_REQUESTS = false;
74 private static final boolean logRequests = 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 61
83 static final int ONGOING_NOTIFICATION_ID = R.string.app_name; 62 static final int ONGOING_NOTIFICATION_ID = R.string.app_name;
63
84 private static final long POSITION_RIGHT = Build.VERSION.SDK_INT >= Build.VERS ION_CODES.GINGERBREAD ? Long.MIN_VALUE : Long.MAX_VALUE; 64 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 65
87 /** 66 /**
88 * Broadcasted when service starts or stops. 67 * Broadcasted when service starts or stops.
89 */ 68 */
90 public static final String BROADCAST_STATE_CHANGED = "org.adblockplus.android. service.state"; 69 public static final String BROADCAST_STATE_CHANGED = "org.adblockplus.android. SERVICE_STATE_CHANGED";
70
91 /** 71 /**
92 * Broadcasted if proxy fails to start. 72 * Broadcasted if proxy fails to start.
93 */ 73 */
94 public static final String BROADCAST_PROXY_FAILED = "org.adblockplus.android.p roxy.failure"; 74 public static final String BROADCAST_PROXY_FAILED = "org.adblockplus.android.P ROXY_FAILURE";
95 75
96 private static final String IPTABLES_RETURN = " -t nat -m owner --uid-owner {{ UID}} -A OUTPUT -p tcp -j RETURN\n"; 76 /**
97 private static final String IPTABLES_ADD_HTTP = " -t nat -A OUTPUT -p tcp --dp ort 80 -j REDIRECT --to {{PORT}}\n"; 77 * Common command bridge
78 */
79 public static final String PROXY_STATE_CHANGED_ACTION = "org.adblockplus.andro id.PROXY_STATE_CHANGED";
98 80
99 boolean hideIcon; 81 boolean hideIcon;
100 private Handler notrafficHandler;
101 82
102 protected ProxyServer proxy = null; 83 protected ProxyServer proxy = null;
84
103 protected int port; 85 protected int port;
86
104 private final Properties proxyConfiguration = new Properties(); 87 private final Properties proxyConfiguration = new Properties();
105 88
106 /** 89 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 90
121 @SuppressLint("NewApi") 91 @SuppressLint("NewApi")
122 @Override 92 @Override
123 public void onCreate() 93 public void onCreate()
124 { 94 {
125 super.onCreate(); 95 super.onCreate();
126 96
127 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.GINGERBREAD) 97 StrictMode.setThreadPolicy(new StrictMode.ThreadPolicy.Builder()
128 { 98 .permitAll()
129 // Proxy is running in separate thread, it's just some resolution request during initialization. 99 .penaltyLog()
130 // Not worth spawning a separate thread for this. 100 .build());
131 final StrictMode.ThreadPolicy policy = new StrictMode.ThreadPolicy.Builder ().permitNetwork().build();
132 StrictMode.setThreadPolicy(policy);
133 }
134 101
135 // Get port for local proxy
136 final SharedPreferences prefs = PreferenceManager.getDefaultSharedPreference s(this); 102 final SharedPreferences prefs = PreferenceManager.getDefaultSharedPreference s(this);
137 final Resources resources = getResources();
138 103
139 // Try to read user proxy settings 104 // Try to read user proxy settings
140 String proxyHost = null; 105 String proxyHost = System.getProperty("http.proxyHost");;
141 String proxyPort = null; 106 String proxyPort = System.getProperty("http.proxyPort");
142 String proxyExcl = null; 107 final String proxyExcl = System.getProperty("http.nonProxyHosts");
143 String proxyUser = null; 108 String proxyUser = null;
144 String proxyPass = null; 109 String proxyPass = null;
145 110
146 if (NATIVE_PROXY_SUPPORTED) 111 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 { 112 {
161 // Read application settings 113 // Read application settings
162 proxyHost = prefs.getString(getString(R.string.pref_proxyhost), null); 114 proxyHost = prefs.getString(getString(R.string.pref_proxyhost), null);
163 proxyPort = prefs.getString(getString(R.string.pref_proxyport), null); 115 proxyPort = prefs.getString(getString(R.string.pref_proxyport), null);
164 proxyUser = prefs.getString(getString(R.string.pref_proxyuser), null); 116 proxyUser = prefs.getString(getString(R.string.pref_proxyuser), null);
165 proxyPass = prefs.getString(getString(R.string.pref_proxypass), null); 117 proxyPass = prefs.getString(getString(R.string.pref_proxypass), null);
166 } 118 }
167 119
168 // Check for root privileges and try to install transparent proxy 120 registerReceiver(this.proxyReceiver, new IntentFilter(ProxyService.BROADCAST _PROXY_FAILED));
169 if (RootTools.isAccessGiven()) 121 registerReceiver(this.proxyStateChangedReceiver, new IntentFilter(ProxyServi ce.PROXY_STATE_CHANGED_ACTION));
122
123 final InetAddress inetAddress;
124 try
170 { 125 {
171 try 126 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 } 127 }
204 128 catch (final UnknownHostException e)
205 if (!transparent)
206 { 129 {
207 // Try to set native proxy 130 sendBroadcast(new Intent(BROADCAST_PROXY_FAILED)
208 nativeProxyAutoConfigured = ProxySettings.setConnectionProxy(getApplicatio nContext(), LOCALHOST, port, ""); 131 .putExtra("msg", "Could not resolve 'localhost'"));
209 132 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 } 133 }
216 134
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 135 // Start proxy
228 if (proxy == null) 136 if (proxy == null)
229 { 137 {
230 // Select available port and bind to it, use previously selected port by d efault 138 // 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; 139 ServerSocket listen = null;
233 String msg = null; 140 String msg = null;
234 for (final int p : portVariants) 141 for (final int p : PORT_VARIANTS)
235 { 142 {
236 if (p < 0) 143 final int toCheck = (p == -1) ? prefs.getInt(getString(R.string.pref_las tport), -1) : p;
237 continue; 144
238 try 145 if (toCheck >= 0)
239 { 146 {
240 // Fix for #232, bind proxy socket to loopback only 147 try
241 listen = new ServerSocket(p, 1024, InetAddress.getByName(LOCALHOST)); 148 {
242 port = p; 149 // Fix for #232, bind proxy socket to loopback only
243 break; 150 listen = new ServerSocket(toCheck, 1024, inetAddress);
244 } 151 this.port = listen.getLocalPort();
245 catch (final IOException e) 152 break;
246 { 153 }
247 Log.e(TAG, null, e); 154 catch (final IOException e)
248 msg = e.getMessage(); 155 {
156 Log.e(TAG, null, e);
157 msg = e.getMessage();
158 }
249 } 159 }
250 } 160 }
161
251 if (listen == null) 162 if (listen == null)
252 { 163 {
253 sendBroadcast(new Intent(BROADCAST_PROXY_FAILED).putExtra("msg", msg)); 164 sendBroadcast(new Intent(BROADCAST_PROXY_FAILED).putExtra("msg", msg));
254 return; 165 return;
255 } 166 }
256 167
168 this.proxyConfigurator = ProxyConfigurators.registerProxy(this, inetAddres s, this.port);
169
170 if (this.proxyConfigurator == null)
171 {
172 sendBroadcast(new Intent(BROADCAST_PROXY_FAILED)
173 .putExtra("msg", "Failed to register proxy"));
174 return;
175 }
176
257 // Save selected port 177 // Save selected port
178 final SharedPreferences.Editor editor = prefs.edit();
179 editor.putBoolean(getString(R.string.pref_proxyautoconfigured), this.getPr oxyRegistrationType().isAutoConfigured());
258 editor.putInt(getString(R.string.pref_lastport), port); 180 editor.putInt(getString(R.string.pref_lastport), port);
259 editor.commit(); 181 editor.commit();
260 182
261 // Initialize proxy 183 // Initialize proxy
262 proxyConfiguration.put("handler", "main"); 184 proxyConfiguration.put("handler", "main");
263 proxyConfiguration.put("main.prefix", ""); 185 proxyConfiguration.put("main.prefix", "");
264 proxyConfiguration.put("main.class", "sunlabs.brazil.server.ChainHandler") ; 186 proxyConfiguration.put("main.class", "sunlabs.brazil.server.ChainHandler") ;
265 if (transparent) 187 switch (this.getProxyRegistrationType().getProxyType())
266 { 188 {
189 case HTTP:
267 proxyConfiguration.put("main.handlers", "urlmodifier adblock"); 190 proxyConfiguration.put("main.handlers", "urlmodifier adblock");
268 proxyConfiguration.put("urlmodifier.class", "org.adblockplus.brazil.Tran sparentProxyHandler"); 191 proxyConfiguration.put("urlmodifier.class", "org.adblockplus.brazil.Tran sparentProxyHandler");
269 } 192 break;
270 else 193 case HTTPS:
271 {
272 proxyConfiguration.put("main.handlers", "https adblock"); 194 proxyConfiguration.put("main.handlers", "https adblock");
273 proxyConfiguration.put("https.class", "org.adblockplus.brazil.SSLConnect ionHandler"); 195 proxyConfiguration.put("https.class", "org.adblockplus.brazil.SSLConnect ionHandler");
196 break;
197 default:
198 sendBroadcast(new Intent(BROADCAST_PROXY_FAILED)
199 .putExtra("msg", "Unsupported proxy server type: " + this.getProxyRe gistrationType().getProxyType()));
200 return;
274 } 201 }
275 proxyConfiguration.put("adblock.class", "org.adblockplus.brazil.RequestHan dler"); 202 proxyConfiguration.put("adblock.class", "org.adblockplus.brazil.RequestHan dler");
276 if (logRequests) 203 if (LOG_REQUESTS)
277 proxyConfiguration.put("adblock.proxylog", "yes"); 204 proxyConfiguration.put("adblock.proxylog", "yes");
278 205
279 configureUserProxy(proxyConfiguration, proxyHost, proxyPort, proxyExcl, pr oxyUser, proxyPass); 206 configureUserProxy(proxyConfiguration, proxyHost, proxyPort, proxyExcl, pr oxyUser, proxyPass);
280 207
281 proxy = new ProxyServer(); 208 proxy = new ProxyServer();
282 proxy.logLevel = Server.LOG_DIAGNOSTIC; 209 proxy.logLevel = Server.LOG_LOG;
283 proxy.setup(listen, proxyConfiguration.getProperty("handler"), proxyConfig uration); 210 proxy.setup(listen, proxyConfiguration.getProperty("handler"), proxyConfig uration);
284 proxy.start(); 211 proxy.start();
285 } 212 }
286 213
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); 214 prefs.registerOnSharedPreferenceChangeListener(this);
317 215
318 // Lock service 216 // Lock service
319 hideIcon = prefs.getBoolean(getString(R.string.pref_hideicon), resources.get Boolean(R.bool.def_hideicon)); 217 hideIcon = prefs.getBoolean(getString(R.string.pref_hideicon), getResources( ).getBoolean(R.bool.def_hideicon));
320 startForeground(ONGOING_NOTIFICATION_ID, getNotification()); 218 startForeground(ONGOING_NOTIFICATION_ID, getNotification());
321 219
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(); 220 sendStateChangedBroadcast();
331 Log.i(TAG, "Service started"); 221 Log.i(TAG, "Service started");
332 } 222 }
333 223
334 @Override 224 @Override
335 public int onStartCommand(final Intent intent, final int flags, final int star tId) 225 public int onStartCommand(final Intent intent, final int flags, final int star tId)
336 { 226 {
337 return START_STICKY; 227 return START_STICKY;
338 } 228 }
339 229
340 @Override 230 @Override
341 public void onDestroy() 231 public void onDestroy()
342 { 232 {
343 super.onDestroy(); 233 super.onDestroy();
344 234
345 stopNoTrafficCheck(); 235 unregisterReceiver(this.proxyReceiver);
236 unregisterReceiver(this.proxyStateChangedReceiver);
346 237
347 unregisterReceiver(filterReceiver); 238 if (this.proxyConfigurator != null)
348 unregisterReceiver(proxyReceiver);
349
350 // Stop IP redirecting
351 if (transparent)
352 { 239 {
353 new Thread() 240 this.proxyConfigurator.unregisterProxy();
354 { 241 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 } 242 }
378 243
379 sendBroadcast(new Intent(BROADCAST_STATE_CHANGED).putExtra("enabled", false) ); 244 sendBroadcast(new Intent(BROADCAST_STATE_CHANGED).putExtra("enabled", false) );
380 245
381 // Stop proxy server 246 // Stop proxy server
382 if (proxy != null) 247 if (proxy != null)
248 {
383 proxy.close(); 249 proxy.close();
250 proxy = null;
251 }
384 252
385 // Release service lock 253 // Release service lock
386 stopForeground(true); 254 stopForeground(true);
387 255
388 Log.i(TAG, "Service stopped"); 256 Log.i(TAG, "Service stopped");
389 } 257 }
390 258
391 /** 259 /**
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. 260 * Sets user proxy settings in proxy service properties.
415 */ 261 */
416 private void configureUserProxy(final Properties config, final String proxyHos t, final String proxyPort, final String proxyExcl, final String proxyUser, final String proxyPass) 262 private void configureUserProxy(final Properties config, final String proxyHos t, final String proxyPort, final String proxyExcl,
263 final String proxyUser, final String proxyPass)
417 { 264 {
418 // Clean previous settings 265 // Clean previous settings
419 config.remove("adblock.proxyHost"); 266 config.remove("adblock.proxyHost");
420 config.remove("adblock.proxyPort"); 267 config.remove("adblock.proxyPort");
421 config.remove("adblock.auth"); 268 config.remove("adblock.auth");
422 config.remove("adblock.proxyExcl"); 269 config.remove("adblock.proxyExcl");
423 if (!transparent) 270 config.remove("https.proxyHost");
271 config.remove("https.proxyPort");
272 config.remove("https.auth");
273
274 final ProxyRegistrationType regType = this.getProxyRegistrationType();
275 if (regType == ProxyRegistrationType.NATIVE)
424 { 276 {
425 config.remove("https.proxyHost"); 277 passProxySettings(proxyHost, proxyPort, proxyExcl);
426 config.remove("https.proxyPort");
427 config.remove("https.auth");
428 } 278 }
429 279
430 if (nativeProxyAutoConfigured)
431 passProxySettings(proxyHost, proxyPort, proxyExcl);
432
433 // Check if there are any settings 280 // Check if there are any settings
434 if (proxyHost == null || "".equals(proxyHost)) 281 if (StringUtils.isEmpty(proxyHost))
282 {
435 return; 283 return;
284 }
436 285
437 // Check for dirty proxy settings - this indicated previous crash: 286 // Check for dirty proxy settings - this indicated previous crash:
438 // proxy points to ourselves 287 // proxy points to ourselves
439 // proxy port is null, 0 or not a number 288 // proxy port is null, 0 or not a number
440 // proxy is 127.0.0.1:8080 289 // proxy is 127.0.0.1:8080
441 if (proxyPort == null) 290 if (proxyPort == null)
291 {
442 return; 292 return;
443 int p = 0; 293 }
294
295 final int p;
444 try 296 try
445 { 297 {
446 p = Integer.valueOf(proxyPort); 298 p = Integer.valueOf(proxyPort);
447 } 299 }
448 catch (final NumberFormatException e) 300 catch (final NumberFormatException e)
449 { 301 {
450 return; 302 return;
451 } 303 }
452 if (p == 0 || isLocalHost(proxyHost) && (p == port || p == 8080)) 304
305 if (p == 0 || isLocalhost(proxyHost) && (p == port || p == 8080))
453 { 306 {
454 if (nativeProxyAutoConfigured) 307 if (regType == ProxyRegistrationType.NATIVE)
308 {
455 passProxySettings(null, null, null); 309 passProxySettings(null, null, null);
310 }
456 return; 311 return;
457 } 312 }
458 313
459 config.put("adblock.proxyHost", proxyHost); 314 config.put("adblock.proxyHost", proxyHost);
460 config.put("adblock.proxyPort", proxyPort); 315 config.put("adblock.proxyPort", proxyPort);
461 if (!transparent) 316 if (regType.getProxyType() == ProxyServerType.HTTPS)
462 { 317 {
463 config.put("https.proxyHost", proxyHost); 318 config.put("https.proxyHost", proxyHost);
464 config.put("https.proxyPort", proxyPort); 319 config.put("https.proxyPort", proxyPort);
465 } 320 }
466 321
467 // TODO Not implemented in our proxy but needed to restore settings 322 // TODO Not implemented in our proxy but needed to restore settings
468 if (proxyExcl != null) 323 if (proxyExcl != null)
324 {
469 config.put("adblock.proxyExcl", proxyExcl); 325 config.put("adblock.proxyExcl", proxyExcl);
326 }
470 327
471 if (proxyUser != null && !"".equals(proxyUser) && proxyPass != null && !"".e quals(proxyPass)) 328 if (StringUtils.isNotEmpty(proxyUser) && StringUtils.isNotEmpty(proxyPass))
472 { 329 {
473 // Base64 encode user:password 330 // Base64 encode user:password
474 final String proxyAuth = "Basic " + new String(Base64.encode(proxyUser + " :" + proxyPass)); 331 final String proxyAuth = "Basic " + new String(Base64.encode(proxyUser + " :" + proxyPass));
475 config.put("adblock.auth", proxyAuth); 332 config.put("adblock.auth", proxyAuth);
476 if (!transparent) 333 if (regType.getProxyType() == ProxyServerType.HTTPS)
334 {
477 config.put("https.auth", proxyAuth); 335 config.put("https.auth", proxyAuth);
336 }
478 } 337 }
479 } 338 }
480 339
340 /**
341 * @return {@code true} if the given host string resolves to {@code localhost}
342 */
343 public static boolean isLocalhost(final String host)
344 {
345 try
346 {
347 if (StringUtils.isEmpty(host))
348 {
349 return false;
350 }
351
352 if (host.equals("127.0.0.1") || host.equalsIgnoreCase("localhost"))
353 {
354 return true;
355 }
356
357 return InetAddress.getByName(host).isLoopbackAddress();
358 }
359 catch (final Exception e)
360 {
361 return false;
362 }
363 }
364
481 private void passProxySettings(final String proxyHost, final String proxyPort, final String proxyExcl) 365 private void passProxySettings(final String proxyHost, final String proxyPort, final String proxyExcl)
482 { 366 {
483 try 367 try
484 { 368 {
485 final CrashHandler handler = (CrashHandler) Thread.getDefaultUncaughtExcep tionHandler(); 369 final CrashHandler handler = (CrashHandler) Thread.getDefaultUncaughtExcep tionHandler();
486 handler.saveProxySettings(proxyHost, proxyPort, proxyExcl); 370 handler.saveProxySettings(proxyHost, proxyPort, proxyExcl);
487 } 371 }
488 catch (final ClassCastException e) 372 catch (final ClassCastException e)
489 { 373 {
490 // ignore - default handler in use 374 // ignore - default handler in use
491 } 375 }
492 } 376 }
493 377
494 @Override 378 @Override
495 public void onSharedPreferenceChanged(final SharedPreferences sharedPreference s, final String key) 379 public void onSharedPreferenceChanged(final SharedPreferences sharedPreference s, final String key)
496 { 380 {
497 if (!NATIVE_PROXY_SUPPORTED) 381 if (this.getProxyRegistrationType() != ProxyRegistrationType.NATIVE)
498 { 382 {
499 final String ketHost = getString(R.string.pref_proxyhost); 383 final String keyHost = getString(R.string.pref_proxyhost);
500 final String keyPort = getString(R.string.pref_proxyport); 384 final String keyPort = getString(R.string.pref_proxyport);
501 final String keyUser = getString(R.string.pref_proxyuser); 385 final String keyUser = getString(R.string.pref_proxyuser);
502 final String keyPass = getString(R.string.pref_proxypass); 386 final String keyPass = getString(R.string.pref_proxypass);
503 if (key.equals(ketHost) || key.equals(keyPort) || key.equals(keyUser) || k ey.equals(keyPass)) 387 if (key.equals(keyHost) || key.equals(keyPort) || key.equals(keyUser) || k ey.equals(keyPass))
504 { 388 {
505 final String proxyHost = sharedPreferences.getString(ketHost, null); 389 final String proxyHost = sharedPreferences.getString(keyHost, null);
506 final String proxyPort = sharedPreferences.getString(keyPort, null); 390 final String proxyPort = sharedPreferences.getString(keyPort, null);
507 final String proxyUser = sharedPreferences.getString(keyUser, null); 391 final String proxyUser = sharedPreferences.getString(keyUser, null);
508 final String proxyPass = sharedPreferences.getString(keyPass, null); 392 final String proxyPass = sharedPreferences.getString(keyPass, null);
509 if (proxy != null) 393 if (proxy != null)
510 { 394 {
511 configureUserProxy(proxyConfiguration, proxyHost, proxyPort, null, pro xyUser, proxyPass); 395 configureUserProxy(proxyConfiguration, proxyHost, proxyPort, null, pro xyUser, proxyPass);
512 proxy.restart(proxyConfiguration.getProperty("handler")); 396 proxy.restart(proxyConfiguration.getProperty("handler"));
513 } 397 }
514 } 398 }
515 } 399 }
516 } 400 }
517 401
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 /** 402 /**
639 * Raises or removes no traffic notification based on current link proxy 403 * @return the active proxy configuration's type or {@link ProxyRegistrationTy pe#UNKNOWN} if none is configured
640 * settings
641 */ 404 */
642 private void updateNoTrafficCheck(final ConnectivityManager connectivityManage r) 405 private ProxyRegistrationType getProxyRegistrationType()
643 { 406 {
644 try 407 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 } 408 }
658 409
659 /** 410 /**
660 * Raises or removes no traffic notification based on the user proxy settings 411 * @return {@code true} if there is a valid proxy configurator and registratio n succeeded
661 */ 412 */
662 private void updateNoTrafficCheck(final String[] userProxy) 413 public boolean isRegistered()
663 { 414 {
664 final boolean ourProxy = userProxy != null && isLocalHost(userProxy[0]) && I nteger.valueOf(userProxy[1]) == port; 415 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 } 416 }
683 417
684 /** 418 /**
685 * Stops no traffic check and resets notification message. 419 * @return {@code true} if registration type is {@link ProxyRegistrationType#N ATIVE} and registration succeeded
686 */ 420 */
687 private void stopNoTrafficCheck() 421 public boolean isNativeProxyAutoConfigured()
688 { 422 {
689 if (notrafficHandler != null) 423 return this.getProxyRegistrationType() == ProxyRegistrationType.NATIVE && th is.isRegistered();
690 { 424 }
691 notrafficHandler.removeCallbacks(noTraffic); 425
692 sendStateChangedBroadcast(); 426 /**
693 final NotificationManager notificationManager = (NotificationManager) getS ystemService(NOTIFICATION_SERVICE); 427 * @return {@code true} if registration type is {@link ProxyRegistrationType#M ANUAL}
694 notificationManager.notify(ONGOING_NOTIFICATION_ID, getNotification()); 428 */
695 notificationManager.cancel(NOTRAFFIC_NOTIFICATION_ID); 429 public boolean isManual()
696 } 430 {
697 notrafficHandler = null; 431 return this.getProxyRegistrationType() == ProxyRegistrationType.MANUAL;
432 }
433
434 /**
435 * @return {@code true} if registration type is {@link ProxyRegistrationType#I PTABLES}
436 */
437 public boolean isIptables()
438 {
439 return this.getProxyRegistrationType() == ProxyRegistrationType.IPTABLES;
698 } 440 }
699 441
700 @SuppressLint("NewApi") 442 @SuppressLint("NewApi")
701 private Notification getNotification() 443 private Notification getNotification()
702 { 444 {
703 final boolean filtering = AdblockPlus.getApplication().isFilteringEnabled(); 445 final boolean filtering = AdblockPlus.getApplication().isFilteringEnabled();
704 446
705 int msgId = R.string.notif_waiting; 447 final int msgId;
706 if (nativeProxyAutoConfigured || proxyManualyConfigured) 448 switch(this.getProxyRegistrationType())
449 {
450 case MANUAL:
451 if (this.isRegistered())
452 {
453 msgId = filtering ? R.string.notif_wifi : R.string.notif_wifi_nofilterin g;
454 }
455 else
456 {
457 msgId = filtering ? R.string.notif_waiting : R.string.notif_wifi_nofilte ring;
458 }
459 break;
460 case NATIVE:
707 msgId = filtering ? R.string.notif_wifi : R.string.notif_wifi_nofiltering; 461 msgId = filtering ? R.string.notif_wifi : R.string.notif_wifi_nofiltering;
708 if (transparent) 462 break;
463 case IPTABLES:
464 case CYANOGENMOD:
709 msgId = R.string.notif_all; 465 msgId = R.string.notif_all;
466 break;
467 default:
468 msgId = R.string.notif_waiting;
469 break;
470 }
710 471
711 final NotificationCompat.Builder builder = new NotificationCompat.Builder(th is); 472 final NotificationCompat.Builder builder = new NotificationCompat.Builder(th is);
712 if (hideIcon && msgId != R.string.notif_waiting) 473 if (hideIcon && msgId != R.string.notif_waiting)
713 { 474 {
714 builder.setWhen(POSITION_RIGHT); 475 builder.setWhen(POSITION_RIGHT);
715 builder.setSmallIcon(R.drawable.transparent); 476 builder.setSmallIcon(R.drawable.transparent);
716 // builder.setContent(new RemoteViews(getPackageName(), R.layout.notif_hid den));
717 } 477 }
718 else 478 else
719 { 479 {
720 builder.setWhen(0); 480 builder.setWhen(0);
721 builder.setSmallIcon(R.drawable.ic_stat_blocking); 481 builder.setSmallIcon(R.drawable.ic_stat_blocking);
722 } 482 }
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); 483 final PendingIntent contentIntent = PendingIntent.getActivity(this, 0,
484 new Intent(this, Preferences.class).addFlags(Intent.FLAG_ACTIVITY_CLEAR_ TOP | Intent.FLAG_ACTIVITY_NEW_TASK), 0);
485
724 builder.setContentIntent(contentIntent); 486 builder.setContentIntent(contentIntent);
725 builder.setContentTitle(getText(R.string.app_name)); 487 builder.setContentTitle(getText(R.string.app_name));
726 builder.setContentText(getString(msgId, port)); 488 builder.setContentText(getString(msgId, port));
727 builder.setOngoing(true); 489 builder.setOngoing(true);
728 490
729 final Notification notification = builder.getNotification(); 491 return builder.getNotification();
730 return notification;
731 } 492 }
732 493
733 public void setEmptyIcon(final boolean hide) 494 public void setEmptyIcon(final boolean hide)
734 { 495 {
735 hideIcon = hide; 496 hideIcon = hide;
736 final NotificationManager notificationManager = (NotificationManager) getSys temService(NOTIFICATION_SERVICE); 497 final NotificationManager notificationManager = (NotificationManager) getSys temService(NOTIFICATION_SERVICE);
737 notificationManager.notify(ONGOING_NOTIFICATION_ID, getNotification()); 498 notificationManager.notify(ONGOING_NOTIFICATION_ID, getNotification());
738 } 499 }
739 500
740 public void sendStateChangedBroadcast() 501 public void sendStateChangedBroadcast()
741 { 502 {
742 Log.i(TAG, "Broadcasting " + BROADCAST_STATE_CHANGED);
743 final boolean manual = isManual(); 503 final boolean manual = isManual();
744 final Intent stateIntent = new Intent(BROADCAST_STATE_CHANGED).putExtra("ena bled", true).putExtra("port", port).putExtra("manual", manual); 504 final Intent stateIntent = new Intent(BROADCAST_STATE_CHANGED)
505 .putExtra("enabled", true)
506 .putExtra("port", port)
507 .putExtra("manual", manual);
508
745 if (manual) 509 if (manual)
746 stateIntent.putExtra("configured", proxyManualyConfigured); 510 {
511 stateIntent.putExtra("configured", this.isRegistered());
512 }
513
747 sendBroadcast(stateIntent); 514 sendBroadcast(stateIntent);
748 } 515 }
749 516
750 private final IBinder binder = new LocalBinder(); 517 private final IBinder binder = new LocalBinder();
751 518
752 public final class LocalBinder extends Binder 519 public final class LocalBinder extends Binder
753 { 520 {
754 public ProxyService getService() 521 public ProxyService getService()
755 { 522 {
756 return ProxyService.this; 523 return ProxyService.this;
757 } 524 }
758 } 525 }
759 526
760 @Override 527 @Override
761 public IBinder onBind(final Intent intent) 528 public IBinder onBind(final Intent intent)
762 { 529 {
763 return binder; 530 return binder;
764 } 531 }
765 532
766 /** 533 /**
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. 534 * Stops service if proxy fails.
824 */ 535 */
825 private final BroadcastReceiver proxyReceiver = new BroadcastReceiver() 536 private final BroadcastReceiver proxyReceiver = new BroadcastReceiver()
826 { 537 {
827 @Override 538 @Override
828 public void onReceive(final Context context, final Intent intent) 539 public void onReceive(final Context context, final Intent intent)
829 { 540 {
830 if (intent.getAction().equals(ProxyService.BROADCAST_PROXY_FAILED)) 541 if (intent.getAction().equals(ProxyService.BROADCAST_PROXY_FAILED))
831 { 542 {
832 stopSelf(); 543 stopSelf();
833 } 544 }
834 } 545 }
835 }; 546 };
836 547
837 /** 548 /**
838 * Monitors system network connection settings changes and updates proxy 549 * <p>
839 * settings accordingly. 550 * Proxy state change receiver.
551 * </p>
840 */ 552 */
841 private final BroadcastReceiver connectionReceiver = new BroadcastReceiver() 553 private final BroadcastReceiver proxyStateChangedReceiver = new BroadcastRecei ver()
842 { 554 {
843 @Override 555 @Override
844 public void onReceive(final Context ctx, final Intent intent) 556 public void onReceive(final Context context, final Intent intent)
845 { 557 {
846 final String action = intent.getAction(); 558 if (intent != null && PROXY_STATE_CHANGED_ACTION.equals(intent.getAction() ))
847 Log.i(TAG, "Action: " + action);
848 // Connectivity change
849 if (ConnectivityManager.CONNECTIVITY_ACTION.equals(action))
850 { 559 {
851 final ConnectivityManager connectivityManager = (ConnectivityManager) ge tSystemService(Context.CONNECTIVITY_SERVICE); 560 final NotificationManager notificationManager = (NotificationManager) ge tSystemService(NOTIFICATION_SERVICE);
852 // TODO Should we use ConnectivityManagerCompat.getNetworkInfoFromBroadc ast() instead? 561 notificationManager.notify(ONGOING_NOTIFICATION_ID, getNotification());
853 final NetworkInfo info = connectivityManager.getActiveNetworkInfo(); 562 ProxyService.this.sendStateChangedBroadcast();
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 {
863 if (nativeProxyAutoConfigured)
864 {
865 ProxySettings.setConnectionProxy(getApplicationContext(), LOCALHOST, port, "");
866 }
867 else
868 {
869 updateNoTrafficCheck(connectivityManager);
870 }
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 }
903 } 563 }
904 } 564 }
905 }; 565 };
906 566
907 final class ProxyServer extends Server 567 final class ProxyServer extends Server
908 { 568 {
909 @Override 569 @Override
910 public void close() 570 public void close()
911 { 571 {
912 try 572 try
(...skipping 12 matching lines...) Expand all
925 @Override 585 @Override
926 public void log(final int level, final Object obj, final String message) 586 public void log(final int level, final Object obj, final String message)
927 { 587 {
928 if (level <= logLevel) 588 if (level <= logLevel)
929 { 589 {
930 Log.println(7 - level, obj != null ? obj.toString() : TAG, message); 590 Log.println(7 - level, obj != null ? obj.toString() : TAG, message);
931 } 591 }
932 } 592 }
933 } 593 }
934 } 594 }
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