summaryrefslogtreecommitdiff
path: root/app/src/main/java/se/leap/bitmaskclient/tor
diff options
context:
space:
mode:
authorcyBerta <cyberta@riseup.net>2021-06-23 03:27:17 +0200
committercyBerta <cyberta@riseup.net>2021-07-21 22:02:24 +0200
commitfe6a0e47121d17d08c7d913f1db086687a569446 (patch)
tree0b37235a33c490647f6222d5f1cd6072abc34506 /app/src/main/java/se/leap/bitmaskclient/tor
parent571c0479f7400e56cfdb27408160d8a816cc8610 (diff)
initial tor-integration to circumvent blocking attempts of the provider api
Diffstat (limited to 'app/src/main/java/se/leap/bitmaskclient/tor')
-rw-r--r--app/src/main/java/se/leap/bitmaskclient/tor/TorNotificationManager.java105
-rw-r--r--app/src/main/java/se/leap/bitmaskclient/tor/TorStatusObservable.java102
2 files changed, 207 insertions, 0 deletions
diff --git a/app/src/main/java/se/leap/bitmaskclient/tor/TorNotificationManager.java b/app/src/main/java/se/leap/bitmaskclient/tor/TorNotificationManager.java
new file mode 100644
index 00000000..71a2735c
--- /dev/null
+++ b/app/src/main/java/se/leap/bitmaskclient/tor/TorNotificationManager.java
@@ -0,0 +1,105 @@
+package se.leap.bitmaskclient.tor;
+/**
+ * Copyright (c) 2021 LEAP Encryption Access Project and contributers
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+import android.annotation.TargetApi;
+import android.app.Notification;
+import android.app.NotificationChannel;
+import android.app.NotificationManager;
+import android.content.Context;
+import android.os.Build;
+
+import androidx.annotation.NonNull;
+import androidx.core.app.NotificationCompat;
+
+import se.leap.bitmaskclient.R;
+
+public class TorNotificationManager {
+ public final static int TOR_SERVICE_NOTIFICATION_ID = 10;
+ static final String NOTIFICATION_CHANNEL_NEWSTATUS_ID = "bitmask_tor_service_news";
+
+
+ public TorNotificationManager() {}
+
+
+ public static Notification buildTorForegroundNotification(Context context) {
+ NotificationManager notificationManager = initNotificationManager(context);
+ if (notificationManager == null) {
+ return null;
+ }
+ NotificationCompat.Builder notificationBuilder = initNotificationBuilderDefaults(context);
+ return notificationBuilder
+ .setSmallIcon(R.drawable.ic_bridge_36)
+ .setWhen(System.currentTimeMillis())
+ .setContentTitle("Using Bridges to configure provider.").build();
+ }
+
+ public void buildTorNotification(Context context, String state) {
+ NotificationManager notificationManager = initNotificationManager(context);
+ if (notificationManager == null) {
+ return;
+ }
+ NotificationCompat.Builder notificationBuilder = initNotificationBuilderDefaults(context);
+ notificationBuilder
+ .setSmallIcon(R.drawable.ic_bridge_36)
+ .setWhen(System.currentTimeMillis())
+ .setTicker(state)
+ .setContentTitle(context.getString(R.string.tor_provider_setup))
+ .setContentText(state);
+ notificationManager.notify(TOR_SERVICE_NOTIFICATION_ID, notificationBuilder.build());
+ }
+
+
+ private static NotificationManager initNotificationManager(Context context) {
+ NotificationManager notificationManager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
+ if (notificationManager == null) {
+ return null;
+ }
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
+ createNotificationChannel(notificationManager);
+ }
+ return notificationManager;
+ }
+
+ @TargetApi(26)
+ private static void createNotificationChannel(NotificationManager notificationManager) {
+ CharSequence name = "Bitmask Tor Service";
+ String description = "Informs about usage of bridges to configure Bitmask.";
+ NotificationChannel channel = new NotificationChannel(NOTIFICATION_CHANNEL_NEWSTATUS_ID,
+ name,
+ NotificationManager.IMPORTANCE_LOW);
+ channel.setSound(null, null);
+ channel.setDescription(description);
+ notificationManager.createNotificationChannel(channel);
+ }
+
+ private static NotificationCompat.Builder initNotificationBuilderDefaults(Context context) {
+ NotificationCompat.Builder notificationBuilder = new NotificationCompat.Builder(context, NOTIFICATION_CHANNEL_NEWSTATUS_ID);
+ notificationBuilder.
+ setDefaults(Notification.DEFAULT_ALL).
+ setAutoCancel(true);
+ return notificationBuilder;
+ }
+
+ public void cancelNotifications(Context context) {
+ NotificationManager notificationManager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
+ if (notificationManager == null) {
+ return;
+ }
+ notificationManager.cancel(TOR_SERVICE_NOTIFICATION_ID);
+ }
+}
diff --git a/app/src/main/java/se/leap/bitmaskclient/tor/TorStatusObservable.java b/app/src/main/java/se/leap/bitmaskclient/tor/TorStatusObservable.java
new file mode 100644
index 00000000..ed4ae24b
--- /dev/null
+++ b/app/src/main/java/se/leap/bitmaskclient/tor/TorStatusObservable.java
@@ -0,0 +1,102 @@
+package se.leap.bitmaskclient.tor;
+
+import android.content.Context;
+import android.os.Handler;
+import android.util.Log;
+
+import androidx.annotation.NonNull;
+import androidx.annotation.Nullable;
+
+import java.util.Observable;
+
+import se.leap.bitmaskclient.R;
+
+public class TorStatusObservable extends Observable {
+
+ private static final String TAG = TorStatusObservable.class.getSimpleName();
+
+ public enum TorStatus {
+ ON,
+ OFF,
+ STARTING,
+ STOPPING,
+ UNKOWN
+ }
+
+ private static TorStatusObservable instance;
+ private TorStatus status = TorStatus.UNKOWN;
+ private final TorNotificationManager torNotificationManager;
+ private String lastError;
+ private int port = -1;
+
+ private TorStatusObservable() {
+ torNotificationManager = new TorNotificationManager();
+ }
+
+ public static TorStatusObservable getInstance() {
+ if (instance == null) {
+ instance = new TorStatusObservable();
+ }
+ return instance;
+ }
+
+ public static TorStatus getStatus() {
+ return getInstance().status;
+ }
+
+
+ public static void updateState(Context context, String status) {
+ try {
+ Log.d(TAG, "update tor state: " + status);
+ getInstance().status = TorStatus.valueOf(status);
+ if (getInstance().status == TorStatus.OFF) {
+ getInstance().torNotificationManager.cancelNotifications(context);
+ } else {
+ getInstance().torNotificationManager.buildTorNotification(context, getStringForCurrentStatus(context));
+ }
+ instance.setChanged();
+ instance.notifyObservers();
+
+
+ } catch (IllegalStateException e) {
+ e.printStackTrace();
+ }
+ }
+
+ public static void setLastError(String error) {
+ getInstance().lastError = error;
+ instance.setChanged();
+ instance.notifyObservers();
+ }
+
+ public static void setProxyPort(int port) {
+ getInstance().port = port;
+ instance.setChanged();
+ instance.notifyObservers();
+ }
+
+ public static int getProxyPort() {
+ return getInstance().port;
+ }
+
+
+ @Nullable
+ public String getLastError() {
+ return lastError;
+ }
+
+ private static String getStringForCurrentStatus(Context context) {
+ switch (getInstance().status) {
+ case ON:
+ return context.getString(R.string.tor_started);
+ case STARTING:
+ return context.getString(R.string.tor_starting);
+ case STOPPING:
+ return context.getString(R.string.tor_stopping);
+ case OFF:
+ case UNKOWN:
+ break;
+ }
+ return null;
+ }
+}