From ea325734e62822d38c1c858ee56dea30b5941038 Mon Sep 17 00:00:00 2001 From: Hans-Christoph Steiner Date: Tue, 1 Sep 2015 20:49:27 +0200 Subject: [PATCH] Orfox: add BroadcastReceiver to receive Tor status from Orbot Run in thread so Tor status updates will be received while the Gecko event sync is blocking the main thread. This might not be the best approach since it probably means that the main UI will be frozen waiting for Tor to reach ON status. Queue URL Intents events when Orbot is not yet started Instead of failing when opening a URL and Tor is not ready, queue those Intents, then send them once we get STATUS_ON from Orbot. Signed-off-by: Amogh Pradeep --- .../java/org/mozilla/gecko/BrowserApp.java | 32 +++++++++++++++++++ .../java/org/mozilla/gecko/GeckoAppShell.java | 32 +++++++++++++++++++ 2 files changed, 64 insertions(+) diff --git a/mobile/android/base/java/org/mozilla/gecko/BrowserApp.java b/mobile/android/base/java/org/mozilla/gecko/BrowserApp.java index 8d5bbddabc885..3cc087e666222 100644 --- a/mobile/android/base/java/org/mozilla/gecko/BrowserApp.java +++ b/mobile/android/base/java/org/mozilla/gecko/BrowserApp.java @@ -13,11 +13,13 @@ import android.app.DownloadManager; import android.app.Notification; import android.app.NotificationManager; import android.app.PendingIntent; +import android.content.BroadcastReceiver; import android.content.ContentProviderClient; import android.content.ContentResolver; import android.content.Context; import android.content.DialogInterface; import android.content.Intent; +import android.content.IntentFilter; import android.content.SharedPreferences; import android.content.pm.PackageManager; import android.content.pm.ResolveInfo; @@ -35,6 +37,9 @@ import android.nfc.NfcEvent; import android.os.Build; import android.os.Bundle; import android.os.Environment; +import android.os.Handler; +import android.os.HandlerThread; +import android.os.Looper; import android.os.Parcel; import android.os.Parcelable; import android.os.StrictMode; @@ -1273,6 +1278,16 @@ public class BrowserApp extends GeckoApp } } + private BroadcastReceiver torStatusReceiver = new BroadcastReceiver() { + + @Override + public void onReceive(Context context, Intent intent) { + if (TextUtils.equals(intent.getAction(), OrbotHelper.ACTION_STATUS)) { + GeckoAppShell.setTorStatus(intent); + } + } + }; + public void checkStartOrbot() { if (!OrbotHelper.isOrbotInstalled(this)) { final Intent installOrbotIntent = OrbotHelper.getOrbotInstallIntent(this); @@ -1293,6 +1308,14 @@ public class BrowserApp extends GeckoApp }); builder.show(); } else { + /* run in thread so Tor status updates will be received while the + * Gecko event sync is blocking the main thread */ + HandlerThread handlerThread = new HandlerThread("torStatusReceiver"); + handlerThread.start(); + Looper looper = handlerThread.getLooper(); + Handler handler = new Handler(looper); + registerReceiver(torStatusReceiver, new IntentFilter(OrbotHelper.ACTION_STATUS), + null, handler); OrbotHelper.requestStartTor(this); } } @@ -1335,6 +1358,15 @@ public class BrowserApp extends GeckoApp for (BrowserAppDelegate delegate : delegates) { delegate.onPause(this); } + + if (torStatusReceiver != null) + { + try { + unregisterReceiver(torStatusReceiver); + } catch (IllegalArgumentException e) { + Log.w(LOGTAG, "Tor status receiver couldn't be unregistered", e); + } + } } @Override diff --git a/mobile/android/geckoview/src/main/java/org/mozilla/gecko/GeckoAppShell.java b/mobile/android/geckoview/src/main/java/org/mozilla/gecko/GeckoAppShell.java index 7dbb286cae040..f67603f853e26 100644 --- a/mobile/android/geckoview/src/main/java/org/mozilla/gecko/GeckoAppShell.java +++ b/mobile/android/geckoview/src/main/java/org/mozilla/gecko/GeckoAppShell.java @@ -18,10 +18,13 @@ import java.net.Proxy; import java.net.URLConnection; import java.nio.ByteBuffer; import java.util.ArrayList; +import java.util.concurrent.ConcurrentLinkedQueue; import java.util.Iterator; import java.util.List; import java.util.Locale; import java.util.Map; +import java.util.NoSuchElementException; +import java.util.Queue; import java.util.StringTokenizer; import java.util.TreeMap; @@ -39,6 +42,8 @@ import org.mozilla.gecko.util.ProxySelector; import org.mozilla.gecko.util.ThreadUtils; import org.mozilla.geckoview.BuildConfig; +import info.guardianproject.netcipher.proxy.OrbotHelper; + import android.Manifest; import android.annotation.SuppressLint; import android.app.Activity; @@ -110,7 +115,11 @@ public class GeckoAppShell // We have static members only. private GeckoAppShell() { } + /* Initialize as STATUS_OFF */ + private static String sTorStatus = OrbotHelper.STATUS_OFF; + private static final CrashHandler CRASH_HANDLER = new CrashHandler() { + @Override protected String getAppPackageName() { final Context appContext = getAppContext(); @@ -200,6 +209,8 @@ public class GeckoAppShell static private int sDensityDpi; static private int sScreenDepth; + static final Queue PENDING_URL_INTENTS = new ConcurrentLinkedQueue(); + /* Is the value in sVibrationEndTime valid? */ private static boolean sVibrationMaybePlaying; @@ -251,6 +262,16 @@ public class GeckoAppShell private static Rect sScreenSize; + static void sendPendingUrlIntents() { + try { + Context context = getApplicationContext(); + while (!PENDING_URL_INTENTS.isEmpty()) { + final Intent intent = PENDING_URL_INTENTS.poll(); + context.startActivity(intent); + } + } catch (NoSuchElementException e) {} + } + @WrapForJNI(stubName = "NotifyObservers", dispatchTo = "gecko") private static native void nativeNotifyObservers(String topic, String data); @@ -1874,4 +1895,15 @@ public class GeckoAppShell public static String getDefaultLocale() { return Locale.getDefault().toString(); } + + public static void setTorStatus(Intent intent) { + sTorStatus = intent.getStringExtra(OrbotHelper.EXTRA_STATUS); + if (OrbotHelper.STATUS_ON.equals(sTorStatus)) { + sendPendingUrlIntents(); + } + } + + public static String getTorStatus() { + return sTorStatus; + } } -- GitLab