diff --git a/briar-android/build.gradle b/briar-android/build.gradle
index d31f16b1f..fac88cf8c 100644
--- a/briar-android/build.gradle
+++ b/briar-android/build.gradle
@@ -18,6 +18,7 @@ dependencies {
}
compile "com.android.support:cardview-v7:$supportVersion"
compile "com.android.support:support-annotations:$supportVersion"
+ compile 'com.android.support.constraint:constraint-layout:1.0.2'
compile('ch.acra:acra:4.8.5') {
exclude module: 'support-v4'
exclude module: 'support-annotations'
@@ -55,6 +56,8 @@ dependencyVerification {
'com.android.support:support-vector-drawable:799bafe4c3de812386f0b291f744d5d6876452722dd40189b9ab87dbbf594ea1',
'com.android.support:recyclerview-v7:44040a888e23e0c93162a3377cfe06751080e3c22d369ab0d4301ef60d63b0fe',
'com.android.support:preference-v7:775101bd07bd052e455761c5c5d9523d7ad59f2f320e3e8cbde241fd6b1d6025',
+ 'com.android.support.constraint:constraint-layout:b0c688cc2b7172608f8153a689d746da40f71e52d7e2fe2bfd9df2f92db77085',
+ 'com.android.support.constraint:constraint-layout-solver:8c62525a9bc5cff5633a96cb9b32fffeccaf41b8841aa87fc22607070dea9b8d',
]
}
diff --git a/briar-android/src/main/AndroidManifest.xml b/briar-android/src/main/AndroidManifest.xml
index c43e5aa27..a2fed381f 100644
--- a/briar-android/src/main/AndroidManifest.xml
+++ b/briar-android/src/main/AndroidManifest.xml
@@ -15,6 +15,7 @@
+
apps = screenFilterMonitor.getApps();
diff --git a/briar-android/src/main/java/org/briarproject/briar/android/activity/BriarActivity.java b/briar-android/src/main/java/org/briarproject/briar/android/activity/BriarActivity.java
index e148db65b..33ed5bfc3 100644
--- a/briar-android/src/main/java/org/briarproject/briar/android/activity/BriarActivity.java
+++ b/briar-android/src/main/java/org/briarproject/briar/android/activity/BriarActivity.java
@@ -14,7 +14,6 @@ import org.briarproject.briar.R;
import org.briarproject.briar.android.controller.BriarController;
import org.briarproject.briar.android.controller.DbController;
import org.briarproject.briar.android.controller.handler.ResultHandler;
-import org.briarproject.briar.android.fragment.BaseFragment;
import org.briarproject.briar.android.login.PasswordActivity;
import org.briarproject.briar.android.panic.ExitActivity;
@@ -64,22 +63,6 @@ public abstract class BriarActivity extends BaseActivity {
}
}
- protected void showInitialFragment(BaseFragment f) {
- getSupportFragmentManager().beginTransaction()
- .replace(R.id.fragmentContainer, f, f.getUniqueTag())
- .commit();
- }
-
- public void showNextFragment(BaseFragment f) {
- getSupportFragmentManager().beginTransaction()
- .setCustomAnimations(R.anim.step_next_in,
- R.anim.step_previous_out, R.anim.step_previous_in,
- R.anim.step_next_out)
- .replace(R.id.fragmentContainer, f, f.getUniqueTag())
- .addToBackStack(f.getUniqueTag())
- .commit();
- }
-
public void setSceneTransitionAnimation() {
if (Build.VERSION.SDK_INT < 21) return;
Transition slide = new Slide(Gravity.RIGHT);
diff --git a/briar-android/src/main/java/org/briarproject/briar/android/activity/RequestCodes.java b/briar-android/src/main/java/org/briarproject/briar/android/activity/RequestCodes.java
index 131b2921b..fe771c430 100644
--- a/briar-android/src/main/java/org/briarproject/briar/android/activity/RequestCodes.java
+++ b/briar-android/src/main/java/org/briarproject/briar/android/activity/RequestCodes.java
@@ -3,13 +3,13 @@ package org.briarproject.briar.android.activity;
public interface RequestCodes {
int REQUEST_PASSWORD = 1;
- int REQUEST_BLUETOOTH = 2;
- int REQUEST_INTRODUCTION = 3;
- int REQUEST_GROUP_INVITE = 4;
- int REQUEST_SHARE_FORUM = 5;
- int REQUEST_WRITE_BLOG_POST = 6;
- int REQUEST_SHARE_BLOG = 7;
- int REQUEST_RINGTONE = 8;
- int REQUEST_PERMISSION_CAMERA = 9;
+ int REQUEST_INTRODUCTION = 2;
+ int REQUEST_GROUP_INVITE = 3;
+ int REQUEST_SHARE_FORUM = 4;
+ int REQUEST_WRITE_BLOG_POST = 5;
+ int REQUEST_SHARE_BLOG = 6;
+ int REQUEST_RINGTONE = 7;
+ int REQUEST_PERMISSION_CAMERA = 8;
+ int REQUEST_DOZE_WHITELISTING = 9;
}
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
new file mode 100644
index 000000000..ab7cd4cd8
--- /dev/null
+++ b/briar-android/src/main/java/org/briarproject/briar/android/login/AuthorNameFragment.java
@@ -0,0 +1,84 @@
+package org.briarproject.briar.android.login;
+
+import android.os.Bundle;
+import android.support.design.widget.TextInputEditText;
+import android.support.design.widget.TextInputLayout;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.Button;
+
+import org.briarproject.bramble.util.StringUtils;
+import org.briarproject.briar.R;
+import org.briarproject.briar.android.activity.ActivityComponent;
+
+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;
+
+public class AuthorNameFragment extends SetupFragment {
+
+ private final static String TAG = AuthorNameFragment.class.getName();
+
+ private TextInputLayout authorNameWrapper;
+ private TextInputEditText authorNameInput;
+ private Button nextButton;
+
+ public static AuthorNameFragment newInstance() {
+ return new AuthorNameFragment();
+ }
+
+ @Override
+ public View onCreateView(LayoutInflater inflater, ViewGroup container,
+ Bundle savedInstanceState) {
+ getActivity().setTitle(getString(R.string.setup_title));
+ View v =
+ inflater.inflate(R.layout.fragment_setup_author_name, container,
+ false);
+ authorNameWrapper =
+ (TextInputLayout) v.findViewById(R.id.nickname_entry_wrapper);
+ authorNameInput =
+ (TextInputEditText) v.findViewById(R.id.nickname_entry);
+ nextButton = (Button) v.findViewById(R.id.next);
+
+ authorNameInput.addTextChangedListener(this);
+
+ nextButton.setOnClickListener(this);
+
+ return v;
+ }
+
+ @Override
+ public String getUniqueTag() {
+ return TAG;
+ }
+
+ @Override
+ public void injectFragment(ActivityComponent component) {
+ component.inject(this);
+ }
+
+ @Override
+ protected String getHelpText() {
+ return getString(R.string.setup_name_explanation);
+ }
+
+ @Override
+ public void onTextChanged(CharSequence authorName, int i, int i1, int i2) {
+ int authorNameLength = StringUtils.toUtf8(authorName.toString()).length;
+ boolean error = authorNameLength > MAX_AUTHOR_NAME_LENGTH;
+ setError(authorNameWrapper, getString(R.string.name_too_long), error);
+ boolean enabled = authorNameLength > 0 && !error;
+ authorNameInput
+ .setImeOptions(enabled ? IME_ACTION_NEXT : IME_ACTION_NONE);
+ authorNameInput.setOnEditorActionListener(enabled ? this : null);
+ nextButton.setEnabled(enabled);
+ }
+
+ @Override
+ public void onClick(View view) {
+ setupController.setAuthorName(authorNameInput.getText().toString());
+ }
+
+}
diff --git a/briar-android/src/main/java/org/briarproject/briar/android/login/ChangePasswordActivity.java b/briar-android/src/main/java/org/briarproject/briar/android/login/ChangePasswordActivity.java
index cea17a2eb..cc460deb7 100644
--- a/briar-android/src/main/java/org/briarproject/briar/android/login/ChangePasswordActivity.java
+++ b/briar-android/src/main/java/org/briarproject/briar/android/login/ChangePasswordActivity.java
@@ -32,8 +32,6 @@ public class ChangePasswordActivity extends BaseActivity
@Inject
protected PasswordController passwordController;
- @Inject
- protected SetupController setupController;
private TextInputLayout currentPasswordEntryWrapper;
private TextInputLayout newPasswordEntryWrapper;
@@ -105,7 +103,7 @@ public class ChangePasswordActivity extends BaseActivity
String secondPassword = newPasswordConfirmation.getText().toString();
boolean passwordsMatch = firstPassword.equals(secondPassword);
float strength =
- setupController.estimatePasswordStrength(firstPassword);
+ passwordController.estimatePasswordStrength(firstPassword);
strengthMeter.setStrength(strength);
UiUtils.setError(newPasswordEntryWrapper,
getString(R.string.password_too_weak),
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
new file mode 100644
index 000000000..328dac981
--- /dev/null
+++ b/briar-android/src/main/java/org/briarproject/briar/android/login/DozeFragment.java
@@ -0,0 +1,95 @@
+package org.briarproject.briar.android.login;
+
+import android.annotation.SuppressLint;
+import android.annotation.TargetApi;
+import android.content.Intent;
+import android.os.Bundle;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.Button;
+import android.widget.ProgressBar;
+
+import org.briarproject.briar.R;
+import org.briarproject.briar.android.activity.ActivityComponent;
+import org.briarproject.briar.android.util.UiUtils;
+
+import static android.view.View.INVISIBLE;
+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;
+
+@TargetApi(23)
+public class DozeFragment extends SetupFragment {
+
+ private final static String TAG = DozeFragment.class.getName();
+
+ private Button dozeButton;
+ private ProgressBar progressBar;
+
+ public static DozeFragment newInstance() {
+ return new DozeFragment();
+ }
+
+ @Override
+ public View onCreateView(LayoutInflater inflater, ViewGroup container,
+ Bundle savedInstanceState) {
+ getActivity().setTitle(getString(R.string.setup_doze_title));
+ View v =
+ inflater.inflate(R.layout.fragment_setup_doze, container,
+ false);
+ dozeButton = (Button) v.findViewById(R.id.dozeButton);
+ progressBar = (ProgressBar) v.findViewById(R.id.progress);
+
+ dozeButton.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View view) {
+ askForDozeWhitelisting();
+ }
+ });
+
+ return v;
+ }
+
+ @Override
+ public String getUniqueTag() {
+ return TAG;
+ }
+
+ @Override
+ public void injectFragment(ActivityComponent component) {
+ component.inject(this);
+ }
+
+ @Override
+ protected String getHelpText() {
+ return getString(R.string.setup_doze_explanation);
+ }
+
+ @Override
+ public void onActivityResult(int request, int result, Intent data) {
+ super.onActivityResult(request, result, data);
+ if (request == REQUEST_DOZE_WHITELISTING) {
+ if (!setupController.needsDozeWhitelisting()) {
+ dozeButton.setEnabled(false);
+ onClick(dozeButton);
+ } else {
+ showOnboardingDialog(getContext(), getHelpText());
+ }
+ }
+ }
+
+ @SuppressLint("BatteryLife")
+ private void askForDozeWhitelisting() {
+ Intent i = UiUtils.getDozeWhitelistingIntent(getContext());
+ startActivityForResult(i, REQUEST_DOZE_WHITELISTING);
+ }
+
+ @Override
+ public void onClick(View view) {
+ dozeButton.setVisibility(INVISIBLE);
+ progressBar.setVisibility(VISIBLE);
+ setupController.createAccount();
+ }
+
+}
diff --git a/briar-android/src/main/java/org/briarproject/briar/android/login/PasswordController.java b/briar-android/src/main/java/org/briarproject/briar/android/login/PasswordController.java
index 209b5ac4a..ec3cb7ed7 100644
--- a/briar-android/src/main/java/org/briarproject/briar/android/login/PasswordController.java
+++ b/briar-android/src/main/java/org/briarproject/briar/android/login/PasswordController.java
@@ -7,9 +7,12 @@ import org.briarproject.briar.android.controller.handler.ResultHandler;
@NotNullByDefault
public interface PasswordController extends ConfigController {
+ float estimatePasswordStrength(String password);
+
void validatePassword(String password,
ResultHandler resultHandler);
void changePassword(String password, String newPassword,
ResultHandler resultHandler);
+
}
diff --git a/briar-android/src/main/java/org/briarproject/briar/android/login/PasswordControllerImpl.java b/briar-android/src/main/java/org/briarproject/briar/android/login/PasswordControllerImpl.java
index ac01eba47..92c80ffe5 100644
--- a/briar-android/src/main/java/org/briarproject/briar/android/login/PasswordControllerImpl.java
+++ b/briar-android/src/main/java/org/briarproject/briar/android/login/PasswordControllerImpl.java
@@ -4,6 +4,7 @@ import android.content.SharedPreferences;
import org.briarproject.bramble.api.crypto.CryptoComponent;
import org.briarproject.bramble.api.crypto.CryptoExecutor;
+import org.briarproject.bramble.api.crypto.PasswordStrengthEstimator;
import org.briarproject.bramble.api.crypto.SecretKey;
import org.briarproject.bramble.api.db.DatabaseConfig;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
@@ -27,14 +28,22 @@ public class PasswordControllerImpl extends ConfigControllerImpl
protected final Executor cryptoExecutor;
protected final CryptoComponent crypto;
+ private final PasswordStrengthEstimator strengthEstimator;
@Inject
PasswordControllerImpl(SharedPreferences briarPrefs,
DatabaseConfig databaseConfig,
- @CryptoExecutor Executor cryptoExecutor, CryptoComponent crypto) {
+ @CryptoExecutor Executor cryptoExecutor, CryptoComponent crypto,
+ PasswordStrengthEstimator strengthEstimator) {
super(briarPrefs, databaseConfig);
this.cryptoExecutor = cryptoExecutor;
this.crypto = crypto;
+ this.strengthEstimator = strengthEstimator;
+ }
+
+ @Override
+ public float estimatePasswordStrength(String password) {
+ return strengthEstimator.estimateStrength(password);
}
@Override
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
new file mode 100644
index 000000000..f24cf2daf
--- /dev/null
+++ b/briar-android/src/main/java/org/briarproject/briar/android/login/PasswordFragment.java
@@ -0,0 +1,117 @@
+package org.briarproject.briar.android.login;
+
+import android.os.Bundle;
+import android.support.design.widget.TextInputEditText;
+import android.support.design.widget.TextInputLayout;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.Button;
+import android.widget.ProgressBar;
+
+import org.briarproject.briar.R;
+import org.briarproject.briar.android.activity.ActivityComponent;
+import org.briarproject.briar.android.util.UiUtils;
+
+import static android.view.View.INVISIBLE;
+import static android.view.View.VISIBLE;
+import static org.briarproject.bramble.api.crypto.PasswordStrengthEstimator.QUITE_WEAK;
+
+public class PasswordFragment extends SetupFragment {
+
+ private final static String TAG = PasswordFragment.class.getName();
+
+ private TextInputLayout passwordEntryWrapper;
+ private TextInputLayout passwordConfirmationWrapper;
+ private TextInputEditText passwordEntry;
+ private TextInputEditText passwordConfirmation;
+ private StrengthMeter strengthMeter;
+ private Button nextButton;
+ private ProgressBar progressBar;
+
+ public static PasswordFragment newInstance() {
+ return new PasswordFragment();
+ }
+
+ @Override
+ public View onCreateView(LayoutInflater inflater, ViewGroup container,
+ Bundle savedInstanceState) {
+ getActivity().setTitle(getString(R.string.setup_password_intro));
+ View v =
+ inflater.inflate(R.layout.fragment_setup_password, container,
+ false);
+
+ strengthMeter = (StrengthMeter) v.findViewById(R.id.strength_meter);
+ passwordEntryWrapper =
+ (TextInputLayout) v.findViewById(R.id.password_entry_wrapper);
+ passwordEntry = (TextInputEditText) v.findViewById(R.id.password_entry);
+ passwordConfirmationWrapper =
+ (TextInputLayout) v.findViewById(R.id.password_confirm_wrapper);
+ passwordConfirmation =
+ (TextInputEditText) v.findViewById(R.id.password_confirm);
+ nextButton = (Button) v.findViewById(R.id.next);
+ progressBar = (ProgressBar) v.findViewById(R.id.progress);
+
+ passwordEntry.addTextChangedListener(this);
+ passwordConfirmation.addTextChangedListener(this);
+ nextButton.setOnClickListener(this);
+
+ return v;
+ }
+
+ @Override
+ public String getUniqueTag() {
+ return TAG;
+ }
+
+ @Override
+ public void injectFragment(ActivityComponent component) {
+ component.inject(this);
+
+ // the controller is not yet available in onCreateView()
+ if (!setupController.needsDozeWhitelisting()) {
+ nextButton.setText(R.string.create_account_button);
+ }
+ }
+
+ @Override
+ protected String getHelpText() {
+ return getString(R.string.setup_password_explanation);
+ }
+
+ @Override
+ public void onTextChanged(CharSequence authorName, int i, int i1, int i2) {
+ String password1 = passwordEntry.getText().toString();
+ String password2 = passwordConfirmation.getText().toString();
+ boolean passwordsMatch = password1.equals(password2);
+
+ strengthMeter
+ .setVisibility(password1.length() > 0 ? VISIBLE : INVISIBLE);
+ float strength = setupController.estimatePasswordStrength(password1);
+ strengthMeter.setStrength(strength);
+ boolean strongEnough = strength >= QUITE_WEAK;
+
+ UiUtils.setError(passwordEntryWrapper,
+ getString(R.string.password_too_weak),
+ password1.length() > 0 && !strongEnough);
+ UiUtils.setError(passwordConfirmationWrapper,
+ getString(R.string.passwords_do_not_match),
+ password2.length() > 0 && !passwordsMatch);
+
+ boolean enabled = passwordsMatch && strongEnough;
+ nextButton.setEnabled(enabled);
+ passwordConfirmation.setOnEditorActionListener(enabled ? this : null);
+ }
+
+ @Override
+ public void onClick(View view) {
+ if (!setupController.needsDozeWhitelisting()) {
+ nextButton.setVisibility(INVISIBLE);
+ progressBar.setVisibility(VISIBLE);
+ }
+ String password = passwordEntry.getText().toString();
+ setupController.setPassword(password);
+ setupController.showDozeOrCreateAccount();
+ }
+
+}
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 767a9eb55..17c6f522f 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
@@ -1,157 +1,64 @@
package org.briarproject.briar.android.login;
+import android.annotation.TargetApi;
import android.content.Intent;
import android.os.Bundle;
-import android.support.design.widget.TextInputLayout;
-import android.text.Editable;
-import android.text.TextWatcher;
-import android.view.KeyEvent;
-import android.view.View;
-import android.view.View.OnClickListener;
-import android.widget.Button;
-import android.widget.EditText;
-import android.widget.ProgressBar;
-import android.widget.TextView;
-import android.widget.TextView.OnEditorActionListener;
-import org.briarproject.bramble.util.StringUtils;
import org.briarproject.briar.R;
import org.briarproject.briar.android.activity.ActivityComponent;
import org.briarproject.briar.android.activity.BaseActivity;
-import org.briarproject.briar.android.controller.handler.UiResultHandler;
+import org.briarproject.briar.android.fragment.BaseFragment.BaseFragmentListener;
import org.briarproject.briar.android.navdrawer.NavDrawerActivity;
-import org.briarproject.briar.android.util.UiUtils;
import javax.inject.Inject;
import static android.content.Intent.FLAG_ACTIVITY_NEW_TASK;
-import static android.view.View.GONE;
-import static android.view.View.INVISIBLE;
-import static android.view.View.VISIBLE;
-import static org.briarproject.bramble.api.crypto.PasswordStrengthEstimator.QUITE_WEAK;
-import static org.briarproject.bramble.api.identity.AuthorConstants.MAX_AUTHOR_NAME_LENGTH;
-public class SetupActivity extends BaseActivity implements OnClickListener,
- OnEditorActionListener {
+public class SetupActivity extends BaseActivity
+ implements BaseFragmentListener {
@Inject
SetupController setupController;
- private TextInputLayout nicknameEntryWrapper;
- private TextInputLayout passwordEntryWrapper;
- private TextInputLayout passwordConfirmationWrapper;
- private EditText nicknameEntry;
- private EditText passwordEntry;
- private EditText passwordConfirmation;
- private StrengthMeter strengthMeter;
- private Button createAccountButton;
- private ProgressBar progress;
-
@Override
public void onCreate(Bundle state) {
super.onCreate(state);
// fade-in after splash screen instead of default animation
overridePendingTransition(R.anim.fade_in, R.anim.fade_out);
- setContentView(R.layout.activity_setup);
+ setContentView(R.layout.activity_fragment_container);
- nicknameEntryWrapper =
- (TextInputLayout) findViewById(R.id.nickname_entry_wrapper);
- passwordEntryWrapper =
- (TextInputLayout) findViewById(R.id.password_entry_wrapper);
- passwordConfirmationWrapper =
- (TextInputLayout) findViewById(R.id.password_confirm_wrapper);
- nicknameEntry = (EditText) findViewById(R.id.nickname_entry);
- passwordEntry = (EditText) findViewById(R.id.password_entry);
- passwordConfirmation = (EditText) findViewById(R.id.password_confirm);
- strengthMeter = (StrengthMeter) findViewById(R.id.strength_meter);
- createAccountButton = (Button) findViewById(R.id.create_account);
- progress = (ProgressBar) findViewById(R.id.progress_wheel);
-
- TextWatcher tw = new TextWatcher() {
-
- @Override
- public void beforeTextChanged(CharSequence s, int start, int count,
- int after) {
- }
-
- @Override
- public void onTextChanged(CharSequence s, int start, int before,
- int count) {
- enableOrDisableContinueButton();
- }
-
- @Override
- public void afterTextChanged(Editable s) {
- }
- };
-
- nicknameEntry.addTextChangedListener(tw);
- passwordEntry.addTextChangedListener(tw);
- passwordConfirmation.addTextChangedListener(tw);
- passwordConfirmation.setOnEditorActionListener(this);
- createAccountButton.setOnClickListener(this);
+ if (state == null) {
+ showInitialFragment(AuthorNameFragment.newInstance());
+ }
}
@Override
public void injectActivity(ActivityComponent component) {
component.inject(this);
+ setupController.setSetupActivity(this);
}
- private void enableOrDisableContinueButton() {
- if (progress == null) return; // Not created yet
- if (passwordEntry.getText().length() > 0 && passwordEntry.hasFocus())
- strengthMeter.setVisibility(VISIBLE);
- else strengthMeter.setVisibility(GONE);
- String nickname = nicknameEntry.getText().toString();
- int nicknameLength = StringUtils.toUtf8(nickname).length;
- String firstPassword = passwordEntry.getText().toString();
- String secondPassword = passwordConfirmation.getText().toString();
- boolean passwordsMatch = firstPassword.equals(secondPassword);
- float strength =
- setupController.estimatePasswordStrength(firstPassword);
- strengthMeter.setStrength(strength);
- UiUtils.setError(nicknameEntryWrapper,
- getString(R.string.name_too_long),
- nicknameLength > MAX_AUTHOR_NAME_LENGTH);
- UiUtils.setError(passwordEntryWrapper,
- getString(R.string.password_too_weak),
- firstPassword.length() > 0 && strength < QUITE_WEAK);
- UiUtils.setError(passwordConfirmationWrapper,
- getString(R.string.passwords_do_not_match),
- secondPassword.length() > 0 && !passwordsMatch);
- createAccountButton.setEnabled(nicknameLength > 0
- && nicknameLength <= MAX_AUTHOR_NAME_LENGTH
- && passwordsMatch && strength >= QUITE_WEAK);
+ public void showPasswordFragment() {
+ showNextFragment(PasswordFragment.newInstance());
}
- @Override
- public boolean onEditorAction(TextView v, int actionId, KeyEvent event) {
- hideSoftKeyboard(v);
- return true;
+ @TargetApi(23)
+ public void showDozeFragment() {
+ showNextFragment(DozeFragment.newInstance());
}
- @Override
- public void onClick(View view) {
- // Replace the button with a progress bar
- createAccountButton.setVisibility(INVISIBLE);
- progress.setVisibility(VISIBLE);
- String nickname = nicknameEntry.getText().toString();
- String password = passwordEntry.getText().toString();
-
- setupController.storeAuthorInfo(nickname, password,
- new UiResultHandler(this) {
- @Override
- public void onResultUi(Void result) {
- showMain();
- }
- });
- }
-
- private void showMain() {
+ public void showApp() {
Intent i = new Intent(this, NavDrawerActivity.class);
i.setFlags(FLAG_ACTIVITY_NEW_TASK);
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.");
+ }
+
}
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 5e72acb93..96ea253f8 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
@@ -6,9 +6,25 @@ import org.briarproject.briar.android.controller.handler.ResultHandler;
@NotNullByDefault
public interface SetupController {
+ void setSetupActivity(SetupActivity setupActivity);
+
+ boolean needsDozeWhitelisting();
+
+ void setAuthorName(String authorName);
+
+ void setPassword(String password);
+
float estimatePasswordStrength(String password);
- void storeAuthorInfo(String nickname, String password,
- ResultHandler resultHandler);
+ /**
+ * 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.
+ */
+ void showDozeOrCreateAccount();
+
+ void createAccount();
+
+ void createAccount(final ResultHandler 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 f413ca736..7fb8a7f7c 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
@@ -1,6 +1,7 @@
package org.briarproject.briar.android.login;
import android.content.SharedPreferences;
+import android.support.annotation.Nullable;
import org.briarproject.bramble.api.crypto.CryptoComponent;
import org.briarproject.bramble.api.crypto.CryptoExecutor;
@@ -9,6 +10,8 @@ import org.briarproject.bramble.api.crypto.SecretKey;
import org.briarproject.bramble.api.db.DatabaseConfig;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import org.briarproject.briar.android.controller.handler.ResultHandler;
+import org.briarproject.briar.android.controller.handler.UiResultHandler;
+import org.briarproject.briar.android.util.UiUtils;
import java.util.concurrent.Executor;
@@ -18,29 +21,75 @@ import javax.inject.Inject;
public class SetupControllerImpl extends PasswordControllerImpl
implements SetupController {
- private final PasswordStrengthEstimator strengthEstimator;
+ @Nullable
+ private String authorName, password;
+ @Nullable
+ private SetupActivity setupActivity;
@Inject
SetupControllerImpl(SharedPreferences briarPrefs,
DatabaseConfig databaseConfig,
@CryptoExecutor Executor cryptoExecutor, CryptoComponent crypto,
PasswordStrengthEstimator strengthEstimator) {
- super(briarPrefs, databaseConfig, cryptoExecutor, crypto);
- this.strengthEstimator = strengthEstimator;
+ super(briarPrefs, databaseConfig, cryptoExecutor, crypto,
+ strengthEstimator);
}
@Override
- public float estimatePasswordStrength(String password) {
- return strengthEstimator.estimateStrength(password);
+ public void setSetupActivity(SetupActivity setupActivity) {
+ this.setupActivity = setupActivity;
}
@Override
- public void storeAuthorInfo(final String nickname, final String password,
- final ResultHandler resultHandler) {
+ public boolean needsDozeWhitelisting() {
+ if (setupActivity == null) throw new IllegalStateException();
+ return UiUtils.needsDozeWhitelisting(setupActivity);
+ }
+
+ @Override
+ public void setAuthorName(String authorName) {
+ this.authorName = authorName;
+ if (setupActivity == null) throw new IllegalStateException();
+ setupActivity.showPasswordFragment();
+ }
+
+ @Override
+ public void setPassword(String password) {
+ this.password = password;
+ }
+
+ @Override
+ public void showDozeOrCreateAccount() {
+ if (setupActivity == null) throw new IllegalStateException();
+ if (needsDozeWhitelisting()) {
+ setupActivity.showDozeFragment();
+ } else {
+ createAccount();
+ }
+ }
+
+ @Override
+ public void createAccount() {
+ final UiResultHandler resultHandler =
+ new UiResultHandler(setupActivity) {
+ @Override
+ public void onResultUi(Void result) {
+ if (setupActivity == null)
+ throw new IllegalStateException();
+ setupActivity.showApp();
+ }
+ };
+ createAccount(resultHandler);
+ }
+
+ @Override
+ public void createAccount(final ResultHandler resultHandler) {
+ if (authorName == null || password == null)
+ throw new IllegalStateException();
cryptoExecutor.execute(new Runnable() {
@Override
public void run() {
- databaseConfig.setLocalAuthorName(nickname);
+ databaseConfig.setLocalAuthorName(authorName);
SecretKey key = crypto.generateSecretKey();
databaseConfig.setEncryptionKey(key);
String hex = encryptDatabaseKey(key, password);
diff --git a/briar-android/src/main/java/org/briarproject/briar/android/login/SetupFragment.java b/briar-android/src/main/java/org/briarproject/briar/android/login/SetupFragment.java
new file mode 100644
index 000000000..6a30e737a
--- /dev/null
+++ b/briar-android/src/main/java/org/briarproject/briar/android/login/SetupFragment.java
@@ -0,0 +1,66 @@
+package org.briarproject.briar.android.login;
+
+import android.text.Editable;
+import android.text.TextWatcher;
+import android.view.KeyEvent;
+import android.view.Menu;
+import android.view.MenuInflater;
+import android.view.MenuItem;
+import android.view.View.OnClickListener;
+import android.widget.TextView;
+import android.widget.TextView.OnEditorActionListener;
+
+import org.briarproject.briar.R;
+import org.briarproject.briar.android.fragment.BaseFragment;
+
+import javax.inject.Inject;
+
+import static org.briarproject.briar.android.util.UiUtils.showOnboardingDialog;
+
+abstract class SetupFragment extends BaseFragment implements TextWatcher,
+ OnEditorActionListener, OnClickListener {
+
+ @Inject
+ SetupController setupController;
+
+ @Override
+ public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
+ inflater.inflate(R.menu.help_action, menu);
+ super.onCreateOptionsMenu(menu, inflater);
+ }
+
+ @Override
+ public boolean onOptionsItemSelected(MenuItem item) {
+ if (item.getItemId() == R.id.action_help) {
+ showOnboardingDialog(getContext(), getHelpText());
+ return true;
+ } else {
+ return super.onOptionsItemSelected(item);
+ }
+ }
+
+ protected abstract String getHelpText();
+
+ @Override
+ public void beforeTextChanged(CharSequence charSequence, int i, int i1,
+ int i2) {
+ // noop
+ }
+
+ @Override
+ public void onTextChanged(CharSequence authorName, int i, int i1, int i2) {
+ // noop
+ }
+
+ @Override
+ public boolean onEditorAction(TextView textView, int i, KeyEvent keyEvent) {
+ onClick(textView);
+ return true;
+ }
+
+ @Override
+ public void afterTextChanged(Editable editable) {
+ // noop
+ }
+
+}
diff --git a/briar-android/src/main/java/org/briarproject/briar/android/navdrawer/NavDrawerActivity.java b/briar-android/src/main/java/org/briarproject/briar/android/navdrawer/NavDrawerActivity.java
index 058d55b55..08c16f784 100644
--- a/briar-android/src/main/java/org/briarproject/briar/android/navdrawer/NavDrawerActivity.java
+++ b/briar-android/src/main/java/org/briarproject/briar/android/navdrawer/NavDrawerActivity.java
@@ -1,14 +1,19 @@
package org.briarproject.briar.android.navdrawer;
+import android.annotation.SuppressLint;
+import android.annotation.TargetApi;
+import android.content.DialogInterface;
import android.content.Intent;
import android.content.res.Configuration;
import android.os.Bundle;
+import android.support.annotation.NonNull;
import android.support.design.widget.NavigationView;
import android.support.design.widget.NavigationView.OnNavigationItemSelectedListener;
import android.support.v4.app.FragmentTransaction;
import android.support.v4.content.ContextCompat;
import android.support.v4.widget.DrawerLayout;
import android.support.v7.app.ActionBarDrawerToggle;
+import android.support.v7.app.AlertDialog;
import android.support.v7.widget.Toolbar;
import android.view.LayoutInflater;
import android.view.MenuItem;
@@ -49,9 +54,12 @@ import static android.support.v4.view.GravityCompat.START;
import static android.support.v4.widget.DrawerLayout.LOCK_MODE_LOCKED_CLOSED;
import static android.view.View.GONE;
import static android.view.View.VISIBLE;
+import static org.briarproject.briar.android.activity.RequestCodes.REQUEST_DOZE_WHITELISTING;
import static org.briarproject.briar.android.navdrawer.NavDrawerController.ExpiryWarning.NO;
import static org.briarproject.briar.android.navdrawer.NavDrawerController.ExpiryWarning.UPDATE;
import static org.briarproject.briar.android.util.UiUtils.getDaysUntilExpiry;
+import static org.briarproject.briar.android.util.UiUtils.getDozeWhitelistingIntent;
+import static org.briarproject.briar.android.util.UiUtils.needsDozeWhitelisting;
public class NavDrawerActivity extends BriarActivity implements
BaseFragmentListener, TransportStateListener,
@@ -134,6 +142,7 @@ public class NavDrawerActivity extends BriarActivity implements
}
@Override
+ @SuppressLint("NewApi")
public void onStart() {
super.onStart();
updateTransports();
@@ -143,6 +152,7 @@ public class NavDrawerActivity extends BriarActivity implements
if (expiry != NO) showExpiryWarning(expiry);
}
});
+ if (needsDozeWhitelisting(this)) requestDozeWhitelisting();
}
private void exitIfStartupFailed(Intent intent) {
@@ -178,7 +188,7 @@ public class NavDrawerActivity extends BriarActivity implements
}
@Override
- public boolean onNavigationItemSelected(MenuItem item) {
+ public boolean onNavigationItemSelected(@NonNull MenuItem item) {
drawerLayout.closeDrawer(START);
clearBackStack();
loadFragment(item.getItemId());
@@ -311,6 +321,24 @@ public class NavDrawerActivity extends BriarActivity implements
expiryWarning.setVisibility(VISIBLE);
}
+ @TargetApi(23)
+ private void requestDozeWhitelisting() {
+ new AlertDialog.Builder(this, R.style.BriarDialogTheme)
+ .setMessage(R.string.setup_doze_intro)
+ .setPositiveButton(R.string.ok,
+ new DialogInterface.OnClickListener() {
+ @Override
+ public void onClick(DialogInterface dialog,
+ int which) {
+ Intent i = getDozeWhitelistingIntent(
+ NavDrawerActivity.this);
+ startActivityForResult(i,
+ REQUEST_DOZE_WHITELISTING);
+ }
+ })
+ .show();
+ }
+
private void initializeTransports(final LayoutInflater inflater) {
transports = new ArrayList<>(3);
diff --git a/briar-android/src/main/java/org/briarproject/briar/android/util/UiUtils.java b/briar-android/src/main/java/org/briarproject/briar/android/util/UiUtils.java
index 74f182cbc..448252659 100644
--- a/briar-android/src/main/java/org/briarproject/briar/android/util/UiUtils.java
+++ b/briar-android/src/main/java/org/briarproject/briar/android/util/UiUtils.java
@@ -1,14 +1,18 @@
package org.briarproject.briar.android.util;
+import android.annotation.SuppressLint;
+import android.annotation.TargetApi;
import android.content.Context;
-
import android.content.DialogInterface;
import android.content.DialogInterface.OnClickListener;
import android.content.Intent;
import android.net.Uri;
+import android.os.Build;
+import android.os.PowerManager;
import android.support.design.widget.TextInputLayout;
import android.support.v4.app.FragmentManager;
import android.support.v4.content.ContextCompat;
+import android.support.v7.app.AlertDialog;
import android.support.v7.app.AppCompatActivity;
import android.text.Html;
import android.text.Spannable;
@@ -23,14 +27,16 @@ import android.view.View;
import android.widget.TextView;
import org.briarproject.bramble.api.contact.ContactId;
-import org.briarproject.briar.BuildConfig;
import org.briarproject.briar.R;
import org.briarproject.briar.android.view.ArticleMovementMethod;
import org.briarproject.briar.android.widget.LinkDialogFragment;
import javax.annotation.Nullable;
-import static android.content.Intent.*;
+import static android.content.Context.POWER_SERVICE;
+import static android.content.Intent.CATEGORY_DEFAULT;
+import static android.content.Intent.FLAG_ACTIVITY_NEW_TASK;
+import static android.provider.Settings.ACTION_REQUEST_IGNORE_BATTERY_OPTIMIZATIONS;
import static android.text.format.DateUtils.DAY_IN_MILLIS;
import static android.text.format.DateUtils.FORMAT_ABBREV_MONTH;
import static android.text.format.DateUtils.FORMAT_ABBREV_RELATIVE;
@@ -38,7 +44,7 @@ import static android.text.format.DateUtils.FORMAT_ABBREV_TIME;
import static android.text.format.DateUtils.FORMAT_SHOW_DATE;
import static android.text.format.DateUtils.MINUTE_IN_MILLIS;
import static android.text.format.DateUtils.WEEK_IN_MILLIS;
-import static org.briarproject.briar.BuildConfig.*;
+import static org.briarproject.briar.BuildConfig.APPLICATION_ID;
import static org.briarproject.briar.android.BriarApplication.EXPIRY_DATE;
public class UiUtils {
@@ -149,4 +155,37 @@ public class UiUtils {
}
};
}
+
+ public static void showOnboardingDialog(Context ctx, String text) {
+ new AlertDialog.Builder(ctx, R.style.OnboardingDialogTheme)
+ .setMessage(text)
+ .setNeutralButton(R.string.got_it,
+ new DialogInterface.OnClickListener() {
+ @Override
+ public void onClick(DialogInterface dialog,
+ int which) {
+ dialog.cancel();
+ }
+ })
+ .show();
+ }
+
+ public static boolean needsDozeWhitelisting(Context ctx) {
+ if (Build.VERSION.SDK_INT < 23) return false;
+ PowerManager pm =
+ (PowerManager) ctx.getSystemService(POWER_SERVICE);
+ String packageName = ctx.getPackageName();
+ if (pm == null) throw new AssertionError();
+ return !pm.isIgnoringBatteryOptimizations(packageName);
+ }
+
+ @TargetApi(23)
+ @SuppressLint("BatteryLife")
+ public static Intent getDozeWhitelistingIntent(Context ctx) {
+ Intent i = new Intent();
+ i.setAction(ACTION_REQUEST_IGNORE_BATTERY_OPTIMIZATIONS);
+ i.setData(Uri.parse("package:" + ctx.getPackageName()));
+ return i;
+ }
+
}
diff --git a/briar-android/src/main/res/layout/fragment_setup_author_name.xml b/briar-android/src/main/res/layout/fragment_setup_author_name.xml
new file mode 100644
index 000000000..8f22bc7ed
--- /dev/null
+++ b/briar-android/src/main/res/layout/fragment_setup_author_name.xml
@@ -0,0 +1,60 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/briar-android/src/main/res/layout/fragment_setup_doze.xml b/briar-android/src/main/res/layout/fragment_setup_doze.xml
new file mode 100644
index 000000000..fedb98f6d
--- /dev/null
+++ b/briar-android/src/main/res/layout/fragment_setup_doze.xml
@@ -0,0 +1,54 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/briar-android/src/main/res/layout/activity_setup.xml b/briar-android/src/main/res/layout/fragment_setup_password.xml
similarity index 54%
rename from briar-android/src/main/res/layout/activity_setup.xml
rename to briar-android/src/main/res/layout/fragment_setup_password.xml
index b1120debd..5a925750e 100644
--- a/briar-android/src/main/res/layout/activity_setup.xml
+++ b/briar-android/src/main/res/layout/fragment_setup_password.xml
@@ -5,12 +5,11 @@
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
- tools:context=".android.login.SetupActivity">
+ android:fillViewport="true">
-
-
-
-
-
-
-
-
+ android:layout_marginTop="8dp"
+ app:errorEnabled="true"
+ app:hintEnabled="false"
+ app:layout_constraintLeft_toLeftOf="parent"
+ app:layout_constraintRight_toRightOf="parent"
+ app:layout_constraintTop_toTopOf="parent">
+ android:maxLines="1">
+
+
+
+
+ android:layout_marginTop="8dp"
+ android:visibility="invisible"
+ app:layout_constraintLeft_toLeftOf="parent"
+ app:layout_constraintRight_toRightOf="parent"
+ app:layout_constraintTop_toBottomOf="@+id/password_entry_wrapper"
+ tools:visibility="visible"/>
+ android:layout_marginTop="8dp"
+ app:errorEnabled="true"
+ app:hintEnabled="false"
+ app:layout_constraintLeft_toLeftOf="parent"
+ app:layout_constraintRight_toRightOf="parent"
+ app:layout_constraintTop_toBottomOf="@+id/strength_meter">
+ android:text="@string/setup_next"
+ app:layout_constraintBottom_toBottomOf="parent"
+ app:layout_constraintLeft_toLeftOf="parent"
+ app:layout_constraintRight_toRightOf="parent"
+ app:layout_constraintTop_toBottomOf="@+id/password_confirm_wrapper"
+ app:layout_constraintVertical_bias="1.0"
+ tools:enabled="true"/>
+ android:visibility="invisible"
+ app:layout_constraintBottom_toBottomOf="parent"
+ app:layout_constraintLeft_toLeftOf="parent"
+ app:layout_constraintRight_toRightOf="parent"
+ app:layout_constraintTop_toBottomOf="@+id/password_confirm_wrapper"
+ app:layout_constraintVertical_bias="1.0"/>
-
+
-
\ No newline at end of file
+
diff --git a/briar-android/src/main/res/menu/help_action.xml b/briar-android/src/main/res/menu/help_action.xml
new file mode 100644
index 000000000..a0e4c3d2c
--- /dev/null
+++ b/briar-android/src/main/res/menu/help_action.xml
@@ -0,0 +1,12 @@
+
+
\ No newline at end of file
diff --git a/briar-android/src/main/res/values-bg/strings.xml b/briar-android/src/main/res/values-bg/strings.xml
index 62169ffce..747ec467f 100644
--- a/briar-android/src/main/res/values-bg/strings.xml
+++ b/briar-android/src/main/res/values-bg/strings.xml
@@ -2,7 +2,7 @@
Briar регистрация
- Briar профилът се съхранява криптиран във вашето устройство, а не в облака. Ако деинсталирате Briar или забравите паролата си, няма как да възстановите профила и данните си.
+ Briar профилът се съхранява криптиран във вашето устройство, а не в облака. Ако деинсталирате Briar или забравите паролата си, няма как да възстановите профила и данните си.
Изберете име
Изберете парола
Потвърдете парола
diff --git a/briar-android/src/main/res/values-ca/strings.xml b/briar-android/src/main/res/values-ca/strings.xml
index e10b2fe88..58fe1a2c6 100644
--- a/briar-android/src/main/res/values-ca/strings.xml
+++ b/briar-android/src/main/res/values-ca/strings.xml
@@ -2,7 +2,7 @@
Configuració de Briar
- El teu compte de Briar està encriptat al teu dispositiu, no al núvol. Si desinstal·les Briar o oblides la contrasenya, no hi ha manera de recuperar el teu compte i les teves dades.
+ El teu compte de Briar està encriptat al teu dispositiu, no al núvol. Si desinstal·les Briar o oblides la contrasenya, no hi ha manera de recuperar el teu compte i les teves dades.
Trieu el sobrenom
Trieu la contrasenya
Confirmeu la contrasenya
diff --git a/briar-android/src/main/res/values-de/strings.xml b/briar-android/src/main/res/values-de/strings.xml
index 9b4a0648a..0948375f4 100644
--- a/briar-android/src/main/res/values-de/strings.xml
+++ b/briar-android/src/main/res/values-de/strings.xml
@@ -2,7 +2,7 @@
Briar einrichten
- Dein Briar-Konto wird verschlüsselt auf deinem Gerät gespeichert und nicht mit der \"Cloud\" synchronisiert. Wenn du Briar deinstallierst oder dein Passwort vergisst, können das Konto und deine Daten nicht wiederhergestellt werden.
+ Dein Briar-Konto wird verschlüsselt auf deinem Gerät gespeichert und nicht mit der \"Cloud\" synchronisiert. Wenn du Briar deinstallierst oder dein Passwort vergisst, können das Konto und deine Daten nicht wiederhergestellt werden.
Wähle deinen Benutzernamen
Wähle dein Passwort
Passwort bestätigen
diff --git a/briar-android/src/main/res/values-es/strings.xml b/briar-android/src/main/res/values-es/strings.xml
index 16de8f81a..d662b4746 100644
--- a/briar-android/src/main/res/values-es/strings.xml
+++ b/briar-android/src/main/res/values-es/strings.xml
@@ -2,7 +2,7 @@
Configuración de Briar
- Tu cuenta de Briar se almacena de manera cifrada en tu dispositivo y no en ninguna nube. Si desinstalas Briar u olvidas tu contraseña, no podrás recuperar ni tu cuenta ni tus datos.
+ Tu cuenta de Briar se almacena de manera cifrada en tu dispositivo y no en ninguna nube. Si desinstalas Briar u olvidas tu contraseña, no podrás recuperar ni tu cuenta ni tus datos.
Elige tu nombre de usuario
Elige tu contraseña
Confirma tu contraseña
diff --git a/briar-android/src/main/res/values-eu/strings.xml b/briar-android/src/main/res/values-eu/strings.xml
index 9e188e369..7e39e8d2c 100644
--- a/briar-android/src/main/res/values-eu/strings.xml
+++ b/briar-android/src/main/res/values-eu/strings.xml
@@ -2,7 +2,7 @@
Briar ezarpena
- Zure Briar kontua zure gailuan zifratuta gordetzen da, ez hodeian. Briar desinstalatzen baduzu edo pasahitza ahazten baduzu, ez dago zure kontua eta datuak berreskuratzeko modurik.
+ Zure Briar kontua zure gailuan zifratuta gordetzen da, ez hodeian. Briar desinstalatzen baduzu edo pasahitza ahazten baduzu, ez dago zure kontua eta datuak berreskuratzeko modurik.
Hautatu zure ezizena
Hautatu zure pasahitza
Berretsi zure pasahitza
diff --git a/briar-android/src/main/res/values-fi/strings.xml b/briar-android/src/main/res/values-fi/strings.xml
index b45fcb161..88787a893 100644
--- a/briar-android/src/main/res/values-fi/strings.xml
+++ b/briar-android/src/main/res/values-fi/strings.xml
@@ -2,7 +2,7 @@
Briarin asetus
- Sinun Briar tili on tallennettu salattuna sinun laitteelle, ei pilvipalvelimelle. Jos poistat Briarin asennuksen tai unohdat salasanasi, ei ole mitään keinoa jolla tilisi tai dataasi voisi palauttaa.
+ Sinun Briar tili on tallennettu salattuna sinun laitteelle, ei pilvipalvelimelle. Jos poistat Briarin asennuksen tai unohdat salasanasi, ei ole mitään keinoa jolla tilisi tai dataasi voisi palauttaa.
Valitse nimimerkki
Valitse salasana
Vahvista salasana
diff --git a/briar-android/src/main/res/values-fr/strings.xml b/briar-android/src/main/res/values-fr/strings.xml
index 8046f385f..67ef5fd28 100644
--- a/briar-android/src/main/res/values-fr/strings.xml
+++ b/briar-android/src/main/res/values-fr/strings.xml
@@ -2,7 +2,7 @@
Configuration de Briar
- Votre compte Briar est enregistré chiffré sur votre appareil et non sur le nuage. Si vous désinstallez Briar ou oubliez votre mot de passe, votre compte et vos données sont irrécupérables.
+ Votre compte Briar est enregistré chiffré sur votre appareil et non sur le nuage. Si vous désinstallez Briar ou oubliez votre mot de passe, votre compte et vos données sont irrécupérables.
Choisir votre pseudonyme
Choisir votre mot de passe
Confirmer votre mot de passe
diff --git a/briar-android/src/main/res/values-gl/strings.xml b/briar-android/src/main/res/values-gl/strings.xml
index 163112a9f..db68f1819 100644
--- a/briar-android/src/main/res/values-gl/strings.xml
+++ b/briar-android/src/main/res/values-gl/strings.xml
@@ -2,7 +2,7 @@
Configuración de Briar
- Briar almacena a súa configuración encriptada no dispositivo, non na nube. Se desinstala Briar ou esquece a súa clave, non hai forma de recuperar a súa conta e datos.
+ Briar almacena a súa configuración encriptada no dispositivo, non na nube. Se desinstala Briar ou esquece a súa clave, non hai forma de recuperar a súa conta e datos.
Escolle o teu alcume
Escolle a túa clave
Confirma a túa clave
diff --git a/briar-android/src/main/res/values-hi/strings.xml b/briar-android/src/main/res/values-hi/strings.xml
index 75a65240b..272d6edbb 100644
--- a/briar-android/src/main/res/values-hi/strings.xml
+++ b/briar-android/src/main/res/values-hi/strings.xml
@@ -2,7 +2,7 @@
ब्रियर सेटअप
- आपका ब्रियर खाता आपके डिवाइस पर एन्क्रिप्ट किया गया है, न कि क्लाउड में। यदि आप बिअर की स्थापना रद्द करते हैं या अपना पासवर्ड भूल जाते हैं, तो आपके खाता और आपके डेटा को पुनर्प्राप्त करने का कोई तरीका नहीं है।
+ आपका ब्रियर खाता आपके डिवाइस पर एन्क्रिप्ट किया गया है, न कि क्लाउड में। यदि आप बिअर की स्थापना रद्द करते हैं या अपना पासवर्ड भूल जाते हैं, तो आपके खाता और आपके डेटा को पुनर्प्राप्त करने का कोई तरीका नहीं है।
आपका मुंहबोला नाम चुनें
अपना पासवर्ड चुनें
अपने पासवर्ड की पुष्टि करें
diff --git a/briar-android/src/main/res/values-it/strings.xml b/briar-android/src/main/res/values-it/strings.xml
index 55bbdec45..11af43134 100644
--- a/briar-android/src/main/res/values-it/strings.xml
+++ b/briar-android/src/main/res/values-it/strings.xml
@@ -2,7 +2,7 @@
Impostazione Briar
- Il tuo account Briar si trova criptato sul tuo dispositivo e non nel cloud. Se disinstalli Briar o dimentichi la tua password, non c\'è modo di recuperare il tuo account o i tuoi dati.
+ Il tuo account Briar si trova criptato sul tuo dispositivo e non nel cloud. Se disinstalli Briar o dimentichi la tua password, non c\'è modo di recuperare il tuo account o i tuoi dati.
Scegli il tuo nickname
Scegli la tua password
Conferma la tua password
diff --git a/briar-android/src/main/res/values-nb/strings.xml b/briar-android/src/main/res/values-nb/strings.xml
index e0bea86d8..91f605a60 100644
--- a/briar-android/src/main/res/values-nb/strings.xml
+++ b/briar-android/src/main/res/values-nb/strings.xml
@@ -2,7 +2,7 @@
Oppsett av Briar
- Din Briar-konto er lagret kryptert på din enhet, ikke i skyen. Hvis du avinstallerer Briar eller glemmer passordet ditt, går det ikke an å gjenopprette kontoen og dataen din.
+ Din Briar-konto er lagret kryptert på din enhet, ikke i skyen. Hvis du avinstallerer Briar eller glemmer passordet ditt, går det ikke an å gjenopprette kontoen og dataen din.
Velg kallenavn
Velg passord
Bekreft passord
diff --git a/briar-android/src/main/res/values-oc/strings.xml b/briar-android/src/main/res/values-oc/strings.xml
index 506da45b3..af0cf51c9 100644
--- a/briar-android/src/main/res/values-oc/strings.xml
+++ b/briar-android/src/main/res/values-oc/strings.xml
@@ -2,7 +2,7 @@
Configuracion de Briar
- Vòstre compte Briar es salvat e chifrat sus vòstre aparelh, non pas sus un servidor alonhat \"cloud\". Se desinstalletz Briar o oblidetz vòstre senhal, vòstre compte e vòstras donadas serà pas possible de los recuperar.
+ Vòstre compte Briar es salvat e chifrat sus vòstre aparelh, non pas sus un servidor alonhat \"cloud\". Se desinstalletz Briar o oblidetz vòstre senhal, vòstre compte e vòstras donadas serà pas possible de los recuperar.
Causir un escais-nom
Causir un senhal
Confirmar lo senhal
diff --git a/briar-android/src/main/res/values-pt-rBR/strings.xml b/briar-android/src/main/res/values-pt-rBR/strings.xml
index 3dc461fb0..68a5e6f3b 100644
--- a/briar-android/src/main/res/values-pt-rBR/strings.xml
+++ b/briar-android/src/main/res/values-pt-rBR/strings.xml
@@ -2,7 +2,7 @@
Configuração de Briar
- Sua conta Briar é armazenada criptografada apenas no seu dispositivo, não na nuvem. Se você Desinstalar o Briar ou esquecer sua senha, não será possível recuperar sua conta e seus dados.
+ Sua conta Briar é armazenada criptografada apenas no seu dispositivo, não na nuvem. Se você Desinstalar o Briar ou esquecer sua senha, não será possível recuperar sua conta e seus dados.
Escolha seu apelido
Escolha sua senha
Confirme sua senha
diff --git a/briar-android/src/main/res/values-ru/strings.xml b/briar-android/src/main/res/values-ru/strings.xml
index 9e2c749a5..f053c81f8 100644
--- a/briar-android/src/main/res/values-ru/strings.xml
+++ b/briar-android/src/main/res/values-ru/strings.xml
@@ -2,7 +2,7 @@
Настройка Briar
- Ваша учетная запись Briar хранится в зашифрованном виде только на устройстве. Если вы удалите Briar или забудете пароль, то не сможете восстановить свою учетную запись и данные.
+ Ваша учетная запись Briar хранится в зашифрованном виде только на устройстве. Если вы удалите Briar или забудете пароль, то не сможете восстановить свою учетную запись и данные.
Выберите псевдоним
Выберите пароль
Подтвердите пароль
diff --git a/briar-android/src/main/res/values-sq/strings.xml b/briar-android/src/main/res/values-sq/strings.xml
index 792c5f7c0..b88bb515c 100644
--- a/briar-android/src/main/res/values-sq/strings.xml
+++ b/briar-android/src/main/res/values-sq/strings.xml
@@ -2,7 +2,7 @@
Rregullimi i Briar-it
- Llogaria juaj Briar depozitohet e fshehtëzuar në pajisjen tuaj, jo në re. Nëse e çinstaloni Briar-in ose harroni fjalëkalimin tuaj, nuk ka rrugë për ta rimarrë llogarinë tuaj dhe të dhënat tuaja.
+ Llogaria juaj Briar depozitohet e fshehtëzuar në pajisjen tuaj, jo në re. Nëse e çinstaloni Briar-in ose harroni fjalëkalimin tuaj, nuk ka rrugë për ta rimarrë llogarinë tuaj dhe të dhënat tuaja.
Zgjidhni nofkën tuaj
Zgjidhni fjalëkalimin tuaj
Ripohoni fjalëkalimin tuaj
diff --git a/briar-android/src/main/res/values-sr/strings.xml b/briar-android/src/main/res/values-sr/strings.xml
index 86f1fa3e7..6bf0c4585 100644
--- a/briar-android/src/main/res/values-sr/strings.xml
+++ b/briar-android/src/main/res/values-sr/strings.xml
@@ -2,7 +2,7 @@
Briar Podešavanje
- Vaš Briar račun je kriptovan i sačuvan na vašem uređaju, ne u server-oblaku. Ako deinstalirate Briar ili zaboravite šifru, nema načina da povratite vaš račun ili vaše podatke.
+ Vaš Briar račun je kriptovan i sačuvan na vašem uređaju, ne u server-oblaku. Ako deinstalirate Briar ili zaboravite šifru, nema načina da povratite vaš račun ili vaše podatke.
Izaberite vaš nadimak
Izaberite vašu šifru
Potvrdite vašu šifru
diff --git a/briar-android/src/main/res/values-tr/strings.xml b/briar-android/src/main/res/values-tr/strings.xml
index 19b78908a..9b7c1ac5a 100644
--- a/briar-android/src/main/res/values-tr/strings.xml
+++ b/briar-android/src/main/res/values-tr/strings.xml
@@ -2,7 +2,7 @@
Briar Kurulum
- Briar hesabınız bulutta değil, cihazınızda şifreli olarak saklanır. Briar\'ı kaldırırsanız veya şifrenizi unutursanız, hesabınızı ve verilerinizi kurtarmanın bir yolu yoktur.
+ Briar hesabınız bulutta değil, cihazınızda şifreli olarak saklanır. Briar\'ı kaldırırsanız veya şifrenizi unutursanız, hesabınızı ve verilerinizi kurtarmanın bir yolu yoktur.
Kullanıcı adınızı belirleyin
Parolanızı belirleyin
Parolanızı doğrulayın
diff --git a/briar-android/src/main/res/values-zh-rCN/strings.xml b/briar-android/src/main/res/values-zh-rCN/strings.xml
index f99ebc279..d7c127577 100644
--- a/briar-android/src/main/res/values-zh-rCN/strings.xml
+++ b/briar-android/src/main/res/values-zh-rCN/strings.xml
@@ -2,7 +2,7 @@
安装 Briar
- 您的 Briar 账号只会被加密储存在您的设备上,不会被上传。如果您卸载了 Briar 或忘记了密码,将无法恢复您的账号和数据。
+ 您的 Briar 账号只会被加密储存在您的设备上,不会被上传。如果您卸载了 Briar 或忘记了密码,将无法恢复您的账号和数据。
设置昵称
设置密码
确认密码
diff --git a/briar-android/src/main/res/values/strings.xml b/briar-android/src/main/res/values/strings.xml
index dd04625cc..0c800fe0c 100644
--- a/briar-android/src/main/res/values/strings.xml
+++ b/briar-android/src/main/res/values/strings.xml
@@ -2,8 +2,15 @@
- Briar Setup
- Your Briar account is stored encrypted on your device, not in the cloud. If you uninstall Briar or forget your password, there\'s no way to recover your account and your data.
+ Welcome to Briar
+ Choose your user name wisely. You can not change it later and it will be shown next to content you post.\n\nWhen this content is shared, strangers might see your name.
+ Next
+ Choose a Password
+ Your Briar account is stored encrypted on your device, not in the cloud. If you forget your password or uninstall Briar, there\'s no way to recover your account.\n\nChoose a long password that\'s hard to guess, such as four random words, or ten random letters, numbers and symbols.
+ Background Connections
+ To receive messages, Briar needs to stay connected in the background.
+ To receive messages, Briar needs to stay connected in the background. Please disable battery optimizations so Briar can stay connected.
+ Allow Connections
Choose your nickname
Choose your password
Confirm your password
@@ -11,6 +18,7 @@
Password is too weak
Passwords do not match
Create Account
+ More Information
Enter your password:
diff --git a/briar-android/src/test/java/org/briarproject/briar/android/login/ChangePasswordActivityTest.java b/briar-android/src/test/java/org/briarproject/briar/android/login/ChangePasswordActivityTest.java
index 24c84835a..af3cccf26 100644
--- a/briar-android/src/test/java/org/briarproject/briar/android/login/ChangePasswordActivityTest.java
+++ b/briar-android/src/test/java/org/briarproject/briar/android/login/ChangePasswordActivityTest.java
@@ -57,8 +57,6 @@ public class ChangePasswordActivityTest {
@Mock
private PasswordController passwordController;
- @Mock
- private SetupController setupController;
@Captor
private ArgumentCaptor> resultCaptor;
@@ -71,14 +69,18 @@ public class ChangePasswordActivityTest {
.findViewById(R.id.new_password_confirm_wrapper);
currentPassword = (EditText) changePasswordActivity
.findViewById(R.id.current_password_entry);
- newPassword = (EditText) changePasswordActivity
- .findViewById(R.id.new_password_entry);
- newPasswordConfirmation = (EditText) changePasswordActivity
- .findViewById(R.id.new_password_confirm);
- strengthMeter = (StrengthMeter) changePasswordActivity
- .findViewById(R.id.strength_meter);
- changePasswordButton = (Button) changePasswordActivity
- .findViewById(R.id.change_password);
+ newPassword =
+ (EditText) changePasswordActivity
+ .findViewById(R.id.new_password_entry);
+ newPasswordConfirmation =
+ (EditText) changePasswordActivity
+ .findViewById(R.id.new_password_confirm);
+ strengthMeter =
+ (StrengthMeter) changePasswordActivity
+ .findViewById(R.id.strength_meter);
+ changePasswordButton =
+ (Button) changePasswordActivity
+ .findViewById(R.id.change_password);
}
private void testStrengthMeter(String pass, float strength, int color) {
@@ -110,12 +112,9 @@ public class ChangePasswordActivityTest {
@Test
public void testChangePasswordUI() {
- PasswordController mockedPasswordController = this.passwordController;
- SetupController mockedSetupController = this.setupController;
- changePasswordActivity.setPasswordController(mockedPasswordController);
- changePasswordActivity.setSetupController(mockedSetupController);
+ changePasswordActivity.setPasswordController(passwordController);
// Mock strong password strength answer
- when(mockedSetupController.estimatePasswordStrength(anyString()))
+ when(passwordController.estimatePasswordStrength(anyString()))
.thenReturn(STRONG);
String curPass = "old.password";
String safePass = "really.safe.password";
@@ -127,7 +126,7 @@ public class ChangePasswordActivityTest {
changePasswordButton.performClick();
// Verify that the controller's method was called with the correct
// params and get the callback
- verify(mockedPasswordController, times(1))
+ verify(passwordController, times(1))
.changePassword(eq(curPass), eq(safePass),
resultCaptor.capture());
// execute the callbacks
@@ -139,23 +138,24 @@ public class ChangePasswordActivityTest {
public void testPasswordChange() {
PasswordController passwordController =
changePasswordActivity.getPasswordController();
- SetupController setupController =
- changePasswordActivity.getSetupController();
+
+ TestSetupActivity setupActivity =
+ Robolectric.setupActivity(TestSetupActivity.class);
+ SetupController setupController = setupActivity.getController();
+ setupController.setAuthorName("nick");
+ setupController.setPassword("some.old.pass");
// mock a resulthandler
- ResultHandler resultHandler =
- (ResultHandler) mock(ResultHandler.class);
- setupController.storeAuthorInfo("nick", "some.old.pass", resultHandler);
- // blocking verification call with timeout that waits until the mocked
- // result gets called with handle 0L, the expected value
+ ResultHandler resultHandler = mock(ResultHandler.class);
+ setupController.createAccount(resultHandler);
verify(resultHandler, timeout(TIMEOUT_MS).times(1)).onResult(null);
+
SharedPreferences prefs = changePasswordActivity
.getSharedPreferences("db", Context.MODE_PRIVATE);
// Confirm database key
assertTrue(prefs.contains("key"));
String oldKey = prefs.getString("key", null);
// mock a resulthandler
- ResultHandler resultHandler2 =
- (ResultHandler) mock(ResultHandler.class);
+ ResultHandler resultHandler2 = mock(ResultHandler.class);
passwordController.changePassword("some.old.pass", "some.strong.pass",
resultHandler2);
// blocking verification call with timeout that waits until the mocked
@@ -164,14 +164,14 @@ public class ChangePasswordActivityTest {
// Confirm database key
assertTrue(prefs.contains("key"));
assertNotEquals(oldKey, prefs.getString("key", null));
- // Note that Robolectric uses its own persistant storage that it
+ // Note that Robolectric uses its own persistent storage that it
// wipes clean after each test run, no need to clean up manually.
}
@Test
public void testStrengthMeter() {
- SetupController controller =
- changePasswordActivity.getSetupController();
+ PasswordController controller =
+ changePasswordActivity.getPasswordController();
String strongPass = "very.strong.password.123";
String weakPass = "we";
@@ -188,9 +188,9 @@ public class ChangePasswordActivityTest {
@Test
public void testStrengthMeterUI() {
Assert.assertNotNull(changePasswordActivity);
- // replace the setup controller with our mocked copy
- SetupController mockedController = this.setupController;
- changePasswordActivity.setSetupController(mockedController);
+ // replace the password controller with our mocked copy
+ PasswordController mockedController = this.passwordController;
+ changePasswordActivity.setPasswordController(mockedController);
// Mock answers for UI testing only
when(mockedController.estimatePasswordStrength("strong")).thenReturn(
STRONG);
@@ -220,4 +220,5 @@ public class ChangePasswordActivityTest {
Mockito.verify(mockedController, Mockito.times(1))
.estimatePasswordStrength(eq("empty"));
}
+
}
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 7841d792b..38c45f044 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
@@ -19,30 +19,24 @@ import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
-import org.mockito.ArgumentCaptor;
-import org.mockito.Captor;
-import org.mockito.Mock;
-import org.mockito.Mockito;
import org.mockito.MockitoAnnotations;
import org.robolectric.Robolectric;
import org.robolectric.RobolectricGradleTestRunner;
import org.robolectric.annotation.Config;
import org.robolectric.shadows.ShadowActivity;
+import org.robolectric.shadows.ShadowLooper;
import static junit.framework.Assert.assertEquals;
+import static junit.framework.Assert.assertNotNull;
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.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(RobolectricGradleTestRunner.class)
@@ -62,84 +56,15 @@ public class SetupActivityTest {
private StrengthMeter strengthMeter;
private Button createAccountButton;
- @Mock
- private SetupController setupController;
- @Captor
- private ArgumentCaptor> authorCaptor;
-
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
setupActivity = Robolectric.setupActivity(TestSetupActivity.class);
nicknameEntryWrapper = (TextInputLayout) setupActivity
.findViewById(R.id.nickname_entry_wrapper);
- passwordConfirmationWrapper = (TextInputLayout) setupActivity
- .findViewById(R.id.password_confirm_wrapper);
nicknameEntry =
(EditText) setupActivity.findViewById(R.id.nickname_entry);
- passwordEntry =
- (EditText) setupActivity.findViewById(R.id.password_entry);
- passwordConfirmation =
- (EditText) setupActivity.findViewById(R.id.password_confirm);
- strengthMeter =
- (StrengthMeter) setupActivity.findViewById(R.id.strength_meter);
- createAccountButton =
- (Button) setupActivity.findViewById(R.id.create_account);
- }
-
- private void testStrengthMeter(String pass, float strength, int color) {
- passwordEntry.setText(pass);
- assertEquals(strengthMeter.getProgress(),
- (int) (strengthMeter.getMax() * strength));
- assertEquals(color, strengthMeter.getColor());
- }
-
- @Test
- public void testPasswordMatchUI() {
- // Password mismatch
- passwordEntry.setText("really.safe.password");
- passwordConfirmation.setText("really.safe.pass");
- assertEquals(createAccountButton.isEnabled(), false);
- assertEquals(passwordConfirmationWrapper.getError(),
- setupActivity.getString(R.string.passwords_do_not_match));
- // Button enabled
- passwordEntry.setText("really.safe.pass");
- passwordConfirmation.setText("really.safe.pass");
- // Confirm that the password mismatch error message is not visible
- Assert.assertNotEquals(passwordConfirmationWrapper.getError(),
- setupActivity.getString(R.string.passwords_do_not_match));
- // Nick has not been set, expect the button to be disabled
- assertEquals(createAccountButton.isEnabled(), false);
- }
-
- @Test
- public void testCreateAccountUI() {
- SetupController mockedController = this.setupController;
- setupActivity.setController(mockedController);
- // Mock strong password strength answer
- when(mockedController.estimatePasswordStrength(anyString())).thenReturn(
- STRONG);
- String safePass = "really.safe.password";
- String nick = "nick.nickerton";
- passwordEntry.setText(safePass);
- passwordConfirmation.setText(safePass);
- nicknameEntry.setText(nick);
- // Confirm that the create account button is clickable
- assertEquals(createAccountButton.isEnabled(), true);
- createAccountButton.performClick();
- // Verify that the controller's method was called with the correct
- // params and get the callback
- verify(mockedController, times(1))
- .storeAuthorInfo(eq(nick), eq(safePass),
- authorCaptor.capture());
- authorCaptor.getValue().onResult(null);
- // execute the callback
- assertEquals(setupActivity.isFinishing(), true);
- // Confirm that the correct Activity has been started
- ShadowActivity shadowActivity = shadowOf(setupActivity);
- Intent intent = shadowActivity.peekNextStartedActivity();
- assertEquals(intent.getComponent().getClassName(),
- NavDrawerActivity.class.getName());
+ createAccountButton = (Button) setupActivity.findViewById(R.id.next);
}
@Test
@@ -154,21 +79,65 @@ public class SetupActivityTest {
setupActivity.getString(R.string.name_too_long));
}
+ @Test
+ public void testPasswordMatchUI() {
+ proceedToPasswordFragment();
+ // Password mismatch
+ passwordEntry.setText("really.safe.password");
+ passwordConfirmation.setText("really.safe.pass");
+ assertEquals(createAccountButton.isEnabled(), false);
+ assertEquals(passwordConfirmationWrapper.getError(),
+ setupActivity.getString(R.string.passwords_do_not_match));
+ // Button enabled
+ passwordEntry.setText("really.safe.pass");
+ passwordConfirmation.setText("really.safe.pass");
+ // Confirm that the password mismatch error message is not visible
+ Assert.assertNotEquals(passwordConfirmationWrapper.getError(),
+ setupActivity.getString(R.string.passwords_do_not_match));
+ // Passwords match, so button should be enabled
+ assertEquals(createAccountButton.isEnabled(), true);
+ }
+
+ @Test
+ public void testCreateAccountUI() {
+ proceedToPasswordFragment();
+ String safePass = "really.safe.password";
+ passwordEntry.setText(safePass);
+ passwordConfirmation.setText(safePass);
+ // Confirm that the create account button is clickable
+ assertEquals(createAccountButton.isEnabled(), true);
+ createAccountButton.performClick();
+ // wait a second since there's no easy way to get a callback
+ try {
+ Thread.sleep(1000);
+ } catch (InterruptedException e) {
+ e.printStackTrace();
+ }
+ ShadowLooper.runUiThreadTasks();
+ // execute the callback
+ assertTrue(setupActivity.isFinishing());
+ // Confirm that the correct Activity has been started
+ ShadowActivity shadowActivity = shadowOf(setupActivity);
+ Intent intent = shadowActivity.peekNextStartedActivity();
+ assertNotNull(intent.getComponent());
+ assertEquals(intent.getComponent().getClassName(),
+ NavDrawerActivity.class.getName());
+ }
+
@Test
public void testAccountCreation() {
SetupController controller = setupActivity.getController();
+ controller.setAuthorName("nick");
+ controller.setPassword("password");
// mock a resulthandler
- ResultHandler resultHandler =
- (ResultHandler) mock(ResultHandler.class);
- controller.storeAuthorInfo("nick", "some.strong.pass", resultHandler);
- // blocking verification call with timeout that waits until the mocked
- // result gets called with handle 0L, the expected value
+ ResultHandler resultHandler = mock(ResultHandler.class);
+ controller.createAccount(resultHandler);
verify(resultHandler, timeout(TIMEOUT_MS).times(1)).onResult(null);
SharedPreferences prefs =
setupActivity.getSharedPreferences("db", Context.MODE_PRIVATE);
// Confirm database key
assertTrue(prefs.contains("key"));
- // Note that Robolectric uses its own persistant storage that it
+ // Note that Robolectric uses its own persistent storage that it
// wipes clean after each test run, no need to clean up manually.
}
@@ -190,37 +159,37 @@ public class SetupActivityTest {
@Test
public void testStrengthMeterUI() {
- Assert.assertNotNull(setupActivity);
- // replace the setup controller with our mocked copy
- SetupController mockedController = this.setupController;
- setupActivity.setController(mockedController);
- // Mock answers for UI testing only
- when(mockedController.estimatePasswordStrength("strong")).thenReturn(
- STRONG);
- when(mockedController.estimatePasswordStrength("qstrong")).thenReturn(
- QUITE_STRONG);
- when(mockedController.estimatePasswordStrength("qweak")).thenReturn(
- QUITE_WEAK);
- when(mockedController.estimatePasswordStrength("weak")).thenReturn(
- WEAK);
- when(mockedController.estimatePasswordStrength("empty")).thenReturn(
- NONE);
+ proceedToPasswordFragment();
// Test the meters progress and color for several values
- testStrengthMeter("strong", STRONG, StrengthMeter.GREEN);
- Mockito.verify(mockedController, Mockito.times(1))
- .estimatePasswordStrength(eq("strong"));
- testStrengthMeter("qstrong", QUITE_STRONG, StrengthMeter.LIME);
- Mockito.verify(mockedController, Mockito.times(1))
- .estimatePasswordStrength(eq("qstrong"));
- testStrengthMeter("qweak", QUITE_WEAK, StrengthMeter.YELLOW);
- Mockito.verify(mockedController, Mockito.times(1))
- .estimatePasswordStrength(eq("qweak"));
- testStrengthMeter("weak", WEAK, StrengthMeter.ORANGE);
- Mockito.verify(mockedController, Mockito.times(1))
- .estimatePasswordStrength(eq("weak"));
- // Not sure this should be the correct behaviour on an empty input ?
- testStrengthMeter("empty", NONE, StrengthMeter.RED);
- Mockito.verify(mockedController, Mockito.times(1))
- .estimatePasswordStrength(eq("empty"));
+ testStrengthMeter("1234567890ab", STRONG, StrengthMeter.GREEN);
+ testStrengthMeter("123456789", QUITE_STRONG, StrengthMeter.LIME);
+ testStrengthMeter("123456", QUITE_WEAK, StrengthMeter.YELLOW);
+ testStrengthMeter("123", WEAK, StrengthMeter.ORANGE);
+ testStrengthMeter("", NONE, StrengthMeter.RED);
}
+
+ private void proceedToPasswordFragment() {
+ // proceed to password fragment
+ nicknameEntry.setText("nick");
+ createAccountButton.performClick();
+
+ // find UI elements in new fragment
+ strengthMeter =
+ (StrengthMeter) setupActivity.findViewById(R.id.strength_meter);
+ passwordConfirmationWrapper = (TextInputLayout) setupActivity
+ .findViewById(R.id.password_confirm_wrapper);
+ passwordEntry =
+ (EditText) setupActivity.findViewById(R.id.password_entry);
+ passwordConfirmation =
+ (EditText) setupActivity.findViewById(R.id.password_confirm);
+ createAccountButton = (Button) setupActivity.findViewById(R.id.next);
+ }
+
+ private void testStrengthMeter(String pass, float strength, int color) {
+ passwordEntry.setText(pass);
+ assertEquals(strengthMeter.getProgress(),
+ (int) (strengthMeter.getMax() * strength));
+ assertEquals(color, strengthMeter.getColor());
+ }
+
}
diff --git a/briar-android/src/test/java/org/briarproject/briar/android/login/TestChangePasswordActivity.java b/briar-android/src/test/java/org/briarproject/briar/android/login/TestChangePasswordActivity.java
index 3298c0e9b..ac4e60a88 100644
--- a/briar-android/src/test/java/org/briarproject/briar/android/login/TestChangePasswordActivity.java
+++ b/briar-android/src/test/java/org/briarproject/briar/android/login/TestChangePasswordActivity.java
@@ -10,15 +10,8 @@ public class TestChangePasswordActivity extends ChangePasswordActivity {
return passwordController;
}
- public SetupController getSetupController() {
- return setupController;
- }
-
public void setPasswordController(PasswordController passwordController) {
this.passwordController = passwordController;
}
- public void setSetupController(SetupController setupController) {
- this.setupController = setupController;
- }
}
diff --git a/build.gradle b/build.gradle
index af816d45f..80632d5eb 100644
--- a/build.gradle
+++ b/build.gradle
@@ -4,6 +4,9 @@ allprojects {
repositories {
jcenter()
mavenLocal()
+ maven {
+ url 'https://maven.google.com'
+ }
}
}