[tor-commits] [tor-browser/tor-browser-68.1.0esr-9.0-1] Bug 28051 - Integrate Orbot and add dependencies

gk at torproject.org gk at torproject.org
Sat Aug 31 19:46:16 UTC 2019


commit a627afad7b69ff3757fb791921d78281ad94c68b
Author: Matthew Finkel <Matthew.Finkel at gmail.com>
Date:   Wed Nov 14 17:36:53 2018 +0000

    Bug 28051 - Integrate Orbot and add dependencies
    
    Also:
    Bug 28051 - Launch Orbot if it isn't running in the background
    
    Bug 28329 - Part 2. Implement checking if the Tor service is running
    
    Bug 28329 - Part 3. Remove OrbotActivity dependency
    
    Bug 28051 - Stop the background service when we're quitting
    
    If the user swips away the app, then initiate quitting as if the user
    selected Quit from the menu.
---
 build.gradle                                       |   4 +
 mobile/android/app/build.gradle                    |  13 ++
 mobile/android/base/AndroidManifest.xml.in         |   8 ++
 .../base/java/org/mozilla/gecko/BrowserApp.java    | 142 +++++++++++++++++++++
 .../base/java/org/mozilla/gecko/GeckoApp.java      |  10 ++
 .../java/org/mozilla/gecko/GeckoApplication.java   |   5 +
 mobile/android/config/proguard/proguard.cfg        |  14 ++
 7 files changed, 196 insertions(+)

diff --git a/build.gradle b/build.gradle
index 8b91888b5d7f..95dfc2ed1323 100644
--- a/build.gradle
+++ b/build.gradle
@@ -32,6 +32,10 @@ allprojects {
                 url repository
             }
         }
+        // These are needed for Orbot's dependencies
+        maven { url "https://raw.githubusercontent.com/guardianproject/gpmaven/master" }
+        maven { url 'https://jitpack.io' }
+        jcenter()
     }
 
     task downloadDependencies() {
diff --git a/mobile/android/app/build.gradle b/mobile/android/app/build.gradle
index c6a0bc45d56f..be0ccdb1b13f 100644
--- a/mobile/android/app/build.gradle
+++ b/mobile/android/app/build.gradle
@@ -235,6 +235,14 @@ dependencies {
     // to generate the `Application` class or fork the file on disk.
     implementation "com.android.support:multidex:1.0.3"
 
+    // tor-android-services
+    implementation files('service-release.aar')
+    implementation files('jsocksAndroid-release.aar')
+
+    // Tor_Onion_Proxy_Library
+    implementation files('universal-0.0.3.jar')
+    implementation files('android-release.aar')
+
     if (mozconfig.substs.MOZ_NATIVE_DEVICES) {
         implementation "com.android.support:mediarouter-v7:$support_library_version"
         implementation "com.google.android.gms:play-services-basement:$google_play_services_version"
@@ -277,6 +285,11 @@ dependencies {
 
     // Including the Robotium JAR directly can cause issues with dexing.
     androidTestImplementation 'com.jayway.android.robotium:robotium-solo:5.5.4'
+
+    // tor-android-service Dependencies
+    implementation 'net.freehaven.tor.control:jtorctl:0.2'
+    implementation 'org.slf4j:slf4j-api:1.7.25'
+    implementation 'org.slf4j:slf4j-android:1.7.25'
 }
 
 // TODO: (bug 1261486): This impl is not robust -
diff --git a/mobile/android/base/AndroidManifest.xml.in b/mobile/android/base/AndroidManifest.xml.in
index 48809195dc57..c60210e0332c 100644
--- a/mobile/android/base/AndroidManifest.xml.in
+++ b/mobile/android/base/AndroidManifest.xml.in
@@ -572,5 +572,13 @@
         <meta-data android:name="com.google.android.gms.version" android:value="@integer/google_play_services_version" />
 #endif
 
+        <!-- Define Orbotservice's TorService -->
+        <service
+            android:name="org.torproject.android.service.TorService"
+            android:enabled="true"
+            android:exported="false"
+            android:stopWithTask="true">
+        </service>
+
     </application>
 </manifest>
diff --git a/mobile/android/base/java/org/mozilla/gecko/BrowserApp.java b/mobile/android/base/java/org/mozilla/gecko/BrowserApp.java
index 4123acca9bbe..e0ef8e9c43d9 100644
--- a/mobile/android/base/java/org/mozilla/gecko/BrowserApp.java
+++ b/mobile/android/base/java/org/mozilla/gecko/BrowserApp.java
@@ -10,11 +10,13 @@ import android.annotation.TargetApi;
 import android.app.Activity;
 import android.app.AlertDialog;
 import android.app.DownloadManager;
+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.ActivityInfo;
 import android.content.pm.PackageManager;
@@ -40,6 +42,8 @@ import android.support.annotation.StringRes;
 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;
@@ -176,6 +180,9 @@ import org.mozilla.geckoview.DynamicToolbarAnimator;
 import org.mozilla.geckoview.DynamicToolbarAnimator.PinReason;
 import org.mozilla.geckoview.GeckoSession;
 
+import org.torproject.android.service.TorService;
+import org.torproject.android.service.TorServiceConstants;
+
 import java.io.File;
 import java.io.FileNotFoundException;
 import java.io.IOException;
@@ -251,6 +258,8 @@ public class BrowserApp extends GeckoApp
     private HomeScreen mHomeScreen;
     private TabsPanel mTabsPanel;
 
+    private boolean mTorNeedsStart = true;
+
     private boolean showSplashScreen = false;
     private SplashScreen splashScreen;
     /**
@@ -1013,6 +1022,130 @@ public class BrowserApp extends GeckoApp
                 .buildAndShow();
     }
 
+    /**
+     * 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);
+    }
+
     private Class<?> getMediaPlayerManager() {
         if (AppConstants.MOZ_MEDIA_PLAYER) {
             try {
@@ -1124,6 +1257,13 @@ public class BrowserApp extends GeckoApp
         for (BrowserAppDelegate delegate : delegates) {
             delegate.onResume(this);
         }
+
+        // isInAutomation is overloaded with isTorBrowser(), but here we actually
+        // need to know if we are in automation.
+        final SafeIntent intent = new SafeIntent(getIntent());
+        if (!IntentUtils.getIsInAutomationFromEnvironment(intent)) {
+            mTorNeedsStart = !checkTorIsStarted();
+        }
     }
 
     @Override
@@ -1641,6 +1781,8 @@ public class BrowserApp extends GeckoApp
 
         MmaDelegate.flushResources(this);
 
+        mTorNeedsStart = true;
+
         super.onDestroy();
     }
 
diff --git a/mobile/android/base/java/org/mozilla/gecko/GeckoApp.java b/mobile/android/base/java/org/mozilla/gecko/GeckoApp.java
index c988923e960f..e01318dab422 100644
--- a/mobile/android/base/java/org/mozilla/gecko/GeckoApp.java
+++ b/mobile/android/base/java/org/mozilla/gecko/GeckoApp.java
@@ -100,6 +100,8 @@ import org.mozilla.geckoview.GeckoViewBridge;
 // SafeReceiver excluded at compile-time
 //import org.mozilla.mozstumbler.service.mainthread.SafeReceiver;
 
+import org.torproject.android.service.TorService;
+
 import java.io.File;
 import java.util.ArrayList;
 import java.util.HashMap;
@@ -623,6 +625,9 @@ public abstract class GeckoApp extends GeckoActivity
 
         EventDispatcher.getInstance().dispatch("Browser:Quit", res);
 
+        Intent torService = new Intent(this, TorService.class);
+        stopService(torService);
+
         // We don't call shutdown here because this creates a race condition which
         // can cause the clearing of private data to fail. Instead, we shut down the
         // UI only after we're done sanitizing.
@@ -2236,6 +2241,11 @@ public abstract class GeckoApp extends GeckoActivity
             GeckoApplication.shutdown(!mRestartOnShutdown ? null : new Intent(
                     Intent.ACTION_MAIN, /* uri */ null, getApplicationContext(), getClass()));
         }
