From 2da8c19d3e2553c174590328b7f12e71af49d00b Mon Sep 17 00:00:00 2001 From: Torsten Grote Date: Wed, 9 Feb 2022 16:32:38 -0300 Subject: [PATCH] Handle TorPlugin not being active during mailbox setup --- .../briar/android/AndroidComponent.java | 3 + .../android/mailbox/MailboxActivity.java | 7 ++ .../briar/android/mailbox/MailboxState.java | 10 ++ .../android/mailbox/MailboxViewModel.java | 39 ++++++- .../android/mailbox/OfflineFragment.java | 100 ++++++++++++++++++ .../src/main/res/layout/fragment_offline.xml | 81 ++++++++++++++ briar-android/src/main/res/values/strings.xml | 3 + 7 files changed, 239 insertions(+), 4 deletions(-) create mode 100644 briar-android/src/main/java/org/briarproject/briar/android/mailbox/OfflineFragment.java create mode 100644 briar-android/src/main/res/layout/fragment_offline.xml diff --git a/briar-android/src/main/java/org/briarproject/briar/android/AndroidComponent.java b/briar-android/src/main/java/org/briarproject/briar/android/AndroidComponent.java index 82f7d5aae..15506f6bb 100644 --- a/briar-android/src/main/java/org/briarproject/briar/android/AndroidComponent.java +++ b/briar-android/src/main/java/org/briarproject/briar/android/AndroidComponent.java @@ -45,6 +45,7 @@ import org.briarproject.briar.android.hotspot.QrHotspotFragment; import org.briarproject.briar.android.logging.CachingLogHandler; import org.briarproject.briar.android.login.SignInReminderReceiver; import org.briarproject.briar.android.mailbox.MailboxScanFragment; +import org.briarproject.briar.android.mailbox.OfflineFragment; import org.briarproject.briar.android.removabledrive.ChooserFragment; import org.briarproject.briar.android.removabledrive.ReceiveFragment; import org.briarproject.briar.android.removabledrive.SendFragment; @@ -242,4 +243,6 @@ public interface AndroidComponent void inject(BluetoothIntroFragment bluetoothIntroFragment); void inject(MailboxScanFragment mailboxScanFragment); + + void inject(OfflineFragment offlineFragment); } diff --git a/briar-android/src/main/java/org/briarproject/briar/android/mailbox/MailboxActivity.java b/briar-android/src/main/java/org/briarproject/briar/android/mailbox/MailboxActivity.java index 53a2aebde..03cc51f84 100644 --- a/briar-android/src/main/java/org/briarproject/briar/android/mailbox/MailboxActivity.java +++ b/briar-android/src/main/java/org/briarproject/briar/android/mailbox/MailboxActivity.java @@ -55,6 +55,8 @@ public class MailboxActivity extends BriarActivity { onCodeScanned(); } else if (state instanceof MailboxState.QrCodeWrong) { onQrCodeWrong(); + } else if (state instanceof MailboxState.OfflineInSetup) { + onOffline(); } }); } @@ -100,4 +102,9 @@ public class MailboxActivity extends BriarActivity { showFragment(getSupportFragmentManager(), f, ErrorFragment.TAG); } + private void onOffline() { + showFragment(getSupportFragmentManager(), new OfflineFragment(), + OfflineFragment.TAG); + } + } diff --git a/briar-android/src/main/java/org/briarproject/briar/android/mailbox/MailboxState.java b/briar-android/src/main/java/org/briarproject/briar/android/mailbox/MailboxState.java index e8deb1df2..b775653aa 100644 --- a/briar-android/src/main/java/org/briarproject/briar/android/mailbox/MailboxState.java +++ b/briar-android/src/main/java/org/briarproject/briar/android/mailbox/MailboxState.java @@ -1,5 +1,7 @@ package org.briarproject.briar.android.mailbox; +import org.briarproject.bramble.api.mailbox.MailboxProperties; + class MailboxState { static class NotSetup extends MailboxState { @@ -11,6 +13,14 @@ class MailboxState { static class QrCodeWrong extends MailboxState { } + static class OfflineInSetup extends MailboxState { + final MailboxProperties mailboxProperties; + + OfflineInSetup(MailboxProperties mailboxProperties) { + this.mailboxProperties = mailboxProperties; + } + } + // TODO add other states } diff --git a/briar-android/src/main/java/org/briarproject/briar/android/mailbox/MailboxViewModel.java b/briar-android/src/main/java/org/briarproject/briar/android/mailbox/MailboxViewModel.java index 1f4c657ff..3d833cc4c 100644 --- a/briar-android/src/main/java/org/briarproject/briar/android/mailbox/MailboxViewModel.java +++ b/briar-android/src/main/java/org/briarproject/briar/android/mailbox/MailboxViewModel.java @@ -13,6 +13,9 @@ import org.briarproject.bramble.api.lifecycle.LifecycleManager; import org.briarproject.bramble.api.mailbox.MailboxAuthToken; import org.briarproject.bramble.api.mailbox.MailboxProperties; import org.briarproject.bramble.api.nullsafety.NotNullByDefault; +import org.briarproject.bramble.api.plugin.Plugin; +import org.briarproject.bramble.api.plugin.PluginManager; +import org.briarproject.bramble.api.plugin.TorConstants; import org.briarproject.bramble.api.system.AndroidExecutor; import org.briarproject.briar.android.mailbox.MailboxState.NotSetup; import org.briarproject.briar.android.qrcode.QrCodeDecoder; @@ -29,8 +32,10 @@ import androidx.annotation.UiThread; import androidx.lifecycle.LiveData; import androidx.lifecycle.MutableLiveData; +import static java.util.Objects.requireNonNull; import static java.util.logging.Level.WARNING; import static java.util.logging.Logger.getLogger; +import static org.briarproject.bramble.api.plugin.Plugin.State.ACTIVE; @NotNullByDefault class MailboxViewModel extends DbViewModel @@ -45,6 +50,7 @@ class MailboxViewModel extends DbViewModel private final CryptoComponent crypto; private final QrCodeDecoder qrCodeDecoder; + private final PluginManager pluginManager; private final MutableLiveData state = new MutableLiveData<>(); @@ -56,9 +62,11 @@ class MailboxViewModel extends DbViewModel TransactionManager db, AndroidExecutor androidExecutor, @IoExecutor Executor ioExecutor, - CryptoComponent crypto) { + CryptoComponent crypto, + PluginManager pluginManager) { super(app, dbExecutor, lifecycleManager, db, androidExecutor); this.crypto = crypto; + this.pluginManager = pluginManager; qrCodeDecoder = new QrCodeDecoder(androidExecutor, ioExecutor, this); checkIfSetup(); } @@ -80,16 +88,17 @@ class MailboxViewModel extends DbViewModel @IoExecutor public void onQrCodeDecoded(Result result) { LOG.info("Got result from decoder"); + MailboxProperties properties; try { - // TODO pass props to core (maybe even do payload parsing there) - MailboxProperties properties = decodeQrCode(result.getText()); + properties = decodeQrCode(result.getText()); } catch (FormatException e) { state.postValue(new MailboxState.QrCodeWrong()); return; } - state.postValue(new MailboxState.SettingUp()); + onMailboxPropertiesReceived(properties); } + // TODO move this into core #2168 private MailboxProperties decodeQrCode(String payload) throws FormatException { byte[] bytes = payload.getBytes(ISO_8859_1); @@ -115,6 +124,28 @@ class MailboxViewModel extends DbViewModel return new MailboxProperties(onionAddress, setupToken, true); } + private void onMailboxPropertiesReceived(MailboxProperties properties) { + if (isTorActive()) { + // TODO pass props to core #2168 + state.postValue(new MailboxState.SettingUp()); + } else { + state.postValue(new MailboxState.OfflineInSetup(properties)); + } + } + + // TODO ideally also move this into core #2168 + private boolean isTorActive() { + Plugin plugin = pluginManager.getPlugin(TorConstants.ID); + return plugin != null && plugin.getState() == ACTIVE; + } + + @UiThread + void tryAgainWhenOffline() { + MailboxState.OfflineInSetup offline = + (MailboxState.OfflineInSetup) requireNonNull(state.getValue()); + onMailboxPropertiesReceived(offline.mailboxProperties); + } + @UiThread QrCodeDecoder getQrCodeDecoder() { return qrCodeDecoder; diff --git a/briar-android/src/main/java/org/briarproject/briar/android/mailbox/OfflineFragment.java b/briar-android/src/main/java/org/briarproject/briar/android/mailbox/OfflineFragment.java new file mode 100644 index 000000000..0e99b6a93 --- /dev/null +++ b/briar-android/src/main/java/org/briarproject/briar/android/mailbox/OfflineFragment.java @@ -0,0 +1,100 @@ +package org.briarproject.briar.android.mailbox; + +import android.content.Context; +import android.content.Intent; +import android.os.Bundle; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.Button; +import android.widget.TextView; + +import org.briarproject.bramble.api.nullsafety.MethodsNotNullByDefault; +import org.briarproject.bramble.api.nullsafety.ParametersNotNullByDefault; +import org.briarproject.briar.R; +import org.briarproject.briar.android.navdrawer.TransportsActivity; + +import javax.inject.Inject; + +import androidx.activity.OnBackPressedCallback; +import androidx.annotation.Nullable; +import androidx.appcompat.app.ActionBar; +import androidx.appcompat.app.AppCompatActivity; +import androidx.core.widget.NestedScrollView; +import androidx.fragment.app.Fragment; +import androidx.fragment.app.FragmentActivity; +import androidx.lifecycle.ViewModelProvider; + +import static android.view.View.FOCUS_DOWN; +import static org.briarproject.briar.android.AppModule.getAndroidComponent; + +@MethodsNotNullByDefault +@ParametersNotNullByDefault +public class OfflineFragment extends Fragment { + + public static final String TAG = OfflineFragment.class.getName(); + + @Inject + ViewModelProvider.Factory viewModelFactory; + + private MailboxViewModel viewModel; + + private NestedScrollView scrollView; + protected Button buttonView; + + @Override + public void onAttach(Context context) { + super.onAttach(context); + FragmentActivity activity = requireActivity(); + getAndroidComponent(activity).inject(this); + viewModel = new ViewModelProvider(activity, viewModelFactory) + .get(MailboxViewModel.class); + } + + @Nullable + @Override + public View onCreateView(LayoutInflater inflater, + @Nullable ViewGroup container, + @Nullable Bundle savedInstanceState) { + View v = inflater + .inflate(R.layout.fragment_offline, container, false); + + scrollView = (NestedScrollView) v; + TextView titleView = v.findViewById(R.id.titleView); + Button checkButton = v.findViewById(R.id.checkButton); + checkButton.setOnClickListener(view -> { + Intent i = new Intent(requireContext(), TransportsActivity.class); + startActivity(i); + }); + buttonView = v.findViewById(R.id.button); + buttonView.setOnClickListener(view -> viewModel.tryAgainWhenOffline()); + + AppCompatActivity a = (AppCompatActivity) requireActivity(); + a.setTitle(titleView.getText()); + ActionBar actionBar = a.getSupportActionBar(); + if (actionBar != null) { + actionBar.setDisplayHomeAsUpEnabled(false); + actionBar.setHomeButtonEnabled(false); + } + a.getOnBackPressedDispatcher().addCallback( + getViewLifecycleOwner(), new OnBackPressedCallback(true) { + @Override + public void handleOnBackPressed() { + onBackButtonPressed(); + } + }); + return v; + } + + @Override + public void onStart() { + super.onStart(); + // Scroll down in case the screen is small, so the button is visible + scrollView.post(() -> scrollView.fullScroll(FOCUS_DOWN)); + } + + private void onBackButtonPressed() { + requireActivity().supportFinishAfterTransition(); + } + +} diff --git a/briar-android/src/main/res/layout/fragment_offline.xml b/briar-android/src/main/res/layout/fragment_offline.xml new file mode 100644 index 000000000..f45a23d33 --- /dev/null +++ b/briar-android/src/main/res/layout/fragment_offline.xml @@ -0,0 +1,81 @@ + + + + + + + + + + + +