Browse Source

Merge branch 'master' of https://github.com/Psiphon-Labs/psiphon-tunnel-core

Rod Hynes 6 years ago
parent
commit
a71952ba08

+ 11 - 3
MobileLibrary/Android/README.md

@@ -61,7 +61,7 @@ When that command completes, the compiled `.aar` files (suitable for use in an A
 repositories {
     ...
     maven {
-        url "https://raw.github.com/Psiphon-Labs/psiphon-tunnel-core-Android-library/master/releases"
+        url "https://raw.github.com/Psiphon-Labs/psiphon-tunnel-core-Android-library/master"
     }
 }
 ```
@@ -69,13 +69,21 @@ then add PsiphonTunnel dependency like following
 ```
 dependencies {
     ...
-    implementation 'ca.psiphon:psiphontunnel:1.0.7'
+    implementation 'ca.psiphon:psiphontunnel:2.0.2'
 }
 ```
-Where 1.0.7 is the target version. Latest available release version can be found at https://github.com/Psiphon-Labs/psiphon-tunnel-core-Android-library
+Where 2.0.2 is the target version. Latest available release version can be found at https://github.com/Psiphon-Labs/psiphon-tunnel-core-Android-library
 
 See example usage in [TunneledWebView sample app](./SampleApps/TunneledWebView/README.md)
 
+---
+
+**NOTE**
+
+The maven repo at `https://raw.github.com/Psiphon-Labs/psiphon-tunnel-core-Android-library/master/releases` which contains releases up to v2.0.2 is deprecated and will not be updated. All new releases starting with v2.0.2 will be deployed to maven repo at  `https://raw.github.com/Psiphon-Labs/psiphon-tunnel-core-Android-library/master`
+
+---
+
 ##### Limitations
 
  - Only supports one concurrent instance of Psiphon.

+ 3 - 0
MobileLibrary/Android/SampleApps/TunneledWebView/.idea/gradle.xml

@@ -3,6 +3,9 @@
   <component name="GradleSettings">
     <option name="linkedExternalProjectsSettings">
       <GradleProjectSettings>
+        <compositeConfiguration>
+          <compositeBuild compositeDefinitionSource="SCRIPT" />
+        </compositeConfiguration>
         <option name="distributionType" value="DEFAULT_WRAPPED" />
         <option name="externalProjectPath" value="$PROJECT_DIR$" />
         <option name="gradleHome" value="$APPLICATION_HOME_DIR$/gradle/gradle-2.4" />

+ 14 - 3
MobileLibrary/Android/SampleApps/TunneledWebView/.idea/misc.xml

@@ -5,26 +5,37 @@
     <option name="myDefaultNotNull" value="android.support.annotation.NonNull" />
     <option name="myNullables">
       <value>
-        <list size="4">
+        <list size="10">
           <item index="0" class="java.lang.String" itemvalue="org.jetbrains.annotations.Nullable" />
           <item index="1" class="java.lang.String" itemvalue="javax.annotation.Nullable" />
           <item index="2" class="java.lang.String" itemvalue="edu.umd.cs.findbugs.annotations.Nullable" />
           <item index="3" class="java.lang.String" itemvalue="android.support.annotation.Nullable" />
+          <item index="4" class="java.lang.String" itemvalue="javax.annotation.CheckForNull" />
+          <item index="5" class="java.lang.String" itemvalue="androidx.annotation.Nullable" />
+          <item index="6" class="java.lang.String" itemvalue="androidx.annotation.RecentlyNullable" />
+          <item index="7" class="java.lang.String" itemvalue="org.checkerframework.checker.nullness.qual.Nullable" />
+          <item index="8" class="java.lang.String" itemvalue="org.checkerframework.checker.nullness.compatqual.NullableDecl" />
+          <item index="9" class="java.lang.String" itemvalue="org.checkerframework.checker.nullness.compatqual.NullableType" />
         </list>
       </value>
     </option>
     <option name="myNotNulls">
       <value>
-        <list size="4">
+        <list size="9">
           <item index="0" class="java.lang.String" itemvalue="org.jetbrains.annotations.NotNull" />
           <item index="1" class="java.lang.String" itemvalue="javax.annotation.Nonnull" />
           <item index="2" class="java.lang.String" itemvalue="edu.umd.cs.findbugs.annotations.NonNull" />
           <item index="3" class="java.lang.String" itemvalue="android.support.annotation.NonNull" />
+          <item index="4" class="java.lang.String" itemvalue="androidx.annotation.NonNull" />
+          <item index="5" class="java.lang.String" itemvalue="androidx.annotation.RecentlyNonNull" />
+          <item index="6" class="java.lang.String" itemvalue="org.checkerframework.checker.nullness.qual.NonNull" />
+          <item index="7" class="java.lang.String" itemvalue="org.checkerframework.checker.nullness.compatqual.NonNullDecl" />
+          <item index="8" class="java.lang.String" itemvalue="org.checkerframework.checker.nullness.compatqual.NonNullType" />
         </list>
       </value>
     </option>
   </component>
-  <component name="ProjectRootManager" version="2" languageLevel="JDK_1_8" project-jdk-name="1.8" project-jdk-type="JavaSDK">
+  <component name="ProjectRootManager" version="2" languageLevel="JDK_1_8" project-jdk-name="JDK" project-jdk-type="JavaSDK">
     <output url="file://$PROJECT_DIR$/build/classes" />
   </component>
   <component name="ProjectType">

+ 9 - 5
MobileLibrary/Android/SampleApps/TunneledWebView/app/build.gradle

@@ -1,15 +1,14 @@
 apply plugin: 'com.android.application'
 
 android {
-    compileSdkVersion 26
-    buildToolsVersion '26.0.3'
+    compileSdkVersion 28
     useLibrary 'org.apache.http.legacy'
 
 
     defaultConfig {
         applicationId "ca.psiphon.tunneledwebview"
         minSdkVersion 15
-        targetSdkVersion 26
+        targetSdkVersion 28
         versionCode 1
         versionName "1.0"
     }
@@ -19,6 +18,10 @@ android {
             proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
         }
     }
+    compileOptions {
+        sourceCompatibility = '1.8'
+        targetCompatibility = '1.8'
+    }
 }
 
 repositories {
@@ -26,7 +29,7 @@ repositories {
         dirs 'libs'
     }
     maven {
-        url "https://raw.github.com/Psiphon-Labs/psiphon-tunnel-core-Android-library/master/releases"
+        url "https://raw.github.com/Psiphon-Labs/psiphon-tunnel-core-Android-library/master"
     }
 }
 
@@ -34,5 +37,6 @@ dependencies {
     implementation fileTree(dir: 'libs', include: ['*.jar'])
     testImplementation 'junit:junit:4.12'
     implementation 'com.android.support:appcompat-v7:26.1.0'
-    implementation 'ca.psiphon:psiphontunnel:1.0.7'
+    // always specify exact library version in your real project to avoid non-deterministic builds
+    implementation 'ca.psiphon:psiphontunnel:2.+'
 }

+ 52 - 50
MobileLibrary/Android/SampleApps/TunneledWebView/app/src/main/java/ca/psiphon/tunneledwebview/WebViewProxySettings.java

@@ -19,10 +19,45 @@ import java.lang.reflect.Constructor;
 import java.lang.reflect.Field;
 import java.lang.reflect.InvocationTargetException;
 import java.lang.reflect.Method;
+import java.util.ArrayList;
+import java.util.List;
 
 public class WebViewProxySettings 
 {
 
+    private static List<Object> getCurrentReceiversSet(Context ctx) {
+        Context appContext = ctx.getApplicationContext();
+        List<Object> receiversList = new ArrayList();
+
+        if (Build.VERSION.SDK_INT < Build.VERSION_CODES.KITKAT) {
+            return receiversList;
+        }
+
+        try {
+            Class applicationClass = Class.forName("android.app.Application");
+            Field mLoadedApkField = applicationClass.getDeclaredField("mLoadedApk");
+            mLoadedApkField.setAccessible(true);
+            Object mloadedApk = mLoadedApkField.get(appContext);
+            Class loadedApkClass = Class.forName("android.app.LoadedApk");
+            Field mReceiversField = loadedApkClass.getDeclaredField("mReceivers");
+            mReceiversField.setAccessible(true);
+            ArrayMap receivers = (ArrayMap) mReceiversField.get(mloadedApk);
+            for (Object receiverMap : receivers.values()) {
+                for (Object receiver : ((ArrayMap) receiverMap).keySet()) {
+                    if (receiver == null) {
+                        continue;
+                    }
+                    receiversList.add(receiver);
+                }
+            }
+        } catch (ClassNotFoundException e) {
+        } catch (NoSuchFieldException e) {
+        } catch (IllegalAccessException e) {
+        }
+
+        return receiversList;
+    }
+
     public static void setLocalProxy(Context ctx, int port)
     {
         setProxy(ctx, "localhost", port);
@@ -131,36 +166,22 @@ public class WebViewProxySettings
         System.setProperty("https.proxyPort", port + "");
         try
         {
-            Class applicationClass = Class.forName("android.app.Application");
-            Field loadedApkField = applicationClass.getDeclaredField("mLoadedApk");
-            loadedApkField.setAccessible(true);
-            Object loadedApk = loadedApkField.get(appContext);
-            Class loadedApkClass = Class.forName("android.app.LoadedApk");
-            Field receiversField = loadedApkClass.getDeclaredField("mReceivers");
-            receiversField.setAccessible(true);
-            ArrayMap receivers = (ArrayMap) receiversField.get(loadedApk);
-            for (Object receiverMap : receivers.values())
+            for (Object receiver : getCurrentReceiversSet(appContext))
             {
-                for (Object receiver : ((ArrayMap) receiverMap).keySet())
+                Class receiverClass = receiver.getClass();
+                if (receiverClass.getName().contains("ProxyChangeListener"))
                 {
-                    if (receiver == null) {
-                        continue;
-                    }
-                    Class receiverClass = receiver.getClass();
-                    if (receiverClass.getName().contains("ProxyChangeListener"))
-                    {
-                        Method onReceiveMethod = receiverClass.getDeclaredMethod("onReceive", Context.class, Intent.class);
-                        Intent intent = new Intent(Proxy.PROXY_CHANGE_ACTION);
+                    Method onReceiveMethod = receiverClass.getDeclaredMethod("onReceive", Context.class, Intent.class);
+                    Intent intent = new Intent(Proxy.PROXY_CHANGE_ACTION);
 
-                        final String CLASS_NAME = "android.net.ProxyProperties";
-                        Class proxyPropertiesClass = Class.forName(CLASS_NAME);
-                        Constructor constructor = proxyPropertiesClass.getConstructor(String.class, Integer.TYPE, String.class);
-                        constructor.setAccessible(true);
-                        Object proxyProperties = constructor.newInstance(host, port, null);
-                        intent.putExtra("proxy", (Parcelable) proxyProperties);
+                    final String CLASS_NAME = "android.net.ProxyProperties";
+                    Class proxyPropertiesClass = Class.forName(CLASS_NAME);
+                    Constructor constructor = proxyPropertiesClass.getConstructor(String.class, Integer.TYPE, String.class);
+                    constructor.setAccessible(true);
+                    Object proxyProperties = constructor.newInstance(host, port, null);
+                    intent.putExtra("proxy", (Parcelable) proxyProperties);
 
-                        onReceiveMethod.invoke(receiver, appContext, intent);
-                    }
+                    onReceiveMethod.invoke(receiver, appContext, intent);
                 }
             }
             return true;
@@ -168,9 +189,6 @@ public class WebViewProxySettings
         catch (ClassNotFoundException e)
         {
         }
-        catch (NoSuchFieldException e)
-        {
-        }
         catch (IllegalAccessException e)
         {
         }
@@ -199,26 +217,13 @@ public class WebViewProxySettings
         System.setProperty("https.proxyHost", host);
         System.setProperty("https.proxyPort", port + "");
         try {
-            Class applictionClass = Class.forName("android.app.Application");
-            Field mLoadedApkField = applictionClass.getDeclaredField("mLoadedApk");
-            mLoadedApkField.setAccessible(true);
-            Object mloadedApk = mLoadedApkField.get(appContext);
-            Class loadedApkClass = Class.forName("android.app.LoadedApk");
-            Field mReceiversField = loadedApkClass.getDeclaredField("mReceivers");
-            mReceiversField.setAccessible(true);
-            ArrayMap receivers = (ArrayMap) mReceiversField.get(mloadedApk);
-            for (Object receiverMap : receivers.values())
+            for (Object receiver : getCurrentReceiversSet(appContext))
             {
-                for (Object receiver : ((ArrayMap) receiverMap).keySet())
+                Class receiverClass = receiver.getClass();
+                String receiverName = receiverClass.getCanonicalName();
+                if (receiverName != null && receiverName.contains("ProxyChangeListener"))
                 {
-                    if (receiver == null) {
-                        continue;
-                    }
-                    Class clazz = receiver.getClass();
-                    // NOTE: as of Chrome 67 the ProxyChangeListener now has an obfuscated name,
-                    // so we are unable to identify the receiver by name. Instead we'll send the
-                    // PROXY_CHANGE intent to all receivers.
-                    Method onReceiveMethod = clazz.getDeclaredMethod("onReceive", Context.class, Intent.class);
+                    Method onReceiveMethod = receiverClass.getDeclaredMethod("onReceive", Context.class, Intent.class);
                     Intent intent = new Intent(Proxy.PROXY_CHANGE_ACTION);
                     
                     final String CLASS_NAME = "android.net.ProxyInfo";
@@ -240,9 +245,6 @@ public class WebViewProxySettings
         catch (ClassNotFoundException e)
         {
         }
-        catch (NoSuchFieldException e)
-        {
-        }
         catch (IllegalAccessException e)
         {
         }

+ 1 - 1
MobileLibrary/Android/SampleApps/TunneledWebView/build.gradle

@@ -6,7 +6,7 @@ buildscript {
         google()
     }
     dependencies {
-        classpath 'com.android.tools.build:gradle:3.0.1'
+        classpath 'com.android.tools.build:gradle:3.4.1'
 
         // NOTE: Do not place your application dependencies here; they belong
         // in the individual module build.gradle files

+ 2 - 2
MobileLibrary/Android/SampleApps/TunneledWebView/gradle/wrapper/gradle-wrapper.properties

@@ -1,6 +1,6 @@
-#Wed Jul 11 15:09:35 EDT 2018
+#Mon May 27 17:09:45 EDT 2019
 distributionBase=GRADLE_USER_HOME
 distributionPath=wrapper/dists
 zipStoreBase=GRADLE_USER_HOME
 zipStorePath=wrapper/dists
-distributionUrl=https\://services.gradle.org/distributions/gradle-4.4-all.zip
+distributionUrl=https\://services.gradle.org/distributions/gradle-5.1.1-all.zip