diff --git a/briar-android/src/main/java/org/briarproject/briar/android/activity/ActivityComponent.java b/briar-android/src/main/java/org/briarproject/briar/android/activity/ActivityComponent.java index f441e651b..d0b7234b9 100644 --- a/briar-android/src/main/java/org/briarproject/briar/android/activity/ActivityComponent.java +++ b/briar-android/src/main/java/org/briarproject/briar/android/activity/ActivityComponent.java @@ -85,6 +85,7 @@ import org.briarproject.briar.android.socialbackup.CustodianSelectorFragment; import org.briarproject.briar.android.socialbackup.DistributedBackupActivity; import org.briarproject.briar.android.socialbackup.ExistingBackupFragment; 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.CustodianReturnShardSuccessFragment; 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.ThresholdSelectorFragment; 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.RestoreAccountDozeFragment; import org.briarproject.briar.android.socialbackup.recover.RestoreAccountSetPasswordFragment; @@ -297,4 +299,8 @@ public interface ActivityComponent { void inject(RestoreAccountSetPasswordFragment restoreAccountSetPasswordFragment); void inject(RestoreAccountDozeFragment restoreAccountDozeFragment); + + void inject(OwnerReturnShardSuccessFragment ownerReturnShardSuccessFragment); + + void inject(CustodianReturnShardErrorFragment custodianReturnShardErrorFragment); } diff --git a/briar-android/src/main/java/org/briarproject/briar/android/socialbackup/recover/CustodianReturnShardActivity.java b/briar-android/src/main/java/org/briarproject/briar/android/socialbackup/recover/CustodianReturnShardActivity.java index 3346e1ce0..33e82536d 100644 --- a/briar-android/src/main/java/org/briarproject/briar/android/socialbackup/recover/CustodianReturnShardActivity.java +++ b/briar-android/src/main/java/org/briarproject/briar/android/socialbackup/recover/CustodianReturnShardActivity.java @@ -59,6 +59,8 @@ public class CustodianReturnShardActivity extends BriarActivity Toast.makeText(this, "It looks like you are not connected to a Wifi network", Toast.LENGTH_SHORT).show(); + showNextFragment(new CustodianReturnShardErrorFragment()); + return; } catch (DbException e) { Toast.makeText(this, "You do not hold a backup piece for this contact", diff --git a/briar-android/src/main/java/org/briarproject/briar/android/socialbackup/recover/CustodianReturnShardErrorFragment.java b/briar-android/src/main/java/org/briarproject/briar/android/socialbackup/recover/CustodianReturnShardErrorFragment.java index c9a5f18a7..d0ae28640 100644 --- a/briar-android/src/main/java/org/briarproject/briar/android/socialbackup/recover/CustodianReturnShardErrorFragment.java +++ b/briar-android/src/main/java/org/briarproject/briar/android/socialbackup/recover/CustodianReturnShardErrorFragment.java @@ -1,6 +1,58 @@ 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 javax.inject.Inject; + +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import androidx.lifecycle.ViewModelProvider; + +@MethodsNotNullByDefault +@ParametersNotNullByDefault 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; + } } diff --git a/briar-android/src/main/java/org/briarproject/briar/android/socialbackup/recover/CustodianReturnShardViewModel.java b/briar-android/src/main/java/org/briarproject/briar/android/socialbackup/recover/CustodianReturnShardViewModel.java index d3970c2ed..9c31b68d3 100644 --- a/briar-android/src/main/java/org/briarproject/briar/android/socialbackup/recover/CustodianReturnShardViewModel.java +++ b/briar-android/src/main/java/org/briarproject/briar/android/socialbackup/recover/CustodianReturnShardViewModel.java @@ -58,6 +58,7 @@ public class CustodianReturnShardViewModel extends AndroidViewModel new MutableLiveEvent<>(); private final MutableLiveEvent successDismissed = new MutableLiveEvent<>(); + private final MutableLiveEvent errorTryAgain = new MutableLiveEvent<>(); private final MutableLiveData state = new MutableLiveData<>(); private final CustodianTask task; @@ -156,6 +157,16 @@ public class CustodianReturnShardViewModel extends AndroidViewModel showCameraFragment.setEvent(true); } + @UiThread + public void onErrorCancelled() { + errorTryAgain.postEvent(false); + } + + @UiThread + public void onErrorTryAgain() { + errorTryAgain.postEvent(true); + } + @UiThread public void onSuccessDismissed() { successDismissed.setEvent(true); @@ -186,4 +197,8 @@ public class CustodianReturnShardViewModel extends AndroidViewModel qrCodeRead = true; } } + + public MutableLiveEvent getErrorTryAgain() { + return errorTryAgain; + } } diff --git a/briar-android/src/main/java/org/briarproject/briar/android/socialbackup/recover/OwnerReturnShardActivity.java b/briar-android/src/main/java/org/briarproject/briar/android/socialbackup/recover/OwnerReturnShardActivity.java index cc6792b5a..4ac3ad86a 100644 --- a/briar-android/src/main/java/org/briarproject/briar/android/socialbackup/recover/OwnerReturnShardActivity.java +++ b/briar-android/src/main/java/org/briarproject/briar/android/socialbackup/recover/OwnerReturnShardActivity.java @@ -77,6 +77,9 @@ public class OwnerReturnShardActivity extends BaseActivity showNextFragment(new OwnerRecoveryModeMainFragment()); } }); + viewModel.getSuccessDismissed().observeEvent(this, success -> { + if (success) onSuccessDismissed(); + }); viewModel.getState() .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) { if (state instanceof SecretOwnerTask.State.Success) { @@ -136,9 +146,8 @@ public class OwnerReturnShardActivity extends BaseActivity Toast.LENGTH_SHORT).show(); if (added && viewModel.canRecover()) { LOG.info("Secret key recovered"); - int version = 0; try { - version = viewModel.recover(); + viewModel.recover(); } catch (GeneralSecurityException e) { LOG.warning("Unable to decrypt backup" + e.toString()); Toast.makeText(this, @@ -153,15 +162,7 @@ public class OwnerReturnShardActivity extends BaseActivity Toast.LENGTH_LONG).show(); return; } - Toast.makeText(this, - "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); + showNextFragment(new OwnerReturnShardSuccessFragment()); return; } onBackPressed(); diff --git a/briar-android/src/main/java/org/briarproject/briar/android/socialbackup/recover/OwnerReturnShardSuccessFragment.java b/briar-android/src/main/java/org/briarproject/briar/android/socialbackup/recover/OwnerReturnShardSuccessFragment.java index e3ccef3a7..92c2ba378 100644 --- a/briar-android/src/main/java/org/briarproject/briar/android/socialbackup/recover/OwnerReturnShardSuccessFragment.java +++ b/briar-android/src/main/java/org/briarproject/briar/android/socialbackup/recover/OwnerReturnShardSuccessFragment.java @@ -1,6 +1,54 @@ 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 javax.inject.Inject; + +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import androidx.lifecycle.ViewModelProvider; + 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; + } } diff --git a/briar-android/src/main/java/org/briarproject/briar/android/socialbackup/recover/OwnerReturnShardViewModel.java b/briar-android/src/main/java/org/briarproject/briar/android/socialbackup/recover/OwnerReturnShardViewModel.java index e5b02dfc6..1ccb763b7 100644 --- a/briar-android/src/main/java/org/briarproject/briar/android/socialbackup/recover/OwnerReturnShardViewModel.java +++ b/briar-android/src/main/java/org/briarproject/briar/android/socialbackup/recover/OwnerReturnShardViewModel.java @@ -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.viewmodel.LiveEvent; 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.Shard; import org.briarproject.briar.api.socialbackup.recovery.RestoreAccount; 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.UnknownHostException; import java.nio.charset.Charset; import java.security.GeneralSecurityException; -import java.util.ArrayList; import java.util.concurrent.Executor; import java.util.logging.Logger; @@ -51,8 +46,6 @@ class OwnerReturnShardViewModel extends AndroidViewModel @SuppressWarnings("CharsetObjectCanBeUsed") // Requires minSdkVersion >= 19 private static final Charset ISO_8859_1 = Charset.forName("ISO-8859-1"); -// private ReturnShardPayload returnShardPayload; - private final AndroidExecutor androidExecutor; private final Executor ioExecutor; private final SecretOwnerTask task; @@ -60,6 +53,7 @@ class OwnerReturnShardViewModel extends AndroidViewModel private final MutableLiveEvent showQrCodeFragment = new MutableLiveEvent<>(); + private final MutableLiveEvent successDismissed = new MutableLiveEvent<>(); private final MutableLiveData state = new MutableLiveData<>(); private final MutableLiveEvent startClicked = @@ -128,6 +122,11 @@ class OwnerReturnShardViewModel extends AndroidViewModel startShardReturn(); } + @UiThread + void onSuccessDismissed() { + successDismissed.setEvent(true); + } + @UiThread void startShardReturn() { // 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 { return restoreAccount.recover(); } + + public MutableLiveEvent getSuccessDismissed() { + return successDismissed; + } } diff --git a/briar-android/src/main/java/org/briarproject/briar/android/socialbackup/recover/RestoreAccountActivity.java b/briar-android/src/main/java/org/briarproject/briar/android/socialbackup/recover/RestoreAccountActivity.java index afdaccb7d..2c9a3fefe 100644 --- a/briar-android/src/main/java/org/briarproject/briar/android/socialbackup/recover/RestoreAccountActivity.java +++ b/briar-android/src/main/java/org/briarproject/briar/android/socialbackup/recover/RestoreAccountActivity.java @@ -7,7 +7,6 @@ import android.os.Bundle; import org.briarproject.bramble.api.nullsafety.MethodsNotNullByDefault; import org.briarproject.bramble.api.nullsafety.ParametersNotNullByDefault; 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.BaseActivity; import org.briarproject.briar.android.fragment.BaseFragment; @@ -61,7 +60,7 @@ public class RestoreAccountActivity extends BaseActivity @TargetApi(23) void showDozeFragment() { - showNextFragment(DozeFragment.newInstance()); + showNextFragment(RestoreAccountDozeFragment.newInstance()); } void showApp() { diff --git a/briar-android/src/main/java/org/briarproject/briar/android/socialbackup/recover/RestoreAccountDozeFragment.java b/briar-android/src/main/java/org/briarproject/briar/android/socialbackup/recover/RestoreAccountDozeFragment.java index 719a56470..6c079646d 100644 --- a/briar-android/src/main/java/org/briarproject/briar/android/socialbackup/recover/RestoreAccountDozeFragment.java +++ b/briar-android/src/main/java/org/briarproject/briar/android/socialbackup/recover/RestoreAccountDozeFragment.java @@ -30,7 +30,7 @@ import static org.briarproject.briar.android.util.UiUtils.showOnboardingDialog; public class RestoreAccountDozeFragment extends RestoreAccountFragment 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 HuaweiView huaweiView; diff --git a/briar-android/src/main/java/org/briarproject/briar/android/socialbackup/recover/RestoreAccountViewModel.java b/briar-android/src/main/java/org/briarproject/briar/android/socialbackup/recover/RestoreAccountViewModel.java index 7f2b3c2f5..fe610ed91 100644 --- a/briar-android/src/main/java/org/briarproject/briar/android/socialbackup/recover/RestoreAccountViewModel.java +++ b/briar-android/src/main/java/org/briarproject/briar/android/socialbackup/recover/RestoreAccountViewModel.java @@ -30,7 +30,8 @@ import static java.util.logging.Logger.getLogger; @MethodsNotNullByDefault @ParametersNotNullByDefault -class RestoreAccountViewModel extends AndroidViewModel { +class RestoreAccountViewModel extends AndroidViewModel implements RestoreAccount.Observer { + enum State {SET_PASSWORD, DOZE, CREATED, FAILED} private static final Logger LOG = @@ -116,19 +117,12 @@ class RestoreAccountViewModel extends AndroidViewModel { ioExecutor.execute(() -> { if (accountManager.restoreAccount(identity, password)) { LOG.info("Restored account"); - try { - restoreAccount.addContactsToDb(); - } catch (InterruptedException e) { - LOG.warning("Process interrupted when waiting for db to open"); - state.postEvent(State.FAILED); - return; + restoreAccount.addContactsToDb(this); } catch (DbException e) { - LOG.warning("DbException when adding contacts"); + LOG.warning("Cannot retrieve social backup"); state.postEvent(State.FAILED); - return; } - LOG.info("Added recovered contacts to database"); state.postEvent(State.CREATED); } else { 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); + } + } }