diff --git a/briar-android/src/main/java/org/briarproject/briar/android/login/AuthorNameFragment.java b/briar-android/src/main/java/org/briarproject/briar/android/login/AuthorNameFragment.java index ec28c6563e7c773ffaaf3e65dc5741c5395504b3..6e4c35d8695a402820b856982b5571626dde6284 100644 --- a/briar-android/src/main/java/org/briarproject/briar/android/login/AuthorNameFragment.java +++ b/briar-android/src/main/java/org/briarproject/briar/android/login/AuthorNameFragment.java @@ -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(); } } diff --git a/briar-android/src/main/java/org/briarproject/briar/android/login/DozeFragment.java b/briar-android/src/main/java/org/briarproject/briar/android/login/DozeFragment.java index f6362a2d89f3352059b4c8cdfcbd51a1e0e0a13b..624437c6dbee32ea6ccaef1b0456f94172d093f2 100644 --- a/briar-android/src/main/java/org/briarproject/briar/android/login/DozeFragment.java +++ b/briar-android/src/main/java/org/briarproject/briar/android/login/DozeFragment.java @@ -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 { diff --git a/briar-android/src/main/java/org/briarproject/briar/android/login/PasswordFragment.java b/briar-android/src/main/java/org/briarproject/briar/android/login/PasswordFragment.java index 3b5f788b746aaa4739e8fca9358baf6beab9e1e3..2b9c0adebddfdd289b532f3f231a758e99997a16 100644 --- a/briar-android/src/main/java/org/briarproject/briar/android/login/PasswordFragment.java +++ b/briar-android/src/main/java/org/briarproject/briar/android/login/PasswordFragment.java @@ -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); @@ -109,12 +116,11 @@ public class PasswordFragment extends SetupFragment { 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()); + setupController.showDozeFragmentOrCreateAccount(); } } diff --git a/briar-android/src/main/java/org/briarproject/briar/android/login/SetupActivity.java b/briar-android/src/main/java/org/briarproject/briar/android/login/SetupActivity.java index 2b17df6eaf0f93d47b7234b728993e37000d0d40..5e74be6b29dddac85dd76d522a30003986a8cb6b 100644 --- a/briar-android/src/main/java/org/briarproject/briar/android/login/SetupActivity.java +++ b/briar-android/src/main/java/org/briarproject/briar/android/login/SetupActivity.java @@ -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); diff --git a/briar-android/src/main/java/org/briarproject/briar/android/login/SetupController.java b/briar-android/src/main/java/org/briarproject/briar/android/login/SetupController.java index 870b64df0b00249df781a4ecc6852c99fca5d916..4ee4e0f2b518e76928e6b06cf97d698981a7d07b 100644 --- a/briar-android/src/main/java/org/briarproject/briar/android/login/SetupController.java +++ b/briar-android/src/main/java/org/briarproject/briar/android/login/SetupController.java @@ -1,7 +1,6 @@ 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,17 @@ 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 + * set. It decides whether to show the doze fragment or create the account * right away. */ - void showDozeOrCreateAccount(); + void showDozeFragmentOrCreateAccount(); void createAccount(); - - void createAccount(ResultHandler<Void> resultHandler); - } diff --git a/briar-android/src/main/java/org/briarproject/briar/android/login/SetupControllerImpl.java b/briar-android/src/main/java/org/briarproject/briar/android/login/SetupControllerImpl.java index 00f2b012b85305e82da9582b719eb616eaec8378..2d8fb420ceb88c709248e3510d813c20b40b7693 100644 --- a/briar-android/src/main/java/org/briarproject/briar/android/login/SetupControllerImpl.java +++ b/briar-android/src/main/java/org/briarproject/briar/android/login/SetupControllerImpl.java @@ -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,32 @@ 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 showDozeFragmentOrCreateAccount() { + if (setupActivity == null) throw new IllegalStateException(); + if (needToShowDozeFragment()) setupActivity.showDozeFragment(); + else createAccount(); } @Override public void createAccount() { + if (setupActivity == null) throw new IllegalStateException(); UiResultHandler<Void> resultHandler = new UiResultHandler<Void>(setupActivity) { @Override @@ -82,10 +84,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(); diff --git a/briar-android/src/test/java/org/briarproject/briar/android/login/PasswordFragmentTest.java b/briar-android/src/test/java/org/briarproject/briar/android/login/PasswordFragmentTest.java index a503e44226368022d7dfb863c5ecb2485f5c1d69..cfad66d8840631c4ff26c97af00e0a4209aff83e 100644 --- a/briar-android/src/test/java/org/briarproject/briar/android/login/PasswordFragmentTest.java +++ b/briar-android/src/test/java/org/briarproject/briar/android/login/PasswordFragmentTest.java @@ -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)).showDozeFragmentOrCreateAccount(); } @Test diff --git a/briar-android/src/test/java/org/briarproject/briar/android/login/SetupActivityTest.java b/briar-android/src/test/java/org/briarproject/briar/android/login/SetupActivityTest.java index 3541d0bda324baf98f783e8caafdf4db5fb8584e..e01220686b691d1c82c6dac30e7d25c939b22996 100644 --- a/briar-android/src/test/java/org/briarproject/briar/android/login/SetupActivityTest.java +++ b/briar-android/src/test/java/org/briarproject/briar/android/login/SetupActivityTest.java @@ -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, diff --git a/briar-android/src/test/java/org/briarproject/briar/android/login/SetupControllerImplTest.java b/briar-android/src/test/java/org/briarproject/briar/android/login/SetupControllerImplTest.java index 9dbfd17afdaba19a4621a117449112edcd57e475..6fe3f42c8910704e76144b0e73e0e4ff8969a4b5 100644 --- a/briar-android/src/test/java/org/briarproject/briar/android/login/SetupControllerImplTest.java +++ b/briar-android/src/test/java/org/briarproject/briar/android/login/SetupControllerImplTest.java @@ -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));