summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorcyberta <cyberta@riseup.net>2024-01-25 23:41:42 +0000
committercyberta <cyberta@riseup.net>2024-01-25 23:41:42 +0000
commit5bf3f807a4804c18b7dc88e07e4e34ecf0791713 (patch)
treea092fd4ab72d1a31daa3cc442331cbb05d034ef0
parentce8106f60d83ee2a788f1920437a0bbd48d6b15f (diff)
parente84289ab4380ae61cc9f2a86da9a16d1aae45cbd (diff)
Merge branch 'post_release_work' into 'master'
post release tweaks and fixes Closes #9150 and #8983 See merge request leap/bitmask_android!264
-rw-r--r--.gitlab-ci.yml14
-rw-r--r--app/build.gradle16
-rw-r--r--app/externalDir1
-rw-r--r--app/src/androidTest/java/se/leap/bitmaskclient/BitmaskTest.java152
-rw-r--r--app/src/androidTest/java/se/leap/bitmaskclient/ProviderSetupTest.java118
-rw-r--r--app/src/androidTest/java/se/leap/bitmaskclient/base/ProviderBaseTest.java167
-rw-r--r--app/src/androidTest/java/se/leap/bitmaskclient/suite/ScreenshotTest.java (renamed from app/src/androidTestNormal/java/se/leap/bitmaskclient/suite/ScreenshotTest.java)4
-rw-r--r--app/src/androidTest/java/utils/CustomInteractions.java3
-rw-r--r--app/src/androidTest/java/utils/ProviderSetupUtils.java98
-rw-r--r--app/src/androidTestCustom/java/se/leap/bitmaskclient/base/CustomProviderTest.java62
-rw-r--r--app/src/androidTestCustom/java/se/leap/bitmaskclient/suite/ScreenshotTest.java17
-rw-r--r--app/src/androidTestNormal/java/se/leap/bitmaskclient/base/BitmaskTest.java42
-rw-r--r--app/src/androidTestNormal/java/se/leap/bitmaskclient/base/ProviderSetupTest.java69
-rw-r--r--app/src/main/java/de/blinkt/openvpn/VpnProfile.java5
-rw-r--r--app/src/main/java/de/blinkt/openvpn/core/OpenVPNService.java2
-rw-r--r--app/src/main/java/de/blinkt/openvpn/core/connection/Obfs4Connection.java2
-rw-r--r--app/src/main/java/se/leap/bitmaskclient/base/BitmaskTileService.java13
-rw-r--r--app/src/main/java/se/leap/bitmaskclient/base/MainActivity.java12
-rw-r--r--app/src/main/java/se/leap/bitmaskclient/base/fragments/EipFragment.java36
-rw-r--r--app/src/main/java/se/leap/bitmaskclient/base/fragments/GatewaySelectionFragment.java10
-rw-r--r--app/src/main/java/se/leap/bitmaskclient/base/fragments/NavigationDrawerFragment.java12
-rw-r--r--app/src/main/java/se/leap/bitmaskclient/base/fragments/ObfuscationProxyDialog.java12
-rw-r--r--app/src/main/java/se/leap/bitmaskclient/base/fragments/SettingsFragment.java2
-rw-r--r--app/src/main/java/se/leap/bitmaskclient/base/fragments/TetheringDialog.java13
-rw-r--r--app/src/main/java/se/leap/bitmaskclient/base/models/Constants.java1
-rw-r--r--app/src/main/java/se/leap/bitmaskclient/base/models/Provider.java4
-rw-r--r--app/src/main/java/se/leap/bitmaskclient/base/models/ProviderObservable.java24
-rw-r--r--app/src/main/java/se/leap/bitmaskclient/base/utils/BuildConfigHelper.java98
-rw-r--r--app/src/main/java/se/leap/bitmaskclient/base/utils/CertificateHelper.java64
-rw-r--r--app/src/main/java/se/leap/bitmaskclient/base/utils/ConfigHelper.java136
-rw-r--r--app/src/main/java/se/leap/bitmaskclient/base/utils/FileHelper.java41
-rw-r--r--app/src/main/java/se/leap/bitmaskclient/base/utils/HandlerProvider.java38
-rw-r--r--app/src/main/java/se/leap/bitmaskclient/base/utils/InputStreamHelper.java24
-rw-r--r--app/src/main/java/se/leap/bitmaskclient/base/utils/PreferenceHelper.java7
-rw-r--r--app/src/main/java/se/leap/bitmaskclient/base/utils/RSAHelper.java72
-rw-r--r--app/src/main/java/se/leap/bitmaskclient/base/utils/TimezoneHelper.java47
-rw-r--r--app/src/main/java/se/leap/bitmaskclient/eip/EIP.java10
-rw-r--r--app/src/main/java/se/leap/bitmaskclient/eip/EipStatus.java47
-rw-r--r--app/src/main/java/se/leap/bitmaskclient/eip/GatewaySelector.java6
-rw-r--r--app/src/main/java/se/leap/bitmaskclient/eip/VoidVpnService.java11
-rw-r--r--app/src/main/java/se/leap/bitmaskclient/eip/VpnConfigGenerator.java2
-rw-r--r--app/src/main/java/se/leap/bitmaskclient/firewall/FirewallManager.java14
-rw-r--r--app/src/main/java/se/leap/bitmaskclient/pluggableTransports/ObfsVpnClient.java10
-rw-r--r--app/src/main/java/se/leap/bitmaskclient/pluggableTransports/ShapeshifterClient.java13
-rw-r--r--app/src/main/java/se/leap/bitmaskclient/providersetup/ProviderApiConnector.java134
-rw-r--r--app/src/main/java/se/leap/bitmaskclient/providersetup/ProviderApiManagerBase.java17
-rw-r--r--app/src/main/java/se/leap/bitmaskclient/providersetup/ProviderSetupObservable.java46
-rw-r--r--app/src/main/java/se/leap/bitmaskclient/providersetup/SetupViewPagerAdapter.java2
-rw-r--r--app/src/main/java/se/leap/bitmaskclient/providersetup/activities/SetupActivity.java4
-rw-r--r--app/src/main/java/se/leap/bitmaskclient/providersetup/fragments/CircumventionSetupFragment.java4
-rw-r--r--app/src/main/java/se/leap/bitmaskclient/providersetup/fragments/ConfigureProviderFragment.java18
-rw-r--r--app/src/main/java/se/leap/bitmaskclient/tethering/TetheringObservable.java26
-rw-r--r--app/src/main/java/se/leap/bitmaskclient/tor/ClientTransportPlugin.java10
-rw-r--r--app/src/main/java/se/leap/bitmaskclient/tor/TorStatusObservable.java40
-rw-r--r--app/src/main/res/layout-xlarge/v_loading_screen.xml214
-rw-r--r--app/src/main/res/layout-xlarge/v_provider_header.xml29
-rw-r--r--app/src/main/res/layout/v_loading_screen.xml213
-rw-r--r--app/src/production/java/se/leap/bitmaskclient/providersetup/ProviderApiManager.java2
-rw-r--r--app/src/test/java/android/content/Intent.java61
-rw-r--r--app/src/test/java/android/os/Bundle.java101
-rw-r--r--app/src/test/java/android/text/TextUtils.java6
-rw-r--r--app/src/test/java/android/util/Base64.java19
-rw-r--r--app/src/test/java/android/util/Log.java23
-rw-r--r--app/src/test/java/de/blinkt/openvpn/VpnProfileTest.java39
-rw-r--r--app/src/test/java/se/leap/bitmaskclient/base/models/ProviderTest.java32
-rw-r--r--app/src/test/java/se/leap/bitmaskclient/eip/GatewaySelectorTest.java74
-rw-r--r--app/src/test/java/se/leap/bitmaskclient/eip/GatewaysManagerTest.java237
-rw-r--r--app/src/test/java/se/leap/bitmaskclient/eip/ProviderApiManagerTest.java529
-rw-r--r--app/src/test/java/se/leap/bitmaskclient/eip/VpnCertificateValidatorTest.java21
-rw-r--r--app/src/test/java/se/leap/bitmaskclient/eip/VpnConfigGeneratorTest.java82
-rw-r--r--app/src/test/java/se/leap/bitmaskclient/providersetup/ProviderManagerTest.java52
-rw-r--r--app/src/test/java/se/leap/bitmaskclient/testutils/BackendMockResponses/BackendMockProvider.java82
-rw-r--r--app/src/test/java/se/leap/bitmaskclient/testutils/BackendMockResponses/BaseBackendResponse.java75
-rw-r--r--app/src/test/java/se/leap/bitmaskclient/testutils/BackendMockResponses/EipSerivceJsonInvalidCertificateBackendResponse.java94
-rw-r--r--app/src/test/java/se/leap/bitmaskclient/testutils/BackendMockResponses/EipServiceJsonInvalidCertificateBackendResponse.java66
-rw-r--r--app/src/test/java/se/leap/bitmaskclient/testutils/BackendMockResponses/GeoIpServiceIsDownBackendResponse.java85
-rw-r--r--app/src/test/java/se/leap/bitmaskclient/testutils/BackendMockResponses/GeoIpServiceNotReachableTorFallbackBackendResponse.java81
-rw-r--r--app/src/test/java/se/leap/bitmaskclient/testutils/BackendMockResponses/MisconfiguredProviderBackendResponse.java85
-rw-r--r--app/src/test/java/se/leap/bitmaskclient/testutils/BackendMockResponses/NoErrorBackendResponse.java85
-rw-r--r--app/src/test/java/se/leap/bitmaskclient/testutils/BackendMockResponses/NoErrorBackendResponseAPIv4.java92
-rw-r--r--app/src/test/java/se/leap/bitmaskclient/testutils/BackendMockResponses/TorFallbackBackendResponse.java131
-rw-r--r--app/src/test/java/se/leap/bitmaskclient/testutils/BackendMockResponses/UpdatedCertificateBackendResponse.java95
-rw-r--r--app/src/test/java/se/leap/bitmaskclient/testutils/MockHelper.java564
-rw-r--r--app/src/test/java/se/leap/bitmaskclient/testutils/MockSharedPreferences.java18
-rw-r--r--app/src/test/java/se/leap/bitmaskclient/tethering/TetheringStateManagerTest.java256
-rw-r--r--app/src/test/java/se/leap/bitmaskclient/tor/TorStatusObservableTest.java48
-rw-r--r--app/src/test/resources/v4/riseup.net.cert89
-rw-r--r--build.gradle6
-rw-r--r--docker/android-fastlane/Dockerfile2
-rwxr-xr-xscripts/installFastlane.sh1
-rwxr-xr-xscripts/prepareForScreenshots.sh2
-rwxr-xr-xscripts/startEmulators.sh14
-rw-r--r--src/custom/fastlane/metadata/android/de/full_description.txt (renamed from src/custom/fastlane/metadata/de/full_description.txt)0
-rw-r--r--src/custom/fastlane/metadata/android/de/short_description.txt (renamed from src/custom/fastlane/metadata/de/short_description.txt)0
-rw-r--r--src/custom/fastlane/metadata/android/de/store-meta-de.json (renamed from src/custom/fastlane/metadata/de/store-meta-de.json)0
-rw-r--r--src/custom/fastlane/metadata/android/de/title.txt (renamed from src/custom/fastlane/metadata/de/title.txt)0
-rw-r--r--src/custom/fastlane/metadata/android/el/full_description.txt (renamed from src/custom/fastlane/metadata/el/full_description.txt)0
-rw-r--r--src/custom/fastlane/metadata/android/el/short_description.txt (renamed from src/custom/fastlane/metadata/el/short_description.txt)0
-rw-r--r--src/custom/fastlane/metadata/android/el/store-meta-el.json (renamed from src/custom/fastlane/metadata/el/store-meta-el.json)0
-rw-r--r--src/custom/fastlane/metadata/android/el/title.txt (renamed from src/custom/fastlane/metadata/el/title.txt)0
-rw-r--r--src/custom/fastlane/metadata/android/en-US/changelogs/169000.txt (renamed from src/custom/fastlane/metadata/en-US/changelogs/169000.txt)0
-rw-r--r--src/custom/fastlane/metadata/android/en-US/changelogs/170000.txt15
-rw-r--r--src/custom/fastlane/metadata/android/en-US/full_description.txt (renamed from src/custom/fastlane/metadata/en-US/full_description.txt)0
-rw-r--r--src/custom/fastlane/metadata/android/en-US/images/sevenInchScreenshots/1_en-US.png (renamed from src/custom/fastlane/metadata/en-US/images/sevenInchScreenshots/1_en-US.png)bin162001 -> 162001 bytes
-rw-r--r--src/custom/fastlane/metadata/android/en-US/images/sevenInchScreenshots/2_en-US.png (renamed from src/custom/fastlane/metadata/en-US/images/sevenInchScreenshots/2_en-US.png)bin269807 -> 269807 bytes
-rw-r--r--src/custom/fastlane/metadata/android/en-US/images/sevenInchScreenshots/3_en-US.png (renamed from src/custom/fastlane/metadata/en-US/images/sevenInchScreenshots/3_en-US.png)bin248841 -> 248841 bytes
-rw-r--r--src/custom/fastlane/metadata/android/en-US/short_description.txt (renamed from src/custom/fastlane/metadata/en-US/short_description.txt)0
-rw-r--r--src/custom/fastlane/metadata/android/en-US/title.txt (renamed from src/custom/fastlane/metadata/en-US/title.txt)0
-rw-r--r--src/custom/fastlane/metadata/android/en-US/video.txt (renamed from src/custom/fastlane/metadata/en-US/video.txt)0
-rw-r--r--src/custom/fastlane/metadata/android/fr/full_description.txt (renamed from src/custom/fastlane/metadata/fr/full_description.txt)0
-rw-r--r--src/custom/fastlane/metadata/android/fr/short_description.txt (renamed from src/custom/fastlane/metadata/fr/short_description.txt)0
-rw-r--r--src/custom/fastlane/metadata/android/fr/store-meta-fr.json (renamed from src/custom/fastlane/metadata/fr/store-meta-fr.json)0
-rw-r--r--src/custom/fastlane/metadata/android/fr/title.txt (renamed from src/custom/fastlane/metadata/fr/title.txt)0
-rw-r--r--src/custom/fastlane/metadata/android/nl/full_description.txt (renamed from src/custom/fastlane/metadata/nl/full_description.txt)0
-rw-r--r--src/custom/fastlane/metadata/android/nl/short_description.txt (renamed from src/custom/fastlane/metadata/nl/short_description.txt)0
-rw-r--r--src/custom/fastlane/metadata/android/nl/store-meta-nl.json (renamed from src/custom/fastlane/metadata/nl/store-meta-nl.json)0
-rw-r--r--src/custom/fastlane/metadata/android/nl/title.txt (renamed from src/custom/fastlane/metadata/nl/title.txt)0
-rw-r--r--src/custom/fastlane/metadata/android/pt-rBR/full_description.txt (renamed from src/custom/fastlane/metadata/pt-rBR/full_description.txt)0
-rw-r--r--src/custom/fastlane/metadata/android/pt-rBR/short_description.txt (renamed from src/custom/fastlane/metadata/pt-rBR/short_description.txt)0
-rw-r--r--src/custom/fastlane/metadata/android/pt-rBR/store-meta-pt-rBR.json (renamed from src/custom/fastlane/metadata/pt-rBR/store-meta-pt-rBR.json)0
-rw-r--r--src/custom/fastlane/metadata/android/pt-rBR/title.txt (renamed from src/custom/fastlane/metadata/pt-rBR/title.txt)0
-rw-r--r--src/custom/fastlane/metadata/android/tr/full_description.txt (renamed from src/custom/fastlane/metadata/tr/full_description.txt)0
-rw-r--r--src/custom/fastlane/metadata/android/tr/short_description.txt (renamed from src/custom/fastlane/metadata/tr/short_description.txt)0
-rw-r--r--src/custom/fastlane/metadata/android/tr/store-meta-tr.json (renamed from src/custom/fastlane/metadata/tr/store-meta-tr.json)0
-rw-r--r--src/custom/fastlane/metadata/android/tr/title.txt (renamed from src/custom/fastlane/metadata/tr/title.txt)0
-rw-r--r--src/normal/fastlane/metadata/android/el/full_description.txt (renamed from src/normal/fastlane/metadata/el/full_description.txt)0
-rw-r--r--src/normal/fastlane/metadata/android/el/short_description.txt (renamed from src/normal/fastlane/metadata/el/short_description.txt)0
-rw-r--r--src/normal/fastlane/metadata/android/el/store-meta-el.json (renamed from src/normal/fastlane/metadata/el/store-meta-el.json)0
-rw-r--r--src/normal/fastlane/metadata/android/el/title.txt (renamed from src/normal/fastlane/metadata/el/title.txt)0
-rw-r--r--src/normal/fastlane/metadata/android/en-US/changelogs/168000.txt (renamed from src/normal/fastlane/metadata/en-US/changelogs/168000.txt)0
-rw-r--r--src/normal/fastlane/metadata/android/en-US/changelogs/170000.txt15
-rw-r--r--src/normal/fastlane/metadata/android/en-US/full_description.txt (renamed from src/normal/fastlane/metadata/en-US/full_description.txt)0
-rw-r--r--src/normal/fastlane/metadata/android/en-US/short_description.txt (renamed from src/normal/fastlane/metadata/en-US/short_description.txt)0
-rw-r--r--src/normal/fastlane/metadata/android/en-US/title.txt (renamed from src/normal/fastlane/metadata/en-US/title.txt)0
-rw-r--r--src/normal/fastlane/metadata/android/en-US/video.txt (renamed from src/normal/fastlane/metadata/en-US/video.txt)0
-rw-r--r--src/normal/fastlane/metadata/android/nl/full_description.txt (renamed from src/normal/fastlane/metadata/nl/full_description.txt)0
-rw-r--r--src/normal/fastlane/metadata/android/nl/short_description.txt (renamed from src/normal/fastlane/metadata/nl/short_description.txt)0
-rw-r--r--src/normal/fastlane/metadata/android/nl/store-meta-nl.json (renamed from src/normal/fastlane/metadata/nl/store-meta-nl.json)0
-rw-r--r--src/normal/fastlane/metadata/android/nl/title.txt (renamed from src/normal/fastlane/metadata/nl/title.txt)0
-rw-r--r--src/normal/fastlane/metadata/android/pt-rBR/store-meta-pt-rBR.json (renamed from src/normal/fastlane/metadata/pt-rBR/store-meta-pt-rBR.json)0
-rw-r--r--src/normal/fastlane/metadata/android/tr/full_description.txt (renamed from src/normal/fastlane/metadata/tr/full_description.txt)0
-rw-r--r--src/normal/fastlane/metadata/android/tr/short_description.txt (renamed from src/normal/fastlane/metadata/tr/short_description.txt)0
-rw-r--r--src/normal/fastlane/metadata/android/tr/store-meta-tr.json (renamed from src/normal/fastlane/metadata/tr/store-meta-tr.json)0
-rw-r--r--src/normal/fastlane/metadata/android/tr/title.txt (renamed from src/normal/fastlane/metadata/tr/title.txt)0
-rw-r--r--src/normal/fastlane/metadata/android/tr/tx-values-tr.json (renamed from src/normal/fastlane/metadata/tr/tx-values-tr.json)0
145 files changed, 2436 insertions, 3151 deletions
diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index 7c9e8a54..1422d90a 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -77,7 +77,6 @@ screenshot:
image: "0xacab.org:4567/leap/bitmask_android/android-fastlane:latest"
stage: test
when: always
-# needs: ["docker_image:fastlane"]
tags:
- birch
variables:
@@ -86,20 +85,16 @@ screenshot:
ANDROID_EMULATOR_USE_SYSTEM_LIBS: 1
DEBIAN_FRONTEN: "noninteractive"
# try to re-use the build artifcats from before, lib building is slow
-# dependencies:
-# - build
+ dependencies:
+ - build
script:
- - ./scripts/prepareForScreenshots.sh
- ./scripts/installFastlane.sh
- - ./gradlew testCustomProductionFatReleaseUnitTest testNormalProductionFatReleaseUnitTest
- ./scripts/startEmulators.sh
- ./scripts/fastlane.sh
+ - ./scripts/fastlane.sh custom
artifacts:
paths:
- - app
- - app/build/screenshots
- - ./source/custom/fastlane/metadata/
- - build/
+ - src/custom/
- src/normal/
when: always
expire_in: 3 days
@@ -150,6 +145,7 @@ build:
- ./scripts/build_deps.sh >> build_deps.log 2>&1
- ./gradlew clean assembleNormalProductionFatDebug -debug >> build.log 2>&1
artifacts:
+ untracked: true
paths:
- app/build/outputs/
- build_deps.log
diff --git a/app/build.gradle b/app/build.gradle
index 091795a3..b27e4616 100644
--- a/app/build.gradle
+++ b/app/build.gradle
@@ -34,9 +34,9 @@ android {
// however we don't calculate the versionCode here, because F-Droid doesn't like that
versionCode 170000
versionName "1.2.0"
- compileSdk 33
+ compileSdk 34
minSdkVersion 21
- targetSdkVersion 33
+ targetSdkVersion 34
vectorDrawables.useSupportLibrary = true
buildConfigField 'boolean', 'openvpn3', 'false'
@@ -399,7 +399,7 @@ android {
dependencies {
- testImplementation 'junit:junit:4.12'
+ testImplementation 'junit:junit:4.13.2'
//outdated mockito-core version due to powermock dependency
testImplementation 'org.mockito:mockito-core:3.6.0'
testImplementation('org.powermock:powermock-api-mockito2:2.0.9')
@@ -421,18 +421,20 @@ dependencies {
testImplementation 'org.json:json:20180813'
androidTestImplementation 'androidx.test.ext:junit:1.1.4'
debugImplementation 'com.squareup.leakcanary:leakcanary-android-core:2.9.1'
+ debugImplementation 'androidx.fragment:fragment-testing:1.6.2'
+ debugImplementation 'androidx.test:core:1.5.0'
- implementation 'com.google.code.gson:gson:2.8.6'
+ implementation 'com.google.code.gson:gson:2.10.1'
implementation 'com.squareup.okhttp3:okhttp:4.10.0'
implementation 'com.squareup.okhttp3:okhttp-dnsoverhttps:4.10.0'
implementation 'org.conscrypt:conscrypt-android:2.5.2'
implementation 'androidx.security:security-crypto:1.1.0-alpha06'
implementation 'androidx.legacy:legacy-support-core-utils:1.0.0'
- implementation 'androidx.annotation:annotation:1.4.0'
+ implementation 'androidx.annotation:annotation:1.7.0'
implementation 'androidx.legacy:legacy-support-v4:1.0.0'
implementation 'androidx.appcompat:appcompat:1.6.1'
- implementation 'com.google.android.material:material:1.6.1'
- implementation 'androidx.fragment:fragment:1.5.1'
+ implementation 'com.google.android.material:material:1.10.0'
+ implementation 'androidx.fragment:fragment:1.6.2'
implementation 'androidx.constraintlayout:constraintlayout:2.1.4'
implementation 'androidx.multidex:multidex:2.0.1'
implementation 'androidx.localbroadcastmanager:localbroadcastmanager:1.1.0'
diff --git a/app/externalDir b/app/externalDir
new file mode 100644
index 00000000..72acfd13
--- /dev/null
+++ b/app/externalDir
@@ -0,0 +1 @@
+{"domain":"","main_url":"https://anotherprovider.org"} \ No newline at end of file
diff --git a/app/src/androidTest/java/se/leap/bitmaskclient/BitmaskTest.java b/app/src/androidTest/java/se/leap/bitmaskclient/BitmaskTest.java
new file mode 100644
index 00000000..1ca0980a
--- /dev/null
+++ b/app/src/androidTest/java/se/leap/bitmaskclient/BitmaskTest.java
@@ -0,0 +1,152 @@
+package se.leap.bitmaskclient;
+
+
+import static org.junit.Assert.assertNotNull;
+
+import android.Manifest;
+import android.app.Activity;
+import android.app.Instrumentation;
+import android.content.Intent;
+import android.os.Build;
+import android.view.Gravity;
+
+import androidx.test.espresso.Espresso;
+import androidx.test.espresso.ViewInteraction;
+import androidx.test.espresso.action.ViewActions;
+import androidx.test.espresso.assertion.ViewAssertions;
+import androidx.test.espresso.contrib.DrawerActions;
+import androidx.test.espresso.contrib.DrawerMatchers;
+import androidx.test.espresso.matcher.RootMatchers;
+import androidx.test.espresso.matcher.ViewMatchers;
+import androidx.test.ext.junit.runners.AndroidJUnit4;
+import androidx.test.filters.LargeTest;
+import androidx.test.platform.app.InstrumentationRegistry;
+import androidx.test.rule.GrantPermissionRule;
+import androidx.test.uiautomator.UiDevice;
+import androidx.test.uiautomator.UiObjectNotFoundException;
+
+import org.hamcrest.Matchers;
+import org.junit.Before;
+import org.junit.ClassRule;
+import org.junit.FixMethodOrder;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.MethodSorters;
+
+import se.leap.bitmaskclient.base.MainActivity;
+import se.leap.bitmaskclient.base.StartActivity;
+import se.leap.bitmaskclient.providersetup.activities.SetupActivity;
+import tools.fastlane.screengrab.Screengrab;
+import tools.fastlane.screengrab.UiAutomatorScreenshotStrategy;
+import tools.fastlane.screengrab.locale.LocaleTestRule;
+import utils.CustomInteractions;
+import utils.ProviderSetupUtils;
+
+@LargeTest
+@RunWith(AndroidJUnit4.class)
+@FixMethodOrder(MethodSorters.NAME_ASCENDING)
+public class BitmaskTest {
+
+ @ClassRule
+ public static final LocaleTestRule localeTestRule = new LocaleTestRule();
+
+ @Rule
+ public GrantPermissionRule notificationPermissionRule = (Build.VERSION.SDK_INT >= 33) ? GrantPermissionRule.grant(Manifest.permission.POST_NOTIFICATIONS) : null;
+
+ UiDevice device;
+ @Before
+ public void setup() {
+ Screengrab.setDefaultScreenshotStrategy(new UiAutomatorScreenshotStrategy());
+ Instrumentation instrumentation = InstrumentationRegistry.getInstrumentation();
+ device = UiDevice.getInstance(instrumentation);
+ }
+
+ @Test
+ public void test01_vpnStartTest() throws InterruptedException, UiObjectNotFoundException {
+ startMainActivity();
+
+ Screengrab.screenshot("VPN_connecting");
+ ViewInteraction mainButtonStop = CustomInteractions.tryResolve(
+ Espresso.onView(Matchers.allOf(
+ ViewMatchers.withId(R.id.button),
+ ViewMatchers.withTagValue(Matchers.is("button_circle_stop")))),
+ ViewAssertions.matches(ViewMatchers.isDisplayed()),
+ 20);
+ Screengrab.screenshot("VPN_connected");
+
+ mainButtonStop.perform(ViewActions.click());
+ Screengrab.screenshot("VPN_ask_disconnect");
+
+ Espresso.onView(ViewMatchers.withText(android.R.string.yes))
+ .inRoot(RootMatchers.isDialog())
+ .check(ViewAssertions.matches(ViewMatchers.isDisplayed()))
+ .perform(ViewActions.click());
+ Screengrab.screenshot("VPN_disconnected");
+ }
+
+ @Test
+ public void test02_SettingsFragmentScreenshots() {
+ startMainActivity();
+ Espresso.onView(ViewMatchers.withId(R.id.drawer_layout))
+ .check(ViewAssertions.matches(DrawerMatchers.isClosed(Gravity.LEFT))) // Left Drawer should be closed.
+ .perform(DrawerActions.open()); // Open Drawer
+
+ Screengrab.screenshot("navigationDrawer");
+
+ // Start the screen of your activity.
+ Espresso.onView(ViewMatchers.withId(R.id.advancedSettings))
+ .perform(ViewActions.click());
+
+ Screengrab.screenshot("settingsFragment");
+ }
+
+ @Test
+ public void test03_LocationSelectionFragmentScreenshots() {
+ startMainActivity();
+ Espresso.onView(ViewMatchers.withId(R.id.drawer_layout))
+ .check(ViewAssertions.matches(DrawerMatchers.isClosed(Gravity.LEFT))) // Left Drawer should be closed.
+ .perform(DrawerActions.open()); // Open Drawer
+
+ Espresso.onView(ViewMatchers.withId(R.id.manualGatewaySelection))
+ .perform(ViewActions.click());
+
+ Screengrab.screenshot("GatewaySelectionFragment");
+ }
+
+ @Test
+ public void test04_AppExclusionFragmentScreenshots() {
+ startMainActivity();
+ Espresso.onView(ViewMatchers.withId(R.id.drawer_layout))
+ .check(ViewAssertions.matches(DrawerMatchers.isClosed(Gravity.LEFT))) // Left Drawer should be closed.
+ .perform(DrawerActions.open()); // Open Drawer
+
+ Espresso.onView(ViewMatchers.withId(R.id.advancedSettings)).perform(ViewActions.click());
+
+ Espresso.onView(ViewMatchers.withId(R.id.exclude_apps)).perform(ViewActions.click());
+
+ CustomInteractions.tryResolve(
+ Espresso.onData(Matchers.anything()).inAdapterView(ViewMatchers.withId(android.R.id.list)).atPosition(2),
+ ViewAssertions.matches(ViewMatchers.isDisplayed()),
+ 5);
+
+ Screengrab.screenshot("App_Exclusion_Fragment");
+ }
+
+ private void startMainActivity() {
+ Instrumentation instrumentation = InstrumentationRegistry.getInstrumentation();
+ Instrumentation.ActivityMonitor setupActivityMonitor = new Instrumentation.ActivityMonitor(SetupActivity.class.getName(), null, false);
+ Instrumentation.ActivityMonitor mainActivityMonitor = new Instrumentation.ActivityMonitor(MainActivity.class.getName(), null, false);
+ instrumentation.addMonitor(setupActivityMonitor);
+ instrumentation.addMonitor(mainActivityMonitor);
+ Intent intent = new Intent(instrumentation.getTargetContext(), StartActivity.class);
+ intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+ instrumentation.startActivitySync(intent);
+ Activity setupActivity = instrumentation.waitForMonitorWithTimeout(setupActivityMonitor, 1000L);
+ if (setupActivity != null) {
+ ProviderSetupUtils.runProviderSetup(device, false, false, InstrumentationRegistry.getInstrumentation().getTargetContext());
+ }
+ Activity mainActivity = instrumentation.waitForMonitorWithTimeout(mainActivityMonitor, 1000);
+ assertNotNull(mainActivity);
+ }
+}
diff --git a/app/src/androidTest/java/se/leap/bitmaskclient/ProviderSetupTest.java b/app/src/androidTest/java/se/leap/bitmaskclient/ProviderSetupTest.java
new file mode 100644
index 00000000..dedb40d7
--- /dev/null
+++ b/app/src/androidTest/java/se/leap/bitmaskclient/ProviderSetupTest.java
@@ -0,0 +1,118 @@
+package se.leap.bitmaskclient;
+
+
+import static androidx.test.espresso.Espresso.onView;
+import static androidx.test.espresso.action.ViewActions.click;
+import static androidx.test.espresso.action.ViewActions.replaceText;
+import static androidx.test.espresso.assertion.ViewAssertions.matches;
+import static androidx.test.espresso.matcher.ViewMatchers.isDisplayed;
+import static androidx.test.espresso.matcher.ViewMatchers.withId;
+import static androidx.test.espresso.matcher.ViewMatchers.withText;
+import static org.junit.Assert.assertNotNull;
+import static se.leap.bitmaskclient.base.models.Constants.SHARED_ENCRYPTED_PREFERENCES;
+import static utils.CustomInteractions.tryResolve;
+
+import android.app.Activity;
+import android.app.Instrumentation;
+import android.content.Context;
+import android.content.Intent;
+
+import androidx.test.espresso.ViewInteraction;
+import androidx.test.ext.junit.rules.ActivityScenarioRule;
+import androidx.test.ext.junit.runners.AndroidJUnit4;
+import androidx.test.filters.LargeTest;
+import androidx.test.platform.app.InstrumentationRegistry;
+import androidx.test.uiautomator.UiDevice;
+
+import org.junit.Before;
+import org.junit.ClassRule;
+import org.junit.FixMethodOrder;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.MethodSorters;
+
+import se.leap.bitmaskclient.base.MainActivity;
+import se.leap.bitmaskclient.base.StartActivity;
+import se.leap.bitmaskclient.base.models.Provider;
+import se.leap.bitmaskclient.base.models.ProviderObservable;
+import se.leap.bitmaskclient.base.utils.PreferenceHelper;
+import se.leap.bitmaskclient.providersetup.activities.SetupActivity;
+import tools.fastlane.screengrab.Screengrab;
+import tools.fastlane.screengrab.UiAutomatorScreenshotStrategy;
+import tools.fastlane.screengrab.locale.LocaleTestRule;
+import utils.ProviderSetupUtils;
+
+@LargeTest
+@RunWith(AndroidJUnit4.class)
+@FixMethodOrder(MethodSorters.NAME_ASCENDING)
+public class ProviderSetupTest {
+
+ @ClassRule
+ public static final LocaleTestRule localeTestRule = new LocaleTestRule();
+
+ // @Rule
+ // public ActivityScenarioRule<SetupActivity> mActivityScenarioRule =
+ // new ActivityScenarioRule<>(SetupActivity.class);
+
+ UiDevice device;
+
+ @Before
+ public void setup() {
+ Screengrab.setDefaultScreenshotStrategy(new UiAutomatorScreenshotStrategy());
+ //PreferenceHelper.clear();
+ Instrumentation instrumentation = InstrumentationRegistry.getInstrumentation();
+ device = UiDevice.getInstance(instrumentation);
+ instrumentation.getTargetContext().deleteSharedPreferences(SHARED_ENCRYPTED_PREFERENCES);
+ ProviderObservable.getInstance().updateProvider(new Provider());
+ }
+
+ @Test
+ public void test01_setupProviderDefault() {
+ startSetupActivity();
+ ProviderSetupUtils.runProviderSetup(device, true, false, InstrumentationRegistry.getInstrumentation().getTargetContext());
+ }
+
+ @Test
+ public void test02_setupProviderCircumvention() {
+ startSetupActivity();
+ ProviderSetupUtils.runProviderSetup(device, true, true, InstrumentationRegistry.getInstrumentation().getTargetContext());
+ }
+
+ @Test
+ public void test03_addManuallyNewProviderScreenshot() {
+ if (!"normal".equals(BuildConfig.FLAVOR_branding)) {
+ System.out.println("skipping custom provider url test");
+ return;
+ }
+ startSetupActivity();
+ Context context = InstrumentationRegistry.getInstrumentation().getTargetContext();
+
+ ViewInteraction radioButtonSelection = tryResolve(onView(withText(R.string.add_provider)), matches(isDisplayed()));
+ radioButtonSelection.perform(click());
+ onView(withId(R.id.edit_customProvider)).perform(replaceText("https://leapvpn.myserver.org"));
+ tryResolve(onView(withId(R.id.edit_customProvider)), matches(withText("https://leapvpn.myserver.org")));
+ Screengrab.screenshot("setup_custom_provider");
+ onView(withId(R.id.setup_next_button)).perform(click());
+
+ onView(withText(context.getString(R.string.use_standard_vpn, context.getString(R.string.app_name)))).perform(click());
+ onView(withId(R.id.setup_next_button)).perform(click());
+
+ tryResolve(
+ onView(withText(context.getString(R.string.malformed_url, context.getString(R.string.app_name)))),
+ matches(isDisplayed()),
+ 20);
+ Screengrab.screenshot("setup_provider_error_dialog");
+ }
+
+ private void startSetupActivity() {
+ Instrumentation instrumentation = InstrumentationRegistry.getInstrumentation();
+ Instrumentation.ActivityMonitor setupActivityMonitor = new Instrumentation.ActivityMonitor(SetupActivity.class.getName(), null, false);
+ instrumentation.addMonitor(setupActivityMonitor);
+ Intent intent = new Intent(instrumentation.getTargetContext(), StartActivity.class);
+ intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+ instrumentation.startActivitySync(intent);
+ Activity setupActivity = instrumentation.waitForMonitorWithTimeout(setupActivityMonitor, 1000L);
+ assertNotNull(setupActivity);
+ }
+}
diff --git a/app/src/androidTest/java/se/leap/bitmaskclient/base/ProviderBaseTest.java b/app/src/androidTest/java/se/leap/bitmaskclient/base/ProviderBaseTest.java
deleted file mode 100644
index 68676bee..00000000
--- a/app/src/androidTest/java/se/leap/bitmaskclient/base/ProviderBaseTest.java
+++ /dev/null
@@ -1,167 +0,0 @@
-package se.leap.bitmaskclient.base;
-
-import static androidx.test.core.app.ApplicationProvider.getApplicationContext;
-import static androidx.test.espresso.Espresso.onData;
-import static androidx.test.espresso.Espresso.onView;
-import static androidx.test.espresso.action.ViewActions.click;
-import static androidx.test.espresso.assertion.ViewAssertions.matches;
-import static androidx.test.espresso.contrib.DrawerMatchers.isClosed;
-import static androidx.test.espresso.matcher.RootMatchers.isDialog;
-import static androidx.test.espresso.matcher.ViewMatchers.isDisplayed;
-import static androidx.test.espresso.matcher.ViewMatchers.withId;
-import static androidx.test.espresso.matcher.ViewMatchers.withTagValue;
-import static androidx.test.espresso.matcher.ViewMatchers.withText;
-import static org.hamcrest.Matchers.allOf;
-import static org.hamcrest.Matchers.anything;
-import static org.hamcrest.Matchers.is;
-import static utils.CustomInteractions.tryResolve;
-
-import android.app.Instrumentation;
-import android.content.SharedPreferences;
-import android.net.VpnService;
-import android.view.Gravity;
-
-import androidx.test.espresso.ViewInteraction;
-import androidx.test.espresso.contrib.DrawerActions;
-import androidx.test.ext.junit.rules.ActivityScenarioRule;
-import androidx.test.ext.junit.runners.AndroidJUnit4;
-import androidx.test.filters.LargeTest;
-import androidx.test.platform.app.InstrumentationRegistry;
-import androidx.test.uiautomator.UiDevice;
-import androidx.test.uiautomator.UiObject;
-import androidx.test.uiautomator.UiObjectNotFoundException;
-import androidx.test.uiautomator.UiSelector;
-
-import org.junit.Before;
-import org.junit.ClassRule;
-import org.junit.FixMethodOrder;
-import org.junit.Rule;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.junit.runners.MethodSorters;
-
-import se.leap.bitmaskclient.R;
-import se.leap.bitmaskclient.base.utils.PreferenceHelper;
-import tools.fastlane.screengrab.Screengrab;
-import tools.fastlane.screengrab.UiAutomatorScreenshotStrategy;
-import tools.fastlane.screengrab.locale.LocaleTestRule;
-
-@LargeTest
-@RunWith(AndroidJUnit4.class)
-@FixMethodOrder(MethodSorters.NAME_ASCENDING)
-public abstract class ProviderBaseTest {
-
- @ClassRule
- public static final LocaleTestRule localeTestRule = new LocaleTestRule();
-
- @Rule
- public ActivityScenarioRule<StartActivity> mActivityScenarioRule =
- new ActivityScenarioRule<>(StartActivity.class);
-
- UiDevice device;
- @Before
- public void setup() {
- Screengrab.setDefaultScreenshotStrategy(new UiAutomatorScreenshotStrategy());
- SharedPreferences preferences = PreferenceHelper.getSharedPreferences(getApplicationContext());
- preferences.edit().clear().commit();
- Instrumentation instrumentation = InstrumentationRegistry.getInstrumentation();
- device = UiDevice.getInstance(instrumentation);
- }
-
- @Test
- public void test01_vpnStartTest() throws InterruptedException, UiObjectNotFoundException {
- boolean configurationNeeded = configureProviderIfNeeded();
-
- ViewInteraction mainButtonStop;
- if (!configurationNeeded) {
- // click on Main on/off button and start VPN
- ViewInteraction mainButton = tryResolve(
- onView(withId(R.id.main_button)),
- matches(isDisplayed())
- );
-
- mainButton.perform(click());
- Thread.sleep(50);
- Screengrab.screenshot("VPN_connecting");
-
- mainButtonStop = tryResolve(
- onView(allOf(
- withId(R.id.button),
- withTagValue(is("button_circle_stop")))),
- matches(isDisplayed()),
- 20);
- Screengrab.screenshot("VPN_connected");
- } else {
- // handle VPN permission dialog
- if (VpnService.prepare(getApplicationContext()) != null) {
- UiObject okButton = device.findObject(new UiSelector().packageName("com.android.vpndialogs").resourceId("android:id/button1"));
- okButton.click();
- }
- // on new configurations the VPN is automatically started
- Screengrab.screenshot("VPN_connecting");
- mainButtonStop = tryResolve(
- onView(allOf(
- withId(R.id.button),
- withTagValue(is("button_circle_stop")))),
- matches(isDisplayed()),
- 20);
- Screengrab.screenshot("VPN_connected");
- }
-
- mainButtonStop.perform(click());
- Screengrab.screenshot("VPN_ask_disconnect");
-
- onView(withText(android.R.string.yes))
- .inRoot(isDialog())
- .check(matches(isDisplayed()))
- .perform(click());
- Screengrab.screenshot("VPN_disconnected");
- }
-
- @Test
- public void test02_SettingsFragmentScreenshots() {
- onView(withId(R.id.drawer_layout))
- .check(matches(isClosed(Gravity.LEFT))) // Left Drawer should be closed.
- .perform(DrawerActions.open()); // Open Drawer
-
- Screengrab.screenshot("navigationDrawer");
-
- // Start the screen of your activity.
- onView(withId(R.id.advancedSettings))
- .perform(click());
-
- Screengrab.screenshot("settingsFragment");
- }
-
- @Test
- public void test03_LocationSelectionFragmentScreenshots() {
- onView(withId(R.id.drawer_layout))
- .check(matches(isClosed(Gravity.LEFT))) // Left Drawer should be closed.
- .perform(DrawerActions.open()); // Open Drawer
-
- onView(withId(R.id.manualGatewaySelection))
- .perform(click());
-
- Screengrab.screenshot("GatewaySelectionFragment");
- }
-
- @Test
- public void test04_AppExclusionFragmentScreenshots() {
- onView(withId(R.id.drawer_layout))
- .check(matches(isClosed(Gravity.LEFT))) // Left Drawer should be closed.
- .perform(DrawerActions.open()); // Open Drawer
-
- onView(withId(R.id.advancedSettings)).perform(click());
-
- onView(withId(R.id.exclude_apps)).perform(click());
-
- tryResolve(
- onData(anything()).inAdapterView(withId(android.R.id.list)).atPosition(2),
- matches(isDisplayed()),
- 5);
-
- Screengrab.screenshot("App_Exclusion_Fragment");
- }
-
- public abstract boolean configureProviderIfNeeded();
-}
diff --git a/app/src/androidTestNormal/java/se/leap/bitmaskclient/suite/ScreenshotTest.java b/app/src/androidTest/java/se/leap/bitmaskclient/suite/ScreenshotTest.java
index 5fa45a95..f3a8d73c 100644
--- a/app/src/androidTestNormal/java/se/leap/bitmaskclient/suite/ScreenshotTest.java
+++ b/app/src/androidTest/java/se/leap/bitmaskclient/suite/ScreenshotTest.java
@@ -6,8 +6,8 @@ import androidx.test.filters.LargeTest;
import org.junit.runner.RunWith;
import org.junit.runners.Suite;
-import se.leap.bitmaskclient.base.ProviderSetupTest;
-import se.leap.bitmaskclient.base.BitmaskTest;
+import se.leap.bitmaskclient.BitmaskTest;
+import se.leap.bitmaskclient.ProviderSetupTest;
@LargeTest
@RunWith(Suite.class)
diff --git a/app/src/androidTest/java/utils/CustomInteractions.java b/app/src/androidTest/java/utils/CustomInteractions.java
index 9e3a8f9d..4890c20c 100644
--- a/app/src/androidTest/java/utils/CustomInteractions.java
+++ b/app/src/androidTest/java/utils/CustomInteractions.java
@@ -30,8 +30,7 @@ public class CustomInteractions {
}
hasFound = true;
} catch (NoMatchingViewException exception) {
- System.out.println("NoMatchingViewException attempt: " + attempt);
- exception.printStackTrace();
+ System.out.println("NoMatchingViewException - attempt: " + attempt + ". " + exception.getLocalizedMessage());
attempt++;
if (attempt == maxTries) {
throw exception;
diff --git a/app/src/androidTest/java/utils/ProviderSetupUtils.java b/app/src/androidTest/java/utils/ProviderSetupUtils.java
new file mode 100644
index 00000000..9b76ffbd
--- /dev/null
+++ b/app/src/androidTest/java/utils/ProviderSetupUtils.java
@@ -0,0 +1,98 @@
+package utils;
+
+import static androidx.test.core.app.ApplicationProvider.getApplicationContext;
+import static androidx.test.espresso.Espresso.onView;
+import static androidx.test.espresso.action.ViewActions.click;
+import static androidx.test.espresso.assertion.ViewAssertions.matches;
+import static androidx.test.espresso.matcher.ViewMatchers.isDisplayed;
+import static androidx.test.espresso.matcher.ViewMatchers.withId;
+import static androidx.test.espresso.matcher.ViewMatchers.withTagValue;
+import static androidx.test.espresso.matcher.ViewMatchers.withText;
+import static utils.CustomInteractions.tryResolve;
+
+import android.content.Context;
+import android.net.VpnService;
+
+import androidx.test.espresso.NoMatchingViewException;
+import androidx.test.espresso.ViewInteraction;
+import androidx.test.espresso.matcher.ViewMatchers;
+import androidx.test.uiautomator.UiDevice;
+import androidx.test.uiautomator.UiObject;
+import androidx.test.uiautomator.UiObjectNotFoundException;
+import androidx.test.uiautomator.UiSelector;
+
+import org.hamcrest.Matchers;
+
+import se.leap.bitmaskclient.BuildConfig;
+import se.leap.bitmaskclient.R;
+import tools.fastlane.screengrab.Screengrab;
+
+public class ProviderSetupUtils {
+
+ public static void runProviderSetup(UiDevice device, boolean takeConfigurationScreenshots, boolean useCircumvention, Context targetContext) {
+ try {
+ // ------- PROVIDER SELECTION --------------
+ if ("normal".equals(BuildConfig.FLAVOR_branding)) {
+ System.out.println("next: provider selection");
+ ViewInteraction radioButtonSelection = tryResolve(onView(withText("Riseup")), matches(isDisplayed()));
+ if (takeConfigurationScreenshots) Screengrab.screenshot("provider_selection");
+ radioButtonSelection.perform(click());
+ // next button click
+ onView(withText(R.string.next)).perform(click());
+ }
+
+ // ------- CIRCUMVENTION SELECTION --------------
+ System.out.println("next: standard/circumvention selection");
+ if (useCircumvention) {
+ onView(withText(targetContext.getString(R.string.use_circumvention_tech))).perform(click());
+ } else {
+ onView(withText(targetContext.getString(R.string.use_standard_vpn, targetContext.getString(R.string.app_name)))).perform(click());
+ }
+ if (takeConfigurationScreenshots) Screengrab.screenshot("circumvention_selection");
+
+ // ------- CONFIGURATION PROGRESS --------------
+ System.out.println("next: configuring");
+ onView(withText(R.string.next)).perform(click());
+ tryResolve(
+ onView(
+ Matchers.allOf(
+ withText(R.string.configuring_provider),
+ withId(R.id.tv_title)
+ )
+ ),
+ matches(isDisplayed())
+ );
+ if (takeConfigurationScreenshots) Screengrab.screenshot("configuring_provider");
+
+ // ------- VPN PERMISSON DIALOG --------------
+ boolean showPermissionDialog = false;
+ if (VpnService.prepare(getApplicationContext()) != null) {
+ showPermissionDialog = true;
+ tryResolve(onView(withText(R.string.upcoming_connection_request_description)), matches(isDisplayed()), useCircumvention ? 180 : 20);
+ System.out.println("next: next permission request");
+ if (takeConfigurationScreenshots) Screengrab.screenshot("vpn_permission_rationale");
+ onView(withText(R.string.next)).perform(click());
+ UiObject okButton = device.findObject(new UiSelector().packageName("com.android.vpndialogs").resourceId("android:id/button1"));
+ okButton.waitForExists(30000);
+ okButton.click();
+ device.waitForWindowUpdate("com.android.vpndialogs", 1000);
+ }
+
+ // ------- START VPN --------------
+ System.out.println("next: perform click on VPN button");
+ ViewInteraction interaction = tryResolve(onView(withTagValue(Matchers.is("button_setup_circle_custom"))), matches(isDisplayed()), useCircumvention && !showPermissionDialog ? 180 : 20);
+ if (takeConfigurationScreenshots) {
+ Screengrab.screenshot("all_set_start_vpn");
+ } else {
+ // we only want to start the VPN in case we're not running the ProviderSetupTest
+ interaction.perform(click());
+ }
+ } catch (NoMatchingViewException e) {
+ // it might be that the provider was already configured, so we print the stack
+ // trace here and try to continue
+ e.printStackTrace();
+ } catch (UiObjectNotFoundException | NullPointerException e) {
+ e.printStackTrace();
+ }
+ }
+}
diff --git a/app/src/androidTestCustom/java/se/leap/bitmaskclient/base/CustomProviderTest.java b/app/src/androidTestCustom/java/se/leap/bitmaskclient/base/CustomProviderTest.java
deleted file mode 100644
index 92416af4..00000000
--- a/app/src/androidTestCustom/java/se/leap/bitmaskclient/base/CustomProviderTest.java
+++ /dev/null
@@ -1,62 +0,0 @@
-package se.leap.bitmaskclient.base;
-
-import static androidx.test.core.app.ApplicationProvider.getApplicationContext;
-import static androidx.test.espresso.Espresso.onView;
-import static androidx.test.espresso.action.ViewActions.click;
-import static androidx.test.espresso.assertion.ViewAssertions.matches;
-import static androidx.test.espresso.matcher.RootMatchers.isDialog;
-import static androidx.test.espresso.matcher.ViewMatchers.isDisplayed;
-import static androidx.test.espresso.matcher.ViewMatchers.withId;
-import static androidx.test.espresso.matcher.ViewMatchers.withText;
-import static utils.CustomInteractions.tryResolve;
-
-import android.net.VpnService;
-
-import androidx.test.espresso.ViewInteraction;
-import androidx.test.uiautomator.UiObject;
-import androidx.test.uiautomator.UiObjectNotFoundException;
-import androidx.test.uiautomator.UiSelector;
-
-import org.junit.Test;
-
-import se.leap.bitmaskclient.R;
-import tools.fastlane.screengrab.Screengrab;
-
-public class CustomProviderTest extends ProviderBaseTest {
-
- @Test
- @Override
- public void test01_vpnStartTest() throws InterruptedException, UiObjectNotFoundException {
- // handle VPN permission dialog
- if (VpnService.prepare(getApplicationContext()) != null) {
- UiObject okButton = device.findObject(new UiSelector().packageName("com.android.vpndialogs").resourceId("android:id/button1"));
- okButton.waitForExists(30000);
- okButton.click();
- }
-
- ViewInteraction mainButtonStop;
- mainButtonStop = tryResolve(
- onView(withId(R.id.main_button)),
- matches(isDisplayed()),
- 30);
- Screengrab.screenshot("VPN_connected");
-
- mainButtonStop.perform(click());
- Screengrab.screenshot("VPN_ask_disconnect");
-
- ViewInteraction alertDialogOKbutton = tryResolve(onView(withText(android.R.string.yes))
- .inRoot(isDialog()),
- matches(isDisplayed()));
- alertDialogOKbutton.perform(click());
- Screengrab.screenshot("VPN_disconnected");
-
- mainButtonStop.perform(click());
- Thread.sleep(50);
- Screengrab.screenshot("VPN_connecting");
- }
-
- @Override
- public boolean configureProviderIfNeeded() {
- return false;
- }
-} \ No newline at end of file
diff --git a/app/src/androidTestCustom/java/se/leap/bitmaskclient/suite/ScreenshotTest.java b/app/src/androidTestCustom/java/se/leap/bitmaskclient/suite/ScreenshotTest.java
deleted file mode 100644
index a19b0ffd..00000000
--- a/app/src/androidTestCustom/java/se/leap/bitmaskclient/suite/ScreenshotTest.java
+++ /dev/null
@@ -1,17 +0,0 @@
-package se.leap.bitmaskclient.suite;
-
-
-import androidx.test.filters.LargeTest;
-
-import org.junit.runner.RunWith;
-import org.junit.runners.Suite;
-
-import se.leap.bitmaskclient.base.CustomProviderTest;
-
-@LargeTest
-@RunWith(Suite.class)
-@Suite.SuiteClasses({
- CustomProviderTest.class
-})
-public class ScreenshotTest {
-}
diff --git a/app/src/androidTestNormal/java/se/leap/bitmaskclient/base/BitmaskTest.java b/app/src/androidTestNormal/java/se/leap/bitmaskclient/base/BitmaskTest.java
deleted file mode 100644
index aa437c74..00000000
--- a/app/src/androidTestNormal/java/se/leap/bitmaskclient/base/BitmaskTest.java
+++ /dev/null
@@ -1,42 +0,0 @@
-package se.leap.bitmaskclient.base;
-
-
-import static androidx.test.espresso.Espresso.onData;
-import static androidx.test.espresso.action.ViewActions.click;
-import static androidx.test.espresso.matcher.ViewMatchers.withId;
-import static org.hamcrest.Matchers.containsString;
-import static org.hamcrest.Matchers.hasToString;
-import static utils.CustomInteractions.tryResolve;
-
-import androidx.test.espresso.DataInteraction;
-import androidx.test.espresso.NoMatchingViewException;
-import androidx.test.ext.junit.runners.AndroidJUnit4;
-import androidx.test.filters.LargeTest;
-
-import org.junit.FixMethodOrder;
-import org.junit.runner.RunWith;
-import org.junit.runners.MethodSorters;
-
-import se.leap.bitmaskclient.R;
-
-@LargeTest
-@RunWith(AndroidJUnit4.class)
-@FixMethodOrder(MethodSorters.NAME_ASCENDING)
-public class BitmaskTest extends ProviderBaseTest {
-
- @Override
- public boolean configureProviderIfNeeded() {
- try {
- DataInteraction linearLayout = tryResolve(onData(hasToString(containsString("riseup.net")))
- .inAdapterView(withId(R.id.provider_list)),
- 2);
- linearLayout.perform(click());
- return true;
- } catch (NoMatchingViewException e) {
- // it might be that the provider was already configured, so we print the stack
- // trace here and try to continue
- e.printStackTrace();
- }
- return false;
- }
-}
diff --git a/app/src/androidTestNormal/java/se/leap/bitmaskclient/base/ProviderSetupTest.java b/app/src/androidTestNormal/java/se/leap/bitmaskclient/base/ProviderSetupTest.java
deleted file mode 100644
index 460a30ad..00000000
--- a/app/src/androidTestNormal/java/se/leap/bitmaskclient/base/ProviderSetupTest.java
+++ /dev/null
@@ -1,69 +0,0 @@
-package se.leap.bitmaskclient.base;
-
-
-import static android.content.Context.MODE_PRIVATE;
-import static androidx.test.core.app.ApplicationProvider.getApplicationContext;
-import static androidx.test.espresso.Espresso.onData;
-import static androidx.test.espresso.action.ViewActions.click;
-import static androidx.test.espresso.matcher.ViewMatchers.withId;
-import static org.hamcrest.Matchers.anything;
-import static org.hamcrest.Matchers.containsString;
-import static org.hamcrest.Matchers.hasToString;
-import static se.leap.bitmaskclient.base.models.Constants.SHARED_PREFERENCES;
-import static utils.CustomInteractions.tryResolve;
-
-import android.content.SharedPreferences;
-
-import androidx.test.espresso.DataInteraction;
-import androidx.test.espresso.NoMatchingViewException;
-import androidx.test.ext.junit.rules.ActivityScenarioRule;
-import androidx.test.ext.junit.runners.AndroidJUnit4;
-import androidx.test.filters.LargeTest;
-
-import org.junit.Before;
-import org.junit.ClassRule;
-import org.junit.Rule;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-
-import se.leap.bitmaskclient.R;
-import se.leap.bitmaskclient.base.utils.PreferenceHelper;
-import se.leap.bitmaskclient.providersetup.ProviderListActivity;
-import tools.fastlane.screengrab.Screengrab;
-import tools.fastlane.screengrab.UiAutomatorScreenshotStrategy;
-import tools.fastlane.screengrab.locale.LocaleTestRule;
-
-@LargeTest
-@RunWith(AndroidJUnit4.class)
-public class ProviderSetupTest {
-
- @ClassRule
- public static final LocaleTestRule localeTestRule = new LocaleTestRule();
-
- @Rule
- public ActivityScenarioRule<ProviderListActivity> mActivityScenarioRule =
- new ActivityScenarioRule<>(ProviderListActivity.class);
-
- @Before
- public void setup() {
- Screengrab.setDefaultScreenshotStrategy(new UiAutomatorScreenshotStrategy());
- SharedPreferences preferences = PreferenceHelper.getSharedPreferences(getApplicationContext());
- preferences.edit().clear().commit();
- }
-
- @Test
- public void testConfigureRiseupVPNScreenshot() {
- DataInteraction linearLayout = tryResolve(onData(hasToString(containsString("riseup.net")))
- .inAdapterView(withId(R.id.provider_list)),
- 2);
- Screengrab.screenshot("ProviderListActivity");
- linearLayout.perform(click());
- Screengrab.screenshot("ProviderListActivity_configureRiseup");
- }
-
- @Test
- public void testaddManuallyNewProviderScreenshot() {
- onData(anything()).inAdapterView(withId(R.id.provider_list)).atPosition(3).perform(click());
- Screengrab.screenshot("ProviderListActivity_addManuallyNewProvider");
- }
-}
diff --git a/app/src/main/java/de/blinkt/openvpn/VpnProfile.java b/app/src/main/java/de/blinkt/openvpn/VpnProfile.java
index 780ac9d8..9da1e452 100644
--- a/app/src/main/java/de/blinkt/openvpn/VpnProfile.java
+++ b/app/src/main/java/de/blinkt/openvpn/VpnProfile.java
@@ -16,7 +16,6 @@ import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.os.Build;
import android.os.Bundle;
-import android.preference.PreferenceManager;
import android.security.KeyChain;
import android.security.KeyChainException;
import android.text.TextUtils;
@@ -77,6 +76,7 @@ import de.blinkt.openvpn.core.connection.ConnectionAdapter;
import se.leap.bitmaskclient.BuildConfig;
import se.leap.bitmaskclient.R;
import se.leap.bitmaskclient.base.models.ProviderObservable;
+import se.leap.bitmaskclient.base.utils.PreferenceHelper;
public class VpnProfile implements Serializable, Cloneable {
// Note that this class cannot be moved to core where it belongs since
@@ -651,8 +651,7 @@ public class VpnProfile implements Serializable, Cloneable {
if (mPushPeerInfo)
cfg.append("push-peer-info\n");
- SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);
- boolean usesystemproxy = prefs.getBoolean("usesystemproxy", true);
+ boolean usesystemproxy = PreferenceHelper.useSystemProxy();
if (usesystemproxy && !mIsOpenVPN22 && !configForOvpn3 && !usesExtraProxyOptions()) {
cfg.append("# Use system proxy setting\n");
cfg.append("management-query-proxy\n");
diff --git a/app/src/main/java/de/blinkt/openvpn/core/OpenVPNService.java b/app/src/main/java/de/blinkt/openvpn/core/OpenVPNService.java
index b38eeb14..5a618f10 100644
--- a/app/src/main/java/de/blinkt/openvpn/core/OpenVPNService.java
+++ b/app/src/main/java/de/blinkt/openvpn/core/OpenVPNService.java
@@ -9,7 +9,7 @@ import static de.blinkt.openvpn.core.ConnectionStatus.LEVEL_CONNECTED;
import static de.blinkt.openvpn.core.ConnectionStatus.LEVEL_WAITING_FOR_USER_INPUT;
import static de.blinkt.openvpn.core.NetworkSpace.IpAddress;
import static se.leap.bitmaskclient.base.models.Constants.PROVIDER_PROFILE;
-import static se.leap.bitmaskclient.base.utils.ConfigHelper.ObfsVpnHelper.useObfsVpn;
+import static se.leap.bitmaskclient.base.utils.BuildConfigHelper.useObfsVpn;
import android.Manifest.permission;
import android.app.Notification;
diff --git a/app/src/main/java/de/blinkt/openvpn/core/connection/Obfs4Connection.java b/app/src/main/java/de/blinkt/openvpn/core/connection/Obfs4Connection.java
index d152031a..19ea180d 100644
--- a/app/src/main/java/de/blinkt/openvpn/core/connection/Obfs4Connection.java
+++ b/app/src/main/java/de/blinkt/openvpn/core/connection/Obfs4Connection.java
@@ -1,6 +1,6 @@
package de.blinkt.openvpn.core.connection;
-import static se.leap.bitmaskclient.base.utils.ConfigHelper.ObfsVpnHelper.useObfsVpn;
+import static se.leap.bitmaskclient.base.utils.BuildConfigHelper.useObfsVpn;
import static se.leap.bitmaskclient.pluggableTransports.ShapeshifterClient.DISPATCHER_IP;
import static se.leap.bitmaskclient.pluggableTransports.ShapeshifterClient.DISPATCHER_PORT;
diff --git a/app/src/main/java/se/leap/bitmaskclient/base/BitmaskTileService.java b/app/src/main/java/se/leap/bitmaskclient/base/BitmaskTileService.java
index 370a7af6..d85e0a75 100644
--- a/app/src/main/java/se/leap/bitmaskclient/base/BitmaskTileService.java
+++ b/app/src/main/java/se/leap/bitmaskclient/base/BitmaskTileService.java
@@ -8,6 +8,8 @@ import android.os.Build;
import android.service.quicksettings.Tile;
import android.service.quicksettings.TileService;
+import java.beans.PropertyChangeEvent;
+import java.beans.PropertyChangeListener;
import java.util.Observable;
import java.util.Observer;
@@ -19,7 +21,7 @@ import se.leap.bitmaskclient.base.models.ProviderObservable;
@TargetApi(Build.VERSION_CODES.N)
-public class BitmaskTileService extends TileService implements Observer {
+public class BitmaskTileService extends TileService implements PropertyChangeListener {
@SuppressLint("Override")
@TargetApi(Build.VERSION_CODES.N)
@@ -59,7 +61,7 @@ public class BitmaskTileService extends TileService implements Observer {
public void onStartListening() {
super.onStartListening();
EipStatus.getInstance().addObserver(this);
- update(EipStatus.getInstance(), null);
+ propertyChange(new PropertyChangeEvent(EipStatus.getInstance(), EipStatus.PROPERTY_CHANGE, null, EipStatus.getInstance()));
}
@Override
@@ -69,16 +71,15 @@ public class BitmaskTileService extends TileService implements Observer {
}
@Override
- public void update(Observable o, Object arg) {
+ public void propertyChange(PropertyChangeEvent evt) {
Tile t = getQsTile();
// Tile t should never be null according to https://developer.android.com/reference/kotlin/android/service/quicksettings/TileService.
// Hovever we've got crash reports.
if (t == null) {
return;
}
-
- if (o instanceof EipStatus) {
- EipStatus status = (EipStatus) o;
+ if (EipStatus.PROPERTY_CHANGE.equals(evt.getPropertyName())) {
+ EipStatus status = (EipStatus) evt.getNewValue();
Icon icon;
String title;
if (status.isConnecting() || status.isReconnecting()) {
diff --git a/app/src/main/java/se/leap/bitmaskclient/base/MainActivity.java b/app/src/main/java/se/leap/bitmaskclient/base/MainActivity.java
index 5da238d4..3f541d8d 100644
--- a/app/src/main/java/se/leap/bitmaskclient/base/MainActivity.java
+++ b/app/src/main/java/se/leap/bitmaskclient/base/MainActivity.java
@@ -59,8 +59,8 @@ import androidx.fragment.app.FragmentTransaction;
import org.json.JSONException;
import org.json.JSONObject;
-import java.util.Observable;
-import java.util.Observer;
+import java.beans.PropertyChangeEvent;
+import java.beans.PropertyChangeListener;
import se.leap.bitmaskclient.BuildConfig;
import se.leap.bitmaskclient.R;
@@ -80,7 +80,7 @@ import se.leap.bitmaskclient.eip.EipSetupListener;
import se.leap.bitmaskclient.eip.EipSetupObserver;
import se.leap.bitmaskclient.providersetup.ProviderAPI;
-public class MainActivity extends AppCompatActivity implements EipSetupListener, Observer {
+public class MainActivity extends AppCompatActivity implements EipSetupListener, PropertyChangeListener {
public final static String TAG = MainActivity.class.getSimpleName();
@@ -354,9 +354,9 @@ public class MainActivity extends AppCompatActivity implements EipSetupListener,
}
@Override
- public void update(Observable o, Object arg) {
- if (o instanceof ProviderObservable) {
- this.provider = ((ProviderObservable) o).getCurrentProvider();
+ public void propertyChange(PropertyChangeEvent evt) {
+ if (ProviderObservable.PROPERTY_CHANGE.equals(evt.getPropertyName())) {
+ this.provider = (Provider) evt.getNewValue();
}
}
diff --git a/app/src/main/java/se/leap/bitmaskclient/base/fragments/EipFragment.java b/app/src/main/java/se/leap/bitmaskclient/base/fragments/EipFragment.java
index f4e09e62..fb93796e 100644
--- a/app/src/main/java/se/leap/bitmaskclient/base/fragments/EipFragment.java
+++ b/app/src/main/java/se/leap/bitmaskclient/base/fragments/EipFragment.java
@@ -56,8 +56,8 @@ import androidx.fragment.app.FragmentTransaction;
import androidx.vectordrawable.graphics.drawable.Animatable2Compat.AnimationCallback;
import androidx.vectordrawable.graphics.drawable.AnimatedVectorDrawableCompat;
-import java.util.Observable;
-import java.util.Observer;
+import java.beans.PropertyChangeEvent;
+import java.beans.PropertyChangeListener;
import de.blinkt.openvpn.core.ConnectionStatus;
import de.blinkt.openvpn.core.VpnStatus;
@@ -80,7 +80,7 @@ import se.leap.bitmaskclient.providersetup.activities.SetupActivity;
import se.leap.bitmaskclient.tor.TorServiceCommand;
import se.leap.bitmaskclient.tor.TorStatusObservable;
-public class EipFragment extends Fragment implements Observer {
+public class EipFragment extends Fragment implements PropertyChangeListener {
public final static String TAG = EipFragment.class.getSimpleName();
@@ -375,17 +375,27 @@ public class EipFragment extends Fragment implements Observer {
}
+
@Override
- public void update(Observable observable, Object data) {
- if (observable instanceof EipStatus) {
- previousEipLevel = eipStatus.getEipLevel();
- eipStatus = (EipStatus) observable;
- handleNewStateOnMain();
-
- } else if (observable instanceof ProviderObservable) {
- provider = ((ProviderObservable) observable).getCurrentProvider();
- } else if (observable instanceof TorStatusObservable && EipStatus.getInstance().isUpdatingVpnCert()) {
- handleNewStateOnMain();
+ public void propertyChange(PropertyChangeEvent evt) {
+ switch (evt.getPropertyName()) {
+ case ProviderObservable.PROPERTY_CHANGE: {
+ provider = ((Provider) evt.getNewValue());
+ break;
+ }
+ case TorStatusObservable.PROPERTY_CHANGE: {
+ if (EipStatus.getInstance().isUpdatingVpnCert()) {
+ handleNewStateOnMain();
+ }
+ break;
+ }
+ case EipStatus.PROPERTY_CHANGE: {
+ previousEipLevel = eipStatus.getEipLevel();
+ eipStatus = (EipStatus) evt.getNewValue();
+ handleNewStateOnMain();
+ break;
+ }
+ default: {}
}
}
diff --git a/app/src/main/java/se/leap/bitmaskclient/base/fragments/GatewaySelectionFragment.java b/app/src/main/java/se/leap/bitmaskclient/base/fragments/GatewaySelectionFragment.java
index 99b1ac39..bb5a06c4 100644
--- a/app/src/main/java/se/leap/bitmaskclient/base/fragments/GatewaySelectionFragment.java
+++ b/app/src/main/java/se/leap/bitmaskclient/base/fragments/GatewaySelectionFragment.java
@@ -44,6 +44,8 @@ import androidx.fragment.app.Fragment;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
+import java.beans.PropertyChangeEvent;
+import java.beans.PropertyChangeListener;
import java.lang.ref.WeakReference;
import java.util.List;
import java.util.Observable;
@@ -64,7 +66,7 @@ interface LocationListSelectionListener {
void onLocationManuallySelected(Location location);
}
-public class GatewaySelectionFragment extends Fragment implements Observer, LocationListSelectionListener, SharedPreferences.OnSharedPreferenceChangeListener {
+public class GatewaySelectionFragment extends Fragment implements PropertyChangeListener, LocationListSelectionListener, SharedPreferences.OnSharedPreferenceChangeListener {
private static final String TAG = GatewaySelectionFragment.class.getSimpleName();
@@ -197,9 +199,9 @@ public class GatewaySelectionFragment extends Fragment implements Observer, Loca
}
@Override
- public void update(Observable o, Object arg) {
- if (o instanceof EipStatus) {
- eipStatus = (EipStatus) o;
+ public void propertyChange(PropertyChangeEvent evt) {
+ if (EipStatus.PROPERTY_CHANGE.equals(evt.getPropertyName())) {
+ eipStatus = (EipStatus) evt.getNewValue();
Activity activity = getActivity();
if (activity != null) {
activity.runOnUiThread(this::updateRecommendedLocation);
diff --git a/app/src/main/java/se/leap/bitmaskclient/base/fragments/NavigationDrawerFragment.java b/app/src/main/java/se/leap/bitmaskclient/base/fragments/NavigationDrawerFragment.java
index 60c21c40..16aea065 100644
--- a/app/src/main/java/se/leap/bitmaskclient/base/fragments/NavigationDrawerFragment.java
+++ b/app/src/main/java/se/leap/bitmaskclient/base/fragments/NavigationDrawerFragment.java
@@ -24,7 +24,7 @@ import static se.leap.bitmaskclient.base.models.Constants.ENABLE_DONATION;
import static se.leap.bitmaskclient.base.models.Constants.PREFERRED_CITY;
import static se.leap.bitmaskclient.base.models.Constants.PROVIDER_KEY;
import static se.leap.bitmaskclient.base.models.Constants.REQUEST_CODE_SWITCH_PROVIDER;
-import static se.leap.bitmaskclient.base.utils.ConfigHelper.isDefaultBitmask;
+import static se.leap.bitmaskclient.base.utils.BuildConfigHelper.isDefaultBitmask;
import static se.leap.bitmaskclient.base.utils.PreferenceHelper.getPreferredCity;
import static se.leap.bitmaskclient.base.utils.PreferenceHelper.getSaveBattery;
import static se.leap.bitmaskclient.base.utils.PreferenceHelper.saveBattery;
@@ -53,8 +53,8 @@ import androidx.core.view.GravityCompat;
import androidx.drawerlayout.widget.DrawerLayout;
import androidx.fragment.app.Fragment;
-import java.util.Observable;
-import java.util.Observer;
+import java.beans.PropertyChangeEvent;
+import java.beans.PropertyChangeListener;
import se.leap.bitmaskclient.BuildConfig;
import se.leap.bitmaskclient.R;
@@ -74,7 +74,7 @@ import se.leap.bitmaskclient.tethering.TetheringObservable;
* See the <a href="https://developer.android.com/design/patterns/navigation-drawer.html#Interaction">
* design guidelines</a> for a complete explanation of the behaviors implemented here.
*/
-public class NavigationDrawerFragment extends Fragment implements SharedPreferences.OnSharedPreferenceChangeListener, Observer {
+public class NavigationDrawerFragment extends Fragment implements SharedPreferences.OnSharedPreferenceChangeListener, PropertyChangeListener {
/**
* Per the design guidelines, you should show the drawer on launch until the user manually
@@ -444,8 +444,8 @@ public class NavigationDrawerFragment extends Fragment implements SharedPreferen
}
@Override
- public void update(Observable o, Object arg) {
- if (o instanceof TetheringObservable || o instanceof EipStatus) {
+ public void propertyChange(PropertyChangeEvent evt) {
+ if (EipStatus.PROPERTY_CHANGE.equals(evt.getPropertyName()) || TetheringObservable.PROPERTY_CHANGE.equals(evt.getPropertyName())) {
try {
getActivity().runOnUiThread(() ->
enableSaveBatteryEntry(!TetheringObservable.getInstance().getTetheringState().isVpnTetheringRunning()));
diff --git a/app/src/main/java/se/leap/bitmaskclient/base/fragments/ObfuscationProxyDialog.java b/app/src/main/java/se/leap/bitmaskclient/base/fragments/ObfuscationProxyDialog.java
index 948d764f..7d12ca70 100644
--- a/app/src/main/java/se/leap/bitmaskclient/base/fragments/ObfuscationProxyDialog.java
+++ b/app/src/main/java/se/leap/bitmaskclient/base/fragments/ObfuscationProxyDialog.java
@@ -15,7 +15,7 @@ import androidx.appcompat.app.AppCompatDialogFragment;
import androidx.appcompat.widget.AppCompatButton;
import androidx.appcompat.widget.AppCompatEditText;
-import se.leap.bitmaskclient.base.utils.ConfigHelper.ObfsVpnHelper;
+import se.leap.bitmaskclient.base.utils.BuildConfigHelper;
import se.leap.bitmaskclient.base.utils.PreferenceHelper;
import se.leap.bitmaskclient.base.views.IconSwitchEntry;
import se.leap.bitmaskclient.databinding.DObfuscationProxyBinding;
@@ -68,12 +68,12 @@ public class ObfuscationProxyDialog extends AppCompatDialogFragment {
dismiss();
});
- useDefaultsButton.setVisibility(ObfsVpnHelper.hasObfuscationPinningDefaults() ? VISIBLE : GONE);
+ useDefaultsButton.setVisibility(BuildConfigHelper.hasObfuscationPinningDefaults() ? VISIBLE : GONE);
useDefaultsButton.setOnClickListener(v -> {
- ipField.setText(ObfsVpnHelper.obfsvpnIP());
- portField.setText(ObfsVpnHelper.obfsvpnPort());
- certificateField.setText(ObfsVpnHelper.obfsvpnCert());
- kcpSwitch.setChecked(ObfsVpnHelper.useKcp());
+ ipField.setText(BuildConfigHelper.obfsvpnIP());
+ portField.setText(BuildConfigHelper.obfsvpnPort());
+ certificateField.setText(BuildConfigHelper.obfsvpnCert());
+ kcpSwitch.setChecked(BuildConfigHelper.useKcp());
});
cancelButton.setOnClickListener(v -> {
diff --git a/app/src/main/java/se/leap/bitmaskclient/base/fragments/SettingsFragment.java b/app/src/main/java/se/leap/bitmaskclient/base/fragments/SettingsFragment.java
index c8c994a5..d7b62de2 100644
--- a/app/src/main/java/se/leap/bitmaskclient/base/fragments/SettingsFragment.java
+++ b/app/src/main/java/se/leap/bitmaskclient/base/fragments/SettingsFragment.java
@@ -8,7 +8,7 @@ import static se.leap.bitmaskclient.base.models.Constants.PREFER_UDP;
import static se.leap.bitmaskclient.base.models.Constants.USE_BRIDGES;
import static se.leap.bitmaskclient.base.models.Constants.USE_IPv6_FIREWALL;
import static se.leap.bitmaskclient.base.models.Constants.USE_OBFUSCATION_PINNING;
-import static se.leap.bitmaskclient.base.utils.ConfigHelper.ObfsVpnHelper.useObfsVpn;
+import static se.leap.bitmaskclient.base.utils.BuildConfigHelper.useObfsVpn;
import static se.leap.bitmaskclient.base.utils.ConfigHelper.isCalyxOSWithTetheringSupport;
import static se.leap.bitmaskclient.base.utils.PreferenceHelper.allowExperimentalTransports;
import static se.leap.bitmaskclient.base.utils.PreferenceHelper.getExcludedApps;
diff --git a/app/src/main/java/se/leap/bitmaskclient/base/fragments/TetheringDialog.java b/app/src/main/java/se/leap/bitmaskclient/base/fragments/TetheringDialog.java
index 588daa3f..05744bc9 100644
--- a/app/src/main/java/se/leap/bitmaskclient/base/fragments/TetheringDialog.java
+++ b/app/src/main/java/se/leap/bitmaskclient/base/fragments/TetheringDialog.java
@@ -22,8 +22,8 @@ import androidx.appcompat.app.AppCompatDialogFragment;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
-import java.util.Observable;
-import java.util.Observer;
+import java.beans.PropertyChangeEvent;
+import java.beans.PropertyChangeListener;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
@@ -52,7 +52,7 @@ import se.leap.bitmaskclient.tethering.TetheringObservable;
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-public class TetheringDialog extends AppCompatDialogFragment implements Observer {
+public class TetheringDialog extends AppCompatDialogFragment implements PropertyChangeListener {
public final static String TAG = TetheringDialog.class.getName();
@@ -241,9 +241,9 @@ public class TetheringDialog extends AppCompatDialogFragment implements Observer
}
@Override
- public void update(Observable o, Object arg) {
- if (o instanceof TetheringObservable) {
- TetheringObservable observable = (TetheringObservable) o;
+ public void propertyChange(PropertyChangeEvent evt) {
+ if (TetheringObservable.PROPERTY_CHANGE.equals(evt.getPropertyName())) {
+ TetheringObservable observable = (TetheringObservable) evt.getNewValue();
Log.d(TAG, "TetheringObservable is updated");
dataset[0].enabled = observable.isWifiTetheringEnabled();
dataset[1].enabled = observable.isUsbTetheringEnabled();
@@ -251,5 +251,4 @@ public class TetheringDialog extends AppCompatDialogFragment implements Observer
adapter.notifyDataSetChanged();
}
}
-
}
diff --git a/app/src/main/java/se/leap/bitmaskclient/base/models/Constants.java b/app/src/main/java/se/leap/bitmaskclient/base/models/Constants.java
index 70bf3943..18590f0b 100644
--- a/app/src/main/java/se/leap/bitmaskclient/base/models/Constants.java
+++ b/app/src/main/java/se/leap/bitmaskclient/base/models/Constants.java
@@ -52,6 +52,7 @@ public interface Constants {
String OBFUSCATION_PINNING_CERT = "obfuscation_pinning_cert";
String OBFUSCATION_PINNING_KCP = "obfuscation_pinning_udp";
String OBFUSCATION_PINNING_LOCATION = "obfuscation_pinning_location";
+ String USE_SYSTEM_PROXY = "usesystemproxy";
//////////////////////////////////////////////
diff --git a/app/src/main/java/se/leap/bitmaskclient/base/models/Provider.java b/app/src/main/java/se/leap/bitmaskclient/base/models/Provider.java
index 14c78cc3..cb9bd520 100644
--- a/app/src/main/java/se/leap/bitmaskclient/base/models/Provider.java
+++ b/app/src/main/java/se/leap/bitmaskclient/base/models/Provider.java
@@ -28,8 +28,8 @@ import static se.leap.bitmaskclient.base.models.Constants.PROVIDER_ALLOWED_REGIS
import static se.leap.bitmaskclient.base.models.Constants.PROVIDER_ALLOW_ANONYMOUS;
import static se.leap.bitmaskclient.base.models.Constants.TRANSPORT;
import static se.leap.bitmaskclient.base.models.Constants.TYPE;
-import static se.leap.bitmaskclient.base.utils.ConfigHelper.ObfsVpnHelper.useObfsVpn;
-import static se.leap.bitmaskclient.base.utils.ConfigHelper.RSAHelper.parseRsaKeyFromString;
+import static se.leap.bitmaskclient.base.utils.BuildConfigHelper.useObfsVpn;
+import static se.leap.bitmaskclient.base.utils.RSAHelper.parseRsaKeyFromString;
import static se.leap.bitmaskclient.providersetup.ProviderAPI.ERRORS;
import android.os.Parcel;
diff --git a/app/src/main/java/se/leap/bitmaskclient/base/models/ProviderObservable.java b/app/src/main/java/se/leap/bitmaskclient/base/models/ProviderObservable.java
index 3e1e1fcc..6e28ac3e 100644
--- a/app/src/main/java/se/leap/bitmaskclient/base/models/ProviderObservable.java
+++ b/app/src/main/java/se/leap/bitmaskclient/base/models/ProviderObservable.java
@@ -2,13 +2,17 @@ package se.leap.bitmaskclient.base.models;
import androidx.annotation.NonNull;
-import java.util.Observable;
+import java.beans.PropertyChangeListener;
+import java.beans.PropertyChangeSupport;
/**
* Created by cyberta on 05.12.18.
*/
-public class ProviderObservable extends Observable {
+public class ProviderObservable {
private static ProviderObservable instance;
+ private final PropertyChangeSupport changeSupport;
+ public static final String PROPERTY_CHANGE = "ProviderObservable";
+
private Provider currentProvider;
private Provider providerForDns;
@@ -19,11 +23,23 @@ public class ProviderObservable extends Observable {
return instance;
}
+ private ProviderObservable() {
+ changeSupport = new PropertyChangeSupport(this);
+ currentProvider = new Provider();
+ }
+
+ public void addObserver(PropertyChangeListener propertyChangeListener) {
+ changeSupport.addPropertyChangeListener(propertyChangeListener);
+ }
+
+ public void deleteObserver(PropertyChangeListener propertyChangeListener) {
+ changeSupport.removePropertyChangeListener(propertyChangeListener);
+ }
+
public synchronized void updateProvider(@NonNull Provider provider) {
instance.currentProvider = provider;
instance.providerForDns = null;
- instance.setChanged();
- instance.notifyObservers();
+ instance.changeSupport.firePropertyChange(PROPERTY_CHANGE, null, provider);
}
public Provider getCurrentProvider() {
diff --git a/app/src/main/java/se/leap/bitmaskclient/base/utils/BuildConfigHelper.java b/app/src/main/java/se/leap/bitmaskclient/base/utils/BuildConfigHelper.java
new file mode 100644
index 00000000..e1f65b5e
--- /dev/null
+++ b/app/src/main/java/se/leap/bitmaskclient/base/utils/BuildConfigHelper.java
@@ -0,0 +1,98 @@
+package se.leap.bitmaskclient.base.utils;
+
+import static se.leap.bitmaskclient.base.models.Constants.DEFAULT_BITMASK;
+
+import androidx.annotation.VisibleForTesting;
+
+import de.blinkt.openvpn.core.NativeUtils;
+import se.leap.bitmaskclient.BuildConfig;
+
+// ObfsVpnHelper class allows us to mock BuildConfig fields related to the pre-shipped circumvention settings
+public class BuildConfigHelper {
+
+ public interface BuildConfigHelperInterface {
+ boolean useObfsVpn();
+ boolean hasObfuscationPinningDefaults();
+ String obfsvpnIP();
+ String obfsvpnPort();
+ String obfsvpnCert();
+ boolean useKcp();
+ boolean isDefaultBitmask();
+ }
+
+ public static class DefaultBuildConfigHelper implements BuildConfigHelperInterface {
+ @Override
+ public boolean useObfsVpn() {
+ return BuildConfig.use_obfsvpn;
+ }
+
+ @Override
+ public boolean hasObfuscationPinningDefaults() {
+ return BuildConfig.obfsvpn_ip != null &&
+ BuildConfig.obfsvpn_port != null &&
+ BuildConfig.obfsvpn_cert != null &&
+ !BuildConfig.obfsvpn_ip.isEmpty() &&
+ !BuildConfig.obfsvpn_port.isEmpty() &&
+ !BuildConfig.obfsvpn_cert.isEmpty();
+ }
+
+ @Override
+ public String obfsvpnIP() {
+ return BuildConfig.obfsvpn_ip;
+ }
+
+ @Override
+ public String obfsvpnPort() {
+ return BuildConfig.obfsvpn_port;
+ }
+
+ @Override
+ public String obfsvpnCert() {
+ return BuildConfig.obfsvpn_cert;
+ }
+
+ @Override
+ public boolean useKcp() {
+ return BuildConfig.obfsvpn_use_kcp;
+ }
+
+ @Override
+ public boolean isDefaultBitmask() {
+ return BuildConfig.FLAVOR_branding.equals(DEFAULT_BITMASK);
+ }
+ }
+
+ private static BuildConfigHelperInterface instance = new DefaultBuildConfigHelper();
+
+ @VisibleForTesting
+ public BuildConfigHelper(BuildConfigHelperInterface helperInterface) {
+ if (!NativeUtils.isUnitTest()) {
+ throw new IllegalStateException("ObfsVpnHelper injected with ObfsVpnHelperInterface outside of an unit test");
+ }
+ instance = helperInterface;
+ }
+
+ public static boolean useObfsVpn() {
+ return instance.useObfsVpn();
+ }
+
+ public static boolean hasObfuscationPinningDefaults() {
+ return instance.hasObfuscationPinningDefaults();
+ }
+ public static String obfsvpnIP() {
+ return instance.obfsvpnIP();
+ }
+ public static String obfsvpnPort() {
+ return instance.obfsvpnPort();
+ }
+ public static String obfsvpnCert() {
+ return instance.obfsvpnCert();
+ }
+ public static boolean useKcp() {
+ return instance.useKcp();
+ }
+
+ public static boolean isDefaultBitmask() {
+ return instance.isDefaultBitmask();
+ }
+}
diff --git a/app/src/main/java/se/leap/bitmaskclient/base/utils/CertificateHelper.java b/app/src/main/java/se/leap/bitmaskclient/base/utils/CertificateHelper.java
new file mode 100644
index 00000000..11202734
--- /dev/null
+++ b/app/src/main/java/se/leap/bitmaskclient/base/utils/CertificateHelper.java
@@ -0,0 +1,64 @@
+package se.leap.bitmaskclient.base.utils;
+
+import androidx.annotation.NonNull;
+import androidx.annotation.VisibleForTesting;
+
+import java.security.MessageDigest;
+import java.security.NoSuchAlgorithmException;
+import java.security.cert.CertificateEncodingException;
+import java.security.cert.X509Certificate;
+
+import de.blinkt.openvpn.core.NativeUtils;
+
+public class CertificateHelper {
+
+ public interface CertificateHelperInterface {
+ String getFingerprintFromCertificate(X509Certificate certificate, String encoding) throws NoSuchAlgorithmException, CertificateEncodingException;
+
+ }
+
+ public static class DefaultCertificateHelper implements CertificateHelperInterface {
+
+ public String byteArrayToHex(byte[] input) {
+ int readBytes = input.length;
+ StringBuffer hexData = new StringBuffer();
+ int onebyte;
+ for (int i = 0; i < readBytes; i++) {
+ onebyte = ((0x000000ff & input[i]) | 0xffffff00);
+ hexData.append(Integer.toHexString(onebyte).substring(6));
+ }
+ return hexData.toString();
+ }
+
+ /**
+ * Calculates the hexadecimal representation of a sha256/sha1 fingerprint of a certificate
+ *
+ * @param certificate
+ * @param encoding
+ * @return
+ * @throws NoSuchAlgorithmException
+ * @throws CertificateEncodingException
+ */
+ @Override
+ public String getFingerprintFromCertificate(X509Certificate certificate, String encoding) throws NoSuchAlgorithmException, CertificateEncodingException {
+ byte[] byteArray = MessageDigest.getInstance(encoding).digest(certificate.getEncoded());
+ return byteArrayToHex(byteArray);
+ }
+ }
+
+ private static CertificateHelperInterface instance = new DefaultCertificateHelper();
+
+ @VisibleForTesting
+ public CertificateHelper(CertificateHelperInterface helperInterface) {
+ if (!NativeUtils.isUnitTest()) {
+ throw new IllegalStateException("CertificateHelper injected with CertificateHelperInterface outside of an unit test");
+ }
+ instance = helperInterface;
+ }
+
+ @NonNull
+ public static String getFingerprintFromCertificate(X509Certificate certificate, String encoding) throws NoSuchAlgorithmException, CertificateEncodingException {
+ return instance.getFingerprintFromCertificate(certificate, encoding);
+ }
+
+}
diff --git a/app/src/main/java/se/leap/bitmaskclient/base/utils/ConfigHelper.java b/app/src/main/java/se/leap/bitmaskclient/base/utils/ConfigHelper.java
index 9289738a..cd5d1fca 100644
--- a/app/src/main/java/se/leap/bitmaskclient/base/utils/ConfigHelper.java
+++ b/app/src/main/java/se/leap/bitmaskclient/base/utils/ConfigHelper.java
@@ -16,8 +16,6 @@
*/
package se.leap.bitmaskclient.base.utils;
-import static se.leap.bitmaskclient.base.models.Constants.DEFAULT_BITMASK;
-
import android.app.PendingIntent;
import android.content.Context;
import android.content.res.Resources;
@@ -36,22 +34,14 @@ import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.math.BigInteger;
-import java.security.KeyFactory;
-import java.security.MessageDigest;
-import java.security.NoSuchAlgorithmException;
-import java.security.NoSuchProviderException;
-import java.security.cert.CertificateEncodingException;
import java.security.cert.CertificateException;
import java.security.cert.CertificateFactory;
import java.security.cert.X509Certificate;
-import java.security.interfaces.RSAPrivateKey;
-import java.security.spec.InvalidKeySpecException;
-import java.security.spec.PKCS8EncodedKeySpec;
import java.util.ArrayList;
-import java.util.Calendar;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
+import de.blinkt.openvpn.core.NativeUtils;
import okhttp3.internal.publicsuffix.PublicSuffixDatabase;
import se.leap.bitmaskclient.BuildConfig;
import se.leap.bitmaskclient.R;
@@ -69,8 +59,6 @@ public class ConfigHelper {
final public static String NG_1024 =
"eeaf0ab9adb38dd69c33f80afa8fc5e86072618775ff3c0b9ea2314c9c256576d674df7496ea81d3383b4813d692c6e0e0d5d8e250b98be48e495c1d6089dad15dc7d7b46154d6b6ce8ef4ad69b15d4982559b297bcf1885c529f566660e57ec68edbc3c05726cc02fd4cbf4976eaa9afd5138fe8376435b9fc61d2fc0eb06e3";
final public static BigInteger G = new BigInteger("2");
- final public static Pattern IPv4_PATTERN = Pattern.compile("^(?:(?:25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9][0-9]|[0-9])\\.){3}(?:25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9][0-9]|[0-9])$");
- final public static Pattern PEM_CERTIFICATE_PATTERN = Pattern.compile("((-----BEGIN CERTIFICATE-----)([A-Za-z0-9+/=\\n]+)(-----END CERTIFICATE-----)+)");
public static boolean checkErroneousDownload(String downloadedString) {
try {
@@ -109,8 +97,8 @@ public class ConfigHelper {
CertificateFactory cf;
try {
cf = CertificateFactory.getInstance("X.509");
-
- Matcher matcher = PEM_CERTIFICATE_PATTERN.matcher(certificateString);
+ Pattern pattern = Pattern.compile("((-----BEGIN CERTIFICATE-----)([A-Za-z0-9+/=\\n]+)(-----END CERTIFICATE-----)+)");
+ Matcher matcher = pattern.matcher(certificateString);
while (matcher.find()) {
String certificate = matcher.group(3);
if (certificate == null) continue;
@@ -131,65 +119,6 @@ public class ConfigHelper {
return null;
}
- public static class RSAHelper {
- public static RSAPrivateKey parseRsaKeyFromString(String rsaKeyString) {
- RSAPrivateKey key;
- try {
- KeyFactory kf;
- if (Build.VERSION.SDK_INT < Build.VERSION_CODES.P) {
- kf = KeyFactory.getInstance("RSA", "BC");
- } else {
- kf = KeyFactory.getInstance("RSA");
- }
- rsaKeyString = rsaKeyString.replaceFirst("-----BEGIN RSA PRIVATE KEY-----", "").replaceFirst("-----END RSA PRIVATE KEY-----", "");
- PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(Base64.decode(rsaKeyString));
- key = (RSAPrivateKey) kf.generatePrivate(keySpec);
- } catch (InvalidKeySpecException e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
- return null;
- } catch (NoSuchAlgorithmException e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
- return null;
- } catch (NullPointerException e) {
- e.printStackTrace();
- return null;
- } catch (NoSuchProviderException e) {
- e.printStackTrace();
- return null;
- }
-
- return key;
- }
- }
-
- private static String byteArrayToHex(byte[] input) {
- int readBytes = input.length;
- StringBuffer hexData = new StringBuffer();
- int onebyte;
- for (int i = 0; i < readBytes; i++) {
- onebyte = ((0x000000ff & input[i]) | 0xffffff00);
- hexData.append(Integer.toHexString(onebyte).substring(6));
- }
- return hexData.toString();
- }
-
- /**
- * Calculates the hexadecimal representation of a sha256/sha1 fingerprint of a certificate
- *
- * @param certificate
- * @param encoding
- * @return
- * @throws NoSuchAlgorithmException
- * @throws CertificateEncodingException
- */
- @NonNull
- public static String getFingerprintFromCertificate(X509Certificate certificate, String encoding) throws NoSuchAlgorithmException, CertificateEncodingException /*, UnsupportedEncodingException*/ {
- byte[] byteArray = MessageDigest.getInstance(encoding).digest(certificate.getEncoded());
- return byteArrayToHex(byteArray);
- }
-
public static void ensureNotOnMainThread(@NonNull Context context) throws IllegalStateException{
Looper looper = Looper.myLooper();
if (looper != null && looper == context.getMainLooper()) {
@@ -198,35 +127,18 @@ public class ConfigHelper {
}
}
- public static boolean isDefaultBitmask() {
- return BuildConfig.FLAVOR_branding.equals(DEFAULT_BITMASK);
- }
-
public static boolean preferAnonymousUsage() {
return BuildConfig.priotize_anonymous_usage;
}
- public static int getCurrentTimezone() {
- return Calendar.getInstance().get(Calendar.ZONE_OFFSET) / 3600000;
- }
-
- public static int timezoneDistance(int local_timezone, int remoteTimezone) {
- // Distance along the numberline of Prime Meridian centric, assumes UTC-11 through UTC+12
- int dist = Math.abs(local_timezone - remoteTimezone);
- // Farther than 12 timezones and it's shorter around the "back"
- if (dist > 12)
- dist = 12 - (dist - 12); // Well i'll be. Absolute values make equations do funny things.
- return dist;
- }
-
/**
*
* @param remoteTimezone
* @return a value between 0.1 and 1.0
*/
public static double getConnectionQualityFromTimezoneDistance(int remoteTimezone) {
- int localTimeZone = ConfigHelper.getCurrentTimezone();
- int distance = ConfigHelper.timezoneDistance(localTimeZone, remoteTimezone);
+ int localTimeZone = TimezoneHelper.getCurrentTimezone();
+ int distance = TimezoneHelper.timezoneDistance(localTimeZone, remoteTimezone);
return Math.max(distance / 12.0, 0.1);
}
@@ -274,7 +186,7 @@ public class ConfigHelper {
if (ipv4 == null) {
return false;
}
- Matcher matcher = IPv4_PATTERN.matcher(ipv4);
+ Matcher matcher = Pattern.compile("^(?:(?:25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9][0-9]|[0-9])\\.){3}(?:25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9][0-9]|[0-9])$").matcher(ipv4);
return matcher.matches();
}
@@ -287,35 +199,6 @@ public class ConfigHelper {
Build.VERSION.SDK_INT >= Build.VERSION_CODES.R;
}
- // ObfsVpnHelper class allows us to mock BuildConfig.use_obfsvpn while
- // not mocking the whole ConfigHelper class
- public static class ObfsVpnHelper {
- public static boolean useObfsVpn() {
- return BuildConfig.use_obfsvpn;
- }
-
- public static boolean hasObfuscationPinningDefaults() {
- return BuildConfig.obfsvpn_ip != null &&
- BuildConfig.obfsvpn_port != null &&
- BuildConfig.obfsvpn_cert != null &&
- !BuildConfig.obfsvpn_ip.isEmpty() &&
- !BuildConfig.obfsvpn_port.isEmpty() &&
- !BuildConfig.obfsvpn_cert.isEmpty();
- }
- public static String obfsvpnIP() {
- return BuildConfig.obfsvpn_ip;
- }
- public static String obfsvpnPort() {
- return BuildConfig.obfsvpn_port;
- }
- public static String obfsvpnCert() {
- return BuildConfig.obfsvpn_cert;
- }
- public static boolean useKcp() {
- return BuildConfig.obfsvpn_use_kcp;
- }
- }
-
public static int getPendingIntentFlags() {
int flags = PendingIntent.FLAG_CANCEL_CURRENT;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
@@ -323,4 +206,11 @@ public class ConfigHelper {
}
return flags;
}
+
+ public static int getTorTimeout() {
+ if (NativeUtils.isUnitTest()) {
+ return 1;
+ }
+ return 180;
+ }
}
diff --git a/app/src/main/java/se/leap/bitmaskclient/base/utils/FileHelper.java b/app/src/main/java/se/leap/bitmaskclient/base/utils/FileHelper.java
index eb1c255c..f1d86876 100644
--- a/app/src/main/java/se/leap/bitmaskclient/base/utils/FileHelper.java
+++ b/app/src/main/java/se/leap/bitmaskclient/base/utils/FileHelper.java
@@ -2,6 +2,8 @@ package se.leap.bitmaskclient.base.utils;
import android.content.Context;
+import androidx.annotation.VisibleForTesting;
+
import java.io.BufferedReader;
import java.io.File;
import java.io.FileWriter;
@@ -9,19 +11,50 @@ import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
+import de.blinkt.openvpn.core.NativeUtils;
+
/**
* Created by cyberta on 18.03.18.
*/
public class FileHelper {
+
+ public interface FileHelperInterface {
+ File createFile(File dir, String fileName);
+ void persistFile(File file, String content) throws IOException;
+ }
+
+ public static class DefaultFileHelper implements FileHelperInterface {
+ @Override
+ public File createFile(File dir, String fileName) {
+ return new File(dir, fileName);
+ }
+
+ @Override
+ public void persistFile(File file, String content) throws IOException {
+ FileWriter writer = new FileWriter(file);
+ writer.write(content);
+ writer.close();
+ }
+ }
+
+ private static FileHelperInterface instance = new DefaultFileHelper();
+
+ @VisibleForTesting
+ public FileHelper(FileHelperInterface helperInterface) {
+ if (!NativeUtils.isUnitTest()) {
+ throw new IllegalStateException("FileHelper injected with FileHelperInterface outside of an unit test");
+ }
+
+ instance = helperInterface;
+ }
+
public static File createFile(File dir, String fileName) {
- return new File(dir, fileName);
+ return instance.createFile(dir, fileName);
}
public static void persistFile(File file, String content) throws IOException {
- FileWriter writer = new FileWriter(file);
- writer.write(content);
- writer.close();
+ instance.persistFile(file, content);
}
public static String readPublicKey(Context context) {
diff --git a/app/src/main/java/se/leap/bitmaskclient/base/utils/HandlerProvider.java b/app/src/main/java/se/leap/bitmaskclient/base/utils/HandlerProvider.java
new file mode 100644
index 00000000..d9198ab7
--- /dev/null
+++ b/app/src/main/java/se/leap/bitmaskclient/base/utils/HandlerProvider.java
@@ -0,0 +1,38 @@
+package se.leap.bitmaskclient.base.utils;
+
+import android.os.Handler;
+import android.os.Looper;
+
+public class HandlerProvider {
+
+
+ public interface HandlerInterface {
+ void postDelayed(Runnable r, long delay);
+ }
+
+
+ private static HandlerInterface instance;
+
+ public HandlerProvider(HandlerInterface handlerInterface) {
+ instance = handlerInterface;
+ }
+ public static HandlerInterface get() {
+ if (instance == null) {
+ instance = new DefaultHandler();
+ }
+ return instance;
+ }
+
+ public static class DefaultHandler implements HandlerInterface {
+ Handler handler;
+
+ public DefaultHandler() {
+ this.handler = new Handler(Looper.getMainLooper());
+ }
+ @Override
+ public void postDelayed(Runnable r, long delay) {
+ this.handler.postDelayed(r, delay);
+ }
+ }
+}
+
diff --git a/app/src/main/java/se/leap/bitmaskclient/base/utils/InputStreamHelper.java b/app/src/main/java/se/leap/bitmaskclient/base/utils/InputStreamHelper.java
index 8e6273a7..6dfe0861 100644
--- a/app/src/main/java/se/leap/bitmaskclient/base/utils/InputStreamHelper.java
+++ b/app/src/main/java/se/leap/bitmaskclient/base/utils/InputStreamHelper.java
@@ -8,14 +8,36 @@ import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
+import de.blinkt.openvpn.core.NativeUtils;
+
/**
* Created by cyberta on 18.03.18.
*/
public class InputStreamHelper {
+ public interface InputStreamHelperInterface {
+ InputStream getInputStreamFrom(String filePath) throws FileNotFoundException;
+
+ }
+
+ private static InputStreamHelperInterface instance = new DefaultInputStreamHelper();
+
+ private static class DefaultInputStreamHelper implements InputStreamHelperInterface {
+ @Override
+ public InputStream getInputStreamFrom(String filePath) throws FileNotFoundException {
+ return new FileInputStream(filePath);
+ }
+ }
+
+ public InputStreamHelper(InputStreamHelperInterface helperInterface) {
+ if (!NativeUtils.isUnitTest()) {
+ throw new IllegalStateException("InputStreamHelper injected with InputStreamHelperInterface outside of an unit test");
+ }
+ instance = helperInterface;
+ }
//allows us to mock FileInputStream
public static InputStream getInputStreamFrom(String filePath) throws FileNotFoundException {
- return new FileInputStream(filePath);
+ return instance.getInputStreamFrom(filePath);
}
public static String loadInputStreamAsString(InputStream is) {
diff --git a/app/src/main/java/se/leap/bitmaskclient/base/utils/PreferenceHelper.java b/app/src/main/java/se/leap/bitmaskclient/base/utils/PreferenceHelper.java
index b35a04cd..2420a797 100644
--- a/app/src/main/java/se/leap/bitmaskclient/base/utils/PreferenceHelper.java
+++ b/app/src/main/java/se/leap/bitmaskclient/base/utils/PreferenceHelper.java
@@ -40,6 +40,7 @@ import static se.leap.bitmaskclient.base.models.Constants.USE_BRIDGES;
import static se.leap.bitmaskclient.base.models.Constants.USE_IPv6_FIREWALL;
import static se.leap.bitmaskclient.base.models.Constants.USE_OBFUSCATION_PINNING;
import static se.leap.bitmaskclient.base.models.Constants.USE_SNOWFLAKE;
+import static se.leap.bitmaskclient.base.models.Constants.USE_SYSTEM_PROXY;
import android.content.Context;
import android.content.SharedPreferences;
@@ -460,12 +461,16 @@ public class PreferenceHelper {
return getBoolean(ALLOW_EXPERIMENTAL_TRANSPORTS, false);
}
+ public static boolean useSystemProxy() {
+ return getBoolean(USE_SYSTEM_PROXY, true);
+ }
+
public static void setUseObfuscationPinning(Boolean pinning) {
putBoolean(USE_OBFUSCATION_PINNING, pinning);
}
public static boolean useObfuscationPinning() {
- return ConfigHelper.ObfsVpnHelper.useObfsVpn() &&
+ return BuildConfigHelper.useObfsVpn() &&
getUseBridges() &&
getBoolean(USE_OBFUSCATION_PINNING, false) &&
!TextUtils.isEmpty(getObfuscationPinningIP()) &&
diff --git a/app/src/main/java/se/leap/bitmaskclient/base/utils/RSAHelper.java b/app/src/main/java/se/leap/bitmaskclient/base/utils/RSAHelper.java
new file mode 100644
index 00000000..2872139a
--- /dev/null
+++ b/app/src/main/java/se/leap/bitmaskclient/base/utils/RSAHelper.java
@@ -0,0 +1,72 @@
+package se.leap.bitmaskclient.base.utils;
+
+import android.os.Build;
+
+import androidx.annotation.VisibleForTesting;
+
+import org.spongycastle.util.encoders.Base64;
+
+import java.security.KeyFactory;
+import java.security.NoSuchAlgorithmException;
+import java.security.NoSuchProviderException;
+import java.security.interfaces.RSAPrivateKey;
+import java.security.spec.InvalidKeySpecException;
+import java.security.spec.PKCS8EncodedKeySpec;
+
+import de.blinkt.openvpn.core.NativeUtils;
+
+public class RSAHelper {
+
+ public interface RSAHelperInterface {
+ RSAPrivateKey parseRsaKeyFromString(String rsaKeyString);
+ }
+
+ public static class DefaultRSAHelper implements RSAHelperInterface {
+
+ @Override
+ public RSAPrivateKey parseRsaKeyFromString(String rsaKeyString) {
+ RSAPrivateKey key;
+ try {
+ KeyFactory kf;
+ if (Build.VERSION.SDK_INT < Build.VERSION_CODES.P) {
+ kf = KeyFactory.getInstance("RSA", "BC");
+ } else {
+ kf = KeyFactory.getInstance("RSA");
+ }
+ rsaKeyString = rsaKeyString.replaceFirst("-----BEGIN RSA PRIVATE KEY-----", "").replaceFirst("-----END RSA PRIVATE KEY-----", "");
+ PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(Base64.decode(rsaKeyString));
+ key = (RSAPrivateKey) kf.generatePrivate(keySpec);
+ } catch (InvalidKeySpecException e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ return null;
+ } catch (NoSuchAlgorithmException e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ return null;
+ } catch (NullPointerException e) {
+ e.printStackTrace();
+ return null;
+ } catch (NoSuchProviderException e) {
+ e.printStackTrace();
+ return null;
+ }
+
+ return key;
+ }
+ }
+
+ private static RSAHelperInterface instance = new DefaultRSAHelper();
+
+ @VisibleForTesting
+ public RSAHelper(RSAHelperInterface helperInterface) {
+ if (!NativeUtils.isUnitTest()) {
+ throw new IllegalStateException("RSAHelper injected with RSAHelperInterface outside of an unit test");
+ }
+ instance = helperInterface;
+ }
+
+ public static RSAPrivateKey parseRsaKeyFromString(String rsaKeyString) {
+ return instance.parseRsaKeyFromString(rsaKeyString);
+ }
+}
diff --git a/app/src/main/java/se/leap/bitmaskclient/base/utils/TimezoneHelper.java b/app/src/main/java/se/leap/bitmaskclient/base/utils/TimezoneHelper.java
new file mode 100644
index 00000000..63b12fd3
--- /dev/null
+++ b/app/src/main/java/se/leap/bitmaskclient/base/utils/TimezoneHelper.java
@@ -0,0 +1,47 @@
+package se.leap.bitmaskclient.base.utils;
+
+import androidx.annotation.VisibleForTesting;
+
+import java.util.Calendar;
+
+import de.blinkt.openvpn.core.NativeUtils;
+
+public class TimezoneHelper {
+
+ public interface TimezoneInterface {
+ int getCurrentTimezone();
+ }
+
+ private static TimezoneInterface instance = new DefaultTimezoneHelper();
+
+ @VisibleForTesting
+ public TimezoneHelper(TimezoneInterface timezoneInterface) {
+ if (!NativeUtils.isUnitTest()) {
+ throw new IllegalStateException("TimezoneHelper injected with timezoneInterface outside of an unit test");
+ }
+ instance = timezoneInterface;
+ }
+
+ public static TimezoneInterface get() {
+ return instance;
+ }
+
+ public static int timezoneDistance(int localTimezone, int remoteTimezone) { // Distance along the numberline of Prime Meridian centric, assumes UTC-11 through UTC+12
+ int dist = Math.abs(localTimezone - remoteTimezone);
+ // Farther than 12 timezones and it's shorter around the "back"
+ if (dist > 12)
+ dist = 12 - (dist - 12); // Well i'll be. Absolute values make equations do funny things.
+ return dist;
+ }
+
+ public static int getCurrentTimezone() {
+ return get().getCurrentTimezone();
+ }
+
+ private static class DefaultTimezoneHelper implements TimezoneInterface {
+ @Override
+ public int getCurrentTimezone() {
+ return Calendar.getInstance().get(Calendar.ZONE_OFFSET) / 3600000;
+ }
+ }
+}
diff --git a/app/src/main/java/se/leap/bitmaskclient/eip/EIP.java b/app/src/main/java/se/leap/bitmaskclient/eip/EIP.java
index d8905bca..ed61ca13 100644
--- a/app/src/main/java/se/leap/bitmaskclient/eip/EIP.java
+++ b/app/src/main/java/se/leap/bitmaskclient/eip/EIP.java
@@ -67,6 +67,8 @@ import androidx.localbroadcastmanager.content.LocalBroadcastManager;
import org.json.JSONException;
import org.json.JSONObject;
+import java.beans.PropertyChangeEvent;
+import java.beans.PropertyChangeListener;
import java.io.Closeable;
import java.lang.ref.WeakReference;
import java.util.Observable;
@@ -97,7 +99,7 @@ import se.leap.bitmaskclient.eip.GatewaysManager.GatewayOptions;
* @author Sean Leonard <meanderingcode@aetherislands.net>
* @author Parménides GV <parmegv@sdf.org>
*/
-public final class EIP extends JobIntentService implements Observer {
+public final class EIP extends JobIntentService implements PropertyChangeListener {
public final static String TAG = EIP.class.getSimpleName(),
@@ -160,9 +162,9 @@ public final class EIP extends JobIntentService implements Observer {
* update eipStatus whenever it changes
*/
@Override
- public void update(Observable observable, Object data) {
- if (observable instanceof EipStatus) {
- eipStatus = (EipStatus) observable;
+ public void propertyChange(PropertyChangeEvent evt) {
+ if (EipStatus.PROPERTY_CHANGE.equals(evt.getPropertyName())) {
+ eipStatus = (EipStatus) evt.getNewValue();
}
}
diff --git a/app/src/main/java/se/leap/bitmaskclient/eip/EipStatus.java b/app/src/main/java/se/leap/bitmaskclient/eip/EipStatus.java
index 9244f531..c2ba8af3 100644
--- a/app/src/main/java/se/leap/bitmaskclient/eip/EipStatus.java
+++ b/app/src/main/java/se/leap/bitmaskclient/eip/EipStatus.java
@@ -20,10 +20,10 @@ import static de.blinkt.openvpn.core.ConnectionStatus.LEVEL_NONETWORK;
import android.content.Context;
import android.os.AsyncTask;
-import androidx.annotation.VisibleForTesting;
import android.util.Log;
-import java.util.Observable;
+import java.beans.PropertyChangeListener;
+import java.beans.PropertyChangeSupport;
import de.blinkt.openvpn.core.ConnectionStatus;
import de.blinkt.openvpn.core.LogItem;
@@ -34,7 +34,7 @@ import de.blinkt.openvpn.core.VpnStatus;
* EipStatus changes it's state (EipLevel) when ConnectionStatus gets updated by OpenVpnService or
* by VoidVpnService.
*/
-public class EipStatus extends Observable implements VpnStatus.StateListener {
+public class EipStatus implements VpnStatus.StateListener {
public static String TAG = EipStatus.class.getSimpleName();
private static EipStatus currentStatus;
@@ -60,6 +60,9 @@ public class EipStatus extends Observable implements VpnStatus.StateListener {
private int localizedResId;
private boolean isUpdatingVPNCertificate;
+ private final PropertyChangeSupport propertyChange;
+ public static final String PROPERTY_CHANGE = "EipStatus";
+
public static EipStatus getInstance() {
if (currentStatus == null) {
currentStatus = new EipStatus();
@@ -69,18 +72,18 @@ public class EipStatus extends Observable implements VpnStatus.StateListener {
}
private EipStatus() {
+ propertyChange = new PropertyChangeSupport(this);
}
@Override
public void updateState(final String state, final String logmessage, final int localizedResId, final ConnectionStatus level) {
- ConnectionStatus tmp = currentStatus.getLevel();
- currentStatus = getInstance();
- currentStatus.setState(state);
- currentStatus.setLogMessage(logmessage);
- currentStatus.setLocalizedResId(localizedResId);
- currentStatus.setLevel(level);
- currentStatus.setEipLevel(level);
- if (tmp != currentStatus.getLevel() || "RECONNECTING".equals(state) || "UI_CONNECTING".equals(state)) {
+ ConnectionStatus tmp = getInstance().getLevel();
+ getInstance().setState(state);
+ getInstance().setLogMessage(logmessage);
+ getInstance().setLocalizedResId(localizedResId);
+ getInstance().setLevel(level);
+ getInstance().setEipLevel(level);
+ if (tmp != getInstance().getLevel() || "RECONNECTING".equals(state) || "UI_CONNECTING".equals(state)) {
refresh();
}
}
@@ -90,13 +93,13 @@ public class EipStatus extends Observable implements VpnStatus.StateListener {
}
public boolean isReconnecting() {
- Log.d(TAG, "eip currentVPNStatus : " + currentStatus.getState() );
- return "RECONNECTING".equals(currentStatus.getState());
+ Log.d(TAG, "eip currentVPNStatus : " + getInstance().getState() );
+ return "RECONNECTING".equals(getInstance().getState());
}
public boolean isVPNRunningWithoutNetwork() {
- return currentStatus.getLevel() == LEVEL_NONETWORK &&
- !"NO_PROCESS".equals(currentStatus.getState());
+ return getInstance().getLevel() == LEVEL_NONETWORK &&
+ !"NO_PROCESS".equals(getInstance().getState());
}
private void setEipLevel(ConnectionStatus level) {
@@ -147,7 +150,7 @@ public class EipStatus extends Observable implements VpnStatus.StateListener {
* @param futureLevel
*/
private void setEipLevelWithDelay(ConnectionStatus futureLevel) {
- new DelayTask(currentStatus.getLevel(), futureLevel).execute();
+ new DelayTask(getInstance().getLevel(), futureLevel).execute();
}
private static class DelayTask extends AsyncTask<Void, Void, Void> {
@@ -169,7 +172,7 @@ public class EipStatus extends Observable implements VpnStatus.StateListener {
}
protected void onPostExecute(Void result) {
- if (currentLevel == currentStatus.getLevel()) {
+ if (currentLevel == getInstance().getLevel()) {
switch (futureLevel) {
case LEVEL_NONETWORK:
currentEipLevel = EipLevel.DISCONNECTED;
@@ -301,8 +304,14 @@ public class EipStatus extends Observable implements VpnStatus.StateListener {
}
public static void refresh() {
- currentStatus.setChanged();
- currentStatus.notifyObservers();
+ currentStatus.propertyChange.firePropertyChange(PROPERTY_CHANGE, null, currentStatus);
+ }
+
+ public void addObserver(PropertyChangeListener propertyChangeListener) {
+ propertyChange.addPropertyChangeListener(propertyChangeListener);
}
+ public void deleteObserver(PropertyChangeListener propertyChangeListener) {
+ propertyChange.removePropertyChangeListener(propertyChangeListener);
+ }
}
diff --git a/app/src/main/java/se/leap/bitmaskclient/eip/GatewaySelector.java b/app/src/main/java/se/leap/bitmaskclient/eip/GatewaySelector.java
index ad95c823..6a0b4b08 100644
--- a/app/src/main/java/se/leap/bitmaskclient/eip/GatewaySelector.java
+++ b/app/src/main/java/se/leap/bitmaskclient/eip/GatewaySelector.java
@@ -1,5 +1,8 @@
package se.leap.bitmaskclient.eip;
+import static se.leap.bitmaskclient.base.utils.TimezoneHelper.timezoneDistance;
+import static se.leap.bitmaskclient.base.utils.TimezoneHelper.getCurrentTimezone;
+
import android.util.Log;
import java.util.ArrayList;
@@ -10,9 +13,6 @@ import java.util.Map;
import java.util.Set;
import java.util.TreeMap;
-import static se.leap.bitmaskclient.base.utils.ConfigHelper.getCurrentTimezone;
-import static se.leap.bitmaskclient.base.utils.ConfigHelper.timezoneDistance;
-
public class GatewaySelector {
private final static String TAG = GatewaySelector.class.getSimpleName();
List<Gateway> gateways;
diff --git a/app/src/main/java/se/leap/bitmaskclient/eip/VoidVpnService.java b/app/src/main/java/se/leap/bitmaskclient/eip/VoidVpnService.java
index b32671ae..f08371c6 100644
--- a/app/src/main/java/se/leap/bitmaskclient/eip/VoidVpnService.java
+++ b/app/src/main/java/se/leap/bitmaskclient/eip/VoidVpnService.java
@@ -33,6 +33,8 @@ import android.os.ParcelFileDescriptor;
import android.system.OsConstants;
import android.util.Log;
+import java.beans.PropertyChangeEvent;
+import java.beans.PropertyChangeListener;
import java.io.IOException;
import java.util.Observable;
import java.util.Observer;
@@ -43,7 +45,7 @@ import se.leap.bitmaskclient.R;
import se.leap.bitmaskclient.base.utils.PreferenceHelper;
-public class VoidVpnService extends VpnService implements Observer, VpnNotificationManager.VpnServiceCallback {
+public class VoidVpnService extends VpnService implements PropertyChangeListener, VpnNotificationManager.VpnServiceCallback {
static final String TAG = VoidVpnService.class.getSimpleName();
private ParcelFileDescriptor fd;
@@ -183,10 +185,11 @@ public class VoidVpnService extends VpnService implements Observer, VpnNotificat
getApplicationContext().startService(startEIP);
}
+
@Override
- public void update(Observable observable, Object arg) {
- if (observable instanceof EipStatus) {
- eipStatus = (EipStatus) observable;
+ public void propertyChange(PropertyChangeEvent evt) {
+ if (EipStatus.PROPERTY_CHANGE.equals(evt.getPropertyName())) {
+ eipStatus = (EipStatus) evt.getNewValue();
}
if (handlerThread.isInterrupted() || !handlerThread.isAlive()) {
return;
diff --git a/app/src/main/java/se/leap/bitmaskclient/eip/VpnConfigGenerator.java b/app/src/main/java/se/leap/bitmaskclient/eip/VpnConfigGenerator.java
index 6d5a406e..4c8fa797 100644
--- a/app/src/main/java/se/leap/bitmaskclient/eip/VpnConfigGenerator.java
+++ b/app/src/main/java/se/leap/bitmaskclient/eip/VpnConfigGenerator.java
@@ -30,7 +30,7 @@ import static se.leap.bitmaskclient.base.models.Constants.REMOTE;
import static se.leap.bitmaskclient.base.models.Constants.TCP;
import static se.leap.bitmaskclient.base.models.Constants.TRANSPORT;
import static se.leap.bitmaskclient.base.models.Constants.UDP;
-import static se.leap.bitmaskclient.base.utils.ConfigHelper.ObfsVpnHelper.useObfsVpn;
+import static se.leap.bitmaskclient.base.utils.BuildConfigHelper.useObfsVpn;
import static se.leap.bitmaskclient.pluggableTransports.ShapeshifterClient.DISPATCHER_IP;
import static se.leap.bitmaskclient.pluggableTransports.ShapeshifterClient.DISPATCHER_PORT;
diff --git a/app/src/main/java/se/leap/bitmaskclient/firewall/FirewallManager.java b/app/src/main/java/se/leap/bitmaskclient/firewall/FirewallManager.java
index 8df1638c..c7a7040f 100644
--- a/app/src/main/java/se/leap/bitmaskclient/firewall/FirewallManager.java
+++ b/app/src/main/java/se/leap/bitmaskclient/firewall/FirewallManager.java
@@ -21,16 +21,16 @@ import android.os.Handler;
import android.os.Looper;
import android.widget.Toast;
-import java.util.Observable;
-import java.util.Observer;
+import java.beans.PropertyChangeEvent;
+import java.beans.PropertyChangeListener;
import de.blinkt.openvpn.core.VpnStatus;
import se.leap.bitmaskclient.R;
+import se.leap.bitmaskclient.base.utils.PreferenceHelper;
import se.leap.bitmaskclient.tethering.TetheringObservable;
import se.leap.bitmaskclient.tethering.TetheringState;
-import se.leap.bitmaskclient.base.utils.PreferenceHelper;
-public class FirewallManager implements FirewallCallback, Observer {
+public class FirewallManager implements FirewallCallback, PropertyChangeListener {
public static String BITMASK_CHAIN = "bitmask_fw";
public static String BITMASK_FORWARD = "bitmask_forward";
public static String BITMASK_POSTROUTING = "bitmask_postrouting";
@@ -150,9 +150,9 @@ public class FirewallManager implements FirewallCallback, Observer {
}
@Override
- public void update(Observable o, Object arg) {
- if (o instanceof TetheringObservable) {
- TetheringObservable observable = (TetheringObservable) o;
+ public void propertyChange(PropertyChangeEvent evt) {
+ if (TetheringObservable.PROPERTY_CHANGE.equals(evt.getPropertyName())) {
+ TetheringObservable observable = (TetheringObservable) evt.getNewValue();
TetheringState state = observable.getTetheringState();
if (state.hasAnyVpnTetheringAllowed() && state.hasAnyDeviceTetheringEnabled()) {
startTethering();
diff --git a/app/src/main/java/se/leap/bitmaskclient/pluggableTransports/ObfsVpnClient.java b/app/src/main/java/se/leap/bitmaskclient/pluggableTransports/ObfsVpnClient.java
index 9d5ddcf9..685349ed 100644
--- a/app/src/main/java/se/leap/bitmaskclient/pluggableTransports/ObfsVpnClient.java
+++ b/app/src/main/java/se/leap/bitmaskclient/pluggableTransports/ObfsVpnClient.java
@@ -4,6 +4,8 @@ import static se.leap.bitmaskclient.base.models.Constants.KCP;
import android.util.Log;
+import java.beans.PropertyChangeEvent;
+import java.beans.PropertyChangeListener;
import java.util.Observable;
import java.util.Observer;
import java.util.concurrent.atomic.AtomicBoolean;
@@ -14,7 +16,7 @@ import de.blinkt.openvpn.core.ConnectionStatus;
import de.blinkt.openvpn.core.VpnStatus;
import se.leap.bitmaskclient.eip.EipStatus;
-public class ObfsVpnClient implements Observer, PtClientInterface {
+public class ObfsVpnClient implements PropertyChangeListener, PtClientInterface {
public static final AtomicInteger SOCKS_PORT = new AtomicInteger(4430);
public static final String SOCKS_IP = "127.0.0.1";
@@ -114,9 +116,9 @@ public class ObfsVpnClient implements Observer, PtClientInterface {
// TODO: register observer!
@Override
- public void update(Observable observable, Object arg) {
- if (observable instanceof EipStatus) {
- EipStatus status = (EipStatus) observable;
+ public void propertyChange(PropertyChangeEvent evt) {
+ if (EipStatus.PROPERTY_CHANGE.equals(evt.getPropertyName())) {
+ EipStatus status = (EipStatus) evt.getNewValue();
if (status.getLevel() == ConnectionStatus.LEVEL_NONETWORK) {
noNetwork = true;
} else {
diff --git a/app/src/main/java/se/leap/bitmaskclient/pluggableTransports/ShapeshifterClient.java b/app/src/main/java/se/leap/bitmaskclient/pluggableTransports/ShapeshifterClient.java
index 102dcf35..e57401f8 100644
--- a/app/src/main/java/se/leap/bitmaskclient/pluggableTransports/ShapeshifterClient.java
+++ b/app/src/main/java/se/leap/bitmaskclient/pluggableTransports/ShapeshifterClient.java
@@ -21,14 +21,14 @@ import android.os.Handler;
import android.os.Looper;
import android.util.Log;
-import java.util.Observable;
-import java.util.Observer;
+import java.beans.PropertyChangeEvent;
+import java.beans.PropertyChangeListener;
import de.blinkt.openvpn.core.ConnectionStatus;
import de.blinkt.openvpn.core.VpnStatus;
import se.leap.bitmaskclient.eip.EipStatus;
-public class ShapeshifterClient implements Observer {
+public class ShapeshifterClient implements PropertyChangeListener {
public static final String DISPATCHER_PORT = "4430";
public static final String DISPATCHER_IP = "127.0.0.1";
@@ -123,10 +123,11 @@ public class ShapeshifterClient implements Observer {
return false;
}
+
@Override
- public void update(Observable observable, Object arg) {
- if (observable instanceof EipStatus) {
- EipStatus status = (EipStatus) observable;
+ public void propertyChange(PropertyChangeEvent evt) {
+ if (EipStatus.PROPERTY_CHANGE.equals(evt.getPropertyName())) {
+ EipStatus status = (EipStatus) evt.getNewValue();
if (status.getLevel() == ConnectionStatus.LEVEL_NONETWORK) {
noNetwork = true;
} else {
diff --git a/app/src/main/java/se/leap/bitmaskclient/providersetup/ProviderApiConnector.java b/app/src/main/java/se/leap/bitmaskclient/providersetup/ProviderApiConnector.java
index 35ad9cd2..cc875c79 100644
--- a/app/src/main/java/se/leap/bitmaskclient/providersetup/ProviderApiConnector.java
+++ b/app/src/main/java/se/leap/bitmaskclient/providersetup/ProviderApiConnector.java
@@ -18,6 +18,8 @@
package se.leap.bitmaskclient.providersetup;
import androidx.annotation.NonNull;
+import androidx.annotation.VisibleForTesting;
+
import android.util.Pair;
import java.io.IOException;
@@ -26,6 +28,9 @@ import java.util.List;
import java.util.Locale;
import java.util.Scanner;
+import javax.net.ssl.SSLHandshakeException;
+
+import de.blinkt.openvpn.core.NativeUtils;
import de.blinkt.openvpn.core.VpnStatus;
import okhttp3.MediaType;
import okhttp3.OkHttpClient;
@@ -39,72 +44,103 @@ import okhttp3.Response;
public class ProviderApiConnector {
- private static final MediaType JSON
- = MediaType.parse("application/json; charset=utf-8");
+ public interface ProviderApiConnectorInterface {
+ boolean delete(OkHttpClient okHttpClient, String deleteUrl) throws RuntimeException, IOException;
+ boolean canConnect(@NonNull OkHttpClient okHttpClient, String url) throws RuntimeException, IOException;
+ String requestStringFromServer(@NonNull String url, @NonNull String requestMethod, String jsonString, @NonNull List<Pair<String, String>> headerArgs, @NonNull OkHttpClient okHttpClient) throws RuntimeException, IOException;
+
+ }
+ public static class DefaultProviderApiCpnnector implements ProviderApiConnectorInterface {
+
+ @Override
+ public boolean delete(OkHttpClient okHttpClient, String deleteUrl) {
+ try {
+ Request.Builder requestBuilder = new Request.Builder()
+ .url(deleteUrl)
+ .delete();
+ Request request = requestBuilder.build();
+
+ Response response = okHttpClient.newCall(request).execute();
+ //response code 401: already logged out
+ if (response.isSuccessful() || response.code() == 401) {
+ return true;
+ }
+ } catch (IOException | RuntimeException e) {
+ return false;
+ }
+
+ return false;
+ }
- public static boolean delete(OkHttpClient okHttpClient, String deleteUrl) {
- try {
+ @Override
+ public boolean canConnect(@NonNull OkHttpClient okHttpClient, String url) throws RuntimeException, IOException {
Request.Builder requestBuilder = new Request.Builder()
- .url(deleteUrl)
- .delete();
+ .url(url)
+ .method("GET", null);
Request request = requestBuilder.build();
Response response = okHttpClient.newCall(request).execute();
- //response code 401: already logged out
- if (response.isSuccessful() || response.code() == 401) {
- return true;
+ if (!response.isSuccessful()) {
+ VpnStatus.logWarning("[API] API request failed canConnect(): " + url);
}
- } catch (IOException | RuntimeException e) {
- return false;
+ return response.isSuccessful();
}
- return false;
- }
+ @Override
+ public String requestStringFromServer(@NonNull String url, @NonNull String requestMethod, String jsonString, @NonNull List<Pair<String, String>> headerArgs, @NonNull OkHttpClient okHttpClient) throws RuntimeException, IOException {
+ RequestBody jsonBody = jsonString != null ? RequestBody.create(JSON, jsonString) : null;
+ Request.Builder requestBuilder = new Request.Builder()
+ .url(url)
+ .method(requestMethod, jsonBody);
+ for (Pair<String, String> keyValPair : headerArgs) {
+ requestBuilder.addHeader(keyValPair.first, keyValPair.second);
+ }
- public static boolean canConnect(@NonNull OkHttpClient okHttpClient, String url) throws RuntimeException, IOException {
- Request.Builder requestBuilder = new Request.Builder()
- .url(url)
- .method("GET", null);
- Request request = requestBuilder.build();
-
- Response response = okHttpClient.newCall(request).execute();
- if (!response.isSuccessful()) {
- VpnStatus.logWarning("[API] API request failed canConnect(): " + url);
+ //TODO: move to getHeaderArgs()?
+ String locale = Locale.getDefault().getLanguage() + Locale.getDefault().getCountry();
+ requestBuilder.addHeader("Accept-Language", locale);
+ Request request = requestBuilder.build();
+
+ Response response = okHttpClient.newCall(request).execute();
+ if (!response.isSuccessful()) {
+ VpnStatus.logWarning("[API] API request failed: " + url);
+ }
+
+ if (response.body() != null) {
+ InputStream inputStream = response.body().byteStream();
+ Scanner scanner = new Scanner(inputStream).useDelimiter("\\A");
+ if (scanner.hasNext()) {
+ String result = scanner.next();
+ response.body().close();
+ return result;
+ }
+ }
+ return null;
}
- return response.isSuccessful();
+ }
+ private static final MediaType JSON = MediaType.parse("application/json; charset=utf-8");
+ private static ProviderApiConnectorInterface instance = new DefaultProviderApiCpnnector();
+ @VisibleForTesting
+ public ProviderApiConnector(ProviderApiConnectorInterface connectorInterface) {
+ if (!NativeUtils.isUnitTest()) {
+ throw new IllegalStateException("ProviderApiConnector injected with ProviderApiConnectorInterface outside of an unit test");
+ }
+ instance = connectorInterface;
}
- public static String requestStringFromServer(@NonNull String url, @NonNull String request_method, String jsonString, @NonNull List<Pair<String, String>> headerArgs, @NonNull OkHttpClient okHttpClient) throws RuntimeException, IOException {
- RequestBody jsonBody = jsonString != null ? RequestBody.create(JSON, jsonString) : null;
- Request.Builder requestBuilder = new Request.Builder()
- .url(url)
- .method(request_method, jsonBody);
- for (Pair<String, String> keyValPair : headerArgs) {
- requestBuilder.addHeader(keyValPair.first, keyValPair.second);
- }
+ public static boolean delete(OkHttpClient okHttpClient, String deleteUrl) throws RuntimeException, IOException {
+ return instance.delete(okHttpClient, deleteUrl);
+ }
- //TODO: move to getHeaderArgs()?
- String locale = Locale.getDefault().getLanguage() + Locale.getDefault().getCountry();
- requestBuilder.addHeader("Accept-Language", locale);
- Request request = requestBuilder.build();
+ public static boolean canConnect(@NonNull OkHttpClient okHttpClient, String url) throws RuntimeException, IOException {
+ return instance.canConnect(okHttpClient, url);
- Response response = okHttpClient.newCall(request).execute();
- if (!response.isSuccessful()) {
- VpnStatus.logWarning("[API] API request failed: " + url);
- }
+ }
- if (response.body() != null) {
- InputStream inputStream = response.body().byteStream();
- Scanner scanner = new Scanner(inputStream).useDelimiter("\\A");
- if (scanner.hasNext()) {
- String result = scanner.next();
- response.body().close();
- return result;
- }
- }
- return null;
+ public static String requestStringFromServer(@NonNull String url, @NonNull String requestMethod, String jsonString, @NonNull List<Pair<String, String>> headerArgs, @NonNull OkHttpClient okHttpClient) throws RuntimeException, IOException {
+ return instance.requestStringFromServer(url, requestMethod, jsonString, headerArgs, okHttpClient);
}
}
diff --git a/app/src/main/java/se/leap/bitmaskclient/providersetup/ProviderApiManagerBase.java b/app/src/main/java/se/leap/bitmaskclient/providersetup/ProviderApiManagerBase.java
index 93648bb0..1f737b0c 100644
--- a/app/src/main/java/se/leap/bitmaskclient/providersetup/ProviderApiManagerBase.java
+++ b/app/src/main/java/se/leap/bitmaskclient/providersetup/ProviderApiManagerBase.java
@@ -45,9 +45,10 @@ import static se.leap.bitmaskclient.base.models.Provider.CA_CERT;
import static se.leap.bitmaskclient.base.models.Provider.GEOIP_URL;
import static se.leap.bitmaskclient.base.models.Provider.PROVIDER_API_IP;
import static se.leap.bitmaskclient.base.models.Provider.PROVIDER_IP;
-import static se.leap.bitmaskclient.base.utils.ConfigHelper.RSAHelper.parseRsaKeyFromString;
+import static se.leap.bitmaskclient.base.utils.ConfigHelper.getTorTimeout;
+import static se.leap.bitmaskclient.base.utils.RSAHelper.parseRsaKeyFromString;
import static se.leap.bitmaskclient.base.utils.ConfigHelper.getDomainFromMainURL;
-import static se.leap.bitmaskclient.base.utils.ConfigHelper.getFingerprintFromCertificate;
+import static se.leap.bitmaskclient.base.utils.CertificateHelper.getFingerprintFromCertificate;
import static se.leap.bitmaskclient.base.utils.ConfigHelper.getProviderFormattedString;
import static se.leap.bitmaskclient.base.utils.PreferenceHelper.deleteProviderDetailsFromPreferences;
import static se.leap.bitmaskclient.base.utils.PreferenceHelper.getFromPersistedProvider;
@@ -380,7 +381,7 @@ public abstract class ProviderApiManagerBase {
if (TorStatusObservable.getStatus() == ON) {
return;
}
- TorStatusObservable.waitUntil(this::isTorOnOrCancelled, 180);
+ TorStatusObservable.waitUntil(this::isTorOnOrCancelled, getTorTimeout());
}
private boolean isTorOnOrCancelled() {
@@ -1138,9 +1139,13 @@ public abstract class ProviderApiManagerBase {
String deleteUrl = provider.getApiUrlWithVersion() + "/logout";
- if (ProviderApiConnector.delete(okHttpClient, deleteUrl)) {
- LeapSRPSession.setToken("");
- return true;
+ try {
+ if (ProviderApiConnector.delete(okHttpClient, deleteUrl)) {
+ LeapSRPSession.setToken("");
+ return true;
+ }
+ } catch (IOException e) {
+ // eat me
}
return false;
}
diff --git a/app/src/main/java/se/leap/bitmaskclient/providersetup/ProviderSetupObservable.java b/app/src/main/java/se/leap/bitmaskclient/providersetup/ProviderSetupObservable.java
index 90a32fea..c882b0bb 100644
--- a/app/src/main/java/se/leap/bitmaskclient/providersetup/ProviderSetupObservable.java
+++ b/app/src/main/java/se/leap/bitmaskclient/providersetup/ProviderSetupObservable.java
@@ -16,14 +16,19 @@ package se.leap.bitmaskclient.providersetup;
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-import android.os.Handler;
-import android.os.Looper;
-
-import java.util.Observable;
+import java.beans.PropertyChangeListener;
+import java.beans.PropertyChangeSupport;
+import se.leap.bitmaskclient.base.utils.HandlerProvider;
+import se.leap.bitmaskclient.base.utils.HandlerProvider.HandlerInterface;
import se.leap.bitmaskclient.tor.TorStatusObservable;
-public class ProviderSetupObservable extends Observable {
+/**
+ * This Observable tracks the progress of a started provider bootstrapping attempt.
+ * Each required API call us taken into account as well as the state of tor's bootstrapping in case
+ * it is used for censorship circumvention.
+ */
+public class ProviderSetupObservable {
private static final String TAG = ProviderSetupObservable.class.getSimpleName();
@@ -36,9 +41,28 @@ public class ProviderSetupObservable extends Observable {
public static final int DOWNLOADED_VPN_CERTIFICATE = 100;
private static ProviderSetupObservable instance;
- private final Handler handler = new Handler(Looper.getMainLooper());
+ private final PropertyChangeSupport changeSupport;
+ public static final String PROPERTY_CHANGE = "ProviderSetupObservable";
+ private final HandlerInterface handler;
private long lastUpdate = 0;
+
+
+ private ProviderSetupObservable() {
+ handler = HandlerProvider.get();
+ changeSupport = new PropertyChangeSupport(this);
+
+ }
+
+ public void addObserver(PropertyChangeListener propertyChangeListener) {
+ changeSupport.addPropertyChangeListener(propertyChangeListener);
+ }
+
+ public void deleteObserver(PropertyChangeListener propertyChangeListener) {
+ changeSupport.removePropertyChangeListener(propertyChangeListener);
+ }
+
+
public static ProviderSetupObservable getInstance() {
if (instance == null) {
instance = new ProviderSetupObservable();
@@ -58,8 +82,8 @@ public class ProviderSetupObservable extends Observable {
getInstance().progress = progress;
}
- getInstance().setChanged();
- getInstance().notifyObservers();
+ getInstance().changeSupport.firePropertyChange(PROPERTY_CHANGE, null, getInstance());
+
}, now - getInstance().lastUpdate < 500L ? 500L : 0L);
getInstance().lastUpdate = System.currentTimeMillis() + 500;
}
@@ -72,8 +96,7 @@ public class ProviderSetupObservable extends Observable {
getInstance().handler.postDelayed(() -> {
getInstance().progress = (TorStatusObservable.getBootstrapProgress()) / 2;
- getInstance().setChanged();
- getInstance().notifyObservers();
+ getInstance().changeSupport.firePropertyChange(PROPERTY_CHANGE, null, getInstance());
}, now - getInstance().lastUpdate < 500L ? 500L : 0);
getInstance().lastUpdate = System.currentTimeMillis() + 500;
}
@@ -84,8 +107,7 @@ public class ProviderSetupObservable extends Observable {
public static void reset() {
getInstance().progress = 0;
- getInstance().setChanged();
- getInstance().notifyObservers();
+ getInstance().changeSupport.firePropertyChange(PROPERTY_CHANGE, null, getInstance());
}
public static void cancel() {
diff --git a/app/src/main/java/se/leap/bitmaskclient/providersetup/SetupViewPagerAdapter.java b/app/src/main/java/se/leap/bitmaskclient/providersetup/SetupViewPagerAdapter.java
index 00630f39..fb190dc2 100644
--- a/app/src/main/java/se/leap/bitmaskclient/providersetup/SetupViewPagerAdapter.java
+++ b/app/src/main/java/se/leap/bitmaskclient/providersetup/SetupViewPagerAdapter.java
@@ -1,6 +1,6 @@
package se.leap.bitmaskclient.providersetup;
-import static se.leap.bitmaskclient.base.utils.ConfigHelper.isDefaultBitmask;
+import static se.leap.bitmaskclient.base.utils.BuildConfigHelper.isDefaultBitmask;
import static se.leap.bitmaskclient.providersetup.fragments.SetupFragmentFactory.CIRCUMVENTION_SETUP_FRAGMENT;
import static se.leap.bitmaskclient.providersetup.fragments.SetupFragmentFactory.CONFIGURE_PROVIDER_FRAGMENT;
import static se.leap.bitmaskclient.providersetup.fragments.SetupFragmentFactory.NOTIFICATION_PERMISSON_EDUCATIONAL_FRAGMENT;
diff --git a/app/src/main/java/se/leap/bitmaskclient/providersetup/activities/SetupActivity.java b/app/src/main/java/se/leap/bitmaskclient/providersetup/activities/SetupActivity.java
index b258a100..9235daad 100644
--- a/app/src/main/java/se/leap/bitmaskclient/providersetup/activities/SetupActivity.java
+++ b/app/src/main/java/se/leap/bitmaskclient/providersetup/activities/SetupActivity.java
@@ -3,7 +3,7 @@ package se.leap.bitmaskclient.providersetup.activities;
import static android.view.View.GONE;
import static android.view.View.VISIBLE;
import static androidx.appcompat.app.ActionBar.DISPLAY_SHOW_CUSTOM;
-import static se.leap.bitmaskclient.base.utils.ConfigHelper.isDefaultBitmask;
+import static se.leap.bitmaskclient.base.utils.BuildConfigHelper.isDefaultBitmask;
import static se.leap.bitmaskclient.base.utils.PreferenceHelper.deleteProviderDetailsFromPreferences;
import static se.leap.bitmaskclient.providersetup.fragments.SetupFragmentFactory.CONFIGURE_PROVIDER_FRAGMENT;
import static se.leap.bitmaskclient.tor.TorStatusObservable.TorStatus.OFF;
@@ -100,7 +100,7 @@ public class SetupActivity extends AppCompatActivity implements SetupActivityCal
// indicator views for VPN permission
- Intent requestVpnPermission = VpnService.prepare(this);
+ Intent requestVpnPermission = VpnService.prepare(this.getApplicationContext());
if (requestVpnPermission != null) {
addIndicatorView(indicatorViews);
addIndicatorView(indicatorViews);
diff --git a/app/src/main/java/se/leap/bitmaskclient/providersetup/fragments/CircumventionSetupFragment.java b/app/src/main/java/se/leap/bitmaskclient/providersetup/fragments/CircumventionSetupFragment.java
index 34a93319..cdb8bd78 100644
--- a/app/src/main/java/se/leap/bitmaskclient/providersetup/fragments/CircumventionSetupFragment.java
+++ b/app/src/main/java/se/leap/bitmaskclient/providersetup/fragments/CircumventionSetupFragment.java
@@ -1,8 +1,7 @@
package se.leap.bitmaskclient.providersetup.fragments;
-import static se.leap.bitmaskclient.base.utils.ConfigHelper.isDefaultBitmask;
+import static se.leap.bitmaskclient.base.utils.BuildConfigHelper.isDefaultBitmask;
-import android.content.Context;
import android.graphics.Typeface;
import android.os.Bundle;
import android.view.LayoutInflater;
@@ -17,7 +16,6 @@ import se.leap.bitmaskclient.base.utils.PreferenceHelper;
import se.leap.bitmaskclient.databinding.FCircumventionSetupBinding;
import se.leap.bitmaskclient.providersetup.ProviderManager;
import se.leap.bitmaskclient.providersetup.activities.CancelCallback;
-import se.leap.bitmaskclient.providersetup.activities.SetupActivityCallback;
public class CircumventionSetupFragment extends BaseSetupFragment implements CancelCallback {
diff --git a/app/src/main/java/se/leap/bitmaskclient/providersetup/fragments/ConfigureProviderFragment.java b/app/src/main/java/se/leap/bitmaskclient/providersetup/fragments/ConfigureProviderFragment.java
index ec646cac..8477c302 100644
--- a/app/src/main/java/se/leap/bitmaskclient/providersetup/fragments/ConfigureProviderFragment.java
+++ b/app/src/main/java/se/leap/bitmaskclient/providersetup/fragments/ConfigureProviderFragment.java
@@ -9,7 +9,7 @@ import static se.leap.bitmaskclient.R.string.description_configure_provider_circ
import static se.leap.bitmaskclient.base.models.Constants.BROADCAST_RESULT_CODE;
import static se.leap.bitmaskclient.base.models.Constants.BROADCAST_RESULT_KEY;
import static se.leap.bitmaskclient.base.models.Constants.PROVIDER_KEY;
-import static se.leap.bitmaskclient.base.utils.ConfigHelper.isDefaultBitmask;
+import static se.leap.bitmaskclient.base.utils.BuildConfigHelper.isDefaultBitmask;
import static se.leap.bitmaskclient.base.utils.PreferenceHelper.getUseSnowflake;
import static se.leap.bitmaskclient.base.utils.ViewHelper.animateContainerVisibility;
import static se.leap.bitmaskclient.providersetup.ProviderAPI.CORRECTLY_DOWNLOADED_VPN_CERTIFICATE;
@@ -42,9 +42,9 @@ import androidx.core.content.res.ResourcesCompat;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
+import java.beans.PropertyChangeEvent;
+import java.beans.PropertyChangeListener;
import java.util.List;
-import java.util.Observable;
-import java.util.Observer;
import se.leap.bitmaskclient.R;
import se.leap.bitmaskclient.base.models.Provider;
@@ -57,7 +57,7 @@ import se.leap.bitmaskclient.providersetup.TorLogAdapter;
import se.leap.bitmaskclient.providersetup.activities.CancelCallback;
import se.leap.bitmaskclient.tor.TorStatusObservable;
-public class ConfigureProviderFragment extends BaseSetupFragment implements Observer, CancelCallback, EipSetupListener {
+public class ConfigureProviderFragment extends BaseSetupFragment implements PropertyChangeListener, CancelCallback, EipSetupListener {
private static final String TAG = ConfigureProviderFragment.class.getSimpleName();
@@ -158,8 +158,8 @@ public class ConfigureProviderFragment extends BaseSetupFragment implements Obse
}
@Override
- public void update(Observable o, Object arg) {
- if (o instanceof ProviderSetupObservable) {
+ public void propertyChange(PropertyChangeEvent evt) {
+ if (ProviderSetupObservable.PROPERTY_CHANGE.equals(evt.getPropertyName())) {
Activity activity = getActivity();
if (activity == null || binding == null) {
return;
@@ -206,7 +206,7 @@ public class ConfigureProviderFragment extends BaseSetupFragment implements Obse
if (ignoreProviderAPIUpdates ||
provider == null ||
(setupActivityCallback.getSelectedProvider() != null &&
- !setupActivityCallback.getSelectedProvider().getDomain().equals(provider.getDomain()))) {
+ !setupActivityCallback.getSelectedProvider().getMainUrlString().equals(provider.getMainUrlString()))) {
return;
}
@@ -222,7 +222,9 @@ public class ConfigureProviderFragment extends BaseSetupFragment implements Obse
setupActivityCallback.onProviderSelected(provider);
handler.postDelayed(() -> {
if (!ProviderSetupObservable.isCanceled()) {
- setupActivityCallback.onConfigurationSuccess();
+ if (setupActivityCallback != null) {
+ setupActivityCallback.onConfigurationSuccess();
+ }
}
}, 750);
break;
diff --git a/app/src/main/java/se/leap/bitmaskclient/tethering/TetheringObservable.java b/app/src/main/java/se/leap/bitmaskclient/tethering/TetheringObservable.java
index a25f8c85..5d62b081 100644
--- a/app/src/main/java/se/leap/bitmaskclient/tethering/TetheringObservable.java
+++ b/app/src/main/java/se/leap/bitmaskclient/tethering/TetheringObservable.java
@@ -18,15 +18,19 @@ package se.leap.bitmaskclient.tethering;
import androidx.annotation.NonNull;
-import java.util.Observable;
+import java.beans.PropertyChangeListener;
+import java.beans.PropertyChangeSupport;
-public class TetheringObservable extends Observable {
+public class TetheringObservable {
private static TetheringObservable instance;
private TetheringState tetheringState;
+ private final PropertyChangeSupport changeSupport;
+ public static final String PROPERTY_CHANGE = "TetheringObservable";
private TetheringObservable() {
tetheringState = new TetheringState();
+ changeSupport = new PropertyChangeSupport(this);
}
public static TetheringObservable getInstance() {
@@ -36,10 +40,17 @@ public class TetheringObservable extends Observable {
return instance;
}
+ public void addObserver(PropertyChangeListener propertyChangeListener) {
+ changeSupport.addPropertyChangeListener(propertyChangeListener);
+ }
+
+ public void deleteObserver(PropertyChangeListener propertyChangeListener) {
+ changeSupport.removePropertyChangeListener(propertyChangeListener);
+ }
+
public static void allowVpnWifiTethering(boolean enabled) {
if (getInstance().tetheringState.isVpnWifiTetheringAllowed != enabled) {
getInstance().tetheringState.isVpnWifiTetheringAllowed = enabled;
- getInstance().setChanged();
getInstance().notifyObservers();
}
}
@@ -47,7 +58,6 @@ public class TetheringObservable extends Observable {
public static void allowVpnUsbTethering(boolean enabled) {
if (getInstance().tetheringState.isVpnUsbTetheringAllowed != enabled) {
getInstance().tetheringState.isVpnUsbTetheringAllowed = enabled;
- getInstance().setChanged();
getInstance().notifyObservers();
}
}
@@ -55,7 +65,6 @@ public class TetheringObservable extends Observable {
public static void allowVpnBluetoothTethering(boolean enabled) {
if (getInstance().tetheringState.isVpnBluetoothTetheringAllowed != enabled) {
getInstance().tetheringState.isVpnBluetoothTetheringAllowed = enabled;
- getInstance().setChanged();
getInstance().notifyObservers();
}
}
@@ -70,7 +79,6 @@ public class TetheringObservable extends Observable {
state.wifiAddress = address;
state.lastSeenWifiAddress = address.isEmpty() ? state.lastSeenWifiAddress : address;
state.lastSeenWifiInterface = interfaceName.isEmpty() ? state.lastSeenWifiInterface : interfaceName;
- getInstance().setChanged();
getInstance().notifyObservers();
}
@@ -86,7 +94,6 @@ public class TetheringObservable extends Observable {
state.usbInterface = interfaceName;
state.lastSeenUsbAddress = address.isEmpty() ? state.lastSeenUsbAddress : address;
state.lastSeenUsbInterface = interfaceName.isEmpty() ? state.lastSeenUsbInterface : interfaceName;
- getInstance().setChanged();
getInstance().notifyObservers();
}
}
@@ -101,7 +108,6 @@ public class TetheringObservable extends Observable {
state.bluetoothInterface = interfaceName;
state.lastSeenBluetoothAddress = address.isEmpty() ? state.lastSeenBluetoothAddress : address;
state.lastSeenBluetoothInterface = interfaceName.isEmpty() ? state.lastSeenBluetoothInterface : interfaceName;
- getInstance().setChanged();
getInstance().notifyObservers();
}
}
@@ -121,4 +127,8 @@ public class TetheringObservable extends Observable {
public TetheringState getTetheringState() {
return tetheringState;
}
+
+ private void notifyObservers() {
+ changeSupport.firePropertyChange(PROPERTY_CHANGE, null, getInstance());
+ }
}
diff --git a/app/src/main/java/se/leap/bitmaskclient/tor/ClientTransportPlugin.java b/app/src/main/java/se/leap/bitmaskclient/tor/ClientTransportPlugin.java
index b1c4ca83..f13eb70e 100644
--- a/app/src/main/java/se/leap/bitmaskclient/tor/ClientTransportPlugin.java
+++ b/app/src/main/java/se/leap/bitmaskclient/tor/ClientTransportPlugin.java
@@ -30,6 +30,8 @@ import androidx.annotation.Nullable;
import org.torproject.jni.ClientTransportPluginInterface;
+import java.beans.PropertyChangeEvent;
+import java.beans.PropertyChangeListener;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileNotFoundException;
@@ -38,8 +40,6 @@ import java.io.InputStreamReader;
import java.lang.ref.WeakReference;
import java.util.Collection;
import java.util.HashMap;
-import java.util.Observable;
-import java.util.Observer;
import java.util.Random;
import java.util.Scanner;
import java.util.Vector;
@@ -49,7 +49,7 @@ import java.util.regex.Pattern;
import IPtProxy.IPtProxy;
-public class ClientTransportPlugin implements ClientTransportPluginInterface, Observer {
+public class ClientTransportPlugin implements ClientTransportPluginInterface, PropertyChangeListener {
public static String TAG = ClientTransportPlugin.class.getSimpleName();
private HashMap<String, String> mFronts;
@@ -221,8 +221,8 @@ public class ClientTransportPlugin implements ClientTransportPluginInterface, Ob
}
@Override
- public void update(Observable o, Object arg) {
- if (o instanceof TorStatusObservable) {
+ public void propertyChange(PropertyChangeEvent evt) {
+ if(TorStatusObservable.PROPERTY_CHANGE.equals(evt.getPropertyName())) {
TorStatusObservable.SnowflakeStatus snowflakeStatus = TorStatusObservable.getSnowflakeStatus();
if (snowflakeStatus == this.snowflakeStatus) {
return;
diff --git a/app/src/main/java/se/leap/bitmaskclient/tor/TorStatusObservable.java b/app/src/main/java/se/leap/bitmaskclient/tor/TorStatusObservable.java
index 8bb41dd2..b1ad6084 100644
--- a/app/src/main/java/se/leap/bitmaskclient/tor/TorStatusObservable.java
+++ b/app/src/main/java/se/leap/bitmaskclient/tor/TorStatusObservable.java
@@ -29,8 +29,8 @@ import android.util.Log;
import androidx.annotation.Nullable;
-import java.util.Observable;
-import java.util.Observer;
+import java.beans.PropertyChangeListener;
+import java.beans.PropertyChangeSupport;
import java.util.Vector;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
@@ -39,10 +39,13 @@ import java.util.concurrent.atomic.AtomicBoolean;
import se.leap.bitmaskclient.R;
-public class TorStatusObservable extends Observable {
+public class TorStatusObservable {
private static final String TAG = TorStatusObservable.class.getSimpleName();
+ private final PropertyChangeSupport propertyChange;
+ public static final String PROPERTY_CHANGE = "TorStatusObservable";
+
public interface StatusCondition {
boolean met();
}
@@ -98,6 +101,7 @@ public class TorStatusObservable extends Observable {
private TorStatusObservable() {
torNotificationManager = new TorNotificationManager();
+ propertyChange = new PropertyChangeSupport(this);
}
public static TorStatusObservable getInstance() {
@@ -126,11 +130,11 @@ public class TorStatusObservable extends Observable {
public static boolean waitUntil(StatusCondition condition, int timeout) throws InterruptedException, TimeoutException {
CountDownLatch countDownLatch = new CountDownLatch(1);
final AtomicBoolean conditionMet = new AtomicBoolean(false);
- Observer observer = (o, arg) -> {
- if (condition.met()) {
- countDownLatch.countDown();
- conditionMet.set(true);
- }
+ PropertyChangeListener observer = evt -> {
+ if (condition.met()) {
+ countDownLatch.countDown();
+ conditionMet.set(true);
+ }
};
if (condition.met()) {
// no need to wait
@@ -145,6 +149,14 @@ public class TorStatusObservable extends Observable {
return true;
}
+ public void addObserver(PropertyChangeListener propertyChangeListener) {
+ propertyChange.addPropertyChangeListener(propertyChangeListener);
+ }
+
+ public void deleteObserver(PropertyChangeListener propertyChangeListener) {
+ propertyChange.removePropertyChangeListener(propertyChangeListener);
+ }
+
public static void logSnowflakeMessage(Context context, String message) {
addLog(message);
if (getInstance().status != TorStatus.OFF) {
@@ -191,7 +203,6 @@ public class TorStatusObservable extends Observable {
getInstance().lastSnowflakeLog = context.getString(R.string.snowflake_sending_data);
}
Log.d(TAG, "snowflake status " + getInstance().snowflakeStatus);
- instance.setChanged();
instance.notifyObservers();
}
@@ -230,7 +241,7 @@ public class TorStatusObservable extends Observable {
public static void updateState(Context context, String status, int bootstrapPercent, @Nullable String logKey) {
try {
- Log.d(TAG, "update tor state: " + status + " " + bootstrapPercent + " "+ logKey);
+ // Log.d(TAG, "update tor state: " + status + " " + bootstrapPercent + " "+ logKey);
getInstance().status = TorStatus.valueOf(status);
if (bootstrapPercent != -1) {
getInstance().bootstrapPercent = bootstrapPercent;
@@ -247,7 +258,7 @@ public class TorStatusObservable extends Observable {
getInstance().torNotificationManager.buildTorNotification(context, getStringForCurrentStatus(context), getNotificationLog(), getBootstrapProgress());
}
- instance.setChanged();
+
instance.notifyObservers();
} catch (IllegalStateException e) {
@@ -255,6 +266,10 @@ public class TorStatusObservable extends Observable {
}
}
+ private void notifyObservers() {
+ instance.propertyChange.firePropertyChange(PROPERTY_CHANGE, null, instance);
+ }
+
private static String getStringFor(Context context, String key) {
switch (key) {
case "conn_pt":
@@ -294,13 +309,11 @@ public class TorStatusObservable extends Observable {
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();
}
@@ -345,7 +358,6 @@ public class TorStatusObservable extends Observable {
if (!getInstance().cancelled) {
getInstance().cancelled = true;
getInstance().port = -1;
- getInstance().setChanged();
getInstance().notifyObservers();
}
}
diff --git a/app/src/main/res/layout-xlarge/v_loading_screen.xml b/app/src/main/res/layout-xlarge/v_loading_screen.xml
deleted file mode 100644
index 22b72f29..00000000
--- a/app/src/main/res/layout-xlarge/v_loading_screen.xml
+++ /dev/null
@@ -1,214 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:app="http://schemas.android.com/apk/res-auto"
- xmlns:tools="http://schemas.android.com/tools"
- android:id="@+id/loading_screen"
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:orientation="vertical"
- android:visibility="gone"
- tools:visibility="visible"
- tools:viewBindingIgnore="true"
- >
-
- <androidx.appcompat.widget.AppCompatImageView
- android:layout_width="32dp"
- android:layout_height="32dp"
- android:adjustViewBounds="true"
- app:tint="@color/colorPrimary"
- app:srcCompat="@drawable/action_history"
- android:layout_marginTop="@dimen/loading_screen_icon_vertical_margin"
- android:layout_marginBottom="@dimen/loading_screen_icon_vertical_margin"
- />
-
- <androidx.appcompat.widget.AppCompatTextView
- android:id="@+id/progressbar_title"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:fadingEdge="horizontal"
- android:singleLine="true"
- android:text="@string/configuring_provider"
- android:textAppearance="@style/Base.TextAppearance.AppCompat.Large"
- android:layout_marginTop="@dimen/standard_margin"
- android:layout_marginBottom="@dimen/standard_margin"
- />
-
- <androidx.appcompat.widget.AppCompatTextView
- android:id="@+id/progressbar_description"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:fadingEdge="horizontal"
- android:maxLines="2"
- android:text="@string/configuring_provider"
- android:textAppearance="@style/Base.TextAppearance.AppCompat.Small"
- android:layout_marginTop="@dimen/standard_margin"
- android:layout_marginBottom="@dimen/standard_margin"
- tools:text="test"
- tools:visibility="visible"
-
- />
-
- <ProgressBar
- android:id="@+id/progressbar"
- style="@style/Widget.AppCompat.ProgressBar.Horizontal"
- android:layout_width="fill_parent"
- android:layout_height="wrap_content"
- android:indeterminate="true"
- android:layout_marginTop="@dimen/standard_margin"
- />
-
- <RelativeLayout
- android:id="@+id/connection_detail_header_container"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:layout_marginTop="@dimen/stdpadding"
- >
-
- <androidx.appcompat.widget.AppCompatTextView
- android:id="@+id/btn_connection_detail"
- android:layout_marginTop="@dimen/stdpadding"
- android:paddingLeft="@dimen/stdpadding"
- android:paddingStart="@dimen/stdpadding"
- android:paddingEnd="@dimen/stdpadding"
- android:paddingRight="@dimen/stdpadding"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_alignParentEnd="true"
- android:layout_alignParentRight="true"
- android:layout_alignParentTop="true"
- android:text="@string/show_connection_details"
- android:textColor="@color/colorPrimaryDark"
- android:maxLines="1"
- android:ellipsize="end"
- android:visibility="visible"
- tools:text="@string/hide"
- />
- <androidx.appcompat.widget.AppCompatTextView
- android:id="@+id/connection_details_title"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:layout_alignBaseline="@id/btn_connection_detail"
- android:text="@string/connection_details"
- android:gravity="start"
- android:textAppearance="@style/Base.TextAppearance.AppCompat.Medium"
- android:paddingBottom="@dimen/stdpadding"
- android:paddingStart="4dp"
- android:paddingLeft="4dp"
- android:paddingEnd="4dp"
- android:paddingRight="4dp"
- tools:visibility="visible"
- android:visibility="gone"
- />
- </RelativeLayout>
- <RelativeLayout
- android:id="@+id/connection_detail_container"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:visibility="gone"
- tools:visibility="visible"
- >
-
-
- <androidx.appcompat.widget.AppCompatImageView
- android:id="@+id/tor_icon"
- android:layout_width="35dp"
- android:layout_height="35dp"
- android:src="@drawable/ic_tor"
- android:layout_alignParentLeft="true"
- android:layout_alignParentStart="true"
- android:layout_marginBottom="@dimen/stdpadding"
- />
- <androidx.appcompat.widget.AppCompatTextView
- android:id="@+id/tor_state"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:fadingEdge="horizontal"
- android:maxLines="2"
- android:text="@string/configuring_provider"
- android:textAppearance="@style/Base.TextAppearance.AppCompat.Small"
- android:layout_alignBottom="@id/tor_icon"
- android:layout_toEndOf="@id/tor_icon"
- android:layout_toRightOf="@+id/tor_icon"
- android:layout_alignParentRight="true"
- android:layout_alignParentEnd="true"
- android:gravity="bottom"
- tools:text="test 12321 123 \n sdf,sdf,m\nn 123 "
- android:ellipsize="end"
- tools:visibility="visible"
- />
-
- <androidx.appcompat.widget.AppCompatImageView
- android:id="@+id/snowflake_icon"
- android:layout_width="35dp"
- android:layout_height="35dp"
- android:src="@drawable/ic_snowflake"
- android:layout_below="@id/tor_icon"
- android:layout_alignParentLeft="true"
- android:layout_alignParentStart="true"
- android:layout_marginBottom="@dimen/stdpadding"
- />
- <androidx.appcompat.widget.AppCompatTextView
- android:id="@+id/snowflake_state"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_below="@id/tor_state"
- android:fadingEdge="horizontal"
- android:maxLines="2"
- android:text="@string/configuring_provider"
- android:textAppearance="@style/Base.TextAppearance.AppCompat.Small"
- android:layout_alignTop="@id/snowflake_icon"
- android:layout_alignBottom="@+id/snowflake_icon"
- android:layout_toEndOf="@+id/snowflake_icon"
- android:layout_toRightOf="@+id/snowflake_icon"
- android:layout_alignParentEnd="true"
- android:layout_alignParentRight="true"
- android:paddingBottom="1dp"
- android:gravity="bottom"
- tools:text="test \n another \n and a third \n blkud"
- android:ellipsize="end"
- tools:visibility="visible"
- />
- </RelativeLayout>
- <RelativeLayout
- android:id="@+id/log_container"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:visibility="gone"
- tools:visibility="visible"
- >
- <androidx.appcompat.widget.AppCompatTextView
- android:id="@+id/connection_detail_logs_title"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:text="@string/log_fragment_title"
- android:textAppearance="@style/Base.TextAppearance.AppCompat.Medium"
- android:layout_alignParentTop="true"
- android:paddingStart="4dp"
- android:paddingLeft="4dp"
- android:paddingEnd="4dp"
- android:paddingRight="4dp"
- android:paddingTop="@dimen/stdpadding"
- android:paddingBottom="@dimen/stdpadding"
- />
-
- <androidx.recyclerview.widget.RecyclerView
- android:id="@+id/connection_detail_logs"
- android:layout_below="@+id/connection_detail_logs_title"
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- tools:listitem="@layout/v_log_item"
- android:isScrollContainer="false"
- />
-
- <ImageView
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:layout_alignBottom="@+id/connection_detail_logs"
- android:layout_alignTop="@id/connection_detail_logs"
- android:src="@drawable/v_vertical_gradient"
- android:layout_marginTop="200dp"
- android:importantForAccessibility="no"
- />
- </RelativeLayout>
-
-</LinearLayout> \ No newline at end of file
diff --git a/app/src/main/res/layout-xlarge/v_provider_header.xml b/app/src/main/res/layout-xlarge/v_provider_header.xml
deleted file mode 100644
index 28bcaa6c..00000000
--- a/app/src/main/res/layout-xlarge/v_provider_header.xml
+++ /dev/null
@@ -1,29 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
- android:layout_height="wrap_content"
- android:layout_width="match_parent"
- xmlns:app="http://schemas.android.com/apk/res-auto"
- xmlns:tools="http://schemas.android.com/tools"
- tools:viewBindingIgnore="true">
-
- <androidx.appcompat.widget.AppCompatImageView
- android:id="@+id/provider_header_logo"
- android:layout_width="@dimen/bitmask_logo"
- android:layout_height="@dimen/bitmask_logo"
- android:adjustViewBounds="true"
- app:srcCompat="@drawable/logo" />
-
- <androidx.appcompat.widget.AppCompatTextView
- android:id="@+id/provider_header_text"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:text=""
- android:ellipsize="end"
- android:layout_below="@id/provider_header_logo"
- android:gravity="center_vertical"
- android:textAppearance="@style/Base.TextAppearance.AppCompat.Headline"
- android:layout_marginTop="@dimen/standard_margin"
- android:layout_marginBottom="@dimen/standard_margin"
- />
-
-</RelativeLayout> \ No newline at end of file
diff --git a/app/src/main/res/layout/v_loading_screen.xml b/app/src/main/res/layout/v_loading_screen.xml
deleted file mode 100644
index dd83aa38..00000000
--- a/app/src/main/res/layout/v_loading_screen.xml
+++ /dev/null
@@ -1,213 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:app="http://schemas.android.com/apk/res-auto"
- xmlns:tools="http://schemas.android.com/tools"
- android:id="@+id/loading_screen"
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:orientation="vertical"
- android:visibility="gone"
- tools:visibility="visible"
- tools:viewBindingIgnore="true"
- >
-
- <androidx.appcompat.widget.AppCompatImageView
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:adjustViewBounds="true"
- app:tint="@color/colorPrimary"
- app:srcCompat="@drawable/action_history"
- android:layout_marginTop="@dimen/loading_screen_icon_vertical_margin"
- android:layout_marginBottom="@dimen/loading_screen_icon_vertical_margin"
- />
-
- <androidx.appcompat.widget.AppCompatTextView
- android:id="@+id/progressbar_title"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:fadingEdge="horizontal"
- android:singleLine="true"
- android:text="@string/configuring_provider"
- android:textAppearance="@style/Base.TextAppearance.AppCompat.Medium"
- android:layout_marginTop="@dimen/standard_margin"
- android:layout_marginBottom="@dimen/standard_margin"
- />
-
- <androidx.appcompat.widget.AppCompatTextView
- android:id="@+id/progressbar_description"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:fadingEdge="horizontal"
- android:maxLines="2"
- android:text="@string/configuring_provider"
- android:textAppearance="@style/Base.TextAppearance.AppCompat.Small"
- android:layout_marginTop="@dimen/standard_margin"
- android:layout_marginBottom="@dimen/standard_margin"
- tools:text="test"
- tools:visibility="visible"
- />
-
- <ProgressBar
- android:id="@+id/progressbar"
- style="@style/Widget.AppCompat.ProgressBar.Horizontal"
- android:layout_width="fill_parent"
- android:layout_height="wrap_content"
- android:indeterminate="true"
- android:layout_marginTop="@dimen/standard_margin"
- />
-
-
- <RelativeLayout
- android:id="@+id/connection_detail_header_container"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:layout_marginTop="@dimen/stdpadding"
- >
-
- <androidx.appcompat.widget.AppCompatTextView
- android:id="@+id/btn_connection_detail"
- android:layout_marginTop="@dimen/stdpadding"
- android:paddingLeft="@dimen/stdpadding"
- android:paddingStart="@dimen/stdpadding"
- android:paddingEnd="@dimen/stdpadding"
- android:paddingRight="@dimen/stdpadding"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_alignParentEnd="true"
- android:layout_alignParentRight="true"
- android:layout_alignParentTop="true"
- android:text="@string/show_connection_details"
- android:textColor="@color/colorPrimaryDark"
- android:maxLines="1"
- android:ellipsize="end"
- android:visibility="visible"
- />
- <androidx.appcompat.widget.AppCompatTextView
- android:id="@+id/connection_details_title"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:layout_alignBaseline="@id/btn_connection_detail"
- android:text="@string/connection_details"
- android:gravity="start"
- android:textAppearance="@style/Base.TextAppearance.AppCompat.Medium"
- android:paddingBottom="@dimen/stdpadding"
- android:paddingStart="4dp"
- android:paddingLeft="4dp"
- android:paddingEnd="4dp"
- android:paddingRight="4dp"
- android:visibility="gone"
- />
- </RelativeLayout>
-
- <RelativeLayout
- android:id="@+id/connection_detail_container"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:visibility="gone"
- tools:visibility="visible"
- >
-
- <androidx.appcompat.widget.AppCompatImageView
- android:id="@+id/tor_icon"
- android:layout_width="35dp"
- android:layout_height="35dp"
- android:src="@drawable/ic_tor"
- android:layout_alignParentLeft="true"
- android:layout_alignParentStart="true"
- android:layout_marginBottom="@dimen/stdpadding"
- />
- <androidx.appcompat.widget.AppCompatTextView
- android:id="@+id/tor_state"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:fadingEdge="horizontal"
- android:maxLines="2"
- android:text="@string/configuring_provider"
- android:textAppearance="@style/Base.TextAppearance.AppCompat.Small"
- android:layout_alignBottom="@id/tor_icon"
- android:layout_toEndOf="@id/tor_icon"
- android:layout_toRightOf="@+id/tor_icon"
- android:layout_alignParentRight="true"
- android:layout_alignParentEnd="true"
- android:gravity="bottom"
- tools:text="test 12321 123 \n sdf,sdf,m\nn 123 "
- android:ellipsize="end"
-
- tools:visibility="visible"
- />
-
- <androidx.appcompat.widget.AppCompatImageView
- android:id="@+id/snowflake_icon"
- android:layout_width="35dp"
- android:layout_height="35dp"
- android:src="@drawable/ic_snowflake"
- android:layout_below="@id/tor_icon"
- android:layout_alignParentLeft="true"
- android:layout_alignParentStart="true"
- android:layout_marginBottom="@dimen/stdpadding"
- />
- <androidx.appcompat.widget.AppCompatTextView
- android:id="@+id/snowflake_state"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:layout_below="@id/tor_state"
- android:fadingEdge="horizontal"
- android:maxLines="2"
- android:text="@string/configuring_provider"
- android:textAppearance="@style/Base.TextAppearance.AppCompat.Small"
- android:layout_alignTop="@id/snowflake_icon"
- android:layout_alignBottom="@+id/snowflake_icon"
- android:layout_toEndOf="@+id/snowflake_icon"
- android:layout_toRightOf="@+id/snowflake_icon"
- android:layout_alignParentEnd="true"
- android:layout_alignParentRight="true"
- android:paddingBottom="1dp"
- android:gravity="bottom"
- tools:text="test \n another \n and a third \n blkud"
- android:ellipsize="end"
- tools:visibility="visible"
- />
- </RelativeLayout>
- <RelativeLayout
- android:id="@+id/log_container"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:visibility="gone"
- tools:visibility="visible"
- >
- <androidx.appcompat.widget.AppCompatTextView
- android:id="@+id/connection_detail_logs_title"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:text="@string/log_fragment_title"
- android:textAppearance="@style/Base.TextAppearance.AppCompat.Medium"
- android:layout_alignParentTop="true"
- android:paddingStart="4dp"
- android:paddingLeft="4dp"
- android:paddingEnd="4dp"
- android:paddingRight="4dp"
- android:paddingTop="@dimen/stdpadding"
- android:paddingBottom="@dimen/stdpadding"
- />
-
- <androidx.recyclerview.widget.RecyclerView
- android:id="@+id/connection_detail_logs"
- android:layout_below="@+id/connection_detail_logs_title"
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- tools:listitem="@layout/v_log_item"
- android:isScrollContainer="false"
- />
-
- <ImageView
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:layout_alignBottom="@+id/connection_detail_logs"
- android:layout_alignTop="@id/connection_detail_logs"
- android:src="@drawable/v_vertical_gradient"
- android:layout_marginTop="200dp"
- android:importantForAccessibility="no"
- />
- </RelativeLayout>
-
-</LinearLayout> \ No newline at end of file
diff --git a/app/src/production/java/se/leap/bitmaskclient/providersetup/ProviderApiManager.java b/app/src/production/java/se/leap/bitmaskclient/providersetup/ProviderApiManager.java
index b08f27ef..1f4e7e49 100644
--- a/app/src/production/java/se/leap/bitmaskclient/providersetup/ProviderApiManager.java
+++ b/app/src/production/java/se/leap/bitmaskclient/providersetup/ProviderApiManager.java
@@ -30,7 +30,7 @@ import static se.leap.bitmaskclient.base.models.Constants.BROADCAST_RESULT_KEY;
import static se.leap.bitmaskclient.base.models.Constants.PROVIDER_KEY;
import static se.leap.bitmaskclient.base.models.Constants.PROVIDER_VPN_CERTIFICATE;
import static se.leap.bitmaskclient.base.utils.ConfigHelper.getProviderFormattedString;
-import static se.leap.bitmaskclient.base.utils.ConfigHelper.isDefaultBitmask;
+import static se.leap.bitmaskclient.base.utils.BuildConfigHelper.isDefaultBitmask;
import static se.leap.bitmaskclient.providersetup.ProviderAPI.ERRORS;
import static se.leap.bitmaskclient.providersetup.ProviderSetupFailedDialog.DOWNLOAD_ERRORS.ERROR_CERTIFICATE_PINNING;
import static se.leap.bitmaskclient.providersetup.ProviderSetupFailedDialog.DOWNLOAD_ERRORS.ERROR_CORRUPTED_PROVIDER_JSON;
diff --git a/app/src/test/java/android/content/Intent.java b/app/src/test/java/android/content/Intent.java
new file mode 100644
index 00000000..92211558
--- /dev/null
+++ b/app/src/test/java/android/content/Intent.java
@@ -0,0 +1,61 @@
+package android.content;
+
+import android.os.Bundle;
+import android.os.Parcelable;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+public class Intent {
+ final String[] action = new String[1];
+ final Map<String, Object> fakeExtras = new HashMap<>();
+ final List<String> categories = new ArrayList<>();
+
+ public Intent setAction(String action) {
+ this.action[0] = action;
+ return this;
+ }
+
+ public String getAction() {
+ return action[0];
+ }
+
+ public Intent putExtra(String key, Bundle bundle) {
+ fakeExtras.put(key, bundle);
+ return this;
+ }
+
+ public Bundle getBundleExtra(String key) {
+ Object o = fakeExtras.get(key);
+ if (o != null) {
+ return (Bundle) o;
+ }
+ return null;
+ }
+
+ public Intent putExtra(String key, Parcelable extra) {
+ fakeExtras.put(key, extra);
+ return this;
+ }
+
+ public Parcelable getParcelableExtra(String key) {
+ Object o = fakeExtras.get(key);
+ if (o != null) {
+ return (Parcelable) o;
+ }
+ return null;
+ }
+
+ public Intent addCategory(String key) {
+ categories.add(key);
+ return this;
+ }
+
+ public Set<String> getCategories() {
+ return new HashSet<>(categories);
+ }
+}
diff --git a/app/src/test/java/android/os/Bundle.java b/app/src/test/java/android/os/Bundle.java
new file mode 100644
index 00000000..ea869cb2
--- /dev/null
+++ b/app/src/test/java/android/os/Bundle.java
@@ -0,0 +1,101 @@
+package android.os;
+
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+
+public class Bundle {
+
+ /** An unmodifiable {@code Bundle} that is always {@link #isEmpty() empty}. */
+ public static final Bundle EMPTY;
+
+ /**
+ * Special extras used to denote extras have been stripped off.
+ * @hide
+ */
+ public static final Bundle STRIPPED;
+
+ static {
+ EMPTY = new Bundle();
+
+ STRIPPED = new Bundle();
+ STRIPPED.putInt("STRIPPED", 1);
+ }
+
+ final Map<String, Boolean> fakeBooleanBundle = new HashMap<>();
+ final Map<String, String> fakeStringBundle = new HashMap<>();
+ final Map<String, Integer> fakeIntBundle = new HashMap<>();
+ final Map<String, Parcelable> fakeParcelableBundle = new HashMap<>();
+
+
+ public void putString(String key, String value) {
+ fakeStringBundle.put(key, value);
+ }
+
+ public String getString(String key) {
+ return fakeStringBundle.get(key);
+ }
+
+ public void putBoolean(String key, boolean value) {
+ fakeBooleanBundle.put(key, value);
+ }
+
+ public boolean getBoolean(String key) {
+ return fakeBooleanBundle.getOrDefault(key, false);
+ }
+
+ public void putInt(String key, int value) {
+ fakeIntBundle.put(key, value);
+ }
+
+ public int getInt(String key) {
+ return fakeIntBundle.getOrDefault(key, 0);
+ }
+
+ public void putParcelable(String key, Parcelable value) {
+ fakeParcelableBundle.put(key, value);
+ }
+
+ public Parcelable getParcelable(String key) {
+ return fakeParcelableBundle.get(key);
+ }
+
+ public Object get(String key) {
+ if (fakeBooleanBundle.containsKey(key)) {
+ return fakeBooleanBundle.get(key);
+ } else if (fakeIntBundle.containsKey(key)) {
+ return fakeIntBundle.get(key);
+ } else if (fakeStringBundle.containsKey(key)) {
+ return fakeStringBundle.get(key);
+ } else {
+ return fakeParcelableBundle.get(key);
+ }
+ }
+
+ public Set<String> keySet() {
+ //this whole approach as a drawback:
+ //you should not add the same keys for values of different types
+ HashSet<String> keys = new HashSet<String>();
+ keys.addAll(fakeBooleanBundle.keySet());
+ keys.addAll(fakeIntBundle.keySet());
+ keys.addAll(fakeStringBundle.keySet());
+ keys.addAll(fakeParcelableBundle.keySet());
+ return keys;
+ }
+
+ public boolean containsKey(String key) {
+ return fakeBooleanBundle.containsKey(key) ||
+ fakeStringBundle.containsKey(key) ||
+ fakeIntBundle.containsKey(key) ||
+ fakeParcelableBundle.containsKey(key);
+ }
+
+ public void remove(String key) {
+ fakeBooleanBundle.remove(key);
+ fakeIntBundle.remove(key);
+ fakeParcelableBundle.remove(key);
+ fakeStringBundle.remove(key);
+ }
+
+}
diff --git a/app/src/test/java/android/text/TextUtils.java b/app/src/test/java/android/text/TextUtils.java
new file mode 100644
index 00000000..520944a5
--- /dev/null
+++ b/app/src/test/java/android/text/TextUtils.java
@@ -0,0 +1,6 @@
+package android.text;
+public class TextUtils {
+ public static boolean isEmpty(CharSequence str) {
+ return str == null || str.length() == 0;
+ }
+}
diff --git a/app/src/test/java/android/util/Base64.java b/app/src/test/java/android/util/Base64.java
new file mode 100644
index 00000000..da40e9c4
--- /dev/null
+++ b/app/src/test/java/android/util/Base64.java
@@ -0,0 +1,19 @@
+package android.util;
+
+import java.util.Arrays;
+
+public class Base64 {
+
+ /**
+ * Base64-encode the given data and return a newly allocated
+ * String with the result.
+ *
+ * @param input the data to encode
+ * @param flags controls certain features of the encoded output.
+ * Passing {@code DEFAULT} results in output that
+ * adheres to RFC 2045.
+ */
+ public static String encodeToString(byte[] input, int flags) {
+ return Arrays.toString(java.util.Base64.getEncoder().encode(input));
+ }
+}
diff --git a/app/src/test/java/android/util/Log.java b/app/src/test/java/android/util/Log.java
new file mode 100644
index 00000000..b3162d10
--- /dev/null
+++ b/app/src/test/java/android/util/Log.java
@@ -0,0 +1,23 @@
+package android.util;
+
+public class Log {
+ public static int d(String tag, String msg) {
+ System.out.println("DEBUG: " + tag + ": " + msg);
+ return 0;
+ }
+
+ public static int i(String tag, String msg) {
+ System.out.println("INFO: " + tag + ": " + msg);
+ return 0;
+ }
+
+ public static int w(String tag, String msg) {
+ System.out.println("WARN: " + tag + ": " + msg);
+ return 0;
+ }
+
+ public static int e(String tag, String msg) {
+ System.out.println("ERROR: " + tag + ": " + msg);
+ return 0;
+ }
+} \ No newline at end of file
diff --git a/app/src/test/java/de/blinkt/openvpn/VpnProfileTest.java b/app/src/test/java/de/blinkt/openvpn/VpnProfileTest.java
index a3ac3f92..ad42ffde 100644
--- a/app/src/test/java/de/blinkt/openvpn/VpnProfileTest.java
+++ b/app/src/test/java/de/blinkt/openvpn/VpnProfileTest.java
@@ -2,6 +2,7 @@ package de.blinkt.openvpn;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotEquals;
import static org.junit.Assert.assertNotNull;
import static org.powermock.api.mockito.PowerMockito.mockStatic;
import static org.powermock.api.mockito.PowerMockito.when;
@@ -18,17 +19,16 @@ import org.junit.runner.RunWith;
import org.powermock.core.classloader.annotations.PrepareForTest;
import org.powermock.modules.junit4.PowerMockRunner;
-import java.util.Arrays;
import java.util.UUID;
import de.blinkt.openvpn.core.connection.Obfs4Connection;
import de.blinkt.openvpn.core.connection.OpenvpnConnection;
import se.leap.bitmaskclient.base.models.Transport;
-import se.leap.bitmaskclient.base.utils.ConfigHelper;
+import se.leap.bitmaskclient.base.utils.BuildConfigHelper;
import se.leap.bitmaskclient.pluggableTransports.Obfs4Options;
@RunWith(PowerMockRunner.class)
-@PrepareForTest({UUID.class, ConfigHelper.ObfsVpnHelper.class})
+@PrepareForTest({UUID.class, BuildConfigHelper.class})
public class VpnProfileTest {
private static final String OPENVPNCONNECTION_PROFILE = "{\"mCipher\":\"\",\"mProfileVersion\":7,\"mLastUsed\":0,\"mCheckRemoteCN\":true,\"mVerb\":\"1\",\"mRemoteRandom\":false,\"mRoutenopull\":false,\"mConnectRetry\":\"2\",\"mAllowedAppsVpn\":[],\"mUserEditable\":true,\"mUseUdp\":true,\"mAllowedAppsVpnAreDisallowed\":true,\"mDNS1\":\"8.8.8.8\",\"mDNS2\":\"8.8.4.4\",\"mUseCustomConfig\":false,\"mUseFloat\":false,\"mUseDefaultRoute\":true,\"mConnectRetryMaxTime\":\"300\",\"mNobind\":true,\"mVersion\":0,\"mConnectRetryMax\":\"-1\",\"mOverrideDNS\":false,\"mAuth\":\"\",\"mTunMtu\":0,\"mPassword\":\"\",\"mTLSAuthDirection\":\"\",\"mKeyPassword\":\"\",\"mCustomConfigOptions\":\"\",\"mName\":\"mockProfile\",\"mExpectTLSCert\":false,\"mUsername\":\"\",\"mAllowLocalLAN\":false,\"mDataCiphers\":\"\",\"mSearchDomain\":\"blinkt.de\",\"mTemporaryProfile\":false,\"mUseTLSAuth\":false,\"mRemoteCN\":\"\",\"mCustomRoutesv6\":\"\",\"mPersistTun\":false,\"mX509AuthType\":3,\"mUuid\":\"9d295ca2-3789-48dd-996e-f731dbf50fdc\",\"mServerName\":\"openvpn.example.com\",\"mMssFix\":0,\"mPushPeerInfo\":false,\"mAuthenticationType\":2,\"mBlockUnusedAddressFamilies\":true,\"mServerPort\":\"1194\",\"mUseDefaultRoutev6\":true,\"mConnections\":[{\"mCustomConfiguration\":\"\",\"mUseUdp\":false,\"mServerName\":\"openvpn.example.com\",\"mProxyType\":\"NONE\",\"mProxyPort\":\"8080\",\"mUseCustomConfig\":false,\"mConnectTimeout\":0,\"mProxyName\":\"proxy.example.com\",\"mUseProxyAuth\":false,\"ConnectionAdapter.META_TYPE\":\"de.blinkt.openvpn.core.connection.OpenvpnConnection\",\"mServerPort\":\"1194\",\"mEnabled\":true}],\"mUseLzo\":false,\"mTransportType\":1,\"mAllowAppVpnBypass\":false,\"mUsePull\":true,\"mUseRandomHostname\":false,\"mAuthRetry\":0}";
@@ -45,7 +45,7 @@ public class VpnProfileTest {
@Before
public void setup() {
mockStatic(UUID.class);
- mockStatic(ConfigHelper.ObfsVpnHelper.class);
+ mockStatic(BuildConfigHelper.class);
}
@Test
@@ -77,7 +77,7 @@ public class VpnProfileTest {
@Test
public void toJson_obfs4() throws JSONException {
- when(ConfigHelper.ObfsVpnHelper.useObfsVpn()).thenReturn(false);
+ when(BuildConfigHelper.useObfsVpn()).thenReturn(false);
VpnProfile mockVpnProfile = new VpnProfile("mockProfile", OBFS4);
@@ -85,7 +85,6 @@ public class VpnProfileTest {
mockVpnProfile.mConnections[0] = new Obfs4Connection(new Obfs4Options("192.168.0.1", transport));
mockVpnProfile.mLastUsed = 0;
String s = mockVpnProfile.toJson();
- System.out.println(s);
//ignore UUID in comparison -> set it to fixed value
JSONObject actual = new JSONObject(s);
@@ -97,14 +96,13 @@ public class VpnProfileTest {
@Test
public void toJson_obfs4_obfsvpn() throws JSONException {
- when(ConfigHelper.ObfsVpnHelper.useObfsVpn()).thenReturn(true);
+ when(BuildConfigHelper.useObfsVpn()).thenReturn(true);
VpnProfile mockVpnProfile = new VpnProfile("mockProfile", OBFS4);
Transport.Options options = new Transport.Options("CERT", "1");
Transport transport = new Transport(OBFS4.toString(), new String[]{"tcp"}, new String[]{"1234"}, options);
mockVpnProfile.mConnections[0] = new Obfs4Connection(new Obfs4Options("192.168.0.1", transport));
mockVpnProfile.mLastUsed = 0;
String s = mockVpnProfile.toJson();
- System.out.println(s);
//ignore UUID in comparison -> set it to fixed value
JSONObject actual = new JSONObject(s);
@@ -116,7 +114,7 @@ public class VpnProfileTest {
@Test
public void toJson_obfs4_obfsvpn_kcp() throws JSONException {
- when(ConfigHelper.ObfsVpnHelper.useObfsVpn()).thenReturn(true);
+ when(BuildConfigHelper.useObfsVpn()).thenReturn(true);
VpnProfile mockVpnProfile = new VpnProfile("mockProfile", OBFS4);
Transport.Options options = new Transport.Options("CERT", "1");
@@ -124,7 +122,6 @@ public class VpnProfileTest {
mockVpnProfile.mConnections[0] = new Obfs4Connection(new Obfs4Options("192.168.0.1", transport));
mockVpnProfile.mLastUsed = 0;
String s = mockVpnProfile.toJson();
- System.out.println(s);
//ignore UUID in comparison -> set it to fixed value
JSONObject actual = new JSONObject(s);
@@ -136,7 +133,7 @@ public class VpnProfileTest {
@Test
public void toJson_obfs4hop_kcp() throws JSONException {
- when(ConfigHelper.ObfsVpnHelper.useObfsVpn()).thenReturn(true);
+ when(BuildConfigHelper.useObfsVpn()).thenReturn(true);
VpnProfile mockVpnProfile = new VpnProfile("mockProfile", OBFS4_HOP);
@@ -146,7 +143,6 @@ public class VpnProfileTest {
mockVpnProfile.mLastUsed = 0;
String s = mockVpnProfile.toJson();
- System.out.println(s);
//ignore UUID in comparison -> set it to fixed value
JSONObject actual = new JSONObject(s);
@@ -158,7 +154,7 @@ public class VpnProfileTest {
@Test
public void toJson_obfs4hop_portHopping() throws JSONException {
- when(ConfigHelper.ObfsVpnHelper.useObfsVpn()).thenReturn(true);
+ when(BuildConfigHelper.useObfsVpn()).thenReturn(true);
VpnProfile mockVpnProfile = new VpnProfile("mockProfile", OBFS4_HOP);
@@ -168,7 +164,6 @@ public class VpnProfileTest {
mockVpnProfile.mLastUsed = 0;
String s = mockVpnProfile.toJson();
- System.out.println(s);
//ignore UUID in comparison -> set it to fixed value
JSONObject actual = new JSONObject(s);
@@ -180,7 +175,7 @@ public class VpnProfileTest {
@Test
public void toJson_obfs4hop() throws JSONException {
- when(ConfigHelper.ObfsVpnHelper.useObfsVpn()).thenReturn(true);
+ when(BuildConfigHelper.useObfsVpn()).thenReturn(true);
VpnProfile mockVpnProfile = new VpnProfile("mockProfile", OBFS4_HOP);
Transport.Options options = new Transport.Options("1", new Transport.Endpoint[]{new Transport.Endpoint("1.1.1.1", "CERT1"), new Transport.Endpoint("2.2.2.2", "CERT2")}, 200, 100, true);
@@ -189,7 +184,6 @@ public class VpnProfileTest {
mockVpnProfile.mLastUsed = 0;
String s = mockVpnProfile.toJson();
- System.out.println(s);
//ignore UUID in comparison -> set it to fixed value
JSONObject actual = new JSONObject(s);
@@ -201,7 +195,7 @@ public class VpnProfileTest {
@Test
public void fromJson_obfs4() {
- when(ConfigHelper.ObfsVpnHelper.useObfsVpn()).thenReturn(false);
+ when(BuildConfigHelper.useObfsVpn()).thenReturn(false);
VpnProfile mockVpnProfile = VpnProfile.fromJson(OBFS4CONNECTION_PROFILE);
assertNotNull(mockVpnProfile);
@@ -210,7 +204,10 @@ public class VpnProfileTest {
assertFalse(mockVpnProfile.mConnections[0].isUseUdp());
Obfs4Connection obfs4Connection = (Obfs4Connection) mockVpnProfile.mConnections[0];
assertEquals(OBFS4, obfs4Connection.getTransportType());
- assertFalse(Arrays.asList(obfs4Connection.getObfs4Options().transport.getProtocols()).contains(UDP));
+ String[] protocols = obfs4Connection.getObfs4Options().transport.getProtocols();
+ for (String protocol : protocols) {
+ assertNotEquals(UDP, protocol);
+ }
assertEquals("CERT", obfs4Connection.getObfs4Options().transport.getOptions().getCert());
assertEquals("0", obfs4Connection.getObfs4Options().transport.getOptions().getIatMode());
assertEquals("192.168.0.1", obfs4Connection.getObfs4Options().gatewayIP);
@@ -220,11 +217,11 @@ public class VpnProfileTest {
@Test
public void fromJson_obfs4_obfsvpn() {
- when(ConfigHelper.ObfsVpnHelper.useObfsVpn()).thenReturn(true);
+ when(BuildConfigHelper.useObfsVpn()).thenReturn(true);
VpnProfile mockVpnProfile = VpnProfile.fromJson(OBFS4CONNECTION_PROFILE_OBFSVPN);
assertNotNull(mockVpnProfile);
- assertNotNull(mockVpnProfile.mConnections);
+ assertNotEquals(null, mockVpnProfile.mConnections);
assertNotNull(mockVpnProfile.mConnections[0]);
assertFalse(mockVpnProfile.mConnections[0].isUseUdp());
Obfs4Connection obfs4Connection = (Obfs4Connection) mockVpnProfile.mConnections[0];
@@ -239,7 +236,7 @@ public class VpnProfileTest {
@Test
public void fromJson_obfs4_obfsvpn_kcp() {
- when(ConfigHelper.ObfsVpnHelper.useObfsVpn()).thenReturn(true);
+ when(BuildConfigHelper.useObfsVpn()).thenReturn(true);
VpnProfile mockVpnProfile = VpnProfile.fromJson(OBFS4CONNECTION_PROFILE_OBFSVPN_KCP);
assertNotNull(mockVpnProfile);
diff --git a/app/src/test/java/se/leap/bitmaskclient/base/models/ProviderTest.java b/app/src/test/java/se/leap/bitmaskclient/base/models/ProviderTest.java
index 8bff690b..4fcc6bac 100644
--- a/app/src/test/java/se/leap/bitmaskclient/base/models/ProviderTest.java
+++ b/app/src/test/java/se/leap/bitmaskclient/base/models/ProviderTest.java
@@ -1,34 +1,26 @@
package se.leap.bitmaskclient.base.models;
import static junit.framework.Assert.assertFalse;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotEquals;
import static org.junit.Assert.assertTrue;
-import static org.mockito.Mockito.when;
-import static org.powermock.api.mockito.PowerMockito.mockStatic;
import org.junit.Before;
import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.powermock.core.classloader.annotations.PrepareForTest;
-import org.powermock.modules.junit4.PowerMockRunner;
-import java.util.HashSet;
-import java.util.Set;
-
-import se.leap.bitmaskclient.base.utils.ConfigHelper;
+import se.leap.bitmaskclient.base.utils.BuildConfigHelper;
+import se.leap.bitmaskclient.testutils.MockHelper;
import se.leap.bitmaskclient.testutils.TestSetupHelper;
/**
* Created by cyberta on 12.02.18.
*/
-@RunWith(PowerMockRunner.class)
-@PrepareForTest({ConfigHelper.ObfsVpnHelper.class})
public class ProviderTest {
@Before
public void setup() {
- mockStatic(ConfigHelper.ObfsVpnHelper.class);
- when(ConfigHelper.ObfsVpnHelper.useObfsVpn()).thenReturn(false);
+ BuildConfigHelper buildConfigHelper = MockHelper.mockBuildConfigHelper(false);
}
@Test
@@ -61,14 +53,12 @@ public class ProviderTest {
Provider p2 = TestSetupHelper.getConfiguredProvider();
p2.setMainUrl("http://somethingsdiffer.org");
Provider p3 = new Provider("https://anotherprovider.net");
+ Provider p4 = TestSetupHelper.getConfiguredProvider();
- Set<Provider> defaultProviders = new HashSet<>();
- defaultProviders.add(p1);
- defaultProviders.add(p2);
+ assertEquals(p1, p4);
+ assertNotEquals(p1, p2);
+ assertNotEquals(p1, p3);
- assertTrue(defaultProviders.contains(p1));
- assertTrue(defaultProviders.contains(p2));
- assertFalse(defaultProviders.contains(p3));
}
@Test
@@ -129,8 +119,6 @@ public class ProviderTest {
@Test
public void testSupportsPluggableTransports_Obfs4Kcp_noObsvpn_returnsFalse() throws Exception {
- when(ConfigHelper.ObfsVpnHelper.useObfsVpn()).thenReturn(false);
-
Provider p1 = TestSetupHelper.getProvider(
"https://pt.demo.bitmask.net",
null,
@@ -145,7 +133,7 @@ public class ProviderTest {
@Test
public void testSupportsPluggableTransports_Obfs4Kcp_obsvpn_returnsTrue() throws Exception {
- when(ConfigHelper.ObfsVpnHelper.useObfsVpn()).thenReturn(true);
+ BuildConfigHelper helper = MockHelper.mockBuildConfigHelper(true);
Provider p1 = TestSetupHelper.getProvider(
"https://pt.demo.bitmask.net",
diff --git a/app/src/test/java/se/leap/bitmaskclient/eip/GatewaySelectorTest.java b/app/src/test/java/se/leap/bitmaskclient/eip/GatewaySelectorTest.java
index 74762813..0175745e 100644
--- a/app/src/test/java/se/leap/bitmaskclient/eip/GatewaySelectorTest.java
+++ b/app/src/test/java/se/leap/bitmaskclient/eip/GatewaySelectorTest.java
@@ -1,8 +1,10 @@
package se.leap.bitmaskclient.eip;
-import android.preference.PreferenceManager;
-import android.text.TextUtils;
-import android.util.Log;
+import static junit.framework.Assert.assertEquals;
+import static junit.framework.Assert.assertTrue;
+import static se.leap.bitmaskclient.base.models.Constants.PROVIDER_PRIVATE_KEY;
+import static se.leap.bitmaskclient.base.models.Constants.PROVIDER_VPN_CERTIFICATE;
+import static se.leap.bitmaskclient.testutils.TestSetupHelper.getInputAsString;
import com.tngtech.java.junit.dataprovider.DataProvider;
import com.tngtech.java.junit.dataprovider.DataProviderRunner;
@@ -14,35 +16,22 @@ import org.json.JSONObject;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
-import org.powermock.core.classloader.annotations.PrepareForTest;
-import org.powermock.modules.junit4.PowerMockRunner;
-import org.powermock.modules.junit4.PowerMockRunnerDelegate;
import java.io.IOException;
import java.util.ArrayList;
+import java.util.List;
+import java.util.Vector;
import de.blinkt.openvpn.core.ConfigParser;
import se.leap.bitmaskclient.base.models.Provider;
-import se.leap.bitmaskclient.base.utils.ConfigHelper;
import se.leap.bitmaskclient.base.utils.PreferenceHelper;
+import se.leap.bitmaskclient.base.utils.TimezoneHelper;
import se.leap.bitmaskclient.testutils.MockSharedPreferences;
-import static junit.framework.Assert.assertEquals;
-import static junit.framework.Assert.assertTrue;
-import static org.mockito.ArgumentMatchers.anyInt;
-import static org.powermock.api.mockito.PowerMockito.mockStatic;
-import static org.powermock.api.mockito.PowerMockito.when;
-import static se.leap.bitmaskclient.base.models.Constants.PROVIDER_PRIVATE_KEY;
-import static se.leap.bitmaskclient.base.models.Constants.PROVIDER_VPN_CERTIFICATE;
-import static se.leap.bitmaskclient.testutils.MockHelper.mockTextUtils;
-import static se.leap.bitmaskclient.testutils.TestSetupHelper.getInputAsString;
-
/**
* Created by cyberta on 18.12.18.
*/
-@RunWith(PowerMockRunner.class)
-@PowerMockRunnerDelegate(DataProviderRunner.class)
-@PrepareForTest({ConfigHelper.class, TextUtils.class})
+@RunWith(DataProviderRunner.class)
public class GatewaySelectorTest {
public static final String TAG = GatewaySelectorTest.class.getSimpleName();
@@ -72,23 +61,26 @@ public class GatewaySelectorTest {
PreferenceHelper preferenceHelper;
- GatewaySelector gatewaySelector;
JSONObject eipDefinition;
- ArrayList<Gateway> gatewayList = new ArrayList<>();
-
@Before
- public void setup() throws IOException, JSONException, ConfigParser.ConfigParseError {
- mockStatic(ConfigHelper.class);
- when(ConfigHelper.timezoneDistance(anyInt(), anyInt())).thenCallRealMethod();
- mockTextUtils();
+ public void setup() throws IOException, JSONException {
preferenceHelper = new PreferenceHelper(new MockSharedPreferences());
eipDefinition = new JSONObject(getInputAsString(getClass().getClassLoader().getResourceAsStream("eip-service-four-gateways.json")));
- JSONArray gateways = eipDefinition.getJSONArray("gateways");
- for (int i = 0; i < gateways.length(); i++) {
- JSONObject gw = gateways.getJSONObject(i);
- JSONObject secrets = secretsConfiguration();
- Gateway aux = new Gateway(eipDefinition, secrets, gw, null);
- gatewayList.add(aux);
+ }
+
+ private List<Gateway> getGateways() {
+ try {
+ Vector<Gateway> gatewayList = new Vector<>();
+ JSONArray gateways = eipDefinition.getJSONArray("gateways");
+ for (int i = 0; i < gateways.length(); i++) {
+ JSONObject gw = gateways.getJSONObject(i);
+ JSONObject secrets = secretsConfiguration();
+ Gateway aux = new Gateway(eipDefinition, secrets, gw, null);
+ gatewayList.add(aux);
+ }
+ return gatewayList;
+ } catch (JSONException | IOException | ConfigParser.ConfigParseError e) {
+ return new ArrayList<>();
}
}
@@ -149,24 +141,24 @@ public class GatewaySelectorTest {
@Test
@UseDataProvider("dataProviderTimezones")
public void testSelect(int timezone, String expected) {
- when(ConfigHelper.getCurrentTimezone()).thenReturn(timezone);
- gatewaySelector = new GatewaySelector(gatewayList);
+ TimezoneHelper timezoneHelper = new TimezoneHelper(() -> timezone);
+ GatewaySelector gatewaySelector = new GatewaySelector(getGateways());
assertEquals(expected, gatewaySelector.select().getName());
}
@Test
@UseDataProvider("dataProviderSameDistanceTimezones")
public void testSelectSameTimezoneDistance(int timezone, String expected1, String expected2) {
- when(ConfigHelper.getCurrentTimezone()).thenReturn(timezone);
- gatewaySelector = new GatewaySelector(gatewayList);
+ TimezoneHelper timezoneHelper = new TimezoneHelper(() -> timezone);
+ GatewaySelector gatewaySelector = new GatewaySelector(getGateways());
assertTrue(gatewaySelector.select().getName().equals(expected1) || gatewaySelector.select().getName().equals(expected2));
}
@Test
@UseDataProvider("dataProviderSameDistanceTimezones")
public void testNClostest_SameTimezoneDistance_chooseGatewayWithSameDistance(int timezone, String expected1, String expected2) {
- when(ConfigHelper.getCurrentTimezone()).thenReturn(timezone);
- gatewaySelector = new GatewaySelector(gatewayList);
+ TimezoneHelper timezoneHelper = new TimezoneHelper(() -> timezone);
+ GatewaySelector gatewaySelector = new GatewaySelector(getGateways());
ArrayList<String> gateways = new ArrayList<>();
gateways.add(gatewaySelector.select(0).getName());
gateways.add(gatewaySelector.select(1).getName());
@@ -177,8 +169,8 @@ public class GatewaySelectorTest {
@Test
public void testNClostest_OneTimezonePerSet_choseSecondClosestTimezone() {
- when(ConfigHelper.getCurrentTimezone()).thenReturn(-4);
- gatewaySelector = new GatewaySelector(gatewayList);
+ TimezoneHelper timezoneHelper = new TimezoneHelper(() -> -4);
+ GatewaySelector gatewaySelector = new GatewaySelector(getGateways());
assertTrue("Frankfurt".equals(gatewaySelector.select(1).getName()));
}
diff --git a/app/src/test/java/se/leap/bitmaskclient/eip/GatewaysManagerTest.java b/app/src/test/java/se/leap/bitmaskclient/eip/GatewaysManagerTest.java
index 86373ff6..d66fedbe 100644
--- a/app/src/test/java/se/leap/bitmaskclient/eip/GatewaysManagerTest.java
+++ b/app/src/test/java/se/leap/bitmaskclient/eip/GatewaysManagerTest.java
@@ -1,19 +1,30 @@
package se.leap.bitmaskclient.eip;
+import static junit.framework.Assert.assertEquals;
+import static junit.framework.Assert.assertNull;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+import static de.blinkt.openvpn.core.connection.Connection.TransportType.OBFS4;
+import static de.blinkt.openvpn.core.connection.Connection.TransportType.OPENVPN;
+import static se.leap.bitmaskclient.base.models.Constants.ALLOW_EXPERIMENTAL_TRANSPORTS;
+import static se.leap.bitmaskclient.base.models.Constants.GATEWAYS;
+import static se.leap.bitmaskclient.base.models.Constants.PREFERRED_CITY;
+import static se.leap.bitmaskclient.base.models.Constants.PROVIDER_EIP_DEFINITION;
+import static se.leap.bitmaskclient.base.models.Constants.PROVIDER_PRIVATE_KEY;
+import static se.leap.bitmaskclient.base.models.Constants.PROVIDER_VPN_CERTIFICATE;
+import static se.leap.bitmaskclient.base.models.Constants.USE_BRIDGES;
+import static se.leap.bitmaskclient.base.models.Provider.CA_CERT;
+import static se.leap.bitmaskclient.testutils.TestSetupHelper.getProvider;
+
import android.content.Context;
import android.content.SharedPreferences;
-import android.text.TextUtils;
-import android.util.Log;
import org.json.JSONException;
import org.json.JSONObject;
import org.junit.Before;
import org.junit.Test;
-import org.junit.runner.RunWith;
import org.mockito.Answers;
import org.mockito.Mock;
-import org.powermock.core.classloader.annotations.PrepareForTest;
-import org.powermock.modules.junit4.PowerMockRunner;
import java.io.IOException;
import java.util.ArrayList;
@@ -21,42 +32,17 @@ import java.util.List;
import de.blinkt.openvpn.VpnProfile;
import de.blinkt.openvpn.core.ConfigParser;
-import de.blinkt.openvpn.core.connection.Connection;
import se.leap.bitmaskclient.base.models.Location;
-import se.leap.bitmaskclient.base.models.Pair;
import se.leap.bitmaskclient.base.models.Provider;
import se.leap.bitmaskclient.base.models.ProviderObservable;
-import se.leap.bitmaskclient.base.utils.ConfigHelper;
import se.leap.bitmaskclient.base.utils.PreferenceHelper;
-import se.leap.bitmaskclient.testutils.MockHelper;
+import se.leap.bitmaskclient.base.utils.TimezoneHelper;
import se.leap.bitmaskclient.testutils.MockSharedPreferences;
import se.leap.bitmaskclient.testutils.TestSetupHelper;
-import static de.blinkt.openvpn.core.connection.Connection.TransportType.OBFS4;
-import static de.blinkt.openvpn.core.connection.Connection.TransportType.OPENVPN;
-import static junit.framework.Assert.assertEquals;
-import static junit.framework.Assert.assertNull;
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertTrue;
-import static org.mockito.ArgumentMatchers.any;
-import static org.mockito.ArgumentMatchers.anyInt;
-import static org.mockito.ArgumentMatchers.anyString;
-import static org.mockito.Mockito.when;
-import static org.powermock.api.mockito.PowerMockito.mockStatic;
-import static se.leap.bitmaskclient.base.models.Constants.GATEWAYS;
-import static se.leap.bitmaskclient.base.models.Constants.PROVIDER_EIP_DEFINITION;
-import static se.leap.bitmaskclient.base.models.Constants.PROVIDER_PRIVATE_KEY;
-import static se.leap.bitmaskclient.base.models.Constants.PROVIDER_VPN_CERTIFICATE;
-import static se.leap.bitmaskclient.base.models.Constants.USE_BRIDGES;
-import static se.leap.bitmaskclient.base.models.Provider.CA_CERT;
-import static se.leap.bitmaskclient.testutils.MockHelper.mockTextUtils;
-import static se.leap.bitmaskclient.testutils.TestSetupHelper.getProvider;
-
/**
* Created by cyberta on 09.10.17.
*/
-@RunWith(PowerMockRunner.class)
-@PrepareForTest({ProviderObservable.class, Log.class, PreferenceHelper.class, ConfigHelper.class, TextUtils.class})
public class GatewaysManagerTest {
@Mock(answer = Answers.RETURNS_DEEP_STUBS)
@@ -65,17 +51,15 @@ public class GatewaysManagerTest {
private SharedPreferences sharedPreferences;
private JSONObject secrets;
+ private TimezoneHelper timezoneHelper;
+ ProviderObservable providerObservable;
+
@Before
public void setUp() throws IOException, JSONException {
- mockStatic(Log.class);
- mockStatic(ConfigHelper.class);
- mockTextUtils();
- when(ConfigHelper.getCurrentTimezone()).thenReturn(-1);
- when(ConfigHelper.stringEqual(anyString(), anyString())).thenCallRealMethod();
- when(ConfigHelper.getConnectionQualityFromTimezoneDistance(anyInt())).thenCallRealMethod();
- when(ConfigHelper.isIPv4(anyString())).thenCallRealMethod();
- when(ConfigHelper.timezoneDistance(anyInt(), anyInt())).thenCallRealMethod();
+ timezoneHelper = new TimezoneHelper(() -> -1);
+ providerObservable = ProviderObservable.getInstance();
+
secrets = new JSONObject(getJsonStringFor("secrets.json"));
sharedPreferences = new MockSharedPreferences();
sharedPreferences.edit().
@@ -83,22 +67,20 @@ public class GatewaysManagerTest {
putString(CA_CERT, secrets.getString(CA_CERT)).
putString(PROVIDER_VPN_CERTIFICATE, secrets.getString(PROVIDER_VPN_CERTIFICATE))
.commit();
- mockStatic(PreferenceHelper.class);
PreferenceHelper preferenceHelper = new PreferenceHelper(sharedPreferences);
}
@Test
public void testGatewayManagerFromCurrentProvider_noProvider_noGateways() {
- MockHelper.mockProviderObservable(null);
+ providerObservable.updateProvider(null);
GatewaysManager gatewaysManager = new GatewaysManager(mockContext);
assertEquals(0, gatewaysManager.size());
}
@Test
public void testGatewayManagerFromCurrentProvider_threeGateways() {
- Provider provider = getProvider(null, null, null, null,null, null, "ptdemo_three_mixed_gateways.json", null);
- MockHelper.mockProviderObservable(provider);
+ providerObservable.updateProvider(getProvider(null, null, null, null,null, null, "ptdemo_three_mixed_gateways.json", null));
GatewaysManager gatewaysManager = new GatewaysManager(mockContext);
assertEquals(3, gatewaysManager.size());
}
@@ -108,7 +90,7 @@ public class GatewaysManagerTest {
Provider provider = getProvider(null, null, null, null, null, null, "ptdemo_three_mixed_gateways.json", null);
JSONObject eipServiceJson = provider.getEipServiceJson();
JSONObject gateway1 = eipServiceJson.getJSONArray(GATEWAYS).getJSONObject(0);
- MockHelper.mockProviderObservable(provider);
+ providerObservable.updateProvider(provider);
GatewaysManager gatewaysManager = new GatewaysManager(mockContext);
VpnConfigGenerator.Configuration configuration = new VpnConfigGenerator.Configuration();
@@ -125,7 +107,7 @@ public class GatewaysManagerTest {
Provider provider = getProvider(null, null, null, null, null, null, "ptdemo_three_mixed_gateways.json", null);
JSONObject eipServiceJson = provider.getEipServiceJson();
JSONObject gateway1 = eipServiceJson.getJSONArray(GATEWAYS).getJSONObject(0);
- MockHelper.mockProviderObservable(provider);
+ providerObservable.updateProvider(provider);
GatewaysManager gatewaysManager = new GatewaysManager(mockContext);
VpnConfigGenerator.Configuration configuration = new VpnConfigGenerator.Configuration();
@@ -142,7 +124,7 @@ public class GatewaysManagerTest {
Provider provider = getProvider(null, null, null, null, null, null, "ptdemo_three_mixed_gateways.json", "ptdemo_three_mixed_gateways.geoip.json");
JSONObject eipServiceJson = provider.getEipServiceJson();
JSONObject gateway1 = eipServiceJson.getJSONArray(GATEWAYS).getJSONObject(0);
- MockHelper.mockProviderObservable(provider);
+ providerObservable.updateProvider(provider);
GatewaysManager gatewaysManager = new GatewaysManager(mockContext);
VpnConfigGenerator.Configuration configuration = new VpnConfigGenerator.Configuration();
@@ -159,7 +141,7 @@ public class GatewaysManagerTest {
Provider provider = getProvider(null, null, null, null, null, null, "ptdemo_three_mixed_gateways.json", "ptdemo_three_mixed_gateways.geoip.json");
JSONObject eipServiceJson = provider.getEipServiceJson();
JSONObject gateway1 = eipServiceJson.getJSONArray(GATEWAYS).getJSONObject(0);
- MockHelper.mockProviderObservable(provider);
+ providerObservable.updateProvider(provider);
GatewaysManager gatewaysManager = new GatewaysManager(mockContext);
VpnConfigGenerator.Configuration configuration = new VpnConfigGenerator.Configuration();
@@ -176,7 +158,7 @@ public class GatewaysManagerTest {
Provider provider = getProvider(null, null, null, null, null, null, "ptdemo_three_mixed_gateways.json", null);
JSONObject eipServiceJson = provider.getEipServiceJson();
JSONObject gateway1 = eipServiceJson.getJSONArray(GATEWAYS).getJSONObject(0);
- MockHelper.mockProviderObservable(provider);
+ providerObservable.updateProvider(provider);
GatewaysManager gatewaysManager = new GatewaysManager(mockContext);
VpnConfigGenerator.Configuration configuration = new VpnConfigGenerator.Configuration();
@@ -193,7 +175,7 @@ public class GatewaysManagerTest {
Provider provider = getProvider(null, null, null, null, null, null, "ptdemo_three_mixed_gateways.json", null);
JSONObject eipServiceJson = provider.getEipServiceJson();
JSONObject gateway1 = eipServiceJson.getJSONArray(GATEWAYS).getJSONObject(1);
- MockHelper.mockProviderObservable(provider);
+ providerObservable.updateProvider(provider);
GatewaysManager gatewaysManager = new GatewaysManager(mockContext);
VpnConfigGenerator.Configuration configuration = new VpnConfigGenerator.Configuration();
@@ -209,9 +191,8 @@ public class GatewaysManagerTest {
public void TestSelectN_selectFirstObfs4Connection_returnThirdGateway() {
Provider provider = getProvider(null, null, null, null, null, null, "ptdemo_two_openvpn_one_pt_gateways.json", null);
- MockHelper.mockProviderObservable(provider);
- mockStatic(PreferenceHelper.class);
- when(PreferenceHelper.getUseBridges()).thenReturn(true);
+ providerObservable.updateProvider(provider);
+ sharedPreferences.edit().putBoolean(USE_BRIDGES, true).commit();
GatewaysManager gatewaysManager = new GatewaysManager(mockContext);
assertEquals("37.12.247.10", gatewaysManager.select(0).gateway.getRemoteIP());
@@ -221,10 +202,11 @@ public class GatewaysManagerTest {
public void TestSelectN_select_includeExperimentalTransport_DecoupledPortHoppingGW() {
Provider provider = getProvider(null, null, null, null, null, null, "decoupled_pt_portHopping.eip-service.json", null);
- MockHelper.mockProviderObservable(provider);
- mockStatic(PreferenceHelper.class);
- when(PreferenceHelper.getUseBridges()).thenReturn(true);
- when(PreferenceHelper.allowExperimentalTransports()).thenReturn(true);
+ providerObservable.updateProvider(provider);
+ sharedPreferences.edit().
+ putBoolean(USE_BRIDGES, true).
+ putBoolean(ALLOW_EXPERIMENTAL_TRANSPORTS, true).
+ commit();
GatewaysManager gatewaysManager = new GatewaysManager(mockContext);
ArrayList<String> hosts = new ArrayList<>();
hosts.add(gatewaysManager.select(0).gateway.getHost());
@@ -239,10 +221,11 @@ public class GatewaysManagerTest {
public void TestSelectN_select_includeExperimentalTransport_DecoupledPortAndIPHoppingGW() {
Provider provider = getProvider(null, null, null, null, null, null, "decoupled_pt.eip-service.json", null);
- MockHelper.mockProviderObservable(provider);
- mockStatic(PreferenceHelper.class);
- when(PreferenceHelper.getUseBridges()).thenReturn(true);
- when(PreferenceHelper.allowExperimentalTransports()).thenReturn(true);
+ providerObservable.updateProvider(provider);
+ sharedPreferences.edit().
+ putBoolean(USE_BRIDGES, true).
+ putBoolean(ALLOW_EXPERIMENTAL_TRANSPORTS, true).
+ commit();
GatewaysManager gatewaysManager = new GatewaysManager(mockContext);
ArrayList<String> hosts = new ArrayList<>();
@@ -256,10 +239,11 @@ public class GatewaysManagerTest {
public void TestSelectN_select_excludeExperimentalTransport_DecoupledPortHoppingGW() {
Provider provider = getProvider(null, null, null, null, null, null, "decoupled_pt_portHopping.eip-service.json", null);
- MockHelper.mockProviderObservable(provider);
- mockStatic(PreferenceHelper.class);
- when(PreferenceHelper.getUseBridges()).thenReturn(true);
- when(PreferenceHelper.allowExperimentalTransports()).thenReturn(false);
+ providerObservable.updateProvider(provider);
+ sharedPreferences.edit().
+ putBoolean(USE_BRIDGES, true).
+ putBoolean(ALLOW_EXPERIMENTAL_TRANSPORTS, false).
+ commit();
for (int i = 0; i < 1000; i++) {
GatewaysManager gatewaysManager = new GatewaysManager(mockContext);
@@ -271,10 +255,11 @@ public class GatewaysManagerTest {
public void TestSelectN_select_excludeExperimentalTransport_DecoupledPortAndIPHoppingGW() {
Provider provider = getProvider(null, null, null, null, null, null, "decoupled_pt.eip-service.json", null);
- MockHelper.mockProviderObservable(provider);
- mockStatic(PreferenceHelper.class);
- when(PreferenceHelper.getUseBridges()).thenReturn(true);
- when(PreferenceHelper.allowExperimentalTransports()).thenReturn(false);
+ providerObservable.updateProvider(provider);
+ sharedPreferences.edit().
+ putBoolean(USE_BRIDGES, true).
+ putBoolean(ALLOW_EXPERIMENTAL_TRANSPORTS, false).
+ commit();
GatewaysManager gatewaysManager = new GatewaysManager(mockContext);
assertEquals("bridge-nyc1-01.bitmask-dev.leapvpn.net", gatewaysManager.select(0).gateway.getHost());
@@ -285,10 +270,11 @@ public class GatewaysManagerTest {
public void TestSelectN_select_excludeExperimentalTransport_InGatewayHoppingPTBridge() {
Provider provider = getProvider(null, null, null, null, null, null, "ptdemo_obfs4hop_tcp_gateways.json", null);
- MockHelper.mockProviderObservable(provider);
- mockStatic(PreferenceHelper.class);
- when(PreferenceHelper.getUseBridges()).thenReturn(true);
- when(PreferenceHelper.allowExperimentalTransports()).thenReturn(false);
+ providerObservable.updateProvider(provider);
+ sharedPreferences.edit().
+ putBoolean(USE_BRIDGES, true).
+ putBoolean(ALLOW_EXPERIMENTAL_TRANSPORTS, false).
+ commit();
GatewaysManager gatewaysManager = new GatewaysManager(mockContext);
ArrayList<String> hosts = new ArrayList<>();
@@ -303,10 +289,7 @@ public class GatewaysManagerTest {
public void testSelectN_selectFromPresortedGateways_returnsGatewaysInPresortedOrder() {
Provider provider = getProvider(null, null, null, null, null, null, "ptdemo_three_mixed_gateways.json", "ptdemo_three_mixed_gateways.geoip.json");
- MockHelper.mockProviderObservable(provider);
- //use openvpn, not pluggable transports
- mockStatic(PreferenceHelper.class);
- when(PreferenceHelper.getUseBridges()).thenReturn(false);
+ providerObservable.updateProvider(provider);
GatewaysManager gatewaysManager = new GatewaysManager(mockContext);
assertEquals("manila.bitmask.net", gatewaysManager.select(0).gateway.getHost());
@@ -318,10 +301,11 @@ public class GatewaysManagerTest {
public void testSelectN_selectObfs4FromPresortedGateways_returnsObfs4GatewaysInPresortedOrder() {
Provider provider = getProvider(null, null, null, null, null, null, "ptdemo_three_mixed_gateways.json", "ptdemo_three_mixed_gateways.geoip.json");
- MockHelper.mockProviderObservable(provider);
+ providerObservable.updateProvider(provider);
//use openvpn, not pluggable transports
- mockStatic(PreferenceHelper.class);
- when(PreferenceHelper.getUseBridges()).thenReturn(true);
+ sharedPreferences.edit().
+ putBoolean(USE_BRIDGES, true).
+ commit();
GatewaysManager gatewaysManager = new GatewaysManager(mockContext);
assertEquals("moscow.bitmask.net", gatewaysManager.select(0).gateway.getHost());
@@ -334,11 +318,11 @@ public class GatewaysManagerTest {
public void testSelectN_selectFromCity_returnsGatewaysInPresortedOrder() {
Provider provider = getProvider(null, null, null, null, null, null, "v4/riseup_eipservice_for_geoip_v4.json", "v4/riseup_geoip_v4.json");
- MockHelper.mockProviderObservable(provider);
+ providerObservable.updateProvider(provider);
//use openvpn, not pluggable transports
- mockStatic(PreferenceHelper.class);
- when(PreferenceHelper.getUseBridges()).thenReturn(false);
- when(PreferenceHelper.getPreferredCity()).thenReturn("Paris");
+ sharedPreferences.edit().
+ putString(PREFERRED_CITY, "Paris").
+ commit();
GatewaysManager gatewaysManager = new GatewaysManager(mockContext);
assertEquals("mouette.riseup.net", gatewaysManager.select(0).gateway.getHost());
@@ -350,11 +334,11 @@ public class GatewaysManagerTest {
public void testSelectN_selectFromCityWithGeoIpServiceV1_returnsGatewaysInPresortedOrder() {
Provider provider = getProvider(null, null, null, null, null, null, "v4/riseup_eipservice_for_geoip_v4.json", "v4/riseup_geoip_v1.json");
- MockHelper.mockProviderObservable(provider);
+ providerObservable.updateProvider(provider);
//use openvpn, not pluggable transports
- mockStatic(PreferenceHelper.class);
- when(PreferenceHelper.getUseBridges()).thenReturn(false);
- when(PreferenceHelper.getPreferredCity()).thenReturn("Paris");
+ sharedPreferences.edit().
+ putString(PREFERRED_CITY, "Paris").
+ commit();
GatewaysManager gatewaysManager = new GatewaysManager(mockContext);
assertEquals("mouette.riseup.net", gatewaysManager.select(0).gateway.getHost());
@@ -367,11 +351,11 @@ public class GatewaysManagerTest {
Provider provider = getProvider(null, null, null, null, null, null, "v4/riseup_eipservice_for_geoip_v4.json", null);
provider.setGeoIpJson(new JSONObject());
- MockHelper.mockProviderObservable(provider);
+ providerObservable.updateProvider(provider);
//use openvpn, not pluggable transports
- mockStatic(PreferenceHelper.class);
- when(PreferenceHelper.getUseBridges()).thenReturn(false);
- when(PreferenceHelper.getPreferredCity()).thenReturn("Paris");
+ sharedPreferences.edit().
+ putString(PREFERRED_CITY, "Paris").
+ commit();
GatewaysManager gatewaysManager = new GatewaysManager(mockContext);
assertEquals("Paris", gatewaysManager.select(0).gateway.getName());
@@ -384,10 +368,7 @@ public class GatewaysManagerTest {
public void testSelectN_selectNAndCity_returnsGatewaysInPresortedOrder() {
Provider provider = getProvider(null, null, null, null, null, null, "v4/riseup_eipservice_for_geoip_v4.json", "v4/riseup_geoip_v4.json");
- MockHelper.mockProviderObservable(provider);
- //use openvpn, not pluggable transports
- mockStatic(PreferenceHelper.class);
- when(PreferenceHelper.getUseBridges()).thenReturn(false);
+ providerObservable.updateProvider(provider);
GatewaysManager gatewaysManager = new GatewaysManager(mockContext);
assertEquals("mouette.riseup.net", gatewaysManager.select(0, "Paris").gateway.getHost());
@@ -399,10 +380,7 @@ public class GatewaysManagerTest {
public void testSelectN_selectNAndCityWithGeoIpServiceV1_returnsGatewaysInPresortedOrder() {
Provider provider = getProvider(null, null, null, null, null, null, "v4/riseup_eipservice_for_geoip_v4.json", "v4/riseup_geoip_v1.json");
- MockHelper.mockProviderObservable(provider);
- //use openvpn, not pluggable transports
- mockStatic(PreferenceHelper.class);
- when(PreferenceHelper.getUseBridges()).thenReturn(false);
+ providerObservable.updateProvider(provider);
GatewaysManager gatewaysManager = new GatewaysManager(mockContext);
assertEquals("mouette.riseup.net", gatewaysManager.select(0, "Paris").gateway.getHost());
@@ -415,10 +393,7 @@ public class GatewaysManagerTest {
Provider provider = getProvider(null, null, null, null, null, null, "v4/riseup_eipservice_for_geoip_v4.json", null);
provider.setGeoIpJson(new JSONObject());
- MockHelper.mockProviderObservable(provider);
- //use openvpn, not pluggable transports
- mockStatic(PreferenceHelper.class);
- when(PreferenceHelper.getUseBridges()).thenReturn(false);
+ providerObservable.updateProvider(provider);
GatewaysManager gatewaysManager = new GatewaysManager(mockContext);
assertEquals("Paris", gatewaysManager.select(0, "Paris").gateway.getName());
@@ -432,10 +407,7 @@ public class GatewaysManagerTest {
Provider provider = getProvider(null, null, null, null, null, null, "v4/riseup_eipservice_for_geoip_v4.json", "v4/riseup_geoip_v4.json");
provider.setGeoIpJson(new JSONObject());
- MockHelper.mockProviderObservable(provider);
- //use openvpn, not pluggable transports
- mockStatic(PreferenceHelper.class);
- when(PreferenceHelper.getUseBridges()).thenReturn(false);
+ providerObservable.updateProvider(provider);
GatewaysManager gatewaysManager = new GatewaysManager(mockContext);
assertNull(gatewaysManager.select(0, "Stockholm"));
}
@@ -444,9 +416,10 @@ public class GatewaysManagerTest {
public void testGetLocations_openvpn() {
Provider provider = getProvider(null, null, null, null, null, null, "v4/riseup_eipservice_for_geoip_v4.json", "v4/riseup_geoip_v4.json");
- MockHelper.mockProviderObservable(provider);
- mockStatic(PreferenceHelper.class);
- when(PreferenceHelper.getUseBridges()).thenReturn(false);
+ providerObservable.updateProvider(provider);
+ sharedPreferences.edit().
+ putString(PREFERRED_CITY, "Paris").
+ commit();
GatewaysManager gatewaysManager = new GatewaysManager(mockContext);
List<Location> locations = gatewaysManager.getGatewayLocations();
@@ -465,9 +438,7 @@ public class GatewaysManagerTest {
public void testGetLocations_obfs4() {
Provider provider = getProvider(null, null, null, null, null, null, "v4/riseup_eipservice_for_geoip_v4.json", "v4/riseup_geoip_v4.json");
- MockHelper.mockProviderObservable(provider);
- mockStatic(PreferenceHelper.class);
- when(PreferenceHelper.getUseBridges()).thenReturn(true);
+ providerObservable.updateProvider(provider);
sharedPreferences.edit().putBoolean(USE_BRIDGES, true).commit();
GatewaysManager gatewaysManager = new GatewaysManager(mockContext);
List<Location> locations = gatewaysManager.getGatewayLocations();
@@ -496,9 +467,7 @@ public class GatewaysManagerTest {
public void testGetLocations_noMenshen_obfs4_calculateAverageLoadFromTimezoneDistance() {
Provider provider = getProvider(null, null, null, null, null, null, "v4/riseup_eipservice_for_geoip_v4.json", "v4/riseup_geoip_v1.json");
- MockHelper.mockProviderObservable(provider);
- mockStatic(PreferenceHelper.class);
- when(PreferenceHelper.getUseBridges()).thenReturn(true);
+ providerObservable.updateProvider(provider);
sharedPreferences.edit().putBoolean(USE_BRIDGES, true).commit();
GatewaysManager gatewaysManager = new GatewaysManager(mockContext);
List<Location> locations = gatewaysManager.getGatewayLocations();
@@ -521,10 +490,7 @@ public class GatewaysManagerTest {
public void testGetLocations_noMenshen_openvpn_calculateAverageLoadFromTimezoneDistance() {
Provider provider = getProvider(null, null, null, null, null, null, "v4/riseup_eipservice_for_geoip_v4.json", "v4/riseup_geoip_v1.json");
- MockHelper.mockProviderObservable(provider);
- mockStatic(PreferenceHelper.class);
- when(PreferenceHelper.getUseBridges()).thenReturn(false);
- sharedPreferences.edit().putBoolean(USE_BRIDGES, false).commit();
+ providerObservable.updateProvider(provider);
GatewaysManager gatewaysManager = new GatewaysManager(mockContext);
List<Location> locations = gatewaysManager.getGatewayLocations();
@@ -547,9 +513,7 @@ public class GatewaysManagerTest {
public void testGetSortedLocations_openvpn() {
Provider provider = getProvider(null, null, null, null, null, null, "v4/riseup_eipservice_for_geoip_v4.json", "v4/riseup_geoip_v4_bad_obfs4_gateway.json");
- MockHelper.mockProviderObservable(provider);
- mockStatic(PreferenceHelper.class);
- when(PreferenceHelper.getUseBridges()).thenReturn(false);
+ providerObservable.updateProvider(provider);
GatewaysManager gatewaysManager = new GatewaysManager(mockContext);
List<Location> locations = gatewaysManager.getSortedGatewayLocations(OPENVPN);
@@ -576,9 +540,7 @@ public class GatewaysManagerTest {
public void testGetSortedLocations_obfs4() {
Provider provider = getProvider(null, null, null, null, null, null, "v4/riseup_eipservice_for_geoip_v4.json", "v4/riseup_geoip_v4_bad_obfs4_gateway.json");
- MockHelper.mockProviderObservable(provider);
- mockStatic(PreferenceHelper.class);
- when(PreferenceHelper.getUseBridges()).thenReturn(false);
+ providerObservable.updateProvider(provider);
GatewaysManager gatewaysManager = new GatewaysManager(mockContext);
List<Location> locations = gatewaysManager.getSortedGatewayLocations(OBFS4);
@@ -606,9 +568,7 @@ public class GatewaysManagerTest {
public void testGetSortedLocations_obfs4kcp_generalizedAsPT() {
Provider provider = getProvider(null, null, null, null, null, null, "v4/riseup_eipservice_for_geoip_v4.json", "v4/riseup_geoip_v4_bad_obfs4_gateway.json");
- MockHelper.mockProviderObservable(provider);
- mockStatic(PreferenceHelper.class);
- when(PreferenceHelper.getUseBridges()).thenReturn(false);
+ providerObservable.updateProvider(provider);
GatewaysManager gatewaysManager = new GatewaysManager(mockContext);
List<Location> locations = gatewaysManager.getSortedGatewayLocations(OBFS4);
@@ -619,9 +579,10 @@ public class GatewaysManagerTest {
public void testgetAverageLoad_isSameForAllTransports() {
Provider provider = getProvider(null, null, null, null, null, null, "ptdemo_kcp_gateways.json", "ptdemo_kcp_gateways_geoip.json");
- MockHelper.mockProviderObservable(provider);
- mockStatic(PreferenceHelper.class);
- when(PreferenceHelper.getUseBridges()).thenReturn(false);
+ providerObservable.updateProvider(provider);
+ sharedPreferences.edit().
+ putString(PREFERRED_CITY, "Paris").
+ commit();
GatewaysManager gatewaysManager = new GatewaysManager(mockContext);
assertEquals(0.3, gatewaysManager.getLocation("Amsterdam").getAverageLoad(OBFS4));
@@ -630,7 +591,7 @@ public class GatewaysManagerTest {
@Test
public void testGetLoadForLocation_() {
- MockHelper.mockProviderObservable(null);
+ providerObservable.updateProvider(null);
GatewaysManager gatewaysManager = new GatewaysManager(mockContext);
assertEquals(GatewaysManager.Load.UNKNOWN, gatewaysManager.getLoadForLocation("unknown city", OPENVPN));
}
@@ -638,7 +599,7 @@ public class GatewaysManagerTest {
@Test
public void testGatewayManagerFromCurrentProvider_decoupledBridges_twoGateways() throws IOException, NullPointerException {
Provider provider = getProvider(null, null, null, null, null, null, "decoupled_pt.eip-service.json", null);
- MockHelper.mockProviderObservable(provider);
+ providerObservable.updateProvider(provider);
GatewaysManager gatewaysManager = new GatewaysManager(mockContext);
assertEquals(2, gatewaysManager.size());
}
@@ -646,9 +607,11 @@ public class GatewaysManagerTest {
@Test
public void testGatewayManagerFromCurrentProvider_decoupledBridgesIncludingExperimental_threeGateways() throws IOException, NullPointerException {
Provider provider = getProvider(null, null, null, null, null, null, "decoupled_pt.eip-service.json", null);
- MockHelper.mockProviderObservable(provider);
- mockStatic(PreferenceHelper.class);
- when(PreferenceHelper.allowExperimentalTransports()).thenReturn(true);
+ providerObservable.updateProvider(provider);
+ sharedPreferences.edit().
+ putBoolean(USE_BRIDGES, true).
+ putBoolean(ALLOW_EXPERIMENTAL_TRANSPORTS, true).
+ commit();
GatewaysManager gatewaysManager = new GatewaysManager(mockContext);
assertEquals(3, gatewaysManager.size());
}
diff --git a/app/src/test/java/se/leap/bitmaskclient/eip/ProviderApiManagerTest.java b/app/src/test/java/se/leap/bitmaskclient/eip/ProviderApiManagerTest.java
index 4af0d072..c6e548ce 100644
--- a/app/src/test/java/se/leap/bitmaskclient/eip/ProviderApiManagerTest.java
+++ b/app/src/test/java/se/leap/bitmaskclient/eip/ProviderApiManagerTest.java
@@ -19,12 +19,11 @@ package se.leap.bitmaskclient.eip;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotEquals;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.when;
-import static org.powermock.api.mockito.PowerMockito.mockStatic;
import static se.leap.bitmaskclient.base.models.Constants.BROADCAST_RESULT_KEY;
import static se.leap.bitmaskclient.base.models.Constants.EIP_ACTION_START;
import static se.leap.bitmaskclient.base.models.Constants.PROVIDER_KEY;
+import static se.leap.bitmaskclient.base.models.Constants.USE_BRIDGES;
+import static se.leap.bitmaskclient.base.models.Constants.USE_SNOWFLAKE;
import static se.leap.bitmaskclient.providersetup.ProviderAPI.CORRECTLY_DOWNLOADED_GEOIP_JSON;
import static se.leap.bitmaskclient.providersetup.ProviderAPI.CORRECTLY_UPDATED_INVALID_VPN_CERTIFICATE;
import static se.leap.bitmaskclient.providersetup.ProviderAPI.ERRORS;
@@ -44,27 +43,25 @@ import static se.leap.bitmaskclient.testutils.BackendMockResponses.BackendMockPr
import static se.leap.bitmaskclient.testutils.BackendMockResponses.BackendMockProvider.TestBackendErrorCase.ERROR_GEOIP_SERVICE_IS_DOWN_TOR_FALLBACK;
import static se.leap.bitmaskclient.testutils.BackendMockResponses.BackendMockProvider.TestBackendErrorCase.NO_ERROR;
import static se.leap.bitmaskclient.testutils.BackendMockResponses.BackendMockProvider.TestBackendErrorCase.NO_ERROR_API_V4;
-import static se.leap.bitmaskclient.testutils.MockHelper.mockBase64;
-import static se.leap.bitmaskclient.testutils.MockHelper.mockBundle;
+import static se.leap.bitmaskclient.testutils.MockHelper.mockBuildConfigHelper;
+import static se.leap.bitmaskclient.testutils.MockHelper.mockCertificateHelper;
import static se.leap.bitmaskclient.testutils.MockHelper.mockClientGenerator;
-import static se.leap.bitmaskclient.testutils.MockHelper.mockConfigHelper;
-import static se.leap.bitmaskclient.testutils.MockHelper.mockIntent;
+import static se.leap.bitmaskclient.testutils.MockHelper.mockContext;
import static se.leap.bitmaskclient.testutils.MockHelper.mockPreferenceHelper;
import static se.leap.bitmaskclient.testutils.MockHelper.mockProviderApiConnector;
import static se.leap.bitmaskclient.testutils.MockHelper.mockRSAHelper;
import static se.leap.bitmaskclient.testutils.MockHelper.mockResources;
import static se.leap.bitmaskclient.testutils.MockHelper.mockResultReceiver;
-import static se.leap.bitmaskclient.testutils.MockHelper.mockTextUtils;
-import static se.leap.bitmaskclient.testutils.MockHelper.mockTorStatusObservable;
import static se.leap.bitmaskclient.testutils.TestSetupHelper.getConfiguredProvider;
import static se.leap.bitmaskclient.testutils.TestSetupHelper.getConfiguredProviderAPIv4;
import static se.leap.bitmaskclient.testutils.TestSetupHelper.getProvider;
import android.content.Context;
import android.content.Intent;
+import android.content.SharedPreferences;
+import android.content.pm.PackageManager;
import android.content.res.Resources;
import android.os.Bundle;
-import android.text.TextUtils;
import androidx.annotation.Nullable;
@@ -72,12 +69,6 @@ import org.json.JSONException;
import org.json.JSONObject;
import org.junit.Before;
import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.mockito.Answers;
-import org.mockito.Mock;
-import org.powermock.api.mockito.PowerMockito;
-import org.powermock.core.classloader.annotations.PrepareForTest;
-import org.powermock.modules.junit4.PowerMockRunner;
import java.io.IOException;
import java.security.NoSuchAlgorithmException;
@@ -86,13 +77,16 @@ import java.util.concurrent.TimeoutException;
import se.leap.bitmaskclient.BuildConfig;
import se.leap.bitmaskclient.base.models.Provider;
-import se.leap.bitmaskclient.base.utils.ConfigHelper;
+import se.leap.bitmaskclient.base.utils.BuildConfigHelper;
+import se.leap.bitmaskclient.base.utils.CertificateHelper;
+import se.leap.bitmaskclient.base.utils.HandlerProvider;
import se.leap.bitmaskclient.base.utils.PreferenceHelper;
+import se.leap.bitmaskclient.base.utils.RSAHelper;
import se.leap.bitmaskclient.providersetup.ProviderAPI;
import se.leap.bitmaskclient.providersetup.ProviderApiConnector;
import se.leap.bitmaskclient.providersetup.ProviderApiManager;
import se.leap.bitmaskclient.providersetup.ProviderApiManagerBase;
-import se.leap.bitmaskclient.providersetup.ProviderSetupObservable;
+import se.leap.bitmaskclient.testutils.MockSharedPreferences;
import se.leap.bitmaskclient.tor.TorStatusObservable;
@@ -100,13 +94,9 @@ import se.leap.bitmaskclient.tor.TorStatusObservable;
* Created by cyberta on 04.01.18.
*/
-@RunWith(PowerMockRunner.class)
-@PrepareForTest({ProviderApiManager.class, TextUtils.class, ConfigHelper.RSAHelper.class, ConfigHelper.class, ProviderApiConnector.class, PreferenceHelper.class, TorStatusObservable.class, android.util.Base64.class, ProviderSetupObservable.class})
public class ProviderApiManagerTest {
- @Mock(answer = Answers.RETURNS_DEEP_STUBS)
private Resources mockResources;
- @Mock(answer = Answers.RETURNS_DEEP_STUBS)
private Context mockContext;
private ProviderApiManager providerApiManager;
@@ -114,12 +104,22 @@ public class ProviderApiManagerTest {
static class TestProviderApiServiceCallback implements ProviderApiManagerBase.ProviderApiServiceCallback {
Throwable startTorServiceException;
boolean hasNetworkConnection;
+ boolean torTimeout;
+ TorStatusObservable torStatusObservable;
+
TestProviderApiServiceCallback() {
this(null, true);
}
TestProviderApiServiceCallback(@Nullable Throwable startTorServiceException, boolean hasNetworkConnection) {
this.startTorServiceException = startTorServiceException;
this.hasNetworkConnection = hasNetworkConnection;
+ this.torStatusObservable = TorStatusObservable.getInstance();
+ }
+
+ TestProviderApiServiceCallback(boolean torTimeout, boolean hasNetworkConnection) {
+ this.hasNetworkConnection = hasNetworkConnection;
+ this.torStatusObservable = TorStatusObservable.getInstance();
+ this.torTimeout = torTimeout;
}
@Override
@@ -136,6 +136,13 @@ public class ProviderApiManagerTest {
throw (IllegalStateException) startTorServiceException;
}
}
+ if (!torTimeout) {
+ try {
+ TorStatusObservable.updateState(mockContext(), TorStatusObservable.TorStatus.ON.toString());
+ } catch (PackageManager.NameNotFoundException e) {
+ throw new RuntimeException(e);
+ }
+ }
return true;
}
@@ -145,7 +152,7 @@ public class ProviderApiManagerTest {
@Override
public int getTorHttpTunnelPort() {
- return 0;
+ return 8118;
}
@Override
@@ -157,31 +164,32 @@ public class ProviderApiManagerTest {
@Before
public void setUp() throws Exception {
-
- Bundle bundle = mockBundle();
- PowerMockito.whenNew(Bundle.class).withAnyArguments().thenReturn(bundle);
- Intent intent = mockIntent();
- PowerMockito.whenNew(Intent.class).withAnyArguments().thenReturn(intent);
- mockTextUtils();
+ mockContext = mockContext();
mockResources = mockResources(getClass().getClassLoader().getResourceAsStream("error_messages.json"));
+ HandlerProvider handlerProvider = new HandlerProvider((r, delay) -> new Thread(r).start());
+ BuildConfigHelper buildConfigHelper = mockBuildConfigHelper(true, true);
+ TorStatusObservable torStatusObservable = TorStatusObservable.getInstance();
+ TorStatusObservable.setProxyPort(-1);
+ TorStatusObservable.setLastError(null);
+ TorStatusObservable.updateState(mockContext, TorStatusObservable.TorStatus.OFF.toString());
}
@Test
public void test_handleIntentSetupProvider_noProviderMainURL() throws IOException, JSONException {
Provider provider = new Provider("");
- mockPreferenceHelper(provider);
+ PreferenceHelper preferenceHelper = mockPreferenceHelper(provider);
providerApiManager = new ProviderApiManager(mockResources, mockClientGenerator(), new TestProviderApiServiceCallback());
- Bundle expectedResult = mockBundle();
+ Bundle expectedResult = new Bundle();
expectedResult.putBoolean(BROADCAST_RESULT_KEY, false);
expectedResult.putString(ERRORS, "{\"errors\":\"It doesn't seem to be a Bitmask provider.\"}");
expectedResult.putParcelable(PROVIDER_KEY, provider);
- Intent providerApiCommand = mockIntent();
+ Intent providerApiCommand = new Intent();
providerApiCommand.setAction(ProviderAPI.SET_UP_PROVIDER);
providerApiCommand.putExtra(ProviderAPI.RECEIVER_KEY, mockResultReceiver(PROVIDER_NOK, expectedResult));
providerApiCommand.putExtra(PROVIDER_KEY, provider);
- providerApiCommand.putExtra(PARAMETERS, mockBundle());
+ providerApiCommand.putExtra(PARAMETERS, new Bundle());
providerApiManager.handleIntent(providerApiCommand);
}
@@ -189,47 +197,42 @@ public class ProviderApiManagerTest {
@Test
public void test_handleIntentSetupProvider_happyPath_preseededProviderAndCA() throws IOException, CertificateEncodingException, NoSuchAlgorithmException, JSONException {
Provider provider = getConfiguredProvider();
- mockPreferenceHelper(provider);
- mockConfigHelper(" a5244308a1374709a9afce95e3ae47c1b44bc2398c0a70ccbf8b3a8a97f29494");
- mockProviderApiConnector(NO_ERROR);
- mockStatic(ProviderSetupObservable.class);
+ PreferenceHelper preferenceHelper = mockPreferenceHelper(provider);
+ CertificateHelper certHelper = mockCertificateHelper(" a5244308a1374709a9afce95e3ae47c1b44bc2398c0a70ccbf8b3a8a97f29494");
+ ProviderApiConnector providerApiConnector = mockProviderApiConnector(NO_ERROR);
providerApiManager = new ProviderApiManager(mockResources, mockClientGenerator(), new TestProviderApiServiceCallback());
- Bundle expectedResult = mockBundle();
-
+ Bundle expectedResult = new Bundle();
expectedResult.putBoolean(BROADCAST_RESULT_KEY, true);
expectedResult.putParcelable(PROVIDER_KEY, provider);
- Intent providerApiCommand = mockIntent();
-
+ Intent providerApiCommand = new Intent();
providerApiCommand.putExtra(PROVIDER_KEY, provider);
providerApiCommand.setAction(ProviderAPI.SET_UP_PROVIDER);
providerApiCommand.putExtra(ProviderAPI.RECEIVER_KEY, mockResultReceiver(PROVIDER_OK, expectedResult));
- providerApiCommand.putExtra(PARAMETERS, mockBundle());
-
+ providerApiCommand.putExtra(PARAMETERS, new Bundle());
providerApiManager.handleIntent(providerApiCommand);
}
@Test
public void test_handleIntentSetupProvider_happyPath_no_preseededProviderAndCA() throws IOException, CertificateEncodingException, NoSuchAlgorithmException, JSONException {
Provider provider = getConfiguredProvider();
- mockPreferenceHelper(provider);
- mockConfigHelper("a5244308a1374709a9afce95e3ae47c1b44bc2398c0a70ccbf8b3a8a97f29494");
- mockProviderApiConnector(NO_ERROR);
- mockStatic(ProviderSetupObservable.class);
+ PreferenceHelper preferenceHelper = mockPreferenceHelper(provider);
+ CertificateHelper certHelper = mockCertificateHelper("a5244308a1374709a9afce95e3ae47c1b44bc2398c0a70ccbf8b3a8a97f29494");
+ ProviderApiConnector mockedApiConnector = mockProviderApiConnector(NO_ERROR);
providerApiManager = new ProviderApiManager(mockResources, mockClientGenerator(), new TestProviderApiServiceCallback());
- Bundle expectedResult = mockBundle();
+ Bundle expectedResult = new Bundle();
expectedResult.putBoolean(BROADCAST_RESULT_KEY, true);
expectedResult.putParcelable(PROVIDER_KEY, provider);
- Intent providerApiCommand = mockIntent();
+ Intent providerApiCommand = new Intent();
providerApiCommand.setAction(ProviderAPI.SET_UP_PROVIDER);
providerApiCommand.putExtra(ProviderAPI.RECEIVER_KEY, mockResultReceiver(PROVIDER_OK, expectedResult));
providerApiCommand.putExtra(PROVIDER_KEY, provider);
- providerApiCommand.putExtra(PARAMETERS, mockBundle());
+ providerApiCommand.putExtra(PARAMETERS, new Bundle());
providerApiManager.handleIntent(providerApiCommand);
}
@@ -237,21 +240,20 @@ public class ProviderApiManagerTest {
@Test
public void test_handleIntentSetupProvider_happyPath_storedProviderAndCAFromPreviousSetup() throws IOException, CertificateEncodingException, NoSuchAlgorithmException, JSONException {
Provider provider = new Provider("https://riseup.net");
- mockPreferenceHelper(getConfiguredProvider());
- mockConfigHelper("a5244308a1374709a9afce95e3ae47c1b44bc2398c0a70ccbf8b3a8a97f29494");
- mockProviderApiConnector(NO_ERROR);
- mockStatic(ProviderSetupObservable.class);
+ PreferenceHelper preferenceHelper = mockPreferenceHelper(getConfiguredProvider());
+ CertificateHelper certHelper = mockCertificateHelper("a5244308a1374709a9afce95e3ae47c1b44bc2398c0a70ccbf8b3a8a97f29494");
+ ProviderApiConnector mockedApiConnector = mockProviderApiConnector(NO_ERROR);
providerApiManager = new ProviderApiManager(mockResources, mockClientGenerator(), new TestProviderApiServiceCallback());
- Bundle expectedResult = mockBundle();
+ Bundle expectedResult = new Bundle();
expectedResult.putBoolean(BROADCAST_RESULT_KEY, true);
expectedResult.putParcelable(PROVIDER_KEY, provider);
- Intent providerApiCommand = mockIntent();
+ Intent providerApiCommand = new Intent();
providerApiCommand.setAction(ProviderAPI.SET_UP_PROVIDER);
providerApiCommand.putExtra(ProviderAPI.RECEIVER_KEY, mockResultReceiver(PROVIDER_OK, expectedResult));
- providerApiCommand.putExtra(PARAMETERS, mockBundle());
+ providerApiCommand.putExtra(PARAMETERS, new Bundle());
providerApiCommand.putExtra(PROVIDER_KEY, provider);
providerApiManager.handleIntent(providerApiCommand);
@@ -261,21 +263,19 @@ public class ProviderApiManagerTest {
public void test_handleIntentSetupProvider_preseededProviderAndCA_failedCAPinning() throws IOException, CertificateEncodingException, NoSuchAlgorithmException, JSONException {
Provider provider = getConfiguredProvider();
- mockPreferenceHelper(provider);
- mockConfigHelper(" a5244308a1374709a9afce95e3ae47c1b44bc2398c0a70ccbf8b3a8a97f29495");
- mockProviderApiConnector(NO_ERROR);
+ PreferenceHelper preferenceHelper = mockPreferenceHelper(provider);
+ CertificateHelper certHelper = mockCertificateHelper(" a5244308a1374709a9afce95e3ae47c1b44bc2398c0a70ccbf8b3a8a97f29495");
+ ProviderApiConnector mockedApiConnector = mockProviderApiConnector(NO_ERROR);
providerApiManager = new ProviderApiManager(mockResources, mockClientGenerator(), new TestProviderApiServiceCallback());
- Bundle expectedResult = mockBundle();
+ Bundle expectedResult = new Bundle();
expectedResult.putBoolean(BROADCAST_RESULT_KEY, false);
expectedResult.putString(ERRORS, "{\"errorId\":\"ERROR_CERTIFICATE_PINNING\",\"errors\":\"Stored provider certificate is invalid. You can either update Bitmask (recommended) or update the provider certificate using a commercial CA certificate.\"}");
expectedResult.putParcelable(PROVIDER_KEY, provider);
- Intent providerApiCommand = mockIntent();
-
+ Intent providerApiCommand = new Intent();
providerApiCommand.setAction(ProviderAPI.SET_UP_PROVIDER);
providerApiCommand.putExtra(ProviderAPI.RECEIVER_KEY, mockResultReceiver(PROVIDER_NOK, expectedResult));
- providerApiCommand.putExtra(PARAMETERS, mockBundle());
-
+ providerApiCommand.putExtra(PARAMETERS, new Bundle());
providerApiCommand.putExtra(PROVIDER_KEY, provider);
providerApiManager.handleIntent(providerApiCommand);
@@ -284,24 +284,21 @@ public class ProviderApiManagerTest {
@Test
public void test_handleIntentSetupProvider_no_preseededProviderAndCA_failedPinning() throws IOException, CertificateEncodingException, NoSuchAlgorithmException, JSONException {
Provider provider = new Provider("https://riseup.net");
- mockPreferenceHelper(provider);
- mockConfigHelper("a5244308a1374709a9afce95e3ae47c1b44bc2398c0a70ccbf8b3a8a97f29495");
- mockProviderApiConnector(NO_ERROR);
- mockStatic(ProviderSetupObservable.class);
+ PreferenceHelper preferenceHelper = mockPreferenceHelper(provider);
+ CertificateHelper certHelper = mockCertificateHelper("a5244308a1374709a9afce95e3ae47c1b44bc2398c0a70ccbf8b3a8a97f29495");
+ ProviderApiConnector mockedApiConnector = mockProviderApiConnector(NO_ERROR);
providerApiManager = new ProviderApiManager(mockResources, mockClientGenerator(), new TestProviderApiServiceCallback());
- Bundle expectedResult = mockBundle();
+ Bundle expectedResult = new Bundle();
expectedResult.putBoolean(BROADCAST_RESULT_KEY, false);
expectedResult.putString(ERRORS, "{\"errorId\":\"ERROR_CERTIFICATE_PINNING\",\"errors\":\"Stored provider certificate is invalid. You can either update Bitmask (recommended) or update the provider certificate using a commercial CA certificate.\"}");
expectedResult.putParcelable(PROVIDER_KEY, provider);
- Intent providerApiCommand = mockIntent();
-
+ Intent providerApiCommand = new Intent();
providerApiCommand.setAction(ProviderAPI.SET_UP_PROVIDER);
providerApiCommand.putExtra(ProviderAPI.RECEIVER_KEY, mockResultReceiver(PROVIDER_NOK, expectedResult));
- providerApiCommand.putExtra(PARAMETERS, mockBundle());
-
+ providerApiCommand.putExtra(PARAMETERS, new Bundle());
providerApiCommand.putExtra(PROVIDER_KEY, provider);
providerApiManager.handleIntent(providerApiCommand);
@@ -311,21 +308,20 @@ public class ProviderApiManagerTest {
public void test_handleIntentSetupProvider_storedProviderAndCAFromPreviousSetup_failedPinning() throws IOException, CertificateEncodingException, NoSuchAlgorithmException, JSONException {
Provider provider = new Provider("https://riseup.net");
mockPreferenceHelper(getConfiguredProvider());
- mockConfigHelper("a5244308a1374709a9afce95e3ae47c1b44bc2398c0a70ccbf8b3a8a97f29495");
+ CertificateHelper certHelper = mockCertificateHelper("a5244308a1374709a9afce95e3ae47c1b44bc2398c0a70ccbf8b3a8a97f29495");
- mockProviderApiConnector(NO_ERROR);
+ ProviderApiConnector mockedApiConnector = mockProviderApiConnector(NO_ERROR);
providerApiManager = new ProviderApiManager(mockResources, mockClientGenerator(), new TestProviderApiServiceCallback());
- Bundle expectedResult = mockBundle();
+ Bundle expectedResult = new Bundle();
expectedResult.putBoolean(BROADCAST_RESULT_KEY, false);
expectedResult.putString(ERRORS, "{\"errorId\":\"ERROR_CERTIFICATE_PINNING\",\"errors\":\"Stored provider certificate is invalid. You can either update Bitmask (recommended) or update the provider certificate using a commercial CA certificate.\"}");
expectedResult.putParcelable(PROVIDER_KEY, provider);
- Intent providerApiCommand = mockIntent();
-
+ Intent providerApiCommand = new Intent();
providerApiCommand.setAction(ProviderAPI.SET_UP_PROVIDER);
providerApiCommand.putExtra(ProviderAPI.RECEIVER_KEY, mockResultReceiver(PROVIDER_NOK, expectedResult));
- providerApiCommand.putExtra(PARAMETERS, mockBundle());
+ providerApiCommand.putExtra(PARAMETERS, new Bundle());
providerApiCommand.putExtra(PROVIDER_KEY, provider);
providerApiManager.handleIntent(providerApiCommand);
@@ -335,21 +331,20 @@ public class ProviderApiManagerTest {
@Test
public void test_handleIntentSetupProvider_preseededProviderAndCA_outdatedCertificate() throws IOException, CertificateEncodingException, NoSuchAlgorithmException, JSONException {
Provider provider = getProvider(null ,null, null, null, "outdated_cert.pem", null, null, null);
- mockPreferenceHelper(provider);
- mockProviderApiConnector(NO_ERROR);
- mockConfigHelper("a5244308a1374709a9afce95e3ae47c1b44bc2398c0a70ccbf8b3a8a97f29494");
+ PreferenceHelper preferenceHelper = mockPreferenceHelper(provider);
+ ProviderApiConnector mockedApiConnector = mockProviderApiConnector(NO_ERROR);
+ CertificateHelper certHelper = mockCertificateHelper("a5244308a1374709a9afce95e3ae47c1b44bc2398c0a70ccbf8b3a8a97f29494");
providerApiManager = new ProviderApiManager(mockResources, mockClientGenerator(), new TestProviderApiServiceCallback());
- Bundle expectedResult = mockBundle();
+ Bundle expectedResult = new Bundle();
expectedResult.putBoolean(BROADCAST_RESULT_KEY, false);
expectedResult.putString(ERRORS, "{\"errorId\":\"ERROR_INVALID_CERTIFICATE\",\"errors\":\"Stored provider certificate is expired. You can either update Bitmask (recommended) or update the provider certificate using a commercial CA certificate.\"}");
expectedResult.putParcelable(PROVIDER_KEY, provider);
- Intent providerApiCommand = mockIntent();
-
+ Intent providerApiCommand = new Intent();
providerApiCommand.setAction(ProviderAPI.SET_UP_PROVIDER);
providerApiCommand.putExtra(ProviderAPI.RECEIVER_KEY, mockResultReceiver(PROVIDER_NOK, expectedResult));
- providerApiCommand.putExtra(PARAMETERS, mockBundle());
+ providerApiCommand.putExtra(PARAMETERS, new Bundle());
providerApiCommand.putExtra(PROVIDER_KEY, provider);
providerApiManager.handleIntent(providerApiCommand);
@@ -358,22 +353,21 @@ public class ProviderApiManagerTest {
@Test
public void test_handleIntentSetupProvider_storedProviderAndCAFromPreviousSetup_outdatedCertificate() throws IOException, CertificateEncodingException, NoSuchAlgorithmException, JSONException {
Provider provider = getProvider(null, null, null, null, "outdated_cert.pem", "riseup.net.json", null, null);
- mockPreferenceHelper(provider);
+ PreferenceHelper preferenceHelper = mockPreferenceHelper(provider);
PreferenceHelper.getEipDefinitionFromPreferences();
- mockProviderApiConnector(NO_ERROR);
- mockConfigHelper("a5244308a1374709a9afce95e3ae47c1b44bc2398c0a70ccbf8b3a8a97f29494");
+ ProviderApiConnector mockedApiConnector = mockProviderApiConnector(NO_ERROR);
+ CertificateHelper certHelper = mockCertificateHelper("a5244308a1374709a9afce95e3ae47c1b44bc2398c0a70ccbf8b3a8a97f29494");
providerApiManager = new ProviderApiManager(mockResources, mockClientGenerator(), new TestProviderApiServiceCallback());
- Bundle expectedResult = mockBundle();
+ Bundle expectedResult = new Bundle();
expectedResult.putBoolean(BROADCAST_RESULT_KEY, false);
expectedResult.putString(ERRORS, "{\"errorId\":\"ERROR_INVALID_CERTIFICATE\",\"errors\":\"Stored provider certificate is expired. You can either update Bitmask (recommended) or update the provider certificate using a commercial CA certificate.\"}");
expectedResult.putParcelable(PROVIDER_KEY, provider);
- Intent providerApiCommand = mockIntent();
-
+ Intent providerApiCommand = new Intent();
providerApiCommand.setAction(ProviderAPI.SET_UP_PROVIDER);
providerApiCommand.putExtra(ProviderAPI.RECEIVER_KEY, mockResultReceiver(PROVIDER_NOK, expectedResult));
- providerApiCommand.putExtra(PARAMETERS, mockBundle());
+ providerApiCommand.putExtra(PARAMETERS, new Bundle());
providerApiCommand.putExtra(PROVIDER_KEY, provider);
providerApiManager.handleIntent(providerApiCommand);
@@ -382,22 +376,21 @@ public class ProviderApiManagerTest {
@Test
public void test_handleIntentSetupProvider_preseededProviderAndCA_ValidCertificateButUpdatedCertificateOnServerSide() throws IOException, CertificateEncodingException, NoSuchAlgorithmException, JSONException {
Provider provider = getConfiguredProvider();
- mockPreferenceHelper(provider);
- mockConfigHelper("a5244308a1374709a9afce95e3ae47c1b44bc2398c0a70ccbf8b3a8a97f29494");
- mockProviderApiConnector(ERROR_CASE_UPDATED_CERTIFICATE);
+ PreferenceHelper preferenceHelper = mockPreferenceHelper(provider);
+ CertificateHelper certHelper = mockCertificateHelper("a5244308a1374709a9afce95e3ae47c1b44bc2398c0a70ccbf8b3a8a97f29494");
+ ProviderApiConnector mockedApiConnector = mockProviderApiConnector(ERROR_CASE_UPDATED_CERTIFICATE);
providerApiManager = new ProviderApiManager(mockResources, mockClientGenerator(), new TestProviderApiServiceCallback());
- Bundle expectedResult = mockBundle();
+ Bundle expectedResult = new Bundle();
expectedResult.putBoolean(BROADCAST_RESULT_KEY, false);
expectedResult.putString(ERRORS, "{\"errorId\":\"ERROR_INVALID_CERTIFICATE\",\"errors\":\"Stored provider certificate is invalid. You can either update Bitmask (recommended) or update the provider certificate using a commercial CA certificate.\"}");
expectedResult.putParcelable(PROVIDER_KEY, provider);
- Intent providerApiCommand = mockIntent();
+ Intent providerApiCommand = new Intent();
providerApiCommand.setAction(ProviderAPI.SET_UP_PROVIDER);
providerApiCommand.putExtra(ProviderAPI.RECEIVER_KEY, mockResultReceiver(PROVIDER_NOK, expectedResult));
- providerApiCommand.putExtra(PARAMETERS, mockBundle());
-
+ providerApiCommand.putExtra(PARAMETERS, new Bundle());
providerApiCommand.putExtra(PROVIDER_KEY, provider);
providerApiManager.handleIntent(providerApiCommand);
@@ -406,22 +399,21 @@ public class ProviderApiManagerTest {
@Test
public void test_handleIntentSetupProvider_storedProviderAndCAFromPreviousSetup_ValidCertificateButUpdatedCertificateOnServerSide() throws IOException, CertificateEncodingException, NoSuchAlgorithmException, JSONException {
Provider provider = new Provider("https://riseup.net");
- mockPreferenceHelper(getConfiguredProvider());
- mockConfigHelper("a5244308a1374709a9afce95e3ae47c1b44bc2398c0a70ccbf8b3a8a97f29494");
- mockProviderApiConnector(ERROR_CASE_UPDATED_CERTIFICATE);
+ PreferenceHelper preferenceHelper = mockPreferenceHelper(getConfiguredProvider());
+ CertificateHelper certHelper = mockCertificateHelper("a5244308a1374709a9afce95e3ae47c1b44bc2398c0a70ccbf8b3a8a97f29494");
+ ProviderApiConnector mockedApiConnector = mockProviderApiConnector(ERROR_CASE_UPDATED_CERTIFICATE);
providerApiManager = new ProviderApiManager(mockResources, mockClientGenerator(), new TestProviderApiServiceCallback());
- Bundle expectedResult = mockBundle();
+ Bundle expectedResult = new Bundle();
expectedResult.putBoolean(BROADCAST_RESULT_KEY, false);
expectedResult.putString(ERRORS, "{\"errorId\":\"ERROR_INVALID_CERTIFICATE\",\"errors\":\"Stored provider certificate is invalid. You can either update Bitmask (recommended) or update the provider certificate using a commercial CA certificate.\"}");
expectedResult.putParcelable(PROVIDER_KEY, provider);
- Intent providerApiCommand = mockIntent();
+ Intent providerApiCommand = new Intent();
providerApiCommand.setAction(ProviderAPI.SET_UP_PROVIDER);
providerApiCommand.putExtra(ProviderAPI.RECEIVER_KEY, mockResultReceiver(PROVIDER_NOK, expectedResult));
- providerApiCommand.putExtra(PARAMETERS, mockBundle());
-
+ providerApiCommand.putExtra(PARAMETERS, new Bundle());
providerApiCommand.putExtra(PROVIDER_KEY, provider);
providerApiManager.handleIntent(providerApiCommand);
@@ -431,55 +423,54 @@ public class ProviderApiManagerTest {
public void test_handleIntentSetupProvider_preseededProviderAndCA_failedConfiguration() throws IOException, CertificateEncodingException, NoSuchAlgorithmException, JSONException {
Provider provider = getConfiguredProvider();
- mockPreferenceHelper(provider);
+ PreferenceHelper preferenceHelper = mockPreferenceHelper(provider);
- mockConfigHelper("a5244308a1374709a9afce95e3ae47c1b44bc2398c0a70ccbf8b3a8a97f29494");
- mockProviderApiConnector(ERROR_CASE_MICONFIGURED_PROVIDER);
- mockStatic(ProviderSetupObservable.class);
+ CertificateHelper certHelper = mockCertificateHelper("a5244308a1374709a9afce95e3ae47c1b44bc2398c0a70ccbf8b3a8a97f29494");
+ ProviderApiConnector mockedApiConnector = mockProviderApiConnector(ERROR_CASE_MICONFIGURED_PROVIDER);
providerApiManager = new ProviderApiManager(mockResources, mockClientGenerator(), new TestProviderApiServiceCallback());
- Bundle expectedResult = mockBundle();
+ Bundle expectedResult = new Bundle();
expectedResult.putBoolean(BROADCAST_RESULT_KEY, false);
expectedResult.putString(ERRORS, "{\"errors\":\"There was an error configuring Bitmask with your chosen provider.\"}");
expectedResult.putParcelable(PROVIDER_KEY, provider);
- Intent providerApiCommand = mockIntent();
+ Intent providerApiCommand = new Intent();
providerApiCommand.putExtra(PROVIDER_KEY, provider);
providerApiCommand.setAction(ProviderAPI.SET_UP_PROVIDER);
providerApiCommand.putExtra(ProviderAPI.RECEIVER_KEY, mockResultReceiver(PROVIDER_NOK, expectedResult));
- providerApiCommand.putExtra(PARAMETERS, mockBundle());
+ providerApiCommand.putExtra(PARAMETERS, new Bundle());
providerApiManager.handleIntent(providerApiCommand);
}
+
@Test
public void test_handleIntentSetupProvider_preseededCustomProviderAndCA_failedConfiguration() throws IOException, CertificateEncodingException, NoSuchAlgorithmException, JSONException {
if ("insecure".equals(BuildConfig.FLAVOR_implementation )) {
return;
}
Provider provider = getConfiguredProvider();
- mockPreferenceHelper(provider);
+ PreferenceHelper preferenceHelper = mockPreferenceHelper(provider);
- mockProviderApiConnector(ERROR_CASE_MICONFIGURED_PROVIDER);
- mockConfigHelper("a5244308a1374709a9afce95e3ae47c1b44bc2398c0a70ccbf8b3a8a97f29494");
- when(ConfigHelper.isDefaultBitmask()).thenReturn(false);
- mockStatic(ProviderSetupObservable.class);
+ ProviderApiConnector mockedApiConnector = mockProviderApiConnector(ERROR_CASE_MICONFIGURED_PROVIDER);
+ CertificateHelper certHelper = mockCertificateHelper("a5244308a1374709a9afce95e3ae47c1b44bc2398c0a70ccbf8b3a8a97f29494");
+ BuildConfigHelper buildConfigHelper = mockBuildConfigHelper(true, false);
providerApiManager = new ProviderApiManager(mockResources, mockClientGenerator(), new TestProviderApiServiceCallback());
- Bundle expectedResult = mockBundle();
+ Bundle expectedResult = new Bundle();
expectedResult.putBoolean(BROADCAST_RESULT_KEY, false);
expectedResult.putString(ERRORS, "{\"errors\":\"There was an error configuring RiseupVPN.\"}");
expectedResult.putParcelable(PROVIDER_KEY, provider);
- Intent providerApiCommand = mockIntent();
+ Intent providerApiCommand = new Intent();
providerApiCommand.putExtra(PROVIDER_KEY, provider);
providerApiCommand.setAction(ProviderAPI.SET_UP_PROVIDER);
providerApiCommand.putExtra(ProviderAPI.RECEIVER_KEY, mockResultReceiver(PROVIDER_NOK, expectedResult));
- providerApiCommand.putExtra(PARAMETERS, mockBundle());
+ providerApiCommand.putExtra(PARAMETERS, new Bundle());
providerApiManager.handleIntent(providerApiCommand);
}
@@ -488,23 +479,22 @@ public class ProviderApiManagerTest {
public void test_handleIntentSetupProvider_outdatedPreseededProviderAndCA_successfulConfiguration() throws IOException, CertificateEncodingException, NoSuchAlgorithmException, JSONException {
Provider provider = getProvider(null, null, null, null, null, "riseup_net_outdated_config.json", null, null);
- mockPreferenceHelper(provider);
- mockConfigHelper(" a5244308a1374709a9afce95e3ae47c1b44bc2398c0a70ccbf8b3a8a97f29494");
- mockProviderApiConnector(NO_ERROR);
- mockStatic(ProviderSetupObservable.class);
+ PreferenceHelper preferenceHelper = mockPreferenceHelper(provider);
+ CertificateHelper certHelper = mockCertificateHelper(" a5244308a1374709a9afce95e3ae47c1b44bc2398c0a70ccbf8b3a8a97f29494");
+ ProviderApiConnector mockedApiConnector = mockProviderApiConnector(NO_ERROR);
providerApiManager = new ProviderApiManager(mockResources, mockClientGenerator(), new TestProviderApiServiceCallback());
- Bundle expectedResult = mockBundle();
+ Bundle expectedResult = new Bundle();
expectedResult.putBoolean(BROADCAST_RESULT_KEY, true);
expectedResult.putParcelable(PROVIDER_KEY, provider);
- Intent providerApiCommand = mockIntent();
+ Intent providerApiCommand = new Intent();
providerApiCommand.putExtra(PROVIDER_KEY, provider);
providerApiCommand.setAction(ProviderAPI.SET_UP_PROVIDER);
providerApiCommand.putExtra(ProviderAPI.RECEIVER_KEY, mockResultReceiver(PROVIDER_OK, expectedResult));
- providerApiCommand.putExtra(PARAMETERS, mockBundle());
+ providerApiCommand.putExtra(PARAMETERS, new Bundle());
providerApiManager.handleIntent(providerApiCommand);
}
@@ -516,29 +506,26 @@ public class ProviderApiManagerTest {
}
Provider provider = new Provider("https://riseup.net");
- mockPreferenceHelper(provider);
-
- mockConfigHelper("a5244308a1374709a9afce95e3ae47c1b44bc2398c0a70ccbf8b3a8a97f29494");
- mockProviderApiConnector(ERROR_CASE_FETCH_EIP_SERVICE_CERTIFICATE_INVALID);
- mockStatic(ProviderSetupObservable.class);
+ PreferenceHelper preferenceHelper = mockPreferenceHelper(provider);
+ CertificateHelper certHelper = mockCertificateHelper("a5244308a1374709a9afce95e3ae47c1b44bc2398c0a70ccbf8b3a8a97f29494");
+ ProviderApiConnector mockedApiConnector = mockProviderApiConnector(ERROR_CASE_FETCH_EIP_SERVICE_CERTIFICATE_INVALID);
providerApiManager = new ProviderApiManager(mockResources, mockClientGenerator(), new TestProviderApiServiceCallback());
- Bundle expectedResult = mockBundle();
+ Bundle expectedResult = new Bundle();
expectedResult.putBoolean(BROADCAST_RESULT_KEY, false);
expectedResult.putParcelable(PROVIDER_KEY, provider);
expectedResult.putString(ERRORS, "This is not a trusted Bitmask provider.");
- Intent providerApiCommand = mockIntent();
+ Intent providerApiCommand = new Intent();
providerApiCommand.setAction(ProviderAPI.SET_UP_PROVIDER);
providerApiCommand.putExtra(ProviderAPI.RECEIVER_KEY, mockResultReceiver(PROVIDER_NOK, expectedResult));
providerApiCommand.putExtra(PROVIDER_KEY, provider);
- providerApiCommand.putExtra(PARAMETERS, mockBundle());
+ providerApiCommand.putExtra(PARAMETERS, new Bundle());
providerApiManager.handleIntent(providerApiCommand);
}
-
@Test
public void test_handleIntentGetGeoip_happyPath() throws IOException, NoSuchAlgorithmException, CertificateEncodingException, JSONException {
if ("insecure".equals(BuildConfig.FLAVOR_implementation )) {
@@ -546,22 +533,22 @@ public class ProviderApiManagerTest {
}
Provider inputProvider = getConfiguredProvider();
- mockPreferenceHelper(inputProvider);
inputProvider.setGeoIpJson(new JSONObject());
+ PreferenceHelper preferenceHelper = mockPreferenceHelper(inputProvider);
Provider expectedProvider = getConfiguredProvider();
- mockConfigHelper("a5244308a1374709a9afce95e3ae47c1b44bc2398c0a70ccbf8b3a8a97f29494");
- mockProviderApiConnector(NO_ERROR);
+ CertificateHelper certHelper = mockCertificateHelper("a5244308a1374709a9afce95e3ae47c1b44bc2398c0a70ccbf8b3a8a97f29494");
+ ProviderApiConnector mockedApiConnector = mockProviderApiConnector(NO_ERROR);
providerApiManager = new ProviderApiManager(mockResources, mockClientGenerator(), new TestProviderApiServiceCallback());
- Bundle expectedResult = mockBundle();
+ Bundle expectedResult = new Bundle();
expectedResult.putBoolean(EIP_ACTION_START, true);
expectedResult.putBoolean(BROADCAST_RESULT_KEY, true);
expectedResult.putParcelable(PROVIDER_KEY, expectedProvider);
- Intent providerApiCommand = mockIntent();
+ Intent providerApiCommand = new Intent();
providerApiCommand.setAction(ProviderAPI.DOWNLOAD_GEOIP_JSON);
- Bundle extrasBundle = mockBundle();
+ Bundle extrasBundle = new Bundle();
extrasBundle.putBoolean(EIP_ACTION_START, true);
providerApiCommand.putExtra(ProviderAPI.RECEIVER_KEY, mockResultReceiver(CORRECTLY_DOWNLOADED_GEOIP_JSON, expectedResult));
providerApiCommand.putExtra(PROVIDER_KEY, inputProvider);
@@ -579,24 +566,24 @@ public class ProviderApiManagerTest {
}
Provider provider = getConfiguredProvider();
- mockPreferenceHelper(provider);
- mockConfigHelper("a5244308a1374709a9afce95e3ae47c1b44bc2398c0a70ccbf8b3a8a97f29494");
- mockProviderApiConnector(ERROR_GEOIP_SERVICE_IS_DOWN);
- when(PreferenceHelper.getUseBridges()).thenReturn(false);
- when(PreferenceHelper.getUseSnowflake()).thenReturn(false);
- when(PreferenceHelper.hasSnowflakePrefs()).thenReturn(true);
-
+ SharedPreferences mockSharedPref = new MockSharedPreferences();
+ mockSharedPref.edit().
+ putBoolean(USE_BRIDGES, false).
+ putBoolean(USE_SNOWFLAKE, false).commit();
+ PreferenceHelper preferenceHelper = mockPreferenceHelper(provider, mockSharedPref);
+ CertificateHelper certHelper = mockCertificateHelper("a5244308a1374709a9afce95e3ae47c1b44bc2398c0a70ccbf8b3a8a97f29494");
+ ProviderApiConnector mockedApiConnector = mockProviderApiConnector(ERROR_GEOIP_SERVICE_IS_DOWN);
providerApiManager = new ProviderApiManager(mockResources, mockClientGenerator(), new TestProviderApiServiceCallback());
- Bundle expectedResult = mockBundle();
+ Bundle expectedResult = new Bundle();
expectedResult.putBoolean(EIP_ACTION_START, true);
expectedResult.putBoolean(BROADCAST_RESULT_KEY, false);
expectedResult.putParcelable(PROVIDER_KEY, provider);
- Intent providerApiCommand = mockIntent();
+ Intent providerApiCommand = new Intent();
providerApiCommand.setAction(ProviderAPI.DOWNLOAD_GEOIP_JSON);
- Bundle extrasBundle = mockBundle();
+ Bundle extrasBundle = new Bundle();
extrasBundle.putBoolean(EIP_ACTION_START, true);
providerApiCommand.putExtra(ProviderAPI.RECEIVER_KEY, mockResultReceiver(INCORRECTLY_DOWNLOADED_GEOIP_JSON, expectedResult));
providerApiCommand.putExtra(PROVIDER_KEY, provider);
@@ -612,22 +599,21 @@ public class ProviderApiManagerTest {
return;
}
- mockTorStatusObservable(null);
Provider provider = getConfiguredProvider();
- mockPreferenceHelper(provider);
- mockConfigHelper("a5244308a1374709a9afce95e3ae47c1b44bc2398c0a70ccbf8b3a8a97f29494");
- mockProviderApiConnector(ERROR_GEOIP_SERVICE_IS_DOWN_TOR_FALLBACK);
+ PreferenceHelper preferenceHelper = mockPreferenceHelper(provider);
+ CertificateHelper certHelper = mockCertificateHelper("a5244308a1374709a9afce95e3ae47c1b44bc2398c0a70ccbf8b3a8a97f29494");
+ ProviderApiConnector mockedApiConnector = mockProviderApiConnector(ERROR_GEOIP_SERVICE_IS_DOWN_TOR_FALLBACK);
providerApiManager = new ProviderApiManager(mockResources, mockClientGenerator(), new TestProviderApiServiceCallback());
- Bundle expectedResult = mockBundle();
+ Bundle expectedResult = new Bundle();
expectedResult.putBoolean(EIP_ACTION_START, true);
expectedResult.putBoolean(BROADCAST_RESULT_KEY, false);
expectedResult.putParcelable(PROVIDER_KEY, provider);
- Intent providerApiCommand = mockIntent();
+ Intent providerApiCommand = new Intent();
providerApiCommand.setAction(ProviderAPI.DOWNLOAD_GEOIP_JSON);
- Bundle extrasBundle = mockBundle();
+ Bundle extrasBundle = new Bundle();
extrasBundle.putBoolean(EIP_ACTION_START, true);
providerApiCommand.putExtra(ProviderAPI.RECEIVER_KEY, mockResultReceiver(INCORRECTLY_DOWNLOADED_GEOIP_JSON, expectedResult));
providerApiCommand.putExtra(PROVIDER_KEY, provider);
@@ -647,20 +633,20 @@ public class ProviderApiManagerTest {
Provider provider = getConfiguredProvider();
provider.setLastGeoIpUpdate(System.currentTimeMillis());
- mockPreferenceHelper(provider);
- mockConfigHelper("a5244308a1374709a9afce95e3ae47c1b44bc2398c0a70ccbf8b3a8a97f29494");
- mockProviderApiConnector(NO_ERROR);
+ PreferenceHelper preferenceHelper = mockPreferenceHelper(provider);
+ CertificateHelper certHelper = mockCertificateHelper("a5244308a1374709a9afce95e3ae47c1b44bc2398c0a70ccbf8b3a8a97f29494");
+ ProviderApiConnector mockedApiConnector = mockProviderApiConnector(NO_ERROR);
providerApiManager = new ProviderApiManager(mockResources, mockClientGenerator(), new TestProviderApiServiceCallback());
- Bundle expectedResult = mockBundle();
+ Bundle expectedResult = new Bundle();
expectedResult.putBoolean(EIP_ACTION_START, true);
expectedResult.putBoolean(BROADCAST_RESULT_KEY, false);
expectedResult.putParcelable(PROVIDER_KEY, provider);
- Intent providerApiCommand = mockIntent();
+ Intent providerApiCommand = new Intent();
providerApiCommand.setAction(ProviderAPI.DOWNLOAD_GEOIP_JSON);
- Bundle extrasBundle = mockBundle();
+ Bundle extrasBundle = new Bundle();
extrasBundle.putBoolean(EIP_ACTION_START, true);
providerApiCommand.putExtra(ProviderAPI.RECEIVER_KEY, mockResultReceiver(INCORRECTLY_DOWNLOADED_GEOIP_JSON, expectedResult));
providerApiCommand.putExtra(PROVIDER_KEY, provider);
@@ -678,20 +664,20 @@ public class ProviderApiManagerTest {
Provider provider = getConfiguredProvider();
provider.setGeoipUrl(null);
provider.setGeoIpJson(new JSONObject());
- mockPreferenceHelper(provider);
- mockConfigHelper("a5244308a1374709a9afce95e3ae47c1b44bc2398c0a70ccbf8b3a8a97f29494");
- mockProviderApiConnector(NO_ERROR);
+ PreferenceHelper preferenceHelper = mockPreferenceHelper(provider);
+ CertificateHelper certHelper = mockCertificateHelper("a5244308a1374709a9afce95e3ae47c1b44bc2398c0a70ccbf8b3a8a97f29494");
+ ProviderApiConnector mockedApiConnector = mockProviderApiConnector(NO_ERROR);
providerApiManager = new ProviderApiManager(mockResources, mockClientGenerator(), new TestProviderApiServiceCallback());
- Bundle expectedResult = mockBundle();
+ Bundle expectedResult = new Bundle();
expectedResult.putBoolean(EIP_ACTION_START, true);
expectedResult.putBoolean(BROADCAST_RESULT_KEY, false);
expectedResult.putParcelable(PROVIDER_KEY, provider);
- Intent providerApiCommand = mockIntent();
+ Intent providerApiCommand = new Intent();
providerApiCommand.setAction(ProviderAPI.DOWNLOAD_GEOIP_JSON);
- Bundle extrasBundle = mockBundle();
+ Bundle extrasBundle = new Bundle();
extrasBundle.putBoolean(EIP_ACTION_START, true);
providerApiCommand.putExtra(ProviderAPI.RECEIVER_KEY, mockResultReceiver(INCORRECTLY_DOWNLOADED_GEOIP_JSON, expectedResult));
providerApiCommand.putExtra(PROVIDER_KEY, provider);
@@ -703,22 +689,20 @@ public class ProviderApiManagerTest {
@Test
public void test_handleIntentSetupProvider_APIv4_happyPath() throws IOException, CertificateEncodingException, NoSuchAlgorithmException, JSONException {
Provider provider = getConfiguredProviderAPIv4();
- mockPreferenceHelper(provider);
- mockConfigHelper(" a5244308a1374709a9afce95e3ae47c1b44bc2398c0a70ccbf8b3a8a97f29494");
- mockProviderApiConnector(NO_ERROR_API_V4);
- mockStatic(ProviderSetupObservable.class);
+ PreferenceHelper preferenceHelper = mockPreferenceHelper(provider);
+ CertificateHelper certHelper = mockCertificateHelper(" a5244308a1374709a9afce95e3ae47c1b44bc2398c0a70ccbf8b3a8a97f29494");
+ ProviderApiConnector mockedApiConnector = mockProviderApiConnector(NO_ERROR_API_V4);
providerApiManager = new ProviderApiManager(mockResources, mockClientGenerator(), new TestProviderApiServiceCallback());
- Bundle expectedResult = mockBundle();
-
+ Bundle expectedResult = new Bundle();
expectedResult.putBoolean(BROADCAST_RESULT_KEY, true);
expectedResult.putParcelable(PROVIDER_KEY, provider);
- Intent providerApiCommand = mockIntent();
+ Intent providerApiCommand = new Intent();
providerApiCommand.putExtra(PROVIDER_KEY, provider);
providerApiCommand.setAction(ProviderAPI.SET_UP_PROVIDER);
providerApiCommand.putExtra(ProviderAPI.RECEIVER_KEY, mockResultReceiver(PROVIDER_OK, expectedResult));
- providerApiCommand.putExtra(PARAMETERS, mockBundle());
+ providerApiCommand.putExtra(PARAMETERS, new Bundle());
providerApiManager.handleIntent(providerApiCommand);
}
@@ -727,41 +711,35 @@ public class ProviderApiManagerTest {
public void test_handleIntentSetupProvider_TorFallback_SecondTryHappyPath() throws IOException, CertificateEncodingException, NoSuchAlgorithmException, TimeoutException, InterruptedException {
Provider provider = getConfiguredProviderAPIv4();
- mockPreferenceHelper(provider);
- when(PreferenceHelper.hasSnowflakePrefs()).thenReturn(false);
- when(PreferenceHelper.getUseSnowflake()).thenReturn(true); // getUseSnowflake() defaults to true if not set
- mockStatic(ProviderSetupObservable.class);
-
- mockConfigHelper(" a5244308a1374709a9afce95e3ae47c1b44bc2398c0a70ccbf8b3a8a97f29494");
- mockProviderApiConnector(ERROR_DNS_RESUOLUTION_TOR_FALLBACK);
+ PreferenceHelper preferenceHelper = mockPreferenceHelper(provider);
+ CertificateHelper certHelper = mockCertificateHelper(" a5244308a1374709a9afce95e3ae47c1b44bc2398c0a70ccbf8b3a8a97f29494");
+ ProviderApiConnector mockedApiConnector = mockProviderApiConnector(ERROR_DNS_RESUOLUTION_TOR_FALLBACK);
providerApiManager = new ProviderApiManager(mockResources, mockClientGenerator(), new TestProviderApiServiceCallback());
- Intent providerApiCommand = mockIntent();
+ Intent providerApiCommand = new Intent();
providerApiCommand.putExtra(PROVIDER_KEY, provider);
providerApiCommand.setAction(ProviderAPI.SET_UP_PROVIDER);
providerApiCommand.putExtra(ProviderAPI.RECEIVER_KEY, mockResultReceiver(PROVIDER_OK));
- providerApiCommand.putExtra(PARAMETERS, mockBundle());
- mockTorStatusObservable(null);
+ providerApiCommand.putExtra(PARAMETERS, new Bundle());
providerApiManager.handleIntent(providerApiCommand);
- assertEquals(8118, TorStatusObservable.getProxyPort());
+ assertNotEquals(-1, TorStatusObservable.getProxyPort());
}
@Test
public void test_handleIntentSetupProvider_TorFallbackStartServiceException_SecondTryFailed() throws IOException, CertificateEncodingException, NoSuchAlgorithmException, TimeoutException, InterruptedException {
Provider provider = getConfiguredProviderAPIv4();
- mockPreferenceHelper(provider);
- mockConfigHelper(" a5244308a1374709a9afce95e3ae47c1b44bc2398c0a70ccbf8b3a8a97f29494");
- mockProviderApiConnector(ERROR_DNS_RESUOLUTION_TOR_FALLBACK);
+ PreferenceHelper preferenceHelper = mockPreferenceHelper(provider);
+ CertificateHelper certHelper = mockCertificateHelper(" a5244308a1374709a9afce95e3ae47c1b44bc2398c0a70ccbf8b3a8a97f29494");
+ ProviderApiConnector mockedApiConnector = mockProviderApiConnector(ERROR_DNS_RESUOLUTION_TOR_FALLBACK);
providerApiManager = new ProviderApiManager(mockResources, mockClientGenerator(), new TestProviderApiServiceCallback(new IllegalStateException("Tor service start not failed."), true));
- Intent providerApiCommand = mockIntent();
+ Intent providerApiCommand = new Intent();
providerApiCommand.putExtra(PROVIDER_KEY, provider);
providerApiCommand.setAction(ProviderAPI.SET_UP_PROVIDER);
providerApiCommand.putExtra(ProviderAPI.RECEIVER_KEY, mockResultReceiver(PROVIDER_NOK));
- providerApiCommand.putExtra(PARAMETERS, mockBundle());
- mockTorStatusObservable(null);
+ providerApiCommand.putExtra(PARAMETERS, new Bundle());
providerApiManager.handleIntent(providerApiCommand);
assertEquals(-1, TorStatusObservable.getProxyPort());
@@ -770,17 +748,16 @@ public class ProviderApiManagerTest {
@Test
public void test_handleIntentSetupProvider_TorFallbackTimeoutException_SecondTryFailed() throws IOException, CertificateEncodingException, NoSuchAlgorithmException, TimeoutException, InterruptedException {
Provider provider = getConfiguredProviderAPIv4();
- mockPreferenceHelper(provider);
- mockConfigHelper(" a5244308a1374709a9afce95e3ae47c1b44bc2398c0a70ccbf8b3a8a97f29494");
- mockProviderApiConnector(ERROR_DNS_RESUOLUTION_TOR_FALLBACK);
- providerApiManager = new ProviderApiManager(mockResources, mockClientGenerator(), new TestProviderApiServiceCallback());
+ PreferenceHelper preferenceHelper = mockPreferenceHelper(provider);
+ CertificateHelper certHelper = mockCertificateHelper(" a5244308a1374709a9afce95e3ae47c1b44bc2398c0a70ccbf8b3a8a97f29494");
+ ProviderApiConnector mockedApiConnector = mockProviderApiConnector(ERROR_DNS_RESUOLUTION_TOR_FALLBACK);
+ providerApiManager = new ProviderApiManager(mockResources, mockClientGenerator(), new TestProviderApiServiceCallback(true, true));
- Intent providerApiCommand = mockIntent();
+ Intent providerApiCommand = new Intent();
providerApiCommand.putExtra(PROVIDER_KEY, provider);
providerApiCommand.setAction(ProviderAPI.SET_UP_PROVIDER);
providerApiCommand.putExtra(ProviderAPI.RECEIVER_KEY, mockResultReceiver(PROVIDER_NOK));
- providerApiCommand.putExtra(PARAMETERS, mockBundle());
- mockTorStatusObservable(new TimeoutException("Tor took too long to start."));
+ providerApiCommand.putExtra(PARAMETERS, new Bundle());
providerApiManager.handleIntent(providerApiCommand);
assertEquals(-1, TorStatusObservable.getProxyPort());
@@ -790,23 +767,19 @@ public class ProviderApiManagerTest {
public void test_handleIntentSetupProvider_TorBridgesPreferenceEnabled_Success() throws IOException, CertificateEncodingException, NoSuchAlgorithmException, TimeoutException, InterruptedException {
Provider provider = getConfiguredProviderAPIv4();
- mockPreferenceHelper(provider);
- mockConfigHelper(" a5244308a1374709a9afce95e3ae47c1b44bc2398c0a70ccbf8b3a8a97f29494");
- mockProviderApiConnector(NO_ERROR_API_V4);
- mockStatic(ProviderSetupObservable.class);
-
- when(PreferenceHelper.getUseBridges()).thenReturn(true);
- when(PreferenceHelper.getUseSnowflake()).thenReturn(true);
- when(PreferenceHelper.hasSnowflakePrefs()).thenReturn(true);
+ SharedPreferences sharedPreferences = new MockSharedPreferences();
+ sharedPreferences.edit().putBoolean(USE_BRIDGES, true).putBoolean(USE_SNOWFLAKE, true).commit();
+ PreferenceHelper preferenceHelper = mockPreferenceHelper(provider, sharedPreferences);
+ CertificateHelper certHelper = mockCertificateHelper(" a5244308a1374709a9afce95e3ae47c1b44bc2398c0a70ccbf8b3a8a97f29494");
+ ProviderApiConnector mockedApiConnector = mockProviderApiConnector(NO_ERROR_API_V4);
providerApiManager = new ProviderApiManager(mockResources, mockClientGenerator(), new TestProviderApiServiceCallback());
- Intent providerApiCommand = mockIntent();
+ Intent providerApiCommand = new Intent();
providerApiCommand.putExtra(PROVIDER_KEY, provider);
providerApiCommand.setAction(ProviderAPI.SET_UP_PROVIDER);
providerApiCommand.putExtra(ProviderAPI.RECEIVER_KEY, mockResultReceiver(PROVIDER_OK));
- providerApiCommand.putExtra(PARAMETERS, mockBundle());
- mockTorStatusObservable(null);
+ providerApiCommand.putExtra(PARAMETERS, new Bundle());
providerApiManager.handleIntent(providerApiCommand);
assertEquals(8118, TorStatusObservable.getProxyPort());
@@ -816,23 +789,19 @@ public class ProviderApiManagerTest {
public void test_handleIntentSetupProvider_TorBridgesDisabled_TorNotStarted() throws IOException, CertificateEncodingException, NoSuchAlgorithmException, TimeoutException, InterruptedException {
Provider provider = getConfiguredProviderAPIv4();
- mockPreferenceHelper(provider);
- mockConfigHelper(" a5244308a1374709a9afce95e3ae47c1b44bc2398c0a70ccbf8b3a8a97f29494");
- mockProviderApiConnector(NO_ERROR_API_V4);
-
- mockStatic(ProviderSetupObservable.class);
- when(PreferenceHelper.getUseBridges()).thenReturn(false);
- when(PreferenceHelper.getUseSnowflake()).thenReturn(false);
- when(PreferenceHelper.hasSnowflakePrefs()).thenReturn(true);
+ SharedPreferences sharedPreferences = new MockSharedPreferences();
+ sharedPreferences.edit().putBoolean(USE_BRIDGES, false).putBoolean(USE_SNOWFLAKE, false).commit();
+ PreferenceHelper preferenceHelper = mockPreferenceHelper(provider, sharedPreferences);
+ CertificateHelper certHelper = mockCertificateHelper(" a5244308a1374709a9afce95e3ae47c1b44bc2398c0a70ccbf8b3a8a97f29494");
+ ProviderApiConnector mockedApiConnector = mockProviderApiConnector(NO_ERROR_API_V4);
providerApiManager = new ProviderApiManager(mockResources, mockClientGenerator(), new TestProviderApiServiceCallback());
- Intent providerApiCommand = mockIntent();
+ Intent providerApiCommand = new Intent();
providerApiCommand.putExtra(PROVIDER_KEY, provider);
providerApiCommand.setAction(ProviderAPI.SET_UP_PROVIDER);
providerApiCommand.putExtra(ProviderAPI.RECEIVER_KEY, mockResultReceiver(PROVIDER_OK));
- providerApiCommand.putExtra(PARAMETERS, mockBundle());
- mockTorStatusObservable(new TimeoutException("This timeout exception is never thrown"));
+ providerApiCommand.putExtra(PARAMETERS, new Bundle());
providerApiManager.handleIntent(providerApiCommand);
assertEquals(-1, TorStatusObservable.getProxyPort());
@@ -841,47 +810,40 @@ public class ProviderApiManagerTest {
@Test
public void test_handleIntentUpdateVPNCertificate_TorBridgesPreferencesNotConfigured_TorStartedAndSuccess() throws IOException, CertificateEncodingException, NoSuchAlgorithmException, TimeoutException, InterruptedException {
Provider provider = getConfiguredProviderAPIv4();
- mockPreferenceHelper(provider);
- when(PreferenceHelper.hasSnowflakePrefs()).thenReturn(false);
- when(PreferenceHelper.getUseSnowflake()).thenReturn(true);
- mockConfigHelper(" a5244308a1374709a9afce95e3ae47c1b44bc2398c0a70ccbf8b3a8a97f29494");
- mockRSAHelper();
- mockBase64();
- mockProviderApiConnector(ERROR_DNS_RESUOLUTION_TOR_FALLBACK);
+ PreferenceHelper preferenceHelper = mockPreferenceHelper(provider);
+ CertificateHelper certHelper = mockCertificateHelper(" a5244308a1374709a9afce95e3ae47c1b44bc2398c0a70ccbf8b3a8a97f29494");
+ RSAHelper rsaHelper = mockRSAHelper();
+ ProviderApiConnector mockedApiConnector = mockProviderApiConnector(ERROR_DNS_RESUOLUTION_TOR_FALLBACK);
providerApiManager = new ProviderApiManager(mockResources, mockClientGenerator(), new TestProviderApiServiceCallback());
- Intent providerApiCommand = mockIntent();
+ Intent providerApiCommand = new Intent();
providerApiCommand.putExtra(PROVIDER_KEY, provider);
providerApiCommand.setAction(ProviderAPI.UPDATE_INVALID_VPN_CERTIFICATE);
providerApiCommand.putExtra(ProviderAPI.RECEIVER_KEY, mockResultReceiver(CORRECTLY_UPDATED_INVALID_VPN_CERTIFICATE));
- providerApiCommand.putExtra(PARAMETERS, mockBundle());
- mockTorStatusObservable(null);
+ providerApiCommand.putExtra(PARAMETERS, new Bundle());
providerApiManager.handleIntent(providerApiCommand);
- assertNotEquals(-1, TorStatusObservable.getProxyPort());
+ assertEquals(8118, TorStatusObservable.getProxyPort());
}
@Test
public void test_handleIntentUpdateVPNCertificate_TorBridgesPreferencesFalse_TorNotStartedAndFailure() throws IOException, CertificateEncodingException, NoSuchAlgorithmException, TimeoutException, InterruptedException {
Provider provider = getConfiguredProviderAPIv4();
- mockPreferenceHelper(provider);
- mockConfigHelper(" a5244308a1374709a9afce95e3ae47c1b44bc2398c0a70ccbf8b3a8a97f29494");
- mockBase64();
- mockProviderApiConnector(ERROR_DNS_RESUOLUTION_TOR_FALLBACK);
- when(PreferenceHelper.getUseBridges()).thenReturn(false);
- when(PreferenceHelper.getUseSnowflake()).thenReturn(false);
- when(PreferenceHelper.hasSnowflakePrefs()).thenReturn(true);
+ SharedPreferences sharedPreferences = new MockSharedPreferences();
+ sharedPreferences.edit().putBoolean(USE_BRIDGES, false).putBoolean(USE_SNOWFLAKE, false).commit();
+ PreferenceHelper preferenceHelper = mockPreferenceHelper(provider, sharedPreferences);
+ CertificateHelper certHelper = mockCertificateHelper(" a5244308a1374709a9afce95e3ae47c1b44bc2398c0a70ccbf8b3a8a97f29494");
+ ProviderApiConnector mockedApiConnector = mockProviderApiConnector(ERROR_DNS_RESUOLUTION_TOR_FALLBACK);
providerApiManager = new ProviderApiManager(mockResources, mockClientGenerator(), new TestProviderApiServiceCallback());
- Intent providerApiCommand = mockIntent();
+ Intent providerApiCommand = new Intent();
providerApiCommand.putExtra(PROVIDER_KEY, provider);
providerApiCommand.setAction(ProviderAPI.UPDATE_INVALID_VPN_CERTIFICATE);
providerApiCommand.putExtra(ProviderAPI.RECEIVER_KEY, mockResultReceiver(INCORRECTLY_UPDATED_INVALID_VPN_CERTIFICATE));
- providerApiCommand.putExtra(PARAMETERS, mockBundle());
- mockTorStatusObservable(new TimeoutException("This timeout exception is never thrown"));
+ providerApiCommand.putExtra(PARAMETERS, new Bundle());
providerApiManager.handleIntent(providerApiCommand);
assertEquals(-1, TorStatusObservable.getProxyPort());
@@ -891,23 +853,20 @@ public class ProviderApiManagerTest {
public void test_handleIntentUpdateVPNCertificate_TorBridgesPreferencesTrue_TorStartedAndSuccess() throws IOException, CertificateEncodingException, NoSuchAlgorithmException, TimeoutException, InterruptedException {
Provider provider = getConfiguredProviderAPIv4();
- mockPreferenceHelper(provider);
- mockConfigHelper(" a5244308a1374709a9afce95e3ae47c1b44bc2398c0a70ccbf8b3a8a97f29494");
- mockBase64();
- mockRSAHelper();
- mockProviderApiConnector(NO_ERROR_API_V4);
- when(PreferenceHelper.getUseBridges()).thenReturn(true);
- when(PreferenceHelper.getUseSnowflake()).thenReturn(true);
- when(PreferenceHelper.hasSnowflakePrefs()).thenReturn(true);
+ SharedPreferences sharedPreferences = new MockSharedPreferences();
+ sharedPreferences.edit().putBoolean(USE_BRIDGES, true).putBoolean(USE_SNOWFLAKE, true).commit();
+ PreferenceHelper preferenceHelper = mockPreferenceHelper(provider, sharedPreferences);
+ CertificateHelper certHelper = mockCertificateHelper(" a5244308a1374709a9afce95e3ae47c1b44bc2398c0a70ccbf8b3a8a97f29494");
+ RSAHelper rsaHelper = mockRSAHelper();
+ ProviderApiConnector mockedApiConnector = mockProviderApiConnector(NO_ERROR_API_V4);
providerApiManager = new ProviderApiManager(mockResources, mockClientGenerator(), new TestProviderApiServiceCallback());
- Intent providerApiCommand = mockIntent();
+ Intent providerApiCommand = new Intent();
providerApiCommand.putExtra(PROVIDER_KEY, provider);
providerApiCommand.setAction(ProviderAPI.UPDATE_INVALID_VPN_CERTIFICATE);
providerApiCommand.putExtra(ProviderAPI.RECEIVER_KEY, mockResultReceiver(CORRECTLY_UPDATED_INVALID_VPN_CERTIFICATE));
- providerApiCommand.putExtra(PARAMETERS, mockBundle());
- mockTorStatusObservable(null);
+ providerApiCommand.putExtra(PARAMETERS, new Bundle());
providerApiManager.handleIntent(providerApiCommand);
assertNotEquals(-1, TorStatusObservable.getProxyPort());
@@ -917,27 +876,24 @@ public class ProviderApiManagerTest {
public void test_handleIntentUpdateVPNCertificate_TorBridgesPreferencesTrue_TorException_Failure() throws IOException, CertificateEncodingException, NoSuchAlgorithmException, TimeoutException, InterruptedException {
Provider provider = getConfiguredProviderAPIv4();
- mockPreferenceHelper(provider);
- mockConfigHelper(" a5244308a1374709a9afce95e3ae47c1b44bc2398c0a70ccbf8b3a8a97f29494");
- mockBase64();
- mockProviderApiConnector(NO_ERROR_API_V4);
- when(PreferenceHelper.getUseBridges()).thenReturn(true);
- when(PreferenceHelper.getUseSnowflake()).thenReturn(true);
- when(PreferenceHelper.hasSnowflakePrefs()).thenReturn(true);
+ SharedPreferences sharedPreferences = new MockSharedPreferences();
+ sharedPreferences.edit().putBoolean(USE_BRIDGES, true).putBoolean(USE_SNOWFLAKE, true).commit();
+ PreferenceHelper preferenceHelper = mockPreferenceHelper(provider, sharedPreferences);
+ CertificateHelper certHelper = mockCertificateHelper(" a5244308a1374709a9afce95e3ae47c1b44bc2398c0a70ccbf8b3a8a97f29494");
+ ProviderApiConnector mockedApiConnector = mockProviderApiConnector(NO_ERROR_API_V4);
- providerApiManager = new ProviderApiManager(mockResources, mockClientGenerator(), new TestProviderApiServiceCallback());
+ providerApiManager = new ProviderApiManager(mockResources, mockClientGenerator(), new TestProviderApiServiceCallback(new IllegalStateException("Nothing works always."), true));
- Bundle expectedResult = mockBundle();
+ Bundle expectedResult = new Bundle();
expectedResult.putBoolean(BROADCAST_RESULT_KEY, false);
expectedResult.putString(ERRORS, "{\"initalAction\":\"ProviderAPI.UPDATE_INVALID_VPN_CERTIFICATE\"}");
expectedResult.putParcelable(PROVIDER_KEY, provider);
- Intent providerApiCommand = mockIntent();
+ Intent providerApiCommand = new Intent();
providerApiCommand.putExtra(PROVIDER_KEY, provider);
providerApiCommand.setAction(ProviderAPI.UPDATE_INVALID_VPN_CERTIFICATE);
providerApiCommand.putExtra(ProviderAPI.RECEIVER_KEY, mockResultReceiver(TOR_EXCEPTION, expectedResult));
- providerApiCommand.putExtra(PARAMETERS, mockBundle());
- mockTorStatusObservable(new InterruptedException("Tor thread was interrupted."));
+ providerApiCommand.putExtra(PARAMETERS, new Bundle());
providerApiManager.handleIntent(providerApiCommand);
assertEquals(-1, TorStatusObservable.getProxyPort());
@@ -946,25 +902,23 @@ public class ProviderApiManagerTest {
@Test
public void test_handleIntentSetupProvider_TorBridgesPreferencesEnabledTimeout_TimeoutError() throws IOException, CertificateEncodingException, NoSuchAlgorithmException, TimeoutException, InterruptedException {
Provider provider = getConfiguredProviderAPIv4();
+ SharedPreferences sharedPreferences = new MockSharedPreferences();
+ sharedPreferences.edit().putBoolean(USE_BRIDGES, true).putBoolean(USE_SNOWFLAKE, true).commit();
+ PreferenceHelper preferenceHelper = mockPreferenceHelper(provider, sharedPreferences);
+ ProviderApiConnector mockedApiConnector = mockProviderApiConnector(NO_ERROR_API_V4);
- mockPreferenceHelper(provider);
- when(PreferenceHelper.getUseBridges()).thenReturn(true);
- when(PreferenceHelper.getUseSnowflake()).thenReturn(true);
- when(PreferenceHelper.hasSnowflakePrefs()).thenReturn(true);
-
- providerApiManager = new ProviderApiManager(mockResources, mockClientGenerator(), new TestProviderApiServiceCallback());
+ providerApiManager = new ProviderApiManager(mockResources, mockClientGenerator(), new TestProviderApiServiceCallback(true, true));
- Bundle expectedResult = mockBundle();
+ Bundle expectedResult = new Bundle();
expectedResult.putBoolean(BROADCAST_RESULT_KEY, false);
expectedResult.putString(ERRORS, "{\"errorId\":\"ERROR_TOR_TIMEOUT\",\"initalAction\":\"setUpProvider\",\"errors\":\"Starting bridges failed. Do you want to retry or continue with an unobfuscated secure connection to configure Bitmask?\"}");
expectedResult.putParcelable(PROVIDER_KEY, provider);
- Intent providerApiCommand = mockIntent();
+ Intent providerApiCommand = new Intent();
providerApiCommand.putExtra(PROVIDER_KEY, provider);
providerApiCommand.setAction(ProviderAPI.SET_UP_PROVIDER);
providerApiCommand.putExtra(ProviderAPI.RECEIVER_KEY, mockResultReceiver(TOR_TIMEOUT, expectedResult));
- providerApiCommand.putExtra(PARAMETERS, mockBundle());
- mockTorStatusObservable(new TimeoutException("Tor took too long to start."));
+ providerApiCommand.putExtra(PARAMETERS, new Bundle());
providerApiManager.handleIntent(providerApiCommand);
assertEquals(-1, TorStatusObservable.getProxyPort());
@@ -974,22 +928,21 @@ public class ProviderApiManagerTest {
public void test_handleIntentSetupProvider_noNetwork_NetworkError() throws IOException, CertificateEncodingException, NoSuchAlgorithmException, JSONException {
Provider provider = getConfiguredProvider();
- mockConfigHelper("a5244308a1374709a9afce95e3ae47c1b44bc2398c0a70ccbf8b3a8a97f29494");
- mockProviderApiConnector(NO_ERROR);
+ CertificateHelper certHelper = mockCertificateHelper("a5244308a1374709a9afce95e3ae47c1b44bc2398c0a70ccbf8b3a8a97f29494");
+ ProviderApiConnector mockedApiConnector = mockProviderApiConnector(NO_ERROR);
providerApiManager = new ProviderApiManager(mockResources, mockClientGenerator(), new TestProviderApiServiceCallback(null, false));
- Bundle expectedResult = mockBundle();
+ Bundle expectedResult = new Bundle();
expectedResult.putBoolean(BROADCAST_RESULT_KEY, false);
expectedResult.putString(ERRORS, "{\"errors\":\"Bitmask has no internet connection. Please check your WiFi and cellular data settings.\"}");
expectedResult.putParcelable(PROVIDER_KEY, provider);
- Intent providerApiCommand = mockIntent();
+ Intent providerApiCommand = new Intent();
providerApiCommand.setAction(ProviderAPI.SET_UP_PROVIDER);
providerApiCommand.putExtra(ProviderAPI.RECEIVER_KEY, mockResultReceiver(MISSING_NETWORK_CONNECTION, expectedResult));
providerApiCommand.putExtra(PROVIDER_KEY, provider);
- providerApiCommand.putExtra(PARAMETERS, mockBundle());
+ providerApiCommand.putExtra(PARAMETERS, new Bundle());
providerApiManager.handleIntent(providerApiCommand);
}
-
}
diff --git a/app/src/test/java/se/leap/bitmaskclient/eip/VpnCertificateValidatorTest.java b/app/src/test/java/se/leap/bitmaskclient/eip/VpnCertificateValidatorTest.java
index 1cb47f43..a951f144 100644
--- a/app/src/test/java/se/leap/bitmaskclient/eip/VpnCertificateValidatorTest.java
+++ b/app/src/test/java/se/leap/bitmaskclient/eip/VpnCertificateValidatorTest.java
@@ -2,25 +2,20 @@ package se.leap.bitmaskclient.eip;
import org.junit.Before;
import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.powermock.core.classloader.annotations.PrepareForTest;
-import org.powermock.modules.junit4.PowerMockRunner;
import java.io.IOException;
import java.security.NoSuchAlgorithmException;
import java.security.cert.CertificateEncodingException;
import java.util.Calendar;
-import se.leap.bitmaskclient.base.utils.ConfigHelper;
+import se.leap.bitmaskclient.base.utils.CertificateHelper;
import se.leap.bitmaskclient.testutils.TestCalendarProvider;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
-import static se.leap.bitmaskclient.testutils.MockHelper.mockConfigHelper;
+import static se.leap.bitmaskclient.testutils.MockHelper.mockCertificateHelper;
import static se.leap.bitmaskclient.testutils.TestSetupHelper.getInputAsString;
-@RunWith(PowerMockRunner.class)
-@PrepareForTest({ConfigHelper.class})
public class VpnCertificateValidatorTest {
@Before
@@ -31,7 +26,7 @@ public class VpnCertificateValidatorTest {
public void test_isValid() throws NoSuchAlgorithmException, CertificateEncodingException, IOException {
String cert = getInputAsString(getClass().getClassLoader().getResourceAsStream("riseup.net.pem"));
Calendar c = new Calendar.Builder().setDate(2018, 1, 1).setCalendarType("gregorian").build();
- mockConfigHelper("falseFingerPrint");
+ CertificateHelper helper = mockCertificateHelper("falseFingerPrint");
VpnCertificateValidator validator = new VpnCertificateValidator(cert);
validator.setCalendarProvider(new TestCalendarProvider(c.getTimeInMillis()));
assertTrue( validator.isValid());
@@ -41,7 +36,7 @@ public class VpnCertificateValidatorTest {
public void test_isValid_lessThan1day_returnFalse() throws NoSuchAlgorithmException, CertificateEncodingException, IOException {
String cert = getInputAsString(getClass().getClassLoader().getResourceAsStream("riseup.net.pem"));
Calendar c = new Calendar.Builder().setDate(2024, 3, 28).setCalendarType("gregorian").build();
- mockConfigHelper("falseFingerPrint");
+ CertificateHelper helper = mockCertificateHelper("falseFingerPrint");
VpnCertificateValidator validator = new VpnCertificateValidator(cert);
validator.setCalendarProvider(new TestCalendarProvider(c.getTimeInMillis()));
assertFalse( validator.isValid());
@@ -51,7 +46,7 @@ public class VpnCertificateValidatorTest {
public void test_isValid_multipleCerts_failIfOneExpires() throws NoSuchAlgorithmException, CertificateEncodingException, IOException {
String cert = getInputAsString(getClass().getClassLoader().getResourceAsStream("float.hexacab.org.pem"));
Calendar c = new Calendar.Builder().setDate(2024, 3, 28).setCalendarType("gregorian").build();
- mockConfigHelper("falseFingerPrint");
+ CertificateHelper helper = mockCertificateHelper("falseFingerPrint");
VpnCertificateValidator validator = new VpnCertificateValidator(cert);
validator.setCalendarProvider(new TestCalendarProvider(c.getTimeInMillis()));
assertFalse(validator.isValid());
@@ -61,7 +56,7 @@ public class VpnCertificateValidatorTest {
public void test_isValid_multipleCerts_allValid() throws NoSuchAlgorithmException, CertificateEncodingException, IOException {
String cert = getInputAsString(getClass().getClassLoader().getResourceAsStream("float.hexacab.org.pem"));
Calendar c = new Calendar.Builder().setDate(2024, 3, 27).setCalendarType("gregorian").build();
- mockConfigHelper("falseFingerPrint");
+ CertificateHelper helper = mockCertificateHelper("falseFingerPrint");
VpnCertificateValidator validator = new VpnCertificateValidator(cert);
validator.setCalendarProvider(new TestCalendarProvider(c.getTimeInMillis()));
assertTrue(validator.isValid());
@@ -71,7 +66,7 @@ public class VpnCertificateValidatorTest {
public void test_shouldBeUpdated_lessThan8days_returnTrue() throws NoSuchAlgorithmException, CertificateEncodingException, IOException {
String cert = getInputAsString(getClass().getClassLoader().getResourceAsStream("float.hexacab.org.pem"));
Calendar c = new Calendar.Builder().setDate(2024, 3, 21).setCalendarType("gregorian").build();
- mockConfigHelper("falseFingerPrint");
+ CertificateHelper helper = mockCertificateHelper("falseFingerPrint");
VpnCertificateValidator validator = new VpnCertificateValidator(cert);
validator.setCalendarProvider(new TestCalendarProvider(c.getTimeInMillis()));
assertTrue(validator.shouldBeUpdated());
@@ -81,7 +76,7 @@ public class VpnCertificateValidatorTest {
public void test_shouldBeUpdated_moreThan8days_returnFalse() throws NoSuchAlgorithmException, CertificateEncodingException, IOException {
String cert = getInputAsString(getClass().getClassLoader().getResourceAsStream("float.hexacab.org.pem"));
Calendar c = new Calendar.Builder().setDate(2024, 3, 20).setCalendarType("gregorian").build();
- mockConfigHelper("falseFingerPrint");
+ CertificateHelper helper = mockCertificateHelper("falseFingerPrint");
VpnCertificateValidator validator = new VpnCertificateValidator(cert);
validator.setCalendarProvider(new TestCalendarProvider(c.getTimeInMillis()));
assertFalse(validator.shouldBeUpdated());
diff --git a/app/src/test/java/se/leap/bitmaskclient/eip/VpnConfigGeneratorTest.java b/app/src/test/java/se/leap/bitmaskclient/eip/VpnConfigGeneratorTest.java
index 3f011a65..4b9e5d65 100644
--- a/app/src/test/java/se/leap/bitmaskclient/eip/VpnConfigGeneratorTest.java
+++ b/app/src/test/java/se/leap/bitmaskclient/eip/VpnConfigGeneratorTest.java
@@ -4,32 +4,18 @@ import static junit.framework.Assert.assertEquals;
import static junit.framework.Assert.assertFalse;
import static junit.framework.Assert.assertNotNull;
import static junit.framework.Assert.assertTrue;
-import static org.mockito.ArgumentMatchers.any;
-import static org.mockito.Mockito.RETURNS_DEEP_STUBS;
-import static org.mockito.Mockito.mock;
-import static org.powermock.api.mockito.PowerMockito.mockStatic;
-import static org.powermock.api.mockito.PowerMockito.when;
+import static org.mockito.Mockito.when;
import static de.blinkt.openvpn.core.connection.Connection.TransportType.OBFS4;
import static de.blinkt.openvpn.core.connection.Connection.TransportType.OBFS4_HOP;
import static de.blinkt.openvpn.core.connection.Connection.TransportType.OPENVPN;
import static se.leap.bitmaskclient.base.models.Constants.OPENVPN_CONFIGURATION;
-import static se.leap.bitmaskclient.testutils.MockHelper.mockRSAHelper;
-import static se.leap.bitmaskclient.testutils.MockHelper.mockTextUtils;
import android.content.Context;
import android.content.SharedPreferences;
-import android.preference.PreferenceManager;
-import android.text.TextUtils;
-import android.util.Log;
import org.json.JSONObject;
import org.junit.Before;
import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.mockito.Answers;
-import org.mockito.Mock;
-import org.powermock.core.classloader.annotations.PrepareForTest;
-import org.powermock.modules.junit4.PowerMockRunner;
import java.io.File;
import java.util.HashMap;
@@ -40,19 +26,21 @@ import de.blinkt.openvpn.core.connection.Connection;
import de.blinkt.openvpn.core.connection.Obfs4Connection;
import de.blinkt.openvpn.core.connection.Obfs4HopConnection;
import se.leap.bitmaskclient.base.models.ProviderObservable;
-import se.leap.bitmaskclient.base.utils.ConfigHelper;
+import se.leap.bitmaskclient.base.utils.BuildConfigHelper;
+import se.leap.bitmaskclient.base.utils.PreferenceHelper;
+import se.leap.bitmaskclient.base.utils.RSAHelper;
import se.leap.bitmaskclient.testutils.MockHelper;
+import se.leap.bitmaskclient.testutils.MockSharedPreferences;
import se.leap.bitmaskclient.testutils.TestSetupHelper;
/**
* Created by cyberta on 03.10.17.
*/
-@RunWith(PowerMockRunner.class)
-@PrepareForTest({Log.class, TextUtils.class, PreferenceManager.class, ProviderObservable.class, ConfigHelper.RSAHelper.class, ConfigHelper.ObfsVpnHelper.class})
public class VpnConfigGeneratorTest {
- @Mock(answer = Answers.RETURNS_DEEP_STUBS)
Context context;
+ PreferenceHelper preferenceHelper;
+ private SharedPreferences sharedPreferences;
private VpnConfigGenerator vpnConfigGenerator;
private JSONObject generalConfig;
@@ -139,7 +127,7 @@ public class VpnConfigGeneratorTest {
"-----END CERTIFICATE-----\n" +
"</cert>\n" +
"management-external-key nopadding pkcs1 pss digest\n" +
- "# crl-verify file missing in config profile\n" +
+ //"# crl-verify file missing in config profile\n" +
"remote-cert-tls server\n" +
"data-ciphers AES-128-CBC\n" +
"cipher AES-128-CBC\n" +
@@ -235,7 +223,7 @@ public class VpnConfigGeneratorTest {
"-----END CERTIFICATE-----\n" +
"</cert>\n" +
"management-external-key nopadding pkcs1 pss digest\n" +
- "# crl-verify file missing in config profile\n" +
+ //"# crl-verify file missing in config profile\n" +
"remote-cert-tls server\n" +
"data-ciphers AES-128-CBC\n" +
"cipher AES-128-CBC\n" +
@@ -330,7 +318,7 @@ public class VpnConfigGeneratorTest {
"-----END CERTIFICATE-----\n" +
"</cert>\n" +
"management-external-key nopadding pkcs1 pss digest\n" +
- "# crl-verify file missing in config profile\n" +
+ //"# crl-verify file missing in config profile\n" +
"route 37.218.247.60 255.255.255.255 net_gateway\n"+
"remote-cert-tls server\n" +
"data-ciphers AES-128-CBC\n" +
@@ -426,7 +414,7 @@ public class VpnConfigGeneratorTest {
"-----END CERTIFICATE-----\n" +
"</cert>\n" +
"management-external-key nopadding pkcs1 pss digest\n" +
- "# crl-verify file missing in config profile\n" +
+ //"# crl-verify file missing in config profile\n" +
"route 37.218.247.60 255.255.255.255 net_gateway\n"+
"remote-cert-tls server\n" +
"data-ciphers AES-128-CBC\n" +
@@ -523,7 +511,7 @@ public class VpnConfigGeneratorTest {
"-----END CERTIFICATE-----\n" +
"</cert>\n" +
"management-external-key nopadding pkcs1 pss digest\n" +
- "# crl-verify file missing in config profile\n" +
+ //"# crl-verify file missing in config profile\n" +
"remote-cert-tls server\n" +
"data-ciphers AES-128-CBC\n" +
"cipher AES-128-CBC\n" +
@@ -619,7 +607,7 @@ public class VpnConfigGeneratorTest {
"-----END CERTIFICATE-----\n" +
"</cert>\n" +
"management-external-key nopadding pkcs1 pss digest\n" +
- "# crl-verify file missing in config profile\n" +
+ //"# crl-verify file missing in config profile\n" +
"remote-cert-tls server\n" +
"data-ciphers AES-128-CBC\n" +
"cipher AES-128-CBC\n" +
@@ -715,7 +703,7 @@ public class VpnConfigGeneratorTest {
"-----END CERTIFICATE-----\n" +
"</cert>\n" +
"management-external-key nopadding pkcs1 pss digest\n" +
- "# crl-verify file missing in config profile\n" +
+ //"# crl-verify file missing in config profile\n" +
"remote-cert-tls server\n" +
"data-ciphers AES-256-GCM:AES-128-GCM:AES-128-CBC\n" +
"cipher AES-128-CBC\n" +
@@ -813,7 +801,7 @@ public class VpnConfigGeneratorTest {
"-----END CERTIFICATE-----\n" +
"</cert>\n" +
"management-external-key nopadding pkcs1 pss digest\n" +
- "# crl-verify file missing in config profile\n" +
+ //"# crl-verify file missing in config profile\n" +
"comp-lzo\n" +
"nobind\n"+
"remote-cert-tls server\n" +
@@ -915,7 +903,7 @@ public class VpnConfigGeneratorTest {
"-----END CERTIFICATE-----\n" +
"</cert>\n" +
"management-external-key nopadding pkcs1 pss digest\n" +
- "# crl-verify file missing in config profile\n" +
+ //"# crl-verify file missing in config profile\n" +
"comp-lzo\n" +
"nobind\n"+
"remote-cert-tls server\n" +
@@ -1025,7 +1013,7 @@ public class VpnConfigGeneratorTest {
"-----END CERTIFICATE-----\n" +
"</cert>\n" +
"management-external-key nopadding pkcs1 pss digest\n" +
- "# crl-verify file missing in config profile\n" +
+ //"# crl-verify file missing in config profile\n" +
"comp-lzo\n" +
"nobind\n"+
"remote-cert-tls server\n" +
@@ -1128,7 +1116,7 @@ public class VpnConfigGeneratorTest {
"-----END CERTIFICATE-----\n" +
"</cert>\n" +
"management-external-key nopadding pkcs1 pss digest\n" +
- "# crl-verify file missing in config profile\n" +
+ //"# crl-verify file missing in config profile\n" +
"nobind\n"+
"remote-cert-tls server\n" +
"data-ciphers AES-256-GCM:AES-128-CBC\n" +
@@ -1228,7 +1216,7 @@ public class VpnConfigGeneratorTest {
"-----END CERTIFICATE-----\n" +
"</cert>\n" +
"management-external-key nopadding pkcs1 pss digest\n" +
- "# crl-verify file missing in config profile\n" +
+ //"# crl-verify file missing in config profile\n" +
"route 192.81.208.164 255.255.255.255 net_gateway\n"+
"tun-mtu 48000\n"+
"nobind\n"+
@@ -1332,7 +1320,7 @@ public class VpnConfigGeneratorTest {
"-----END CERTIFICATE-----\n" +
"</cert>\n" +
"management-external-key nopadding pkcs1 pss digest\n" +
- "# crl-verify file missing in config profile\n" +
+ //"# crl-verify file missing in config profile\n" +
"route 192.81.208.164 255.255.255.255 net_gateway\n"+
"route 192.81.208.165 255.255.255.255 net_gateway\n"+
"route 192.81.208.166 255.255.255.255 net_gateway\n"+
@@ -1364,17 +1352,13 @@ public class VpnConfigGeneratorTest {
public void setUp() throws Exception {
generalConfig = new JSONObject(TestSetupHelper.getInputAsString(getClass().getClassLoader().getResourceAsStream("general_configuration.json")));
secrets = new JSONObject(TestSetupHelper.getInputAsString(getClass().getClassLoader().getResourceAsStream("secrets.json")));
- mockStatic(Log.class);
context = MockHelper.mockContext();
- mockTextUtils();
- mockStatic(PreferenceManager.class);
- MockHelper.mockProviderObservable(TestSetupHelper.getConfiguredProvider());
- MockHelper.mockRSAHelper();
- SharedPreferences preferences = mock(SharedPreferences.class, RETURNS_DEEP_STUBS);
- when(PreferenceManager.getDefaultSharedPreferences(any(Context.class))).thenReturn(preferences);
- when(preferences.getBoolean("usesystemproxy", true)).thenReturn(true);
+
+ ProviderObservable providerObservable = MockHelper.mockProviderObservable(TestSetupHelper.getConfiguredProvider());
+ RSAHelper rsaHelper = MockHelper.mockRSAHelper();
+ sharedPreferences = new MockSharedPreferences();
+ preferenceHelper = new PreferenceHelper(new MockSharedPreferences());
when(context.getCacheDir()).thenReturn(new File("/data/data/se.leap.bitmask"));
- mockStatic(ConfigHelper.ObfsVpnHelper.class);
}
@Test
@@ -1424,7 +1408,7 @@ public class VpnConfigGeneratorTest {
@Test
public void testGenerateVpnProfile_v3_obfs4() throws Exception {
- when(ConfigHelper.ObfsVpnHelper.useObfsVpn()).thenReturn(false);
+ BuildConfigHelper buildConfigHelper = MockHelper.mockBuildConfigHelper(false);
gateway = new JSONObject(TestSetupHelper.getInputAsString(getClass().getClassLoader().getResourceAsStream("ptdemo.bitmask.eip-service.json"))).getJSONArray("gateways").getJSONObject(0);
VpnConfigGenerator.Configuration configuration = new VpnConfigGenerator.Configuration();
configuration.apiVersion = 3;
@@ -1438,7 +1422,7 @@ public class VpnConfigGeneratorTest {
@Test
public void testGenerateVpnProfile_v3_obfs4_obfsvpn() throws Exception {
- when(ConfigHelper.ObfsVpnHelper.useObfsVpn()).thenReturn(true);
+ BuildConfigHelper buildConfigHelper = MockHelper.mockBuildConfigHelper(true);
gateway = new JSONObject(TestSetupHelper.getInputAsString(getClass().getClassLoader().getResourceAsStream("ptdemo.bitmask.eip-service.json"))).getJSONArray("gateways").getJSONObject(0);
VpnConfigGenerator.Configuration configuration = new VpnConfigGenerator.Configuration();
configuration.apiVersion = 3;
@@ -1744,7 +1728,7 @@ public class VpnConfigGeneratorTest {
@Test
public void testGetConfigFile_testHoppingPtPortHopping_decoupled() throws Exception {
- when(ConfigHelper.ObfsVpnHelper.useObfsVpn()).thenReturn(true);
+ BuildConfigHelper buildConfigHelper = MockHelper.mockBuildConfigHelper(true);
gateway = new JSONObject(TestSetupHelper.getInputAsString(getClass().getClassLoader().getResourceAsStream("decoupled_pt_portHopping.eip-service.json"))).getJSONArray("gateways").getJSONObject(2);
generalConfig = new JSONObject(TestSetupHelper.getInputAsString(getClass().getClassLoader().getResourceAsStream("decoupled_pt_portHopping.eip-service.json"))).getJSONObject(OPENVPN_CONFIGURATION);
VpnConfigGenerator.Configuration configuration = new VpnConfigGenerator.Configuration();
@@ -1758,7 +1742,7 @@ public class VpnConfigGeneratorTest {
@Test
public void testGetConfigFile_testHoppingPtPortAndIPHopping_decoupled() throws Exception {
- when(ConfigHelper.ObfsVpnHelper.useObfsVpn()).thenReturn(true);
+ BuildConfigHelper buildConfigHelper = MockHelper.mockBuildConfigHelper(true);
gateway = new JSONObject(TestSetupHelper.getInputAsString(getClass().getClassLoader().getResourceAsStream("decoupled_pt_portHopping.eip-service.json"))).getJSONArray("gateways").getJSONObject(2);
generalConfig = new JSONObject(TestSetupHelper.getInputAsString(getClass().getClassLoader().getResourceAsStream("decoupled_pt_portHopping.eip-service.json"))).getJSONObject(OPENVPN_CONFIGURATION);
VpnConfigGenerator.Configuration configuration = new VpnConfigGenerator.Configuration();
@@ -1771,7 +1755,7 @@ public class VpnConfigGeneratorTest {
}
@Test
public void testGenerateVpnProfile_obfs4_decoupled() throws Exception {
- when(ConfigHelper.ObfsVpnHelper.useObfsVpn()).thenReturn(true);
+ BuildConfigHelper buildConfigHelper = MockHelper.mockBuildConfigHelper(true);
gateway = new JSONObject(TestSetupHelper.getInputAsString(getClass().getClassLoader().getResourceAsStream("decoupled_pt.eip-service.json"))).getJSONArray("gateways").getJSONObject(1);
generalConfig = new JSONObject(TestSetupHelper.getInputAsString(getClass().getClassLoader().getResourceAsStream("decoupled_pt.eip-service.json"))).getJSONObject(OPENVPN_CONFIGURATION);
VpnConfigGenerator.Configuration configuration = new VpnConfigGenerator.Configuration();
@@ -1786,7 +1770,7 @@ public class VpnConfigGeneratorTest {
@Test
public void testGenerateVpnProfile_obfs4hop_decoupled() throws Exception {
- when(ConfigHelper.ObfsVpnHelper.useObfsVpn()).thenReturn(true);
+ BuildConfigHelper buildConfigHelper = MockHelper.mockBuildConfigHelper(true);
gateway = new JSONObject(TestSetupHelper.getInputAsString(getClass().getClassLoader().getResourceAsStream("decoupled_pt.eip-service.json"))).getJSONArray("gateways").getJSONObject(2);
generalConfig = new JSONObject(TestSetupHelper.getInputAsString(getClass().getClassLoader().getResourceAsStream("decoupled_pt.eip-service.json"))).getJSONObject(OPENVPN_CONFIGURATION);
VpnConfigGenerator.Configuration configuration = new VpnConfigGenerator.Configuration();
@@ -1802,7 +1786,7 @@ public class VpnConfigGeneratorTest {
@Test
public void testGenerateVpnProfile_noExperimental_skipObfs4Hop() throws Exception {
- when(ConfigHelper.ObfsVpnHelper.useObfsVpn()).thenReturn(true);
+ BuildConfigHelper buildConfigHelper = MockHelper.mockBuildConfigHelper(true);
gateway = new JSONObject(TestSetupHelper.getInputAsString(getClass().getClassLoader().getResourceAsStream("decoupled_pt.eip-service.json"))).getJSONArray("gateways").getJSONObject(2);
generalConfig = new JSONObject(TestSetupHelper.getInputAsString(getClass().getClassLoader().getResourceAsStream("decoupled_pt.eip-service.json"))).getJSONObject(OPENVPN_CONFIGURATION);
VpnConfigGenerator.Configuration configuration = new VpnConfigGenerator.Configuration();
@@ -1820,7 +1804,7 @@ public class VpnConfigGeneratorTest {
@Test
public void testGenerateVpnProfile_obfs4hop_onlyPortHopping_decoupled() throws Exception {
- when(ConfigHelper.ObfsVpnHelper.useObfsVpn()).thenReturn(true);
+ BuildConfigHelper buildConfigHelper = MockHelper.mockBuildConfigHelper(true);
gateway = new JSONObject(TestSetupHelper.getInputAsString(getClass().getClassLoader().getResourceAsStream("decoupled_pt_portHopping.eip-service.json"))).getJSONArray("gateways").getJSONObject(2);
generalConfig = new JSONObject(TestSetupHelper.getInputAsString(getClass().getClassLoader().getResourceAsStream("decoupled_pt_portHopping.eip-service.json"))).getJSONObject(OPENVPN_CONFIGURATION);
VpnConfigGenerator.Configuration configuration = new VpnConfigGenerator.Configuration();
diff --git a/app/src/test/java/se/leap/bitmaskclient/providersetup/ProviderManagerTest.java b/app/src/test/java/se/leap/bitmaskclient/providersetup/ProviderManagerTest.java
index e7295452..7584fb3f 100644
--- a/app/src/test/java/se/leap/bitmaskclient/providersetup/ProviderManagerTest.java
+++ b/app/src/test/java/se/leap/bitmaskclient/providersetup/ProviderManagerTest.java
@@ -1,56 +1,49 @@
package se.leap.bitmaskclient.providersetup;
+import static junit.framework.Assert.assertEquals;
+import static junit.framework.Assert.assertFalse;
+import static junit.framework.Assert.assertTrue;
+import static org.mockito.ArgumentMatchers.anyString;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+import static se.leap.bitmaskclient.testutils.MockHelper.mockInputStreamHelper;
+
import android.content.res.AssetManager;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.mockito.Mock;
import org.mockito.invocation.InvocationOnMock;
import org.mockito.stubbing.Answer;
-import org.powermock.core.classloader.annotations.PrepareForTest;
-import org.powermock.modules.junit4.PowerMockRunner;
import java.io.File;
import java.io.InputStream;
import java.util.ArrayList;
import se.leap.bitmaskclient.base.models.Provider;
-import se.leap.bitmaskclient.base.utils.ConfigHelper;
import se.leap.bitmaskclient.base.utils.FileHelper;
import se.leap.bitmaskclient.base.utils.InputStreamHelper;
-import se.leap.bitmaskclient.providersetup.ProviderManager;
-
-import static junit.framework.Assert.assertEquals;
-import static junit.framework.Assert.assertFalse;
-import static junit.framework.Assert.assertTrue;
-import static org.mockito.ArgumentMatchers.any;
-import static org.mockito.ArgumentMatchers.anyString;
-import static org.mockito.Mockito.times;
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.when;
-import static org.powermock.api.mockito.PowerMockito.verifyStatic;
-import static se.leap.bitmaskclient.testutils.MockHelper.mockFileHelper;
-import static se.leap.bitmaskclient.testutils.MockHelper.mockInputStreamHelper;
+import se.leap.bitmaskclient.testutils.MockHelper;
/**
* Created by cyberta on 20.02.18.
*/
-@RunWith(PowerMockRunner.class)
-@PrepareForTest({ConfigHelper.class, FileHelper.class, InputStreamHelper.class})
public class ProviderManagerTest {
- @Mock
private AssetManager assetManager;
- @Mock
private File file;
private ProviderManager providerManager;
+ InputStreamHelper inputStreamHelper;
+ FileHelper fileHelper;
+ MockHelper.MockFileHelper mockedFileHelperInterface;
@Before
public void setup() throws Exception {
- //mock assetManager methods
- //--------------------------
+ assetManager = mock(AssetManager.class);
+ file = mock(File.class);
+
when(assetManager.open(anyString())).thenAnswer(new Answer<InputStream>() {
@Override
public InputStream answer(InvocationOnMock invocation) throws Throwable {
@@ -85,11 +78,9 @@ public class ProviderManagerTest {
when(file.getAbsolutePath()).thenReturn("externalDir");
when(file.getPath()).thenReturn("externalDir");
- mockFileHelper(file);
-
- // mock inputStream
- //-----------------------------------
- mockInputStreamHelper();
+ mockedFileHelperInterface = new MockHelper.MockFileHelper(file);
+ fileHelper = new FileHelper(mockedFileHelperInterface);
+ inputStreamHelper = mockInputStreamHelper();
}
@@ -217,8 +208,7 @@ public class ProviderManagerTest {
providerManager.add(secondCustomProvider);
providerManager.saveCustomProvidersToFile();
- verifyStatic(FileHelper.class, times(2));
- FileHelper.persistFile(any(File.class), anyString());
+ assertEquals("persist was called twice", 2, mockedFileHelperInterface.getPersistFileCounter());
}
diff --git a/app/src/test/java/se/leap/bitmaskclient/testutils/BackendMockResponses/BackendMockProvider.java b/app/src/test/java/se/leap/bitmaskclient/testutils/BackendMockResponses/BackendMockProvider.java
index 280aa5a1..4ef41619 100644
--- a/app/src/test/java/se/leap/bitmaskclient/testutils/BackendMockResponses/BackendMockProvider.java
+++ b/app/src/test/java/se/leap/bitmaskclient/testutils/BackendMockResponses/BackendMockProvider.java
@@ -18,6 +18,8 @@ package se.leap.bitmaskclient.testutils.BackendMockResponses;
import java.io.IOException;
+import se.leap.bitmaskclient.providersetup.ProviderApiConnector;
+
/**
* Created by cyberta on 10.01.18.
*/
@@ -43,67 +45,43 @@ public class BackendMockProvider {
ERROR_PAYLOAD_MISSING, // => IllegalArgumentException
ERROR_TLS_1_2_NOT_SUPPORTED, // => UnknownServiceException
ERROR_UNKNOWN_IO_EXCEPTION, // => IOException
- ERROR_NO_ACCESS,
ERROR_INVALID_SESSION_TOKEN,
ERROR_NO_CONNECTION,
- ERROR_WRONG_SRP_CREDENTIALS,
NO_ERROR_API_V4,
ERROR_DNS_RESUOLUTION_TOR_FALLBACK
}
- public static void provideBackendResponsesFor(TestBackendErrorCase errorCase) throws IOException {
+ public static ProviderApiConnector.ProviderApiConnectorInterface provideBackendResponsesFor(TestBackendErrorCase errorCase) throws IOException {
switch (errorCase) {
+ case NO_ERROR -> {
+ return new NoErrorBackendResponse();
+ }
+ case NO_ERROR_API_V4 -> {
+ return new NoErrorBackendResponseAPIv4();
+ }
+ case ERROR_CASE_UPDATED_CERTIFICATE -> {
+ return new UpdatedCertificateBackendResponse();
+ }
+ case ERROR_CASE_MICONFIGURED_PROVIDER -> {
+ return new MisconfiguredProviderBackendResponse();
+ }
+ case ERROR_CASE_FETCH_EIP_SERVICE_CERTIFICATE_INVALID -> {
+ return new EipServiceJsonInvalidCertificateBackendResponse();
+ }
+ case ERROR_GEOIP_SERVICE_IS_DOWN -> {
+ return new GeoIpServiceIsDownBackendResponse();
+ }
+ case ERROR_GEOIP_SERVICE_IS_DOWN_TOR_FALLBACK -> {
+ return new GeoIpServiceNotReachableTorFallbackBackendResponse();
+ }
+ case ERROR_DNS_RESUOLUTION_TOR_FALLBACK -> {
+ return new TorFallbackBackendResponse();
+ }
- case NO_ERROR:
- new NoErrorBackendResponse();
- break;
- case NO_ERROR_API_V4:
- new NoErrorBackendResponseAPIv4();
- break;
- case ERROR_CASE_UPDATED_CERTIFICATE:
- new UpdatedCertificateBackendResponse();
- break;
- case ERROR_CASE_MICONFIGURED_PROVIDER:
- new MisconfiguredProviderBackendResponse();
- break;
- case ERROR_CASE_FETCH_EIP_SERVICE_CERTIFICATE_INVALID:
- new EipSerivceJsonInvalidCertificateBackendResponse();
- break;
- case ERROR_GEOIP_SERVICE_IS_DOWN:
- new GeoIpServiceIsDownBackendResponse();
- break;
- case ERROR_GEOIP_SERVICE_IS_DOWN_TOR_FALLBACK:
- new GeoIpServiceNotReachableTorFallbackBackendResponse();
- case ERROR_DNS_RESUOLUTION_TOR_FALLBACK:
- new TorFallbackBackendResponse();
- break;
- case ERROR_NO_RESPONSE_BODY:
- break;
- case ERROR_DNS_RESOLUTION_ERROR:
- break;
- case ERROR_SOCKET_TIMEOUT:
- break;
- case ERROR_WRONG_PROTOCOL:
- break;
- case ERROR_CERTIFICATE_INVALID:
- break;
- case ERROR_WRONG_PORT:
- break;
- case ERROR_PAYLOAD_MISSING:
- break;
- case ERROR_TLS_1_2_NOT_SUPPORTED:
- break;
- case ERROR_UNKNOWN_IO_EXCEPTION:
- break;
- case ERROR_NO_ACCESS:
- break;
- case ERROR_INVALID_SESSION_TOKEN:
- break;
- case ERROR_NO_CONNECTION:
- break;
- case ERROR_WRONG_SRP_CREDENTIALS:
- break;
+ default -> {
+ return new NoErrorBackendResponse();
+ }
}
}
}
diff --git a/app/src/test/java/se/leap/bitmaskclient/testutils/BackendMockResponses/BaseBackendResponse.java b/app/src/test/java/se/leap/bitmaskclient/testutils/BackendMockResponses/BaseBackendResponse.java
deleted file mode 100644
index 9a538d3c..00000000
--- a/app/src/test/java/se/leap/bitmaskclient/testutils/BackendMockResponses/BaseBackendResponse.java
+++ /dev/null
@@ -1,75 +0,0 @@
-/**
- * Copyright (c) 2018 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/>.
- */
-package se.leap.bitmaskclient.testutils.BackendMockResponses;
-
-import android.util.Pair;
-
-import org.mockito.ArgumentMatchers;
-import org.mockito.Mockito;
-import org.mockito.stubbing.Answer;
-
-import java.io.IOException;
-
-import okhttp3.OkHttpClient;
-import se.leap.bitmaskclient.providersetup.ProviderApiConnector;
-
-import static org.mockito.ArgumentMatchers.any;
-import static org.mockito.ArgumentMatchers.anyString;
-import static org.mockito.ArgumentMatchers.nullable;
-import static org.powermock.api.mockito.PowerMockito.mockStatic;
-
-/**
- * Created by cyberta on 10.01.18.
- */
-
-public abstract class BaseBackendResponse {
-
- private Answer<String> answerRequestStringFromServer;
- private Answer<Boolean> answerCanConnect;
- private Answer<Boolean> answerDelete;
-
- public BaseBackendResponse() throws IOException {
- mockStatic(ProviderApiConnector.class);
- this.answerRequestStringFromServer = getAnswerForRequestStringFromServer();
- this.answerCanConnect = getAnswerForCanConnect();
- this.answerDelete = getAnswerForDelete();
-
- responseOnRequestStringFromServer();
- responseOnCanConnect();
- responseOnDelete();
-
- }
-
- public abstract Answer<String> getAnswerForRequestStringFromServer();
- public abstract Answer<Boolean> getAnswerForCanConnect();
- public abstract Answer<Boolean> getAnswerForDelete();
-
-
- public void responseOnRequestStringFromServer() throws IOException, RuntimeException {
- Mockito.when(ProviderApiConnector.requestStringFromServer(anyString(), anyString(), nullable(String.class), ArgumentMatchers.<Pair<String,String>>anyList(), any(OkHttpClient.class))).
- thenAnswer(answerRequestStringFromServer);
- }
-
- public void responseOnCanConnect() throws IOException, RuntimeException {
- Mockito.when(ProviderApiConnector.canConnect(any(OkHttpClient.class), anyString())).thenAnswer(answerCanConnect);
- }
-
- public void responseOnDelete() throws IOException, RuntimeException {
- Mockito.when(ProviderApiConnector.delete(any(OkHttpClient.class), anyString())).thenAnswer(answerDelete);
- }
-
-}
diff --git a/app/src/test/java/se/leap/bitmaskclient/testutils/BackendMockResponses/EipSerivceJsonInvalidCertificateBackendResponse.java b/app/src/test/java/se/leap/bitmaskclient/testutils/BackendMockResponses/EipSerivceJsonInvalidCertificateBackendResponse.java
deleted file mode 100644
index 7c2d49cc..00000000
--- a/app/src/test/java/se/leap/bitmaskclient/testutils/BackendMockResponses/EipSerivceJsonInvalidCertificateBackendResponse.java
+++ /dev/null
@@ -1,94 +0,0 @@
-/**
- * Copyright (c) 2018 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/>.
- */
-package se.leap.bitmaskclient.testutils.BackendMockResponses;
-
-import org.mockito.invocation.InvocationOnMock;
-import org.mockito.stubbing.Answer;
-
-import java.io.IOException;
-
-import javax.net.ssl.SSLHandshakeException;
-
-import static se.leap.bitmaskclient.testutils.TestSetupHelper.getInputAsString;
-
-/**
- * Created by cyberta on 10.01.18.
- */
-
-public class EipSerivceJsonInvalidCertificateBackendResponse extends BaseBackendResponse {
- public EipSerivceJsonInvalidCertificateBackendResponse() throws IOException {
- super();
- }
-
- @Override
- public Answer<String> getAnswerForRequestStringFromServer() {
- return new Answer<String>() {
- @Override
- public String answer(InvocationOnMock invocation) throws Throwable {
- String url = (String) invocation.getArguments()[0];
- String requestMethod = (String) invocation.getArguments()[1];
- String jsonPayload = (String) invocation.getArguments()[2];
-
- if (url.contains("/provider.json")) {
- //download provider json
- return getInputAsString(getClass().getClassLoader().getResourceAsStream("riseup.net.json"));
- } else if (url.contains("/ca.crt")) {
- //download provider ca cert
- return getInputAsString(getClass().getClassLoader().getResourceAsStream("riseup.net.pem"));
- } else if (url.contains("config/eip-service.json")) {
- // download provider service json containing gateways, locations and openvpn settings
- throw new SSLHandshakeException("Invalid provider CA certificate");
- } else if (url.contains(":9001/json")) {
- // download geoip json, containing a sorted list of gateways
- return getInputAsString(getClass().getClassLoader().getResourceAsStream("riseup.geoip.json"));
- } else if (url.contains("/users.json")) {
- //create new user
- //TODO: implement me
- } else if (url.contains("/sessions.json")) {
- //srp auth: sendAToSRPServer
- //TODO: implement me
- } else if (url.contains("/sessions/parmegvtest10.json")){
- //srp auth: sendM1ToSRPServer
- //TODO: implement me
- }
-
- return null;
- }
- };
- }
-
- @Override
- public Answer<Boolean> getAnswerForCanConnect() {
- return new Answer<Boolean>() {
- @Override
- public Boolean answer(InvocationOnMock invocation) throws Throwable {
- return true;
- }
- };
- }
-
- @Override
- public Answer<Boolean> getAnswerForDelete() {
- return new Answer<Boolean>() {
- @Override
- public Boolean answer(InvocationOnMock invocation) throws Throwable {
- return true;
- }
- };
- }
-
-}
diff --git a/app/src/test/java/se/leap/bitmaskclient/testutils/BackendMockResponses/EipServiceJsonInvalidCertificateBackendResponse.java b/app/src/test/java/se/leap/bitmaskclient/testutils/BackendMockResponses/EipServiceJsonInvalidCertificateBackendResponse.java
new file mode 100644
index 00000000..15df00cb
--- /dev/null
+++ b/app/src/test/java/se/leap/bitmaskclient/testutils/BackendMockResponses/EipServiceJsonInvalidCertificateBackendResponse.java
@@ -0,0 +1,66 @@
+/**
+ * Copyright (c) 2018 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/>.
+ */
+package se.leap.bitmaskclient.testutils.BackendMockResponses;
+
+import java.io.IOException;
+import java.util.List;
+
+import javax.net.ssl.SSLHandshakeException;
+
+import static se.leap.bitmaskclient.testutils.TestSetupHelper.getInputAsString;
+
+import android.util.Pair;
+
+import androidx.annotation.NonNull;
+
+import okhttp3.OkHttpClient;
+import se.leap.bitmaskclient.providersetup.ProviderApiConnector;
+
+/**
+ * Created by cyberta on 10.01.18.
+ */
+
+public class EipServiceJsonInvalidCertificateBackendResponse implements ProviderApiConnector.ProviderApiConnectorInterface {
+
+ @Override
+ public boolean delete(OkHttpClient okHttpClient, String deleteUrl) {
+ return true;
+ }
+
+ @Override
+ public boolean canConnect(@NonNull OkHttpClient okHttpClient, String url) throws RuntimeException, IOException {
+ return true;
+ }
+
+ @Override
+ public String requestStringFromServer(@NonNull String url, @NonNull String requestMethod, String jsonString, @NonNull List<Pair<String, String>> headerArgs, @NonNull OkHttpClient okHttpClient) throws RuntimeException, IOException {
+ if (url.contains("/provider.json")) {
+ //download provider json
+ return getInputAsString(getClass().getClassLoader().getResourceAsStream("riseup.net.json"));
+ } else if (url.contains("/ca.crt")) {
+ //download provider ca cert
+ return getInputAsString(getClass().getClassLoader().getResourceAsStream("riseup.net.pem"));
+ } else if (url.contains("config/eip-service.json")) {
+ // download provider service json containing gateways, locations and openvpn settings
+ throw new SSLHandshakeException("Invalid provider CA certificate");
+ } else if (url.contains(":9001/json")) {
+ // download geoip json, containing a sorted list of gateways
+ return getInputAsString(getClass().getClassLoader().getResourceAsStream("riseup.geoip.json"));
+ }
+ return null;
+ }
+}
diff --git a/app/src/test/java/se/leap/bitmaskclient/testutils/BackendMockResponses/GeoIpServiceIsDownBackendResponse.java b/app/src/test/java/se/leap/bitmaskclient/testutils/BackendMockResponses/GeoIpServiceIsDownBackendResponse.java
index 3a08d8da..482276a6 100644
--- a/app/src/test/java/se/leap/bitmaskclient/testutils/BackendMockResponses/GeoIpServiceIsDownBackendResponse.java
+++ b/app/src/test/java/se/leap/bitmaskclient/testutils/BackendMockResponses/GeoIpServiceIsDownBackendResponse.java
@@ -16,78 +16,51 @@
*/
package se.leap.bitmaskclient.testutils.BackendMockResponses;
-import org.mockito.invocation.InvocationOnMock;
-import org.mockito.stubbing.Answer;
+import static se.leap.bitmaskclient.testutils.TestSetupHelper.getInputAsString;
+
+import android.util.Pair;
+
+import androidx.annotation.NonNull;
import java.io.IOException;
import java.net.ConnectException;
+import java.util.List;
-import static se.leap.bitmaskclient.testutils.TestSetupHelper.getInputAsString;
+import okhttp3.OkHttpClient;
+import se.leap.bitmaskclient.providersetup.ProviderApiConnector;
/**
* Created by cyberta on 10.01.18.
*/
-public class GeoIpServiceIsDownBackendResponse extends BaseBackendResponse {
- public GeoIpServiceIsDownBackendResponse() throws IOException {
- super();
- }
+public class GeoIpServiceIsDownBackendResponse implements ProviderApiConnector.ProviderApiConnectorInterface {
@Override
- public Answer<String> getAnswerForRequestStringFromServer() {
- return new Answer<String>() {
- @Override
- public String answer(InvocationOnMock invocation) throws Throwable {
- String url = (String) invocation.getArguments()[0];
- String requestMethod = (String) invocation.getArguments()[1];
- String jsonPayload = (String) invocation.getArguments()[2];
-
- if (url.contains("/provider.json")) {
- //download provider json
- return getInputAsString(getClass().getClassLoader().getResourceAsStream("riseup.net.json"));
- } else if (url.contains("/ca.crt")) {
- //download provider ca cert
- return getInputAsString(getClass().getClassLoader().getResourceAsStream("riseup.net.pem"));
- } else if (url.contains("config/eip-service.json")) {
- // download provider service json containing gateways, locations and openvpn settings
- return getInputAsString(getClass().getClassLoader().getResourceAsStream("riseup.service.json"));
- } else if (url.contains(":9001/json")) {
- // download geoip json, containing a sorted list of gateways
- throw new ConnectException("Failed to connect to api.black.riseup.net/198.252.153.107:9001");
- } else if (url.contains("/users.json")) {
- //create new user
- //TODO: implement me
- } else if (url.contains("/sessions.json")) {
- //srp auth: sendAToSRPServer
- //TODO: implement me
- } else if (url.contains("/sessions/parmegvtest10.json")){
- //srp auth: sendM1ToSRPServer
- //TODO: implement me
- }
-
- return null;
- }
- };
+ public boolean delete(OkHttpClient okHttpClient, String deleteUrl) throws RuntimeException, IOException {
+ return true;
}
@Override
- public Answer<Boolean> getAnswerForCanConnect() {
- return new Answer<Boolean>() {
- @Override
- public Boolean answer(InvocationOnMock invocation) throws Throwable {
- return true;
- }
- };
+ public boolean canConnect(@NonNull OkHttpClient okHttpClient, String url) throws RuntimeException, IOException {
+ return true;
}
@Override
- public Answer<Boolean> getAnswerForDelete() {
- return new Answer<Boolean>() {
- @Override
- public Boolean answer(InvocationOnMock invocation) throws Throwable {
- return true;
- }
- };
- }
+ public String requestStringFromServer(@NonNull String url, @NonNull String requestMethod, String jsonString, @NonNull List<Pair<String, String>> headerArgs, @NonNull OkHttpClient okHttpClient) throws RuntimeException, IOException {
+ if (url.contains("/provider.json")) {
+ //download provider json
+ return getInputAsString(getClass().getClassLoader().getResourceAsStream("riseup.net.json"));
+ } else if (url.contains("/ca.crt")) {
+ //download provider ca cert
+ return getInputAsString(getClass().getClassLoader().getResourceAsStream("riseup.net.pem"));
+ } else if (url.contains("config/eip-service.json")) {
+ // download provider service json containing gateways, locations and openvpn settings
+ return getInputAsString(getClass().getClassLoader().getResourceAsStream("riseup.service.json"));
+ } else if (url.contains(":9001/json")) {
+ // download geoip json, containing a sorted list of gateways
+ throw new ConnectException("Failed to connect to api.black.riseup.net/198.252.153.107:9001");
+ }
+ return null;
+ }
}
diff --git a/app/src/test/java/se/leap/bitmaskclient/testutils/BackendMockResponses/GeoIpServiceNotReachableTorFallbackBackendResponse.java b/app/src/test/java/se/leap/bitmaskclient/testutils/BackendMockResponses/GeoIpServiceNotReachableTorFallbackBackendResponse.java
index 02aa31fa..d11c21f8 100644
--- a/app/src/test/java/se/leap/bitmaskclient/testutils/BackendMockResponses/GeoIpServiceNotReachableTorFallbackBackendResponse.java
+++ b/app/src/test/java/se/leap/bitmaskclient/testutils/BackendMockResponses/GeoIpServiceNotReachableTorFallbackBackendResponse.java
@@ -16,74 +16,61 @@
*/
package se.leap.bitmaskclient.testutils.BackendMockResponses;
-import org.mockito.invocation.InvocationOnMock;
-import org.mockito.stubbing.Answer;
+import static se.leap.bitmaskclient.testutils.TestSetupHelper.getInputAsString;
+
+import android.util.Pair;
+
+import androidx.annotation.NonNull;
import java.io.IOException;
import java.net.ConnectException;
+import java.util.List;
-import static se.leap.bitmaskclient.testutils.TestSetupHelper.getInputAsString;
+import okhttp3.OkHttpClient;
+import se.leap.bitmaskclient.providersetup.ProviderApiConnector;
/**
* Created by cyberta on 10.01.18.
*/
-public class GeoIpServiceNotReachableTorFallbackBackendResponse extends BaseBackendResponse {
+public class GeoIpServiceNotReachableTorFallbackBackendResponse implements ProviderApiConnector.ProviderApiConnectorInterface {
public GeoIpServiceNotReachableTorFallbackBackendResponse() throws IOException {
super();
}
int requestAttempt = 0;
@Override
- public Answer<String> getAnswerForRequestStringFromServer() {
- return new Answer<String>() {
- @Override
- public String answer(InvocationOnMock invocation) throws Throwable {
- String url = (String) invocation.getArguments()[0];
-
- if (url.contains("/provider.json")) {
- //download provider json
- return getInputAsString(getClass().getClassLoader().getResourceAsStream("riseup.net.json"));
- } else if (url.contains("/ca.crt")) {
- //download provider ca cert
- return getInputAsString(getClass().getClassLoader().getResourceAsStream("riseup.net.pem"));
- } else if (url.contains("config/eip-service.json")) {
- // download provider service json containing gateways, locations and openvpn settings
- return getInputAsString(getClass().getClassLoader().getResourceAsStream("riseup.service.json"));
- } else if (url.contains(":9001/json")) {
- if (requestAttempt == 0) {
- // download geoip json, containing a sorted list of gateways
- requestAttempt++;
- throw new ConnectException("Failed to connect to api.black.riseup.net/198.252.153.107:9001");
- } else {
- // assumtion: 2. connection attempt has been made with proxy on, which is not allowed
- // this branch should never be called otherwise you have found a bug
- return getInputAsString(getClass().getClassLoader().getResourceAsStream("riseup.geoip.json"));
- }
- }
- return null;
- }
- };
+ public boolean delete(OkHttpClient okHttpClient, String deleteUrl) throws RuntimeException, IOException {
+ return true;
}
@Override
- public Answer<Boolean> getAnswerForCanConnect() {
- return new Answer<Boolean>() {
- @Override
- public Boolean answer(InvocationOnMock invocation) throws Throwable {
- return true;
- }
- };
+ public boolean canConnect(@NonNull OkHttpClient okHttpClient, String url) throws RuntimeException, IOException {
+ return true;
}
@Override
- public Answer<Boolean> getAnswerForDelete() {
- return new Answer<Boolean>() {
- @Override
- public Boolean answer(InvocationOnMock invocation) throws Throwable {
- return true;
+ public String requestStringFromServer(@NonNull String url, @NonNull String requestMethod, String jsonString, @NonNull List<Pair<String, String>> headerArgs, @NonNull OkHttpClient okHttpClient) throws RuntimeException, IOException {
+ if (url.contains("/provider.json")) {
+ //download provider json
+ return getInputAsString(getClass().getClassLoader().getResourceAsStream("riseup.net.json"));
+ } else if (url.contains("/ca.crt")) {
+ //download provider ca cert
+ return getInputAsString(getClass().getClassLoader().getResourceAsStream("riseup.net.pem"));
+ } else if (url.contains("config/eip-service.json")) {
+ // download provider service json containing gateways, locations and openvpn settings
+ return getInputAsString(getClass().getClassLoader().getResourceAsStream("riseup.service.json"));
+ } else if (url.contains(":9001/json")) {
+ if (requestAttempt == 0) {
+ // download geoip json, containing a sorted list of gateways
+ requestAttempt++;
+ throw new ConnectException("Failed to connect to api.black.riseup.net/198.252.153.107:9001");
+ } else {
+ // assumtion: 2. connection attempt has been made with proxy on, which is not allowed
+ // this branch should never be called otherwise you have found a bug
+ return getInputAsString(getClass().getClassLoader().getResourceAsStream("riseup.geoip.json"));
}
- };
+ }
+ return null;
}
-
}
diff --git a/app/src/test/java/se/leap/bitmaskclient/testutils/BackendMockResponses/MisconfiguredProviderBackendResponse.java b/app/src/test/java/se/leap/bitmaskclient/testutils/BackendMockResponses/MisconfiguredProviderBackendResponse.java
index 10e69bc3..301f1a75 100644
--- a/app/src/test/java/se/leap/bitmaskclient/testutils/BackendMockResponses/MisconfiguredProviderBackendResponse.java
+++ b/app/src/test/java/se/leap/bitmaskclient/testutils/BackendMockResponses/MisconfiguredProviderBackendResponse.java
@@ -16,77 +16,50 @@
*/
package se.leap.bitmaskclient.testutils.BackendMockResponses;
-import org.mockito.invocation.InvocationOnMock;
-import org.mockito.stubbing.Answer;
+import static se.leap.bitmaskclient.testutils.TestSetupHelper.getInputAsString;
+
+import android.util.Pair;
+
+import androidx.annotation.NonNull;
import java.io.IOException;
+import java.util.List;
-import static se.leap.bitmaskclient.testutils.TestSetupHelper.getInputAsString;
+import okhttp3.OkHttpClient;
+import se.leap.bitmaskclient.providersetup.ProviderApiConnector;
/**
* Created by cyberta on 10.01.18.
*/
-public class MisconfiguredProviderBackendResponse extends BaseBackendResponse {
- public MisconfiguredProviderBackendResponse() throws IOException {
- super();
- }
+public class MisconfiguredProviderBackendResponse implements ProviderApiConnector.ProviderApiConnectorInterface {
@Override
- public Answer<String> getAnswerForRequestStringFromServer() {
- return new Answer<String>() {
- @Override
- public String answer(InvocationOnMock invocation) throws Throwable {
- String url = (String) invocation.getArguments()[0];
- String requestMethod = (String) invocation.getArguments()[1];
- String jsonPayload = (String) invocation.getArguments()[2];
-
- if (url.contains("/provider.json")) {
- //download provider json
- return getInputAsString(getClass().getClassLoader().getResourceAsStream("riseup_net_invalid_config.json"));
- } else if (url.contains("/ca.crt")) {
- //download provider ca cert
- return getInputAsString(getClass().getClassLoader().getResourceAsStream("riseup.net.pem"));
- } else if (url.contains("config/eip-service.json")) {
- // download provider service json containing gateways, locations and openvpn settings
- return getInputAsString(getClass().getClassLoader().getResourceAsStream("riseup.service.json"));
- } else if (url.contains(":9001/json")) {
- // download geoip json, containing a sorted list of gateways
- return getInputAsString(getClass().getClassLoader().getResourceAsStream("riseup.geoip.json"));
- } else if (url.contains("/users.json")) {
- //create new user
- //TODO: implement me
- } else if (url.contains("/sessions.json")) {
- //srp auth: sendAToSRPServer
- //TODO: implement me
- } else if (url.contains("/sessions/parmegvtest10.json")){
- //srp auth: sendM1ToSRPServer
- //TODO: implement me
- }
-
- return null;
- }
- };
+ public boolean delete(OkHttpClient okHttpClient, String deleteUrl) throws RuntimeException, IOException {
+ return true;
}
@Override
- public Answer<Boolean> getAnswerForCanConnect() {
- return new Answer<Boolean>() {
- @Override
- public Boolean answer(InvocationOnMock invocation) throws Throwable {
- return true;
- }
- };
+ public boolean canConnect(@NonNull OkHttpClient okHttpClient, String url) throws RuntimeException, IOException {
+ return true;
}
@Override
- public Answer<Boolean> getAnswerForDelete() {
- return new Answer<Boolean>() {
- @Override
- public Boolean answer(InvocationOnMock invocation) throws Throwable {
- return true;
- }
- };
- }
+ public String requestStringFromServer(@NonNull String url, @NonNull String requestMethod, String jsonString, @NonNull List<Pair<String, String>> headerArgs, @NonNull OkHttpClient okHttpClient) throws RuntimeException, IOException {
+ if (url.contains("/provider.json")) {
+ //download provider json
+ return getInputAsString(getClass().getClassLoader().getResourceAsStream("riseup_net_invalid_config.json"));
+ } else if (url.contains("/ca.crt")) {
+ //download provider ca cert
+ return getInputAsString(getClass().getClassLoader().getResourceAsStream("riseup.net.pem"));
+ } else if (url.contains("config/eip-service.json")) {
+ // download provider service json containing gateways, locations and openvpn settings
+ return getInputAsString(getClass().getClassLoader().getResourceAsStream("riseup.service.json"));
+ } else if (url.contains(":9001/json")) {
+ // download geoip json, containing a sorted list of gateways
+ return getInputAsString(getClass().getClassLoader().getResourceAsStream("riseup.geoip.json"));
+ }
+ return null;
+ }
}
diff --git a/app/src/test/java/se/leap/bitmaskclient/testutils/BackendMockResponses/NoErrorBackendResponse.java b/app/src/test/java/se/leap/bitmaskclient/testutils/BackendMockResponses/NoErrorBackendResponse.java
index 3c3a8ffa..44067139 100644
--- a/app/src/test/java/se/leap/bitmaskclient/testutils/BackendMockResponses/NoErrorBackendResponse.java
+++ b/app/src/test/java/se/leap/bitmaskclient/testutils/BackendMockResponses/NoErrorBackendResponse.java
@@ -16,77 +16,50 @@
*/
package se.leap.bitmaskclient.testutils.BackendMockResponses;
-import org.mockito.invocation.InvocationOnMock;
-import org.mockito.stubbing.Answer;
+import static se.leap.bitmaskclient.testutils.TestSetupHelper.getInputAsString;
+
+import android.util.Pair;
+
+import androidx.annotation.NonNull;
import java.io.IOException;
+import java.util.List;
-import static se.leap.bitmaskclient.testutils.TestSetupHelper.getInputAsString;
+import okhttp3.OkHttpClient;
+import se.leap.bitmaskclient.providersetup.ProviderApiConnector;
/**
* Created by cyberta on 10.01.18.
*/
-public class NoErrorBackendResponse extends BaseBackendResponse {
- public NoErrorBackendResponse() throws IOException {
- super();
- }
+public class NoErrorBackendResponse implements ProviderApiConnector.ProviderApiConnectorInterface {
@Override
- public Answer<String> getAnswerForRequestStringFromServer() {
- return new Answer<String>() {
- @Override
- public String answer(InvocationOnMock invocation) throws Throwable {
- String url = (String) invocation.getArguments()[0];
- String requestMethod = (String) invocation.getArguments()[1];
- String jsonPayload = (String) invocation.getArguments()[2];
-
- if (url.contains("/provider.json")) {
- //download provider json
- return getInputAsString(getClass().getClassLoader().getResourceAsStream("riseup.net.json"));
- } else if (url.contains("/ca.crt")) {
- //download provider ca cert
- return getInputAsString(getClass().getClassLoader().getResourceAsStream("riseup.net.pem"));
- } else if (url.contains("config/eip-service.json")) {
- // download provider service json containing gateways, locations and openvpn settings
- return getInputAsString(getClass().getClassLoader().getResourceAsStream("riseup.service.json"));
- } else if (url.contains(":9001/json")) {
- // download geoip json, containing a sorted list of gateways
- return getInputAsString(getClass().getClassLoader().getResourceAsStream("riseup.geoip.json"));
- } else if (url.contains("/users.json")) {
- //create new user
- //TODO: implement me
- } else if (url.contains("/sessions.json")) {
- //srp auth: sendAToSRPServer
- //TODO: implement me
- } else if (url.contains("/sessions/parmegvtest10.json")){
- //srp auth: sendM1ToSRPServer
- //TODO: implement me
- }
-
- return null;
- }
- };
+ public boolean delete(OkHttpClient okHttpClient, String deleteUrl) {
+ return true;
}
@Override
- public Answer<Boolean> getAnswerForCanConnect() {
- return new Answer<Boolean>() {
- @Override
- public Boolean answer(InvocationOnMock invocation) throws Throwable {
- return true;
- }
- };
+ public boolean canConnect(@NonNull OkHttpClient okHttpClient, String url) throws RuntimeException, IOException {
+ return true;
}
@Override
- public Answer<Boolean> getAnswerForDelete() {
- return new Answer<Boolean>() {
- @Override
- public Boolean answer(InvocationOnMock invocation) throws Throwable {
- return true;
- }
- };
- }
+ public String requestStringFromServer(@NonNull String url, @NonNull String requestMethod, String jsonString, @NonNull List<Pair<String, String>> headerArgs, @NonNull OkHttpClient okHttpClient) throws RuntimeException, IOException {
+ if (url.contains("/provider.json")) {
+ //download provider json
+ return getInputAsString(getClass().getClassLoader().getResourceAsStream("riseup.net.json"));
+ } else if (url.contains("/ca.crt")) {
+ //download provider ca cert
+ return getInputAsString(getClass().getClassLoader().getResourceAsStream("riseup.net.pem"));
+ } else if (url.contains("config/eip-service.json")) {
+ // download provider service json containing gateways, locations and openvpn settings
+ return getInputAsString(getClass().getClassLoader().getResourceAsStream("riseup.service.json"));
+ } else if (url.contains(":9001/json")) {
+ // download geoip json, containing a sorted list of gateways
+ return getInputAsString(getClass().getClassLoader().getResourceAsStream("riseup.geoip.json"));
+ }
+ return null;
+ }
}
diff --git a/app/src/test/java/se/leap/bitmaskclient/testutils/BackendMockResponses/NoErrorBackendResponseAPIv4.java b/app/src/test/java/se/leap/bitmaskclient/testutils/BackendMockResponses/NoErrorBackendResponseAPIv4.java
index b9dc26b1..bbbed821 100644
--- a/app/src/test/java/se/leap/bitmaskclient/testutils/BackendMockResponses/NoErrorBackendResponseAPIv4.java
+++ b/app/src/test/java/se/leap/bitmaskclient/testutils/BackendMockResponses/NoErrorBackendResponseAPIv4.java
@@ -16,80 +16,52 @@
*/
package se.leap.bitmaskclient.testutils.BackendMockResponses;
-import org.mockito.invocation.InvocationOnMock;
-import org.mockito.stubbing.Answer;
+import static se.leap.bitmaskclient.testutils.TestSetupHelper.getInputAsString;
+
+import android.util.Pair;
+
+import androidx.annotation.NonNull;
import java.io.IOException;
+import java.util.List;
-import static se.leap.bitmaskclient.testutils.TestSetupHelper.getInputAsString;
+import okhttp3.OkHttpClient;
+import se.leap.bitmaskclient.providersetup.ProviderApiConnector;
/**
* Created by cyberta on 10.01.18.
*/
-public class NoErrorBackendResponseAPIv4 extends BaseBackendResponse {
- public NoErrorBackendResponseAPIv4() throws IOException {
- super();
- }
-
+public class NoErrorBackendResponseAPIv4 implements ProviderApiConnector.ProviderApiConnectorInterface {
@Override
- public Answer<String> getAnswerForRequestStringFromServer() {
- return new Answer<String>() {
- @Override
- public String answer(InvocationOnMock invocation) throws Throwable {
- String url = (String) invocation.getArguments()[0];
- String requestMethod = (String) invocation.getArguments()[1];
- String jsonPayload = (String) invocation.getArguments()[2];
-
- if (url.contains("/provider.json")) {
- //download provider json
- return getInputAsString(getClass().getClassLoader().getResourceAsStream("v4/riseup.net.json"));
- } else if (url.contains("/ca.crt")) {
- //download provider ca cert
- return getInputAsString(getClass().getClassLoader().getResourceAsStream("riseup.net.pem"));
- } else if (url.contains("config/eip-service.json")) {
- // download provider service json containing gateways, locations and openvpn settings
- return getInputAsString(getClass().getClassLoader().getResourceAsStream("v4/riseup.service.json"));
- } else if (url.contains(":9001/json")) {
- // download geoip json, containing a sorted list of gateways
- return getInputAsString(getClass().getClassLoader().getResourceAsStream("riseup.geoip.json"));
- } else if (url.contains("/cert")) {
- // download vpn key and cert
- return getInputAsString(getClass().getClassLoader().getResourceAsStream("v4/riseup.net.cert"));
- } else if (url.contains("/users.json")) {
- //create new user
- //TODO: implement me
- } else if (url.contains("/sessions.json")) {
- //srp auth: sendAToSRPServer
- //TODO: implement me
- } else if (url.contains("/sessions/parmegvtest10.json")){
- //srp auth: sendM1ToSRPServer
- //TODO: implement me
- }
-
- return null;
- }
- };
+ public boolean delete(OkHttpClient okHttpClient, String deleteUrl) {
+ return true;
}
@Override
- public Answer<Boolean> getAnswerForCanConnect() {
- return new Answer<Boolean>() {
- @Override
- public Boolean answer(InvocationOnMock invocation) throws Throwable {
- return true;
- }
- };
+ public boolean canConnect(@NonNull OkHttpClient okHttpClient, String url) throws RuntimeException, IOException {
+ return true;
}
@Override
- public Answer<Boolean> getAnswerForDelete() {
- return new Answer<Boolean>() {
- @Override
- public Boolean answer(InvocationOnMock invocation) throws Throwable {
- return true;
- }
- };
- }
+ public String requestStringFromServer(@NonNull String url, @NonNull String requestMethod, String jsonString, @NonNull List<Pair<String, String>> headerArgs, @NonNull OkHttpClient okHttpClient) throws RuntimeException, IOException {
+ if (url.contains("/provider.json")) {
+ //download provider json
+ return getInputAsString(getClass().getClassLoader().getResourceAsStream("v4/riseup.net.json"));
+ } else if (url.contains("/ca.crt")) {
+ //download provider ca cert
+ return getInputAsString(getClass().getClassLoader().getResourceAsStream("riseup.net.pem"));
+ } else if (url.contains("config/eip-service.json")) {
+ // download provider service json containing gateways, locations and openvpn settings
+ return getInputAsString(getClass().getClassLoader().getResourceAsStream("v4/riseup.service.json"));
+ } else if (url.contains(":9001/json")) {
+ // download geoip json, containing a sorted list of gateways
+ return getInputAsString(getClass().getClassLoader().getResourceAsStream("riseup.geoip.json"));
+ } else if (url.contains("/cert")) {
+ // download vpn key and cert
+ return getInputAsString(getClass().getClassLoader().getResourceAsStream("v4/riseup.net.cert"));
+ }
+ return null;
+ }
}
diff --git a/app/src/test/java/se/leap/bitmaskclient/testutils/BackendMockResponses/TorFallbackBackendResponse.java b/app/src/test/java/se/leap/bitmaskclient/testutils/BackendMockResponses/TorFallbackBackendResponse.java
index c3779a21..45dd36e4 100644
--- a/app/src/test/java/se/leap/bitmaskclient/testutils/BackendMockResponses/TorFallbackBackendResponse.java
+++ b/app/src/test/java/se/leap/bitmaskclient/testutils/BackendMockResponses/TorFallbackBackendResponse.java
@@ -1,94 +1,81 @@
package se.leap.bitmaskclient.testutils.BackendMockResponses;
-import org.mockito.invocation.InvocationOnMock;
-import org.mockito.stubbing.Answer;
+import static se.leap.bitmaskclient.testutils.TestSetupHelper.getInputAsString;
+
+import android.util.Pair;
+
+import androidx.annotation.NonNull;
import java.io.IOException;
import java.net.UnknownHostException;
+import java.util.List;
-import static se.leap.bitmaskclient.testutils.TestSetupHelper.getInputAsString;
+import okhttp3.OkHttpClient;
+import se.leap.bitmaskclient.providersetup.ProviderApiConnector;
-public class TorFallbackBackendResponse extends BaseBackendResponse {
+public class TorFallbackBackendResponse implements ProviderApiConnector.ProviderApiConnectorInterface {
public TorFallbackBackendResponse() throws IOException {
super();
}
int requestAttempt = 0;
@Override
- public Answer<String> getAnswerForRequestStringFromServer() {
- return new Answer<String>() {
- @Override
- public String answer(InvocationOnMock invocation) throws Throwable {
- String url = (String) invocation.getArguments()[0];
-
- if (url.contains("/provider.json")) {
- if (requestAttempt == 0) {
- requestAttempt++;
- throw new UnknownHostException();
- }
- //download provider json
- return getInputAsString(getClass().getClassLoader().getResourceAsStream("v4/riseup.net.json"));
- } else if (url.contains("/ca.crt")) {
- if (requestAttempt == 0) {
- requestAttempt++;
- throw new UnknownHostException("DNS blocked by censor ;)");
- }
- //download provider ca cert
- return getInputAsString(getClass().getClassLoader().getResourceAsStream("riseup.net.pem"));
- } else if (url.contains("config/eip-service.json")) {
- if (requestAttempt == 0) {
- requestAttempt++;
- throw new UnknownHostException("DNS blocked by censor ;)");
- }
- // download provider service json containing gateways, locations and openvpn settings
- return getInputAsString(getClass().getClassLoader().getResourceAsStream("v4/riseup.service.json"));
- } else if (url.contains(":9001/json")) {
- if (requestAttempt == 0) {
- requestAttempt++;
- throw new UnknownHostException("DNS blocked by censor ;)");
- }
- // download geoip json, containing a sorted list of gateways
- return getInputAsString(getClass().getClassLoader().getResourceAsStream("riseup.geoip.json"));
- } else if (url.contains("/cert")) {
- if (requestAttempt == 0) {
- requestAttempt++;
- throw new UnknownHostException("DNS blocked by censor ;)");
- }
- // download vpn certificate for authentication
- return getInputAsString(getClass().getClassLoader().getResourceAsStream("v4/riseup.net.cert"));
-
- }
-
- return null;
- }
- };
+ public boolean delete(OkHttpClient okHttpClient, String deleteUrl) throws RuntimeException, IOException {
+ if (requestAttempt == 0) {
+ requestAttempt++;
+ throw new UnknownHostException("DNS blocked by censor ;)");
+ }
+ return true;
}
@Override
- public Answer<Boolean> getAnswerForCanConnect() {
- return new Answer<Boolean>() {
- @Override
- public Boolean answer(InvocationOnMock invocation) throws Throwable {
- if (requestAttempt == 0) {
- requestAttempt++;
- throw new UnknownHostException("DNS blocked by censor ;)");
- }
- return true;
- }
- };
+ public boolean canConnect(@NonNull OkHttpClient okHttpClient, String url) throws RuntimeException, IOException {
+ if (requestAttempt == 0) {
+ requestAttempt++;
+ throw new UnknownHostException("DNS blocked by censor ;)");
+ }
+ return true;
}
@Override
- public Answer<Boolean> getAnswerForDelete() {
- return new Answer<Boolean>() {
- @Override
- public Boolean answer(InvocationOnMock invocation) throws Throwable {
- if (requestAttempt == 0) {
- requestAttempt++;
- throw new UnknownHostException("DNS blocked by censor ;)");
- }
- return true;
+ public String requestStringFromServer(@NonNull String url, @NonNull String requestMethod, String jsonString, @NonNull List<Pair<String, String>> headerArgs, @NonNull OkHttpClient okHttpClient) throws RuntimeException, IOException {
+ if (url.contains("/provider.json")) {
+ if (requestAttempt == 0) {
+ requestAttempt++;
+ throw new UnknownHostException();
+ }
+ //download provider json
+ return getInputAsString(getClass().getClassLoader().getResourceAsStream("v4/riseup.net.json"));
+ } else if (url.contains("/ca.crt")) {
+ if (requestAttempt == 0) {
+ requestAttempt++;
+ throw new UnknownHostException("DNS blocked by censor ;)");
+ }
+ //download provider ca cert
+ return getInputAsString(getClass().getClassLoader().getResourceAsStream("riseup.net.pem"));
+ } else if (url.contains("config/eip-service.json")) {
+ if (requestAttempt == 0) {
+ requestAttempt++;
+ throw new UnknownHostException("DNS blocked by censor ;)");
}
- };
+ // download provider service json containing gateways, locations and openvpn settings
+ return getInputAsString(getClass().getClassLoader().getResourceAsStream("v4/riseup.service.json"));
+ } else if (url.contains(":9001/json")) {
+ if (requestAttempt == 0) {
+ requestAttempt++;
+ throw new UnknownHostException("DNS blocked by censor ;)");
+ }
+ // download geoip json, containing a sorted list of gateways
+ return getInputAsString(getClass().getClassLoader().getResourceAsStream("riseup.geoip.json"));
+ } else if (url.contains("/cert")) {
+ if (requestAttempt == 0) {
+ requestAttempt++;
+ throw new UnknownHostException("DNS blocked by censor ;)");
+ }
+ // download vpn certificate for authentication
+ return getInputAsString(getClass().getClassLoader().getResourceAsStream("v4/riseup.net.cert"));
+
+ }
+ return null;
}
}
diff --git a/app/src/test/java/se/leap/bitmaskclient/testutils/BackendMockResponses/UpdatedCertificateBackendResponse.java b/app/src/test/java/se/leap/bitmaskclient/testutils/BackendMockResponses/UpdatedCertificateBackendResponse.java
index 232649a1..1da18f76 100644
--- a/app/src/test/java/se/leap/bitmaskclient/testutils/BackendMockResponses/UpdatedCertificateBackendResponse.java
+++ b/app/src/test/java/se/leap/bitmaskclient/testutils/BackendMockResponses/UpdatedCertificateBackendResponse.java
@@ -16,82 +16,63 @@
*/
package se.leap.bitmaskclient.testutils.BackendMockResponses;
-import org.mockito.invocation.InvocationOnMock;
-import org.mockito.stubbing.Answer;
+import static se.leap.bitmaskclient.testutils.TestSetupHelper.getInputAsString;
+
+import android.util.Pair;
+
+import androidx.annotation.NonNull;
import java.io.IOException;
+import java.util.List;
import javax.net.ssl.SSLHandshakeException;
-import static se.leap.bitmaskclient.testutils.TestSetupHelper.getInputAsString;
+import okhttp3.OkHttpClient;
+import se.leap.bitmaskclient.providersetup.ProviderApiConnector;
/**
* Created by cyberta on 10.01.18.
*/
-public class UpdatedCertificateBackendResponse extends BaseBackendResponse {
+public class UpdatedCertificateBackendResponse implements ProviderApiConnector.ProviderApiConnectorInterface {
static volatile boolean wasCACertCalled = false;
-
- public UpdatedCertificateBackendResponse() throws IOException {
- super();
- }
-
@Override
- public Answer<String> getAnswerForRequestStringFromServer() {
- return new Answer<String>() {
-
- @Override
- public String answer(InvocationOnMock invocation) throws Throwable {
- String url = (String) invocation.getArguments()[0];
-
- if (url.contains("/provider.json")) {
- if (!wasCACertCalled) {
- throw new SSLHandshakeException("Updated certificate on server side");
- }
- //download provider json
- return getInputAsString(getClass().getClassLoader().getResourceAsStream("riseup.net.json"));
- } else if (url.contains("/ca.crt")) {
- //download provider ca cert
- wasCACertCalled = true;
- return getInputAsString(getClass().getClassLoader().getResourceAsStream("updated_cert.pem"));
- } else if (url.contains("config/eip-service.json")) {
- // download provider service json containing gateways, locations and openvpn settings
- if (!wasCACertCalled) {
- throw new SSLHandshakeException("Updated certificate on server side");
- }
- return getInputAsString(getClass().getClassLoader().getResourceAsStream("riseup.service.json"));
- }
-
- return null;
- }
- };
+ public boolean delete(OkHttpClient okHttpClient, String deleteUrl) throws RuntimeException, IOException {
+ if (!wasCACertCalled) {
+ throw new SSLHandshakeException("Updated certificate on server side");
+ }
+ return true;
}
@Override
- public Answer<Boolean> getAnswerForCanConnect() {
- return new Answer<Boolean>() {
- @Override
- public Boolean answer(InvocationOnMock invocation) throws Throwable {
- if (!wasCACertCalled) {
- throw new SSLHandshakeException("Updated certificate on server side");
- }
- return true;
- }
- };
+ public boolean canConnect(@NonNull OkHttpClient okHttpClient, String url) throws RuntimeException, IOException {
+ if (!wasCACertCalled) {
+ throw new SSLHandshakeException("Updated certificate on server side");
+ }
+ return true;
}
@Override
- public Answer<Boolean> getAnswerForDelete() {
- return new Answer<Boolean>() {
- @Override
- public Boolean answer(InvocationOnMock invocation) throws Throwable {
- if (!wasCACertCalled) {
- throw new SSLHandshakeException("Updated certificate on server side");
- }
- return true;
+ public String requestStringFromServer(@NonNull String url, @NonNull String requestMethod, String jsonString, @NonNull List<Pair<String, String>> headerArgs, @NonNull OkHttpClient okHttpClient) throws RuntimeException, IOException {
+ if (url.contains("/provider.json")) {
+ if (!wasCACertCalled) {
+ throw new SSLHandshakeException("Updated certificate on server side");
}
- };
- }
+ //download provider json
+ return getInputAsString(getClass().getClassLoader().getResourceAsStream("riseup.net.json"));
+ } else if (url.contains("/ca.crt")) {
+ //download provider ca cert
+ wasCACertCalled = true;
+ return getInputAsString(getClass().getClassLoader().getResourceAsStream("updated_cert.pem"));
+ } else if (url.contains("config/eip-service.json")) {
+ // download provider service json containing gateways, locations and openvpn settings
+ if (!wasCACertCalled) {
+ throw new SSLHandshakeException("Updated certificate on server side");
+ }
+ return getInputAsString(getClass().getClassLoader().getResourceAsStream("riseup.service.json"));
+ }
+ return null;
+ }
}
diff --git a/app/src/test/java/se/leap/bitmaskclient/testutils/MockHelper.java b/app/src/test/java/se/leap/bitmaskclient/testutils/MockHelper.java
index 1f8a18f4..3175b0ad 100644
--- a/app/src/test/java/se/leap/bitmaskclient/testutils/MockHelper.java
+++ b/app/src/test/java/se/leap/bitmaskclient/testutils/MockHelper.java
@@ -3,42 +3,39 @@ package se.leap.bitmaskclient.testutils;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertThat;
import static org.mockito.ArgumentMatchers.any;
-import static org.mockito.ArgumentMatchers.anyBoolean;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.anyString;
-import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.RETURNS_DEEP_STUBS;
import static org.mockito.Mockito.doAnswer;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
import static org.powermock.api.mockito.PowerMockito.mockStatic;
+import static se.leap.bitmaskclient.base.models.Constants.PROVIDER_CONFIGURED;
+import static se.leap.bitmaskclient.base.models.Constants.PROVIDER_EIP_DEFINITION;
import static se.leap.bitmaskclient.base.models.Constants.PROVIDER_MOTD;
import static se.leap.bitmaskclient.base.models.Constants.PROVIDER_MOTD_HASHES;
import static se.leap.bitmaskclient.base.models.Constants.PROVIDER_MOTD_LAST_SEEN;
import static se.leap.bitmaskclient.base.models.Constants.PROVIDER_MOTD_LAST_UPDATED;
import static se.leap.bitmaskclient.base.models.Constants.PROVIDER_PRIVATE_KEY;
import static se.leap.bitmaskclient.base.models.Constants.PROVIDER_VPN_CERTIFICATE;
-import static se.leap.bitmaskclient.base.utils.FileHelper.createFile;
import static se.leap.bitmaskclient.base.utils.PreferenceHelper.getEipDefinitionFromPreferences;
-import static se.leap.bitmaskclient.base.utils.PreferenceHelper.getFromPersistedProvider;
-import static se.leap.bitmaskclient.base.utils.PreferenceHelper.getLongFromPersistedProvider;
-import static se.leap.bitmaskclient.base.utils.PreferenceHelper.getStringSetFromPersistedProvider;
import android.content.Context;
import android.content.Intent;
+import android.content.SharedPreferences;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.content.res.Resources;
import android.os.Bundle;
import android.os.Parcelable;
import android.os.ResultReceiver;
-import android.text.TextUtils;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import org.json.JSONException;
import org.json.JSONObject;
+import org.mockito.Mockito;
import org.mockito.invocation.InvocationOnMock;
import org.mockito.stubbing.Answer;
@@ -48,9 +45,6 @@ import java.io.IOException;
import java.io.InputStream;
import java.math.BigInteger;
import java.net.UnknownHostException;
-import java.security.NoSuchAlgorithmException;
-import java.security.cert.CertificateEncodingException;
-import java.security.cert.X509Certificate;
import java.security.interfaces.RSAPrivateKey;
import java.util.ArrayList;
import java.util.Arrays;
@@ -69,10 +63,13 @@ import okhttp3.OkHttpClient;
import se.leap.bitmaskclient.R;
import se.leap.bitmaskclient.base.models.Provider;
import se.leap.bitmaskclient.base.models.ProviderObservable;
-import se.leap.bitmaskclient.base.utils.ConfigHelper;
+import se.leap.bitmaskclient.base.utils.CertificateHelper;
import se.leap.bitmaskclient.base.utils.FileHelper;
import se.leap.bitmaskclient.base.utils.InputStreamHelper;
+import se.leap.bitmaskclient.base.utils.BuildConfigHelper;
import se.leap.bitmaskclient.base.utils.PreferenceHelper;
+import se.leap.bitmaskclient.base.utils.RSAHelper;
+import se.leap.bitmaskclient.providersetup.ProviderApiConnector;
import se.leap.bitmaskclient.providersetup.connectivity.DnsResolver;
import se.leap.bitmaskclient.providersetup.connectivity.OkHttpClientGenerator;
import se.leap.bitmaskclient.testutils.BackendMockResponses.BackendMockProvider;
@@ -84,268 +81,6 @@ import se.leap.bitmaskclient.tor.TorStatusObservable;
*/
public class MockHelper {
- @NonNull
- public static Bundle mockBundle() {
- final Map<String, Boolean> fakeBooleanBundle = new HashMap<>();
- final Map<String, String> fakeStringBundle = new HashMap<>();
- final Map<String, Integer> fakeIntBundle = new HashMap<>();
- final Map<String, Parcelable> fakeParcelableBundle = new HashMap<>();
-
- Bundle bundle = mock(Bundle.class);
-
- //mock String values in Bundle
- doAnswer(new Answer() {
- @Override
- public Object answer(InvocationOnMock invocation) throws Throwable {
- Object[] arguments = invocation.getArguments();
- String key = ((String) arguments[0]);
- String value = ((String) arguments[1]);
- fakeStringBundle.put(key, value);
- return null;
- }
- }).when(bundle).putString(anyString(), anyString());
- when(bundle.getString(anyString())).thenAnswer(new Answer<String>() {
- @Override
- public String answer(InvocationOnMock invocation) throws Throwable {
- Object[] arguments = invocation.getArguments();
- String key = ((String) arguments[0]);
- return fakeStringBundle.get(key);
- }
- });
-
- //mock Boolean values in Bundle
- doAnswer(new Answer() {
- @Override
- public Object answer(InvocationOnMock invocation) throws Throwable {
- Object[] arguments = invocation.getArguments();
- String key = ((String) arguments[0]);
- Boolean value = ((boolean) arguments[1]);
- fakeBooleanBundle.put(key, value);
- return null;
- }
- }).when(bundle).putBoolean(anyString(), anyBoolean());
- when(bundle.getBoolean(anyString())).thenAnswer(new Answer<Boolean>() {
- @Override
- public Boolean answer(InvocationOnMock invocation) throws Throwable {
- Object[] arguments = invocation.getArguments();
- String key = ((String) arguments[0]);
- return fakeBooleanBundle.get(key);
- }
- });
-
- //mock Integer values in Bundle
- doAnswer(new Answer() {
- @Override
- public Object answer(InvocationOnMock invocation) throws Throwable {
- Object[] arguments = invocation.getArguments();
- String key = ((String) arguments[0]);
- Integer value = ((int) arguments[1]);
- fakeIntBundle.put(key, value);
- return null;
- }
- }).when(bundle).putInt(anyString(), anyInt());
- when(bundle.getInt(anyString())).thenAnswer(new Answer<Integer>() {
- @Override
- public Integer answer(InvocationOnMock invocation) throws Throwable {
- Object[] arguments = invocation.getArguments();
- String key = ((String) arguments[0]);
- return fakeIntBundle.get(key);
- }
- });
-
- //mock Parcelable values in Bundle
- doAnswer(new Answer() {
- @Override
- public Object answer(InvocationOnMock invocation) throws Throwable {
- Object[] arguments = invocation.getArguments();
- String key = ((String) arguments[0]);
- Parcelable value = ((Parcelable) arguments[1]);
- fakeParcelableBundle.put(key, value);
- return null;
- }
- }).when(bundle).putParcelable(anyString(), any(Parcelable.class));
- when(bundle.getParcelable(anyString())).thenAnswer(new Answer<Parcelable>() {
- @Override
- public Parcelable answer(InvocationOnMock invocation) throws Throwable {
- Object[] arguments = invocation.getArguments();
- String key = ((String) arguments[0]);
- return fakeParcelableBundle.get(key);
- }
- });
-
- //mock get
- when(bundle.get(anyString())).thenAnswer(new Answer<Object>() {
- @Override
- public Object answer(InvocationOnMock invocation) throws Throwable {
- Object[] arguments = invocation.getArguments();
- String key = ((String) arguments[0]);
- if (fakeBooleanBundle.containsKey(key)) {
- return fakeBooleanBundle.get(key);
- } else if (fakeIntBundle.containsKey(key)) {
- return fakeIntBundle.get(key);
- } else if (fakeStringBundle.containsKey(key)) {
- return fakeStringBundle.get(key);
- } else {
- return fakeParcelableBundle.get(key);
- }
- }
- });
-
- //mock getKeySet
- when(bundle.keySet()).thenAnswer(new Answer<Set<String>>() {
- @Override
- public Set<String> answer(InvocationOnMock invocation) throws Throwable {
- //this whole approach as a drawback:
- //you should not add the same keys for values of different types
- HashSet<String> keys = new HashSet<String>();
- keys.addAll(fakeBooleanBundle.keySet());
- keys.addAll(fakeIntBundle.keySet());
- keys.addAll(fakeStringBundle.keySet());
- keys.addAll(fakeParcelableBundle.keySet());
- return keys;
- }
- });
-
- //mock containsKey
- when(bundle.containsKey(anyString())).thenAnswer(new Answer<Boolean>() {
- @Override
- public Boolean answer(InvocationOnMock invocation) throws Throwable {
- String key = (String) invocation.getArguments()[0];
- return fakeBooleanBundle.containsKey(key) ||
- fakeStringBundle.containsKey(key) ||
- fakeIntBundle.containsKey(key) ||
- fakeParcelableBundle.containsKey(key);
- }
- });
-
- doAnswer(new Answer() {
- @Override
- public Object answer(InvocationOnMock invocation) throws Throwable {
- String key = (String) invocation.getArguments()[0];
- fakeBooleanBundle.remove(key);
- fakeIntBundle.remove(key);
- fakeParcelableBundle.remove(key);
- fakeStringBundle.remove(key);
- return null;
- }
- }).when(bundle).remove(anyString());
-
- return bundle;
- }
-
- public static Intent mockIntent() {
- Intent intent = mock(Intent.class);
- final String[] action = new String[1];
- final Map<String, Object> fakeExtras = new HashMap<>();
- final List<String> categories = new ArrayList<>();
-
-
- //mock Action in intent
- doAnswer(new Answer() {
- @Override
- public Object answer(InvocationOnMock invocation) throws Throwable {
- Object[] arguments = invocation.getArguments();
- action[0] = ((String) arguments[0]);
- return null;
- }
- }).when(intent).setAction(anyString());
- when(intent.getAction()).thenAnswer(new Answer<String>() {
- @Override
- public String answer(InvocationOnMock invocation) throws Throwable {
- return action[0];
- }
- });
-
- //mock Bundle in intent extras
- doAnswer(new Answer() {
- @Override
- public Object answer(InvocationOnMock invocation) throws Throwable {
- Object[] arguments = invocation.getArguments();
- String key = ((String) arguments[0]);
- Bundle value = ((Bundle) arguments[1]);
- fakeExtras.put(key, value);
- return null;
- }
- }).when(intent).putExtra(anyString(), any(Bundle.class));
- when(intent.getBundleExtra(anyString())).thenAnswer(new Answer<Bundle>() {
- @Override
- public Bundle answer(InvocationOnMock invocation) throws Throwable {
- Object[] arguments = invocation.getArguments();
- String key = ((String) arguments[0]);
- return (Bundle) fakeExtras.get(key);
- }
- });
-
- //mock Parcelable in intent extras
- doAnswer(new Answer() {
- @Override
- public Object answer(InvocationOnMock invocation) throws Throwable {
- Object[] arguments = invocation.getArguments();
- String key = ((String) arguments[0]);
- Parcelable value = ((Parcelable) arguments[1]);
- fakeExtras.put(key, value);
- return null;
- }
- }).when(intent).putExtra(anyString(), any(Parcelable.class));
- when(intent.getParcelableExtra(anyString())).thenAnswer(new Answer<Parcelable>() {
- @Override
- public Parcelable answer(InvocationOnMock invocation) throws Throwable {
- Object[] arguments = invocation.getArguments();
- String key = ((String) arguments[0]);
- return (Parcelable) fakeExtras.get(key);
- }
- });
- doAnswer(new Answer() {
- @Override
- public Object answer(InvocationOnMock invocation) throws Throwable {
- Object[] arguments = invocation.getArguments();
- categories.add(((String) arguments[0]));
- return null;
- }
- }).when(intent).addCategory(anyString());
-
- when(intent.getCategories()).thenAnswer(new Answer<Set<String>>() {
- @Override
- public Set<String> answer(InvocationOnMock invocation) throws Throwable {
- return new HashSet<>(categories);
- }
- });
-
- return intent;
- }
-
- public static void mockTextUtils() {
- mockStatic(TextUtils.class);
-
- when(TextUtils.equals(any(CharSequence.class), any(CharSequence.class))).thenAnswer(new Answer<Object>() {
- @Override
- public Object answer(InvocationOnMock invocation) throws Throwable {
- CharSequence a = (CharSequence) invocation.getArguments()[0];
- CharSequence b = (CharSequence) invocation.getArguments()[1];
- if (a == b) return true;
- int length;
- if (a != null && b != null && (length = a.length()) == b.length()) {
- if (a instanceof String && b instanceof String) {
- return a.equals(b);
- } else {
- for (int i = 0; i < length; i++) {
- if (a.charAt(i) != b.charAt(i)) return false;
- }
- return true;
- }
- }
- return false;
- }
- });
-
- when(TextUtils.isEmpty(any(CharSequence.class))).thenAnswer(new Answer<Boolean>() {
- @Override
- public Boolean answer(InvocationOnMock invocation) throws Throwable {
- CharSequence param = (CharSequence) invocation.getArguments()[0];
- return param == null || param.length() == 0;
- }
- });
- }
public static ResultReceiver mockResultReceiver(final int expectedResultCode) {
ResultReceiver resultReceiver = mock(ResultReceiver.class);
@@ -398,34 +133,45 @@ public class MockHelper {
return resultReceiver;
}
- public static void mockInputStreamHelper() throws FileNotFoundException {
- mockStatic(InputStreamHelper.class);
- when(InputStreamHelper.loadInputStreamAsString(any(InputStream.class))).thenCallRealMethod();
- when(InputStreamHelper.getInputStreamFrom(anyString())).thenAnswer(new Answer<InputStream>() {
+
+ public static InputStreamHelper mockInputStreamHelper() {
+ return new InputStreamHelper(new InputStreamHelper.InputStreamHelperInterface() {
@Override
- public InputStream answer(InvocationOnMock invocation) throws Throwable {
- String filename = (String) invocation.getArguments()[0];
- return getClass().getClassLoader().getResourceAsStream(filename);
+ public InputStream getInputStreamFrom(String filePath) {
+ return getClass().getClassLoader().getResourceAsStream(filePath);
}
});
- when(InputStreamHelper.inputStreamToJson(any(InputStream.class))).thenCallRealMethod();
-
}
- public static void mockFileHelper(final File mockedFile) throws FileNotFoundException {
- mockStatic(FileHelper.class);
- when(createFile(any(File.class), anyString())).thenReturn(mockedFile);
- }
+ public static class MockFileHelper implements FileHelper.FileHelperInterface {
+ private final File file;
+ private int persistFileCounter = 0;
+ public MockFileHelper(File file) {
+ this.file = file;
+ }
+
+
+ @Override
+ public File createFile(File dir, String fileName) {
+ return file;
+ }
+
+ @Override
+ public void persistFile(File file, String content) throws IOException {
+ persistFileCounter++;
+ }
- public static void mockBase64() {
- mockStatic(android.util.Base64.class);
- when(android.util.Base64.encodeToString(any(), anyInt())).thenAnswer(invocation -> Arrays.toString(Base64.getEncoder().encode((byte[]) invocation.getArguments()[0])));
+ public int getPersistFileCounter() {
+ return persistFileCounter;
+ }
}
- public static void mockRSAHelper() {
- mockStatic(ConfigHelper.RSAHelper.class);
+ public static FileHelper mockFileHelper(final File mockedFile) throws FileNotFoundException {
+ return new FileHelper(new MockFileHelper(mockedFile));
+ }
- when(ConfigHelper.RSAHelper.parseRsaKeyFromString(anyString())).thenReturn(new RSAPrivateKey() {
+ public static RSAHelper mockRSAHelper() {
+ return new RSAHelper(rsaKeyString -> new RSAPrivateKey() {
@Override
public BigInteger getPrivateExponent() {
return BigInteger.TEN;
@@ -451,103 +197,113 @@ public class MockHelper {
return BigInteger.ONE;
}
});
+
}
- public static void mockConfigHelper(String mockedFingerprint) throws CertificateEncodingException, NoSuchAlgorithmException {
- mockStatic(ConfigHelper.class);
- when(ConfigHelper.getFingerprintFromCertificate(any(X509Certificate.class), anyString())).thenReturn(mockedFingerprint);
- when(ConfigHelper.checkErroneousDownload(anyString())).thenCallRealMethod();
- when(ConfigHelper.parseX509CertificatesFromString(anyString())).thenCallRealMethod();
- when(ConfigHelper.getProviderFormattedString(any(Resources.class), anyInt())).thenCallRealMethod();
- when(ConfigHelper.timezoneDistance(anyInt(), anyInt())).thenCallRealMethod();
- when(ConfigHelper.isIPv4(anyString())).thenCallRealMethod();
- when(ConfigHelper.isDefaultBitmask()).thenReturn(true);
- when(ConfigHelper.getDomainFromMainURL(anyString())).thenCallRealMethod();
+ public static BuildConfigHelper mockBuildConfigHelper(boolean useObfsvpn) {
+ return mockBuildConfigHelper(useObfsvpn, true);
}
- public static void mockPreferenceHelper(final Provider providerFromPrefs) {
- // FIXME use MockSharedPreferences instead of provider
- mockStatic(PreferenceHelper.class);
- when(getFromPersistedProvider(anyString(), anyString())).thenAnswer(new Answer<String>() {
+ public static BuildConfigHelper mockBuildConfigHelper(boolean useObfsvpn, boolean isDefaultBitmask) {
+ return new BuildConfigHelper(new BuildConfigHelper.BuildConfigHelperInterface() {
@Override
- public String answer(InvocationOnMock invocation) throws Throwable {
- String key = (String) invocation.getArguments()[0];
- switch (key) {
- case PROVIDER_PRIVATE_KEY:
- return providerFromPrefs.getPrivateKey();
- case PROVIDER_VPN_CERTIFICATE:
- return providerFromPrefs.getVpnCertificate();
- case Provider.KEY:
- return providerFromPrefs.getDefinition().toString();
- case Provider.CA_CERT_FINGERPRINT:
- return providerFromPrefs.getCaCertFingerprint();
- case Provider.CA_CERT:
- return providerFromPrefs.getCaCert();
- case Provider.GEOIP_URL:
- return providerFromPrefs.getGeoipUrl().toString();
- case Provider.MOTD_URL:
- return providerFromPrefs.getMotdUrl().toString();
- case PROVIDER_MOTD:
- return providerFromPrefs.getMotdJsonString();
+ public boolean useObfsVpn() {
+ return useObfsvpn;
+ }
- }
+ @Override
+ public boolean hasObfuscationPinningDefaults() {
+ return false;
+ }
+
+ @Override
+ public String obfsvpnIP() {
return null;
}
- });
- when(getLongFromPersistedProvider(anyString(), anyString())).thenAnswer(new Answer<Long>() {
+
@Override
- public Long answer(InvocationOnMock invocation) throws Throwable {
- String key = (String) invocation.getArguments()[0];
- switch (key) {
- case PROVIDER_MOTD_LAST_SEEN:
- return providerFromPrefs.getLastMotdSeen();
- case PROVIDER_MOTD_LAST_UPDATED:
- return providerFromPrefs.getLastMotdUpdate();
- }
- return 0L;
+ public String obfsvpnPort() {
+ return null;
}
- });
- when(getStringSetFromPersistedProvider(anyString(), anyString())).thenAnswer(new Answer<Set<String>>() {
+
@Override
- public Set<String> answer(InvocationOnMock invocation) throws Throwable {
- String key = (String) invocation.getArguments()[0];
- switch (key) {
- case PROVIDER_MOTD_HASHES:
- return providerFromPrefs.getMotdLastSeenHashes();
- }
+ public String obfsvpnCert() {
return null;
}
- });
- when(PreferenceHelper.hasKey(anyString())).then(new Answer<Boolean>() {
+
@Override
- public Boolean answer(InvocationOnMock invocation) throws Throwable {
- String key = (String) invocation.getArguments()[0];
- if (key!= null && key.contains(providerFromPrefs.getDomain()) && !providerFromPrefs.getDomain().isEmpty()) {
- key = key.substring(0, key.indexOf(providerFromPrefs.getDomain()) - 1 /* -1 -> "." at the end */);
- }
- switch (key) {
- case PROVIDER_PRIVATE_KEY:
- return providerFromPrefs.getPrivateKey() != null;
- case PROVIDER_VPN_CERTIFICATE:
- return providerFromPrefs.getVpnCertificate() != null;
- case Provider.KEY:
- return providerFromPrefs.getDefinition().keys().hasNext();
- case Provider.CA_CERT_FINGERPRINT:
- return providerFromPrefs.getCaCertFingerprint().length() > 1;
- case Provider.CA_CERT:
- return providerFromPrefs.getCaCert() != null;
- case Provider.GEOIP_URL:
- return !providerFromPrefs.getGeoipUrl().isDefault();
- case Provider.MOTD_URL:
- return !providerFromPrefs.getMotdUrl().isDefault();
- case PROVIDER_MOTD:
- return providerFromPrefs.getMotdJson().keys().hasNext();
- }
+ public boolean useKcp() {
return false;
}
+
+ @Override
+ public boolean isDefaultBitmask() {
+ return isDefaultBitmask;
+ }
});
}
+ public static CertificateHelper mockCertificateHelper(String mockedFingerprint) {
+ return new CertificateHelper((certificate, encoding) -> mockedFingerprint);
+ }
+
+ public static PreferenceHelper mockPreferenceHelper(final Provider providerFromPrefs, SharedPreferences sharedPreferences) {
+ PreferenceHelper preferenceHelper = new PreferenceHelper(sharedPreferences);
+
+ sharedPreferences.edit().
+ putString(PROVIDER_PRIVATE_KEY, providerFromPrefs.getPrivateKey()).
+ putString(PROVIDER_VPN_CERTIFICATE, providerFromPrefs.getVpnCertificate()).
+ putString(Provider.KEY, providerFromPrefs.getDefinitionString()).
+ putString(Provider.CA_CERT_FINGERPRINT, providerFromPrefs.getCaCertFingerprint()).
+ putString(Provider.GEOIP_URL, providerFromPrefs.getGeoipUrl().toString()).
+ putString(Provider.MOTD_URL, providerFromPrefs.getMotdUrl().toString()).
+ putString(PROVIDER_MOTD, providerFromPrefs.getMotdJsonString()).
+ putLong(PROVIDER_MOTD_LAST_SEEN, providerFromPrefs.getLastMotdSeen()).
+ putLong(PROVIDER_MOTD_LAST_UPDATED, providerFromPrefs.getLastMotdUpdate()).
+ putStringSet(PROVIDER_MOTD_HASHES, providerFromPrefs.getMotdLastSeenHashes()).
+ commit();
+
+ return preferenceHelper;
+ }
+
+ public static PreferenceHelper mockPreferenceHelper(final Provider provider) {
+ SharedPreferences sharedPreferences = new MockSharedPreferences();
+ PreferenceHelper preferenceHelper = new PreferenceHelper(sharedPreferences);
+
+ sharedPreferences.edit().
+ putString(PROVIDER_PRIVATE_KEY, provider.getPrivateKey()).
+ putString(PROVIDER_VPN_CERTIFICATE, provider.getVpnCertificate()).
+ putString(Provider.KEY, provider.getDefinitionString()).
+ putString(Provider.CA_CERT_FINGERPRINT, provider.getCaCertFingerprint()).
+ putString(Provider.GEOIP_URL, provider.getGeoipUrl().toString()).
+ putString(Provider.MOTD_URL, provider.getMotdUrl().toString()).
+ putString(PROVIDER_MOTD, provider.getMotdJsonString()).
+ putLong(PROVIDER_MOTD_LAST_SEEN, provider.getLastMotdSeen()).
+ putLong(PROVIDER_MOTD_LAST_UPDATED, provider.getLastMotdUpdate()).
+ putStringSet(PROVIDER_MOTD_HASHES, provider.getMotdLastSeenHashes()).
+ commit();
+
+ if (!provider.getDomain().isBlank()) {
+ String providerDomain = provider.getDomain();
+ sharedPreferences.edit().
+ putString(Provider.PROVIDER_IP + "." + providerDomain, provider.getProviderIp()).
+ putString(Provider.PROVIDER_API_IP + "." + providerDomain, provider.getProviderApiIp()).
+ putString(Provider.MAIN_URL + "." + providerDomain, provider.getMainUrlString()).
+ putString(Provider.GEOIP_URL + "." + providerDomain, provider.getGeoipUrl().toString()).
+ putString(Provider.MOTD_URL + "." + providerDomain, provider.getMotdUrl().toString()).
+ putString(Provider.KEY + "." + providerDomain, provider.getDefinitionString()).
+ putString(Provider.CA_CERT + "." + providerDomain, provider.getCaCert()).
+ putString(PROVIDER_EIP_DEFINITION + "." + providerDomain, provider.getEipServiceJsonString()).
+ putString(PROVIDER_MOTD + "." + providerDomain, provider.getMotdJsonString()).
+ putStringSet(PROVIDER_MOTD_HASHES + "." + providerDomain, provider.getMotdLastSeenHashes()).
+ putLong(PROVIDER_MOTD_LAST_SEEN + "." + providerDomain, provider.getLastMotdSeen()).
+ putLong(PROVIDER_MOTD_LAST_UPDATED + "." + providerDomain, provider.getLastMotdUpdate()).
+ commit();
+ }
+
+ return preferenceHelper;
+ }
+
public static void mockPreferenceHelper(MockSharedPreferences preferences) {
mockStatic(PreferenceHelper.class);
@@ -560,54 +316,14 @@ public class MockHelper {
});
}
- public static void mockTorStatusObservable(@Nullable Throwable exception) throws TimeoutException, InterruptedException {
- TorStatusObservable observable = TorStatusObservable.getInstance();
- mockStatic(TorStatusObservable.class);
- when(TorStatusObservable.getInstance()).thenAnswer((Answer<TorStatusObservable>) invocation -> observable);
-
- when(TorStatusObservable.getBootstrapProgress()).thenReturn(0);
- when(TorStatusObservable.getLastLogs()).thenReturn(new Vector<>());
- when(TorStatusObservable.getLastTorLog()).thenReturn("");
- when(TorStatusObservable.getLastSnowflakeLog()).thenReturn("");
- AtomicBoolean waitUntilSuccess = new AtomicBoolean(false);
- when(TorStatusObservable.getProxyPort()).thenAnswer((Answer<Integer>) invocation -> {
- if (waitUntilSuccess.get()) {
- return 8118;
- }
- return -1;
- });
- when(TorStatusObservable.getStatus()).thenAnswer((Answer<TorStatusObservable.TorStatus>) invocation -> {
- if (waitUntilSuccess.get()) {
- return TorStatusObservable.TorStatus.ON;
- }
- return TorStatusObservable.TorStatus.OFF;
- });
- when(TorStatusObservable.getSnowflakeStatus()).thenAnswer((Answer<TorStatusObservable.SnowflakeStatus>) invocation -> {
- if (waitUntilSuccess.get()) {
- return TorStatusObservable.SnowflakeStatus.STARTED;
- }
- return TorStatusObservable.SnowflakeStatus.STOPPED;
- });
-
- if (exception != null) {
- when(TorStatusObservable.waitUntil(any(TorStatusObservable.StatusCondition.class), anyInt())).thenThrow(exception);
- } else {
- when(TorStatusObservable.waitUntil(any(TorStatusObservable.StatusCondition.class), anyInt())).thenAnswer((Answer<Boolean>) invocation -> {
- waitUntilSuccess.set(true);
- return true;
- });
- }
- }
-
- public static void mockProviderObservable(Provider provider) {
+ public static ProviderObservable mockProviderObservable(Provider provider) {
ProviderObservable observable = ProviderObservable.getInstance();
observable.updateProvider(provider);
- mockStatic(ProviderObservable.class);
- when(ProviderObservable.getInstance()).thenAnswer((Answer<ProviderObservable>) invocation -> observable);
+ return observable;
}
- public static void mockProviderApiConnector(final BackendMockProvider.TestBackendErrorCase errorCase) throws IOException {
- BackendMockProvider.provideBackendResponsesFor(errorCase);
+ public static ProviderApiConnector mockProviderApiConnector(final BackendMockProvider.TestBackendErrorCase errorCase) throws IOException {
+ return new ProviderApiConnector(BackendMockProvider.provideBackendResponsesFor(errorCase));
}
public static OkHttpClientGenerator mockClientGenerator(boolean resolveDNS) throws UnknownHostException {
@@ -633,15 +349,15 @@ public class MockHelper {
JSONObject errorMessages = new JSONObject(TestSetupHelper.getInputAsString(inputStream));
- when(mockedResources.getString(eq(R.string.warning_corrupted_provider_details), anyString())).
+ when(mockedResources.getString(Mockito.eq(R.string.warning_corrupted_provider_details), anyString())).
thenReturn(String.format(errorMessages.getString("warning_corrupted_provider_details"), "Bitmask"));
when(mockedResources.getString(R.string.server_unreachable_message)).
thenReturn(errorMessages.getString("server_unreachable_message"));
when(mockedResources.getString(R.string.error_security_pinnedcertificate)).
thenReturn(errorMessages.getString("error.security.pinnedcertificate"));
- when(mockedResources.getString(eq(R.string.malformed_url), anyString())).
+ when(mockedResources.getString(Mockito.eq(R.string.malformed_url), anyString())).
thenReturn(String.format(errorMessages.getString("malformed_url"), "Bitmask"));
- when(mockedResources.getString(eq(R.string.certificate_error), anyString())).
+ when(mockedResources.getString(Mockito.eq(R.string.certificate_error), anyString())).
thenReturn(String.format(errorMessages.getString("certificate_error"), "Bitmask"));
when(mockedResources.getString(R.string.error_srp_math_error_user_message)).
thenReturn(errorMessages.getString("error_srp_math_error_user_message"));
@@ -657,21 +373,21 @@ public class MockHelper {
thenReturn(errorMessages.getString("error_json_exception_user_message"));
when(mockedResources.getString(R.string.error_no_such_algorithm_exception_user_message)).
thenReturn(errorMessages.getString("error_no_such_algorithm_exception_user_message"));
- when(mockedResources.getString(eq(R.string.warning_corrupted_provider_details), anyString())).
+ when(mockedResources.getString(Mockito.eq(R.string.warning_corrupted_provider_details), anyString())).
thenReturn(String.format(errorMessages.getString("warning_corrupted_provider_details"), "Bitmask"));
- when(mockedResources.getString(eq(R.string.warning_corrupted_provider_cert), anyString())).
+ when(mockedResources.getString(Mockito.eq(R.string.warning_corrupted_provider_cert), anyString())).
thenReturn(String.format(errorMessages.getString("warning_corrupted_provider_cert"), "Bitmask"));
- when(mockedResources.getString(eq(R.string.warning_expired_provider_cert), anyString())).
+ when(mockedResources.getString(Mockito.eq(R.string.warning_expired_provider_cert), anyString())).
thenReturn(String.format(errorMessages.getString("warning_expired_provider_cert"), "Bitmask"));
- when(mockedResources.getString(eq(R.string.setup_error_text), anyString())).
+ when(mockedResources.getString(Mockito.eq(R.string.setup_error_text), anyString())).
thenReturn(String.format(errorMessages.getString("setup_error_text"), "Bitmask"));
- when(mockedResources.getString(eq(R.string.setup_error_text_custom), anyString())).
+ when(mockedResources.getString(Mockito.eq(R.string.setup_error_text_custom), anyString())).
thenReturn(String.format(errorMessages.getString("setup_error_text_custom"), "RiseupVPN"));
when(mockedResources.getString(R.string.app_name)).
thenReturn("Bitmask");
- when(mockedResources.getString(eq(R.string.error_tor_timeout), anyString())).
+ when(mockedResources.getString(Mockito.eq(R.string.error_tor_timeout), anyString())).
thenReturn(String.format(errorMessages.getString("error_tor_timeout"), "Bitmask"));
- when(mockedResources.getString(eq(R.string.error_network_connection), anyString())).
+ when(mockedResources.getString(Mockito.eq(R.string.error_network_connection), anyString())).
thenReturn(String.format(errorMessages.getString("error_network_connection"), "Bitmask"));
return mockedResources;
}
diff --git a/app/src/test/java/se/leap/bitmaskclient/testutils/MockSharedPreferences.java b/app/src/test/java/se/leap/bitmaskclient/testutils/MockSharedPreferences.java
index 4fabc2c0..30ced782 100644
--- a/app/src/test/java/se/leap/bitmaskclient/testutils/MockSharedPreferences.java
+++ b/app/src/test/java/se/leap/bitmaskclient/testutils/MockSharedPreferences.java
@@ -33,6 +33,8 @@ public class MockSharedPreferences implements SharedPreferences {
HashMap<String, String> mockedStringPrefs = new HashMap<>();
HashMap<String, Integer> mockedIntPrefs = new HashMap<>();
HashMap<String, Boolean> mockedBooleanPrefs = new HashMap<>();
+ HashMap<String, Long> mockedLongPrefs = new HashMap<>();
+ HashMap<String, Set<String>> mockedStringSetPrefs = new HashMap<>();
@Override
public Map<String, ?> getAll() {
@@ -49,7 +51,7 @@ public class MockSharedPreferences implements SharedPreferences {
@Nullable
@Override
public Set<String> getStringSet(String key, @Nullable Set<String> defValues) {
- return new HashSet<>();
+ return mockedStringSetPrefs.getOrDefault(key, new HashSet<>());
}
@Override
@@ -60,7 +62,7 @@ public class MockSharedPreferences implements SharedPreferences {
@Override
public long getLong(String key, long defValue) {
- return 0;
+ return mockedLongPrefs.getOrDefault(key, defValue);
}
@Override
@@ -78,7 +80,9 @@ public class MockSharedPreferences implements SharedPreferences {
public boolean contains(String key) {
return mockedStringPrefs.containsKey(key) ||
mockedBooleanPrefs.containsKey(key) ||
- mockedIntPrefs.containsKey(key);
+ mockedIntPrefs.containsKey(key) ||
+ mockedStringSetPrefs.containsKey(key) ||
+ mockedLongPrefs.containsKey(key);
}
@Override
@@ -87,6 +91,8 @@ public class MockSharedPreferences implements SharedPreferences {
private HashMap<String, String> tempStrings = new HashMap<>(mockedStringPrefs);
private HashMap<String, Integer> tempIntegers = new HashMap<>(mockedIntPrefs);
private HashMap<String, Boolean> tempBoolean = new HashMap<>(mockedBooleanPrefs);
+ private HashMap<String, Long> tempLongs = new HashMap<>(mockedLongPrefs);
+ private HashMap<String, Set<String>> tempStringSets = new HashMap<>(mockedStringSetPrefs);
@Override
public Editor putString(String key, @Nullable String value) {
@@ -96,7 +102,8 @@ public class MockSharedPreferences implements SharedPreferences {
@Override
public Editor putStringSet(String key, @Nullable Set<String> values) {
- return null;
+ tempStringSets.put(key, values);
+ return this;
}
@Override
@@ -107,7 +114,8 @@ public class MockSharedPreferences implements SharedPreferences {
@Override
public Editor putLong(String key, long value) {
- return null;
+ tempLongs.put(key, value);
+ return this;
}
@Override
diff --git a/app/src/test/java/se/leap/bitmaskclient/tethering/TetheringStateManagerTest.java b/app/src/test/java/se/leap/bitmaskclient/tethering/TetheringStateManagerTest.java
index a2569282..a5954a97 100644
--- a/app/src/test/java/se/leap/bitmaskclient/tethering/TetheringStateManagerTest.java
+++ b/app/src/test/java/se/leap/bitmaskclient/tethering/TetheringStateManagerTest.java
@@ -16,279 +16,25 @@
*/
package se.leap.bitmaskclient.tethering;
-import static junit.framework.TestCase.assertTrue;
import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertFalse;
-import static org.mockito.ArgumentMatchers.any;
-import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.Mockito.mock;
-import static org.powermock.api.mockito.PowerMockito.mockStatic;
-import static org.powermock.api.mockito.PowerMockito.when;
-
-import android.content.Context;
-import android.content.IntentFilter;
-import android.content.SharedPreferences;
+import static org.mockito.Mockito.when;
import org.junit.Before;
import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.mockito.Answers;
-import org.mockito.Mock;
-import org.mockito.invocation.InvocationOnMock;
-import org.mockito.stubbing.Answer;
import org.powermock.api.mockito.PowerMockito;
-import org.powermock.core.classloader.annotations.PrepareForTest;
-import org.powermock.modules.junit4.PowerMockRunner;
-
-import java.net.NetworkInterface;
-import java.net.SocketException;
-import java.util.Arrays;
-import java.util.Collections;
-import java.util.Enumeration;
-
-import se.leap.bitmaskclient.base.utils.Cmd;
-import se.leap.bitmaskclient.base.utils.PreferenceHelper;
-import se.leap.bitmaskclient.testutils.MockSharedPreferences;
-
-@RunWith(PowerMockRunner.class)
-@PrepareForTest({WifiManagerWrapper.class, TetheringStateManager.class, Cmd.class, NetworkInterface.class, PreferenceHelper.class})
public class TetheringStateManagerTest {
- @Mock(answer = Answers.RETURNS_DEEP_STUBS)
- Context mockContext;
-
- @Mock(answer = Answers.RETURNS_DEEP_STUBS)
- IntentFilter intentFilter;
-
private TetheringObservable observable;
@Before
public void setup() throws Exception {
- PowerMockito.whenNew(IntentFilter.class).withArguments(anyString()).thenReturn(intentFilter);
- PowerMockito.whenNew(IntentFilter.class).withNoArguments().thenReturn(intentFilter);
- mockStatic(PreferenceHelper.class);
-
observable = TetheringObservable.getInstance();
-
- }
-
- @Test
- public void updateUsbTetheringState_findsRndisX_returnsTrue() throws Exception {
- WifiManagerWrapper mockWrapper = mock(WifiManagerWrapper.class);
- when(mockWrapper.isWifiAPEnabled()).thenReturn(false);
- PowerMockito.whenNew(WifiManagerWrapper.class).withAnyArguments().thenReturn(mockWrapper);
-
- PowerMockito.mockStatic(NetworkInterface.class);
- NetworkInterface mock1 = PowerMockito.mock(NetworkInterface.class);
- when(mock1.isLoopback()).thenReturn(false);
- when(mock1.getName()).thenReturn("eth0");
- NetworkInterface mock2 = PowerMockito.mock(NetworkInterface.class);
- when(mock2.isLoopback()).thenReturn(false);
- when(mock2.getName()).thenReturn("rndis0");
-
- NetworkInterface[] networkInterfaces = new NetworkInterface[2];
- networkInterfaces[0] = mock1;
- networkInterfaces[1] = mock2;
-
- PowerMockito.when(NetworkInterface.getNetworkInterfaces()).then(new Answer<Enumeration<NetworkInterface>>() {
- @Override
- public Enumeration<NetworkInterface> answer(InvocationOnMock invocation) throws Throwable {
- return Collections.enumeration(Arrays.asList(networkInterfaces));
- }
- });
-
- TetheringObservable.setUsbTethering(false, "192.168.42.0/24", "rndis0");
- TetheringStateManager.getInstance().init(mockContext);
- TetheringStateManager manager = TetheringStateManager.getInstance();
- assertTrue(observable.isUsbTetheringEnabled());
- }
-
- @Test
- public void updateUsbTetheringState_doesntFindRndisX_returnsFalse() throws Exception {
- WifiManagerWrapper mockWrapper = mock(WifiManagerWrapper.class);
- when(mockWrapper.isWifiAPEnabled()).thenReturn(false);
- PowerMockito.whenNew(WifiManagerWrapper.class).withAnyArguments().thenReturn(mockWrapper);
-
- PowerMockito.mockStatic(NetworkInterface.class);
- NetworkInterface mock1 = PowerMockito.mock(NetworkInterface.class);
- when(mock1.isLoopback()).thenReturn(false);
- when(mock1.getName()).thenReturn("eth0");
- NetworkInterface mock2 = PowerMockito.mock(NetworkInterface.class);
- when(mock2.isLoopback()).thenReturn(false);
- when(mock2.getName()).thenReturn("wifi0");
-
- NetworkInterface[] networkInterfaces = new NetworkInterface[2];
- networkInterfaces[0] = mock1;
- networkInterfaces[1] = mock2;
-
- PowerMockito.when(NetworkInterface.getNetworkInterfaces()).then(new Answer<Enumeration<NetworkInterface>>() {
- @Override
- public Enumeration<NetworkInterface> answer(InvocationOnMock invocation) throws Throwable {
- return Collections.enumeration(Arrays.asList(networkInterfaces));
- }
- });
-
- TetheringObservable.setUsbTethering(true, "192.168.42.0/24", "rndis0");
- TetheringStateManager.getInstance().init(mockContext);
- TetheringStateManager manager = TetheringStateManager.getInstance();
- assertFalse(observable.isUsbTetheringEnabled());
- }
-
- @Test
- public void updateUsbTetheringState_ThrowsException_returnsFalse() throws Exception {
- WifiManagerWrapper mockWrapper = mock(WifiManagerWrapper.class);
- when(mockWrapper.isWifiAPEnabled()).thenReturn(false);
- PowerMockito.whenNew(WifiManagerWrapper.class).withAnyArguments().thenReturn(mockWrapper);
-
- PowerMockito.mockStatic(NetworkInterface.class);
- PowerMockito.when(NetworkInterface.getNetworkInterfaces()).thenThrow(new SocketException());
-
- TetheringObservable.setUsbTethering(true, "192.168.42.0/24", "rndis0");
- TetheringStateManager.getInstance().init(mockContext);
- TetheringStateManager manager = TetheringStateManager.getInstance();
- assertFalse(observable.isUsbTetheringEnabled());
- }
-
-/* //TODO enable these tests as soon as bluetooth tethering has been enabled again
- @Test
- public void updateBluetoothTetheringState_btDeviceFound_returnTrue() throws Exception {
- WifiManagerWrapper mockWrapper = mock(WifiManagerWrapper.class);
- when(mockWrapper.isWifiAPEnabled()).thenReturn(true);
- PowerMockito.whenNew(WifiManagerWrapper.class).withAnyArguments().thenReturn(mockWrapper);
-
- mockStatic(Cmd.class);
- PowerMockito.when(Cmd.runBlockingCmd(any(), any(StringBuilder.class))).then(new Answer<Integer>() {
- @Override
- public Integer answer(InvocationOnMock invocation) throws Throwable {
- StringBuilder logStringBuilder = invocation.getArgument(1);
- logStringBuilder.append("bt-pan device found");
- return 0;
- }
- });
-
- TetheringObservable.setBluetoothTethering(false);
- TetheringStateManager.getInstance().init(mockContext);
- TetheringStateManager manager = TetheringStateManager.getInstance();
- assertTrue(observable.isBluetoothTetheringEnabled());
- }
-
-
- @Test
- public void updateBluetoothTetheringState_btPanDeviceNotFound_returnFalse() throws Exception {
- WifiManagerWrapper mockWrapper = mock(WifiManagerWrapper.class);
- when(mockWrapper.isWifiAPEnabled()).thenReturn(true);
- PowerMockito.whenNew(WifiManagerWrapper.class).withAnyArguments().thenReturn(mockWrapper);
-
- mockStatic(Cmd.class);
- PowerMockito.when(Cmd.runBlockingCmd(any(), any(StringBuilder.class))).then(new Answer<Integer>() {
- @Override
- public Integer answer(InvocationOnMock invocation) throws Throwable {
- StringBuilder logStringBuilder = invocation.getArgument(1);
- logStringBuilder.append("bt-pan device not found");
- return 1;
- }
- });
-
- TetheringObservable.setBluetoothTethering(true);
- TetheringStateManager.getInstance().init(mockContext);
- TetheringStateManager manager = TetheringStateManager.getInstance();
- assertFalse(observable.isBluetoothTetheringEnabled());
- }
-
- @Test
- public void updateBluetoothTetheringState_ThrowsException_returnsFalse() throws Exception {
- WifiManagerWrapper mockWrapper = mock(WifiManagerWrapper.class);
- when(mockWrapper.isWifiAPEnabled()).thenReturn(true);
- PowerMockito.whenNew(WifiManagerWrapper.class).withAnyArguments().thenReturn(mockWrapper);
-
- mockStatic(Cmd.class);
- PowerMockito.when(Cmd.runBlockingCmd(any(), any(StringBuilder.class))).
- thenThrow(new SecurityException("Creation of subprocess is not allowed"));
-
- TetheringObservable.setBluetoothTethering(true);
- TetheringStateManager.getInstance().init(mockContext);
- TetheringStateManager manager = TetheringStateManager.getInstance();
- assertFalse(observable.isBluetoothTetheringEnabled());
- }
-
- @Test
- public void updateBluetoothTetheringState_WifiManagerWrapperThrowsException_hasNoInfluenceOnResult() throws Exception {
- WifiManagerWrapper mockWrapper = mock(WifiManagerWrapper.class);
- when(mockWrapper.isWifiAPEnabled()).thenThrow(new NoSuchMethodException());
- PowerMockito.whenNew(WifiManagerWrapper.class).withAnyArguments().thenReturn(mockWrapper);
-
- mockStatic(Cmd.class);
- PowerMockito.when(Cmd.runBlockingCmd(any(), any(StringBuilder.class))).then(new Answer<Integer>() {
- @Override
- public Integer answer(InvocationOnMock invocation) throws Throwable {
- StringBuilder logStringBuilder = invocation.getArgument(1);
- logStringBuilder.append("bt-pan device found");
- return 0;
- }
- });
-
- TetheringObservable.setBluetoothTethering(false);
- TetheringStateManager.getInstance().init(mockContext);
- TetheringStateManager manager = TetheringStateManager.getInstance();
- assertTrue(observable.isBluetoothTetheringEnabled());
- }
- */
-
- @Test
- public void updateWifiTetheringState_ignoreFailingWifiAPReflection_keepsOldValueTrue() throws Exception {
- WifiManagerWrapper mockWrapper = mock(WifiManagerWrapper.class);
- when(mockWrapper.isWifiAPEnabled()).thenThrow(new NoSuchMethodException());
- PowerMockito.whenNew(WifiManagerWrapper.class).withAnyArguments().thenReturn(mockWrapper);
-
- TetheringObservable.setWifiTethering(true, "192.168.43.0/24", "wlan0");
- TetheringStateManager.getInstance().init(mockContext);
- TetheringStateManager manager = TetheringStateManager.getInstance();
- assertTrue(observable.isWifiTetheringEnabled());
- }
-
- @Test
- public void updateWifiTetheringState_ignoreFailingWifiAPReflection_keepsOldValueFalse() throws Exception {
- WifiManagerWrapper mockWrapper = mock(WifiManagerWrapper.class);
- when(mockWrapper.isWifiAPEnabled()).thenThrow(new NoSuchMethodException());
- PowerMockito.whenNew(WifiManagerWrapper.class).withAnyArguments().thenReturn(mockWrapper);
-
- TetheringObservable.setWifiTethering(false, "", "");
- TetheringStateManager.getInstance().init(mockContext);
- TetheringStateManager manager = TetheringStateManager.getInstance();
- assertFalse(observable.isWifiTetheringEnabled());
- }
-
- @Test
- public void updateWifiTetheringState_WifiApReflectionWithoutException_changeValueToTrue() throws Exception {
- WifiManagerWrapper mockWrapper = mock(WifiManagerWrapper.class);
- when(mockWrapper.isWifiAPEnabled()).thenReturn(true);
- PowerMockito.whenNew(WifiManagerWrapper.class).withAnyArguments().thenReturn(mockWrapper);
-
- TetheringObservable.setWifiTethering(false, "", "");
- TetheringStateManager.getInstance().init(mockContext);
- TetheringStateManager manager = TetheringStateManager.getInstance();
- assertTrue(observable.isWifiTetheringEnabled());
- }
-
- @Test
- public void updateWifiTetheringState_WifiApReflectionWithoutException_changeValueToFalse() throws Exception {
- WifiManagerWrapper mockWrapper = mock(WifiManagerWrapper.class);
- when(mockWrapper.isWifiAPEnabled()).thenReturn(false);
- PowerMockito.whenNew(WifiManagerWrapper.class).withAnyArguments().thenReturn(mockWrapper);
-
- TetheringObservable.setWifiTethering(true, "", "");
- TetheringStateManager.getInstance().init(mockContext);
- TetheringStateManager manager = TetheringStateManager.getInstance();
- assertFalse(observable.isWifiTetheringEnabled());
}
@Test
public void testGetWifiAddressRangee_keepsLastSeenAddressAndInterface() throws Exception {
- WifiManagerWrapper mockWrapper = mock(WifiManagerWrapper.class);
- when(mockWrapper.isWifiAPEnabled()).thenReturn(true);
- PowerMockito.whenNew(WifiManagerWrapper.class).withAnyArguments().thenReturn(mockWrapper);
-
//WifiTethering was switched on
TetheringObservable.setWifiTethering(true, "192.168.40.0/24", "wlan0");
diff --git a/app/src/test/java/se/leap/bitmaskclient/tor/TorStatusObservableTest.java b/app/src/test/java/se/leap/bitmaskclient/tor/TorStatusObservableTest.java
new file mode 100644
index 00000000..10dbf6cb
--- /dev/null
+++ b/app/src/test/java/se/leap/bitmaskclient/tor/TorStatusObservableTest.java
@@ -0,0 +1,48 @@
+package se.leap.bitmaskclient.tor;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNull;
+
+import android.content.Context;
+import android.content.pm.PackageManager;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Answers;
+import org.mockito.Mock;
+import org.mockito.junit.MockitoJUnitRunner;
+
+import java.beans.PropertyChangeEvent;
+import java.beans.PropertyChangeListener;
+
+@RunWith(MockitoJUnitRunner.class)
+public class TorStatusObservableTest {
+
+
+ @Mock(answer = Answers.RETURNS_DEEP_STUBS)
+ private Context mockContext;
+
+
+
+ @Test
+ public void testPropertyChange() throws PackageManager.NameNotFoundException {
+ TorStatusObservable statusObservable = TorStatusObservable.getInstance();
+ int i = 10;
+ PropertyChangeListener propertyChangeListener = new PropertyChangeListener() {
+ @Override
+ public void propertyChange(PropertyChangeEvent evt) {
+ assertEquals(12, TorStatusObservable.getBootstrapProgress());
+ assertEquals("a logkey", TorStatusObservable.getLastLogs().lastElement());
+ assertNull(evt.getOldValue());
+ TorStatusObservable.getInstance().deleteObserver(this);
+ }
+ };
+
+ TorStatusObservable.updateState(mockContext, "STARTING", 10, "a logkey");
+ TorStatusObservable.updateState(mockContext, "STARTING", 11, "a log 2");
+ TorStatusObservable.getInstance().addObserver(propertyChangeListener);
+ TorStatusObservable.updateState(mockContext, "STARTING", 12, "a log 3");
+
+ }
+
+} \ No newline at end of file
diff --git a/app/src/test/resources/v4/riseup.net.cert b/app/src/test/resources/v4/riseup.net.cert
index 711a7067..49b4f576 100644
--- a/app/src/test/resources/v4/riseup.net.cert
+++ b/app/src/test/resources/v4/riseup.net.cert
@@ -1,54 +1,43 @@
-----BEGIN RSA PRIVATE KEY-----
-MIIEpAIBAAKCAQEAyRUoZOO7jQb5aIyJA5I8om6WO2vQoNDywCsuVF42TiddPIQt
-/JF4excbozFu+IZJLd20n3+zzUR0SHw30mLYAjnVmRaf8XD91xirlc4LWhhXqHPb
-+WuvgBeALnhDdCZr1rKbnfiwYYeGRkozafSL61AW3LtuaA/uW/MWfrlLYry0TG/q
-KFYt9VNg72vKE/+PQ44bsLpUBB9OsYBSG15dC4ohp7tN59P7GZ0F5tKOGdnMJyL1
-0M9bEEISS5rlgpmVZ5+V10q83qu4fSNyGqsPVdiI0JhsKYSlyqMxTLLWPs95LaaR
-U0uGVt0cq3MUO+vN9gzczS1MJS1DulxMjMnMMQIDAQABAoIBAQCLbGkqsyC64ygR
-zse9uyrhsW3nW5U3vElk50vjYcOjovWp3TiJlFAGgPo/yCnaljmtXLk9km0YGavL
-Cp4l+TUvLeyljiNuZFsNRmTKpSgH2zMEcPkIUxtH5IOTNP4ITg+duQ/fk6ywoyh+
-GjrV76MIkOqZODiQXON3y/BAA7h6h4QFQ7z7EAZAKCIdYEtP52JM7EtUd8enre4P
-XaL2wan/YX65xWPftOqcPeWLp4tSz5zIPphJzqbZZt9fOeKd4KrpwxK70vV23UgM
-Kkr1SK/CQZq+remzJzjLBSrcrzL251Oliy/72HnoURUWVSe0PZjqZiZx7ui6VZwA
-d0Sez79BAoGBAPDmMjMVtW0ixn4HPRkkBTwZBURVLIf2BNVyAj6d7DbhULEfv9Oj
-KKVn48kxo2shoXXT6UoArVIKov/jz2TNQjt5V1zqRqXq3jhPm9fcRV4pserbEHJp
-SNBlKYGpJRncxTr7hkLB5Bp4CaPeXXm7KdPObDDGLI+Rfb9qCt7uCgnJAoGBANWw
-AoPaPBsUH8tVMRfGAjX7YgeG5Kacb10FiO+eQL48DVxvMYjl+sYBoPrOuJk2gDEC
-J45NMgDGIaI4sLcrpCgKyeJjMgT4fFqK2BLDBBrx8n/2u6mWw8CEQJnGgTEPv0oV
-ZqhF2pBa8/WC8w6+/cQ6r50GPvfY8yWziXLy+eMpAoGAady/MrPXhp5BnCCSOPob
-Us2sAttrNlRmy2XOlrXPmE5rp2rMYbTRp95/u2qU5f9hdOYrHtotUGBcQRdbjHCn
-KnuoaKyLX15XSWeylKm30imAhjS+hYi+9tV95/zs0PCzu7fMyIlsNDWMBvcxHM2j
-E/Eimkx8SJsnJ3byUAVLZAECgYEAhAOBCkRA7dm46r1u3ukNZJwxK8VCbUwn4KgS
-uTZjeSNQfdKUH6c1Di7jbQ9ZLA5nk99o4JkAU0oUbUvooMDtYW+I2bu+oyOAb89n
-PfANETh4QGYF+feSZ9VMs7PXDKBV5UbjbQH6zUPjg8Gqt2l3DUvUQoYhUK1PSfNo
-7wL9LkECgYB1QgADq+e28riLsclkRkfnUqrOIc80jVmZLszflnQVyQEanWc1QgPo
-FGvH+PGGiFme+3qMIK01JsiDng7rUTnbHOgfLMifG0ph65pFcp2fnAEr3DzNuk+m
-HsdPcNGqU0Jt9r/7jAqKluXd6pNa4Ve0KaAW0a7J+9s5kWIlQNwM3w==
+MIIEowIBAAKCAQEAudf0Quu9UehPF+oi8ZwBf7OBE1oj/SoY5tDkkWHcShxVfw26
+Cwnw+dAViCXS0zgTtx1qIN9bQgMEheanc2iuP1emF0G18Yi9L54soh6O+zR5M6od
+tpWLOxYMqYCJPoAK+GBxW95bobLUjk1EJigyrrtORprgO2wi8TznZ+shdO6AlvUr
+iUrvbmdMMIxPk3wvSX1f+2IbVlRf+2ovcRHMZqJ+plQiZEuRWkMqGiwiKwNFmIfZ
+lIwkPIzly06RGfRML2cMS8ewM0ryAsgjH6O9KyujtW+T8B03Es1xHowxw9yIeiAr
+sgWbDwawWtfzGUlLkupoice7huBMYe1vBCdglQIDAQABAoIBAHTe6A9FrPNbgpHp
+fjwu/YpPWnbPEx7cYHiXGYaL4jsBAos6GKtkfxS61S+fiaum8k8PwnQVwpAK0cdb
+PCcJx7qx5hNuEXtpoH/Xmv4A9a3oW+gvrSvrc3me7iuSV7zkTQHRtLgvZ7SSf7VV
+xeuxD95ukFU6hJUZ9gd7Y5MofQvI9iFn5V+w7wPlmqkZM/whxrPQwTHGvPsXWaEu
+5nUuGW3y1WvvhwNBjrnPP1A/UZ06hhMvAUGlvFRxBm4ADoSDBfjZdP5ZjOPMP1Y0
+D5FGHboueYzFDBQEXpxw1nvjuXzlt6SjA91gRIMJQAwsK5MxntQJXrOX7JEl6BgI
+aGgVfEECgYEAyo1KFgVoleyyZ9aBzlXs7g+WKRrD8jxbloQiaamLpxTOgvBDU4Wq
+KI+zcEJ5GOrAOe6qEfCXn7REefZZr2z7hOs/oj/zsAGHgRDpFkZ3USA5LsruL917
+4EAZH+VJUvN8H8GgU2N4sj0sDk+yaLZo9dhYilo78cDUX4BoGtdaEykCgYEA6uH9
+O3UcgnKVghTrpuLca8ov1S4QH8XamD4rMIeHpSn/l32JCBjtjL9LQYqve+lcxyC8
+Je07ZzznhEYdQ/ASMVjBOVMVNq+AaYm1X2DSYvje1IDFFz4Ya/luHy3xThhSqnkm
+jtjxAICScuboUmAC+E9rpnmlJ6W06DwxYlWJm40CgYBSCcfoA2jI0IWx6P/KQqMk
+CMwY+e5DPo8Z94q4oSMfGR5LimS6f3jb1Ngor8O8g9g3nqLjgT7oQGs7uru4gbud
+qmqrnJtmvjfT3rWJgCDzismeWjL+0AZMXanPcV6xakzrz9DP9Yn9Jymg4kawgrEg
+Ye/6mXGOCTv7Mlb4CCFDgQKBgQDYdDh00aDbShMjlHnyCoCMyP+5mkB7t06SHECa
+8Vr8xy5mgeaFUsufeC43EUJUk6LPUwhwfyXOJt9IE4EmuZdaaGtwk3MqOSPCnohJ
+hCV91dErzhtTJwNEhdGI5ELK8DlGJm11GNFH4DSVtNuGBjrWcAJJoTKkzd1gYxAz
+iZZNhQKBgB78oOOWX6yS+UDnJzyuojZbl9YeXXRjPXqUWqjdp+Qagn6KFYIBRdFL
+S8vHtJpshsP0qAAEo7P+KueMQKFTRsU6CWZN68omB3K+LNGod+PT4yfM4PqC4MlN
+kis7OehmiRA7HUPmV9YRL3JsH0W9q0PxCtm8c6gLfcp3OZ93yNSJ
-----END RSA PRIVATE KEY-----
-----BEGIN CERTIFICATE-----
-MIIEmzCCAoOgAwIBAgIQHybvsqrpyjLQlh3K46x6ozANBgkqhkiG9w0BAQsFADB1
-MRgwFgYDVQQKDA9SaXNldXAgTmV0d29ya3MxGzAZBgNVBAsMEmh0dHBzOi8vcmlz
-ZXVwLm5ldDE8MDoGA1UEAwwzUmlzZXVwIE5ldHdvcmtzIFJvb3QgQ0EgKGNsaWVu
-dCBjZXJ0aWZpY2F0ZXMgb25seSEpMB4XDTIzMDkyMzAwMDAwMFoXDTIzMTIyMzAw
-MDAwMFowLTErMCkGA1UEAwwiVU5MSU1JVEVEZHZiYW45cXBsZXUxcGl0b3lhZnZi
-OGFkNDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMkVKGTju40G+WiM
-iQOSPKJuljtr0KDQ8sArLlReNk4nXTyELfyReHsXG6MxbviGSS3dtJ9/s81EdEh8
-N9Ji2AI51ZkWn/Fw/dcYq5XOC1oYV6hz2/lrr4AXgC54Q3Qma9aym534sGGHhkZK
-M2n0i+tQFty7bmgP7lvzFn65S2K8tExv6ihWLfVTYO9ryhP/j0OOG7C6VAQfTrGA
-UhteXQuKIae7TefT+xmdBebSjhnZzCci9dDPWxBCEkua5YKZlWeflddKvN6ruH0j
-chqrD1XYiNCYbCmEpcqjMUyy1j7PeS2mkVNLhlbdHKtzFDvrzfYM3M0tTCUtQ7pc
-TIzJzDECAwEAAaNvMG0wHQYDVR0OBBYEFEzWvshjpfxlaIp1lqAzun0SJsUbMAsG
-A1UdDwQEAwIHgDATBgNVHSUEDDAKBggrBgEFBQcDAjAJBgNVHRMEAjAAMB8GA1Ud
-IwQYMBaAFBf0G9XlKgEBTWuiXTYKKQmWZYBGMA0GCSqGSIb3DQEBCwUAA4ICAQAR
-ZzHo/Sn14yISzWnlvmQA7kqICm5j0mENib2BhaM7b6kmZRzvt9s9BwD83DYQwfCV
-VBeGx1YkXCHsUEVcqJCXF/of9CsUUvUhMMp+fd068OdrJuPVxglOCmY4zMIfSlQW
-YLvBalER1ilm8IuVrSVwBHP1vpnKj/g6W8gufZn06Tq7/c6X+QOrjebijJ4WuRtm
-V3mqEoMcBOEaHk9T7Lxe0yixrssUm13yJmCz3R5x6jRDtaVnQ95VwgBqnrJpXPgb
-sE2GrR5E74e+PbNQPfJJSobtYpJifp97wOpHFy2z5EcHyRuLdD3PX3it9mz5b0FJ
-GwMb+YmgIWI8oAngWj8KiELDTWpKH6DdrQBljARHwjjBAG+rSYyWwkKKO2Nk8nsz
-cnBlYY2rqLJ3gXc9oNDFWlh96K9rGy7bGcY0ALSxrLWFrpODQIKerjSNcsOhXp4D
-6OS603EPgFKSo1bca9wKkTIjJIsIXjTfJEKXR22huhJhkJsTIg5z02N2dBJfmNkz
-nffWtSk7tu8+CNEGruWfQ2TzYyknS5D0E2Eba07W/39gs6uXncrXwIidGg/G8D/h
-mpw7L/+f41za+mlykz2ivoUJsDb7TsQeW4O/Oj5wnekyAnJKHUJy9O8y4vpqJkUn
-+xLUpVnNpH6lAzAV3xODOVg2pTbwnkCnBkCDUx3Eww==
+MIICeTCCAh6gAwIBAgIRAIbLa6Ts1lih8SKdunuWB+gwCgYIKoZIzj0EAwIwMzEx
+MC8GA1UEAwwoTEVBUCBSb290IENBIChjbGllbnQgY2VydGlmaWNhdGVzIG9ubHkh
+KTAeFw0yNDAxMTgxOTAzNTZaFw0yNDAyMjIxOTAzNTZaMBQxEjAQBgNVBAMTCVVO
+TElNSVRFRDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALnX9ELrvVHo
+TxfqIvGcAX+zgRNaI/0qGObQ5JFh3EocVX8NugsJ8PnQFYgl0tM4E7cdaiDfW0ID
+BIXmp3Norj9XphdBtfGIvS+eLKIejvs0eTOqHbaVizsWDKmAiT6ACvhgcVveW6Gy
+1I5NRCYoMq67Tkaa4DtsIvE852frIXTugJb1K4lK725nTDCMT5N8L0l9X/tiG1ZU
+X/tqL3ERzGaifqZUImRLkVpDKhosIisDRZiH2ZSMJDyM5ctOkRn0TC9nDEvHsDNK
+8gLIIx+jvSsro7Vvk/AdNxLNcR6MMcPciHogK7IFmw8GsFrX8xlJS5LqaInHu4bg
+TGHtbwQnYJUCAwEAAaNnMGUwDgYDVR0PAQH/BAQDAgeAMBMGA1UdJQQMMAoGCCsG
+AQUFBwMCMB0GA1UdDgQWBBSRZk4gUAUtg/gnCBt2OfkYak38mTAfBgNVHSMEGDAW
+gBR9SmLY/ytJxHm2orHcjj5jB1yo/jAKBggqhkjOPQQDAgNJADBGAiEA+7MB5Thd
+Xpb9vnNIpX10TahuOb9N4IQcpO6ai8pOqmwCIQD5zpNjB16pyKg/ctOpVjzKStQD
+kKiTsZU2DSNaeSapoA==
-----END CERTIFICATE----- \ No newline at end of file
diff --git a/build.gradle b/build.gradle
index aafc76c2..0757f4fa 100644
--- a/build.gradle
+++ b/build.gradle
@@ -25,3 +25,9 @@ allprojects {
mavenCentral()
}
}
+
+subprojects{
+ tasks.withType(Test).configureEach{
+ jvmArgs = jvmArgs + ['--add-opens=java.base/java.lang=ALL-UNNAMED', '--add-exports=java.base/java.lang=ALL-UNNAMED', '--add-reads=java.base/java.lang=ALL-UNNAMED']
+ }
+}
diff --git a/docker/android-fastlane/Dockerfile b/docker/android-fastlane/Dockerfile
index 5c7470aa..20ec98e5 100644
--- a/docker/android-fastlane/Dockerfile
+++ b/docker/android-fastlane/Dockerfile
@@ -1,4 +1,4 @@
-FROM registry.0xacab.org/leap/bitmask_android/android-sdk:latest
+FROM registry.0xacab.org/leap/bitmask_android/android-ndk:latest
MAINTAINER LEAP Encryption Access Project <info@leap.se>
LABEL Description="Android emulator image based on android-sdk" Vendor="LEAP" Version="4"
diff --git a/scripts/installFastlane.sh b/scripts/installFastlane.sh
index 9abc6211..d1772b86 100755
--- a/scripts/installFastlane.sh
+++ b/scripts/installFastlane.sh
@@ -6,6 +6,7 @@ apt-get -y dist-upgrade && \
apt-get -y install make build-essential ruby ruby-dev imagemagick xvfb libxcb1 libname-dev
gem install fastlane
+fastlane frameit download_frames
## ------------------------------------------------------
## --- Android Emulator
diff --git a/scripts/prepareForScreenshots.sh b/scripts/prepareForScreenshots.sh
index c2ae1bd5..0b38cfae 100755
--- a/scripts/prepareForScreenshots.sh
+++ b/scripts/prepareForScreenshots.sh
@@ -26,4 +26,4 @@ git submodule foreach --recursive git reset --hard HEAD
git submodule sync --recursive
git submodule update --init --recursive
-BUILD_TOR=false BUILD_OPENVPN_LIBS=false ./scripts/build_deps.sh
+./scripts/build_deps.sh
diff --git a/scripts/startEmulators.sh b/scripts/startEmulators.sh
index 1d73dee7..0e6a519c 100755
--- a/scripts/startEmulators.sh
+++ b/scripts/startEmulators.sh
@@ -1,12 +1,13 @@
#!/bin/bash
PATH=$PATH:$ANDROID_HOME/cmdline-tools/latest/bin:$ANDROID_HOME/Sdk/tools:$ANDROID_HOME/emulator
+SCRIPT_DIR=$(dirname "$0")
+
apt-get update
apt-get install -y libpulse-java libpulse0 imagemagick libxkbcommon-x11-0 xvfb vulkan-tools
# there's a QT thing missing
emulator -accel-check
docker info
-export DISPLAY=:99.0
# init parameters
for ((i=1;i<=$#;i++));
@@ -41,7 +42,6 @@ timeout=30
echo y | sdkmanager "emulator"
avdmanager list avd
emulator -version
-find /opt -iname emulator -type f
waitForAdbDevices() {
while true; do
@@ -62,14 +62,10 @@ waitForAdbDevices() {
}
#start first N avd images
-Xvfb :0 -screen 0 800x600x16 &
-#avdmanager list avd | grep 'Name:' | cut -d ':' -f2 | head -n $N | xargs -I{} -P$N -n1 emulator -no-snapshot -avd {} &
-avdmanager list avd | grep 'Name:' | cut -d ':' -f2 | head -n $N | xargs -I{} -P$N -n1 emulator -no-window -no-audio -no-snapshot -avd {} &
-#avdmanager list avd | grep 'Name:' | cut -d ':' -f2 | head -n $N | xargs -I{} -P$N -n1 emulator -no-snapshot -no-window -avd {} &
-# avdmanager list avd | grep 'Name:' | cut -d ':' -f2 | head -n $N | xargs -I{} -P$N -n1 emulator -no-snapshot -no-window -no-boot-anim -accel on -avd {} &
+#Xvfb :0 -screen 0 800x600x16 &
+avdmanager list avd | grep 'Name:' | cut -d ':' -f2 | head -n $N | xargs -I {} emulator -no-window -no-audio -avd {} &
waitForAdbDevices
echo "adb found all emulators..."
-#wait for each emulator that booting completed
-adb devices | grep -v List | awk '$2{print $1}' | xargs -I{} .gitlab/wait-for-emulator.sh -s {}
+adb devices | grep -v List | awk '$2{print $1}' | xargs -I{} $SCRIPT_DIR/wait-for-emulator.sh -s {}
echo "all emulators successfully booted"
diff --git a/src/custom/fastlane/metadata/de/full_description.txt b/src/custom/fastlane/metadata/android/de/full_description.txt
index b53d9c25..b53d9c25 100644
--- a/src/custom/fastlane/metadata/de/full_description.txt
+++ b/src/custom/fastlane/metadata/android/de/full_description.txt
diff --git a/src/custom/fastlane/metadata/de/short_description.txt b/src/custom/fastlane/metadata/android/de/short_description.txt
index 8ab5f289..8ab5f289 100644
--- a/src/custom/fastlane/metadata/de/short_description.txt
+++ b/src/custom/fastlane/metadata/android/de/short_description.txt
diff --git a/src/custom/fastlane/metadata/de/store-meta-de.json b/src/custom/fastlane/metadata/android/de/store-meta-de.json
index c1ad30cd..c1ad30cd 100644
--- a/src/custom/fastlane/metadata/de/store-meta-de.json
+++ b/src/custom/fastlane/metadata/android/de/store-meta-de.json
diff --git a/src/custom/fastlane/metadata/de/title.txt b/src/custom/fastlane/metadata/android/de/title.txt
index 8d2e228a..8d2e228a 100644
--- a/src/custom/fastlane/metadata/de/title.txt
+++ b/src/custom/fastlane/metadata/android/de/title.txt
diff --git a/src/custom/fastlane/metadata/el/full_description.txt b/src/custom/fastlane/metadata/android/el/full_description.txt
index 7d96bc0e..7d96bc0e 100644
--- a/src/custom/fastlane/metadata/el/full_description.txt
+++ b/src/custom/fastlane/metadata/android/el/full_description.txt
diff --git a/src/custom/fastlane/metadata/el/short_description.txt b/src/custom/fastlane/metadata/android/el/short_description.txt
index 157e767e..157e767e 100644
--- a/src/custom/fastlane/metadata/el/short_description.txt
+++ b/src/custom/fastlane/metadata/android/el/short_description.txt
diff --git a/src/custom/fastlane/metadata/el/store-meta-el.json b/src/custom/fastlane/metadata/android/el/store-meta-el.json
index 35f23c9d..35f23c9d 100644
--- a/src/custom/fastlane/metadata/el/store-meta-el.json
+++ b/src/custom/fastlane/metadata/android/el/store-meta-el.json
diff --git a/src/custom/fastlane/metadata/el/title.txt b/src/custom/fastlane/metadata/android/el/title.txt
index 8d2e228a..8d2e228a 100644
--- a/src/custom/fastlane/metadata/el/title.txt
+++ b/src/custom/fastlane/metadata/android/el/title.txt
diff --git a/src/custom/fastlane/metadata/en-US/changelogs/169000.txt b/src/custom/fastlane/metadata/android/en-US/changelogs/169000.txt
index 9cdf3a40..9cdf3a40 100644
--- a/src/custom/fastlane/metadata/en-US/changelogs/169000.txt
+++ b/src/custom/fastlane/metadata/android/en-US/changelogs/169000.txt
diff --git a/src/custom/fastlane/metadata/android/en-US/changelogs/170000.txt b/src/custom/fastlane/metadata/android/en-US/changelogs/170000.txt
new file mode 100644
index 00000000..d2dbd888
--- /dev/null
+++ b/src/custom/fastlane/metadata/android/en-US/changelogs/170000.txt
@@ -0,0 +1,15 @@
+1.2.0
+features:
+* updated openvpn, openssl, tor, snowflake
+* encrypted storage
+* new provider setup UI
+* Support for Android 13
+* enforce TLS 1.3 on all Android versions
+* Dns over Https (DoH) during provider setup
+
+bugfixes:
+* fixed possible on-device DoS vulnerability, leading to app crashes
+* fixed task hijacking vulnerability (aka. strandhogg)
+* fixed memory leaks
+* fixed blocking vpn service stopping and notifications disappearing correctly
+* disable location selection button if provider only supports 1 location
diff --git a/src/custom/fastlane/metadata/en-US/full_description.txt b/src/custom/fastlane/metadata/android/en-US/full_description.txt
index c4ba7305..c4ba7305 100644
--- a/src/custom/fastlane/metadata/en-US/full_description.txt
+++ b/src/custom/fastlane/metadata/android/en-US/full_description.txt
diff --git a/src/custom/fastlane/metadata/en-US/images/sevenInchScreenshots/1_en-US.png b/src/custom/fastlane/metadata/android/en-US/images/sevenInchScreenshots/1_en-US.png
index 04ad4c9a..04ad4c9a 100644
--- a/src/custom/fastlane/metadata/en-US/images/sevenInchScreenshots/1_en-US.png
+++ b/src/custom/fastlane/metadata/android/en-US/images/sevenInchScreenshots/1_en-US.png
Binary files differ
diff --git a/src/custom/fastlane/metadata/en-US/images/sevenInchScreenshots/2_en-US.png b/src/custom/fastlane/metadata/android/en-US/images/sevenInchScreenshots/2_en-US.png
index e7bd728c..e7bd728c 100644
--- a/src/custom/fastlane/metadata/en-US/images/sevenInchScreenshots/2_en-US.png
+++ b/src/custom/fastlane/metadata/android/en-US/images/sevenInchScreenshots/2_en-US.png
Binary files differ
diff --git a/src/custom/fastlane/metadata/en-US/images/sevenInchScreenshots/3_en-US.png b/src/custom/fastlane/metadata/android/en-US/images/sevenInchScreenshots/3_en-US.png
index c8893dee..c8893dee 100644
--- a/src/custom/fastlane/metadata/en-US/images/sevenInchScreenshots/3_en-US.png
+++ b/src/custom/fastlane/metadata/android/en-US/images/sevenInchScreenshots/3_en-US.png
Binary files differ
diff --git a/src/custom/fastlane/metadata/en-US/short_description.txt b/src/custom/fastlane/metadata/android/en-US/short_description.txt
index 1df82a44..1df82a44 100644
--- a/src/custom/fastlane/metadata/en-US/short_description.txt
+++ b/src/custom/fastlane/metadata/android/en-US/short_description.txt
diff --git a/src/custom/fastlane/metadata/en-US/title.txt b/src/custom/fastlane/metadata/android/en-US/title.txt
index 8d2e228a..8d2e228a 100644
--- a/src/custom/fastlane/metadata/en-US/title.txt
+++ b/src/custom/fastlane/metadata/android/en-US/title.txt
diff --git a/src/custom/fastlane/metadata/en-US/video.txt b/src/custom/fastlane/metadata/android/en-US/video.txt
index e69de29b..e69de29b 100644
--- a/src/custom/fastlane/metadata/en-US/video.txt
+++ b/src/custom/fastlane/metadata/android/en-US/video.txt
diff --git a/src/custom/fastlane/metadata/fr/full_description.txt b/src/custom/fastlane/metadata/android/fr/full_description.txt
index 5f7c855e..5f7c855e 100644
--- a/src/custom/fastlane/metadata/fr/full_description.txt
+++ b/src/custom/fastlane/metadata/android/fr/full_description.txt
diff --git a/src/custom/fastlane/metadata/fr/short_description.txt b/src/custom/fastlane/metadata/android/fr/short_description.txt
index 7e92f7da..7e92f7da 100644
--- a/src/custom/fastlane/metadata/fr/short_description.txt
+++ b/src/custom/fastlane/metadata/android/fr/short_description.txt
diff --git a/src/custom/fastlane/metadata/fr/store-meta-fr.json b/src/custom/fastlane/metadata/android/fr/store-meta-fr.json
index af63f77c..af63f77c 100644
--- a/src/custom/fastlane/metadata/fr/store-meta-fr.json
+++ b/src/custom/fastlane/metadata/android/fr/store-meta-fr.json
diff --git a/src/custom/fastlane/metadata/fr/title.txt b/src/custom/fastlane/metadata/android/fr/title.txt
index 8d2e228a..8d2e228a 100644
--- a/src/custom/fastlane/metadata/fr/title.txt
+++ b/src/custom/fastlane/metadata/android/fr/title.txt
diff --git a/src/custom/fastlane/metadata/nl/full_description.txt b/src/custom/fastlane/metadata/android/nl/full_description.txt
index 0a365ed2..0a365ed2 100644
--- a/src/custom/fastlane/metadata/nl/full_description.txt
+++ b/src/custom/fastlane/metadata/android/nl/full_description.txt
diff --git a/src/custom/fastlane/metadata/nl/short_description.txt b/src/custom/fastlane/metadata/android/nl/short_description.txt
index 0e1b3573..0e1b3573 100644
--- a/src/custom/fastlane/metadata/nl/short_description.txt
+++ b/src/custom/fastlane/metadata/android/nl/short_description.txt
diff --git a/src/custom/fastlane/metadata/nl/store-meta-nl.json b/src/custom/fastlane/metadata/android/nl/store-meta-nl.json
index d1923610..d1923610 100644
--- a/src/custom/fastlane/metadata/nl/store-meta-nl.json
+++ b/src/custom/fastlane/metadata/android/nl/store-meta-nl.json
diff --git a/src/custom/fastlane/metadata/nl/title.txt b/src/custom/fastlane/metadata/android/nl/title.txt
index 8d2e228a..8d2e228a 100644
--- a/src/custom/fastlane/metadata/nl/title.txt
+++ b/src/custom/fastlane/metadata/android/nl/title.txt
diff --git a/src/custom/fastlane/metadata/pt-rBR/full_description.txt b/src/custom/fastlane/metadata/android/pt-rBR/full_description.txt
index fc9e95d1..fc9e95d1 100644
--- a/src/custom/fastlane/metadata/pt-rBR/full_description.txt
+++ b/src/custom/fastlane/metadata/android/pt-rBR/full_description.txt
diff --git a/src/custom/fastlane/metadata/pt-rBR/short_description.txt b/src/custom/fastlane/metadata/android/pt-rBR/short_description.txt
index 79efc5e9..79efc5e9 100644
--- a/src/custom/fastlane/metadata/pt-rBR/short_description.txt
+++ b/src/custom/fastlane/metadata/android/pt-rBR/short_description.txt
diff --git a/src/custom/fastlane/metadata/pt-rBR/store-meta-pt-rBR.json b/src/custom/fastlane/metadata/android/pt-rBR/store-meta-pt-rBR.json
index 974408d5..974408d5 100644
--- a/src/custom/fastlane/metadata/pt-rBR/store-meta-pt-rBR.json
+++ b/src/custom/fastlane/metadata/android/pt-rBR/store-meta-pt-rBR.json
diff --git a/src/custom/fastlane/metadata/pt-rBR/title.txt b/src/custom/fastlane/metadata/android/pt-rBR/title.txt
index 8d2e228a..8d2e228a 100644
--- a/src/custom/fastlane/metadata/pt-rBR/title.txt
+++ b/src/custom/fastlane/metadata/android/pt-rBR/title.txt
diff --git a/src/custom/fastlane/metadata/tr/full_description.txt b/src/custom/fastlane/metadata/android/tr/full_description.txt
index 8c6e27ce..8c6e27ce 100644
--- a/src/custom/fastlane/metadata/tr/full_description.txt
+++ b/src/custom/fastlane/metadata/android/tr/full_description.txt
diff --git a/src/custom/fastlane/metadata/tr/short_description.txt b/src/custom/fastlane/metadata/android/tr/short_description.txt
index 83342ec2..83342ec2 100644
--- a/src/custom/fastlane/metadata/tr/short_description.txt
+++ b/src/custom/fastlane/metadata/android/tr/short_description.txt
diff --git a/src/custom/fastlane/metadata/tr/store-meta-tr.json b/src/custom/fastlane/metadata/android/tr/store-meta-tr.json
index 7fd8fcc0..7fd8fcc0 100644
--- a/src/custom/fastlane/metadata/tr/store-meta-tr.json
+++ b/src/custom/fastlane/metadata/android/tr/store-meta-tr.json
diff --git a/src/custom/fastlane/metadata/tr/title.txt b/src/custom/fastlane/metadata/android/tr/title.txt
index 8d2e228a..8d2e228a 100644
--- a/src/custom/fastlane/metadata/tr/title.txt
+++ b/src/custom/fastlane/metadata/android/tr/title.txt
diff --git a/src/normal/fastlane/metadata/el/full_description.txt b/src/normal/fastlane/metadata/android/el/full_description.txt
index aaaaf476..aaaaf476 100644
--- a/src/normal/fastlane/metadata/el/full_description.txt
+++ b/src/normal/fastlane/metadata/android/el/full_description.txt
diff --git a/src/normal/fastlane/metadata/el/short_description.txt b/src/normal/fastlane/metadata/android/el/short_description.txt
index 4ac7309e..4ac7309e 100644
--- a/src/normal/fastlane/metadata/el/short_description.txt
+++ b/src/normal/fastlane/metadata/android/el/short_description.txt
diff --git a/src/normal/fastlane/metadata/el/store-meta-el.json b/src/normal/fastlane/metadata/android/el/store-meta-el.json
index 0e32bdc9..0e32bdc9 100644
--- a/src/normal/fastlane/metadata/el/store-meta-el.json
+++ b/src/normal/fastlane/metadata/android/el/store-meta-el.json
diff --git a/src/normal/fastlane/metadata/el/title.txt b/src/normal/fastlane/metadata/android/el/title.txt
index a953d6a6..a953d6a6 100644
--- a/src/normal/fastlane/metadata/el/title.txt
+++ b/src/normal/fastlane/metadata/android/el/title.txt
diff --git a/src/normal/fastlane/metadata/en-US/changelogs/168000.txt b/src/normal/fastlane/metadata/android/en-US/changelogs/168000.txt
index 80766d7f..80766d7f 100644
--- a/src/normal/fastlane/metadata/en-US/changelogs/168000.txt
+++ b/src/normal/fastlane/metadata/android/en-US/changelogs/168000.txt
diff --git a/src/normal/fastlane/metadata/android/en-US/changelogs/170000.txt b/src/normal/fastlane/metadata/android/en-US/changelogs/170000.txt
new file mode 100644
index 00000000..d2dbd888
--- /dev/null
+++ b/src/normal/fastlane/metadata/android/en-US/changelogs/170000.txt
@@ -0,0 +1,15 @@
+1.2.0
+features:
+* updated openvpn, openssl, tor, snowflake
+* encrypted storage
+* new provider setup UI
+* Support for Android 13
+* enforce TLS 1.3 on all Android versions
+* Dns over Https (DoH) during provider setup
+
+bugfixes:
+* fixed possible on-device DoS vulnerability, leading to app crashes
+* fixed task hijacking vulnerability (aka. strandhogg)
+* fixed memory leaks
+* fixed blocking vpn service stopping and notifications disappearing correctly
+* disable location selection button if provider only supports 1 location
diff --git a/src/normal/fastlane/metadata/en-US/full_description.txt b/src/normal/fastlane/metadata/android/en-US/full_description.txt
index 2fcf278a..2fcf278a 100644
--- a/src/normal/fastlane/metadata/en-US/full_description.txt
+++ b/src/normal/fastlane/metadata/android/en-US/full_description.txt
diff --git a/src/normal/fastlane/metadata/en-US/short_description.txt b/src/normal/fastlane/metadata/android/en-US/short_description.txt
index 6f481599..6f481599 100644
--- a/src/normal/fastlane/metadata/en-US/short_description.txt
+++ b/src/normal/fastlane/metadata/android/en-US/short_description.txt
diff --git a/src/normal/fastlane/metadata/en-US/title.txt b/src/normal/fastlane/metadata/android/en-US/title.txt
index a953d6a6..a953d6a6 100644
--- a/src/normal/fastlane/metadata/en-US/title.txt
+++ b/src/normal/fastlane/metadata/android/en-US/title.txt
diff --git a/src/normal/fastlane/metadata/en-US/video.txt b/src/normal/fastlane/metadata/android/en-US/video.txt
index e69de29b..e69de29b 100644
--- a/src/normal/fastlane/metadata/en-US/video.txt
+++ b/src/normal/fastlane/metadata/android/en-US/video.txt
diff --git a/src/normal/fastlane/metadata/nl/full_description.txt b/src/normal/fastlane/metadata/android/nl/full_description.txt
index a714dff0..a714dff0 100644
--- a/src/normal/fastlane/metadata/nl/full_description.txt
+++ b/src/normal/fastlane/metadata/android/nl/full_description.txt
diff --git a/src/normal/fastlane/metadata/nl/short_description.txt b/src/normal/fastlane/metadata/android/nl/short_description.txt
index dd626a6c..dd626a6c 100644
--- a/src/normal/fastlane/metadata/nl/short_description.txt
+++ b/src/normal/fastlane/metadata/android/nl/short_description.txt
diff --git a/src/normal/fastlane/metadata/nl/store-meta-nl.json b/src/normal/fastlane/metadata/android/nl/store-meta-nl.json
index 61c9b38d..61c9b38d 100644
--- a/src/normal/fastlane/metadata/nl/store-meta-nl.json
+++ b/src/normal/fastlane/metadata/android/nl/store-meta-nl.json
diff --git a/src/normal/fastlane/metadata/nl/title.txt b/src/normal/fastlane/metadata/android/nl/title.txt
index a953d6a6..a953d6a6 100644
--- a/src/normal/fastlane/metadata/nl/title.txt
+++ b/src/normal/fastlane/metadata/android/nl/title.txt
diff --git a/src/normal/fastlane/metadata/pt-rBR/store-meta-pt-rBR.json b/src/normal/fastlane/metadata/android/pt-rBR/store-meta-pt-rBR.json
index 07ab743d..07ab743d 100644
--- a/src/normal/fastlane/metadata/pt-rBR/store-meta-pt-rBR.json
+++ b/src/normal/fastlane/metadata/android/pt-rBR/store-meta-pt-rBR.json
diff --git a/src/normal/fastlane/metadata/tr/full_description.txt b/src/normal/fastlane/metadata/android/tr/full_description.txt
index 10418aa9..10418aa9 100644
--- a/src/normal/fastlane/metadata/tr/full_description.txt
+++ b/src/normal/fastlane/metadata/android/tr/full_description.txt
diff --git a/src/normal/fastlane/metadata/tr/short_description.txt b/src/normal/fastlane/metadata/android/tr/short_description.txt
index 4e042739..4e042739 100644
--- a/src/normal/fastlane/metadata/tr/short_description.txt
+++ b/src/normal/fastlane/metadata/android/tr/short_description.txt
diff --git a/src/normal/fastlane/metadata/tr/store-meta-tr.json b/src/normal/fastlane/metadata/android/tr/store-meta-tr.json
index b38b70a6..b38b70a6 100644
--- a/src/normal/fastlane/metadata/tr/store-meta-tr.json
+++ b/src/normal/fastlane/metadata/android/tr/store-meta-tr.json
diff --git a/src/normal/fastlane/metadata/tr/title.txt b/src/normal/fastlane/metadata/android/tr/title.txt
index a953d6a6..a953d6a6 100644
--- a/src/normal/fastlane/metadata/tr/title.txt
+++ b/src/normal/fastlane/metadata/android/tr/title.txt
diff --git a/src/normal/fastlane/metadata/tr/tx-values-tr.json b/src/normal/fastlane/metadata/android/tr/tx-values-tr.json
index 9e26dfee..9e26dfee 100644
--- a/src/normal/fastlane/metadata/tr/tx-values-tr.json
+++ b/src/normal/fastlane/metadata/android/tr/tx-values-tr.json