[tor-commits] [tor-browser/tor-browser-60.5.1esr-8.5-1] Bug 28329 - Part 2. Implement checking if the Tor service is running
gk at torproject.org
gk at torproject.org
Fri Mar 15 21:48:09 UTC 2019
commit a6e87093856101ec93bbeaf93eed22ac77031f73
Author: Matthew Finkel <Matthew.Finkel at gmail.com>
Date: Wed Feb 20 01:04:56 2019 +0000
Bug 28329 - Part 2. Implement checking if the Tor service is running
---
.../base/java/org/mozilla/gecko/BrowserApp.java | 130 +++++++++++++++++++++
1 file changed, 130 insertions(+)
diff --git a/mobile/android/base/java/org/mozilla/gecko/BrowserApp.java b/mobile/android/base/java/org/mozilla/gecko/BrowserApp.java
index 9330a6ba9838..5aa0a6a7f3ac 100644
--- a/mobile/android/base/java/org/mozilla/gecko/BrowserApp.java
+++ b/mobile/android/base/java/org/mozilla/gecko/BrowserApp.java
@@ -51,6 +51,7 @@ import android.support.design.widget.Snackbar;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.NotificationCompat;
+import android.support.v4.content.LocalBroadcastManager;
import android.support.v4.content.res.ResourcesCompat;
import android.support.v4.view.MenuItemCompat;
import android.text.TextUtils;
@@ -182,6 +183,7 @@ import org.mozilla.gecko.widget.SplashScreen;
import org.mozilla.geckoview.GeckoSession;
import org.torproject.android.OrbotMainActivity;
+import org.torproject.android.service.TorService;
import org.torproject.android.service.TorServiceConstants;
import java.io.File;
@@ -270,6 +272,7 @@ public class BrowserApp extends GeckoApp
private TabsPanel mTabsPanel;
private boolean mOrbotNeedsStart = true;
+ private boolean mTorNeedsStart = true;
private boolean showSplashScreen = false;
private SplashScreen splashScreen;
@@ -1079,6 +1082,131 @@ public class BrowserApp extends GeckoApp
}
/**
+ * Send the service a request for the current status.
+ * The response is sent as a broadcast. Capture that in
+ * receiveTorIsStartedAsync().
+ */
+ private void requestTorIsStartedAsync() {
+ Intent torServiceStatus = new Intent(this, TorService.class);
+ torServiceStatus.setAction(TorServiceConstants.ACTION_STATUS);
+ startService(torServiceStatus);
+ }
+
+ private BroadcastReceiver mLocalBroadcastReceiver;
+ private Boolean mTorStatus;
+
+ /**
+ * Setup the status receiver for broadcasts from the service.
+ * The response is sent as a broadcast. Create a background thread
+ * for receiving/handling the broadcast.
+ *
+ * This method is coupled with receiveTorIsStartedAsync(). They should
+ * be used together.
+ */
+ private BroadcastReceiver setupReceiveTorIsStartedAsync() {
+
+ // Create a thread specifically for defining the BroadcastReceiver
+ new Thread(new Runnable() {
+
+ @Override
+ public void run() {
+ mLocalBroadcastReceiver = new BroadcastReceiver() {
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ String action = intent.getAction();
+ if (action == null) {
+ return;
+ }
+
+ // We only want ACTION_STATUS messages
+ if (!action.equals(TorServiceConstants.ACTION_STATUS)) {
+ return;
+ }
+
+ // The current status has the EXTRA_STATUS key
+ String currentStatus =
+ intent.getStringExtra(TorServiceConstants.EXTRA_STATUS);
+
+ try {
+ synchronized (mTorStatus) {
+ mTorStatus = (currentStatus == TorServiceConstants.STATUS_ON);
+ mTorStatus.notify();
+ }
+ } catch (IllegalMonitorStateException e) {
+ // |synchronized| should prevent this
+ }
+ }
+ };
+
+ LocalBroadcastManager lbm = LocalBroadcastManager.getInstance(BrowserApp.this);
+ lbm.registerReceiver(mLocalBroadcastReceiver,
+ new IntentFilter(TorServiceConstants.ACTION_STATUS));
+
+ }
+ }).start();
+
+ return mLocalBroadcastReceiver;
+ }
+
+ /**
+ * Receive the current status from the service.
+ * The response is sent as a broadcast. If it is not received within
+ * 1 second, then return false.
+ *
+ * This method is coupled with setupReceiveTorIsStartedAsync(). They
+ * should be used together.
+ */
+ private boolean receiveTorIsStartedAsync(BroadcastReceiver mLocalBroadcastReceiver, Boolean torStatus) {
+ // Wait until we're notified from the above thread, or we're
+ // interrupted by the timeout.
+ try {
+ // One thousand milliseconds = one second
+ final long oneSecTimeout = Math.round(Math.pow(10, 3));
+ synchronized (torStatus) {
+ // We wake from wait() because we reached the one second
+ // timeout, the BroadcastReceiver notified us, or we received
+ // a spurious wakeup. For all three cases, we can accept the
+ // current value of torStatus.
+ torStatus.wait(oneSecTimeout);
+ }
+ } catch (InterruptedException e) {
+ // ignore.
+ } catch (IllegalArgumentException e) {
+ // oneSecTimeout should never be negative
+ } catch (IllegalMonitorStateException e) {
+ // |synchronized| should take care of this
+ }
+
+ // Unregister the receiver
+ LocalBroadcastManager.getInstance(this).unregisterReceiver(mLocalBroadcastReceiver);
+
+ return torStatus;
+ }
+
+ /**
+ * Receive the current Tor status.
+ *
+ * Send a request for the current status and receive the response.
+ * Returns true if Tor is running, false otherwise.
+ *
+ * mTorStatus provides synchronization across threads.
+ */
+ private boolean checkTorIsStarted() {
+ // When tor is started, true. Otherwise, false
+ mTorStatus = false;
+ BroadcastReceiver br = setupReceiveTorIsStartedAsync();
+ new Thread(new Runnable() {
+ @Override
+ public void run() {
+ requestTorIsStartedAsync();
+ }
+ }).start();
+
+ return receiveTorIsStartedAsync(br, mTorStatus);
+ }
+
+
+ /**
* Code to actually show the first run pager, separated
* for distribution purposes.
*/
@@ -1309,6 +1437,7 @@ public class BrowserApp extends GeckoApp
final SafeIntent intent = new SafeIntent(getIntent());
if (!IntentUtils.getIsInAutomationFromEnvironment(intent)) {
checkStartOrbot();
+ mTorNeedsStart = !checkTorIsStarted();
}
}
@@ -1763,6 +1892,7 @@ public class BrowserApp extends GeckoApp
GeckoNetworkManager.destroy();
mOrbotNeedsStart = true;
+ mTorNeedsStart = true;
super.onDestroy();
}
More information about the tor-commits
mailing list