From 99e0f80ba7a2e25e349683290f55245b829f1f2e Mon Sep 17 00:00:00 2001 From: M66B Date: Fri, 25 Dec 2015 13:10:00 +0100 Subject: [PATCH] Allow/block new applications from notification --- app/src/main/AndroidManifest.xml | 2 + .../eu/faircode/netguard/ActivityMain.java | 13 +-- .../java/eu/faircode/netguard/Receiver.java | 83 ++++++++++++++++++- .../eu/faircode/netguard/SinkholeService.java | 40 ++++++++- app/src/main/res/values/strings.xml | 3 + 5 files changed, 132 insertions(+), 9 deletions(-) diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 622e17c6..54e47e0a 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -66,7 +66,9 @@ + + diff --git a/app/src/main/java/eu/faircode/netguard/ActivityMain.java b/app/src/main/java/eu/faircode/netguard/ActivityMain.java index 84b62872..39d143db 100644 --- a/app/src/main/java/eu/faircode/netguard/ActivityMain.java +++ b/app/src/main/java/eu/faircode/netguard/ActivityMain.java @@ -358,13 +358,16 @@ public class ActivityMain extends AppCompatActivity implements SharedPreferences Util.logExtras(intent); if (adapter != null) - if (intent.getBooleanExtra("connected", false)) - if (intent.getBooleanExtra("metered", false)) - adapter.setMobileActive(); + if (intent.hasExtra("connected") && intent.hasExtra("metered")) + if (intent.getBooleanExtra("connected", false)) + if (intent.getBooleanExtra("metered", false)) + adapter.setMobileActive(); + else + adapter.setWifiActive(); else - adapter.setWifiActive(); + adapter.setDisconnected(); else - adapter.setDisconnected(); + updateApplicationList(); } }; diff --git a/app/src/main/java/eu/faircode/netguard/Receiver.java b/app/src/main/java/eu/faircode/netguard/Receiver.java index 3038a185..573d9ad7 100644 --- a/app/src/main/java/eu/faircode/netguard/Receiver.java +++ b/app/src/main/java/eu/faircode/netguard/Receiver.java @@ -19,13 +19,19 @@ package eu.faircode.netguard; Copyright 2015 by Marcel Bokhorst (M66B) */ +import android.app.Notification; +import android.app.PendingIntent; import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; import android.content.SharedPreferences; +import android.content.pm.PackageManager; import android.net.VpnService; import android.os.PowerManager; import android.preference.PreferenceManager; +import android.support.v4.app.NotificationCompat; +import android.support.v4.app.NotificationManagerCompat; +import android.support.v4.content.ContextCompat; import android.util.Log; import java.util.Map; @@ -38,9 +44,78 @@ public class Receiver extends BroadcastReceiver { Log.i(TAG, "Received " + intent); Util.logExtras(intent); - if (Intent.ACTION_PACKAGE_REMOVED.equals(intent.getAction())) { - // Remove settings + if (Intent.ACTION_PACKAGE_ADDED.equals(intent.getAction())) { + // Application added + if (!intent.getBooleanExtra(Intent.EXTRA_REPLACING, false)) + // Show notification + try { + // Get package info + int uid = intent.getIntExtra(Intent.EXTRA_UID, 0); + PackageManager pm = context.getPackageManager(); + String[] packages = pm.getPackagesForUid(uid); + if (packages.length < 1) + throw new PackageManager.NameNotFoundException(Integer.toString(uid)); + String name = (String) pm.getApplicationLabel(pm.getApplicationInfo(packages[0], 0)); + + // Build notification + Intent main = new Intent(context, ActivityMain.class); + PendingIntent pi = PendingIntent.getActivity(context, 0, main, PendingIntent.FLAG_UPDATE_CURRENT); + + NotificationCompat.Builder notification = new NotificationCompat.Builder(context) + .setSmallIcon(R.drawable.ic_security_white_24dp) + .setContentTitle(context.getString(R.string.app_name)) + .setContentText(context.getString(R.string.msg_installed, name)) + .setContentIntent(pi) + .setCategory(Notification.CATEGORY_STATUS) + .setVisibility(Notification.VISIBILITY_SECRET) + .setColor(ContextCompat.getColor(context, R.color.colorPrimary)) + .setAutoCancel(true); + + // Get defaults + SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context); + boolean default_wifi = prefs.getBoolean("whitelist_wifi", true); + boolean default_other = prefs.getBoolean("whitelist_other", true); + + // Build Wi-Fi action + Intent riWifi = new Intent(context, SinkholeService.class); + riWifi.putExtra(SinkholeService.EXTRA_COMMAND, SinkholeService.Command.set); + riWifi.putExtra(SinkholeService.EXTRA_NETWORK, "wifi"); + riWifi.putExtra(SinkholeService.EXTRA_UID, uid); + riWifi.putExtra(SinkholeService.EXTRA_PACKAGE, packages[0]); + riWifi.putExtra(SinkholeService.EXTRA_BLOCKED, !default_wifi); + + PendingIntent piWifi = PendingIntent.getService(context, 0, riWifi, PendingIntent.FLAG_UPDATE_CURRENT); + notification.addAction( + default_wifi ? R.drawable.wifi_on : R.drawable.wifi_off, + context.getString(default_wifi ? R.string.title_allow : R.string.title_block), + piWifi + ); + + // Build mobile action + Intent riOther = new Intent(context, SinkholeService.class); + riOther.putExtra(SinkholeService.EXTRA_COMMAND, SinkholeService.Command.set); + riOther.putExtra(SinkholeService.EXTRA_NETWORK, "other"); + riOther.putExtra(SinkholeService.EXTRA_UID, uid); + riOther.putExtra(SinkholeService.EXTRA_PACKAGE, packages[0]); + riOther.putExtra(SinkholeService.EXTRA_BLOCKED, !default_other); + PendingIntent piOther = PendingIntent.getService(context, 1, riOther, PendingIntent.FLAG_UPDATE_CURRENT); + notification.addAction( + default_other ? R.drawable.other_on : R.drawable.other_off, + context.getString(default_other ? R.string.title_allow : R.string.title_block), + piOther + ); + + // Show notification + NotificationManagerCompat.from(context).notify(uid, notification.build()); + + } catch (PackageManager.NameNotFoundException ex) { + Log.e(TAG, ex.toString() + "\n" + Log.getStackTraceString(ex)); + } + + } else if (Intent.ACTION_PACKAGE_REMOVED.equals(intent.getAction())) { + // Application removed if (intent.getBooleanExtra(Intent.EXTRA_DATA_REMOVED, false)) { + // Remove settings String packageName = intent.getData().getSchemeSpecificPart(); Log.i(TAG, "Deleting settings package=" + packageName); context.getSharedPreferences("wifi", Context.MODE_PRIVATE).edit().remove(packageName).apply(); @@ -48,6 +123,10 @@ public class Receiver extends BroadcastReceiver { context.getSharedPreferences("screen_wifi", Context.MODE_PRIVATE).edit().remove(packageName).apply(); context.getSharedPreferences("screen_other", Context.MODE_PRIVATE).edit().remove(packageName).apply(); context.getSharedPreferences("roaming", Context.MODE_PRIVATE).edit().remove(packageName).apply(); + + int uid = intent.getIntExtra(Intent.EXTRA_UID, 0); + if (uid > 0) + NotificationManagerCompat.from(context).cancel(uid); } } else { diff --git a/app/src/main/java/eu/faircode/netguard/SinkholeService.java b/app/src/main/java/eu/faircode/netguard/SinkholeService.java index 137d25e0..b9ac7330 100644 --- a/app/src/main/java/eu/faircode/netguard/SinkholeService.java +++ b/app/src/main/java/eu/faircode/netguard/SinkholeService.java @@ -89,15 +89,19 @@ public class SinkholeService extends VpnService { private static final int NOTIFY_DISABLED = 2; private static final int NOTIFY_TRAFFIC = 3; - private static final String EXTRA_COMMAND = "Command"; + public static final String EXTRA_COMMAND = "Command"; private static final String EXTRA_REASON = "Reason"; + public static final String EXTRA_NETWORK = "Network"; + public static final String EXTRA_UID = "UID"; + public static final String EXTRA_PACKAGE = "Package"; + public static final String EXTRA_BLOCKED = "Blocked"; private static final int MSG_SERVICE_INTENT = 0; private static final int MSG_STATS_START = 1; private static final int MSG_STATS_STOP = 2; private static final int MSG_STATS_UPDATE = 3; - private enum Command {start, reload, stop, stats} + public enum Command {start, reload, stop, stats, set} private static volatile PowerManager.WakeLock wlInstance = null; @@ -232,6 +236,10 @@ public class SinkholeService extends VpnService { stopStats(); startStats(); break; + + case set: + set(intent); + break; } // Update main view @@ -454,6 +462,34 @@ public class SinkholeService extends VpnService { .setOngoing(true); NotificationManagerCompat.from(SinkholeService.this).notify(NOTIFY_TRAFFIC, builder.build()); } + + private void set(Intent intent) { + // Get arguments + int uid = intent.getIntExtra(EXTRA_UID, 0); + String network = intent.getStringExtra(EXTRA_NETWORK); + String pkg = intent.getStringExtra(EXTRA_PACKAGE); + boolean blocked = intent.getBooleanExtra(EXTRA_BLOCKED, false); + Log.i(TAG, "Set " + pkg + " " + network + "=" + blocked); + + // Get defailts + SharedPreferences settings = PreferenceManager.getDefaultSharedPreferences(SinkholeService.this); + boolean default_wifi = settings.getBoolean("whitelist_wifi", true); + boolean default_other = settings.getBoolean("whitelist_other", true); + + // Update setting + SharedPreferences prefs = getSharedPreferences(network, Context.MODE_PRIVATE); + if (blocked == ("wifi".equals(network) ? default_wifi : default_other)) + prefs.edit().remove(pkg).apply(); + else + prefs.edit().putBoolean(pkg, blocked).apply(); + + // Remove notification + NotificationManagerCompat.from(SinkholeService.this).cancel(uid); + + // Update UI + Intent ruleset = new Intent(ActivityMain.ACTION_RULES_CHANGED); + LocalBroadcastManager.getInstance(SinkholeService.this).sendBroadcast(ruleset); + } } private ParcelFileDescriptor startVPN() { diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 5bdd5ee9..6adac75b 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -63,6 +63,7 @@ These issues are caused by bugs in Android, or in the software provided by the m %1$d allowed, %2$d blocked NetGuard is disabled, use the switch above to enable NetGuard NetGuard has been disabled, likely by using another VPN based application + \'%1$s\' installed Action completed NetGuard uses a local VPN as a sinkhole to block internet traffic. For this reason, please allow a VPN connection in the next dialog. @@ -84,6 +85,8 @@ Since NetGuard has no internet permission, you know your internet traffic is not Donate Rate Thank you for your donation! + Allow + Block ef46f813d2c8a064d72c936b9b96d1cccc989378