diff --git a/briar-android/res/layout/activity_password.xml b/briar-android/res/layout/activity_password.xml
new file mode 100644
index 000000000..5a306a79c
--- /dev/null
+++ b/briar-android/res/layout/activity_password.xml
@@ -0,0 +1,61 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/briar-android/res/values-v14/styles.xml b/briar-android/res/values-v14/styles.xml
index 9fd201d23..c1fc08f07 100644
--- a/briar-android/res/values-v14/styles.xml
+++ b/briar-android/res/values-v14/styles.xml
@@ -9,4 +9,9 @@
- @color/action_bar_text
- @color/action_bar_background
+
+
+
\ No newline at end of file
diff --git a/briar-android/res/values/color.xml b/briar-android/res/values/color.xml
index 00b5d2412..18e88d64c 100644
--- a/briar-android/res/values/color.xml
+++ b/briar-android/res/values/color.xml
@@ -14,4 +14,6 @@
#AAAAAA
#2D3E50
#2D3E50
+
+ #2D3E50
\ No newline at end of file
diff --git a/briar-android/res/values/dimens.xml b/briar-android/res/values/dimens.xml
new file mode 100644
index 000000000..35c316f12
--- /dev/null
+++ b/briar-android/res/values/dimens.xml
@@ -0,0 +1,21 @@
+
+
+
+ 16dp
+ 16dp
+
+ 1dp
+ 2dp
+ 4dp
+ 8dp
+ 16dp
+ 32dp
+
+
+ 12sp
+ 14sp
+ 16sp
+ 20sp
+ 34sp
+
+
diff --git a/briar-android/res/values/strings.xml b/briar-android/res/values/strings.xml
index d429004d6..6532d77d8 100644
--- a/briar-android/res/values/strings.xml
+++ b/briar-android/res/values/strings.xml
@@ -1,5 +1,7 @@
+
+
Briar
Briar Crash Report
Signed into Briar
@@ -13,6 +15,10 @@
Passwords do not match
Create Account
Enter your password:
+ Password
+ Yes
+ No
+ I have forgotten my password
Wrong password, try again:
Sign In
Briar could not start
@@ -104,4 +110,8 @@
Default ringtone
None
Choose ringtone
+
+
+ Lost password
+ Password recovery is not possible. Do you wish to delete your user, all contacts, and re-register ?
\ No newline at end of file
diff --git a/briar-android/res/values/styles.xml b/briar-android/res/values/styles.xml
index 79b84d8b7..4c5928922 100644
--- a/briar-android/res/values/styles.xml
+++ b/briar-android/res/values/styles.xml
@@ -12,4 +12,21 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/briar-android/src/org/briarproject/android/BaseActivity.java b/briar-android/src/org/briarproject/android/BaseActivity.java
new file mode 100644
index 000000000..f2b2fdeef
--- /dev/null
+++ b/briar-android/src/org/briarproject/android/BaseActivity.java
@@ -0,0 +1,59 @@
+package org.briarproject.android;
+
+import static android.view.inputmethod.InputMethodManager.HIDE_IMPLICIT_ONLY;
+import static org.briarproject.android.TestingConstants.PREVENT_SCREENSHOTS;
+import static android.view.WindowManager.LayoutParams.FLAG_SECURE;
+
+import android.content.Intent;
+import android.content.SharedPreferences;
+import android.os.Bundle;
+import android.view.inputmethod.InputMethodManager;
+
+import roboguice.activity.RoboActivity;
+
+public abstract class BaseActivity extends RoboActivity {
+
+ private final static String PREFS_DB = "db";
+ private final static String KEY_DB_KEY = "key";
+
+ @Override
+ public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+
+ if (PREVENT_SCREENSHOTS) getWindow().addFlags(FLAG_SECURE);
+ }
+
+ private SharedPreferences getBriarPrefs(String prefsName) {
+ return getSharedPreferences(prefsName, MODE_PRIVATE);
+ }
+
+ protected String getDbKeyInHex() {
+ return getBriarPrefs(PREFS_DB).getString(KEY_DB_KEY, null);
+ }
+
+ private void clearPrefs(String prefsName) {
+ SharedPreferences.Editor editor = getBriarPrefs(prefsName).edit();
+ editor.clear();
+ editor.apply();
+ }
+
+ protected void clearDbPrefs() {
+ this.clearPrefs(PREFS_DB);
+ }
+
+ protected void gotoAndFinish(Class classInstance, int resultCode) {
+ if (resultCode != Integer.MIN_VALUE)
+ setResult(resultCode);
+ startActivity(new Intent(this, classInstance));
+ finish();
+ }
+
+ protected void gotoAndFinish(Class classInstance) {
+ gotoAndFinish(classInstance, Integer.MIN_VALUE);
+ }
+
+ protected void hideSoftKeyboard() {
+ Object o = getSystemService(INPUT_METHOD_SERVICE);
+ ((InputMethodManager) o).toggleSoftInput(HIDE_IMPLICIT_ONLY, 0);
+ }
+}
diff --git a/briar-android/src/org/briarproject/android/BriarActivity.java b/briar-android/src/org/briarproject/android/BriarActivity.java
index e098bfee7..49a025914 100644
--- a/briar-android/src/org/briarproject/android/BriarActivity.java
+++ b/briar-android/src/org/briarproject/android/BriarActivity.java
@@ -25,7 +25,7 @@ import android.os.IBinder;
import android.view.inputmethod.InputMethodManager;
@SuppressLint("Registered")
-public class BriarActivity extends RoboActivity {
+public class BriarActivity extends BaseActivity {
public static final int REQUEST_PASSWORD = 1;
@@ -45,7 +45,6 @@ public class BriarActivity extends RoboActivity {
@Override
public void onCreate(Bundle state) {
super.onCreate(state);
- if (PREVENT_SCREENSHOTS) getWindow().addFlags(FLAG_SECURE);
if (databaseConfig.getEncryptionKey() != null) startAndBindService();
}
diff --git a/briar-android/src/org/briarproject/android/CrashReportActivity.java b/briar-android/src/org/briarproject/android/CrashReportActivity.java
index 539591cb7..a2b8b2ac9 100644
--- a/briar-android/src/org/briarproject/android/CrashReportActivity.java
+++ b/briar-android/src/org/briarproject/android/CrashReportActivity.java
@@ -45,7 +45,6 @@ import org.briarproject.android.util.LayoutUtils;
import org.briarproject.android.util.ListLoadingProgressBar;
import org.briarproject.api.android.AndroidExecutor;
import org.briarproject.api.system.FileUtils;
-import org.briarproject.system.AndroidFileUtils;
import org.briarproject.util.StringUtils;
import android.annotation.SuppressLint;
@@ -71,12 +70,14 @@ import android.widget.LinearLayout;
import android.widget.ScrollView;
import android.widget.TextView;
+import javax.inject.Inject;
+
public class CrashReportActivity extends Activity implements OnClickListener {
private static final Logger LOG =
Logger.getLogger(CrashReportActivity.class.getName());
- private final FileUtils fileUtils = new AndroidFileUtils();
+ @Inject private FileUtils fileUtils;
private final AndroidExecutor androidExecutor = new AndroidExecutorImpl();
private ScrollView scroll = null;
diff --git a/briar-android/src/org/briarproject/android/PasswordActivity.java b/briar-android/src/org/briarproject/android/PasswordActivity.java
index c3437852d..383fa88b8 100644
--- a/briar-android/src/org/briarproject/android/PasswordActivity.java
+++ b/briar-android/src/org/briarproject/android/PasswordActivity.java
@@ -1,138 +1,106 @@
package org.briarproject.android;
-import static android.text.InputType.TYPE_CLASS_TEXT;
-import static android.text.InputType.TYPE_TEXT_VARIATION_PASSWORD;
-import static android.view.Gravity.CENTER;
-import static android.view.Gravity.CENTER_HORIZONTAL;
import static android.view.View.GONE;
import static android.view.View.VISIBLE;
-import static android.view.WindowManager.LayoutParams.FLAG_SECURE;
-import static android.view.inputmethod.InputMethodManager.HIDE_IMPLICIT_ONLY;
-import static android.widget.LinearLayout.VERTICAL;
-import static org.briarproject.android.TestingConstants.PREVENT_SCREENSHOTS;
-import static org.briarproject.android.util.CommonLayoutParams.MATCH_MATCH;
-import static org.briarproject.android.util.CommonLayoutParams.WRAP_WRAP;
-import java.io.File;
import java.util.concurrent.Executor;
import javax.inject.Inject;
import org.briarproject.R;
-import org.briarproject.android.util.FixedVerticalSpace;
-import org.briarproject.android.util.LayoutUtils;
import org.briarproject.api.crypto.CryptoComponent;
import org.briarproject.api.crypto.CryptoExecutor;
import org.briarproject.api.crypto.SecretKey;
import org.briarproject.api.db.DatabaseConfig;
+import org.briarproject.api.system.FileUtils;
import org.briarproject.util.StringUtils;
-import roboguice.activity.RoboActivity;
-import android.content.Intent;
-import android.content.SharedPreferences;
+import android.app.AlertDialog;
+import android.content.DialogInterface;
import android.os.Bundle;
import android.text.Editable;
import android.view.KeyEvent;
import android.view.View;
-import android.view.View.OnClickListener;
-import android.view.inputmethod.InputMethodManager;
+import android.view.inputmethod.EditorInfo;
import android.widget.Button;
import android.widget.EditText;
-import android.widget.LinearLayout;
import android.widget.ProgressBar;
import android.widget.TextView;
import android.widget.TextView.OnEditorActionListener;
-public class PasswordActivity extends RoboActivity {
+public class PasswordActivity extends BaseActivity {
@Inject @CryptoExecutor private Executor cryptoExecutor;
- private TextView enterPassword = null;
- private EditText passwordEntry = null;
- private Button signInButton = null;
- private ProgressBar progress = null;
+ private Button signInButton;
+ private ProgressBar progress;
+ private TextView title;
+ private EditText password;
+
+ private byte[] encrypted;
// Fields that are accessed from background threads must be volatile
@Inject private volatile CryptoComponent crypto;
@Inject private volatile DatabaseConfig databaseConfig;
+ @Inject private FileUtils fileUtils;
@Override
public void onCreate(Bundle state) {
super.onCreate(state);
- if (PREVENT_SCREENSHOTS) getWindow().addFlags(FLAG_SECURE);
-
- SharedPreferences prefs = getSharedPreferences("db", MODE_PRIVATE);
- String hex = prefs.getString("key", null);
+ String hex = getDbKeyInHex();
if (hex == null || !databaseConfig.databaseExists()) {
- // Storage has been deleted - clean up and return to setup
- prefs.edit().clear().commit();
- delete(databaseConfig.getDatabaseDirectory());
- setResult(RESULT_CANCELED);
- startActivity(new Intent(this, SetupActivity.class));
- finish();
+ clearDbPrefs();
return;
}
- final byte[] encrypted = StringUtils.fromHexString(hex);
+ encrypted = StringUtils.fromHexString(hex);
- LinearLayout layout = new LinearLayout(this);
- layout.setLayoutParams(MATCH_MATCH);
- layout.setOrientation(VERTICAL);
- layout.setGravity(CENTER_HORIZONTAL);
- int pad = LayoutUtils.getPadding(this);
- layout.setPadding(pad, pad, pad, pad);
-
- enterPassword = new TextView(this);
- enterPassword.setGravity(CENTER);
- enterPassword.setTextSize(18);
- enterPassword.setText(R.string.enter_password);
- layout.addView(enterPassword);
-
- passwordEntry = new EditText(this);
- passwordEntry.setId(1);
- passwordEntry.setMaxLines(1);
- int inputType = TYPE_CLASS_TEXT | TYPE_TEXT_VARIATION_PASSWORD;
- passwordEntry.setInputType(inputType);
- passwordEntry.setOnEditorActionListener(new OnEditorActionListener() {
- public boolean onEditorAction(TextView v, int action, KeyEvent e) {
- validatePassword(encrypted, passwordEntry.getText());
- return true;
+ setContentView(R.layout.activity_password);
+ signInButton = (Button)findViewById(R.id.btn_sign_in);
+ progress = (ProgressBar)findViewById(R.id.progress_wheel);
+ title = (TextView)findViewById(R.id.title_password);
+ password = (EditText)findViewById(R.id.edit_password);
+ password.setOnEditorActionListener(new OnEditorActionListener() {
+ @Override
+ public boolean onEditorAction(TextView v, int actionId, KeyEvent event) {
+ if (actionId == EditorInfo.IME_ACTION_DONE) {
+ validatePassword(encrypted, password.getText());
+ }
+ return false;
}
});
- layout.addView(passwordEntry);
-
- // Adjusting the padding of buttons and EditTexts has the wrong results
- layout.addView(new FixedVerticalSpace(this));
-
- signInButton = new Button(this);
- signInButton.setLayoutParams(WRAP_WRAP);
- signInButton.setText(R.string.sign_in_button);
- signInButton.setOnClickListener(new OnClickListener() {
- public void onClick(View v) {
- validatePassword(encrypted, passwordEntry.getText());
- }
- });
- layout.addView(signInButton);
-
- progress = new ProgressBar(this);
- progress.setLayoutParams(WRAP_WRAP);
- progress.setIndeterminate(true);
- progress.setVisibility(GONE);
- layout.addView(progress);
- setContentView(layout);
}
- private void delete(File f) {
- if (f.isFile()) f.delete();
- else if (f.isDirectory()) for (File child : f.listFiles()) delete(child);
+ @Override
+ protected void clearDbPrefs() {
+ super.clearDbPrefs();
+ fileUtils.deleteFileOrDir(databaseConfig.getDatabaseDirectory());
+ gotoAndFinish(SetupActivity.class, RESULT_CANCELED);
+ }
+
+ public void onSignInClick(View v) {
+ validatePassword(encrypted, password.getText());
+ }
+
+ public void onForgottenPasswordClick(View v) {
+ // TODO Encapsulate the dialog in a re-usable fragment
+ AlertDialog.Builder builder = new AlertDialog.Builder(this);
+ builder.setTitle(R.string.dialog_title_lost_password);
+ builder.setMessage(R.string.dialog_message_lost_password);
+ builder.setNegativeButton(R.string.no, null);
+ builder.setPositiveButton(R.string.yes, new DialogInterface.OnClickListener() {
+ @Override
+ public void onClick(DialogInterface dialog, int which) {
+ clearDbPrefs();
+ }
+ });
+ AlertDialog dialog = builder.create();
+ dialog.show();
}
private void validatePassword(final byte[] encrypted, Editable e) {
- if (progress == null) return; // Not created yet
- // Hide the soft keyboard
- Object o = getSystemService(INPUT_METHOD_SERVICE);
- ((InputMethodManager) o).toggleSoftInput(HIDE_IMPLICIT_ONLY, 0);
+ hideSoftKeyboard();
// Replace the button with a progress bar
- signInButton.setVisibility(GONE);
+ signInButton.setVisibility(View.INVISIBLE);
progress.setVisibility(VISIBLE);
// Decrypt the database key in a background thread
final String password = e.toString();
@@ -152,10 +120,10 @@ public class PasswordActivity extends RoboActivity {
private void tryAgain() {
runOnUiThread(new Runnable() {
public void run() {
- enterPassword.setText(R.string.try_again);
- passwordEntry.setText("");
+ title.setText(R.string.try_again);
signInButton.setVisibility(VISIBLE);
progress.setVisibility(GONE);
+ password.setText("");
}
});
}
diff --git a/briar-android/src/org/briarproject/system/AndroidFileUtils.java b/briar-android/src/org/briarproject/system/AndroidFileUtils.java
deleted file mode 100644
index c0beb54d8..000000000
--- a/briar-android/src/org/briarproject/system/AndroidFileUtils.java
+++ /dev/null
@@ -1,17 +0,0 @@
-package org.briarproject.system;
-
-import org.briarproject.api.system.FileUtils;
-
-import java.io.File;
-import java.io.IOException;
-
-public class AndroidFileUtils implements FileUtils {
-
- public long getTotalSpace(File f) throws IOException {
- return f.getTotalSpace();
- }
-
- public long getFreeSpace(File f) throws IOException {
- return f.getUsableSpace();
- }
-}
diff --git a/briar-android/src/org/briarproject/system/AndroidSystemModule.java b/briar-android/src/org/briarproject/system/AndroidSystemModule.java
index aa6769e59..03fd56dcc 100644
--- a/briar-android/src/org/briarproject/system/AndroidSystemModule.java
+++ b/briar-android/src/org/briarproject/system/AndroidSystemModule.java
@@ -14,7 +14,7 @@ public class AndroidSystemModule extends AbstractModule {
bind(Clock.class).to(SystemClock.class);
bind(Timer.class).to(SystemTimer.class);
bind(SeedProvider.class).to(AndroidSeedProvider.class);
- bind(FileUtils.class).to(AndroidFileUtils.class);
+ bind(FileUtils.class).to(FileUtilsImpl.class);
bind(LocationUtils.class).to(AndroidLocationUtils.class);
}
}
diff --git a/briar-api/src/org/briarproject/api/system/FileUtils.java b/briar-api/src/org/briarproject/api/system/FileUtils.java
index bde396049..baf68ca01 100644
--- a/briar-api/src/org/briarproject/api/system/FileUtils.java
+++ b/briar-api/src/org/briarproject/api/system/FileUtils.java
@@ -8,4 +8,6 @@ public interface FileUtils {
long getTotalSpace(File f) throws IOException;
long getFreeSpace(File f) throws IOException;
+
+ void deleteFileOrDir(File f);
}
diff --git a/briar-core/src/org/briarproject/system/FileUtilsImpl.java b/briar-core/src/org/briarproject/system/FileUtilsImpl.java
new file mode 100644
index 000000000..923f35c9a
--- /dev/null
+++ b/briar-core/src/org/briarproject/system/FileUtilsImpl.java
@@ -0,0 +1,25 @@
+package org.briarproject.system;
+
+import org.briarproject.api.system.FileUtils;
+
+import java.io.File;
+import java.io.IOException;
+
+public class FileUtilsImpl implements FileUtils {
+
+ public long getTotalSpace(File f) throws IOException {
+ return f.getTotalSpace(); // Requires Java 1.6
+ }
+
+ public long getFreeSpace(File f) throws IOException {
+ return f.getUsableSpace(); // Requires Java 1.6
+ }
+
+ public void deleteFileOrDir(File f) {
+ if (f.isFile())
+ f.delete();
+ else if (f.isDirectory())
+ for (File child : f.listFiles())
+ deleteFileOrDir(child);
+ }
+}
diff --git a/briar-desktop/src/org/briarproject/system/DesktopFileUtils.java b/briar-desktop/src/org/briarproject/system/DesktopFileUtils.java
deleted file mode 100644
index c39706864..000000000
--- a/briar-desktop/src/org/briarproject/system/DesktopFileUtils.java
+++ /dev/null
@@ -1,17 +0,0 @@
-package org.briarproject.system;
-
-import java.io.File;
-import java.io.IOException;
-
-import org.briarproject.api.system.FileUtils;
-
-class DesktopFileUtils implements FileUtils {
-
- public long getTotalSpace(File f) throws IOException {
- return f.getTotalSpace(); // Requires Java 1.6
- }
-
- public long getFreeSpace(File f) throws IOException {
- return f.getUsableSpace(); // Requires Java 1.6
- }
-}
diff --git a/briar-desktop/src/org/briarproject/system/DesktopSystemModule.java b/briar-desktop/src/org/briarproject/system/DesktopSystemModule.java
index e6286d17d..e605fe950 100644
--- a/briar-desktop/src/org/briarproject/system/DesktopSystemModule.java
+++ b/briar-desktop/src/org/briarproject/system/DesktopSystemModule.java
@@ -15,6 +15,6 @@ public class DesktopSystemModule extends AbstractModule {
bind(Timer.class).to(SystemTimer.class);
if (OsUtils.isLinux())
bind(SeedProvider.class).to(LinuxSeedProvider.class);
- bind(FileUtils.class).to(DesktopFileUtils.class);
+ bind(FileUtils.class).to(FileUtilsImpl.class);
}
}
diff --git a/briar-tests/src/org/briarproject/TestDatabaseModule.java b/briar-tests/src/org/briarproject/TestDatabaseModule.java
index 263ec20c2..c04b3ba51 100644
--- a/briar-tests/src/org/briarproject/TestDatabaseModule.java
+++ b/briar-tests/src/org/briarproject/TestDatabaseModule.java
@@ -4,6 +4,7 @@ import com.google.inject.AbstractModule;
import org.briarproject.api.db.DatabaseConfig;
import org.briarproject.api.system.FileUtils;
+import org.briarproject.system.FileUtilsImpl;
import java.io.File;
@@ -25,6 +26,6 @@ public class TestDatabaseModule extends AbstractModule {
protected void configure() {
bind(DatabaseConfig.class).toInstance(config);
- bind(FileUtils.class).to(TestFileUtils.class);
+ bind(FileUtils.class).to(FileUtilsImpl.class);
}
}
diff --git a/briar-tests/src/org/briarproject/TestFileUtils.java b/briar-tests/src/org/briarproject/TestFileUtils.java
deleted file mode 100644
index 78a02ff81..000000000
--- a/briar-tests/src/org/briarproject/TestFileUtils.java
+++ /dev/null
@@ -1,17 +0,0 @@
-package org.briarproject;
-
-import org.briarproject.api.system.FileUtils;
-
-import java.io.File;
-import java.io.IOException;
-
-public class TestFileUtils implements FileUtils {
-
- public long getTotalSpace(File f) throws IOException {
- return f.getTotalSpace();
- }
-
- public long getFreeSpace(File f) throws IOException {
- return f.getUsableSpace();
- }
-}
diff --git a/briar-tests/src/org/briarproject/db/H2DatabaseTest.java b/briar-tests/src/org/briarproject/db/H2DatabaseTest.java
index 5aff9c74a..430a9a7ec 100644
--- a/briar-tests/src/org/briarproject/db/H2DatabaseTest.java
+++ b/briar-tests/src/org/briarproject/db/H2DatabaseTest.java
@@ -2,7 +2,6 @@ package org.briarproject.db;
import org.briarproject.BriarTestCase;
import org.briarproject.TestDatabaseConfig;
-import org.briarproject.TestFileUtils;
import org.briarproject.TestMessage;
import org.briarproject.TestUtils;
import org.briarproject.api.Author;
@@ -20,6 +19,7 @@ import org.briarproject.api.messaging.Message;
import org.briarproject.api.messaging.MessageId;
import org.briarproject.api.transport.Endpoint;
import org.briarproject.api.transport.TemporarySecret;
+import org.briarproject.system.FileUtilsImpl;
import org.briarproject.system.SystemClock;
import org.junit.After;
import org.junit.Before;
@@ -1610,7 +1610,7 @@ public class H2DatabaseTest extends BriarTestCase {
private Database open(boolean resume) throws Exception {
Database db = new H2Database(new TestDatabaseConfig(testDir,
- MAX_SIZE), new TestFileUtils(), new SystemClock());
+ MAX_SIZE), new FileUtilsImpl(), new SystemClock());
if (!resume) TestUtils.deleteTestDirectory(testDir);
db.open();
return db;
diff --git a/briar-tests/src/org/briarproject/plugins/file/RemovableDrivePluginTest.java b/briar-tests/src/org/briarproject/plugins/file/RemovableDrivePluginTest.java
index f4326e9e6..cb29fc269 100644
--- a/briar-tests/src/org/briarproject/plugins/file/RemovableDrivePluginTest.java
+++ b/briar-tests/src/org/briarproject/plugins/file/RemovableDrivePluginTest.java
@@ -1,7 +1,7 @@
package org.briarproject.plugins.file;
+import com.google.inject.Inject;
import org.briarproject.BriarTestCase;
-import org.briarproject.TestFileUtils;
import org.briarproject.TestUtils;
import org.briarproject.api.ContactId;
import org.briarproject.api.plugins.TransportConnectionWriter;
@@ -34,7 +34,7 @@ public class RemovableDrivePluginTest extends BriarTestCase {
private final File testDir = TestUtils.getTestDirectory();
private final ContactId contactId = new ContactId(234);
- private final FileUtils fileUtils = new TestFileUtils();
+ @Inject private FileUtils fileUtils;
@Before
public void setUp() {