diff --git a/bramble-android/build.gradle b/bramble-android/build.gradle
index 8ff8edd7b..a36d5a2c3 100644
--- a/bramble-android/build.gradle
+++ b/bramble-android/build.gradle
@@ -32,76 +32,43 @@ dependencies {
provided 'javax.annotation:jsr250-api:1.0'
}
-def torBinaryDir = 'src/main/res/raw'
+ext.torBinaryDir = 'src/main/res/raw'
+ext.torVersion = '0.2.9.12'
+ext.geoipVersion = '2017-09-06'
+ext.torDownloadUrl = 'https://briarproject.org/build/'
-task downloadTorGeoIp(type: Download) {
- src 'https://briarproject.org/build/geoip-2017-09-06.zip'
- dest "$torBinaryDir/geoip.zip"
- onlyIfNewer true
+def torBinaries = [
+ "tor_arm" : '8ed0b347ffed1d6a4d2fd14495118eb92be83e9cc06e057e15220dc288b31688',
+ "tor_arm_pie": '64403262511c29f462ca5e7c7621bfc3c944898364d1d5ad35a016bb8a034283',
+ "tor_x86" : '61e014607a2079bcf1646289c67bff6372b1aded6e1d8d83d7791efda9a4d5ab',
+ "tor_x86_pie": '18fbc98356697dd0895836ab46d5c9877d1c539193464f7db1e82a65adaaf288',
+ "geoip" : 'fe49d3adb86d3c512373101422a017dbb86c85a570524663f09dd8ce143a24f3'
+]
+
+def downloadBinary(name) {
+ return tasks.create("downloadBinary${name}", Download) {
+ src "$torDownloadUrl${name}.zip"
+ .replace('tor_', "tor-${torVersion}-")
+ .replace('geoip', "geoip-${geoipVersion}")
+ .replaceAll('_', '-')
+ dest "$torBinaryDir/${name}.zip"
+ onlyIfNewer true
+ }
}
-task downloadTorBinaryArm(type: Download) {
- src 'https://briarproject.org/build/tor-0.2.9.12-arm.zip'
- dest "$torBinaryDir/tor_arm.zip"
- onlyIfNewer true
-}
-
-task downloadTorBinaryArmPie(type: Download) {
- src 'https://briarproject.org/build/tor-0.2.9.12-arm-pie.zip'
- dest "$torBinaryDir/tor_arm_pie.zip"
- onlyIfNewer true
-}
-
-task downloadTorBinaryX86(type: Download) {
- src 'https://briarproject.org/build/tor-0.2.9.12-x86.zip'
- dest "$torBinaryDir/tor_x86.zip"
- onlyIfNewer true
-}
-
-task downloadTorBinaryX86Pie(type: Download) {
- src 'https://briarproject.org/build/tor-0.2.9.12-x86-pie.zip'
- dest "$torBinaryDir/tor_x86_pie.zip"
- onlyIfNewer true
-}
-
-task verifyTorGeoIp(type: Verify, dependsOn: 'downloadTorGeoIp') {
- src "$torBinaryDir/geoip.zip"
- algorithm 'SHA-256'
- checksum 'fe49d3adb86d3c512373101422a017dbb86c85a570524663f09dd8ce143a24f3'
-}
-
-task verifyTorBinaryArm(type: Verify, dependsOn: 'downloadTorBinaryArm') {
- src "$torBinaryDir/tor_arm.zip"
- algorithm 'SHA-256'
- checksum '8ed0b347ffed1d6a4d2fd14495118eb92be83e9cc06e057e15220dc288b31688'
-}
-
-task verifyTorBinaryArmPie(type: Verify, dependsOn: 'downloadTorBinaryArmPie') {
- src "$torBinaryDir/tor_arm_pie.zip"
- algorithm 'SHA-256'
- checksum '64403262511c29f462ca5e7c7621bfc3c944898364d1d5ad35a016bb8a034283'
-}
-
-task verifyTorBinaryX86(type: Verify, dependsOn: 'downloadTorBinaryX86') {
- src "$torBinaryDir/tor_x86.zip"
- algorithm 'SHA-256'
- checksum '61e014607a2079bcf1646289c67bff6372b1aded6e1d8d83d7791efda9a4d5ab'
-}
-
-task verifyTorBinaryX86Pie(type: Verify, dependsOn: 'downloadTorBinaryX86Pie') {
- src "$torBinaryDir/tor_x86_pie.zip"
- algorithm 'SHA-256'
- checksum '18fbc98356697dd0895836ab46d5c9877d1c539193464f7db1e82a65adaaf288'
+def verifyBinary(name, chksum) {
+ return tasks.create([
+ name : "verifyBinary${name}",
+ type : Verify,
+ dependsOn: downloadBinary(name)]) {
+ src "$torBinaryDir/${name}.zip"
+ algorithm 'SHA-256'
+ checksum chksum
+ }
}
project.afterEvaluate {
- preBuild.dependsOn {
- [
- 'verifyTorGeoIp',
- 'verifyTorBinaryArm',
- 'verifyTorBinaryArmPie',
- 'verifyTorBinaryX86',
- 'verifyTorBinaryX86Pie'
- ]
+ torBinaries.every { key, value ->
+ preBuild.dependsOn.add(verifyBinary(key, value))
}
}
diff --git a/briar-android/build.gradle b/briar-android/build.gradle
index 9242644a5..274598674 100644
--- a/briar-android/build.gradle
+++ b/briar-android/build.gradle
@@ -20,6 +20,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'
@@ -39,6 +40,7 @@ dependencies {
testCompile project(path: ':bramble-core', configuration: 'testOutput')
testCompile 'org.robolectric:robolectric:3.5.1'
+ testCompile 'org.robolectric:shadows-support-v4:3.0'
testCompile 'org.mockito:mockito-core:2.8.9'
}
@@ -60,6 +62,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..303d79d15
--- /dev/null
+++ b/briar-android/src/main/java/org/briarproject/briar/android/login/AuthorNameFragment.java
@@ -0,0 +1,82 @@
+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..38376b2a9
--- /dev/null
+++ b/briar-android/src/main/java/org/briarproject/briar/android/login/DozeFragment.java
@@ -0,0 +1,94 @@
+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..e2a921d30 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
@@ -82,7 +91,7 @@ public class PasswordControllerImpl extends ConfigControllerImpl
return StringUtils.fromHexString(hex);
}
- // Call inside cryptoExecutor
+ @CryptoExecutor
String encryptDatabaseKey(SecretKey key, String password) {
long now = System.currentTimeMillis();
byte[] encrypted = crypto.encryptWithPassword(key.getBytes(), password);
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..0106892a1
--- /dev/null
+++ b/briar-android/src/main/java/org/briarproject/briar/android/login/PasswordFragment.java
@@ -0,0 +1,116 @@
+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..5d3fce362
--- /dev/null
+++ b/briar-android/src/main/java/org/briarproject/briar/android/login/SetupFragment.java
@@ -0,0 +1,68 @@
+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 s, int start, int count,
+ int after) {
+ // noop
+ }
+
+ @Override
+ public void onTextChanged(CharSequence s, int start, int before,
+ int count) {
+ // noop
+ }
+
+ @Override
+ public boolean onEditorAction(TextView textView, int actionId,
+ 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..b6557a693 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,15 +188,12 @@ 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());
- //Don't display the Settings Item as checked
- if (item.getItemId() == R.id.nav_btn_settings) {
- return false;
- }
- return true;
+ // Don't display the Settings item as checked
+ return item.getItemId() != R.id.nav_btn_settings;
}
@Override
@@ -204,7 +211,7 @@ public class NavDrawerActivity extends BriarActivity implements
getSupportFragmentManager()
.findFragmentByTag(ContactListFragment.TAG) == null) {
/*
- * This Makes sure that the first fragment (ContactListFragment) the
+ * This makes sure that the first fragment (ContactListFragment) the
* user sees is the same as the last fragment the user sees before
* exiting. This models the typical Google navigation behaviour such
* as in Gmail/Inbox.
@@ -311,6 +318,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..61991d6e6 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,36 @@ 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..98c44d56c 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
+ Your nickname will be shown next to any content you post. You can\'t change it after creating your account.
+ 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 bc4d5e9a3..852624f79 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
@@ -1,7 +1,5 @@
package org.briarproject.briar.android.login;
-import android.content.Context;
-import android.content.SharedPreferences;
import android.support.design.widget.TextInputLayout;
import android.widget.Button;
import android.widget.EditText;
@@ -28,12 +26,8 @@ import static org.briarproject.bramble.api.crypto.PasswordStrengthEstimator.QUIT
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.assertNotEquals;
-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;
@@ -43,8 +37,6 @@ import static org.mockito.Mockito.when;
packageName = "org.briarproject.briar")
public class ChangePasswordActivityTest {
- private static final int TIMEOUT_MS = 10 * 1000;
-
private TestChangePasswordActivity changePasswordActivity;
private TextInputLayout passwordConfirmationWrapper;
private EditText currentPassword;
@@ -55,8 +47,6 @@ public class ChangePasswordActivityTest {
@Mock
private PasswordController passwordController;
- @Mock
- private SetupController setupController;
@Captor
private ArgumentCaptor> resultCaptor;
@@ -108,12 +98,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";
@@ -125,7 +112,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
@@ -133,89 +120,39 @@ public class ChangePasswordActivityTest {
assertEquals(changePasswordActivity.isFinishing(), true);
}
- @Test
- public void testPasswordChange() {
- PasswordController passwordController =
- changePasswordActivity.getPasswordController();
- SetupController setupController =
- changePasswordActivity.getSetupController();
- // 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
- 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);
- passwordController.changePassword("some.old.pass", "some.strong.pass",
- resultHandler2);
- // blocking verification call with timeout that waits until the mocked
- // result gets called with handle 0L, the expected value
- verify(resultHandler2, timeout(TIMEOUT_MS).times(1)).onResult(true);
- // Confirm database key
- assertTrue(prefs.contains("key"));
- assertNotEquals(oldKey, prefs.getString("key", null));
- // Note that Robolectric uses its own persistant storage that it
- // wipes clean after each test run, no need to clean up manually.
- }
-
- @Test
- public void testStrengthMeter() {
- SetupController controller =
- changePasswordActivity.getSetupController();
-
- String strongPass = "very.strong.password.123";
- String weakPass = "we";
- String quiteStrongPass = "quite.strong";
-
- float val = controller.estimatePasswordStrength(strongPass);
- assertTrue(val == STRONG);
- val = controller.estimatePasswordStrength(weakPass);
- assertTrue(val < WEAK && val > NONE);
- val = controller.estimatePasswordStrength(quiteStrongPass);
- assertTrue(val < STRONG && val > QUITE_WEAK);
- }
-
@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
+ changePasswordActivity.setPasswordController(passwordController);
// Mock answers for UI testing only
- when(mockedController.estimatePasswordStrength("strong")).thenReturn(
+ when(passwordController.estimatePasswordStrength("strong")).thenReturn(
STRONG);
- when(mockedController.estimatePasswordStrength("qstrong")).thenReturn(
+ when(passwordController.estimatePasswordStrength("qstrong")).thenReturn(
QUITE_STRONG);
- when(mockedController.estimatePasswordStrength("qweak")).thenReturn(
+ when(passwordController.estimatePasswordStrength("qweak")).thenReturn(
QUITE_WEAK);
- when(mockedController.estimatePasswordStrength("weak")).thenReturn(
+ when(passwordController.estimatePasswordStrength("weak")).thenReturn(
WEAK);
- when(mockedController.estimatePasswordStrength("empty")).thenReturn(
+ when(passwordController.estimatePasswordStrength("empty")).thenReturn(
NONE);
// Test the meters progress and color for several values
testStrengthMeter("strong", STRONG, StrengthMeter.GREEN);
- Mockito.verify(mockedController, Mockito.times(1))
+ Mockito.verify(passwordController, Mockito.times(1))
.estimatePasswordStrength(eq("strong"));
testStrengthMeter("qstrong", QUITE_STRONG, StrengthMeter.LIME);
- Mockito.verify(mockedController, Mockito.times(1))
+ Mockito.verify(passwordController, Mockito.times(1))
.estimatePasswordStrength(eq("qstrong"));
testStrengthMeter("qweak", QUITE_WEAK, StrengthMeter.YELLOW);
- Mockito.verify(mockedController, Mockito.times(1))
+ Mockito.verify(passwordController, Mockito.times(1))
.estimatePasswordStrength(eq("qweak"));
testStrengthMeter("weak", WEAK, StrengthMeter.ORANGE);
- Mockito.verify(mockedController, Mockito.times(1))
+ Mockito.verify(passwordController, 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))
+ Mockito.verify(passwordController, Mockito.times(1))
.estimatePasswordStrength(eq("empty"));
}
+
}
diff --git a/briar-android/src/test/java/org/briarproject/briar/android/login/PasswordControllerImplTest.java b/briar-android/src/test/java/org/briarproject/briar/android/login/PasswordControllerImplTest.java
new file mode 100644
index 000000000..34ad19fc5
--- /dev/null
+++ b/briar-android/src/test/java/org/briarproject/briar/android/login/PasswordControllerImplTest.java
@@ -0,0 +1,99 @@
+package org.briarproject.briar.android.login;
+
+import android.content.SharedPreferences;
+
+import org.briarproject.bramble.api.crypto.CryptoComponent;
+import org.briarproject.bramble.api.crypto.PasswordStrengthEstimator;
+import org.briarproject.bramble.api.db.DatabaseConfig;
+import org.briarproject.bramble.test.BrambleMockTestCase;
+import org.briarproject.bramble.test.ImmediateExecutor;
+import org.briarproject.briar.android.controller.handler.ResultHandler;
+import org.jmock.Expectations;
+import org.junit.Test;
+
+import java.util.concurrent.Executor;
+import java.util.concurrent.atomic.AtomicBoolean;
+
+import static junit.framework.Assert.assertFalse;
+import static junit.framework.Assert.assertTrue;
+import static org.briarproject.bramble.test.TestUtils.getSecretKey;
+
+public class PasswordControllerImplTest extends BrambleMockTestCase {
+
+ private final SharedPreferences briarPrefs =
+ context.mock(SharedPreferences.class);
+ private final DatabaseConfig databaseConfig =
+ context.mock(DatabaseConfig.class);
+ private final CryptoComponent crypto = context.mock(CryptoComponent.class);
+ private final PasswordStrengthEstimator estimator =
+ context.mock(PasswordStrengthEstimator.class);
+ private final SharedPreferences.Editor editor =
+ context.mock(SharedPreferences.Editor.class);
+
+ private final Executor cryptoExecutor = new ImmediateExecutor();
+
+ private final String oldPassword = "some.old.pass";
+ private final String newPassword = "some.new.pass";
+ private final String oldEncryptedHex = "010203";
+ private final String newEncryptedHex = "020304";
+ private final byte[] oldEncryptedBytes = new byte[] {1, 2, 3};
+ private final byte[] newEncryptedBytes = new byte[] {2, 3, 4};
+ private final byte[] keyBytes = getSecretKey().getBytes();
+
+ @Test
+ public void testChangePasswordReturnsTrue() {
+ context.checking(new Expectations() {{
+ // Look up the encrypted DB key
+ oneOf(briarPrefs).getString("key", null);
+ will(returnValue(oldEncryptedHex));
+ // Decrypt and re-encrypt the key
+ oneOf(crypto).decryptWithPassword(oldEncryptedBytes, oldPassword);
+ will(returnValue(keyBytes));
+ oneOf(crypto).encryptWithPassword(keyBytes, newPassword);
+ will(returnValue(newEncryptedBytes));
+ // Store the re-encrypted key
+ oneOf(briarPrefs).edit();
+ will(returnValue(editor));
+ oneOf(editor).putString("key", newEncryptedHex);
+ oneOf(editor).apply();
+ }});
+
+ PasswordControllerImpl p = new PasswordControllerImpl(briarPrefs,
+ databaseConfig, cryptoExecutor, crypto, estimator);
+
+ final AtomicBoolean capturedResult = new AtomicBoolean(false);
+ p.changePassword(oldPassword, newPassword,
+ new ResultHandler() {
+ @Override
+ public void onResult(Boolean result) {
+ capturedResult.set(result);
+ }
+ });
+ assertTrue(capturedResult.get());
+ }
+
+ @Test
+ public void testChangePasswordReturnsFalseIfOldPasswordIsWrong() {
+ context.checking(new Expectations() {{
+ // Look up the encrypted DB key
+ oneOf(briarPrefs).getString("key", null);
+ will(returnValue(oldEncryptedHex));
+ // Try to decrypt the key - the password is wrong
+ oneOf(crypto).decryptWithPassword(oldEncryptedBytes, oldPassword);
+ will(returnValue(null));
+ }});
+
+ PasswordControllerImpl p = new PasswordControllerImpl(briarPrefs,
+ databaseConfig, cryptoExecutor, crypto, estimator);
+
+ final AtomicBoolean capturedResult = new AtomicBoolean(true);
+ p.changePassword(oldPassword, newPassword,
+ new ResultHandler() {
+ @Override
+ public void onResult(Boolean result) {
+ capturedResult.set(result);
+ }
+ });
+ assertFalse(capturedResult.get());
+ }
+}
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
new file mode 100644
index 000000000..7e13211a4
--- /dev/null
+++ b/briar-android/src/test/java/org/briarproject/briar/android/login/PasswordFragmentTest.java
@@ -0,0 +1,115 @@
+package org.briarproject.briar.android.login;
+
+import android.support.design.widget.TextInputLayout;
+import android.view.View;
+import android.widget.Button;
+import android.widget.EditText;
+
+import org.briarproject.briar.R;
+import org.briarproject.briar.android.TestBriarApplication;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+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.junit.Assert.assertNotEquals;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+import static org.robolectric.shadows.support.v4.SupportFragmentTestUtil.startFragment;
+
+@RunWith(RobolectricTestRunner.class)
+@Config(sdk = 21, application = TestBriarApplication.class,
+ packageName = "org.briarproject.briar")
+public class PasswordFragmentTest {
+
+ private PasswordFragment passwordFragment = new PasswordFragment();
+ private EditText passwordEntry;
+ private EditText passwordConfirmation;
+ private TextInputLayout passwordConfirmationWrapper;
+ private StrengthMeter strengthMeter;
+ private Button createAccountButton;
+
+ @Mock
+ private SetupController setupController;
+
+ @Before
+ public void setUp() {
+ MockitoAnnotations.initMocks(this);
+ startFragment(passwordFragment, SetupActivity.class);
+
+ View v = passwordFragment.getView();
+ passwordEntry = (EditText) v.findViewById(R.id.password_entry);
+ passwordConfirmation = (EditText) v.findViewById(R.id.password_confirm);
+ passwordConfirmationWrapper =
+ (TextInputLayout) v.findViewById(R.id.password_confirm_wrapper);
+ strengthMeter = (StrengthMeter) v.findViewById(R.id.strength_meter);
+ createAccountButton = (Button) v.findViewById(R.id.next);
+ }
+
+ @Test
+ public void testCreateAccountUI() {
+ String safePass = "really.safe.password";
+
+ passwordFragment.setupController = setupController;
+ when(setupController.needsDozeWhitelisting()).thenReturn(false);
+ when(setupController.estimatePasswordStrength(safePass))
+ .thenReturn(STRONG);
+
+ passwordEntry.setText(safePass);
+ passwordConfirmation.setText(safePass);
+ // Confirm that the create account button is clickable
+ assertEquals(createAccountButton.isEnabled(), true);
+ createAccountButton.performClick();
+
+ // assert controller has been called properly
+ verify(setupController, times(1)).setPassword(safePass);
+ verify(setupController, times(1)).showDozeOrCreateAccount();
+ }
+
+ @Test
+ public void testStrengthMeterUI() {
+ // Test the meters' progress and color for several values
+ 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 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(),
+ passwordFragment.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
+ assertNotEquals(passwordConfirmationWrapper.getError(),
+ passwordFragment.getString(R.string.passwords_do_not_match));
+ // Passwords match, so button should be enabled
+ assertEquals(createAccountButton.isEnabled(), true);
+ }
+
+}
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 9b4217edd..3f2550903 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
@@ -1,29 +1,18 @@
package org.briarproject.briar.android.login;
-import android.content.Context;
-import android.content.Intent;
-import android.content.SharedPreferences;
import android.support.design.widget.TextInputLayout;
-import android.widget.Button;
import android.widget.EditText;
import org.briarproject.briar.R;
import org.briarproject.briar.android.TestBriarApplication;
-import org.briarproject.briar.android.controller.handler.ResultHandler;
-import org.briarproject.briar.android.navdrawer.NavDrawerActivity;
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.RobolectricTestRunner;
import org.robolectric.annotation.Config;
-import org.robolectric.shadows.ShadowActivity;
import static junit.framework.Assert.assertEquals;
import static org.briarproject.bramble.api.crypto.PasswordStrengthEstimator.NONE;
@@ -48,95 +37,18 @@ import static org.robolectric.Shadows.shadowOf;
packageName = "org.briarproject.briar")
public class SetupActivityTest {
- private static final int TIMEOUT_MS = 10 * 1000;
-
- private TestSetupActivity setupActivity;
+ private SetupActivity setupActivity;
private TextInputLayout nicknameEntryWrapper;
- private TextInputLayout passwordConfirmationWrapper;
private EditText nicknameEntry;
- private EditText passwordEntry;
- private EditText passwordConfirmation;
- 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);
+ setupActivity = Robolectric.setupActivity(SetupActivity.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());
}
@Test
@@ -148,74 +60,4 @@ public class SetupActivityTest {
assertEquals(nicknameEntryWrapper.getError(),
setupActivity.getString(R.string.name_too_long));
}
-
- @Test
- public void testAccountCreation() {
- SetupController controller = setupActivity.getController();
- // 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
- 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
- // wipes clean after each test run, no need to clean up manually.
- }
-
- @Test
- public void testStrengthMeter() {
- SetupController controller = setupActivity.getController();
-
- String strongPass = "very.strong.password.123";
- String weakPass = "we";
- String quiteStrongPass = "quite.strong";
-
- float val = controller.estimatePasswordStrength(strongPass);
- assertTrue(val == STRONG);
- val = controller.estimatePasswordStrength(weakPass);
- assertTrue(val < WEAK && val > NONE);
- val = controller.estimatePasswordStrength(quiteStrongPass);
- assertTrue(val < STRONG && val > QUITE_WEAK);
- }
-
- @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);
- // 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"));
- }
}
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
new file mode 100644
index 000000000..f181e2881
--- /dev/null
+++ b/briar-android/src/test/java/org/briarproject/briar/android/login/SetupControllerImplTest.java
@@ -0,0 +1,86 @@
+package org.briarproject.briar.android.login;
+
+import android.content.SharedPreferences;
+
+import org.briarproject.bramble.api.crypto.CryptoComponent;
+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.test.BrambleMockTestCase;
+import org.briarproject.bramble.test.ImmediateExecutor;
+import org.briarproject.briar.android.controller.handler.ResultHandler;
+import org.jmock.Expectations;
+import org.jmock.lib.legacy.ClassImposteriser;
+import org.junit.Test;
+
+import java.util.concurrent.Executor;
+import java.util.concurrent.atomic.AtomicBoolean;
+
+import static junit.framework.Assert.assertTrue;
+import static org.briarproject.bramble.api.identity.AuthorConstants.MAX_AUTHOR_NAME_LENGTH;
+import static org.briarproject.bramble.test.TestUtils.getSecretKey;
+import static org.briarproject.bramble.util.StringUtils.getRandomString;
+
+public class SetupControllerImplTest extends BrambleMockTestCase {
+
+ private final SharedPreferences briarPrefs =
+ context.mock(SharedPreferences.class);
+ private final DatabaseConfig databaseConfig =
+ context.mock(DatabaseConfig.class);
+ private final CryptoComponent crypto = context.mock(CryptoComponent.class);
+ private final PasswordStrengthEstimator estimator =
+ context.mock(PasswordStrengthEstimator.class);
+ private final SharedPreferences.Editor editor =
+ context.mock(SharedPreferences.Editor.class);
+ private final SetupActivity setupActivity;
+
+ private final Executor cryptoExecutor = new ImmediateExecutor();
+
+ private final String authorName = getRandomString(MAX_AUTHOR_NAME_LENGTH);
+ private final String password = "some.strong.pass";
+ private final String encryptedHex = "010203";
+ private final byte[] encryptedBytes = new byte[] {1, 2, 3};
+ private final SecretKey key = getSecretKey();
+
+ public SetupControllerImplTest() {
+ context.setImposteriser(ClassImposteriser.INSTANCE);
+ setupActivity = context.mock(SetupActivity.class);
+ }
+
+ @Test
+ public void testCreateAccount() {
+ context.checking(new Expectations() {{
+ // Setting the author name shows the password fragment
+ oneOf(setupActivity).showPasswordFragment();
+ // Generate a database key
+ oneOf(crypto).generateSecretKey();
+ will(returnValue(key));
+ // Attach the author name and database key to the database config
+ oneOf(databaseConfig).setLocalAuthorName(authorName);
+ oneOf(databaseConfig).setEncryptionKey(key);
+ // Encrypt the key with the password
+ oneOf(crypto).encryptWithPassword(key.getBytes(), password);
+ will(returnValue(encryptedBytes));
+ // Store the encrypted key
+ oneOf(briarPrefs).edit();
+ will(returnValue(editor));
+ oneOf(editor).putString("key", encryptedHex);
+ oneOf(editor).apply();
+ }});
+
+ SetupControllerImpl s = new SetupControllerImpl(briarPrefs,
+ databaseConfig, cryptoExecutor, crypto, estimator);
+ s.setSetupActivity(setupActivity);
+
+ final AtomicBoolean called = new AtomicBoolean(false);
+ s.setAuthorName(authorName);
+ s.setPassword(password);
+ s.createAccount(new ResultHandler() {
+ @Override
+ public void onResult(Void result) {
+ called.set(true);
+ }
+ });
+ assertTrue(called.get());
+ }
+}
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..c27ad7e11 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
@@ -1,24 +1,13 @@
package org.briarproject.briar.android.login;
/**
- * This class exposes the PasswordController and SetupController and offers the
- * possibility to override them.
+ * This class exposes the PasswordController and offers the possibility to
+ * replace it.
*/
public class TestChangePasswordActivity extends ChangePasswordActivity {
- public PasswordController getPasswordController() {
- 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/briar-android/src/test/java/org/briarproject/briar/android/login/TestSetupActivity.java b/briar-android/src/test/java/org/briarproject/briar/android/login/TestSetupActivity.java
deleted file mode 100644
index 0595329be..000000000
--- a/briar-android/src/test/java/org/briarproject/briar/android/login/TestSetupActivity.java
+++ /dev/null
@@ -1,16 +0,0 @@
-package org.briarproject.briar.android.login;
-
-/**
- * This class exposes the SetupController and offers the possibility to
- * override it.
- */
-public class TestSetupActivity extends SetupActivity {
-
- SetupController getController() {
- return setupController;
- }
-
- void setController(SetupController setupController) {
- this.setupController = setupController;
- }
-}
diff --git a/build.gradle b/build.gradle
index fc55df933..24e8f774e 100644
--- a/build.gradle
+++ b/build.gradle
@@ -4,6 +4,9 @@ allprojects {
repositories {
jcenter()
mavenLocal()
+ maven {
+ url 'https://maven.google.com'
+ }
}
}