Handle scanning a wrong QR code

when pairing a mailbox.
This commit is contained in:
Torsten Grote
2022-02-09 15:24:02 -03:00
parent 73d9e05ada
commit 237ac50b01
9 changed files with 100 additions and 43 deletions

View File

@@ -181,12 +181,6 @@ public abstract class BaseActivity extends AppCompatActivity
showFragment(getSupportFragmentManager(), f, f.getUniqueTag());
}
protected boolean isFragmentAdded(String fragmentTag) {
FragmentManager fm = getSupportFragmentManager();
Fragment f = fm.findFragmentByTag(fragmentTag);
return f != null && f.isAdded();
}
private boolean showScreenFilterWarning() {
if (((BriarApplication) getApplication()).isInstrumentationTest()) {
return false;

View File

@@ -56,13 +56,9 @@ public class HotspotActivity extends BriarActivity
if (hotspotState instanceof HotspotStarted) {
HotspotStarted started = (HotspotStarted) hotspotState;
String tag = HotspotFragment.TAG;
// check if fragment is already added
// to not lose state on configuration changes
if (fm.findFragmentByTag(tag) == null) {
if (started.wasNotYetConsumed()) {
started.consume();
showFragment(fm, new HotspotFragment(), tag);
}
if (started.wasNotYetConsumed()) {
started.consume();
showFragment(fm, new HotspotFragment(), tag);
}
} else if (hotspotState instanceof HotspotError) {
HotspotError error = (HotspotError) hotspotState;
@@ -116,10 +112,8 @@ public class HotspotActivity extends BriarActivity
private void showErrorFragment(String error) {
FragmentManager fm = getSupportFragmentManager();
String tag = HotspotErrorFragment.TAG;
if (fm.findFragmentByTag(tag) == null) {
Fragment f = HotspotErrorFragment.newInstance(error);
showFragment(fm, f, tag, false);
}
Fragment f = HotspotErrorFragment.newInstance(error);
showFragment(fm, f, tag, false);
}
@Override

View File

@@ -85,16 +85,10 @@ public class StartupActivity extends BaseActivity implements
if (state == SIGNED_OUT) {
// Configuration changes such as screen rotation
// can cause this to get called again.
// Don't replace the fragment in that case to not lose view state.
if (!isFragmentAdded(PasswordFragment.TAG)) {
showInitialFragment(new PasswordFragment());
}
showInitialFragment(new PasswordFragment());
} else if (state == SIGNED_IN || state == STARTING) {
startService(new Intent(this, BriarService.class));
// Only show OpenDatabaseFragment if not already visible.
if (!isFragmentAdded(OpenDatabaseFragment.TAG)) {
showNextFragment(new OpenDatabaseFragment());
}
showNextFragment(new OpenDatabaseFragment());
} else if (state == STARTED) {
setResult(RESULT_OK);
supportFinishAfterTransition();

View File

@@ -0,0 +1,47 @@
package org.briarproject.briar.android.mailbox;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import org.briarproject.bramble.api.nullsafety.MethodsNotNullByDefault;
import org.briarproject.bramble.api.nullsafety.ParametersNotNullByDefault;
import org.briarproject.briar.R;
import org.briarproject.briar.android.fragment.FinalFragment;
import androidx.annotation.Nullable;
import androidx.annotation.StringRes;
@MethodsNotNullByDefault
@ParametersNotNullByDefault
public class ErrorFragment extends FinalFragment {
public static ErrorFragment newInstance(@StringRes int title,
@StringRes int text) {
ErrorFragment f = new ErrorFragment();
Bundle args = new Bundle();
args.putInt(ARG_TITLE, title);
args.putInt(ARG_ICON, R.drawable.alerts_and_states_error);
args.putInt(ARG_ICON_TINT, R.color.briar_red_500);
args.putInt(ARG_TEXT, text);
f.setArguments(args);
return f;
}
@Nullable
@Override
public View onCreateView(LayoutInflater inflater,
@Nullable ViewGroup container,
@Nullable Bundle savedInstanceState) {
View v = super.onCreateView(inflater, container, savedInstanceState);
buttonView.setText(R.string.try_again_button);
return v;
}
@Override
protected void onBackButtonPressed() {
requireActivity().getSupportFragmentManager().popBackStack();
}
}

View File

@@ -13,6 +13,7 @@ import org.briarproject.briar.android.activity.BriarActivity;
import javax.inject.Inject;
import androidx.annotation.Nullable;
import androidx.fragment.app.Fragment;
import androidx.lifecycle.ViewModelProvider;
import static android.view.View.INVISIBLE;
@@ -49,9 +50,11 @@ public class MailboxActivity extends BriarActivity {
viewModel.getState().observe(this, state -> {
if (state instanceof MailboxState.NotSetup) {
if (savedInstanceState == null) onNotSetup();
onNotSetup();
} else if (state instanceof MailboxState.SettingUp) {
onCodeScanned();
} else if (state instanceof MailboxState.QrCodeWrong) {
onQrCodeWrong();
}
});
}
@@ -90,4 +93,11 @@ public class MailboxActivity extends BriarActivity {
MailboxConnectingFragment.TAG, false);
}
private void onQrCodeWrong() {
Fragment f = ErrorFragment.newInstance(
R.string.mailbox_setup_qr_code_wrong_title,
R.string.mailbox_setup_qr_code_wrong_description);
showFragment(getSupportFragmentManager(), f, ErrorFragment.TAG);
}
}

View File

@@ -8,6 +8,9 @@ class MailboxState {
static class SettingUp extends MailboxState {
}
static class QrCodeWrong extends MailboxState {
}
// TODO add other states
}

View File

@@ -4,6 +4,7 @@ import android.app.Application;
import com.google.zxing.Result;
import org.briarproject.bramble.api.FormatException;
import org.briarproject.bramble.api.crypto.CryptoComponent;
import org.briarproject.bramble.api.db.DatabaseExecutor;
import org.briarproject.bramble.api.db.TransactionManager;
@@ -28,7 +29,7 @@ import androidx.annotation.UiThread;
import androidx.lifecycle.LiveData;
import androidx.lifecycle.MutableLiveData;
import static java.util.logging.Level.INFO;
import static java.util.logging.Level.WARNING;
import static java.util.logging.Logger.getLogger;
@NotNullByDefault
@@ -79,31 +80,39 @@ class MailboxViewModel extends DbViewModel
@IoExecutor
public void onQrCodeDecoded(Result result) {
LOG.info("Got result from decoder");
byte[] bytes = result.getText().getBytes(ISO_8859_1);
try {
// TODO pass props to core (maybe even do payload parsing there)
MailboxProperties properties = decodeQrCode(result.getText());
} catch (FormatException e) {
state.postValue(new MailboxState.QrCodeWrong());
return;
}
state.postValue(new MailboxState.SettingUp());
}
if (LOG.isLoggable(INFO))
LOG.info("QR code length in bytes: " + bytes.length);
private MailboxProperties decodeQrCode(String payload)
throws FormatException {
byte[] bytes = payload.getBytes(ISO_8859_1);
if (bytes.length != 65) {
LOG.info("QR code has wrong length");
return;
if (LOG.isLoggable(WARNING)) {
LOG.warning("QR code length is not 65: " + bytes.length);
}
throw new FormatException();
}
if (LOG.isLoggable(INFO))
LOG.info("QR code version: " + bytes[0]);
if (bytes[0] != VERSION_REQUIRED) {
LOG.info("QR code has wrong version");
return;
int version = bytes[0] & 0xFF;
if (version != VERSION_REQUIRED) {
if (LOG.isLoggable(WARNING)) {
LOG.warning("QR code has not version " + VERSION_REQUIRED +
": " + version);
}
throw new FormatException();
}
LOG.info("QR code is valid");
byte[] onionPubKey = Arrays.copyOfRange(bytes, 1, 33);
String onionAddress = crypto.encodeOnionAddress(onionPubKey);
byte[] tokenBytes = Arrays.copyOfRange(bytes, 33, 65);
MailboxAuthToken setupToken = new MailboxAuthToken(tokenBytes);
MailboxProperties props =
new MailboxProperties(onionAddress, setupToken, true);
// TODO pass props to core (maybe even do payload parsing there)
state.postValue(new MailboxState.SettingUp());
return new MailboxProperties(onionAddress, setupToken, true);
}
@UiThread

View File

@@ -147,6 +147,10 @@ public class UiUtils {
public static void showFragment(FragmentManager fm, Fragment f,
@Nullable String tag, boolean addToBackStack) {
// don't re-add same (already added/visible) fragment again
Fragment fragment = fm.findFragmentByTag(tag);
if (fragment != null && fragment.isAdded()) return;
FragmentTransaction ta = fm.beginTransaction()
.setCustomAnimations(R.anim.step_next_in,
R.anim.step_previous_out, R.anim.step_previous_in,