Commit bffb5c94 authored by akwizgran's avatar akwizgran

Merge branch '1229-setup-crash' into 'master'

Store nickname and password across screen rotations

Closes #1229

See merge request akwizgran/briar!796
parents c19f7c27 9a5a1489
Pipeline #1485 passed with stage
in 12 minutes and 46 seconds
......@@ -8,15 +8,21 @@ 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.bramble.util.StringUtils;
import org.briarproject.briar.R;
import org.briarproject.briar.android.activity.ActivityComponent;
import javax.annotation.Nullable;
import static android.view.inputmethod.EditorInfo.IME_ACTION_NEXT;
import static android.view.inputmethod.EditorInfo.IME_ACTION_NONE;
import static org.briarproject.bramble.api.identity.AuthorConstants.MAX_AUTHOR_NAME_LENGTH;
import static org.briarproject.briar.android.util.UiUtils.setError;
@MethodsNotNullByDefault
@ParametersNotNullByDefault
public class AuthorNameFragment extends SetupFragment {
private final static String TAG = AuthorNameFragment.class.getName();
......@@ -30,8 +36,9 @@ public class AuthorNameFragment extends SetupFragment {
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
public View onCreateView(LayoutInflater inflater,
@Nullable ViewGroup container,
@Nullable Bundle savedInstanceState) {
getActivity().setTitle(getString(R.string.setup_title));
View v = inflater.inflate(R.layout.fragment_setup_author_name,
container, false);
......@@ -75,6 +82,7 @@ public class AuthorNameFragment extends SetupFragment {
@Override
public void onClick(View view) {
setupController.setAuthorName(authorNameInput.getText().toString());
setupController.showPasswordFragment();
}
}
......@@ -10,7 +10,8 @@ import android.view.ViewGroup;
import android.widget.Button;
import android.widget.ProgressBar;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
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.login.PowerView.OnCheckedChangedListener;
......@@ -21,7 +22,8 @@ import static android.view.View.VISIBLE;
import static org.briarproject.briar.android.activity.RequestCodes.REQUEST_DOZE_WHITELISTING;
import static org.briarproject.briar.android.util.UiUtils.showOnboardingDialog;
@NotNullByDefault
@MethodsNotNullByDefault
@ParametersNotNullByDefault
public class DozeFragment extends SetupFragment
implements OnCheckedChangedListener {
......
......@@ -11,15 +11,21 @@ import android.view.inputmethod.InputMethodManager;
import android.widget.Button;
import android.widget.ProgressBar;
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.util.UiUtils;
import javax.annotation.Nullable;
import static android.content.Context.INPUT_METHOD_SERVICE;
import static android.view.View.INVISIBLE;
import static android.view.View.VISIBLE;
import static org.briarproject.bramble.api.crypto.PasswordStrengthEstimator.QUITE_WEAK;
@MethodsNotNullByDefault
@ParametersNotNullByDefault
public class PasswordFragment extends SetupFragment {
private final static String TAG = PasswordFragment.class.getName();
......@@ -37,8 +43,9 @@ public class PasswordFragment extends SetupFragment {
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
public View onCreateView(LayoutInflater inflater,
@Nullable ViewGroup container,
@Nullable Bundle savedInstanceState) {
getActivity().setTitle(getString(R.string.setup_password_intro));
View v = inflater.inflate(R.layout.fragment_setup_password, container,
false);
......@@ -105,16 +112,17 @@ public class PasswordFragment extends SetupFragment {
@Override
public void onClick(View view) {
if (!setupController.needToShowDozeFragment()) {
nextButton.setVisibility(INVISIBLE);
progressBar.setVisibility(VISIBLE);
}
String password = passwordEntry.getText().toString();
IBinder token = passwordEntry.getWindowToken();
Object o = getContext().getSystemService(INPUT_METHOD_SERVICE);
((InputMethodManager) o).hideSoftInputFromWindow(token, 0);
setupController.setPassword(password);
setupController.showDozeOrCreateAccount();
setupController.setPassword(passwordEntry.getText().toString());
if (setupController.needToShowDozeFragment()) {
setupController.showDozeFragment();
} else {
nextButton.setVisibility(INVISIBLE);
progressBar.setVisibility(VISIBLE);
setupController.createAccount();
}
}
}
......@@ -4,23 +4,34 @@ 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.activity.ActivityComponent;
import org.briarproject.briar.android.activity.BaseActivity;
import org.briarproject.briar.android.fragment.BaseFragment.BaseFragmentListener;
import javax.annotation.Nullable;
import javax.inject.Inject;
import static android.content.Intent.FLAG_ACTIVITY_NEW_TASK;
@MethodsNotNullByDefault
@ParametersNotNullByDefault
public class SetupActivity extends BaseActivity
implements BaseFragmentListener {
private static final String STATE_KEY_AUTHOR_NAME = "authorName";
private static final String STATE_KEY_PASSWORD = "password";
@Inject
SetupController setupController;
@Nullable
private String authorName, password;
@Override
public void onCreate(Bundle state) {
public void onCreate(@Nullable Bundle state) {
super.onCreate(state);
// fade-in after splash screen instead of default animation
overridePendingTransition(R.anim.fade_in, R.anim.fade_out);
......@@ -28,6 +39,9 @@ public class SetupActivity extends BaseActivity
if (state == null) {
showInitialFragment(AuthorNameFragment.newInstance());
} else {
authorName = state.getString(STATE_KEY_AUTHOR_NAME);
password = state.getString(STATE_KEY_PASSWORD);
}
}
......@@ -37,16 +51,46 @@ public class SetupActivity extends BaseActivity
setupController.setSetupActivity(this);
}
public void showPasswordFragment() {
@Override
protected void onSaveInstanceState(Bundle state) {
super.onSaveInstanceState(state);
if (authorName != null)
state.putString(STATE_KEY_AUTHOR_NAME, authorName);
if (password != null)
state.putString(STATE_KEY_PASSWORD, password);
}
@Nullable
String getAuthorName() {
return authorName;
}
void setAuthorName(String authorName) {
this.authorName = authorName;
}
@Nullable
String getPassword() {
return password;
}
void setPassword(String password) {
this.password = password;
}
void showPasswordFragment() {
if (authorName == null) throw new IllegalStateException();
showNextFragment(PasswordFragment.newInstance());
}
@TargetApi(23)
public void showDozeFragment() {
void showDozeFragment() {
if (authorName == null) throw new IllegalStateException();
if (password == null) throw new IllegalStateException();
showNextFragment(DozeFragment.newInstance());
}
public void showApp() {
void showApp() {
Intent i = new Intent(this, OpenDatabaseActivity.class);
i.setFlags(FLAG_ACTIVITY_NEW_TASK);
startActivity(i);
......
package org.briarproject.briar.android.login;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import org.briarproject.briar.android.controller.handler.ResultHandler;
@NotNullByDefault
public interface SetupController {
......@@ -16,15 +15,20 @@ public interface SetupController {
float estimatePasswordStrength(String password);
/**
* This should be called after the author name has been set.
*/
void showPasswordFragment();
/**
* This should be called after the author name and the password have been
* set. It decides whether to ask for doze exception or create the account
* right away.
* set.
*/
void showDozeOrCreateAccount();
void showDozeFragment();
/**
* This should be called after the author name and the password have been
* set.
*/
void createAccount();
void createAccount(ResultHandler<Void> resultHandler);
}
......@@ -20,8 +20,6 @@ import javax.inject.Inject;
public class SetupControllerImpl extends PasswordControllerImpl
implements SetupController {
@Nullable
private String authorName, password;
@Nullable
private SetupActivity setupActivity;
......@@ -48,28 +46,31 @@ public class SetupControllerImpl extends PasswordControllerImpl
@Override
public void setAuthorName(String authorName) {
this.authorName = authorName;
if (setupActivity == null) throw new IllegalStateException();
setupActivity.showPasswordFragment();
setupActivity.setAuthorName(authorName);
}
@Override
public void setPassword(String password) {
this.password = password;
if (setupActivity == null) throw new IllegalStateException();
setupActivity.setPassword(password);
}
@Override
public void showDozeOrCreateAccount() {
public void showPasswordFragment() {
if (setupActivity == null) throw new IllegalStateException();
if (needToShowDozeFragment()) {
setupActivity.showDozeFragment();
} else {
createAccount();
}
setupActivity.showPasswordFragment();
}
@Override
public void showDozeFragment() {
if (setupActivity == null) throw new IllegalStateException();
setupActivity.showDozeFragment();
}
@Override
public void createAccount() {
if (setupActivity == null) throw new IllegalStateException();
UiResultHandler<Void> resultHandler =
new UiResultHandler<Void>(setupActivity) {
@Override
......@@ -82,10 +83,13 @@ public class SetupControllerImpl extends PasswordControllerImpl
createAccount(resultHandler);
}
@Override
public void createAccount(ResultHandler<Void> resultHandler) {
if (authorName == null || password == null)
throw new IllegalStateException();
// Package access for testing
void createAccount(ResultHandler<Void> resultHandler) {
if (setupActivity == null) throw new IllegalStateException();
String authorName = setupActivity.getAuthorName();
if (authorName == null) throw new IllegalStateException();
String password = setupActivity.getPassword();
if (password == null) throw new IllegalStateException();
cryptoExecutor.execute(() -> {
databaseConfig.setLocalAuthorName(authorName);
SecretKey key = crypto.generateSecretKey();
......
......@@ -73,7 +73,7 @@ public class PasswordFragmentTest {
// assert controller has been called properly
verify(setupController, times(1)).setPassword(safePass);
verify(setupController, times(1)).showDozeOrCreateAccount();
verify(setupController, times(1)).createAccount();
}
@Test
......
......@@ -15,22 +15,8 @@ import org.robolectric.RobolectricTestRunner;
import org.robolectric.annotation.Config;
import static junit.framework.Assert.assertEquals;
import static org.briarproject.bramble.api.crypto.PasswordStrengthEstimator.NONE;
import static org.briarproject.bramble.api.crypto.PasswordStrengthEstimator.QUITE_STRONG;
import static org.briarproject.bramble.api.crypto.PasswordStrengthEstimator.QUITE_WEAK;
import static org.briarproject.bramble.api.crypto.PasswordStrengthEstimator.STRONG;
import static org.briarproject.bramble.api.crypto.PasswordStrengthEstimator.WEAK;
import static org.briarproject.bramble.api.identity.AuthorConstants.MAX_AUTHOR_NAME_LENGTH;
import static org.briarproject.bramble.util.StringUtils.getRandomString;
import static org.junit.Assert.assertTrue;
import static org.mockito.Matchers.anyString;
import static org.mockito.Matchers.eq;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.timeout;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import static org.robolectric.Shadows.shadowOf;
@RunWith(RobolectricTestRunner.class)
@Config(sdk = 21, application = TestBriarApplication.class,
......
......@@ -47,10 +47,17 @@ public class SetupControllerImplTest extends BrambleMockTestCase {
}
@Test
@SuppressWarnings("ResultOfMethodCallIgnored")
public void testCreateAccount() {
context.checking(new Expectations() {{
// Setting the author name shows the password fragment
oneOf(setupActivity).showPasswordFragment();
// Set the author name and password
oneOf(setupActivity).setAuthorName(authorName);
oneOf(setupActivity).setPassword(password);
// Get the author name and password
oneOf(setupActivity).getAuthorName();
will(returnValue(authorName));
oneOf(setupActivity).getPassword();
will(returnValue(password));
// Generate a database key
oneOf(crypto).generateSecretKey();
will(returnValue(key));
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment