From d157f98aebc088205f427861ac414d19c7a05c3a Mon Sep 17 00:00:00 2001 From: cyBerta Date: Tue, 24 Oct 2023 21:57:06 +0200 Subject: show progress spinner during provider setup in custom flavored apps --- .../java/se/leap/bitmaskclient/base/views/ProgressSpinner.java | 5 +++++ .../providersetup/fragments/ConfigureProviderFragment.java | 8 ++++++++ 2 files changed, 13 insertions(+) (limited to 'app/src/main/java/se') diff --git a/app/src/main/java/se/leap/bitmaskclient/base/views/ProgressSpinner.java b/app/src/main/java/se/leap/bitmaskclient/base/views/ProgressSpinner.java index 380ddf23..97238ec6 100644 --- a/app/src/main/java/se/leap/bitmaskclient/base/views/ProgressSpinner.java +++ b/app/src/main/java/se/leap/bitmaskclient/base/views/ProgressSpinner.java @@ -2,6 +2,7 @@ package se.leap.bitmaskclient.base.views; import android.annotation.TargetApi; import android.content.Context; +import android.graphics.drawable.Drawable; import android.util.AttributeSet; import android.view.LayoutInflater; import android.widget.RelativeLayout; @@ -60,4 +61,8 @@ public class ProgressSpinner extends RelativeLayout { } textView.setText(text); } + + public void setAnimatedSpinnerDrawable(Drawable drawable) { + spinnerView.setImageDrawable(drawable); + } } 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 3c36065e..26eb5f4c 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,6 +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.PreferenceHelper.getUseSnowflake; import static se.leap.bitmaskclient.base.utils.ViewHelper.animateContainerVisibility; import static se.leap.bitmaskclient.providersetup.ProviderAPI.CORRECTLY_DOWNLOADED_VPN_CERTIFICATE; @@ -28,6 +29,7 @@ import static se.leap.bitmaskclient.tor.TorStatusObservable.getLastTorLog; import android.app.Activity; import android.content.Intent; +import android.graphics.drawable.Drawable; import android.os.Bundle; import android.view.LayoutInflater; import android.view.View; @@ -35,6 +37,7 @@ import android.view.ViewGroup; import androidx.annotation.NonNull; import androidx.annotation.Nullable; +import androidx.core.content.res.ResourcesCompat; import androidx.recyclerview.widget.LinearLayoutManager; import androidx.recyclerview.widget.RecyclerView; @@ -42,6 +45,7 @@ import java.util.List; import java.util.Observable; import java.util.Observer; +import se.leap.bitmaskclient.R; import se.leap.bitmaskclient.base.models.Provider; import se.leap.bitmaskclient.databinding.FConfigureProviderBinding; import se.leap.bitmaskclient.eip.EipSetupListener; @@ -116,6 +120,10 @@ public class ConfigureProviderFragment extends BaseSetupFragment implements Obse ignoreProviderAPIUpdates = false; binding.detailContainer.setVisibility(getUseSnowflake() ? VISIBLE : GONE); binding.tvCircumventionDescription.setText(getUseSnowflake() ? description_configure_provider_circumvention : description_configure_provider); + if (!isDefaultBitmask()) { + Drawable drawable = ResourcesCompat.getDrawable(getResources(), R.drawable.setup_progress_spinner, null); + binding.progressSpinner.setAnimatedSpinnerDrawable(drawable); + } setupActivityCallback.setNavigationButtonHidden(true); setupActivityCallback.setCancelButtonHidden(false); ProviderAPICommand.execute(getContext(), SET_UP_PROVIDER, setupActivityCallback.getSelectedProvider()); -- cgit v1.2.3 From f64576feee47a783a3058ac181e8460fb19a30ce Mon Sep 17 00:00:00 2001 From: cyBerta Date: Tue, 24 Oct 2023 21:57:49 +0200 Subject: replace snake_case with camelCase in ProviderManager --- .../java/se/leap/bitmaskclient/providersetup/ProviderManager.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'app/src/main/java/se') diff --git a/app/src/main/java/se/leap/bitmaskclient/providersetup/ProviderManager.java b/app/src/main/java/se/leap/bitmaskclient/providersetup/ProviderManager.java index 0f6c5090..b46072ff 100644 --- a/app/src/main/java/se/leap/bitmaskclient/providersetup/ProviderManager.java +++ b/app/src/main/java/se/leap/bitmaskclient/providersetup/ProviderManager.java @@ -73,9 +73,9 @@ public class ProviderManager implements AdapteeCollection { addCustomProviders(externalFilesDir); } - private void addDefaultProviders(AssetManager assets_manager) { + private void addDefaultProviders(AssetManager assetManager) { try { - defaultProviders = providersFromAssets(URLS, assets_manager.list(URLS)); + defaultProviders = providersFromAssets(URLS, assetManager.list(URLS)); defaultProviderURLs = getProviderUrlSetFromProviderSet(defaultProviders); } catch (IOException e) { e.printStackTrace(); -- cgit v1.2.3 From 6d7a966b39a8a1208d67981e726c63d02efd4f4a Mon Sep 17 00:00:00 2001 From: cyBerta Date: Tue, 24 Oct 2023 22:02:29 +0200 Subject: use new provider setup flow for custom branded apps --- .../se/leap/bitmaskclient/base/StartActivity.java | 10 ++--- .../providersetup/SetupViewPagerAdapter.java | 5 ++- .../providersetup/activities/SetupActivity.java | 14 +++++-- .../fragments/CircumventionSetupFragment.java | 43 ++++++++++++++++++++-- 4 files changed, 57 insertions(+), 15 deletions(-) (limited to 'app/src/main/java/se') diff --git a/app/src/main/java/se/leap/bitmaskclient/base/StartActivity.java b/app/src/main/java/se/leap/bitmaskclient/base/StartActivity.java index 8372b6ad..19f03dee 100644 --- a/app/src/main/java/se/leap/bitmaskclient/base/StartActivity.java +++ b/app/src/main/java/se/leap/bitmaskclient/base/StartActivity.java @@ -247,13 +247,9 @@ public class StartActivity extends Activity{ if (getIntent().hasExtra(APP_ACTION_CONFIGURE_ALWAYS_ON_PROFILE)) { getIntent().removeExtra(APP_ACTION_CONFIGURE_ALWAYS_ON_PROFILE); } - if (isDefaultBitmask()) { - Intent intent = new Intent(this, SetupActivity.class); - intent.putExtra(SetupActivity.EXTRA_SWITCH_PROVIDER, false); - startActivityForResult(intent, REQUEST_CODE_CONFIGURE_LEAP); - } else { // custom branded app - startActivityForResult(new Intent(this, CustomProviderSetupActivity.class), REQUEST_CODE_CONFIGURE_LEAP); - } + Intent intent = new Intent(this, SetupActivity.class); + intent.putExtra(SetupActivity.EXTRA_SWITCH_PROVIDER, false); + startActivityForResult(intent, REQUEST_CODE_CONFIGURE_LEAP); } @Override 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 a4a8fabd..00630f39 100644 --- a/app/src/main/java/se/leap/bitmaskclient/providersetup/SetupViewPagerAdapter.java +++ b/app/src/main/java/se/leap/bitmaskclient/providersetup/SetupViewPagerAdapter.java @@ -1,5 +1,6 @@ package se.leap.bitmaskclient.providersetup; +import static se.leap.bitmaskclient.base.utils.ConfigHelper.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; @@ -33,7 +34,9 @@ public class SetupViewPagerAdapter extends FragmentStateAdapter { this(fragmentManager, lifecycle); ArrayList fragments = new ArrayList<>(); if (providerSetup) { - fragments.add(PROVIDER_SELECTION_FRAGMENT); + if (isDefaultBitmask()) { + fragments.add(PROVIDER_SELECTION_FRAGMENT); + } fragments.add(CIRCUMVENTION_SETUP_FRAGMENT); fragments.add(CONFIGURE_PROVIDER_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 a6e50769..724543e4 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,6 +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.PreferenceHelper.deleteProviderDetailsFromPreferences; import static se.leap.bitmaskclient.providersetup.fragments.SetupFragmentFactory.CONFIGURE_PROVIDER_FRAGMENT; import static se.leap.bitmaskclient.tor.TorStatusObservable.TorStatus.OFF; @@ -84,14 +85,19 @@ public class SetupActivity extends AppCompatActivity implements SetupActivityCal fragmentManager = new FragmentManagerEnhanced(getSupportFragmentManager()); ArrayList indicatorViews = new ArrayList<>(); - // indicator views for provider selection and config setup + if (isDefaultBitmask()) { + // indicator view for provider selection + addIndicatorView(indicatorViews); + } + + // indicator views for config setup boolean basicProviderSetup = !ProviderObservable.getInstance().getCurrentProvider().isConfigured() || switchProvider; if (basicProviderSetup) { - for (int i = 0; i < 3; i++) { - addIndicatorView(indicatorViews); - } + addIndicatorView(indicatorViews); + addIndicatorView(indicatorViews); } + // indicator views for VPN permission Intent requestVpnPermission = VpnService.prepare(this); if (requestVpnPermission != null) { 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 11fa582b..34a93319 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,5 +1,8 @@ package se.leap.bitmaskclient.providersetup.fragments; +import static se.leap.bitmaskclient.base.utils.ConfigHelper.isDefaultBitmask; + +import android.content.Context; import android.graphics.Typeface; import android.os.Bundle; import android.view.LayoutInflater; @@ -9,10 +12,14 @@ import android.view.ViewGroup; import androidx.annotation.NonNull; import androidx.annotation.Nullable; +import se.leap.bitmaskclient.R; 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 { +public class CircumventionSetupFragment extends BaseSetupFragment implements CancelCallback { public static CircumventionSetupFragment newInstance(int position) { CircumventionSetupFragment fragment = new CircumventionSetupFragment(); @@ -24,7 +31,8 @@ public class CircumventionSetupFragment extends BaseSetupFragment { public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { FCircumventionSetupBinding binding = FCircumventionSetupBinding.inflate(inflater, container, false); - + binding.rbPlainVpn.setText(getString(R.string.use_standard_vpn, getString(R.string.app_name))); + binding.tvCircumventionDetailDescription.setText(getString(R.string.circumvention_setup_hint, getString(R.string.app_name))); binding.circumventionRadioGroup.setOnCheckedChangeListener((group, checkedId) -> { if (binding.rbCircumvention.getId() == checkedId) { PreferenceHelper.useBridges(true); @@ -49,10 +57,39 @@ public class CircumventionSetupFragment extends BaseSetupFragment { return binding.getRoot(); } + @Override + public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) { + super.onViewCreated(view, savedInstanceState); + setupActivityCallback.registerCancelCallback(this); + } + + @Override + public void onDestroyView() { + super.onDestroyView(); + setupActivityCallback.removeCancelCallback(this); + } + @Override public void onFragmentSelected() { super.onFragmentSelected(); - setupActivityCallback.setCancelButtonHidden(false); + setupActivityCallback.setCancelButtonHidden(!isDefaultBitmask()); setupActivityCallback.setNavigationButtonHidden(false); + if (!isDefaultBitmask()) { + loadProviderFromAssets(); + } + } + + private void loadProviderFromAssets() { + ProviderManager providerManager = ProviderManager.getInstance(getContext().getApplicationContext().getAssets(), + getContext().getExternalFilesDir(null)); + providerManager.setAddDummyEntry(false); + setupActivityCallback.onProviderSelected(providerManager.providers().get(0)); + } + + @Override + public void onCanceled() { + if (!isDefaultBitmask()) { + loadProviderFromAssets(); + } } } \ No newline at end of file -- cgit v1.2.3 From b2956073c6f0770347ec71bdc592b74426fddf2a Mon Sep 17 00:00:00 2001 From: cyBerta Date: Wed, 25 Oct 2023 14:54:41 +0200 Subject: always show provider setup progress in percentage, combine tor bootstrap progress and provider api communication progress in case circumvention is needed --- .../se/leap/bitmaskclient/base/BitmaskApp.java | 5 +- .../leap/bitmaskclient/eip/EipSetupObserver.java | 2 + .../providersetup/ProviderApiManagerBase.java | 6 ++ .../providersetup/ProviderSetupObservable.java | 103 +++++++++++++++++++++ .../providersetup/activities/SetupActivity.java | 3 + .../fragments/ConfigureProviderFragment.java | 25 +++-- 6 files changed, 136 insertions(+), 8 deletions(-) create mode 100644 app/src/main/java/se/leap/bitmaskclient/providersetup/ProviderSetupObservable.java (limited to 'app/src/main/java/se') diff --git a/app/src/main/java/se/leap/bitmaskclient/base/BitmaskApp.java b/app/src/main/java/se/leap/bitmaskclient/base/BitmaskApp.java index a66f75d7..0fa62285 100644 --- a/app/src/main/java/se/leap/bitmaskclient/base/BitmaskApp.java +++ b/app/src/main/java/se/leap/bitmaskclient/base/BitmaskApp.java @@ -26,7 +26,6 @@ import static se.leap.bitmaskclient.base.utils.ConfigHelper.isCalyxOSWithTetheri import static se.leap.bitmaskclient.base.utils.PreferenceHelper.getSavedProviderFromSharedPreferences; import android.content.IntentFilter; -import android.content.SharedPreferences; import androidx.appcompat.app.AppCompatDelegate; import androidx.localbroadcastmanager.content.LocalBroadcastManager; @@ -42,6 +41,7 @@ import se.leap.bitmaskclient.base.models.ProviderObservable; import se.leap.bitmaskclient.base.utils.PRNGFixes; import se.leap.bitmaskclient.base.utils.PreferenceHelper; import se.leap.bitmaskclient.eip.EipSetupObserver; +import se.leap.bitmaskclient.providersetup.ProviderSetupObservable; import se.leap.bitmaskclient.tethering.TetheringStateManager; import se.leap.bitmaskclient.tor.TorStatusObservable; @@ -56,6 +56,8 @@ public class BitmaskApp extends MultiDexApplication { private DownloadBroadcastReceiver downloadBroadcastReceiver; private TorStatusObservable torStatusObservable; + private ProviderSetupObservable providerSetupObservable; + private PreferenceHelper preferenceHelper; @@ -69,6 +71,7 @@ public class BitmaskApp extends MultiDexApplication { providerObservable = ProviderObservable.getInstance(); providerObservable.updateProvider(getSavedProviderFromSharedPreferences()); torStatusObservable = TorStatusObservable.getInstance(); + providerSetupObservable = ProviderSetupObservable.getInstance(); EipSetupObserver.init(this); AppCompatDelegate.setCompatVectorFromResourcesEnabled(true); if (!isCalyxOSWithTetheringSupport(this)) { diff --git a/app/src/main/java/se/leap/bitmaskclient/eip/EipSetupObserver.java b/app/src/main/java/se/leap/bitmaskclient/eip/EipSetupObserver.java index ed83770b..c8b8bea4 100644 --- a/app/src/main/java/se/leap/bitmaskclient/eip/EipSetupObserver.java +++ b/app/src/main/java/se/leap/bitmaskclient/eip/EipSetupObserver.java @@ -79,6 +79,7 @@ import se.leap.bitmaskclient.base.models.ProviderObservable; import se.leap.bitmaskclient.base.utils.PreferenceHelper; import se.leap.bitmaskclient.providersetup.ProviderAPI; import se.leap.bitmaskclient.providersetup.ProviderAPICommand; +import se.leap.bitmaskclient.providersetup.ProviderSetupObservable; import se.leap.bitmaskclient.tor.TorServiceCommand; import se.leap.bitmaskclient.tor.TorStatusObservable; @@ -177,6 +178,7 @@ public class EipSetupObserver extends BroadcastReceiver implements VpnStatus.Sta Integer bootstrap = intent.getIntExtra(TorService.EXTRA_STATUS_DETAIL_BOOTSTRAP, -1); String logKey = intent.getStringExtra(TorService.EXTRA_STATUS_DETAIL_LOGKEY); TorStatusObservable.updateState(appContext, status, bootstrap, logKey); + ProviderSetupObservable.updateTorSetupProgress(); } 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 9468f76e..93648bb0 100644 --- a/app/src/main/java/se/leap/bitmaskclient/providersetup/ProviderApiManagerBase.java +++ b/app/src/main/java/se/leap/bitmaskclient/providersetup/ProviderApiManagerBase.java @@ -96,6 +96,8 @@ import static se.leap.bitmaskclient.providersetup.ProviderSetupFailedDialog.DOWN import static se.leap.bitmaskclient.providersetup.ProviderSetupFailedDialog.DOWNLOAD_ERRORS.ERROR_CORRUPTED_PROVIDER_JSON; import static se.leap.bitmaskclient.providersetup.ProviderSetupFailedDialog.DOWNLOAD_ERRORS.ERROR_INVALID_CERTIFICATE; import static se.leap.bitmaskclient.providersetup.ProviderSetupFailedDialog.DOWNLOAD_ERRORS.ERROR_TOR_TIMEOUT; +import static se.leap.bitmaskclient.providersetup.ProviderSetupObservable.DOWNLOADED_GEOIP_JSON; +import static se.leap.bitmaskclient.providersetup.ProviderSetupObservable.DOWNLOADED_VPN_CERTIFICATE; import static se.leap.bitmaskclient.tor.TorStatusObservable.TorStatus.OFF; import static se.leap.bitmaskclient.tor.TorStatusObservable.TorStatus.ON; import static se.leap.bitmaskclient.tor.TorStatusObservable.getProxyPort; @@ -256,6 +258,9 @@ public abstract class ProviderApiManagerBase { result = setUpProvider(provider, parameters); if (result.getBoolean(BROADCAST_RESULT_KEY)) { getGeoIPJson(provider); + if (provider.hasGeoIpJson()) { + ProviderSetupObservable.updateProgress(DOWNLOADED_GEOIP_JSON); + } sendToReceiverOrBroadcast(receiver, PROVIDER_OK, result, provider); } else { sendToReceiverOrBroadcast(receiver, PROVIDER_NOK, result, provider); @@ -289,6 +294,7 @@ public abstract class ProviderApiManagerBase { ProviderObservable.getInstance().setProviderForDns(provider); result = updateVpnCertificate(provider); if (result.getBoolean(BROADCAST_RESULT_KEY)) { + ProviderSetupObservable.updateProgress(DOWNLOADED_VPN_CERTIFICATE); sendToReceiverOrBroadcast(receiver, CORRECTLY_DOWNLOADED_VPN_CERTIFICATE, result, provider); } else { sendToReceiverOrBroadcast(receiver, INCORRECTLY_DOWNLOADED_VPN_CERTIFICATE, result, provider); diff --git a/app/src/main/java/se/leap/bitmaskclient/providersetup/ProviderSetupObservable.java b/app/src/main/java/se/leap/bitmaskclient/providersetup/ProviderSetupObservable.java new file mode 100644 index 00000000..56ef357b --- /dev/null +++ b/app/src/main/java/se/leap/bitmaskclient/providersetup/ProviderSetupObservable.java @@ -0,0 +1,103 @@ +package se.leap.bitmaskclient.providersetup; +/** + * Copyright (c) 2023 LEAP Encryption Access Project and contributors + * + * 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 . + */ + +import android.os.Handler; +import android.os.Looper; + +import java.util.Observable; + +import se.leap.bitmaskclient.tor.TorStatusObservable; + +public class ProviderSetupObservable extends Observable { + + private static final String TAG = ProviderSetupObservable.class.getSimpleName(); + + private int progress = 0; + private boolean canceled = false; + public static final int DOWNLOADED_PROVIDER_JSON = 20; + public static final int DOWNLOADED_CA_CERT = 40; + public static final int DOWNLOADED_EIP_SERVICE_JSON = 60; + public static final int DOWNLOADED_GEOIP_JSON = 80; + public static final int DOWNLOADED_VPN_CERTIFICATE = 100; + + private static ProviderSetupObservable instance; + private final Handler handler = new Handler(Looper.getMainLooper()); + private long lastUpdate = 0; + + public static ProviderSetupObservable getInstance() { + if (instance == null) { + instance = new ProviderSetupObservable(); + } + return instance; + } + + public static void updateProgress(int progress) { + if (instance.canceled) { + return; + } + long now = System.currentTimeMillis(); + getInstance().handler.postDelayed(() -> { + if (TorStatusObservable.isRunning()) { + getInstance().progress = (TorStatusObservable.getBootstrapProgress() + progress) / 2; + } else { + getInstance().progress = progress; + } + + getInstance().setChanged(); + getInstance().notifyObservers(); + }, now - getInstance().lastUpdate < 500L ? 500L : 0L); + getInstance().lastUpdate = System.currentTimeMillis() + 500; + } + + public static void updateTorSetupProgress() { + if (!TorStatusObservable.isRunning() || getInstance().canceled) { + return; + } + long now = System.currentTimeMillis(); + getInstance().handler.postDelayed(() -> { + getInstance().progress = (TorStatusObservable.getBootstrapProgress()) / 2; + + getInstance().setChanged(); + getInstance().notifyObservers(); + }, now - getInstance().lastUpdate < 500L ? 500L : 0); + getInstance().lastUpdate = System.currentTimeMillis() + 500; + } + + public static int getProgress() { + return getInstance().progress; + } + + public static void reset() { + getInstance().progress = 0; + getInstance().setChanged(); + getInstance().notifyObservers(); + } + + public static void cancel() { + getInstance().canceled = true; + reset(); + } + + public static boolean isCanceled() { + return getInstance().canceled; + } + + public static void startSetup() { + getInstance().canceled = false; + } +} 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 724543e4..b258a100 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 @@ -48,6 +48,7 @@ import se.leap.bitmaskclient.base.utils.ViewHelper; import se.leap.bitmaskclient.base.views.ActionBarTitle; import se.leap.bitmaskclient.databinding.ActivitySetupBinding; import se.leap.bitmaskclient.providersetup.ProviderSetupFailedDialog; +import se.leap.bitmaskclient.providersetup.ProviderSetupObservable; import se.leap.bitmaskclient.providersetup.SetupViewPagerAdapter; import se.leap.bitmaskclient.tor.TorServiceCommand; import se.leap.bitmaskclient.tor.TorStatusObservable; @@ -166,6 +167,7 @@ public class SetupActivity extends AppCompatActivity implements SetupActivityCal private void cancel() { binding.viewPager.setCurrentItem(0, false); + ProviderSetupObservable.cancel(); if (TorStatusObservable.getStatus() != OFF) { Log.d(TAG, "SHUTDOWN - cancelSettingUpProvider"); TorServiceCommand.stopTorServiceAsync(this); @@ -287,6 +289,7 @@ public class SetupActivity extends AppCompatActivity implements SetupActivityCal @Override public void onSetupFinished() { + ProviderSetupObservable.reset(); Intent intent = getIntent(); if (provider == null && ProviderObservable.getInstance().getCurrentProvider().isConfigured()) { // only permissions were requested, no new provider configured, so reuse previously configured one 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 26eb5f4c..ec646cac 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 @@ -22,7 +22,6 @@ import static se.leap.bitmaskclient.providersetup.ProviderAPI.PROVIDER_OK; import static se.leap.bitmaskclient.providersetup.ProviderAPI.SET_UP_PROVIDER; import static se.leap.bitmaskclient.providersetup.ProviderAPI.TOR_EXCEPTION; import static se.leap.bitmaskclient.providersetup.ProviderAPI.TOR_TIMEOUT; -import static se.leap.bitmaskclient.tor.TorStatusObservable.getBootstrapProgress; import static se.leap.bitmaskclient.tor.TorStatusObservable.getLastLogs; import static se.leap.bitmaskclient.tor.TorStatusObservable.getLastSnowflakeLog; import static se.leap.bitmaskclient.tor.TorStatusObservable.getLastTorLog; @@ -31,6 +30,8 @@ import android.app.Activity; import android.content.Intent; import android.graphics.drawable.Drawable; import android.os.Bundle; +import android.os.Handler; +import android.os.Looper; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; @@ -51,6 +52,7 @@ import se.leap.bitmaskclient.databinding.FConfigureProviderBinding; import se.leap.bitmaskclient.eip.EipSetupListener; import se.leap.bitmaskclient.eip.EipSetupObserver; import se.leap.bitmaskclient.providersetup.ProviderAPICommand; +import se.leap.bitmaskclient.providersetup.ProviderSetupObservable; import se.leap.bitmaskclient.providersetup.TorLogAdapter; import se.leap.bitmaskclient.providersetup.activities.CancelCallback; import se.leap.bitmaskclient.tor.TorStatusObservable; @@ -64,6 +66,8 @@ public class ConfigureProviderFragment extends BaseSetupFragment implements Obse private boolean ignoreProviderAPIUpdates = false; private TorLogAdapter torLogAdapter; + private Handler handler = new Handler(Looper.getMainLooper()); + public static ConfigureProviderFragment newInstance(int position) { ConfigureProviderFragment fragment = new ConfigureProviderFragment(); @@ -101,14 +105,14 @@ public class ConfigureProviderFragment extends BaseSetupFragment implements Obse public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) { super.onViewCreated(view, savedInstanceState); setupActivityCallback.registerCancelCallback(this); - TorStatusObservable.getInstance().addObserver(this); + ProviderSetupObservable.getInstance().addObserver(this); EipSetupObserver.addListener(this); } @Override public void onDestroyView() { setupActivityCallback.removeCancelCallback(this); - TorStatusObservable.getInstance().deleteObserver(this); + ProviderSetupObservable.getInstance().deleteObserver(this); EipSetupObserver.removeListener(this); binding = null; super.onDestroyView(); @@ -124,8 +128,10 @@ public class ConfigureProviderFragment extends BaseSetupFragment implements Obse Drawable drawable = ResourcesCompat.getDrawable(getResources(), R.drawable.setup_progress_spinner, null); binding.progressSpinner.setAnimatedSpinnerDrawable(drawable); } + binding.progressSpinner.update(ProviderSetupObservable.getProgress()); setupActivityCallback.setNavigationButtonHidden(true); setupActivityCallback.setCancelButtonHidden(false); + ProviderSetupObservable.startSetup(); ProviderAPICommand.execute(getContext(), SET_UP_PROVIDER, setupActivityCallback.getSelectedProvider()); } @@ -153,7 +159,7 @@ public class ConfigureProviderFragment extends BaseSetupFragment implements Obse @Override public void update(Observable o, Object arg) { - if (o instanceof TorStatusObservable) { + if (o instanceof ProviderSetupObservable) { Activity activity = getActivity(); if (activity == null || binding == null) { return; @@ -170,7 +176,7 @@ public class ConfigureProviderFragment extends BaseSetupFragment implements Obse } } binding.tvProgressStatus.setText(TorStatusObservable.getStringForCurrentStatus(activity)); - binding.progressSpinner.update(getBootstrapProgress()); + binding.progressSpinner.update(ProviderSetupObservable.getProgress()); }); } } @@ -199,7 +205,8 @@ public class ConfigureProviderFragment extends BaseSetupFragment implements Obse Provider provider = resultData.getParcelable(PROVIDER_KEY); if (ignoreProviderAPIUpdates || provider == null || - !setupActivityCallback.getSelectedProvider().getDomain().equals(provider.getDomain())) { + (setupActivityCallback.getSelectedProvider() != null && + !setupActivityCallback.getSelectedProvider().getDomain().equals(provider.getDomain()))) { return; } @@ -213,7 +220,11 @@ public class ConfigureProviderFragment extends BaseSetupFragment implements Obse break; case CORRECTLY_DOWNLOADED_VPN_CERTIFICATE: setupActivityCallback.onProviderSelected(provider); - setupActivityCallback.onConfigurationSuccess(); + handler.postDelayed(() -> { + if (!ProviderSetupObservable.isCanceled()) { + setupActivityCallback.onConfigurationSuccess(); + } + }, 750); break; case PROVIDER_NOK: case INCORRECTLY_DOWNLOADED_VPN_CERTIFICATE: -- cgit v1.2.3 From 743cd82d2c061631e493f13685065c987c8665ea Mon Sep 17 00:00:00 2001 From: cyBerta Date: Wed, 25 Oct 2023 14:56:50 +0200 Subject: deprecate old Provider API jobs, such as login and signup --- .../java/se/leap/bitmaskclient/providersetup/ProviderAPI.java | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) (limited to 'app/src/main/java/se') diff --git a/app/src/main/java/se/leap/bitmaskclient/providersetup/ProviderAPI.java b/app/src/main/java/se/leap/bitmaskclient/providersetup/ProviderAPI.java index 07ea4691..ed30c454 100644 --- a/app/src/main/java/se/leap/bitmaskclient/providersetup/ProviderAPI.java +++ b/app/src/main/java/se/leap/bitmaskclient/providersetup/ProviderAPI.java @@ -52,15 +52,18 @@ public class ProviderAPI extends JobIntentService implements ProviderApiManagerB */ static final int JOB_ID = 161375; + @Deprecated + final public static String + UPDATE_PROVIDER_DETAILS = "updateProviderDetails", + SIGN_UP = "srpRegister", + LOG_IN = "srpAuth", + LOG_OUT = "logOut"; + final public static String TAG = ProviderAPI.class.getSimpleName(), SET_UP_PROVIDER = "setUpProvider", - UPDATE_PROVIDER_DETAILS = "updateProviderDetails", DOWNLOAD_GEOIP_JSON = "downloadGeoIpJson", DOWNLOAD_MOTD = "downloadMotd", - SIGN_UP = "srpRegister", - LOG_IN = "srpAuth", - LOG_OUT = "logOut", // all vpn certificate download commands are used in different scenarios with different error handling // command key used for the initial vpn certificate download during the provider setup DOWNLOAD_VPN_CERTIFICATE = "downloadUserAuthedVPNCertificate", -- cgit v1.2.3 From 3668796930633a4850aa9a5e0117c3c4d4d21af6 Mon Sep 17 00:00:00 2001 From: cyBerta Date: Wed, 25 Oct 2023 14:57:32 +0200 Subject: make linter happy about missing super() call in CustomProviderSetupActivity --- .../providersetup/activities/CustomProviderSetupActivity.java | 1 + 1 file changed, 1 insertion(+) (limited to 'app/src/main/java/se') diff --git a/app/src/main/java/se/leap/bitmaskclient/providersetup/activities/CustomProviderSetupActivity.java b/app/src/main/java/se/leap/bitmaskclient/providersetup/activities/CustomProviderSetupActivity.java index 9cd46049..520395f8 100644 --- a/app/src/main/java/se/leap/bitmaskclient/providersetup/activities/CustomProviderSetupActivity.java +++ b/app/src/main/java/se/leap/bitmaskclient/providersetup/activities/CustomProviderSetupActivity.java @@ -145,6 +145,7 @@ public class CustomProviderSetupActivity extends ProviderSetupBaseActivity { @Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { + super.onActivityResult(requestCode, resultCode, data); if (requestCode == REQUEST_CODE_CONFIGURE_LEAP) { setResult(resultCode, data); finish(); -- cgit v1.2.3 From 923c51413b577754320667ead42b6393472051b9 Mon Sep 17 00:00:00 2001 From: cyBerta Date: Wed, 25 Oct 2023 16:34:54 +0200 Subject: automatically move to next provider setup fragment after permission dialog was either accepted or rejected --- .../fragments/EmptyPermissionSetupFragment.java | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) (limited to 'app/src/main/java/se') diff --git a/app/src/main/java/se/leap/bitmaskclient/providersetup/fragments/EmptyPermissionSetupFragment.java b/app/src/main/java/se/leap/bitmaskclient/providersetup/fragments/EmptyPermissionSetupFragment.java index 4226d804..849ac681 100644 --- a/app/src/main/java/se/leap/bitmaskclient/providersetup/fragments/EmptyPermissionSetupFragment.java +++ b/app/src/main/java/se/leap/bitmaskclient/providersetup/fragments/EmptyPermissionSetupFragment.java @@ -14,6 +14,7 @@ import androidx.activity.result.contract.ActivityResultContracts; import androidx.annotation.NonNull; import androidx.annotation.Nullable; +import se.leap.bitmaskclient.R; import se.leap.bitmaskclient.databinding.FEmptyPermissionSetupBinding; public class EmptyPermissionSetupFragment extends BaseSetupFragment { @@ -31,9 +32,10 @@ public class EmptyPermissionSetupFragment extends BaseSetupFragment { setupActivityCallback.onConfigurationSuccess(); } } else { - Toast.makeText(getContext(), "Permission request failed :(", Toast.LENGTH_LONG).show(); - setupActivityCallback.setNavigationButtonHidden(false); - // TODO: implement sth. useful + Toast.makeText(getContext(), getText(R.string.permission_rejected), Toast.LENGTH_LONG).show(); + if (setupActivityCallback != null) { + setupActivityCallback.onConfigurationSuccess(); + } } }); @@ -46,9 +48,10 @@ public class EmptyPermissionSetupFragment extends BaseSetupFragment { setupActivityCallback.onConfigurationSuccess(); } } else { - Toast.makeText(getContext(), "Permission request failed :(", Toast.LENGTH_LONG).show(); - setupActivityCallback.setNavigationButtonHidden(false); - // TODO: implement sth. useful + Toast.makeText(getContext(), getText(R.string.permission_rejected), Toast.LENGTH_LONG).show(); + if (setupActivityCallback != null) { + setupActivityCallback.onConfigurationSuccess(); + } } } ); -- cgit v1.2.3 From 2eb98255755f8aff09dd8ab0858072a2037087d0 Mon Sep 17 00:00:00 2001 From: cyBerta Date: Wed, 25 Oct 2023 22:56:53 +0200 Subject: tint action bar toggle in GatewaySelectionFragment --- .../leap/bitmaskclient/base/fragments/GatewaySelectionFragment.java | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'app/src/main/java/se') 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 dc7f64e1..99b1ac39 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 @@ -39,6 +39,7 @@ import android.view.ViewGroup; import androidx.annotation.NonNull; import androidx.annotation.Nullable; import androidx.appcompat.widget.AppCompatTextView; +import androidx.core.content.ContextCompat; import androidx.fragment.app.Fragment; import androidx.recyclerview.widget.LinearLayoutManager; import androidx.recyclerview.widget.RecyclerView; @@ -105,6 +106,10 @@ public class GatewaySelectionFragment extends Fragment implements Observer, Loca initRecommendedLocationEntry(); initBridgesHint(view); setActionBarSubtitle(this, R.string.gateway_selection_title); + Activity activity = getActivity(); + if (activity != null) { + ((MainActivity) activity).setActionBarToggleColor(ContextCompat.getColor(activity, R.color.colorActionBarTitleFont)); + } } @Override -- cgit v1.2.3 From f74107e3c47824e1cf4fdbc415d32871eb85f83c Mon Sep 17 00:00:00 2001 From: cyBerta Date: Thu, 26 Oct 2023 15:57:11 +0200 Subject: fix possible NPE in ProviderSetupObservable --- .../se/leap/bitmaskclient/providersetup/ProviderSetupObservable.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'app/src/main/java/se') 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 56ef357b..90a32fea 100644 --- a/app/src/main/java/se/leap/bitmaskclient/providersetup/ProviderSetupObservable.java +++ b/app/src/main/java/se/leap/bitmaskclient/providersetup/ProviderSetupObservable.java @@ -47,7 +47,7 @@ public class ProviderSetupObservable extends Observable { } public static void updateProgress(int progress) { - if (instance.canceled) { + if (getInstance().canceled) { return; } long now = System.currentTimeMillis(); -- cgit v1.2.3