mirror of
https://code.briarproject.org/briar/briar.git
synced 2026-02-18 05:39:53 +01:00
Restore account activity/view model
This commit is contained in:
@@ -94,8 +94,10 @@ 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.RestoreAccountActivity;
|
||||||
import org.briarproject.briar.android.splash.SplashScreenActivity;
|
import org.briarproject.briar.android.splash.SplashScreenActivity;
|
||||||
import org.briarproject.briar.android.test.TestDataActivity;
|
import org.briarproject.briar.android.test.TestDataActivity;
|
||||||
|
import org.briarproject.briar.api.socialbackup.recovery.RestoreAccount;
|
||||||
|
|
||||||
import dagger.Component;
|
import dagger.Component;
|
||||||
|
|
||||||
@@ -206,6 +208,8 @@ public interface ActivityComponent {
|
|||||||
|
|
||||||
void inject(OwnerRecoveryModeMainFragment ownerRecoveryModeMainFragment);
|
void inject(OwnerRecoveryModeMainFragment ownerRecoveryModeMainFragment);
|
||||||
|
|
||||||
|
void inject(RestoreAccountActivity restoreAccountActivity);
|
||||||
|
|
||||||
// Fragments
|
// Fragments
|
||||||
|
|
||||||
void inject(AuthorNameFragment fragment);
|
void inject(AuthorNameFragment fragment);
|
||||||
|
|||||||
@@ -15,12 +15,12 @@ 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.BackupPayload;
|
||||||
import org.briarproject.briar.api.socialbackup.DarkCrystal;
|
|
||||||
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.Shard;
|
||||||
|
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.socialbackup.BackupPayloadDecoder;
|
||||||
import org.briarproject.briar.socialbackup.SocialBackup;
|
import org.briarproject.briar.api.socialbackup.SocialBackup;
|
||||||
|
|
||||||
import java.net.InetAddress;
|
import java.net.InetAddress;
|
||||||
import java.net.UnknownHostException;
|
import java.net.UnknownHostException;
|
||||||
@@ -56,8 +56,7 @@ class OwnerReturnShardViewModel extends AndroidViewModel
|
|||||||
private final AndroidExecutor androidExecutor;
|
private final AndroidExecutor androidExecutor;
|
||||||
private final Executor ioExecutor;
|
private final Executor ioExecutor;
|
||||||
private final SecretOwnerTask task;
|
private final SecretOwnerTask task;
|
||||||
private final DarkCrystal darkCrystal;
|
private final RestoreAccount restoreAccount;
|
||||||
private final BackupPayloadDecoder backupPayloadDecoder;
|
|
||||||
|
|
||||||
private final MutableLiveEvent<Boolean> showQrCodeFragment =
|
private final MutableLiveEvent<Boolean> showQrCodeFragment =
|
||||||
new MutableLiveEvent<>();
|
new MutableLiveEvent<>();
|
||||||
@@ -67,7 +66,6 @@ class OwnerReturnShardViewModel extends AndroidViewModel
|
|||||||
new MutableLiveEvent<>();
|
new MutableLiveEvent<>();
|
||||||
private boolean wasContinueClicked = false;
|
private boolean wasContinueClicked = false;
|
||||||
private boolean isActivityResumed = false;
|
private boolean isActivityResumed = false;
|
||||||
private ArrayList<ReturnShardPayload> recoveredShards = new ArrayList<>();
|
|
||||||
private Bitmap qrCodeBitmap;
|
private Bitmap qrCodeBitmap;
|
||||||
private WifiManager wifiManager;
|
private WifiManager wifiManager;
|
||||||
private SecretKey secretKey;
|
private SecretKey secretKey;
|
||||||
@@ -76,14 +74,12 @@ class OwnerReturnShardViewModel extends AndroidViewModel
|
|||||||
OwnerReturnShardViewModel(Application app,
|
OwnerReturnShardViewModel(Application app,
|
||||||
AndroidExecutor androidExecutor,
|
AndroidExecutor androidExecutor,
|
||||||
SecretOwnerTask task,
|
SecretOwnerTask task,
|
||||||
DarkCrystal darkCrystal,
|
RestoreAccount restoreAccount,
|
||||||
BackupPayloadDecoder backupPayloadDecoder,
|
|
||||||
@IoExecutor Executor ioExecutor) {
|
@IoExecutor Executor ioExecutor) {
|
||||||
super(app);
|
super(app);
|
||||||
this.androidExecutor = androidExecutor;
|
this.androidExecutor = androidExecutor;
|
||||||
this.ioExecutor = ioExecutor;
|
this.ioExecutor = ioExecutor;
|
||||||
this.backupPayloadDecoder = backupPayloadDecoder;
|
this.restoreAccount = restoreAccount;
|
||||||
this.darkCrystal = darkCrystal;
|
|
||||||
this.task = task;
|
this.task = task;
|
||||||
wifiManager = (WifiManager) app.getSystemService(WIFI_SERVICE);
|
wifiManager = (WifiManager) app.getSystemService(WIFI_SERVICE);
|
||||||
|
|
||||||
@@ -196,7 +192,7 @@ class OwnerReturnShardViewModel extends AndroidViewModel
|
|||||||
}
|
}
|
||||||
|
|
||||||
public int getNumberOfShards() {
|
public int getNumberOfShards() {
|
||||||
return recoveredShards.size();
|
return restoreAccount.getNumberOfShards();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -227,38 +223,14 @@ class OwnerReturnShardViewModel extends AndroidViewModel
|
|||||||
|
|
||||||
// TODO figure out how to actually use a hash set for these objects
|
// TODO figure out how to actually use a hash set for these objects
|
||||||
public boolean addToShardSet(ReturnShardPayload toAdd) {
|
public boolean addToShardSet(ReturnShardPayload toAdd) {
|
||||||
boolean found = false;
|
return restoreAccount.addReturnShardPayload(toAdd);
|
||||||
for (ReturnShardPayload returnShardPayload : recoveredShards) {
|
|
||||||
if (toAdd.equals(returnShardPayload)) {
|
|
||||||
found = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (!found) recoveredShards.add(toAdd);
|
|
||||||
return !found;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean canRecover() {
|
public boolean canRecover() {
|
||||||
ArrayList<Shard> shards = new ArrayList();
|
return restoreAccount.canRecover();
|
||||||
for (ReturnShardPayload returnShardPayload : recoveredShards) {
|
|
||||||
// TODO check shards all have same secret id
|
|
||||||
shards.add(returnShardPayload.getShard());
|
|
||||||
}
|
|
||||||
try {
|
|
||||||
secretKey = darkCrystal.combineShards(shards);
|
|
||||||
} catch (GeneralSecurityException e) {
|
|
||||||
// TODO handle error message
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public int recover() throws FormatException, GeneralSecurityException {
|
public int recover() throws FormatException, GeneralSecurityException {
|
||||||
if (secretKey == null) throw new GeneralSecurityException();
|
return restoreAccount.recover();
|
||||||
// TODO find backup with highest version number
|
|
||||||
BackupPayload backupPayload = recoveredShards.get(0).getBackupPayload();
|
|
||||||
SocialBackup decodedBackup = backupPayloadDecoder.decodeBackupPayload(secretKey, backupPayload);
|
|
||||||
int version = decodedBackup.getVersion();
|
|
||||||
return version;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,83 @@
|
|||||||
package org.briarproject.briar.android.socialbackup.recover;
|
package org.briarproject.briar.android.socialbackup.recover;
|
||||||
|
|
||||||
public class RestoreAccountActivity {
|
import android.annotation.TargetApi;
|
||||||
|
import android.content.Intent;
|
||||||
|
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.account.SetPasswordFragment;
|
||||||
|
import org.briarproject.briar.android.activity.ActivityComponent;
|
||||||
|
import org.briarproject.briar.android.activity.BaseActivity;
|
||||||
|
import org.briarproject.briar.android.fragment.BaseFragment;
|
||||||
|
|
||||||
|
import javax.annotation.Nullable;
|
||||||
|
import javax.inject.Inject;
|
||||||
|
|
||||||
|
import androidx.lifecycle.ViewModelProvider;
|
||||||
|
|
||||||
|
import static android.content.Intent.FLAG_ACTIVITY_CLEAR_TASK;
|
||||||
|
import static android.content.Intent.FLAG_ACTIVITY_CLEAR_TOP;
|
||||||
|
import static android.content.Intent.FLAG_ACTIVITY_NEW_TASK;
|
||||||
|
import static android.content.Intent.FLAG_ACTIVITY_TASK_ON_HOME;
|
||||||
|
import static org.briarproject.briar.android.BriarApplication.ENTRY_ACTIVITY;
|
||||||
|
import static org.briarproject.briar.android.socialbackup.recover.RestoreAccountViewModel.State;
|
||||||
|
|
||||||
|
@MethodsNotNullByDefault
|
||||||
|
@ParametersNotNullByDefault
|
||||||
|
public class RestoreAccountActivity extends BaseActivity
|
||||||
|
implements BaseFragment.BaseFragmentListener {
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
ViewModelProvider.Factory viewModelFactory;
|
||||||
|
RestoreAccountViewModel viewModel;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void injectActivity(ActivityComponent component) {
|
||||||
|
component.inject(this);
|
||||||
|
|
||||||
|
viewModel = new ViewModelProvider(this, viewModelFactory)
|
||||||
|
.get(RestoreAccountViewModel.class);
|
||||||
|
viewModel.getState().observeEvent(this, this::onStateChanged);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onCreate(@Nullable Bundle state) {
|
||||||
|
super.onCreate(state);
|
||||||
|
setContentView(R.layout.activity_fragment_container);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void onStateChanged(RestoreAccountViewModel.State state) {
|
||||||
|
if (state == RestoreAccountViewModel.State.SET_PASSWORD) {
|
||||||
|
showInitialFragment(SetPasswordFragment.newInstance());
|
||||||
|
} else if (state == State.DOZE) {
|
||||||
|
showDozeFragment();
|
||||||
|
} else if (state == State.CREATED || state == State.FAILED) {
|
||||||
|
// TODO: Show an error if failed
|
||||||
|
showApp();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@TargetApi(23)
|
||||||
|
void showDozeFragment() {
|
||||||
|
showNextFragment(DozeFragment.newInstance());
|
||||||
|
}
|
||||||
|
|
||||||
|
void showApp() {
|
||||||
|
Intent i = new Intent(this, ENTRY_ACTIVITY);
|
||||||
|
i.setFlags(FLAG_ACTIVITY_NEW_TASK | FLAG_ACTIVITY_TASK_ON_HOME |
|
||||||
|
FLAG_ACTIVITY_CLEAR_TASK | FLAG_ACTIVITY_CLEAR_TOP);
|
||||||
|
startActivity(i);
|
||||||
|
supportFinishAfterTransition();
|
||||||
|
overridePendingTransition(R.anim.screen_new_in, R.anim.screen_old_out);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@Deprecated
|
||||||
|
public void runOnDbThread(Runnable runnable) {
|
||||||
|
throw new RuntimeException("Don't use this deprecated method here.");
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,122 @@
|
|||||||
package org.briarproject.briar.android.socialbackup.recover;
|
package org.briarproject.briar.android.socialbackup.recover;
|
||||||
|
|
||||||
public class RestoreAccountViewModel {
|
import android.app.Application;
|
||||||
|
|
||||||
|
import org.briarproject.bramble.api.account.AccountManager;
|
||||||
|
import org.briarproject.bramble.api.crypto.PasswordStrengthEstimator;
|
||||||
|
import org.briarproject.bramble.api.identity.Identity;
|
||||||
|
import org.briarproject.bramble.api.lifecycle.IoExecutor;
|
||||||
|
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.DozeHelper;
|
||||||
|
import org.briarproject.briar.android.viewmodel.LiveEvent;
|
||||||
|
import org.briarproject.briar.android.viewmodel.MutableLiveEvent;
|
||||||
|
import org.briarproject.briar.api.socialbackup.recovery.RestoreAccount;
|
||||||
|
|
||||||
|
import java.util.concurrent.Executor;
|
||||||
|
import java.util.logging.Logger;
|
||||||
|
|
||||||
|
import javax.inject.Inject;
|
||||||
|
|
||||||
|
import androidx.annotation.Nullable;
|
||||||
|
import androidx.lifecycle.AndroidViewModel;
|
||||||
|
import androidx.lifecycle.LiveData;
|
||||||
|
import androidx.lifecycle.MutableLiveData;
|
||||||
|
|
||||||
|
import static java.util.logging.Logger.getLogger;
|
||||||
|
|
||||||
|
@MethodsNotNullByDefault
|
||||||
|
@ParametersNotNullByDefault
|
||||||
|
class RestoreAccountViewModel extends AndroidViewModel {
|
||||||
|
enum State {SET_PASSWORD, DOZE, CREATED, FAILED}
|
||||||
|
|
||||||
|
private static final Logger LOG =
|
||||||
|
getLogger(RestoreAccountViewModel.class.getName());
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
private String password;
|
||||||
|
private final MutableLiveEvent<State>
|
||||||
|
state = new MutableLiveEvent<>();
|
||||||
|
private final MutableLiveData<Boolean> isCreatingAccount =
|
||||||
|
new MutableLiveData<>(false);
|
||||||
|
|
||||||
|
private final AccountManager accountManager;
|
||||||
|
private final Executor ioExecutor;
|
||||||
|
private final PasswordStrengthEstimator strengthEstimator;
|
||||||
|
private final DozeHelper dozeHelper;
|
||||||
|
private final RestoreAccount restoreAccount;
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
RestoreAccountViewModel(Application app,
|
||||||
|
AccountManager accountManager,
|
||||||
|
RestoreAccount restoreAccount,
|
||||||
|
@IoExecutor Executor ioExecutor,
|
||||||
|
PasswordStrengthEstimator strengthEstimator,
|
||||||
|
DozeHelper dozeHelper) {
|
||||||
|
super(app);
|
||||||
|
this.accountManager = accountManager;
|
||||||
|
this.ioExecutor = ioExecutor;
|
||||||
|
this.strengthEstimator = strengthEstimator;
|
||||||
|
this.dozeHelper = dozeHelper;
|
||||||
|
this.restoreAccount = restoreAccount;
|
||||||
|
|
||||||
|
ioExecutor.execute(() -> {
|
||||||
|
if (accountManager.accountExists()) {
|
||||||
|
throw new AssertionError();
|
||||||
|
} else {
|
||||||
|
state.postEvent(State.SET_PASSWORD);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
LiveEvent<State> getState() {
|
||||||
|
return state;
|
||||||
|
}
|
||||||
|
|
||||||
|
LiveData<Boolean> getIsCreatingAccount() {
|
||||||
|
return isCreatingAccount;
|
||||||
|
}
|
||||||
|
|
||||||
|
// void setAuthorName(String authorName) {
|
||||||
|
// this.authorName = authorName;
|
||||||
|
// state.setEvent(SET_PASSWORD);
|
||||||
|
// }
|
||||||
|
|
||||||
|
void setPassword(String password) {
|
||||||
|
this.password = password;
|
||||||
|
if (needToShowDozeFragment()) {
|
||||||
|
state.setEvent(State.DOZE);
|
||||||
|
} else {
|
||||||
|
createAccount();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
float estimatePasswordStrength(String password) {
|
||||||
|
return strengthEstimator.estimateStrength(password);
|
||||||
|
}
|
||||||
|
|
||||||
|
boolean needToShowDozeFragment() {
|
||||||
|
return dozeHelper.needToShowDozeFragment(getApplication());
|
||||||
|
}
|
||||||
|
|
||||||
|
void dozeExceptionConfirmed() {
|
||||||
|
createAccount();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void createAccount() {
|
||||||
|
// if (authorName == null) throw new IllegalStateException();
|
||||||
|
if (password == null) throw new IllegalStateException();
|
||||||
|
isCreatingAccount.setValue(true);
|
||||||
|
Identity identity = restoreAccount.getSocialBackup().getIdentity();
|
||||||
|
ioExecutor.execute(() -> {
|
||||||
|
if (accountManager.restoreAccount(identity, password)) {
|
||||||
|
LOG.info("Restore account");
|
||||||
|
state.postEvent(State.CREATED);
|
||||||
|
} else {
|
||||||
|
LOG.warning("Failed to create account");
|
||||||
|
state.postEvent(State.FAILED);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user