From fcec92a0042477347338a25cd072d622edfa03c9 Mon Sep 17 00:00:00 2001 From: cyBerta Date: Sat, 16 Oct 2021 11:59:42 +0200 Subject: show tor bootstrapping progress in notifications --- .../leap/bitmaskclient/eip/EipSetupObserver.java | 4 +- .../bitmaskclient/tor/TorNotificationManager.java | 13 +++- .../bitmaskclient/tor/TorStatusObservable.java | 77 +++++++++++++++++++++- app/src/main/res/values/strings.xml | 18 ++++- 4 files changed, 104 insertions(+), 8 deletions(-) diff --git a/app/src/main/java/se/leap/bitmaskclient/eip/EipSetupObserver.java b/app/src/main/java/se/leap/bitmaskclient/eip/EipSetupObserver.java index a71a5613..23fbdc0c 100644 --- a/app/src/main/java/se/leap/bitmaskclient/eip/EipSetupObserver.java +++ b/app/src/main/java/se/leap/bitmaskclient/eip/EipSetupObserver.java @@ -169,7 +169,9 @@ public class EipSetupObserver extends BroadcastReceiver implements VpnStatus.Sta private void handleTorStatusEvent(Intent intent) { String status = intent.getStringExtra(TorService.EXTRA_STATUS); Log.d(TAG, "handle Tor status event: " + status); - TorStatusObservable.updateState(context, status); + Integer bootstrap = intent.getIntExtra(TorService.EXTRA_STATUS_DETAIL_BOOTSTRAP, -1); + String logKey = intent.getStringExtra(TorService.EXTRA_STATUS_DETAIL_LOGKEY); + TorStatusObservable.updateState(context, status, bootstrap, logKey); } diff --git a/app/src/main/java/se/leap/bitmaskclient/tor/TorNotificationManager.java b/app/src/main/java/se/leap/bitmaskclient/tor/TorNotificationManager.java index a2401732..8148fd94 100644 --- a/app/src/main/java/se/leap/bitmaskclient/tor/TorNotificationManager.java +++ b/app/src/main/java/se/leap/bitmaskclient/tor/TorNotificationManager.java @@ -50,7 +50,7 @@ public class TorNotificationManager { .setContentText(context.getString(R.string.tor_started)).build(); } - public void buildTorNotification(Context context, String state) { + public void buildTorNotification(Context context, String state, String message, int progress) { NotificationManager notificationManager = initNotificationManager(context); if (notificationManager == null) { return; @@ -59,8 +59,15 @@ public class TorNotificationManager { notificationBuilder .setSmallIcon(R.drawable.ic_bridge_36) .setWhen(System.currentTimeMillis()) - .setTicker(state) - .setContentText(state); + .setStyle(new NotificationCompat.BigTextStyle(). + setBigContentTitle(state). + bigText(message)) + .setTicker(message) + .setContentTitle(state) + .setContentText(message); + if (progress > 0) { + notificationBuilder.setProgress(100, progress, false); + } notificationManager.notify(TOR_SERVICE_NOTIFICATION_ID, notificationBuilder.build()); } diff --git a/app/src/main/java/se/leap/bitmaskclient/tor/TorStatusObservable.java b/app/src/main/java/se/leap/bitmaskclient/tor/TorStatusObservable.java index e806e441..11baecbf 100644 --- a/app/src/main/java/se/leap/bitmaskclient/tor/TorStatusObservable.java +++ b/app/src/main/java/se/leap/bitmaskclient/tor/TorStatusObservable.java @@ -8,6 +8,7 @@ import androidx.annotation.NonNull; import androidx.annotation.Nullable; import java.util.Observable; +import java.util.Vector; import se.leap.bitmaskclient.R; @@ -28,6 +29,8 @@ public class TorStatusObservable extends Observable { private final TorNotificationManager torNotificationManager; private String lastError; private int port = -1; + private int bootstrapPercent = -1; + private Vector lastLogs = new Vector<>(100); private TorStatusObservable() { torNotificationManager = new TorNotificationManager(); @@ -44,25 +47,93 @@ public class TorStatusObservable extends Observable { return getInstance().status; } + public static void logMessage(Context context, String tag, String message) { + Log.d(tag, message); + addLog(message); + if (getInstance().status != TorStatus.OFF) { + getInstance().torNotificationManager.buildTorNotification(context, getStringForCurrentStatus(context), message, getInstance().bootstrapPercent); + } + instance.setChanged(); + instance.notifyObservers(); + } + + private static void addLog(String message) { + if (instance.lastLogs.size() > 100) { + instance.lastLogs.remove(0); + } + instance.lastLogs.add(message); + } public static void updateState(Context context, String status) { + updateState(context,status, -1, null); + } + + public static void updateState(Context context, String status, int bootstrapPercent, @Nullable String logKey) { try { - Log.d(TAG, "update tor state: " + status); + Log.d(TAG, "update tor state: " + status + " " + bootstrapPercent + " "+ logKey); getInstance().status = TorStatus.valueOf(status); + if (bootstrapPercent != -1) { + getInstance().bootstrapPercent = bootstrapPercent; + } + int progress = getInstance().status == TorStatus.STARTING ? getInstance().bootstrapPercent : -1; + + if (getInstance().status == TorStatus.OFF) { getInstance().torNotificationManager.cancelNotifications(context); + } else if (logKey != null) { + String log = getStringFor(context, logKey); + addLog(log); + getInstance().torNotificationManager.buildTorNotification(context, getStringForCurrentStatus(context), log, progress); } else { - getInstance().torNotificationManager.buildTorNotification(context, getStringForCurrentStatus(context)); + String log = instance.lastLogs.size() > 0 ? instance.lastLogs.lastElement() : ""; + getInstance().torNotificationManager.buildTorNotification(context, getStringForCurrentStatus(context), log, progress); } + instance.setChanged(); instance.notifyObservers(); - } catch (IllegalStateException e) { e.printStackTrace(); } } + private static String getStringFor(Context context, String key) { + switch (key) { + case "conn_pt": + return context.getString(R.string.log_conn_pt); + case "conn_done_pt": + return context.getString(R.string.log_conn_done_pt); + case "conn_done": + return context.getString(R.string.log_conn_done); + case "handshake": + return context.getString(R.string.log_handshake); + case "handshake_done": + return context.getString(R.string.log_handshake_done); + case "onehop_create": + return context.getString(R.string.log_onehop_create); + case "requesting_status": + return context.getString(R.string.log_requesting_status); + case "loading_status": + return context.getString(R.string.log_loading_status); + case "loading_keys": + return context.getString(R.string.log_loading_keys); + case "requesting_descriptors": + return context.getString(R.string.log_requesting_desccriptors); + case "loading_descriptors": + return context.getString(R.string.log_loading_descriptors); + case "enough_dirinfo": + return context.getString(R.string.log_enough_dirinfo); + case "ap_handshake_done": + return context.getString(R.string.log_ap_handshake_done); + case "circuit_create": + return context.getString(R.string.log_circuit_create); + case "done": + return context.getString(R.string.log_done); + default: + return key; + } + } + public static void setLastError(String error) { getInstance().lastError = error; instance.setChanged(); diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 7c0e6334..dfb0db0e 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -155,8 +155,24 @@ Automatic Your traffic is currently routed through: - Starting bridges for censorship circumvention. Please hold on… + Starting bridges for censorship circumvention… Stopping bridges. Using bridges for censorship circumvention. + Connected to pluggable transport + Connecting to pluggable transport + Connected to a relay + Handshaking with a relay + Handshake with a relay done + Establishing an encrypted directory connection + Asking for networkstatus consensus + Loading networkstatus consensus + Loading authority key certs + Asking for relay descriptors + Loading relay descriptors + Loaded enough directory info to build circuits + Handshake finished with a relay to build circuits + Establishing a Tor circuit + Done! + -- cgit v1.2.3