Show success fragment on recovering account

This commit is contained in:
ameba23
2021-04-23 13:18:47 +02:00
parent acb9b18507
commit 3d34a36908
10 changed files with 161 additions and 31 deletions

View File

@@ -85,6 +85,7 @@ import org.briarproject.briar.android.socialbackup.CustodianSelectorFragment;
import org.briarproject.briar.android.socialbackup.DistributedBackupActivity; import org.briarproject.briar.android.socialbackup.DistributedBackupActivity;
import org.briarproject.briar.android.socialbackup.ExistingBackupFragment; import org.briarproject.briar.android.socialbackup.ExistingBackupFragment;
import org.briarproject.briar.android.socialbackup.recover.CustodianReturnShardActivity; import org.briarproject.briar.android.socialbackup.recover.CustodianReturnShardActivity;
import org.briarproject.briar.android.socialbackup.recover.CustodianReturnShardErrorFragment;
import org.briarproject.briar.android.socialbackup.recover.CustodianReturnShardFragment; import org.briarproject.briar.android.socialbackup.recover.CustodianReturnShardFragment;
import org.briarproject.briar.android.socialbackup.recover.CustodianReturnShardSuccessFragment; import org.briarproject.briar.android.socialbackup.recover.CustodianReturnShardSuccessFragment;
import org.briarproject.briar.android.socialbackup.recover.OwnerRecoveryModeExplainerFragment; import org.briarproject.briar.android.socialbackup.recover.OwnerRecoveryModeExplainerFragment;
@@ -94,6 +95,7 @@ import org.briarproject.briar.android.socialbackup.recover.OwnerReturnShardFragm
import org.briarproject.briar.android.socialbackup.ShardsSentFragment; import org.briarproject.briar.android.socialbackup.ShardsSentFragment;
import org.briarproject.briar.android.socialbackup.ThresholdSelectorFragment; import org.briarproject.briar.android.socialbackup.ThresholdSelectorFragment;
import org.briarproject.briar.android.socialbackup.creation.CreateBackupModule; import org.briarproject.briar.android.socialbackup.creation.CreateBackupModule;
import org.briarproject.briar.android.socialbackup.recover.OwnerReturnShardSuccessFragment;
import org.briarproject.briar.android.socialbackup.recover.RestoreAccountActivity; import org.briarproject.briar.android.socialbackup.recover.RestoreAccountActivity;
import org.briarproject.briar.android.socialbackup.recover.RestoreAccountDozeFragment; import org.briarproject.briar.android.socialbackup.recover.RestoreAccountDozeFragment;
import org.briarproject.briar.android.socialbackup.recover.RestoreAccountSetPasswordFragment; import org.briarproject.briar.android.socialbackup.recover.RestoreAccountSetPasswordFragment;
@@ -297,4 +299,8 @@ public interface ActivityComponent {
void inject(RestoreAccountSetPasswordFragment restoreAccountSetPasswordFragment); void inject(RestoreAccountSetPasswordFragment restoreAccountSetPasswordFragment);
void inject(RestoreAccountDozeFragment restoreAccountDozeFragment); void inject(RestoreAccountDozeFragment restoreAccountDozeFragment);
void inject(OwnerReturnShardSuccessFragment ownerReturnShardSuccessFragment);
void inject(CustodianReturnShardErrorFragment custodianReturnShardErrorFragment);
} }

View File

