Handle TorPlugin not being active during mailbox setup

This commit is contained in:
Torsten Grote
2022-02-09 16:32:38 -03:00
parent 237ac50b01
commit 2da8c19d3e
7 changed files with 239 additions and 4 deletions

View File

@@ -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);
}

View File

@@ -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);
}
}

View File

@@ -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
}

View File

@@ -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<MailboxState> 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;

View File

@@ -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();
}
}

View File

@@ -0,0 +1,81 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.core.widget.NestedScrollView 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:layout_width="match_parent"
android:layout_height="match_parent"
android:fillViewport="true">
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<ImageView
android:id="@+id/iconView"
android:layout_width="@dimen/hero_square"
android:layout_height="@dimen/hero_square"
android:layout_marginHorizontal="@dimen/margin_xlarge"
android:layout_marginTop="@dimen/margin_xlarge"
app:layout_constraintBottom_toTopOf="@+id/titleView"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintVertical_bias="0.25"
app:layout_constraintVertical_chainStyle="packed"
app:srcCompat="@drawable/transport_tor"
app:tint="@color/briar_red_500"
tools:ignore="ContentDescription" />
<TextView
android:id="@+id/titleView"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginHorizontal="@dimen/margin_xlarge"
android:layout_marginTop="@dimen/margin_xlarge"
android:gravity="center"
android:text="@string/offline"
android:textAppearance="@style/TextAppearance.MaterialComponents.Headline5"
app:layout_constraintBottom_toTopOf="@+id/textView"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/iconView" />
<TextView
android:id="@+id/textView"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginHorizontal="@dimen/margin_xlarge"
android:layout_marginTop="@dimen/margin_xlarge"
android:layout_marginBottom="@dimen/margin_large"
android:text="@string/tor_offline_description"
android:textAppearance="@style/TextAppearance.MaterialComponents.Body1"
app:layout_constraintBottom_toTopOf="@+id/checkButton"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/titleView" />
<Button
android:id="@+id/checkButton"
style="@style/BriarButtonFlat.Neutral"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_margin="@dimen/margin_large"
android:text="@string/tor_offline_button_check"
app:layout_constraintBottom_toTopOf="@+id/button"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent" />
<Button
android:id="@+id/button"
style="@style/BriarButton"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_margin="@dimen/margin_large"
android:text="@string/try_again_button"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
</androidx.core.widget.NestedScrollView>

View File

@@ -632,6 +632,9 @@
<string name="mailbox_setup_connecting">Connecting…</string>
<string name="mailbox_setup_qr_code_wrong_title">Wrong QR code</string>
<string name="mailbox_setup_qr_code_wrong_description">The scanned code is invalid. Please open the Briar Mailbox app and scan the QR code it presents.</string>
<string name="tor_offline_title">Offline</string>
<string name="tor_offline_description">Ensure that this device is online and connections to the internet are allowed.\n\nAfterwards, wait for the globe icon in connection settings needs to turn green.</string>
<string name="tor_offline_button_check">Check connection settings</string>
<!-- Conversation Settings -->
<string name="disappearing_messages_title">Disappearing messages</string>