+
+        if (isFinishing()) {
+            Log.i(LOGTAG, "onDestroy() is finishing.");
+            quitAndClear();
+        }
     }
 
     public void showSDKVersionError() {
diff --git a/mobile/android/base/java/org/mozilla/gecko/GeckoApplication.java b/mobile/android/base/java/org/mozilla/gecko/GeckoApplication.java
index dbd57d72ebc8..26e06b55ecfc 100644
--- a/mobile/android/base/java/org/mozilla/gecko/GeckoApplication.java
+++ b/mobile/android/base/java/org/mozilla/gecko/GeckoApplication.java
@@ -74,6 +74,8 @@ import java.lang.reflect.Method;
 import java.net.URL;
 import java.util.UUID;
 
+import org.torproject.android.service.util.Prefs;
+
 public class GeckoApplication extends Application
                               implements HapticFeedbackDelegate,
                                          SharedPreferences.OnSharedPreferenceChangeListener {
@@ -402,6 +404,9 @@ public class GeckoApplication extends Application
                 "Profile:Create",
                 null);
 
+        // Give Orbot the base Context
+        Prefs.setContext(context);
+
         super.onCreate();
     }
 
diff --git a/mobile/android/config/proguard/proguard.cfg b/mobile/android/config/proguard/proguard.cfg
index 175ec85518d9..711e66c4bfc6 100644
--- a/mobile/android/config/proguard/proguard.cfg
+++ b/mobile/android/config/proguard/proguard.cfg
@@ -170,6 +170,20 @@
 -dontwarn java.lang.management.**
 -dontwarn javax.management.**
 
+# XXX 68rebase Are these still needed?
+# From https://github.com/square/okhttp/blob/master/okhttp/src/main/resources/META-INF/proguard/okhttp3.pro
+# JSR 305 annotations are for embedding nullability information.
+-dontwarn javax.annotation.**
+
+# A resource is loaded with a relative path so the package of this class must be preserved.
+-keepnames class okhttp3.internal.publicsuffix.PublicSuffixDatabase
+
+# Animal Sniffer compileOnly dependency to ensure APIs are compatible with older versions of Java.
+-dontwarn org.codehaus.mojo.animal_sniffer.*
+
+# OkHttp platform used only on JVM and when Conscrypt dependency is available.
+-dontwarn okhttp3.internal.platform.ConscryptPlatform
+
 -include "adjust-keeps.cfg"
 
 -include "leakcanary-keeps.cfg"





More information about the tor-commits mailing list