@@ -59,6 +59,8 @@ public class CustodianReturnShardActivity extends BriarActivity
Toast.makeText(this, Toast.makeText(this,
"It looks like you are not connected to a Wifi network", "It looks like you are not connected to a Wifi network",
Toast.LENGTH_SHORT).show(); Toast.LENGTH_SHORT).show();
showNextFragment(new CustodianReturnShardErrorFragment());
return;
} catch (DbException e) { } catch (DbException e) {
Toast.makeText(this, Toast.makeText(this,
"You do not hold a backup piece for this contact", "You do not hold a backup piece for this contact",

View File

@@ -1,6 +1,58 @@
package org.briarproject.briar.android.socialbackup.recover; package org.briarproject.briar.android.socialbackup.recover;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import org.briarproject.bramble.api.nullsafety.MethodsNotNullByDefault;
import org.briarproject.bramble.api.nullsafety.ParametersNotNullByDefault;
import org.briarproject.briar.R;
import org.briarproject.briar.android.activity.ActivityComponent;
import org.briarproject.briar.android.fragment.BaseFragment; import org.briarproject.briar.android.fragment.BaseFragment;
import javax.inject.Inject;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.lifecycle.ViewModelProvider;
@MethodsNotNullByDefault
@ParametersNotNullByDefault
public class CustodianReturnShardErrorFragment extends BaseFragment { public class CustodianReturnShardErrorFragment extends BaseFragment {
public static final String TAG =
CustodianReturnShardErrorFragment.class.getName();
@Inject
ViewModelProvider.Factory viewModelFactory;
private CustodianReturnShardViewModel viewModel;
@Override
public void injectFragment(ActivityComponent component) {
component.inject(this);
viewModel = new ViewModelProvider(requireActivity(), viewModelFactory)
.get(CustodianReturnShardViewModel.class);
}
@Nullable
@Override
public View onCreateView(@NonNull LayoutInflater inflater,
@Nullable ViewGroup container,
@Nullable Bundle savedInstanceState) {
// TODO change fragment to error
View view = inflater.inflate(R.layout.fragment_recovery_custodian_done,
container, false);
Button button = view.findViewById(R.id.button);
button.setOnClickListener(e -> viewModel.onErrorCancelled());
// TODO try again button
return view;
}
@Override
public String getUniqueTag() {
return TAG;
}
} }

View File

@@ -58,6 +58,7 @@ public class CustodianReturnShardViewModel extends AndroidViewModel
new MutableLiveEvent<>(); new MutableLiveEvent<>();
private final MutableLiveEvent<Boolean> successDismissed = private final MutableLiveEvent<Boolean> successDismissed =
new MutableLiveEvent<>(); new MutableLiveEvent<>();
private final MutableLiveEvent<Boolean> errorTryAgain = new MutableLiveEvent<>();
private final MutableLiveData<CustodianTask.State> state = private final MutableLiveData<CustodianTask.State> state =
new MutableLiveData<>(); new MutableLiveData<>();
private final CustodianTask task; private final CustodianTask task;
@@ -156,6 +157,16 @@ public class CustodianReturnShardViewModel extends AndroidViewModel
showCameraFragment.setEvent(true); showCameraFragment.setEvent(true);
} }
@UiThread
public void onErrorCancelled() {
errorTryAgain.postEvent(false);
}
@UiThread
public void onErrorTryAgain() {
errorTryAgain.postEvent(true);
}
@UiThread @UiThread
public void onSuccessDismissed() { public void onSuccessDismissed() {
successDismissed.setEvent(true); successDismissed.setEvent(true);
@@ -186,4 +197,8 @@ public class CustodianReturnShardViewModel extends AndroidViewModel
qrCodeRead = true; qrCodeRead = true;
} }
} }
public MutableLiveEvent<Boolean> getErrorTryAgain() {
return errorTryAgain;
}
} }

View File

