mirror of
https://code.briarproject.org/briar/briar.git
synced 2026-02-11 18:29:05 +01:00
Resolve merge conflicts.
# Conflicts: # briar-android/build.gradle # briar-android/src/test/java/org/briarproject/briar/android/login/SetupActivityTest.java
This commit is contained in:
@@ -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))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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',
|
||||
]
|
||||
}
|
||||
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
<uses-permission android:name="android.permission.READ_LOGS"/>
|
||||
<uses-permission android:name="android.permission.VIBRATE" />
|
||||
<uses-permission android:name="android.permission.WAKE_LOCK" />
|
||||
<uses-permission-sdk-23 android:name="android.permission.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS"/>
|
||||
|
||||
<application
|
||||
android:name="org.briarproject.briar.android.BriarApplicationImpl"
|
||||
|
||||
@@ -27,8 +27,11 @@ import org.briarproject.briar.android.introduction.IntroductionMessageFragment;
|
||||
import org.briarproject.briar.android.keyagreement.IntroFragment;
|
||||
import org.briarproject.briar.android.keyagreement.KeyAgreementActivity;
|
||||
import org.briarproject.briar.android.keyagreement.ShowQrCodeFragment;
|
||||
import org.briarproject.briar.android.login.AuthorNameFragment;
|
||||
import org.briarproject.briar.android.login.ChangePasswordActivity;
|
||||
import org.briarproject.briar.android.login.DozeFragment;
|
||||
import org.briarproject.briar.android.login.PasswordActivity;
|
||||
import org.briarproject.briar.android.login.PasswordFragment;
|
||||
import org.briarproject.briar.android.login.SetupActivity;
|
||||
import org.briarproject.briar.android.navdrawer.NavDrawerActivity;
|
||||
import org.briarproject.briar.android.panic.PanicPreferencesActivity;
|
||||
@@ -148,6 +151,10 @@ public interface ActivityComponent {
|
||||
void inject(RssFeedManageActivity activity);
|
||||
|
||||
// Fragments
|
||||
void inject(AuthorNameFragment fragment);
|
||||
void inject(PasswordFragment fragment);
|
||||
void inject(DozeFragment fragment);
|
||||
|
||||
void inject(ContactListFragment fragment);
|
||||
|
||||
void inject(CreateGroupFragment fragment);
|
||||
|
||||
@@ -12,11 +12,13 @@ import android.view.ViewGroup.LayoutParams;
|
||||
import android.view.inputmethod.InputMethodManager;
|
||||
|
||||
import org.briarproject.bramble.api.db.DbException;
|
||||
import org.briarproject.briar.R;
|
||||
import org.briarproject.briar.android.AndroidComponent;
|
||||
import org.briarproject.briar.android.BriarApplication;
|
||||
import org.briarproject.briar.android.DestroyableContext;
|
||||
import org.briarproject.briar.android.controller.ActivityLifecycleController;
|
||||
import org.briarproject.briar.android.forum.ForumModule;
|
||||
import org.briarproject.briar.android.fragment.BaseFragment;
|
||||
import org.briarproject.briar.android.fragment.ScreenFilterDialogFragment;
|
||||
import org.briarproject.briar.android.widget.TapSafeFrameLayout;
|
||||
import org.briarproject.briar.android.widget.TapSafeFrameLayout.OnTapFilteredListener;
|
||||
@@ -113,6 +115,22 @@ public abstract class BaseActivity extends AppCompatActivity
|
||||
}
|
||||
}
|
||||
|
||||
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();
|
||||
}
|
||||
|
||||
private void showScreenFilterWarning() {
|
||||
if (dialogFrag != null && dialogFrag.isVisible()) return;
|
||||
Set<String> apps = screenFilterMonitor.getApps();
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
|
||||
}
|
||||
|
||||
@@ -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());
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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),
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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<Boolean> resultHandler);
|
||||
|
||||
void changePassword(String password, String newPassword,
|
||||
ResultHandler<Boolean> resultHandler);
|
||||
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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<Void>(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.");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -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<Void> 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<Void> resultHandler);
|
||||
|
||||
}
|
||||
|
||||
@@ -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<Void> 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<Void> resultHandler =
|
||||
new UiResultHandler<Void>(setupActivity) {
|
||||
@Override
|
||||
public void onResultUi(Void result) {
|
||||
if (setupActivity == null)
|
||||
throw new IllegalStateException();
|
||||
setupActivity.showApp();
|
||||
}
|
||||
};
|
||||
createAccount(resultHandler);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void createAccount(final ResultHandler<Void> 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);
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,60 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<ScrollView
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:fillViewport="true">
|
||||
|
||||
<android.support.constraint.ConstraintLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:paddingBottom="@dimen/margin_activity_vertical"
|
||||
android:paddingEnd="@dimen/margin_activity_horizontal"
|
||||
android:paddingLeft="@dimen/margin_activity_horizontal"
|
||||
android:paddingRight="@dimen/margin_activity_horizontal"
|
||||
android:paddingStart="@dimen/margin_activity_horizontal"
|
||||
android:paddingTop="@dimen/margin_activity_vertical">
|
||||
|
||||
<android.support.design.widget.TextInputLayout
|
||||
android:id="@+id/nickname_entry_wrapper"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="@dimen/margin_medium"
|
||||
app:errorEnabled="true"
|
||||
app:hintEnabled="false"
|
||||
app:layout_constraintLeft_toLeftOf="parent"
|
||||
app:layout_constraintRight_toRightOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="parent">
|
||||
|
||||
<android.support.design.widget.TextInputEditText
|
||||
android:id="@+id/nickname_entry"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:hint="@string/choose_nickname"
|
||||
android:imeOptions="actionNext"
|
||||
android:inputType="text|textCapWords"
|
||||
android:maxLines="1"/>
|
||||
|
||||
<requestFocus/>
|
||||
</android.support.design.widget.TextInputLayout>
|
||||
|
||||
<Button
|
||||
android:id="@+id/next"
|
||||
style="@style/BriarButton.Default"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="@dimen/margin_activity_horizontal"
|
||||
android:enabled="false"
|
||||
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/nickname_entry_wrapper"
|
||||
app:layout_constraintVertical_bias="1.0"
|
||||
tools:enabled="true"/>
|
||||
|
||||
</android.support.constraint.ConstraintLayout>
|
||||
|
||||
</ScrollView>
|
||||
54
briar-android/src/main/res/layout/fragment_setup_doze.xml
Normal file
54
briar-android/src/main/res/layout/fragment_setup_doze.xml
Normal file
@@ -0,0 +1,54 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<ScrollView
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:fillViewport="true">
|
||||
|
||||
<android.support.constraint.ConstraintLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:paddingBottom="@dimen/margin_activity_vertical"
|
||||
android:paddingEnd="@dimen/margin_activity_horizontal"
|
||||
android:paddingLeft="@dimen/margin_activity_horizontal"
|
||||
android:paddingRight="@dimen/margin_activity_horizontal"
|
||||
android:paddingStart="@dimen/margin_activity_horizontal"
|
||||
android:paddingTop="@dimen/margin_activity_vertical">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/setup_explanation"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/setup_doze_intro"
|
||||
android:textSize="@dimen/text_size_medium"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent"/>
|
||||
|
||||
<Button
|
||||
android:id="@+id/dozeButton"
|
||||
style="@style/BriarButton.Default"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="@dimen/margin_activity_horizontal"
|
||||
android:text="@string/setup_doze_button"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@+id/setup_explanation"/>
|
||||
|
||||
<ProgressBar
|
||||
android:id="@+id/progress"
|
||||
style="?android:attr/progressBarStyle"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginBottom="16dp"
|
||||
android:layout_marginTop="16dp"
|
||||
android:visibility="invisible"
|
||||
app:layout_constraintBottom_toBottomOf="@+id/dozeButton"
|
||||
app:layout_constraintLeft_toLeftOf="parent"
|
||||
app:layout_constraintRight_toRightOf="parent"
|
||||
app:layout_constraintTop_toTopOf="@+id/dozeButton"/>
|
||||
|
||||
</android.support.constraint.ConstraintLayout>
|
||||
|
||||
</ScrollView>
|
||||
@@ -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">
|
||||
|
||||
<RelativeLayout
|
||||
<android.support.constraint.ConstraintLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical"
|
||||
android:paddingBottom="@dimen/margin_activity_vertical"
|
||||
android:paddingEnd="@dimen/margin_activity_horizontal"
|
||||
android:paddingLeft="@dimen/margin_activity_horizontal"
|
||||
@@ -18,38 +17,16 @@
|
||||
android:paddingStart="@dimen/margin_activity_horizontal"
|
||||
android:paddingTop="@dimen/margin_activity_vertical">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/setup_explanation"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/setup_explanation"/>
|
||||
|
||||
<android.support.design.widget.TextInputLayout
|
||||
android:id="@+id/nickname_entry_wrapper"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_below="@+id/setup_explanation"
|
||||
android:layout_centerHorizontal="true"
|
||||
android:layout_marginTop="@dimen/margin_medium"
|
||||
app:errorEnabled="true">
|
||||
|
||||
<android.support.design.widget.TextInputEditText
|
||||
android:id="@+id/nickname_entry"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:hint="@string/choose_nickname"
|
||||
android:imeOptions="actionNext"
|
||||
android:inputType="text|textCapWords"
|
||||
android:maxLines="1"/>
|
||||
</android.support.design.widget.TextInputLayout>
|
||||
|
||||
<android.support.design.widget.TextInputLayout
|
||||
android:id="@+id/password_entry_wrapper"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_below="@+id/nickname_entry_wrapper"
|
||||
android:layout_centerHorizontal="true"
|
||||
app:errorEnabled="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.support.design.widget.TextInputEditText
|
||||
android:id="@+id/password_entry"
|
||||
@@ -58,55 +35,70 @@
|
||||
android:hint="@string/choose_password"
|
||||
android:imeOptions="actionNext"
|
||||
android:inputType="textPassword"
|
||||
android:maxLines="1"/>
|
||||
android:maxLines="1">
|
||||
|
||||
<requestFocus/>
|
||||
</android.support.design.widget.TextInputEditText>
|
||||
|
||||
</android.support.design.widget.TextInputLayout>
|
||||
|
||||
<org.briarproject.briar.android.login.StrengthMeter
|
||||
android:id="@+id/strength_meter"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_below="@+id/password_entry_wrapper"
|
||||
android:layout_centerHorizontal="true"
|
||||
android:layout_marginBottom="@dimen/margin_medium"
|
||||
android:visibility="gone"/>
|
||||
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.support.design.widget.TextInputLayout
|
||||
android:id="@+id/password_confirm_wrapper"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_below="@+id/strength_meter"
|
||||
android:layout_centerHorizontal="true"
|
||||
app:errorEnabled="true">
|
||||
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.support.design.widget.TextInputEditText
|
||||
android:id="@+id/password_confirm"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:hint="@string/confirm_password"
|
||||
android:imeOptions="actionDone"
|
||||
android:inputType="textPassword"
|
||||
android:maxLines="1"/>
|
||||
</android.support.design.widget.TextInputLayout>
|
||||
|
||||
<Button
|
||||
android:id="@+id/create_account"
|
||||
android:id="@+id/next"
|
||||
style="@style/BriarButton.Default"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_below="@+id/password_confirm_wrapper"
|
||||
android:layout_centerHorizontal="true"
|
||||
android:enabled="false"
|
||||
android:text="@string/create_account_button"/>
|
||||
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"/>
|
||||
|
||||
<ProgressBar
|
||||
android:id="@+id/progress_wheel"
|
||||
android:id="@+id/progress"
|
||||
style="?android:attr/progressBarStyle"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_alignTop="@id/create_account"
|
||||
android:layout_centerHorizontal="true"
|
||||
android:visibility="invisible"/>
|
||||
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"/>
|
||||
|
||||
</RelativeLayout>
|
||||
</android.support.constraint.ConstraintLayout>
|
||||
|
||||
</ScrollView>
|
||||
</ScrollView>
|
||||
12
briar-android/src/main/res/menu/help_action.xml
Normal file
12
briar-android/src/main/res/menu/help_action.xml
Normal file
@@ -0,0 +1,12 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<menu
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto">
|
||||
|
||||
<item
|
||||
android:id="@+id/action_help"
|
||||
android:icon="@drawable/ic_info_white"
|
||||
android:title="@string/more_info"
|
||||
app:showAsAction="always"/>
|
||||
|
||||
</menu>
|
||||
@@ -2,7 +2,7 @@
|
||||
<resources>
|
||||
<!--Setup-->
|
||||
<string name="setup_title">Briar регистрация</string>
|
||||
<string name="setup_explanation">Briar профилът се съхранява криптиран във вашето устройство, а не в облака. Ако деинсталирате Briar или забравите паролата си, няма как да възстановите профила и данните си.</string>
|
||||
<string name="setup_password_explanation">Briar профилът се съхранява криптиран във вашето устройство, а не в облака. Ако деинсталирате Briar или забравите паролата си, няма как да възстановите профила и данните си.</string>
|
||||
<string name="choose_nickname">Изберете име</string>
|
||||
<string name="choose_password">Изберете парола</string>
|
||||
<string name="confirm_password">Потвърдете парола</string>
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
<resources>
|
||||
<!--Setup-->
|
||||
<string name="setup_title">Configuració de Briar</string>
|
||||
<string name="setup_explanation">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.</string>
|
||||
<string name="setup_password_explanation">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.</string>
|
||||
<string name="choose_nickname">Trieu el sobrenom</string>
|
||||
<string name="choose_password">Trieu la contrasenya</string>
|
||||
<string name="confirm_password">Confirmeu la contrasenya</string>
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
<resources>
|
||||
<!--Setup-->
|
||||
<string name="setup_title">Briar einrichten</string>
|
||||
<string name="setup_explanation">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.</string>
|
||||
<string name="setup_password_explanation">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.</string>
|
||||
<string name="choose_nickname">Wähle deinen Benutzernamen</string>
|
||||
<string name="choose_password">Wähle dein Passwort</string>
|
||||
<string name="confirm_password">Passwort bestätigen</string>
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
<resources>
|
||||
<!--Setup-->
|
||||
<string name="setup_title">Configuración de Briar</string>
|
||||
<string name="setup_explanation">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.</string>
|
||||
<string name="setup_password_explanation">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.</string>
|
||||
<string name="choose_nickname">Elige tu nombre de usuario</string>
|
||||
<string name="choose_password">Elige tu contraseña</string>
|
||||
<string name="confirm_password">Confirma tu contraseña</string>
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
<resources>
|
||||
<!--Setup-->
|
||||
<string name="setup_title">Briar ezarpena</string>
|
||||
<string name="setup_explanation">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.</string>
|
||||
<string name="setup_password_explanation">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.</string>
|
||||
<string name="choose_nickname">Hautatu zure ezizena</string>
|
||||
<string name="choose_password">Hautatu zure pasahitza</string>
|
||||
<string name="confirm_password">Berretsi zure pasahitza</string>
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
<resources>
|
||||
<!--Setup-->
|
||||
<string name="setup_title">Briarin asetus</string>
|
||||
<string name="setup_explanation">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.</string>
|
||||
<string name="setup_password_explanation">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.</string>
|
||||
<string name="choose_nickname">Valitse nimimerkki</string>
|
||||
<string name="choose_password">Valitse salasana</string>
|
||||
<string name="confirm_password">Vahvista salasana</string>
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
<resources>
|
||||
<!--Setup-->
|
||||
<string name="setup_title">Configuration de Briar</string>
|
||||
<string name="setup_explanation">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.</string>
|
||||
<string name="setup_password_explanation">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.</string>
|
||||
<string name="choose_nickname">Choisir votre pseudonyme</string>
|
||||
<string name="choose_password">Choisir votre mot de passe</string>
|
||||
<string name="confirm_password">Confirmer votre mot de passe</string>
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
<resources>
|
||||
<!--Setup-->
|
||||
<string name="setup_title">Configuración de Briar</string>
|
||||
<string name="setup_explanation">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.</string>
|
||||
<string name="setup_password_explanation">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.</string>
|
||||
<string name="choose_nickname">Escolle o teu alcume</string>
|
||||
<string name="choose_password">Escolle a túa clave</string>
|
||||
<string name="confirm_password">Confirma a túa clave</string>
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
<resources>
|
||||
<!--Setup-->
|
||||
<string name="setup_title">ब्रियर सेटअप</string>
|
||||
<string name="setup_explanation">आपका ब्रियर खाता आपके डिवाइस पर एन्क्रिप्ट किया गया है, न कि क्लाउड में। यदि आप बिअर की स्थापना रद्द करते हैं या अपना पासवर्ड भूल जाते हैं, तो आपके खाता और आपके डेटा को पुनर्प्राप्त करने का कोई तरीका नहीं है।</string>
|
||||
<string name="setup_password_explanation">आपका ब्रियर खाता आपके डिवाइस पर एन्क्रिप्ट किया गया है, न कि क्लाउड में। यदि आप बिअर की स्थापना रद्द करते हैं या अपना पासवर्ड भूल जाते हैं, तो आपके खाता और आपके डेटा को पुनर्प्राप्त करने का कोई तरीका नहीं है।</string>
|
||||
<string name="choose_nickname">आपका मुंहबोला नाम चुनें</string>
|
||||
<string name="choose_password">अपना पासवर्ड चुनें</string>
|
||||
<string name="confirm_password">अपने पासवर्ड की पुष्टि करें</string>
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
<resources>
|
||||
<!--Setup-->
|
||||
<string name="setup_title">Impostazione Briar</string>
|
||||
<string name="setup_explanation">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.</string>
|
||||
<string name="setup_password_explanation">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.</string>
|
||||
<string name="choose_nickname">Scegli il tuo nickname</string>
|
||||
<string name="choose_password">Scegli la tua password</string>
|
||||
<string name="confirm_password">Conferma la tua password</string>
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
<resources>
|
||||
<!--Setup-->
|
||||
<string name="setup_title">Oppsett av Briar</string>
|
||||
<string name="setup_explanation">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.</string>
|
||||
<string name="setup_password_explanation">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.</string>
|
||||
<string name="choose_nickname">Velg kallenavn</string>
|
||||
<string name="choose_password">Velg passord</string>
|
||||
<string name="confirm_password">Bekreft passord</string>
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
<resources>
|
||||
<!--Setup-->
|
||||
<string name="setup_title">Configuracion de Briar</string>
|
||||
<string name="setup_explanation">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.</string>
|
||||
<string name="setup_password_explanation">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.</string>
|
||||
<string name="choose_nickname">Causir un escais-nom</string>
|
||||
<string name="choose_password">Causir un senhal</string>
|
||||
<string name="confirm_password">Confirmar lo senhal</string>
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
<resources>
|
||||
<!--Setup-->
|
||||
<string name="setup_title">Configuração de Briar</string>
|
||||
<string name="setup_explanation">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.</string>
|
||||
<string name="setup_password_explanation">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.</string>
|
||||
<string name="choose_nickname">Escolha seu apelido</string>
|
||||
<string name="choose_password">Escolha sua senha</string>
|
||||
<string name="confirm_password">Confirme sua senha</string>
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
<resources>
|
||||
<!--Setup-->
|
||||
<string name="setup_title">Настройка Briar</string>
|
||||
<string name="setup_explanation">Ваша учетная запись Briar хранится в зашифрованном виде только на устройстве. Если вы удалите Briar или забудете пароль, то не сможете восстановить свою учетную запись и данные.</string>
|
||||
<string name="setup_password_explanation">Ваша учетная запись Briar хранится в зашифрованном виде только на устройстве. Если вы удалите Briar или забудете пароль, то не сможете восстановить свою учетную запись и данные.</string>
|
||||
<string name="choose_nickname">Выберите псевдоним</string>
|
||||
<string name="choose_password">Выберите пароль</string>
|
||||
<string name="confirm_password">Подтвердите пароль</string>
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
<resources>
|
||||
<!--Setup-->
|
||||
<string name="setup_title">Rregullimi i Briar-it</string>
|
||||
<string name="setup_explanation">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.</string>
|
||||
<string name="setup_password_explanation">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.</string>
|
||||
<string name="choose_nickname">Zgjidhni nofkën tuaj</string>
|
||||
<string name="choose_password">Zgjidhni fjalëkalimin tuaj</string>
|
||||
<string name="confirm_password">Ripohoni fjalëkalimin tuaj</string>
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
<resources>
|
||||
<!--Setup-->
|
||||
<string name="setup_title">Briar Podešavanje</string>
|
||||
<string name="setup_explanation">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.</string>
|
||||
<string name="setup_password_explanation">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.</string>
|
||||
<string name="choose_nickname">Izaberite vaš nadimak</string>
|
||||
<string name="choose_password">Izaberite vašu šifru</string>
|
||||
<string name="confirm_password">Potvrdite vašu šifru</string>
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
<resources>
|
||||
<!--Setup-->
|
||||
<string name="setup_title">Briar Kurulum</string>
|
||||
<string name="setup_explanation">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.</string>
|
||||
<string name="setup_password_explanation">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.</string>
|
||||
<string name="choose_nickname">Kullanıcı adınızı belirleyin</string>
|
||||
<string name="choose_password">Parolanızı belirleyin</string>
|
||||
<string name="confirm_password">Parolanızı doğrulayın</string>
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
<resources>
|
||||
<!--Setup-->
|
||||
<string name="setup_title">安装 Briar</string>
|
||||
<string name="setup_explanation">您的 Briar 账号只会被加密储存在您的设备上,不会被上传。如果您卸载了 Briar 或忘记了密码,将无法恢复您的账号和数据。</string>
|
||||
<string name="setup_password_explanation">您的 Briar 账号只会被加密储存在您的设备上,不会被上传。如果您卸载了 Briar 或忘记了密码,将无法恢复您的账号和数据。</string>
|
||||
<string name="choose_nickname">设置昵称</string>
|
||||
<string name="choose_password">设置密码</string>
|
||||
<string name="confirm_password">确认密码</string>
|
||||
|
||||
@@ -2,8 +2,15 @@
|
||||
<resources>
|
||||
|
||||
<!-- Setup -->
|
||||
<string name="setup_title">Briar Setup</string>
|
||||
<string name="setup_explanation">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.</string>
|
||||
<string name="setup_title">Welcome to Briar</string>
|
||||
<string name="setup_name_explanation">Your nickname will be shown next to any content you post. You can\'t change it after creating your account.</string>
|
||||
<string name="setup_next">Next</string>
|
||||
<string name="setup_password_intro">Choose a Password</string>
|
||||
<string name="setup_password_explanation">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.</string>
|
||||
<string name="setup_doze_title">Background Connections</string>
|
||||
<string name="setup_doze_intro">To receive messages, Briar needs to stay connected in the background.</string>
|
||||
<string name="setup_doze_explanation">To receive messages, Briar needs to stay connected in the background. Please disable battery optimizations so Briar can stay connected.</string>
|
||||
<string name="setup_doze_button">Allow Connections</string>
|
||||
<string name="choose_nickname">Choose your nickname</string>
|
||||
<string name="choose_password">Choose your password</string>
|
||||
<string name="confirm_password">Confirm your password</string>
|
||||
@@ -11,6 +18,7 @@
|
||||
<string name="password_too_weak">Password is too weak</string>
|
||||
<string name="passwords_do_not_match">Passwords do not match</string>
|
||||
<string name="create_account_button">Create Account</string>
|
||||
<string name="more_info">More Information</string>
|
||||
|
||||
<!-- Login -->
|
||||
<string name="enter_password">Enter your password:</string>
|
||||
|
||||
@@ -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<ResultHandler<Boolean>> 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<Void> resultHandler =
|
||||
(ResultHandler<Void>) 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<Boolean> resultHandler2 =
|
||||
(ResultHandler<Boolean>) 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"));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -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<Boolean>() {
|
||||
@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<Boolean>() {
|
||||
@Override
|
||||
public void onResult(Boolean result) {
|
||||
capturedResult.set(result);
|
||||
}
|
||||
});
|
||||
assertFalse(capturedResult.get());
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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<ResultHandler<Void>> 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<Void> resultHandler =
|
||||
(ResultHandler<Void>) 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"));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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<Void>() {
|
||||
@Override
|
||||
public void onResult(Void result) {
|
||||
called.set(true);
|
||||
}
|
||||
});
|
||||
assertTrue(called.get());
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -4,6 +4,9 @@ allprojects {
|
||||
repositories {
|
||||
jcenter()
|
||||
mavenLocal()
|
||||
maven {
|
||||
url 'https://maven.google.com'
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user