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

Delta Between Two Patch Sets: src/org/adblockplus/android/ProxyService.java

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

Powered by Google App Engine
This is Rietveld