@@ -77,6 +77,9 @@ public class OwnerReturnShardActivity extends BaseActivity
showNextFragment(new OwnerRecoveryModeMainFragment()); showNextFragment(new OwnerRecoveryModeMainFragment());
} }
}); });
viewModel.getSuccessDismissed().observeEvent(this, success -> {
if (success) onSuccessDismissed();
});
viewModel.getState() viewModel.getState()
.observe(this, this::onReturnShardStateChanged); .observe(this, this::onReturnShardStateChanged);
} }
@@ -125,6 +128,13 @@ public class OwnerReturnShardActivity extends BaseActivity
} }
} }
private void onSuccessDismissed() {
finish();
Intent i = new Intent(this, RestoreAccountActivity.class);
i.addFlags(FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_CLEAR_TOP |
FLAG_ACTIVITY_CLEAR_TASK | FLAG_ACTIVITY_TASK_ON_HOME);
startActivity(i);
}
private void onReturnShardStateChanged(SecretOwnerTask.State state) { private void onReturnShardStateChanged(SecretOwnerTask.State state) {
if (state instanceof SecretOwnerTask.State.Success) { if (state instanceof SecretOwnerTask.State.Success) {
@@ -136,9 +146,8 @@ public class OwnerReturnShardActivity extends BaseActivity
Toast.LENGTH_SHORT).show(); Toast.LENGTH_SHORT).show();
if (added && viewModel.canRecover()) { if (added && viewModel.canRecover()) {
LOG.info("Secret key recovered"); LOG.info("Secret key recovered");
int version = 0;
try { try {
version = viewModel.recover(); viewModel.recover();
} catch (GeneralSecurityException e) { } catch (GeneralSecurityException e) {
LOG.warning("Unable to decrypt backup" + e.toString()); LOG.warning("Unable to decrypt backup" + e.toString());
Toast.makeText(this, Toast.makeText(this,
@@ -153,15 +162,7 @@ public class OwnerReturnShardActivity extends BaseActivity
Toast.LENGTH_LONG).show(); Toast.LENGTH_LONG).show();
return; return;
} }
Toast.makeText(this, showNextFragment(new OwnerReturnShardSuccessFragment());
"Account recovered! " + version,
Toast.LENGTH_LONG).show();
finish();
// TODO Success fragment
Intent i = new Intent(this, RestoreAccountActivity.class);
i.addFlags(FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_CLEAR_TOP |
FLAG_ACTIVITY_CLEAR_TASK | FLAG_ACTIVITY_TASK_ON_HOME);
startActivity(i);
return; return;
} }
onBackPressed(); onBackPressed();

View File

@@ -1,6 +1,54 @@
package org.briarproject.briar.android.socialbackup.recover; package org.briarproject.briar.android.socialbackup.recover;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import org.briarproject.briar.R;
import org.briarproject.briar.android.activity.ActivityComponent;
import org.briarproject.briar.android.fragment.BaseFragment; import org.briarproject.briar.android.fragment.BaseFragment;
import javax.inject.Inject;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.lifecycle.ViewModelProvider;
public class OwnerReturnShardSuccessFragment extends BaseFragment { public class OwnerReturnShardSuccessFragment extends BaseFragment {
public static final String TAG =
OwnerReturnShardSuccessFragment.class.getName();
@Inject
ViewModelProvider.Factory viewModelFactory;
private OwnerReturnShardViewModel viewModel;
@Override
public void injectFragment(ActivityComponent component) {
component.inject(this);
viewModel = new ViewModelProvider(requireActivity(), viewModelFactory)
.get(OwnerReturnShardViewModel.class);
}
@Nullable
@Override
public View onCreateView(@NonNull LayoutInflater inflater,
@Nullable ViewGroup container,
@Nullable Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_recovery_custodian_done,
container, false);
Button button = view.findViewById(R.id.button);
button.setOnClickListener(e -> viewModel.onSuccessDismissed());
return view;
}
@Override
public String getUniqueTag() {
return TAG;
}
} }

View File

@@ -14,19 +14,14 @@ import org.briarproject.bramble.api.system.AndroidExecutor;
import org.briarproject.briar.android.contact.add.nearby.QrCodeUtils; import org.briarproject.briar.android.contact.add.nearby.QrCodeUtils;
import org.briarproject.briar.android.viewmodel.LiveEvent; import org.briarproject.briar.android.viewmodel.LiveEvent;
import org.briarproject.briar.android.viewmodel.MutableLiveEvent; import org.briarproject.briar.android.viewmodel.MutableLiveEvent;
import org.briarproject.briar.api.socialbackup.BackupPayload;
import org.briarproject.briar.api.socialbackup.ReturnShardPayload; import org.briarproject.briar.api.socialbackup.ReturnShardPayload;
import org.briarproject.briar.api.socialbackup.Shard;
import org.briarproject.briar.api.socialbackup.recovery.RestoreAccount; import org.briarproject.briar.api.socialbackup.recovery.RestoreAccount;
import org.briarproject.briar.api.socialbackup.recovery.SecretOwnerTask; import org.briarproject.briar.api.socialbackup.recovery.SecretOwnerTask;
import org.briarproject.briar.socialbackup.BackupPayloadDecoder;
import org.briarproject.briar.api.socialbackup.SocialBackup;
import java.net.InetAddress; import java.net.InetAddress;
import java.net.UnknownHostException; import java.net.UnknownHostException;
import java.nio.charset.Charset; import java.nio.charset.Charset;
import java.security.GeneralSecurityException; import java.security.GeneralSecurityException;
import java.util.ArrayList;
import java.util.concurrent.Executor; import java.util.concurrent.Executor;
import java.util.logging.Logger; import java.util.logging.Logger;
@@ -51,8 +46,6 @@ class OwnerReturnShardViewModel extends AndroidViewModel
@SuppressWarnings("CharsetObjectCanBeUsed") // Requires minSdkVersion >= 19 @SuppressWarnings("CharsetObjectCanBeUsed") // Requires minSdkVersion >= 19
private static final Charset ISO_8859_1 = Charset.forName("ISO-8859-1"); private static final Charset ISO_8859_1 = Charset.forName("ISO-8859-1");
// private ReturnShardPayload returnShardPayload;
private final AndroidExecutor androidExecutor; private final AndroidExecutor androidExecutor;
private final Executor ioExecutor; private final Executor ioExecutor;
private final SecretOwnerTask task; private final SecretOwnerTask task;
@@ -60,6 +53,7 @@ class OwnerReturnShardViewModel extends AndroidViewModel
private final MutableLiveEvent<Boolean> showQrCodeFragment = private final MutableLiveEvent<Boolean> showQrCodeFragment =
new MutableLiveEvent<>(); new MutableLiveEvent<>();
private final MutableLiveEvent<Boolean> successDismissed = new MutableLiveEvent<>();
private final MutableLiveData<SecretOwnerTask.State> state = private final MutableLiveData<SecretOwnerTask.State> state =
new MutableLiveData<>(); new MutableLiveData<>();
private final MutableLiveEvent<Boolean> startClicked = private final MutableLiveEvent<Boolean> startClicked =
@@ -128,6 +122,11 @@ class OwnerReturnShardViewModel extends AndroidViewModel
startShardReturn(); startShardReturn();
} }
@UiThread
void onSuccessDismissed() {
successDismissed.setEvent(true);
}
@UiThread @UiThread
void startShardReturn() { void startShardReturn() {
// If we return to the intro fragment, the continue button needs to be // If we return to the intro fragment, the continue button needs to be
@@ -233,4 +232,8 @@ class OwnerReturnShardViewModel extends AndroidViewModel
public int recover() throws FormatException, GeneralSecurityException { public int recover() throws FormatException, GeneralSecurityException {
return restoreAccount.recover(); return restoreAccount.recover();
} }
public MutableLiveEvent<Boolean> getSuccessDismissed() {
return successDismissed;
}
} }

View File

@@ -7,7 +7,6 @@ import android.os.Bundle;
import org.briarproject.bramble.api.nullsafety.MethodsNotNullByDefault; import org.briarproject.bramble.api.nullsafety.MethodsNotNullByDefault;
import org.briarproject.bramble.api.nullsafety.ParametersNotNullByDefault; import org.briarproject.bramble.api.nullsafety.ParametersNotNullByDefault;
import org.briarproject.briar.R; import org.briarproject.briar.R;
import org.briarproject.briar.android.account.DozeFragment;
import org.briarproject.briar.android.activity.ActivityComponent; import org.briarproject.briar.android.activity.ActivityComponent;
import org.briarproject.briar.android.activity.BaseActivity; import org.briarproject.briar.android.activity.BaseActivity;
import org.briarproject.briar.android.fragment.BaseFragment; import org.briarproject.briar.android.fragment.BaseFragment;
@@ -61,7 +60,7 @@ public class RestoreAccountActivity extends BaseActivity
@TargetApi(23) @TargetApi(23)
void showDozeFragment() { void showDozeFragment() {
showNextFragment(DozeFragment.newInstance()); showNextFragment(RestoreAccountDozeFragment.newInstance());
} }
void showApp() { void showApp() {

View File

@@ -30,7 +30,7 @@ import static org.briarproject.briar.android.util.UiUtils.showOnboardingDialog;
public class RestoreAccountDozeFragment extends RestoreAccountFragment public class RestoreAccountDozeFragment extends RestoreAccountFragment
implements PowerView.OnCheckedChangedListener { implements PowerView.OnCheckedChangedListener {
private final static String TAG = org.briarproject.briar.android.account.DozeFragment.class.getName(); private final static String TAG = RestoreAccountDozeFragment.class.getName();
private DozeView dozeView; private DozeView dozeView;
private HuaweiView huaweiView; private HuaweiView huaweiView;

View File

@@ -30,7 +30,8 @@ import static java.util.logging.Logger.getLogger;
@MethodsNotNullByDefault @MethodsNotNullByDefault
@ParametersNotNullByDefault @ParametersNotNullByDefault
class RestoreAccountViewModel extends AndroidViewModel { class RestoreAccountViewModel extends AndroidViewModel implements RestoreAccount.Observer {
enum State {SET_PASSWORD, DOZE, CREATED, FAILED} enum State {SET_PASSWORD, DOZE, CREATED, FAILED}
private static final Logger LOG = private static final Logger LOG =
@@ -116,19 +117,12 @@ class RestoreAccountViewModel extends AndroidViewModel {
ioExecutor.execute(() -> { ioExecutor.execute(() -> {
if (accountManager.restoreAccount(identity, password)) { if (accountManager.restoreAccount(identity, password)) {
LOG.info("Restored account"); LOG.info("Restored account");
try { try {
restoreAccount.addContactsToDb(); restoreAccount.addContactsToDb(this);
} catch (InterruptedException e) {
LOG.warning("Process interrupted when waiting for db to open");
state.postEvent(State.FAILED);
return;
} catch (DbException e) { } catch (DbException e) {
LOG.warning("DbException when adding contacts"); LOG.warning("Cannot retrieve social backup");
state.postEvent(State.FAILED); state.postEvent(State.FAILED);
return;
} }
LOG.info("Added recovered contacts to database");
state.postEvent(State.CREATED); state.postEvent(State.CREATED);
} else { } else {
LOG.warning("Failed to create account"); LOG.warning("Failed to create account");
@@ -136,4 +130,14 @@ class RestoreAccountViewModel extends AndroidViewModel {
} }
}); });
} }
@Override
public void onAddingContactsFinished(boolean success) {
if (success) {
LOG.info("Added recovered contacts to database");
} else {
LOG.warning("Error when adding contacts to database");
// state.postEvent(State.FAILED);
}
}
} }