Compare commits

..

3 Commits

Author SHA1 Message Date
Torsten Grote
51cf49da19 Create AccountManager to encapsulate authentication and account logic 2018-07-12 18:35:58 -03:00
Torsten Grote
9892199305 Also remind to sign-in again after app was upgraded 2018-07-09 09:55:08 -03:00
Torsten Grote
b28307002e Add an option to not show the sign-in reminder
This is done via another preference in the settings screen
and an action button attached to the notification itself
2018-07-09 09:55:08 -03:00
88 changed files with 1171 additions and 924 deletions

View File

@@ -8,8 +8,8 @@ android {
defaultConfig {
minSdkVersion 14
targetSdkVersion 26
versionCode 10012
versionName "1.0.12"
versionCode 10011
versionName "1.0.11"
consumerProguardFiles 'proguard-rules.txt'
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
@@ -28,7 +28,7 @@ configurations {
dependencies {
implementation project(path: ':bramble-core', configuration: 'default')
implementation 'org.briarproject:jtorctl:0.3'
tor 'org.briarproject:tor-android:0.2.9.16@zip'
tor 'org.briarproject:tor-android:0.2.9.15@zip'
annotationProcessor 'com.google.dagger:dagger-compiler:2.0.2'
@@ -100,7 +100,7 @@ dependencyVerification {
'org.bouncycastle:bcpkix-jdk15on:1.56:bcpkix-jdk15on-1.56.jar:7043dee4e9e7175e93e0b36f45b1ec1ecb893c5f755667e8b916eb8dd201c6ca',
'org.bouncycastle:bcprov-jdk15on:1.56:bcprov-jdk15on-1.56.jar:963e1ee14f808ffb99897d848ddcdb28fa91ddda867eb18d303e82728f878349',
'org.briarproject:jtorctl:0.3:jtorctl-0.3.jar:f2939238a097898998432effe93b0334d97a787972ab3a91a8973a1d309fc864',
'org.briarproject:tor-android:0.2.9.16:tor-android-0.2.9.16.zip:515e33dda6a30853c885a2de2c79ae1ab9ad8b6db44f5db8890333ec2e24f4ae',
'org.briarproject:tor-android:0.2.9.15:tor-android-0.2.9.15.zip:34a6474ee219ffa52e0f3393e917dda6ed03d320b02247d4fa5075aa4094ee6d',
'org.codehaus.groovy:groovy-all:2.4.12:groovy-all-2.4.12.jar:6a56af4bd48903d56bec62821876cadefafd007360cc6bd0d8f7aa8d72b38be4',
'org.codehaus.mojo:animal-sniffer-annotations:1.14:animal-sniffer-annotations-1.14.jar:2068320bd6bad744c3673ab048f67e30bef8f518996fa380033556600669905d',
'org.glassfish.jaxb:jaxb-core:2.2.11:jaxb-core-2.2.11.jar:37bcaee8ebb04362c8352a5bf6221b86967ecdab5164c696b10b9a2bb587b2aa',

View File

@@ -2,13 +2,14 @@
package="org.briarproject.bramble"
xmlns:android="http://schemas.android.com/apk/res/android">
<uses-feature android:name="android.hardware.bluetooth" android:required="false"/>
<uses-feature android:name="android.hardware.bluetooth"/>
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE"/>
<uses-permission android:name="android.permission.BLUETOOTH"/>
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN"/>
<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.READ_LOGS"/>
<uses-permission android:name="android.permission.WAKE_LOCK"/>
<application

View File

@@ -2,7 +2,4 @@ Bridge 131.252.210.150:8081 0E858AC201BF0F3FA3C462F64844CBFFC7297A42
Bridge 67.205.189.122:8443 12D64D5D44E20169585E7378580C0D33A872AD98
Bridge 45.32.148.146:8443 0CE016FB2462D8BF179AE71F7D702D09DEAC3F1D
Bridge 148.251.90.59:7510 019F727CA6DCA6CA5C90B55E477B7D87981E75BC
Bridge 195.91.239.8:9001 BA83F62551545655BBEBBFF353A45438D73FD45A
Bridge 185.165.184.217:6429 64CC94BEC51254E4409AD059192833854CCB95F0
Bridge 45.55.1.74:8443 6F18FEFBB0CAECD5ABA755312FCCB34FC11A7AB8
Bridge 95.85.40.163:9001 40057BE9CF76B6C5BDBE713753468BE0A990DE9C
#Bridge 128.105.214.161:8081 1E326AAFB3FCB515015250D8FCCC8E37F91A153B

View File

@@ -0,0 +1,39 @@
package org.briarproject.bramble.api.account;
import org.briarproject.bramble.api.crypto.CryptoExecutor;
import org.briarproject.bramble.api.identity.IdentityManager;
import org.briarproject.bramble.api.identity.LocalAuthor;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import javax.annotation.Nullable;
@NotNullByDefault
public interface AccountManager {
@CryptoExecutor
void createAccount(String name, String password);
AccountState getAccountState();
/**
* Returns the name of the {@link LocalAuthor} if it was just created and
* null otherwise.
*
* See {@link IdentityManager#getLocalAuthor()} for reliable retrieval.
*/
@Nullable
String getCreatedLocalAuthorName();
/**
* Validates the account password and returns true if it was valid.
*/
boolean validatePassword(String password);
/**
* Changes the password and returns true if successful, false otherwise.
*/
@CryptoExecutor
boolean changePassword(String password, String newPassword);
void deleteAccount();
}

View File

@@ -0,0 +1,12 @@
package org.briarproject.bramble.api.account;
public enum AccountState {
NO_ACCOUNT,
CREATING_ACCOUNT,
SIGNING_IN,
SIGNED_IN,
SIGNING_OUT,
SIGNED_OUT
}

View File

@@ -21,10 +21,5 @@ public interface DatabaseConfig {
@Nullable
SecretKey getEncryptionKey();
void setLocalAuthorName(String nickname);
@Nullable
String getLocalAuthorName();
long getMaxSize();
}

View File

@@ -0,0 +1,127 @@
package org.briarproject.bramble.account;
import org.briarproject.bramble.api.account.AccountManager;
import org.briarproject.bramble.api.account.AccountState;
import org.briarproject.bramble.api.crypto.CryptoComponent;
import org.briarproject.bramble.api.crypto.CryptoExecutor;
import org.briarproject.bramble.api.crypto.SecretKey;
import org.briarproject.bramble.api.db.DatabaseConfig;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import org.briarproject.bramble.util.StringUtils;
import java.util.logging.Logger;
import javax.annotation.Nullable;
import static java.util.logging.Level.INFO;
import static org.briarproject.bramble.api.account.AccountState.CREATING_ACCOUNT;
import static org.briarproject.bramble.api.account.AccountState.NO_ACCOUNT;
import static org.briarproject.bramble.api.account.AccountState.SIGNED_IN;
import static org.briarproject.bramble.api.account.AccountState.SIGNED_OUT;
import static org.briarproject.bramble.util.LogUtils.logDuration;
import static org.briarproject.bramble.util.LogUtils.now;
@NotNullByDefault
public abstract class AccountManagerImpl implements AccountManager {
private final static Logger LOG =
Logger.getLogger(AccountManagerImpl.class.getSimpleName());
protected final DatabaseConfig databaseConfig;
private final CryptoComponent crypto;
@Nullable
private volatile String nickname = null;
public AccountManagerImpl(CryptoComponent crypto,
DatabaseConfig databaseConfig) {
this.crypto = crypto;
this.databaseConfig = databaseConfig;
}
protected abstract boolean storeEncryptedDatabaseKey(String hex);
@Nullable
protected abstract String getEncryptedDatabaseKey();
private boolean hasEncryptedDatabaseKey() {
return getEncryptedDatabaseKey() != null;
}
@Override
@CryptoExecutor
public void createAccount(String name, String password) {
LOG.info("Setting local author name");
this.nickname = name;
SecretKey key = crypto.generateSecretKey();
databaseConfig.setEncryptionKey(key);
String hex = encryptDatabaseKey(key, password);
storeEncryptedDatabaseKey(hex);
}
@Override
public AccountState getAccountState() {
AccountState state;
if (!databaseConfig.databaseExists() && nickname != null &&
hasEncryptedDatabaseKey()) {
state = CREATING_ACCOUNT;
} else if (!hasEncryptedDatabaseKey()) {
state = NO_ACCOUNT;
} else if (databaseConfig.getEncryptionKey() == null) {
state = SIGNED_OUT;
} else {
state = SIGNED_IN;
}
// TODO SIGNING_IN, SIGNING_OUT, DELETING_ACCOUNT
if (LOG.isLoggable(INFO)) LOG.info("Account State: " + state.name());
return state;
}
@Nullable
@Override
public String getCreatedLocalAuthorName() {
String nickname = this.nickname;
if (LOG.isLoggable(INFO))
LOG.info("Local author name has been set: " + (nickname != null));
return nickname;
}
@CryptoExecutor
private String encryptDatabaseKey(SecretKey key, String password) {
long start = now();
byte[] encrypted = crypto.encryptWithPassword(key.getBytes(), password);
logDuration(LOG, "Key derivation", start);
return StringUtils.toHexString(encrypted);
}
@Override
public boolean validatePassword(String password) {
byte[] encrypted = getEncryptedKeyAsBytes();
byte[] key = crypto.decryptWithPassword(encrypted, password);
if (key == null) {
return false;
}
databaseConfig.setEncryptionKey(new SecretKey(key));
return true;
}
@Override
@CryptoExecutor
public boolean changePassword(String password, String newPassword) {
byte[] encrypted = getEncryptedKeyAsBytes();
byte[] key = crypto.decryptWithPassword(encrypted, password);
if (key == null) {
return false;
}
String hex = encryptDatabaseKey(new SecretKey(key), newPassword);
return storeEncryptedDatabaseKey(hex);
}
private byte[] getEncryptedKeyAsBytes() {
String hex = getEncryptedDatabaseKey();
if (hex == null)
throw new IllegalStateException("Encrypted database key is null");
return StringUtils.fromHexString(hex);
}
}

View File

@@ -46,16 +46,6 @@ public class TestDatabaseConfig implements DatabaseConfig {
return key;
}
@Override
public void setLocalAuthorName(String nickname) {
}
@Override
public String getLocalAuthorName() {
return null;
}
@Override
public long getMaxSize() {
return maxSize;

View File

@@ -14,7 +14,7 @@
x="0px"
y="0px"
xml:space="preserve"
inkscape:version="0.92.3 (2405546, 2018-03-11)"
inkscape:version="0.91 r13725"
sodipodi:docname="logo_horizontal_white.svg"
width="138"
height="50"><metadata
@@ -31,18 +31,18 @@
inkscape:pageopacity="0"
inkscape:pageshadow="2"
inkscape:window-width="1920"
inkscape:window-height="1020"
inkscape:window-height="1021"
id="namedview67"
showgrid="false"
fit-margin-top="0"
fit-margin-left="0"
fit-margin-right="0"
fit-margin-bottom="0"
inkscape:zoom="5.640316"
inkscape:cx="47.227033"
inkscape:cy="7.5801079"
inkscape:window-x="1440"
inkscape:window-y="24"
inkscape:zoom="1.410079"
inkscape:cx="96.786606"
inkscape:cy="117.77539"
inkscape:window-x="1443"
inkscape:window-y="23"
inkscape:window-maximized="0"
inkscape:current-layer="Ebene_1" /><style
type="text/css"
@@ -53,7 +53,55 @@
.st3{fill:#95D220;}
.st4{display:none;fill:#95D220;}
.st5{fill:#FFFFFF;}
</style><path
</style><rect
style="display:none;fill:#87c214"
id="rect11"
height="9.279274"
width="9.279274"
class="st0"
y="214.00124"
x="230.02246" /><path
class="st2"
d="m 235.54331,203.97877 c 2.05971,0 3.75843,1.69872 3.75843,3.75842 l 0,42.40437 c 0,2.05971 -1.69872,3.75843 -3.75843,3.75843 l -1.76242,0 c -2.0597,0 -3.75843,-1.69872 -3.75843,-3.75843 l 0,-42.40437 c 0,-2.0597 1.67749,-3.75842 3.73719,-3.75842 l 1.78366,0 m 0,-1.48638 -1.76242,0 c -2.90906,0 -5.24481,2.35697 -5.24481,5.2448 l 0,42.40437 c 0,2.88783 2.35698,5.24481 5.24481,5.24481 l 1.76242,0 c 2.88783,0 5.24481,-2.35698 5.24481,-5.24481 l 0,-42.40437 c -0.0212,-2.88783 -2.35698,-5.2448 -5.24481,-5.2448 l 0,0 z"
id="path17"
inkscape:connector-curvature="0"
style="display:none;fill:#ffffff" /><rect
style="display:none;fill:#87c214"
id="rect25"
height="9.279274"
width="9.279274"
class="st0"
y="234.59825"
x="250.61948" /><path
class="st2"
d="m 256.14033,203.97877 c 2.0597,0 3.75842,1.69872 3.75842,3.75842 l 0,42.40437 c 0,2.05971 -1.67749,3.75843 -3.75842,3.75843 l -1.76243,0 c -2.0597,0 -3.75842,-1.69872 -3.75842,-3.75843 l 0,-42.40437 c 0,-2.0597 1.69872,-3.75842 3.75842,-3.75842 l 1.76243,0 m 0,-1.48638 -1.76243,0 c -2.88783,0 -5.2448,2.35697 -5.2448,5.2448 l 0,42.40437 c 0,2.88783 2.35697,5.24481 5.2448,5.24481 l 1.76243,0 c 2.88783,0 5.24481,-2.35698 5.24481,-5.24481 l 0,-42.40437 c -0.0212,-2.88783 -2.35698,-5.2448 -5.24481,-5.2448 l 0,0 z"
id="path29"
inkscape:connector-curvature="0"
style="display:none;fill:#ffffff" /><rect
style="display:none;fill:#95d220"
id="rect37"
height="9.279274"
width="9.279274"
class="st4"
y="234.59825"
x="230.02246" /><path
class="st2"
d="m 266.14156,234.59825 c 2.0597,0 3.75842,1.67749 3.75842,3.75842 l 0,1.76243 c 0,2.0597 -1.69872,3.75842 -3.75842,3.75842 l -42.38314,0 c -2.0597,0 -3.75842,-1.69872 -3.75842,-3.75842 l 0,-1.76243 c 0,-2.0597 1.67749,-3.75842 3.75842,-3.75842 l 42.38314,0 m 0,-1.48638 -42.38314,0 c -2.88783,0 -5.2448,2.33574 -5.2448,5.22357 l 0,1.76242 c 0,2.88783 2.35697,5.24481 5.2448,5.24481 l 42.40437,0 c 2.88783,0 5.24481,-2.35698 5.24481,-5.24481 l 0,-1.76242 c -0.0212,-2.88783 -2.37821,-5.22357 -5.26604,-5.22357 l 0,0 z"
id="path41"
inkscape:connector-curvature="0"
style="display:none;fill:#ffffff" /><rect
style="display:none;fill:#95d220"
id="rect47"
height="9.279274"
width="9.279274"
class="st4"
y="214.00124"
x="250.61948" /><path
class="st2"
d="m 266.14156,214.00123 c 2.0597,0 3.75842,1.67749 3.75842,3.75843 l 0,1.76242 c 0,2.05971 -1.69872,3.75843 -3.75842,3.75843 l -42.38314,0 C 221.67749,223.25927 220,221.58179 220,219.52208 l 0,-1.76242 c 0,-2.0597 1.67749,-3.75843 3.75842,-3.75843 l 42.38314,0 m 0,-1.48638 -42.38314,0 c -2.88783,0 -5.2448,2.33575 -5.2448,5.22357 l 0,1.76243 c 0,2.88783 2.35697,5.24481 5.2448,5.24481 l 42.40437,0 c 2.88783,0 5.24481,-2.35698 5.24481,-5.24481 l 0,-1.76243 c -0.0212,-2.88782 -2.37821,-5.22357 -5.26604,-5.22357 l 0,0 z"
id="path53"
inkscape:connector-curvature="0"
style="display:none;fill:#ffffff" /><path
style="fill:#ffffff"
d="m 57.097656,30.69922 0,19.30078 9.06836,0 c 4.22557,0 6.474893,-2.12355 6.496093,-5.47852 0,-2.14464 -1.017672,-3.78004 -3.013671,-4.67187 l 0,-0.041 c 1.507609,-0.9343 2.166015,-2.10331 2.166015,-3.9082 0,-2.73919 -1.848098,-5.20117 -5.861328,-5.20117 l -8.855469,0 z m 18.75,0 0,19.30078 2.271485,0 0,-7.72852 -0.232422,-0.23437 4.585937,0 c 2.54808,0 4.012966,0.91391 4.947266,2.88867 L 89.820312,50 92.367188,50 89.4375,43.96875 c -0.63702,-1.35898 -1.614284,-2.20763 -2.527344,-2.58984 l 0,-0.043 c 2.1234,-0.55208 3.865235,-2.42042 3.865235,-4.94727 0,-3.80089 -2.951713,-5.68945 -6.476563,-5.68945 l -8.451172,0 z m 18.876953,0 0,19.30078 2.273438,0 0,-19.30078 -2.273438,0 z m 13.419921,0 L 99.650391,50 l 2.484379,0 2.03906,-4.65039 -0.12695,-0.23438 10.57421,0 -0.12695,0.23438 2.03906,4.65039 2.48438,0 -8.47266,-19.30078 -2.40039,0 z m 13.33594,0 0,19.30078 2.27148,0 0,-7.72852 -0.23437,-0.23437 4.58789,0 c 2.54808,0 4.01296,0.91391 4.94726,2.88867 L 135.45117,50 138,50 135.07031,43.96875 c -0.63702,-1.35898 -1.61427,-2.20763 -2.52734,-2.58984 l 0,-0.043 c 2.12341,-0.55208 3.86523,-2.42042 3.86523,-4.94727 0,-3.80089 -2.95171,-5.68945 -6.47656,-5.68945 l -8.45117,0 z m -62.322267,2.14453 6.560547,0 c 2.46315,0 3.759766,0.9967 3.759766,3.03516 0,1.71996 -0.999336,3.10156 -3.759766,3.10156 l -6.560547,0 0.234375,-0.23438 0,-5.66992 -0.234375,-0.23242 z m 18.728516,0 6.433593,0 c 2.378211,0 4.14091,0.97535 4.16211,3.52344 0,2.03846 -1.634356,3.5039 -4.416016,3.5039 l -6.179687,0 0.232422,-0.23242 0,-6.5625 -0.232422,-0.23242 z m 45.652341,0 6.4336,0 c 2.35698,0 4.14062,0.97535 4.14062,3.52344 0,2.03846 -1.61288,3.5039 -4.39453,3.5039 l -6.17969,0 0.23438,-0.23242 0,-6.5625 -0.23438,-0.23242 z m -14.20508,0.21094 0.043,0 0.57227,1.93359 3.39844,7.75 0.23242,0.23242 -8.4707,0 0.23242,-0.23242 3.39843,-7.75 0.59375,-1.93359 z m -50.197261,8.07031 7.007812,0 c 2.84536,0 4.16211,1.3153 4.16211,3.375 0,2.14464 -1.189095,3.33398 -4.140625,3.33398 l -7.029297,0 0.234375,-0.23437 0,-6.24219 -0.234375,-0.23242 z"
id="path57"

Before

Width:  |  Height:  |  Size: 5.5 KiB

After

Width:  |  Height:  |  Size: 8.7 KiB

View File

@@ -1,70 +0,0 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Generator: Adobe Illustrator 19.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
version="1.1"
id="Ebene_1"
x="0px"
y="0px"
xml:space="preserve"
inkscape:version="0.92.3 (2405546, 2018-03-11)"
sodipodi:docname="navigation_drawer_header.svg"
width="146"
height="50"><metadata
id="metadata71"><rdf:RDF><cc:Work
rdf:about=""><dc:format>image/svg+xml</dc:format><dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" /><dc:title></dc:title></cc:Work></rdf:RDF></metadata><defs
id="defs69" /><sodipodi:namedview
pagecolor="#000000"
bordercolor="#666666"
borderopacity="1"
objecttolerance="10"
gridtolerance="10"
guidetolerance="10"
inkscape:pageopacity="0"
inkscape:pageshadow="2"
inkscape:window-width="1920"
inkscape:window-height="1020"
id="namedview67"
showgrid="false"
fit-margin-top="0"
fit-margin-left="0"
fit-margin-right="0"
fit-margin-bottom="0"
inkscape:zoom="3.9883057"
inkscape:cx="55.084459"
inkscape:cy="13.664636"
inkscape:window-x="1442"
inkscape:window-y="24"
inkscape:window-maximized="0"
inkscape:current-layer="Ebene_1"
showguides="true"
inkscape:guide-bbox="true" /><style
type="text/css"
id="style3">
.st0{display:none;fill:#87C214;}
.st1{fill:#87C214;}
.st2{display:none;fill:#FFFFFF;}
.st3{fill:#95D220;}
.st4{display:none;fill:#95D220;}
.st5{fill:#FFFFFF;}
</style><path
style="fill:#ffffff;fill-opacity:1"
d="m 65.097656,30.699216 v 19.30078 h 9.06836 c 4.22557,0 6.474893,-2.12355 6.496093,-5.47852 0,-2.14464 -1.017672,-3.78004 -3.013671,-4.67187 v -0.041 c 1.507609,-0.9343 2.166015,-2.10331 2.166015,-3.9082 0,-2.73919 -1.848098,-5.20117 -5.861328,-5.20117 h -8.855469 z m 18.75,0 v 19.30078 h 2.271485 v -7.72852 l -0.232422,-0.23437 h 4.585937 c 2.54808,0 4.012966,0.91391 4.947266,2.88867 l 2.40039,5.07422 h 2.546878 l -2.92969,-6.03125 c -0.63702,-1.35898 -1.614284,-2.20763 -2.527344,-2.58984 v -0.043 c 2.1234,-0.55208 3.865235,-2.42042 3.865235,-4.94727 0,-3.80089 -2.951713,-5.68945 -6.476563,-5.68945 h -8.451172 z m 18.876954,0 v 19.30078 h 2.27344 v -19.30078 z m 13.41992,0 -8.49414,19.30078 h 2.48438 l 2.03906,-4.65039 -0.12695,-0.23438 h 10.57421 l -0.12695,0.23438 2.03906,4.65039 h 2.48438 l -8.47266,-19.30078 z m 13.33594,0 v 19.30078 h 2.27148 v -7.72852 l -0.23437,-0.23437 h 4.58789 c 2.54808,0 4.01296,0.91391 4.94726,2.88867 l 2.39844,5.07422 H 146 l -2.92969,-6.03125 c -0.63702,-1.35898 -1.61427,-2.20763 -2.52734,-2.58984 v -0.043 c 2.12341,-0.55208 3.86523,-2.42042 3.86523,-4.94727 0,-3.80089 -2.95171,-5.68945 -6.47656,-5.68945 h -8.45117 z m -62.322267,2.14453 h 6.560547 c 2.46315,0 3.759766,0.9967 3.759766,3.03516 0,1.71996 -0.999336,3.10156 -3.759766,3.10156 h -6.560547 l 0.234375,-0.23438 v -5.66992 z m 18.728516,0 h 6.433593 c 2.378211,0 4.14091,0.97535 4.16211,3.52344 0,2.03846 -1.634356,3.5039 -4.416016,3.5039 h -6.179687 l 0.232422,-0.23242 v -6.5625 z m 45.652341,0 h 6.4336 c 2.35698,0 4.14062,0.97535 4.14062,3.52344 0,2.03846 -1.61288,3.5039 -4.39453,3.5039 h -6.17969 l 0.23438,-0.23242 v -6.5625 z m -14.20508,0.21094 h 0.043 l 0.57227,1.93359 3.39844,7.75 0.23242,0.23242 h -8.4707 l 0.23242,-0.23242 3.39843,-7.75 0.59375,-1.93359 z m -50.197261,8.07031 h 7.007812 c 2.84536,0 4.16211,1.3153 4.16211,3.375 0,2.14464 -1.189095,3.33398 -4.140625,3.33398 h -7.029297 l 0.234375,-0.23437 v -6.24219 z"
id="path57"
inkscape:connector-curvature="0" /><path
inkscape:connector-curvature="0"
style="fill:#87c214;stroke-width:0.21276595"
d="m 13.808594,0 c -2.06383,0 -3.766207,1.7019614 -3.766207,3.7657911 V 8.553025 h 9.276928 V 3.7657911 C 19.319315,1.7019614 17.638132,0 15.574302,0 Z m 20.638297,0 c -2.06383,0 -3.766206,1.7019614 -3.766206,3.7657911 V 29.191323 h 9.276927 V 3.7657911 C 39.957612,1.7019614 38.276429,0 36.212599,0 Z M 10.042387,20.808676 v 25.425531 c 0,2.06383 1.681101,3.765791 3.766207,3.765791 h 1.765708 c 2.06383,0 3.766207,-1.701961 3.766207,-3.765791 V 20.808676 Z m 20.638298,20.638297 v 4.787234 c 0,2.06383 1.702376,3.765791 3.766206,3.765791 h 1.765708 c 2.06383,0 3.766206,-1.701961 3.766206,-3.765791 v -4.787234 z"
id="path13-3" /><path
inkscape:connector-curvature="0"
style="fill:#95d220;stroke-width:0.21276595"
d="M 3.7657914,10.042387 C 1.7019617,10.042387 0,11.723487 0,13.808594 v 1.765708 c 0,2.063829 1.6806851,3.766206 3.7657914,3.766206 H 29.191323 v -9.298121 z m 37.6811826,0 v 9.298121 h 4.787233 c 2.06383,0 3.765792,-1.6811 3.765792,-3.766206 v -1.765708 c 0,-2.085107 -1.701962,-3.766207 -3.765792,-3.766207 z M 3.7657914,30.680684 C 1.7019617,30.680684 0,32.361784 0,34.44689 v 1.765709 c 0,2.06383 1.6806851,3.766206 3.7657914,3.766206 h 4.7872339 v -9.298121 z m 17.0428856,0 v 9.298121 h 25.42553 c 2.06383,0 3.765792,-1.702376 3.765792,-3.766206 V 34.44689 c 0,-2.085106 -1.701962,-3.766206 -3.765792,-3.766206 z"
id="path35" /></svg>

Before

Width:  |  Height:  |  Size: 5.3 KiB

View File

@@ -1,70 +0,0 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Generator: Adobe Illustrator 19.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
version="1.1"
id="Ebene_1"
x="0px"
y="0px"
xml:space="preserve"
inkscape:version="0.92.3 (2405546, 2018-03-11)"
sodipodi:docname="navigation_drawer_header_night.svg"
width="146"
height="50"><metadata
id="metadata71"><rdf:RDF><cc:Work
rdf:about=""><dc:format>image/svg+xml</dc:format><dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" /><dc:title></dc:title></cc:Work></rdf:RDF></metadata><defs
id="defs69" /><sodipodi:namedview
pagecolor="#000000"
bordercolor="#666666"
borderopacity="1"
objecttolerance="10"
gridtolerance="10"
guidetolerance="10"
inkscape:pageopacity="0"
inkscape:pageshadow="2"
inkscape:window-width="1920"
inkscape:window-height="1020"
id="namedview67"
showgrid="false"
fit-margin-top="0"
fit-margin-left="0"
fit-margin-right="0"
fit-margin-bottom="0"
inkscape:zoom="3.9883057"
inkscape:cx="110.49646"
inkscape:cy="13.664636"
inkscape:window-x="1442"
inkscape:window-y="24"
inkscape:window-maximized="0"
inkscape:current-layer="Ebene_1"
showguides="true"
inkscape:guide-bbox="true" /><style
type="text/css"
id="style3">
.st0{display:none;fill:#87C214;}
.st1{fill:#87C214;}
.st2{display:none;fill:#FFFFFF;}
.st3{fill:#95D220;}
.st4{display:none;fill:#95D220;}
.st5{fill:#FFFFFF;}
</style><path
style="fill:#95d220;fill-opacity:1"
d="m 65.097656,15.349623 v 19.30078 h 9.06836 c 4.22557,0 6.474893,-2.12355 6.496093,-5.47852 0,-2.14464 -1.017672,-3.78004 -3.013671,-4.67187 v -0.041 c 1.507609,-0.9343 2.166015,-2.10331 2.166015,-3.9082 0,-2.73919 -1.848098,-5.20117 -5.861328,-5.20117 h -8.855469 z m 18.75,0 v 19.30078 h 2.271485 v -7.72852 l -0.232422,-0.23437 h 4.585937 c 2.54808,0 4.012966,0.91391 4.947266,2.88867 l 2.40039,5.07422 h 2.546878 l -2.92969,-6.03125 c -0.63702,-1.35898 -1.614284,-2.20763 -2.527344,-2.58984 v -0.043 c 2.1234,-0.55208 3.865235,-2.42042 3.865235,-4.94727 0,-3.80089 -2.951713,-5.68945 -6.476563,-5.68945 h -8.451172 z m 18.876954,0 v 19.30078 h 2.27344 v -19.30078 z m 13.41992,0 -8.49414,19.30078 h 2.48438 l 2.03906,-4.65039 -0.12695,-0.23438 h 10.57421 l -0.12695,0.23438 2.03906,4.65039 h 2.48438 l -8.47266,-19.30078 z m 13.33594,0 v 19.30078 h 2.27148 v -7.72852 l -0.23437,-0.23437 h 4.58789 c 2.54808,0 4.01296,0.91391 4.94726,2.88867 l 2.39844,5.07422 H 146 l -2.92969,-6.03125 c -0.63702,-1.35898 -1.61427,-2.20763 -2.52734,-2.58984 v -0.043 c 2.12341,-0.55208 3.86523,-2.42042 3.86523,-4.94727 0,-3.80089 -2.95171,-5.68945 -6.47656,-5.68945 h -8.45117 z m -62.322267,2.14453 h 6.560547 c 2.46315,0 3.759766,0.9967 3.759766,3.03516 0,1.71996 -0.999336,3.10156 -3.759766,3.10156 h -6.560547 l 0.234375,-0.23438 v -5.66992 z m 18.728516,0 h 6.433593 c 2.378211,0 4.14091,0.97535 4.16211,3.52344 0,2.03846 -1.634356,3.5039 -4.416016,3.5039 h -6.179687 l 0.232422,-0.23242 v -6.5625 z m 45.652341,0 h 6.4336 c 2.35698,0 4.14062,0.97535 4.14062,3.52344 0,2.03846 -1.61288,3.5039 -4.39453,3.5039 h -6.17969 l 0.23438,-0.23242 v -6.5625 z m -14.20508,0.21094 h 0.043 l 0.57227,1.93359 3.39844,7.75 0.23242,0.23242 h -8.4707 l 0.23242,-0.23242 3.39843,-7.75 0.59375,-1.93359 z m -50.197261,8.07031 h 7.007812 c 2.84536,0 4.16211,1.3153 4.16211,3.375 0,2.14464 -1.189095,3.33398 -4.140625,3.33398 h -7.029297 l 0.234375,-0.23437 v -6.24219 z"
id="path57"
inkscape:connector-curvature="0" /><path
inkscape:connector-curvature="0"
style="fill:#87c214;stroke-width:0.21276595"
d="m 13.808594,0 c -2.06383,0 -3.766207,1.7019614 -3.766207,3.7657911 V 8.553025 h 9.276928 V 3.7657911 C 19.319315,1.7019614 17.638132,0 15.574302,0 Z m 20.638297,0 c -2.06383,0 -3.766206,1.7019614 -3.766206,3.7657911 V 29.191323 h 9.276927 V 3.7657911 C 39.957612,1.7019614 38.276429,0 36.212599,0 Z M 10.042387,20.808676 v 25.425531 c 0,2.06383 1.681101,3.765791 3.766207,3.765791 h 1.765708 c 2.06383,0 3.766207,-1.701961 3.766207,-3.765791 V 20.808676 Z m 20.638298,20.638297 v 4.787234 c 0,2.06383 1.702376,3.765791 3.766206,3.765791 h 1.765708 c 2.06383,0 3.766206,-1.701961 3.766206,-3.765791 v -4.787234 z"
id="path13-3" /><path
inkscape:connector-curvature="0"
style="fill:#95d220;stroke-width:0.21276595"
d="M 3.7657914,10.042387 C 1.7019617,10.042387 0,11.723487 0,13.808594 v 1.765708 c 0,2.063829 1.6806851,3.766206 3.7657914,3.766206 H 29.191323 v -9.298121 z m 37.6811826,0 v 9.298121 h 4.787233 c 2.06383,0 3.765792,-1.6811 3.765792,-3.766206 v -1.765708 c 0,-2.085107 -1.701962,-3.766207 -3.765792,-3.766207 z M 3.7657914,30.680684 C 1.7019617,30.680684 0,32.361784 0,34.44689 v 1.765709 c 0,2.06383 1.6806851,3.766206 3.7657914,3.766206 h 4.7872339 v -9.298121 z m 17.0428856,0 v 9.298121 h 25.42553 c 2.06383,0 3.765792,-1.702376 3.765792,-3.766206 V 34.44689 c 0,-2.085106 -1.701962,-3.766206 -3.765792,-3.766206 z"
id="path35" /></svg>

Before

Width:  |  Height:  |  Size: 5.3 KiB

View File

@@ -0,0 +1,57 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Generator: Adobe Illustrator 19.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
version="1.1"
id="Ebene_1"
x="0px"
y="0px"
viewBox="0 0 24 24"
xml:space="preserve"
inkscape:version="0.92.3 (2405546, 2018-03-11)"
sodipodi:docname="notification_reminder.svg"
width="24"
height="24"><metadata
id="metadata61"><rdf:RDF><cc:Work
rdf:about=""><dc:format>image/svg+xml</dc:format><dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" /><dc:title /></cc:Work></rdf:RDF></metadata><defs
id="defs59" /><sodipodi:namedview
pagecolor="#000000"
bordercolor="#666666"
borderopacity="1"
objecttolerance="10"
gridtolerance="10"
guidetolerance="10"
inkscape:pageopacity="0"
inkscape:pageshadow="2"
inkscape:window-width="1920"
inkscape:window-height="1020"
id="namedview57"
showgrid="false"
inkscape:zoom="32.43286"
inkscape:cx="6.4172501"
inkscape:cy="12.231457"
inkscape:window-x="1442"
inkscape:window-y="24"
inkscape:window-maximized="0"
inkscape:current-layer="Ebene_1"
units="px" /><style
type="text/css"
id="style3">
.st0{fill:#FFFFFF;}
.st1{display:none;fill:#87C214;}
.st2{fill:#87C214;}
.st3{display:none;fill:#FFFFFF;}
.st4{fill:#95D220;}
.st5{display:none;fill:#95D220;}
</style><path
style="display:inline;fill:#ffffff;stroke-width:0.07272727"
d="M 12 0 A 12 12 0 0 0 4.875 2.3613281 L 6.9316406 4.4160156 C 7.0875805 3.8805807 7.5639651 3.4765625 8.1464844 3.4765625 L 8.7480469 3.4765625 C 9.4535014 3.4765625 10.035156 4.0582174 10.035156 4.7636719 L 10.035156 6.4003906 L 8.9140625 6.4003906 L 9.4238281 6.9101562 L 13.404297 6.9101562 L 13.404297 10.085938 L 12.601562 10.085938 L 13.914062 11.398438 L 13.914062 4.7636719 C 13.914062 4.0582174 14.495717 3.4765625 15.201172 3.4765625 L 15.802734 3.4765625 C 16.515461 3.4765625 17.089844 4.0582174 17.089844 4.7636719 L 17.089844 13.455078 L 15.96875 13.455078 L 16.478516 13.964844 L 19.236328 13.964844 C 19.941782 13.964844 20.516165 14.546498 20.523438 15.251953 L 20.523438 15.853516 C 20.523438 16.436036 20.119418 16.91242 19.583984 17.068359 L 21.638672 19.125 A 12 12 0 0 0 24 12 A 12 12 0 0 0 12 0 z M 1.2617188 1.3632812 L 0 2.6269531 L 2.3125 4.9472656 A 12 12 0 0 0 0 12 A 12 12 0 0 0 12 24 A 12 12 0 0 0 19.027344 21.707031 L 21.314453 24 L 22.576172 22.734375 L 2.7519531 2.8554688 L 1.9863281 2.0898438 L 1.2617188 1.3632812 z M 17.599609 6.9101562 L 19.236328 6.9101562 C 19.941782 6.9101562 20.516165 7.4918111 20.523438 8.1972656 L 20.523438 8.7988281 C 20.523438 9.511555 19.941782 10.085937 19.236328 10.085938 L 17.599609 10.085938 L 17.599609 6.9101562 z M 4.359375 6.9980469 L 7.4394531 10.085938 L 4.7128906 10.085938 C 4.0001632 10.085938 3.4257813 9.504282 3.4257812 8.7988281 L 3.4257812 8.1972656 C 3.4257812 7.6133228 3.8294199 7.1540656 4.359375 6.9980469 z M 6.859375 10.595703 L 7.9472656 10.595703 L 10.035156 12.689453 L 10.035156 19.287109 C 10.035156 19.992562 9.4535014 20.574219 8.7480469 20.574219 L 8.1464844 20.574219 C 7.4337573 20.574219 6.859375 19.992563 6.859375 19.287109 L 6.859375 10.595703 z M 4.7128906 13.964844 L 6.3496094 13.964844 L 6.3496094 17.140625 L 4.7128906 17.140625 C 4.0001632 17.140625 3.4257813 16.558971 3.4257812 15.853516 L 3.4257812 15.251953 C 3.4257812 14.539226 4.007436 13.964844 4.7128906 13.964844 z M 10.544922 13.964844 L 11.306641 13.964844 L 14.474609 17.140625 L 10.544922 17.140625 L 10.544922 13.964844 z M 13.914062 17.650391 L 14.982422 17.650391 L 16.992188 19.666016 C 16.827053 20.182975 16.371277 20.574219 15.802734 20.574219 L 15.201172 20.574219 C 14.495717 20.574219 13.914063 19.992563 13.914062 19.287109 L 13.914062 17.650391 z "
id="circle7" /></svg>

After

Width:  |  Height:  |  Size: 4.1 KiB

View File

@@ -238,8 +238,8 @@ android {
defaultConfig {
minSdkVersion 14
targetSdkVersion 26
versionCode 10012
versionName "1.0.12"
versionCode 10011
versionName "1.0.11"
applicationId "org.briarproject.briar.android"
resValue "string", "app_package", "org.briarproject.briar.android"
resValue "string", "app_name", "Briar"

View File

@@ -3,9 +3,8 @@
package="org.briarproject.briar"
xmlns:android="http://schemas.android.com/apk/res/android">
<uses-feature android:name="android.hardware.bluetooth" android:required="false"/>
<uses-feature android:name="android.hardware.bluetooth"/>
<uses-feature android:name="android.hardware.camera" />
<uses-feature android:name="android.hardware.touchscreen" android:required="false" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
@@ -71,7 +70,7 @@
</activity>
<activity
android:name="org.briarproject.briar.android.login.SetupActivity"
android:name="org.briarproject.briar.android.account.SetupActivity"
android:label="@string/setup_title"
android:windowSoftInputMode="adjustResize">
</activity>

View File

@@ -5,6 +5,7 @@ import android.content.SharedPreferences;
import org.briarproject.bramble.BrambleAndroidModule;
import org.briarproject.bramble.BrambleCoreEagerSingletons;
import org.briarproject.bramble.BrambleCoreModule;
import org.briarproject.bramble.api.account.AccountManager;
import org.briarproject.bramble.api.contact.ContactExchangeTask;
import org.briarproject.bramble.api.contact.ContactManager;
import org.briarproject.bramble.api.crypto.CryptoComponent;
@@ -77,6 +78,8 @@ public interface AndroidComponent
DatabaseConfig databaseConfig();
AccountManager accountManager();
@DatabaseExecutor
Executor databaseExecutor();

View File

@@ -21,8 +21,6 @@ class AndroidDatabaseConfig implements DatabaseConfig {
@Nullable
private volatile SecretKey key = null;
@Nullable
private volatile String nickname = null;
AndroidDatabaseConfig(File dbDir, File keyDir) {
this.dbDir = dbDir;
@@ -70,21 +68,6 @@ class AndroidDatabaseConfig implements DatabaseConfig {
this.key = key;
}
@Override
public void setLocalAuthorName(String nickname) {
LOG.info("Setting local author name");
this.nickname = nickname;
}
@Override
@Nullable
public String getLocalAuthorName() {
String nickname = this.nickname;
if (LOG.isLoggable(INFO))
LOG.info("Local author name has been set: " + (nickname != null));
return nickname;
}
@Override
@Nullable
public SecretKey getEncryptionKey() {

View File

@@ -5,6 +5,7 @@ import android.content.Context;
import android.content.SharedPreferences;
import android.os.StrictMode;
import org.briarproject.bramble.api.account.AccountManager;
import org.briarproject.bramble.api.crypto.CryptoComponent;
import org.briarproject.bramble.api.crypto.PublicKey;
import org.briarproject.bramble.api.db.DatabaseConfig;
@@ -29,8 +30,10 @@ import org.briarproject.bramble.plugin.tor.CircumventionProvider;
import org.briarproject.bramble.plugin.tor.TorPluginFactory;
import org.briarproject.bramble.util.AndroidUtils;
import org.briarproject.bramble.util.StringUtils;
import org.briarproject.briar.android.account.AndroidAccountManagerImpl;
import org.briarproject.briar.api.android.AndroidNotificationManager;
import org.briarproject.briar.api.android.DozeWatchdog;
import org.briarproject.briar.api.android.ReferenceManager;
import org.briarproject.briar.api.android.ScreenFilterMonitor;
import java.io.File;
@@ -93,6 +96,13 @@ public class AppModule {
return databaseConfig;
}
@Provides
@Singleton
AccountManager provideAccountManager(
AndroidAccountManagerImpl androidAccountManager) {
return androidAccountManager;
}
@Provides
PluginConfig providePluginConfig(@IoExecutor Executor ioExecutor,
@Scheduler ScheduledExecutorService scheduler,
@@ -166,6 +176,12 @@ public class AppModule {
return app.getSharedPreferences("db", MODE_PRIVATE);
}
@Provides
@Singleton
ReferenceManager provideReferenceManager() {
return new ReferenceManagerImpl();
}
@Provides
@Singleton
AndroidNotificationManager provideAndroidNotificationManager(

View File

@@ -1,5 +1,6 @@
package org.briarproject.briar.android;
import android.content.Context;
import android.content.SharedPreferences;
import java.util.Collection;
@@ -15,5 +16,7 @@ public interface BriarApplication {
AndroidComponent getApplicationComponent();
Context getApplicationContext();
SharedPreferences getDefaultSharedPreferences();
}

View File

@@ -17,7 +17,8 @@ import android.os.IBinder;
import android.support.v4.app.NotificationCompat;
import android.support.v4.content.ContextCompat;
import org.briarproject.bramble.api.db.DatabaseConfig;
import org.briarproject.bramble.api.account.AccountManager;
import org.briarproject.bramble.api.account.AccountState;
import org.briarproject.bramble.api.lifecycle.LifecycleManager;
import org.briarproject.bramble.api.lifecycle.LifecycleManager.StartResult;
import org.briarproject.bramble.api.system.AndroidExecutor;
@@ -48,12 +49,15 @@ import static android.support.v4.app.NotificationCompat.PRIORITY_MIN;
import static android.support.v4.app.NotificationCompat.VISIBILITY_SECRET;
import static java.util.logging.Level.INFO;
import static java.util.logging.Level.WARNING;
import static org.briarproject.bramble.api.account.AccountState.CREATING_ACCOUNT;
import static org.briarproject.bramble.api.account.AccountState.SIGNED_IN;
import static org.briarproject.bramble.api.lifecycle.LifecycleManager.StartResult.ALREADY_RUNNING;
import static org.briarproject.bramble.api.lifecycle.LifecycleManager.StartResult.SUCCESS;
import static org.briarproject.briar.api.android.AndroidNotificationManager.FAILURE_CHANNEL_ID;
import static org.briarproject.briar.api.android.AndroidNotificationManager.FAILURE_NOTIFICATION_ID;
import static org.briarproject.briar.api.android.AndroidNotificationManager.ONGOING_CHANNEL_ID;
import static org.briarproject.briar.api.android.AndroidNotificationManager.ONGOING_NOTIFICATION_ID;
import static org.briarproject.briar.api.android.AndroidNotificationManager.REMINDER_NOTIFICATION_ID;
public class BriarService extends Service {
@@ -74,7 +78,7 @@ public class BriarService extends Service {
private BroadcastReceiver receiver = null;
@Inject
protected DatabaseConfig databaseConfig;
protected AccountManager accountManager;
// Fields that are accessed from background threads must be volatile
@Inject
protected volatile LifecycleManager lifecycleManager;
@@ -95,16 +99,17 @@ public class BriarService extends Service {
stopSelf();
return;
}
if (databaseConfig.getEncryptionKey() == null) {
AccountState accountState = accountManager.getAccountState();
if (accountState != SIGNED_IN && accountState != CREATING_ACCOUNT) {
LOG.info("No database key");
stopSelf();
return;
}
// Create notification channels
NotificationManager nm = (NotificationManager)
getSystemService(NOTIFICATION_SERVICE);
if (SDK_INT >= 26) {
NotificationManager nm = (NotificationManager)
getSystemService(NOTIFICATION_SERVICE);
NotificationChannel ongoingChannel = new NotificationChannel(
ONGOING_CHANNEL_ID,
getString(R.string.ongoing_notification_title),
@@ -136,9 +141,11 @@ public class BriarService extends Service {
}
b.setPriority(PRIORITY_MIN);
startForeground(ONGOING_NOTIFICATION_ID, b.build());
// Remove sign-in reminder notification
nm.cancel(REMINDER_NOTIFICATION_ID);
// Start the services in a background thread
new Thread(() -> {
String nickname = databaseConfig.getLocalAuthorName();
String nickname = accountManager.getCreatedLocalAuthorName();
StartResult result = lifecycleManager.startServices(nickname);
if (result == SUCCESS) {
started = true;

View File

@@ -0,0 +1,83 @@
package org.briarproject.briar.android;
import org.briarproject.briar.api.android.ReferenceManager;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
import java.util.logging.Logger;
import static java.util.logging.Level.INFO;
class ReferenceManagerImpl implements ReferenceManager {
private static final Logger LOG =
Logger.getLogger(ReferenceManagerImpl.class.getName());
private final Lock lock = new ReentrantLock();
// The following are locking: lock
private final Map<Class<?>, Map<Long, Object>> outerMap = new HashMap<>();
private long nextHandle = 0;
@Override
public <T> T getReference(long handle, Class<T> c) {
lock.lock();
try {
Map<Long, Object> innerMap = outerMap.get(c);
if (innerMap == null) {
if (LOG.isLoggable(INFO))
LOG.info("0 handles for " + c.getName());
return null;
}
if (LOG.isLoggable(INFO))
LOG.info(innerMap.size() + " handles for " + c.getName());
Object o = innerMap.get(handle);
return c.cast(o);
} finally {
lock.unlock();
}
}
@Override
public <T> long putReference(T reference, Class<T> c) {
lock.lock();
try {
Map<Long, Object> innerMap = outerMap.get(c);
if (innerMap == null) {
innerMap = new HashMap<>();
outerMap.put(c, innerMap);
}
long handle = nextHandle++;
innerMap.put(handle, reference);
if (LOG.isLoggable(INFO)) {
LOG.info(innerMap.size() + " handles for " + c.getName() +
" after put");
}
return handle;
} finally {
lock.unlock();
}
}
@Override
public <T> T removeReference(long handle, Class<T> c) {
lock.lock();
try {
Map<Long, Object> innerMap = outerMap.get(c);
if (innerMap == null) return null;
Object o = innerMap.remove(handle);
if (innerMap.isEmpty()) outerMap.remove(c);
if (LOG.isLoggable(INFO)) {
LOG.info(innerMap.size() + " handles for " + c.getName() +
" after remove");
}
return c.cast(o);
} finally {
lock.unlock();
}
}
}

View File

@@ -1,12 +1,13 @@
package org.briarproject.briar.android.controller;
package org.briarproject.briar.android.account;
import android.content.Context;
import android.app.Application;
import android.content.SharedPreferences;
import android.support.v7.preference.PreferenceManager;
import org.briarproject.bramble.account.AccountManagerImpl;
import org.briarproject.bramble.api.crypto.CryptoComponent;
import org.briarproject.bramble.api.db.DatabaseConfig;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import org.briarproject.bramble.util.AndroidUtils;
import org.briarproject.briar.android.BriarApplication;
import java.io.BufferedReader;
import java.io.File;
@@ -20,27 +21,30 @@ import javax.annotation.Nullable;
import javax.inject.Inject;
import static java.util.logging.Level.WARNING;
import static org.briarproject.bramble.util.AndroidUtils.deleteAppData;
import static org.briarproject.bramble.util.LogUtils.logException;
@NotNullByDefault
public class ConfigControllerImpl implements ConfigController {
public class AndroidAccountManagerImpl extends AccountManagerImpl {
private static final Logger LOG =
Logger.getLogger(ConfigControllerImpl.class.getName());
private final static Logger LOG =
Logger.getLogger(AndroidAccountManagerImpl.class.getSimpleName());
private static final String PREF_DB_KEY = "key";
private static final String DB_KEY_FILENAME = "db.key";
private static final String DB_KEY_BACKUP_FILENAME = "db.key.bak";
private final SharedPreferences briarPrefs;
private final BriarApplication app;
private final SharedPreferences dbPrefs;
private final File dbKeyFile, dbKeyBackupFile;
protected final DatabaseConfig databaseConfig;
@Inject
public ConfigControllerImpl(SharedPreferences briarPrefs,
DatabaseConfig databaseConfig) {
this.briarPrefs = briarPrefs;
this.databaseConfig = databaseConfig;
public AndroidAccountManagerImpl(CryptoComponent crypto,
DatabaseConfig databaseConfig, Application app,
SharedPreferences dbPrefs) {
super(crypto, databaseConfig);
this.app = (BriarApplication) app;
this.dbPrefs = dbPrefs;
File keyDir = databaseConfig.getDatabaseKeyDirectory();
dbKeyFile = new File(keyDir, DB_KEY_FILENAME);
dbKeyBackupFile = new File(keyDir, DB_KEY_BACKUP_FILENAME);
@@ -48,7 +52,7 @@ public class ConfigControllerImpl implements ConfigController {
@Override
@Nullable
public String getEncryptedDatabaseKey() {
protected String getEncryptedDatabaseKey() {
String key = getDatabaseKeyFromPreferences();
if (key == null) key = getDatabaseKeyFromFile();
else migrateDatabaseKeyToFile(key);
@@ -57,7 +61,7 @@ public class ConfigControllerImpl implements ConfigController {
@Nullable
private String getDatabaseKeyFromPreferences() {
String key = briarPrefs.getString(PREF_DB_KEY, null);
String key = dbPrefs.getString(PREF_DB_KEY, null);
if (key == null) LOG.info("No database key in preferences");
else LOG.info("Found database key in preferences");
return key;
@@ -97,7 +101,7 @@ public class ConfigControllerImpl implements ConfigController {
private void migrateDatabaseKeyToFile(String key) {
if (storeEncryptedDatabaseKey(key)) {
if (briarPrefs.edit().remove(PREF_DB_KEY).commit())
if (dbPrefs.edit().remove(PREF_DB_KEY).commit())
LOG.info("Database key migrated to file");
else LOG.warning("Database key not removed from preferences");
} else {
@@ -106,7 +110,7 @@ public class ConfigControllerImpl implements ConfigController {
}
@Override
public boolean storeEncryptedDatabaseKey(String hex) {
protected boolean storeEncryptedDatabaseKey(String hex) {
LOG.info("Storing database key in file");
// Create the directory if necessary
if (databaseConfig.getDatabaseKeyDirectory().mkdirs())
@@ -151,21 +155,10 @@ public class ConfigControllerImpl implements ConfigController {
}
@Override
public void deleteAccount(Context ctx) {
public void deleteAccount() {
LOG.info("Deleting account");
SharedPreferences defaultPrefs =
PreferenceManager.getDefaultSharedPreferences(ctx);
AndroidUtils.deleteAppData(ctx, briarPrefs, defaultPrefs);
SharedPreferences defaultPrefs = app.getDefaultSharedPreferences();
deleteAppData(app.getApplicationContext(), dbPrefs, defaultPrefs);
}
@Override
public boolean accountExists() {
String hex = getEncryptedDatabaseKey();
return hex != null && databaseConfig.databaseExists();
}
@Override
public boolean accountSignedIn() {
return databaseConfig.getEncryptionKey() != null;
}
}

View File

@@ -1,4 +1,4 @@
package org.briarproject.briar.android.login;
package org.briarproject.briar.android.account;
import android.os.Bundle;
import android.support.design.widget.TextInputEditText;

View File

@@ -1,4 +1,4 @@
package org.briarproject.briar.android.login;
package org.briarproject.briar.android.account;
import android.annotation.SuppressLint;
import android.content.Intent;
@@ -13,8 +13,8 @@ import android.widget.ProgressBar;
import org.briarproject.bramble.api.nullsafety.MethodsNotNullByDefault;
import org.briarproject.bramble.api.nullsafety.ParametersNotNullByDefault;
import org.briarproject.briar.R;
import org.briarproject.briar.android.account.PowerView.OnCheckedChangedListener;
import org.briarproject.briar.android.activity.ActivityComponent;
import org.briarproject.briar.android.login.PowerView.OnCheckedChangedListener;
import org.briarproject.briar.android.util.UiUtils;
import static android.view.View.INVISIBLE;

View File

@@ -1,4 +1,4 @@
package org.briarproject.briar.android.login;
package org.briarproject.briar.android.account;
import android.content.Context;

View File

@@ -1,4 +1,4 @@
package org.briarproject.briar.android.login;
package org.briarproject.briar.android.account;
import android.content.Context;

View File

@@ -1,4 +1,4 @@
package org.briarproject.briar.android.login;
package org.briarproject.briar.android.account;
import android.os.Bundle;
import android.os.IBinder;
@@ -15,6 +15,7 @@ import org.briarproject.bramble.api.nullsafety.MethodsNotNullByDefault;
import org.briarproject.bramble.api.nullsafety.ParametersNotNullByDefault;
import org.briarproject.briar.R;
import org.briarproject.briar.android.activity.ActivityComponent;
import org.briarproject.briar.android.login.StrengthMeter;
import org.briarproject.briar.android.util.UiUtils;
import javax.annotation.Nullable;

View File

@@ -1,4 +1,4 @@
package org.briarproject.briar.android.login;
package org.briarproject.briar.android.account;
import android.content.Context;
import android.os.Parcel;

View File

@@ -1,4 +1,4 @@
package org.briarproject.briar.android.login;
package org.briarproject.briar.android.account;
import android.annotation.TargetApi;
import android.content.Intent;
@@ -10,6 +10,7 @@ import org.briarproject.briar.R;
import org.briarproject.briar.android.activity.ActivityComponent;
import org.briarproject.briar.android.activity.BaseActivity;
import org.briarproject.briar.android.fragment.BaseFragment.BaseFragmentListener;
import org.briarproject.briar.android.login.OpenDatabaseActivity;
import javax.annotation.Nullable;
import javax.inject.Inject;

View File

@@ -1,6 +1,7 @@
package org.briarproject.briar.android.login;
package org.briarproject.briar.android.account;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import org.briarproject.briar.android.login.PasswordController;
@NotNullByDefault
public interface SetupController extends PasswordController {

View File

@@ -1,16 +1,15 @@
package org.briarproject.briar.android.login;
package org.briarproject.briar.android.account;
import android.content.SharedPreferences;
import android.support.annotation.Nullable;
import org.briarproject.bramble.api.account.AccountManager;
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;
import org.briarproject.briar.android.controller.handler.ResultHandler;
import org.briarproject.briar.android.controller.handler.UiResultHandler;
import org.briarproject.briar.android.login.PasswordControllerImpl;
import java.util.concurrent.Executor;
import java.util.logging.Logger;
@@ -28,11 +27,10 @@ public class SetupControllerImpl extends PasswordControllerImpl
private volatile SetupActivity setupActivity;
@Inject
SetupControllerImpl(SharedPreferences briarPrefs,
DatabaseConfig databaseConfig,
SetupControllerImpl(AccountManager accountManager,
@CryptoExecutor Executor cryptoExecutor, CryptoComponent crypto,
PasswordStrengthEstimator strengthEstimator) {
super(briarPrefs, databaseConfig, cryptoExecutor, crypto,
super(accountManager, cryptoExecutor, crypto,
strengthEstimator);
}
@@ -102,11 +100,7 @@ public class SetupControllerImpl extends PasswordControllerImpl
if (password == null) throw new IllegalStateException();
cryptoExecutor.execute(() -> {
LOG.info("Creating account");
databaseConfig.setLocalAuthorName(authorName);
SecretKey key = crypto.generateSecretKey();
databaseConfig.setEncryptionKey(key);
String hex = encryptDatabaseKey(key, password);
storeEncryptedDatabaseKey(hex);
accountManager.createAccount(authorName, password);
resultHandler.onResult(null);
});
}

View File

@@ -1,4 +1,4 @@
package org.briarproject.briar.android.login;
package org.briarproject.briar.android.account;
import android.text.Editable;
import android.text.TextWatcher;
@@ -17,7 +17,7 @@ import javax.inject.Inject;
import static org.briarproject.briar.android.util.UiUtils.showOnboardingDialog;
abstract class SetupFragment extends BaseFragment implements TextWatcher,
public abstract class SetupFragment extends BaseFragment implements TextWatcher,
OnEditorActionListener, OnClickListener {
@Inject

View File

@@ -30,13 +30,13 @@ import org.briarproject.briar.android.keyagreement.ContactExchangeActivity;
import org.briarproject.briar.android.keyagreement.IntroFragment;
import org.briarproject.briar.android.keyagreement.KeyAgreementActivity;
import org.briarproject.briar.android.keyagreement.KeyAgreementFragment;
import org.briarproject.briar.android.login.AuthorNameFragment;
import org.briarproject.briar.android.account.AuthorNameFragment;
import org.briarproject.briar.android.login.ChangePasswordActivity;
import org.briarproject.briar.android.login.DozeFragment;
import org.briarproject.briar.android.account.DozeFragment;
import org.briarproject.briar.android.login.OpenDatabaseActivity;
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.account.PasswordFragment;
import org.briarproject.briar.android.account.SetupActivity;
import org.briarproject.briar.android.navdrawer.NavDrawerActivity;
import org.briarproject.briar.android.panic.PanicPreferencesActivity;
import org.briarproject.briar.android.panic.PanicResponderActivity;

View File

@@ -4,14 +4,12 @@ import android.app.Activity;
import org.briarproject.briar.android.controller.BriarController;
import org.briarproject.briar.android.controller.BriarControllerImpl;
import org.briarproject.briar.android.controller.ConfigController;
import org.briarproject.briar.android.controller.ConfigControllerImpl;
import org.briarproject.briar.android.controller.DbController;
import org.briarproject.briar.android.controller.DbControllerImpl;
import org.briarproject.briar.android.login.PasswordController;
import org.briarproject.briar.android.login.PasswordControllerImpl;
import org.briarproject.briar.android.login.SetupController;
import org.briarproject.briar.android.login.SetupControllerImpl;
import org.briarproject.briar.android.account.SetupController;
import org.briarproject.briar.android.account.SetupControllerImpl;
import org.briarproject.briar.android.navdrawer.NavDrawerController;
import org.briarproject.briar.android.navdrawer.NavDrawerControllerImpl;
@@ -48,13 +46,6 @@ public class ActivityModule {
return setupController;
}
@ActivityScope
@Provides
ConfigController provideConfigController(
ConfigControllerImpl configController) {
return configController;
}
@ActivityScope
@Provides
PasswordController providePasswordController(

View File

@@ -61,7 +61,7 @@ public abstract class BriarActivity extends BaseActivity {
@Override
public void onStart() {
super.onStart();
if (!briarController.hasEncryptionKey() && !isFinishing()) {
if (!briarController.signedIn() && !isFinishing()) {
Intent i = new Intent(this, PasswordActivity.class);
startActivityForResult(i, REQUEST_PASSWORD);
} else if (SDK_INT >= 23) {
@@ -138,7 +138,7 @@ public abstract class BriarActivity extends BaseActivity {
}
protected void signOut(boolean removeFromRecentApps) {
if (briarController.hasEncryptionKey()) {
if (briarController.signedIn()) {
// Don't use UiResultHandler because we want the result even if
// this activity has been destroyed
briarController.signOut(result -> runOnUiThread(

View File

@@ -6,7 +6,7 @@ public interface BriarController extends ActivityLifecycleController {
void startAndBindService();
boolean hasEncryptionKey();
boolean signedIn();
/**
* Returns true via the handler when the app has dozed

View File

@@ -5,7 +5,8 @@ import android.content.Intent;
import android.os.IBinder;
import android.support.annotation.CallSuper;
import org.briarproject.bramble.api.db.DatabaseConfig;
import org.briarproject.bramble.api.account.AccountManager;
import org.briarproject.bramble.api.account.AccountState;
import org.briarproject.bramble.api.db.DatabaseExecutor;
import org.briarproject.bramble.api.db.DbException;
import org.briarproject.bramble.api.settings.Settings;
@@ -21,6 +22,8 @@ import java.util.logging.Logger;
import javax.inject.Inject;
import static java.util.logging.Level.WARNING;
import static org.briarproject.bramble.api.account.AccountState.CREATING_ACCOUNT;
import static org.briarproject.bramble.api.account.AccountState.SIGNED_IN;
import static org.briarproject.bramble.util.LogUtils.logException;
import static org.briarproject.briar.android.settings.SettingsFragment.SETTINGS_NAMESPACE;
import static org.briarproject.briar.android.util.UiUtils.needsDozeWhitelisting;
@@ -33,7 +36,7 @@ public class BriarControllerImpl implements BriarController {
public static final String DOZE_ASK_AGAIN = "dozeAskAgain";
private final BriarServiceConnection serviceConnection;
private final DatabaseConfig databaseConfig;
private final AccountManager accountManager;
@DatabaseExecutor
private final Executor databaseExecutor;
private final SettingsManager settingsManager;
@@ -44,12 +47,12 @@ public class BriarControllerImpl implements BriarController {
@Inject
BriarControllerImpl(BriarServiceConnection serviceConnection,
DatabaseConfig databaseConfig,
AccountManager accountManager,
@DatabaseExecutor Executor databaseExecutor,
SettingsManager settingsManager, DozeWatchdog dozeWatchdog,
Activity activity) {
this.serviceConnection = serviceConnection;
this.databaseConfig = databaseConfig;
this.accountManager = accountManager;
this.databaseExecutor = databaseExecutor;
this.settingsManager = settingsManager;
this.dozeWatchdog = dozeWatchdog;
@@ -59,7 +62,7 @@ public class BriarControllerImpl implements BriarController {
@Override
@CallSuper
public void onActivityCreate(Activity activity) {
if (databaseConfig.getEncryptionKey() != null) startAndBindService();
if (signedIn()) startAndBindService();
}
@Override
@@ -84,8 +87,9 @@ public class BriarControllerImpl implements BriarController {
}
@Override
public boolean hasEncryptionKey() {
return databaseConfig.getEncryptionKey() != null;
public boolean signedIn() {
AccountState state = accountManager.getAccountState();
return state == CREATING_ACCOUNT || state == SIGNED_IN;
}
@Override

View File

@@ -1,23 +0,0 @@
package org.briarproject.briar.android.controller;
import android.content.Context;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import javax.annotation.Nullable;
@NotNullByDefault
public interface ConfigController {
@Nullable
String getEncryptedDatabaseKey();
boolean storeEncryptedDatabaseKey(String hex);
void deleteAccount(Context ctx);
boolean accountExists();
boolean accountSignedIn();
}

View File

@@ -6,7 +6,6 @@ import android.os.Bundle;
import android.support.annotation.CallSuper;
import android.support.annotation.UiThread;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentActivity;
import android.view.MenuItem;
import org.briarproject.bramble.api.db.DbException;
@@ -57,8 +56,8 @@ public abstract class BaseFragment extends Fragment
@UiThread
protected void finish() {
FragmentActivity activity = getActivity();
if (activity != null) activity.supportFinishAfterTransition();
if (!isDetached())
getActivity().supportFinishAfterTransition();
}
public interface BaseFragmentListener {
@@ -86,7 +85,7 @@ public abstract class BaseFragment extends Fragment
activity.runOnUiThread(() -> {
// Note that we don't have to check if the activity has
// been destroyed as the Fragment has not been detached yet
if (isAdded() && !activity.isFinishing()) {
if (!isDetached() && !activity.isFinishing()) {
r.run();
}
});

View File

@@ -1,6 +1,5 @@
package org.briarproject.briar.android.login;
import android.app.NotificationManager;
import android.content.Intent;
import android.os.Bundle;
import android.support.annotation.NonNull;
@@ -15,6 +14,7 @@ import android.widget.ProgressBar;
import org.briarproject.briar.R;
import org.briarproject.briar.android.Localizer;
import org.briarproject.briar.android.account.SetupActivity;
import org.briarproject.briar.android.activity.ActivityComponent;
import org.briarproject.briar.android.activity.BaseActivity;
import org.briarproject.briar.android.controller.BriarController;
@@ -29,7 +29,6 @@ import static android.content.Intent.FLAG_ACTIVITY_CLEAR_TASK;
import static android.content.Intent.FLAG_ACTIVITY_NEW_TASK;
import static android.view.View.INVISIBLE;
import static android.view.View.VISIBLE;
import static org.briarproject.briar.api.android.AndroidNotificationManager.REMINDER_NOTIFICATION_ID;
public class PasswordActivity extends BaseActivity {
@@ -87,14 +86,9 @@ public class PasswordActivity extends BaseActivity {
public void onStart() {
super.onStart();
// If the user has already signed in, clean up this instance
if (briarController.hasEncryptionKey()) {
if (briarController.signedIn()) {
setResult(RESULT_OK);
finish();
} else {
// Remove sign-in reminder notification
NotificationManager nm = (NotificationManager)
getSystemService(NOTIFICATION_SERVICE);
nm.cancel(REMINDER_NOTIFICATION_ID);
}
}
@@ -112,7 +106,7 @@ public class PasswordActivity extends BaseActivity {
}
private void deleteAccount() {
passwordController.deleteAccount(this);
passwordController.deleteAccount();
Localizer.reinitialize();
UiUtils.setTheme(this, getString(R.string.pref_theme_light_value));
setResult(RESULT_CANCELED);

View File

@@ -1,11 +1,12 @@
package org.briarproject.briar.android.login;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import org.briarproject.briar.android.controller.ConfigController;
import org.briarproject.briar.android.controller.handler.ResultHandler;
@NotNullByDefault
public interface PasswordController extends ConfigController {
public interface PasswordController {
boolean accountExists();
float estimatePasswordStrength(String password);
@@ -15,4 +16,6 @@ public interface PasswordController extends ConfigController {
void changePassword(String password, String newPassword,
ResultHandler<Boolean> resultHandler);
void deleteAccount();
}

View File

@@ -1,47 +1,41 @@
package org.briarproject.briar.android.login;
import android.content.SharedPreferences;
import org.briarproject.bramble.api.account.AccountManager;
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;
import org.briarproject.bramble.util.StringUtils;
import org.briarproject.briar.android.controller.ConfigControllerImpl;
import org.briarproject.briar.android.controller.handler.ResultHandler;
import java.util.concurrent.Executor;
import java.util.logging.Logger;
import javax.inject.Inject;
import static org.briarproject.bramble.util.LogUtils.logDuration;
import static org.briarproject.bramble.util.LogUtils.now;
import static org.briarproject.bramble.api.account.AccountState.NO_ACCOUNT;
@NotNullByDefault
public class PasswordControllerImpl extends ConfigControllerImpl
implements PasswordController {
private static final Logger LOG =
Logger.getLogger(PasswordControllerImpl.class.getName());
public class PasswordControllerImpl implements PasswordController {
protected final AccountManager accountManager;
protected final Executor cryptoExecutor;
protected final CryptoComponent crypto;
private final PasswordStrengthEstimator strengthEstimator;
@Inject
PasswordControllerImpl(SharedPreferences briarPrefs,
DatabaseConfig databaseConfig,
public PasswordControllerImpl(AccountManager accountManager,
@CryptoExecutor Executor cryptoExecutor, CryptoComponent crypto,
PasswordStrengthEstimator strengthEstimator) {
super(briarPrefs, databaseConfig);
this.accountManager = accountManager;
this.cryptoExecutor = cryptoExecutor;
this.crypto = crypto;
this.strengthEstimator = strengthEstimator;
}
@Override
public boolean accountExists() {
return accountManager.getAccountState() != NO_ACCOUNT;
}
@Override
public float estimatePasswordStrength(String password) {
return strengthEstimator.estimateStrength(password);
@@ -50,46 +44,25 @@ public class PasswordControllerImpl extends ConfigControllerImpl
@Override
public void validatePassword(String password,
ResultHandler<Boolean> resultHandler) {
byte[] encrypted = getEncryptedKey();
cryptoExecutor.execute(() -> {
byte[] key = crypto.decryptWithPassword(encrypted, password);
if (key == null) {
resultHandler.onResult(false);
} else {
databaseConfig.setEncryptionKey(new SecretKey(key));
resultHandler.onResult(true);
}
boolean result = accountManager.validatePassword(password);
resultHandler.onResult(result);
});
}
@Override
public void changePassword(String password, String newPassword,
ResultHandler<Boolean> resultHandler) {
byte[] encrypted = getEncryptedKey();
cryptoExecutor.execute(() -> {
byte[] key = crypto.decryptWithPassword(encrypted, password);
if (key == null) {
resultHandler.onResult(false);
} else {
String hex =
encryptDatabaseKey(new SecretKey(key), newPassword);
resultHandler.onResult(storeEncryptedDatabaseKey(hex));
}
boolean result =
accountManager.changePassword(password, newPassword);
resultHandler.onResult(result);
});
}
private byte[] getEncryptedKey() {
String hex = getEncryptedDatabaseKey();
if (hex == null)
throw new IllegalStateException("Encrypted database key is null");
return StringUtils.fromHexString(hex);
@Override
public void deleteAccount() {
accountManager.deleteAccount();
}
@CryptoExecutor
String encryptDatabaseKey(SecretKey key, String password) {
long start = now();
byte[] encrypted = crypto.encryptWithPassword(key.getBytes(), password);
logDuration(LOG, "Key derivation", start);
return StringUtils.toHexString(encrypted);
}
}

View File

@@ -10,11 +10,12 @@ import android.content.SharedPreferences;
import android.support.v4.app.NotificationCompat;
import android.support.v4.content.ContextCompat;
import org.briarproject.bramble.api.db.DatabaseConfig;
import org.briarproject.bramble.api.account.AccountManager;
import org.briarproject.briar.R;
import org.briarproject.briar.android.AndroidComponent;
import org.briarproject.briar.android.BriarApplication;
import org.briarproject.briar.android.navdrawer.NavDrawerActivity;
import org.briarproject.briar.android.settings.SettingsActivity;
import javax.inject.Inject;
@@ -27,17 +28,17 @@ import static android.content.Intent.FLAG_ACTIVITY_NEW_TASK;
import static android.os.Build.VERSION.SDK_INT;
import static android.support.v4.app.NotificationCompat.PRIORITY_LOW;
import static android.support.v4.app.NotificationCompat.VISIBILITY_SECRET;
import static org.briarproject.bramble.api.account.AccountState.NO_ACCOUNT;
import static org.briarproject.briar.android.TestingConstants.FEATURE_FLAG_SIGN_IN_REMINDER;
import static org.briarproject.briar.android.settings.SettingsActivity.NO_NOTIFY_SIGN_IN;
import static org.briarproject.briar.android.settings.SettingsFragment.NOTIFY_SIGN_IN;
import static org.briarproject.briar.api.android.AndroidNotificationManager.REMINDER_CHANNEL_ID;
import static org.briarproject.briar.api.android.AndroidNotificationManager.REMINDER_NOTIFICATION_ID;
public class SignInReminderReceiver extends BroadcastReceiver {
public static final String DISMISS_REMINDER = "dismissReminder";
@Inject
DatabaseConfig databaseConfig;
AccountManager accountManager;
@Override
public void onReceive(Context ctx, Intent intent) {
@@ -51,14 +52,12 @@ public class SignInReminderReceiver extends BroadcastReceiver {
if (action == null) return;
if (action.equals(ACTION_BOOT_COMPLETED) ||
action.equals(ACTION_MY_PACKAGE_REPLACED)) {
if (databaseConfig.databaseExists()) {
if (accountManager.getAccountState() != NO_ACCOUNT) {
SharedPreferences prefs = app.getDefaultSharedPreferences();
if (prefs.getBoolean(NOTIFY_SIGN_IN, true)) {
showSignInNotification(ctx);
}
}
} else if (action.equals(DISMISS_REMINDER)) {
dismissReminder(ctx);
}
}
@@ -78,7 +77,7 @@ public class SignInReminderReceiver extends BroadcastReceiver {
NotificationCompat.Builder b =
new NotificationCompat.Builder(ctx, REMINDER_CHANNEL_ID);
b.setSmallIcon(R.drawable.ic_signout);
b.setSmallIcon(R.drawable.notification_reminder);
b.setColor(ContextCompat.getColor(ctx, R.color.briar_primary));
b.setContentTitle(ctx.getText(R.string.reminder_notification_title));
b.setContentText(ctx.getText(R.string.reminder_notification_text));
@@ -86,12 +85,12 @@ public class SignInReminderReceiver extends BroadcastReceiver {
b.setWhen(0); // Don't show the time
b.setPriority(PRIORITY_LOW);
// Add a 'Dismiss' action
// Add a 'Do not show sign-in reminder' action
String actionTitle =
ctx.getString(R.string.reminder_notification_dismiss);
Intent i1 = new Intent(ctx, SignInReminderReceiver.class);
i1.setAction(DISMISS_REMINDER);
PendingIntent actionIntent = PendingIntent.getBroadcast(ctx, 0, i1, 0);
ctx.getString(R.string.reminder_notification_do_not_show_again);
Intent i1 = new Intent(ctx, SettingsActivity.class);
i1.setAction(NO_NOTIFY_SIGN_IN);
PendingIntent actionIntent = PendingIntent.getActivity(ctx, 0, i1, 0);
b.addAction(0, actionTitle, actionIntent);
Intent i = new Intent(ctx, NavDrawerActivity.class);
@@ -101,11 +100,4 @@ public class SignInReminderReceiver extends BroadcastReceiver {
nm.notify(REMINDER_NOTIFICATION_ID, b.build());
}
private void dismissReminder(Context ctx) {
NotificationManager nm = (NotificationManager)
ctx.getSystemService(NOTIFICATION_SERVICE);
if (nm == null) return;
nm.cancel(REMINDER_NOTIFICATION_ID);
}
}

View File

@@ -7,10 +7,10 @@ import android.os.Build;
import android.os.Bundle;
import android.support.v7.preference.PreferenceManager;
import org.briarproject.bramble.api.account.AccountManager;
import org.briarproject.bramble.api.system.AndroidExecutor;
import org.briarproject.briar.android.activity.ActivityComponent;
import org.briarproject.briar.android.activity.BriarActivity;
import org.briarproject.briar.android.controller.ConfigController;
import org.iilab.IilabEngineeringRSA2048Pin;
import java.util.logging.Logger;
@@ -33,7 +33,7 @@ public class PanicResponderActivity extends BriarActivity {
Logger.getLogger(PanicResponderActivity.class.getName());
@Inject
protected ConfigController configController;
protected AccountManager accountManager;
@Inject
protected AndroidExecutor androidExecutor;
@@ -94,7 +94,7 @@ public class PanicResponderActivity extends BriarActivity {
private void deleteAllData() {
androidExecutor.runOnBackgroundThread(() -> {
configController.deleteAccount(PanicResponderActivity.this);
accountManager.deleteAccount();
// TODO somehow delete/shred the database more thoroughly
PanicResponder.deleteAllAppData(PanicResponderActivity.this);

View File

@@ -1,19 +1,43 @@
package org.briarproject.briar.android.settings;
import android.app.NotificationManager;
import android.content.Intent;
import android.content.SharedPreferences;
import android.os.Bundle;
import android.support.v7.app.ActionBar;
import android.view.MenuItem;
import org.briarproject.briar.R;
import org.briarproject.briar.android.BriarApplication;
import org.briarproject.briar.android.activity.ActivityComponent;
import org.briarproject.briar.android.activity.BriarActivity;
import static org.briarproject.briar.android.settings.SettingsFragment.NOTIFY_SIGN_IN;
import static org.briarproject.briar.api.android.AndroidNotificationManager.REMINDER_NOTIFICATION_ID;
public class SettingsActivity extends BriarActivity {
public static final String NO_NOTIFY_SIGN_IN = "noNotifySignIn";
@Override
public void onCreate(Bundle bundle) {
super.onCreate(bundle);
// Maybe turn off sign-in reminder
Intent intent = getIntent();
if (intent != null && NO_NOTIFY_SIGN_IN.equals(intent.getAction())) {
// Turn it off
BriarApplication app = (BriarApplication) getApplication();
SharedPreferences prefs = app.getDefaultSharedPreferences();
prefs.edit().putBoolean(NOTIFY_SIGN_IN, false).apply();
// Remove sign-in reminder notification
NotificationManager nm = (NotificationManager)
getSystemService(NOTIFICATION_SERVICE);
if (nm != null) nm.cancel(REMINDER_NOTIFICATION_ID);
// Finish this activity again
finish();
}
ActionBar actionBar = getSupportActionBar();
if (actionBar != null) {
actionBar.setHomeButtonEnabled(true);

View File

@@ -4,22 +4,17 @@ import android.annotation.TargetApi;
import android.app.AlertDialog;
import android.content.Context;
import android.content.Intent;
import android.graphics.drawable.ColorDrawable;
import android.media.Ringtone;
import android.media.RingtoneManager;
import android.net.Uri;
import android.os.Bundle;
import android.support.annotation.StringRes;
import android.support.v4.content.ContextCompat;
import android.support.v4.text.TextUtilsCompat;
import android.support.v7.preference.CheckBoxPreference;
import android.support.v7.preference.ListPreference;
import android.support.v7.preference.Preference;
import android.support.v7.preference.PreferenceFragmentCompat;
import android.support.v7.preference.PreferenceGroup;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Toast;
import org.acra.ACRA;
@@ -221,16 +216,6 @@ public class SettingsFragment extends PreferenceFragmentCompat
loadSettings();
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View view = super.onCreateView(inflater, container, savedInstanceState);
ColorDrawable divider = new ColorDrawable(
ContextCompat.getColor(getContext(), R.color.divider));
setDivider(divider);
return view;
}
@Override
public void onStart() {
super.onStart();

View File

@@ -7,18 +7,20 @@ import android.os.Handler;
import android.support.v7.preference.PreferenceManager;
import android.transition.Fade;
import org.briarproject.bramble.api.account.AccountManager;
import org.briarproject.bramble.api.system.AndroidExecutor;
import org.briarproject.briar.R;
import org.briarproject.briar.android.account.SetupActivity;
import org.briarproject.briar.android.activity.ActivityComponent;
import org.briarproject.briar.android.activity.BaseActivity;
import org.briarproject.briar.android.controller.ConfigController;
import org.briarproject.briar.android.login.OpenDatabaseActivity;
import org.briarproject.briar.android.login.SetupActivity;
import java.util.logging.Logger;
import javax.inject.Inject;
import static org.briarproject.bramble.api.account.AccountState.NO_ACCOUNT;
import static org.briarproject.bramble.api.account.AccountState.SIGNED_IN;
import static org.briarproject.briar.android.TestingConstants.EXPIRY_DATE;
public class SplashScreenActivity extends BaseActivity {
@@ -27,7 +29,7 @@ public class SplashScreenActivity extends BaseActivity {
Logger.getLogger(SplashScreenActivity.class.getName());
@Inject
protected ConfigController configController;
AccountManager accountManager;
@Inject
protected AndroidExecutor androidExecutor;
@@ -43,7 +45,7 @@ public class SplashScreenActivity extends BaseActivity {
setContentView(R.layout.splash);
if (configController.accountSignedIn()) {
if (accountManager.getAccountState() == SIGNED_IN) {
startActivity(new Intent(this, OpenDatabaseActivity.class));
finish();
} else {
@@ -64,12 +66,12 @@ public class SplashScreenActivity extends BaseActivity {
LOG.info("Expired");
startActivity(new Intent(this, ExpiredActivity.class));
} else {
if (configController.accountExists()) {
if (accountManager.getAccountState() != NO_ACCOUNT) {
LOG.info("Account exists");
startActivity(new Intent(this, OpenDatabaseActivity.class));
} else {
LOG.info("Account does not exist");
configController.deleteAccount(this);
accountManager.deleteAccount();
startActivity(new Intent(this, SetupActivity.class));
}
}

View File

@@ -0,0 +1,27 @@
package org.briarproject.briar.api.android;
/**
* Manages mappings between object references and serialisable handles. This
* enables references to be passed between Android UI objects that belong to
* the same process but can only communicate via serialisation.
*/
public interface ReferenceManager {
/**
* Returns the object with the given handle, or null if no mapping exists
* for the handle.
*/
<T> T getReference(long handle, Class<T> c);
/**
* Creates a mapping between the given reference and a handle, and returns
* the handle.
*/
<T> long putReference(T reference, Class<T> c);
/**
* Removes and returns the object with the given handle, or returns null
* if no mapping exists for the handle.
*/
<T> T removeReference(long handle, Class<T> c);
}

View File

@@ -1,15 +0,0 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="146dp"
android:height="50dp"
android:viewportHeight="50"
android:viewportWidth="146">
<path
android:fillColor="#95d220"
android:pathData="m65.098,15.35v19.301h9.068c4.226,0 6.475,-2.124 6.496,-5.479 0,-2.145 -1.018,-3.78 -3.014,-4.672v-0.041c1.508,-0.934 2.166,-2.103 2.166,-3.908 0,-2.739 -1.848,-5.201 -5.861,-5.201h-8.855zM83.848,15.35v19.301h2.271v-7.729l-0.232,-0.234h4.586c2.548,0 4.013,0.914 4.947,2.889l2.4,5.074h2.547l-2.93,-6.031c-0.637,-1.359 -1.614,-2.208 -2.527,-2.59v-0.043c2.123,-0.552 3.865,-2.42 3.865,-4.947 0,-3.801 -2.952,-5.689 -6.477,-5.689h-8.451zM102.725,15.35v19.301h2.273v-19.301zM116.145,15.35 L107.65,34.65h2.484l2.039,-4.65 -0.127,-0.234h10.574l-0.127,0.234 2.039,4.65h2.484l-8.473,-19.301zM129.48,15.35v19.301h2.271v-7.729l-0.234,-0.234h4.588c2.548,0 4.013,0.914 4.947,2.889l2.398,5.074L146,34.65l-2.93,-6.031c-0.637,-1.359 -1.614,-2.208 -2.527,-2.59v-0.043c2.123,-0.552 3.865,-2.42 3.865,-4.947 0,-3.801 -2.952,-5.689 -6.477,-5.689h-8.451zM67.158,17.494h6.561c2.463,0 3.76,0.997 3.76,3.035 0,1.72 -0.999,3.102 -3.76,3.102h-6.561l0.234,-0.234v-5.67zM85.887,17.494h6.434c2.378,0 4.141,0.975 4.162,3.523 0,2.038 -1.634,3.504 -4.416,3.504h-6.18l0.232,-0.232v-6.563zM131.539,17.494h6.434c2.357,0 4.141,0.975 4.141,3.523 0,2.038 -1.613,3.504 -4.395,3.504h-6.18l0.234,-0.232v-6.563zM117.334,17.705h0.043l0.572,1.934 3.398,7.75 0.232,0.232h-8.471l0.232,-0.232 3.398,-7.75 0.594,-1.934zM67.137,25.775h7.008c2.845,0 4.162,1.315 4.162,3.375 0,2.145 -1.189,3.334 -4.141,3.334h-7.029l0.234,-0.234v-6.242z"/>
<path
android:fillColor="#87c214"
android:pathData="m13.809,0c-2.064,0 -3.766,1.702 -3.766,3.766L10.042,8.553h9.277L19.319,3.766C19.319,1.702 17.638,0 15.574,0ZM34.447,0c-2.064,0 -3.766,1.702 -3.766,3.766L30.681,29.191h9.277L39.958,3.766C39.958,1.702 38.276,0 36.213,0ZM10.042,20.809v25.426c0,2.064 1.681,3.766 3.766,3.766h1.766c2.064,0 3.766,-1.702 3.766,-3.766L19.341,20.809ZM30.681,41.447v4.787c0,2.064 1.702,3.766 3.766,3.766h1.766c2.064,0 3.766,-1.702 3.766,-3.766v-4.787z"/>
<path
android:fillColor="#95d220"
android:pathData="M3.766,10.042C1.702,10.042 0,11.723 0,13.809v1.766c0,2.064 1.681,3.766 3.766,3.766L29.191,19.341v-9.298zM41.447,10.042v9.298h4.787c2.064,0 3.766,-1.681 3.766,-3.766v-1.766c0,-2.085 -1.702,-3.766 -3.766,-3.766zM3.766,30.681C1.702,30.681 0,32.362 0,34.447v1.766c0,2.064 1.681,3.766 3.766,3.766h4.787v-9.298zM20.809,30.681v9.298h25.426c2.064,0 3.766,-1.702 3.766,-3.766L50,34.447c0,-2.085 -1.702,-3.766 -3.766,-3.766z"/>
</vector>

View File

@@ -1,5 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="@color/item_background_highlight" android:state_checked="true"/>
<item android:drawable="@color/window_background" android:state_checked="false"/>
</selector>

View File

@@ -1,9 +0,0 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportHeight="24"
android:viewportWidth="24">
<path
android:fillColor="#FFFFFFFF"
android:pathData="M17,17.25V14H10V10H17V6.75L22.25,12L17,17.25M13,2A2,2 0 0,1 15,4V8H13V4H4V20H13V16H15V20A2,2 0 0,1 13,22H4A2,2 0 0,1 2,20V4A2,2 0 0,1 4,2H13Z"/>
</vector>

View File

@@ -0,0 +1,9 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportHeight="24.0"
android:viewportWidth="24.0">
<path
android:fillColor="#FF000000"
android:pathData="M13,8.2l-1,-1 -4,4 -4,-4 -1,1 4,4 -4,4 1,1 4,-4 4,4 1,-1 -4,-4 4,-4zM19,1H9c-1.1,0 -2,0.9 -2,2v3h2V4h10v16H9v-2H7v3c0,1.1 0.9,2 2,2h10c1.1,0 2,-0.9 2,-2V3c0,-1.1 -0.9,-2 -2,-2z"/>
</vector>

View File

@@ -1,15 +1,129 @@
<?xml version="1.0" encoding="utf-8"?>
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="146dp"
android:width="138dp"
android:height="50dp"
android:viewportHeight="50"
android:viewportWidth="146">
<path
android:fillColor="#ffffff"
android:pathData="m65.098,30.699v19.301h9.068c4.226,0 6.475,-2.124 6.496,-5.479 0,-2.145 -1.018,-3.78 -3.014,-4.672v-0.041c1.508,-0.934 2.166,-2.103 2.166,-3.908 0,-2.739 -1.848,-5.201 -5.861,-5.201h-8.855zM83.848,30.699v19.301h2.271v-7.729l-0.232,-0.234h4.586c2.548,0 4.013,0.914 4.947,2.889l2.4,5.074h2.547l-2.93,-6.031c-0.637,-1.359 -1.614,-2.208 -2.527,-2.59v-0.043c2.123,-0.552 3.865,-2.42 3.865,-4.947 0,-3.801 -2.952,-5.689 -6.477,-5.689h-8.451zM102.725,30.699v19.301h2.273v-19.301zM116.145,30.699 L107.65,50h2.484l2.039,-4.65 -0.127,-0.234h10.574l-0.127,0.234 2.039,4.65h2.484l-8.473,-19.301zM129.48,30.699v19.301h2.271v-7.729l-0.234,-0.234h4.588c2.548,0 4.013,0.914 4.947,2.889l2.398,5.074L146,50l-2.93,-6.031c-0.637,-1.359 -1.614,-2.208 -2.527,-2.59v-0.043c2.123,-0.552 3.865,-2.42 3.865,-4.947 0,-3.801 -2.952,-5.689 -6.477,-5.689h-8.451zM67.158,32.844h6.561c2.463,0 3.76,0.997 3.76,3.035 0,1.72 -0.999,3.102 -3.76,3.102h-6.561l0.234,-0.234v-5.67zM85.887,32.844h6.434c2.378,0 4.141,0.975 4.162,3.523 0,2.038 -1.634,3.504 -4.416,3.504h-6.18l0.232,-0.232v-6.563zM131.539,32.844h6.434c2.357,0 4.141,0.975 4.141,3.523 0,2.038 -1.613,3.504 -4.395,3.504h-6.18l0.234,-0.232v-6.563zM117.334,33.055h0.043l0.572,1.934 3.398,7.75 0.232,0.232h-8.471l0.232,-0.232 3.398,-7.75 0.594,-1.934zM67.137,41.125h7.008c2.845,0 4.162,1.315 4.162,3.375 0,2.145 -1.189,3.334 -4.141,3.334h-7.029l0.234,-0.234v-6.242z"/>
android:viewportWidth="138">
<path
android:fillColor="#87c214"
android:pathData="m13.809,0c-2.064,0 -3.766,1.702 -3.766,3.766L10.042,8.553h9.277L19.319,3.766C19.319,1.702 17.638,0 15.574,0ZM34.447,0c-2.064,0 -3.766,1.702 -3.766,3.766L30.681,29.191h9.277L39.958,3.766C39.958,1.702 38.276,0 36.213,0ZM10.042,20.809v25.426c0,2.064 1.681,3.766 3.766,3.766h1.766c2.064,0 3.766,-1.702 3.766,-3.766L19.341,20.809ZM30.681,41.447v4.787c0,2.064 1.702,3.766 3.766,3.766h1.766c2.064,0 3.766,-1.702 3.766,-3.766v-4.787z"/>
android:pathData="M230.022,214.001 L239.302,214.001 L239.302,223.281 L230.022,223.281
L230.022,214.001 Z"/>
<path
android:fillColor="#ffffff"
android:pathData="M235.543,203.979 C237.603,203.979,239.301,205.678,239.301,207.737
L239.301,250.141 C239.301,252.201,237.602,253.899,235.543,253.899
L233.781,253.899 C231.721,253.899,230.023,252.2,230.023,250.141 L230.023,207.737
C230.023,205.677,231.7,203.979,233.76,203.979 L235.544,203.979 M235.544,202.493
L233.782,202.493 C230.873,202.493,228.537,204.85,228.537,207.738
L228.537,250.142 C228.537,253.03,230.894,255.387,233.782,255.387
L235.544,255.387 C238.432,255.387,240.789,253.03,240.789,250.142
L240.789,207.738 C240.768,204.85,238.432,202.493,235.544,202.493
L235.544,202.493 Z"/>
<path
android:fillColor="#87c214"
android:pathData="M250.619,234.598 L259.899,234.598 L259.899,243.878 L250.619,243.878
L250.619,234.598 Z"/>
<path
android:fillColor="#ffffff"
android:pathData="M256.14,203.979 C258.2,203.979,259.898,205.678,259.898,207.737 L259.898,250.141
C259.898,252.201,258.221,253.899,256.14,253.899 L254.378,253.899
C252.318,253.899,250.62,252.2,250.62,250.141 L250.62,207.737
C250.62,205.677,252.319,203.979,254.378,203.979 L256.14,203.979 M256.14,202.493
L254.378,202.493 C251.49,202.493,249.133,204.85,249.133,207.738 L249.133,250.142
C249.133,253.03,251.49,255.387,254.378,255.387 L256.14,255.387
C259.028,255.387,261.385,253.03,261.385,250.142 L261.385,207.738
C261.364,204.85,259.028,202.493,256.14,202.493 L256.14,202.493 Z"/>
<path
android:fillColor="#95d220"
android:pathData="M3.766,10.042C1.702,10.042 0,11.723 0,13.809v1.766c0,2.064 1.681,3.766 3.766,3.766L29.191,19.341v-9.298zM41.447,10.042v9.298h4.787c2.064,0 3.766,-1.681 3.766,-3.766v-1.766c0,-2.085 -1.702,-3.766 -3.766,-3.766zM3.766,30.681C1.702,30.681 0,32.362 0,34.447v1.766c0,2.064 1.681,3.766 3.766,3.766h4.787v-9.298zM20.809,30.681v9.298h25.426c2.064,0 3.766,-1.702 3.766,-3.766L50,34.447c0,-2.085 -1.702,-3.766 -3.766,-3.766z"/>
android:pathData="M230.022,234.598 L239.302,234.598 L239.302,243.878 L230.022,243.878
L230.022,234.598 Z"/>
<path
android:fillColor="#ffffff"
android:pathData="M266.142,234.598 C268.202,234.598,269.9,236.275,269.9,238.356 L269.9,240.118
C269.9,242.178,268.201,243.876,266.142,243.876 L223.759,243.876
C221.699,243.876,220.001,242.177,220.001,240.118 L220.001,238.356
C220.001,236.296,221.678,234.598,223.759,234.598 L266.142,234.598
M266.142,233.112 L223.759,233.112
C220.871,233.112,218.514,235.448,218.514,238.336 L218.514,240.098
C218.514,242.986,220.871,245.343,223.759,245.343 L266.163,245.343
C269.051,245.343,271.408,242.986,271.408,240.098 L271.408,238.336
C271.387,235.448,269.03,233.112,266.142,233.112 L266.142,233.112 Z"/>
<path
android:fillColor="#95d220"
android:pathData="M250.619,214.001 L259.899,214.001 L259.899,223.281 L250.619,223.281
L250.619,214.001 Z"/>
<path
android:fillColor="#ffffff"
android:pathData="M266.142,214.001 C268.202,214.001,269.9,215.678,269.9,217.759 L269.9,219.521
C269.9,221.581,268.201,223.279,266.142,223.279 L223.759,223.279
C221.677,223.259,220,221.582,220,219.522 L220,217.76
C220,215.7,221.677,214.002,223.758,214.002 L266.141,214.002 M266.141,212.516
L223.758,212.516 C220.87,212.516,218.513,214.852,218.513,217.74 L218.513,219.502
C218.513,222.39,220.87,224.747,223.758,224.747 L266.162,224.747
C269.05,224.747,271.407,222.39,271.407,219.502 L271.407,217.74
C271.386,214.852,269.029,212.516,266.141,212.516 L266.141,212.516 Z"/>
<path
android:fillColor="#ffffff"
android:pathData="M57.0977,30.6992 L57.0977,50 L66.1661,50
C70.3917,50,72.641,47.8764,72.6622,44.5215
C72.6622,42.3769,71.6445,40.7415,69.6485,39.8496 L69.6485,39.8086
C71.1561,38.8743,71.8145,37.7053,71.8145,35.9004
C71.8145,33.1612,69.9664,30.6992,65.9532,30.6992 L57.0977,30.6992 Z
M75.8477,30.6992 L75.8477,50 L78.1192,50 L78.1192,42.2715 L77.8868,42.0371
L82.4727,42.0371 C85.0208,42.0371,86.4857,42.951,87.42,44.9258 L89.8203,50
L92.3672,50 L89.4375,43.9688 C88.8005,42.6098,87.8232,41.7611,86.9102,41.3789
L86.9102,41.3359 C89.0336,40.7838,90.7754,38.9155,90.7754,36.3886
C90.7754,32.5877,87.8237,30.6991,84.2988,30.6991 L75.8476,30.6991 Z
M94.7247,30.6992 L94.7247,50 L96.9981,50 L96.9981,30.6992 L94.7247,30.6992 Z
M108.145,30.6992 L99.6504,50 L102.135,50 L104.174,45.3496 L104.047,45.1152
L114.621,45.1152 L114.494,45.3496 L116.533,50 L119.017,50 L110.544,30.6992
L108.144,30.6992 Z M121.481,30.6992 L121.481,50 L123.752,50 L123.752,42.2715
L123.518,42.0371 L128.106,42.0371
C130.654,42.0371,132.119,42.951,133.053,44.9258 L135.451,50 L138,50
L135.07,43.9688 C134.433,42.6098,133.456,41.7611,132.543,41.3789
L132.543,41.3359 C134.666,40.7838,136.408,38.9155,136.408,36.3886
C136.408,32.5877,133.456,30.6991,129.931,30.6991 L121.48,30.6991 Z
M59.1587,32.8437 L65.7192,32.8437 C68.1823,32.8437,69.479,33.8404,69.479,35.8789
C69.479,37.5989,68.4797,38.9805,65.7192,38.9805 L59.1587,38.9805
L59.3931,38.7461 L59.3931,33.0762 L59.1587,32.8438 Z M77.8872,32.8437
L84.3208,32.8437 C86.699,32.8437,88.4617,33.819,88.4829,36.3671
C88.4829,38.4056,86.8485,39.871,84.0669,39.871 L77.8872,39.871 L78.1196,39.6386
L78.1196,33.0761 L77.8872,32.8437 Z M123.54,32.8437 L129.974,32.8437
C132.331,32.8437,134.115,33.819,134.115,36.3671
C134.115,38.4056,132.502,39.871,129.72,39.871 L123.54,39.871 L123.774,39.6386
L123.774,33.0761 L123.54,32.8437 Z M109.335,33.0546 L109.378,33.0546
L109.95,34.9882 L113.348,42.7382 L113.58,42.9706 L105.109,42.9706
L105.341,42.7382 L108.739,34.9882 L109.333,33.0546 Z M59.1377,41.1249
L66.1455,41.1249 C68.9909,41.1249,70.3076,42.4402,70.3076,44.4999
C70.3076,46.6445,69.1185,47.8339,66.167,47.8339 L59.1377,47.8339
L59.3721,47.5995 L59.3721,41.3573 L59.1377,41.1249 Z"/>
<path
android:fillColor="#87c214"
android:pathData="M13.8086,0.00000870181 C11.7448,0.00000870181,10.0425,1.70197,10.0425,3.7658
L10.0425,8.55303 L19.3194,8.55303 L19.3194,3.7658
C19.3194,1.70197,17.6382,0.00001,15.5744,0.00001 L13.8087,0.00001 Z
M34.4469,0.00000870181 C32.3831,0.00000870181,30.6807,1.70197,30.6807,3.7658
L30.6807,29.1913 L39.9576,29.1913 L39.9576,3.7658
C39.9576,1.70197,38.2764,0.00001,36.2126,0.00001 L34.4469,0.00001 Z
M10.0425,20.8087 L10.0425,46.2341
C10.0425,48.2979,11.7236,49.9999,13.8087,49.9999 L15.5744,49.9999
C17.6382,49.9999,19.3406,48.2979,19.3406,46.2341 L19.3406,20.8086
L10.0425,20.8086 Z M30.6808,41.4469 L30.6808,46.2341
C30.6808,48.2979,32.3832,49.9999,34.447,49.9999 L36.2127,49.9999
C38.2765,49.9999,39.9789,48.2979,39.9789,46.2341 L39.9789,41.4469
L30.6808,41.4469 Z"/>
<path
android:fillColor="#95d220"
android:pathData="M3.76588,10.0424 C1.70205,10.0424,0.00014,11.7235,0.00014,13.8086
L0.00014,15.5743 C0.00014,17.6381,1.68077,19.3405,3.76588,19.3405
L29.1914,19.3405 L29.1914,10.0424 L3.7659,10.0424 Z M41.4471,10.0424
L41.4471,19.3405 L46.2343,19.3405
C48.2981,19.3405,50.0001,17.6594,50.0001,15.5743 L50.0001,13.8086
C50.0001,11.7235,48.2981,10.0424,46.2343,10.0424 L41.4471,10.0424 Z
M3.76579,30.6807 C1.70205,30.6807,-0.00008,32.3618,-0.00008,34.4469
L-0.00008,36.2126 C-0.00008,38.2764,1.68056,39.9788,3.76567,39.9788
L8.5529,39.9788 L8.5529,30.6807 L3.76567,30.6807 Z M20.8087,30.6807
L20.8087,39.9788 L46.2342,39.9788 C48.298,39.9788,50,38.2764,50,36.2126
L50,34.4469 C50,32.3618,48.298,30.6807,46.2342,30.6807 L20.8087,30.6807 Z"/>
</vector>

View File

@@ -1,5 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="@color/item_background_highlight" android:state_checked="true"/>
<item android:drawable="@android:color/transparent" android:state_checked="false"/>
</selector>

View File

@@ -0,0 +1,10 @@
<?xml version="1.0" encoding="utf-8"?>
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportHeight="24"
android:viewportWidth="24">
<path
android:fillColor="#ffffff"
android:pathData="M 12 0 A 12 12 0 0 0 4.875 2.3613281 L 6.9316406 4.4160156 C 7.0875805 3.8805807 7.5639651 3.4765625 8.1464844 3.4765625 L 8.7480469 3.4765625 C 9.4535014 3.4765625 10.035156 4.0582174 10.035156 4.7636719 L 10.035156 6.4003906 L 8.9140625 6.4003906 L 9.4238281 6.9101562 L 13.404297 6.9101562 L 13.404297 10.085938 L 12.601562 10.085938 L 13.914062 11.398438 L 13.914062 4.7636719 C 13.914062 4.0582174 14.495717 3.4765625 15.201172 3.4765625 L 15.802734 3.4765625 C 16.515461 3.4765625 17.089844 4.0582174 17.089844 4.7636719 L 17.089844 13.455078 L 15.96875 13.455078 L 16.478516 13.964844 L 19.236328 13.964844 C 19.941782 13.964844 20.516165 14.546498 20.523438 15.251953 L 20.523438 15.853516 C 20.523438 16.436036 20.119418 16.91242 19.583984 17.068359 L 21.638672 19.125 A 12 12 0 0 0 24 12 A 12 12 0 0 0 12 0 z M 1.2617188 1.3632812 L 0 2.6269531 L 2.3125 4.9472656 A 12 12 0 0 0 0 12 A 12 12 0 0 0 12 24 A 12 12 0 0 0 19.027344 21.707031 L 21.314453 24 L 22.576172 22.734375 L 2.7519531 2.8554688 L 1.9863281 2.0898438 L 1.2617188 1.3632812 z M 17.599609 6.9101562 L 19.236328 6.9101562 C 19.941782 6.9101562 20.516165 7.4918111 20.523438 8.1972656 L 20.523438 8.7988281 C 20.523438 9.511555 19.941782 10.085937 19.236328 10.085938 L 17.599609 10.085938 L 17.599609 6.9101562 z M 4.359375 6.9980469 L 7.4394531 10.085938 L 4.7128906 10.085938 C 4.0001632 10.085938 3.4257813 9.504282 3.4257812 8.7988281 L 3.4257812 8.1972656 C 3.4257812 7.6133228 3.8294199 7.1540656 4.359375 6.9980469 z M 6.859375 10.595703 L 7.9472656 10.595703 L 10.035156 12.689453 L 10.035156 19.287109 C 10.035156 19.992562 9.4535014 20.574219 8.7480469 20.574219 L 8.1464844 20.574219 C 7.4337573 20.574219 6.859375 19.992563 6.859375 19.287109 L 6.859375 10.595703 z M 4.7128906 13.964844 L 6.3496094 13.964844 L 6.3496094 17.140625 L 4.7128906 17.140625 C 4.0001632 17.140625 3.4257813 16.558971 3.4257812 15.853516 L 3.4257812 15.251953 C 3.4257812 14.539226 4.007436 13.964844 4.7128906 13.964844 z M 10.544922 13.964844 L 11.306641 13.964844 L 14.474609 17.140625 L 10.544922 17.140625 L 10.544922 13.964844 z M 13.914062 17.650391 L 14.982422 17.650391 L 16.992188 19.666016 C 16.827053 20.182975 16.371277 20.574219 15.802734 20.574219 L 15.201172 20.574219 C 14.495717 20.574219 13.914063 19.992563 13.914062 19.287109 L 13.914062 17.650391 z"/>
</vector>

View File

@@ -2,59 +2,38 @@
<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="wrap_content"
android:layout_height="match_parent"
android:background="@color/window_background"
android:background="?android:attr/windowBackground"
android:fillViewport="true"
android:orientation="vertical">
<android.support.constraint.ConstraintLayout
<LinearLayout
android:layout_width="wrap_content"
android:layout_height="wrap_content">
android:layout_height="wrap_content"
android:orientation="vertical">
<android.support.design.widget.NavigationView
android:id="@+id/navigation"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="@color/window_background"
app:elevation="0dp"
app:headerLayout="@layout/navigation_header"
app:itemBackground="@drawable/navigation_item_background"
app:itemIconTint="?attr/colorControlNormal"
app:itemTextColor="?android:textColorPrimary"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:menu="@menu/navigation_drawer"/>
<View
android:id="@+id/divider1"
style="@style/Divider.Horizontal"
android:layout_width="0dp"
app:layout_constraintEnd_toEndOf="@+id/navigation"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/navigation"/>
<View
android:id="@+id/spacer"
android:layout_width="0dp"
android:layout_width="match_parent"
android:layout_height="0dp"
app:layout_constraintBottom_toTopOf="@+id/transports"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/divider1"
app:layout_constraintVertical_weight="1"/>
android:layout_weight="1"/>
<include
android:id="@+id/transports"
layout="@layout/transports_list"
android:layout_width="0dp"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="@+id/navigation"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/spacer"
tools:layout_height="75dp"/>
android:layout_gravity="bottom"/>
</android.support.constraint.ConstraintLayout>
</LinearLayout>
</ScrollView>

View File

@@ -1,13 +1,14 @@
<?xml version="1.0" encoding="utf-8"?>
<TextView
android:id="@android:id/title"
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@android:id/title"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@color/preference_category_background"
android:padding="16dp"
android:textColor="@color/briar_accent"
android:layout_marginTop="16dp"
android:layout_marginLeft="16dp"
android:layout_marginStart="16dp"
android:textSize="14sp"
android:textStyle="bold"
android:textColor="@color/preference_category"
tools:text="This is a category"/>

View File

@@ -18,7 +18,6 @@
android:layout_marginTop="@dimen/margin_medium"
android:elevation="@dimen/cardview_default_elevation"
android:minHeight="@dimen/text_input_height"
app:cardBackgroundColor="@color/card_background"
app:cardCornerRadius="0dp"
app:cardUseCompatPadding="false">

View File

@@ -15,6 +15,7 @@
android:layout_height="wrap_content"
android:listSelector="@android:color/transparent"
android:numColumns="3"
android:padding="@dimen/margin_medium"
tools:listitem="@layout/list_item_transport"/>
</LinearLayout>

View File

@@ -28,7 +28,7 @@
android:title="@string/settings_button"/>
<item
android:id="@+id/nav_btn_signout"
android:icon="@drawable/ic_signout"
android:icon="@drawable/ic_signout_black_24dp"
android:title="@string/sign_out_button"/>
</group>

View File

@@ -63,9 +63,8 @@
<string name="transport_lan">Wi-Fi</string>
<!--Notifications-->
<string name="reminder_notification_title">Heu sortit de Briar</string>
<string name="reminder_notification_text">Toqueu per tornar a iniciar sessió.</string>
<string name="reminder_notification_text">Toqueu per reiniciar la sessió o feu lliscar el dit per descartar-la.</string>
<string name="reminder_notification_channel_title">Recordatori d\'inici de sessió de Briar</string>
<string name="reminder_notification_dismiss">Descarta</string>
<string name="ongoing_notification_title">Sessió iniciada</string>
<string name="ongoing_notification_text">Toca per a obrir Briar.</string>
<plurals name="private_message_notification_text">
@@ -351,8 +350,6 @@
<string name="uninstall_setting_summary">Això requeria la confirmació manual malgrat ser en una situació de pànic</string>
<!--Settings Notifications-->
<string name="notification_settings_title">Notificacions</string>
<string name="notify_sign_in_title">Recordeu-me que iniciï sessió</string>
<string name="notify_sign_in_summary">Mostra un recordatori quan s\'inicia el telèfon o s\'ha actualitzat l\'aplicació</string>
<string name="notify_private_messages_setting_title">Missatges privats</string>
<string name="notify_private_messages_setting_summary">Mostra avisos pels missatges privats</string>
<string name="notify_private_messages_setting_summary_26">Configura els avisos pels missatges privats</string>

View File

@@ -222,7 +222,6 @@
<item quantity="one">%d Beitrag</item>
<item quantity="other">%d Beiträge</item>
</plurals>
<string name="forum_new_message_hint">Neuer Beitrag</string>
<string name="forum_message_reply_hint">Neue Antwort</string>
<string name="btn_reply">Antworten</string>
<string name="forum_leave">Forum verlassen</string>
@@ -302,7 +301,6 @@
<string name="blogs_rss_feeds_manage_empty_state">Du hast noch keine RSS-Feeds\n\nTippe auf das +-Symbol um einen Feed zu importieren</string>
<string name="blogs_rss_feeds_manage_error">Es gab ein Problem beim Laden deiner Feeds. Bitte versuche es später erneut.</string>
<!--Settings Display-->
<string name="pref_language_title">Sprache &amp; Region</string>
<string name="pref_language_changed">Diese Einstellung wird aktiv sobald Du Briar neu startest. Bitte melde dich ab und starte Briar neu.</string>
<string name="display_settings_title">Anzeigen</string>
<string name="pref_theme_title">Design</string>
@@ -320,7 +318,6 @@
<!--Settings Security and Panic-->
<string name="security_settings_title">Sicherheit</string>
<string name="change_password">Passwort ändern</string>
<string name="current_password">Aktuelles Passwort</string>
<string name="choose_new_password">Neues Passwort</string>
<string name="confirm_new_password">Neues Passwort bestätigen</string>
<string name="password_changed">Passwort wurde geändert.</string>

View File

@@ -63,7 +63,6 @@
<string name="transport_lan">Wi-Fi</string>
<!--Notifications-->
<string name="reminder_notification_title">Desconectado de Briar</string>
<string name="reminder_notification_dismiss">Descartar</string>
<string name="ongoing_notification_title">Conectado a Briar</string>
<string name="ongoing_notification_text">Toca para abrir Briar.</string>
<plurals name="private_message_notification_text">

View File

@@ -63,9 +63,8 @@
<string name="transport_lan">Wi-Fi</string>
<!--Notifications-->
<string name="reminder_notification_title">Briar saioa amaituta</string>
<string name="reminder_notification_text">Sakatu saioa berriro hasteko</string>
<string name="reminder_notification_text">Sakatu saioa berriro hasteko edo pasatu hatza baztertzeko</string>
<string name="reminder_notification_channel_title">Briar saioaren oroigarria</string>
<string name="reminder_notification_dismiss">Baztertu</string>
<string name="ongoing_notification_title">Briar saioa hasita</string>
<string name="ongoing_notification_text">Ukitu Briar irekitzeko</string>
<plurals name="private_message_notification_text">
@@ -351,8 +350,6 @@
<string name="uninstall_setting_summary">Honek eskuzko berrespena behar du larrialdi egoeran</string>
<!--Settings Notifications-->
<string name="notification_settings_title">Jakinarazpenak</string>
<string name="notify_sign_in_title">Gogorarazi saioa hasteko</string>
<string name="notify_sign_in_summary">Erakutsi oroigarri bat telefonoa abiatzean edo aplikazioa eguneratzean.</string>
<string name="notify_private_messages_setting_title">Mezu pribatuak</string>
<string name="notify_private_messages_setting_summary">Erakutsi mezu pribatuen alertak</string>
<string name="notify_private_messages_setting_summary_26">Konfiguratu mezu pribatuen alertak</string>

View File

@@ -69,6 +69,7 @@
<string name="transport_lan">وای فای</string>
<!--Notifications-->
<string name="reminder_notification_title">از برایر خارج شد</string>
<string name="reminder_notification_text">برای اینکه دوباره وارد شوید کلیک کنید و برای رد کردن آن را بکشید</string>
<string name="reminder_notification_channel_title">یادآور ورود برایر</string>
<string name="ongoing_notification_title">وارد برایر شد</string>
<string name="ongoing_notification_text">برای باز کردن برایر کلیک کنید.</string>

View File

@@ -62,10 +62,6 @@
<string name="transport_bt">Bluetooth</string>
<string name="transport_lan">Wi-Fi</string>
<!--Notifications-->
<string name="reminder_notification_title">Uloskirjautunut Briarista</string>
<string name="reminder_notification_text">Napauta kirjautuaksesi takaisin sisään.</string>
<string name="reminder_notification_channel_title">Briarin sisäänkirjautumisen muistutus</string>
<string name="reminder_notification_dismiss">Hylkää</string>
<string name="ongoing_notification_title">Kirjautunut Briariin</string>
<string name="ongoing_notification_text">Napauta avataksesi Briar.</string>
<plurals name="private_message_notification_text">
@@ -225,8 +221,6 @@
<item quantity="one">%d viesti</item>
<item quantity="other">%d viestiä</item>
</plurals>
<string name="forum_new_entry_posted">Foorumikirjoitus julkaistu</string>
<string name="forum_new_message_hint">Uusi julkaisu</string>
<string name="forum_message_reply_hint">Uusi vastaus</string>
<string name="btn_reply">Vastaa</string>
<string name="forum_leave">Lähde foorumista</string>
@@ -316,8 +310,6 @@
<string name="pref_theme_title">Teema</string>
<string name="pref_theme_light">Vaalea</string>
<string name="pref_theme_dark">Tumma</string>
<string name="pref_theme_auto">Automaattinen (päiväsaika)</string>
<string name="pref_theme_system">Järjestelmäoletus</string>
<!--Settings Network-->
<string name="network_settings_title">Verkot</string>
<string name="bluetooth_setting">Yhdistä Bluetoothin kautta</string>
@@ -330,7 +322,6 @@
<!--Settings Security and Panic-->
<string name="security_settings_title">Turvallisuus</string>
<string name="change_password">Vaihda salasana</string>
<string name="current_password">Nykyinen salasana</string>
<string name="choose_new_password">Uusi salasana</string>
<string name="confirm_new_password">Vahvista uusi salasana</string>
<string name="password_changed">Salasana on vaihdettu.</string>
@@ -351,8 +342,6 @@
<string name="uninstall_setting_summary">Tämä tulee vaatimaan manuaalisen varmennuksen paniikkitilanteessa</string>
<!--Settings Notifications-->
<string name="notification_settings_title">Ilmoitukset</string>
<string name="notify_sign_in_title">Muistuta minua kirjautumaan sisään</string>
<string name="notify_sign_in_summary">Näytä muistutus kun puhelin käynnistyy tai kun sovellus on päivitetty</string>
<string name="notify_private_messages_setting_title">Yksityisviestit</string>
<string name="notify_private_messages_setting_summary">Näytä ilmoitukset yksityisviesteistä</string>
<string name="notify_private_messages_setting_summary_26">Aseta ilmoitukset yksityisviesteille</string>
@@ -404,10 +393,10 @@
<string name="screen_filter_body">Toinen sovellus on piirtämässä Briarin päälle. Suojellakseen sinun turvallisuutta, Briar ei tule vastaamaan kosketuksiin silloin kun toinen sovellus on piirtämässä Briarin päälle.\n\nOn mahdollista, että seuraavat sovellukset piirtävät päälle:\n\n%1$s</string>
<string name="screen_filter_allow">Salli näiden sovellusten piirtää päälle</string>
<!--Permission Requests-->
<string name="permission_camera_title">Kameran käyttöoikeus</string>
<string name="permission_camera_title">Kameralupa</string>
<string name="permission_camera_request_body">Skannatakseen QR koodin, Briar tarvitsee luvan käyttää kameraa.</string>
<string name="permission_camera_denied_body">Olet kieltänyt käyttämästä kameraa, mutta yhteyshenkilöiden lisääminen vaatii kameran käyttöä.\n\nOle hyvä ja harkitse kameraluvan myöntämistä.</string>
<string name="permission_camera_denied_toast">Kameran käyttöoikeutta ei myönnetty</string>
<string name="permission_camera_denied_toast">Kameralupaa ei myönnetty</string>
<string name="qr_code">QR-koodi</string>
<string name="show_qr_code_fullscreen">Näytä QR-koodi koko näytöllä</string>
</resources>

View File

@@ -63,9 +63,8 @@
<string name="transport_lan">Wi-Fi</string>
<!--Notifications-->
<string name="reminder_notification_title">Déconnecté de Briar</string>
<string name="reminder_notification_text">Touchez pour vous reconnecter</string>
<string name="reminder_notification_text">Toucher pour se reconnecter au balayer pour annuler</string>
<string name="reminder_notification_channel_title">Rappel de connexion à Briar</string>
<string name="reminder_notification_dismiss">Fermer</string>
<string name="ongoing_notification_title">Connecté à Briar</string>
<string name="ongoing_notification_text">Toucher pour ouvrir Briar.</string>
<plurals name="private_message_notification_text">
@@ -351,8 +350,6 @@
<string name="uninstall_setting_summary">Une confirmation manuelle est exigée en cas dévénement durgence</string>
<!--Settings Notifications-->
<string name="notification_settings_title">Notifications</string>
<string name="notify_sign_in_title">Rappelez-moi de me connecter</string>
<string name="notify_sign_in_summary">Afficher un rappel lors du démarrage du téléphone ou si lappli a été mise à jour</string>
<string name="notify_private_messages_setting_title">Messages privés</string>
<string name="notify_private_messages_setting_summary">Afficher des notifications pour les messages privés</string>
<string name="notify_private_messages_setting_summary_26">Configurer les alertes pour les messages privés</string>

View File

@@ -63,6 +63,7 @@
<string name="transport_lan">Wi-Fi</string>
<!--Notifications-->
<string name="reminder_notification_title">Desconectou de Briar</string>
<string name="reminder_notification_text">Toque para voltar a conectar ou desplace para desbotar.</string>
<string name="reminder_notification_channel_title">Recordatorio para conectar a Briar</string>
<string name="ongoing_notification_title">Conectado a Briar</string>
<string name="ongoing_notification_text">Toque para abrir Briar</string>
@@ -223,8 +224,6 @@
<item quantity="one">%d publicación</item>
<item quantity="other">%d publicacións</item>
</plurals>
<string name="forum_new_entry_posted">Foro público publicado</string>
<string name="forum_new_message_hint">Nova publicación</string>
<string name="forum_message_reply_hint">Nova Resposta</string>
<string name="btn_reply">Respostar</string>
<string name="forum_leave">Deixar foro</string>

View File

@@ -62,7 +62,6 @@
<string name="transport_bt">ब्लूटूथ</string>
<string name="transport_lan">वाई - फाई</string>
<!--Notifications-->
<string name="reminder_notification_dismiss">खारिज करना</string>
<string name="ongoing_notification_title">ब्रायर में हस्ताक्षर किए</string>
<string name="ongoing_notification_text">ब्रियर को खोलने के लिए स्पर्श करें</string>
<plurals name="private_message_notification_text">

View File

@@ -63,9 +63,8 @@
<string name="transport_lan">Wi-Fi</string>
<!--Notifications-->
<string name="reminder_notification_title">Uscito da Briar</string>
<string name="reminder_notification_text">Tocca per riaccedere.</string>
<string name="reminder_notification_text">Tocca per riaccedere o scorri per annullare.</string>
<string name="reminder_notification_channel_title">Promemoria accesso a Briar</string>
<string name="reminder_notification_dismiss">Ignora</string>
<string name="ongoing_notification_title">Entrato in Briar</string>
<string name="ongoing_notification_text">Tocca per aprire Briar.</string>
<plurals name="private_message_notification_text">
@@ -351,8 +350,6 @@
<string name="uninstall_setting_summary">Questo richiede una conferma manuale in un evento panico</string>
<!--Settings Notifications-->
<string name="notification_settings_title">Notifiche</string>
<string name="notify_sign_in_title">Ricordami di accedere</string>
<string name="notify_sign_in_summary">Mostra un promemoria quando si avvia il telefono o l\'app è stata aggiornata</string>
<string name="notify_private_messages_setting_title">Messaggi privati</string>
<string name="notify_private_messages_setting_summary">Mostra avvisi per i messaggi privati</string>
<string name="notify_private_messages_setting_summary_26">Configurare avvisi per messaggi privati</string>

View File

@@ -1,20 +1,15 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<color name="briar_primary">@color/briar_blue_dark</color>
<color name="briar_accent">@color/briar_green</color>
<color name="preference_category">@color/briar_accent</color>
<color name="preference_category_background">@color/divider</color>
<color name="briar_accent">@color/briar_blue_light2</color>
<color name="preference_category">@color/briar_blue_light2</color>
<color name="color_primary">#ffffff</color>
<color name="window_background">@color/briar_blue_very_dark</color>
<color name="card_background">@color/briar_blue_dark</color>
<color name="item_background_highlight">@color/briar_blue</color>
<color name="divider">#000000</color>
<color name="window_background">#ff303030</color>
<color name="card_background">@color/cardview_dark_background</color>
<color name="divider">#666666</color>
<color name="briar_button_neutral">@color/briar_link</color>
<color name="briar_button_text_disabled">#23cccccc</color>
<color name="thread_item_background">@color/window_background</color>

View File

@@ -63,9 +63,6 @@
<string name="transport_lan">Wifi</string>
<!--Notifications-->
<string name="reminder_notification_title">Uitgelogd van Briar</string>
<string name="reminder_notification_text">Tik om opnieuw in te loggen.</string>
<string name="reminder_notification_channel_title">Briar inlogherinnering</string>
<string name="reminder_notification_dismiss">Afwijzen</string>
<string name="ongoing_notification_title">Ingelogd op Briar</string>
<string name="ongoing_notification_text">Raak aan om Briar te openen.</string>
<plurals name="private_message_notification_text">
@@ -108,7 +105,7 @@
<string name="help">Help</string>
<string name="sorry">Excuses</string>
<!--Contacts and Private Conversations-->
<string name="no_contacts">Geen contacten om te tonen\n\nTik op het +-icoon om een contact toe te voegen</string>
<string name="no_contacts">Geen contacten om te tonen\n\nTap het +-icoon om contact toe te voegen</string>
<string name="date_no_private_messages">Geen berichten.</string>
<string name="no_private_messages">Geen berichten om te tonen</string>
<string name="message_hint">Schrijf een bericht</string>
@@ -117,7 +114,7 @@
<string name="dialog_message_delete_contact">Weet je zeker dat je dit contact en alle berichten die met dit contact zijn uitgewisseld wil verwijderen?</string>
<string name="contact_deleted_toast">Contact is verwijderd</string>
<!--Adding Contacts-->
<string name="add_contact_title">Voeg contact toe</string>
<string name="add_contact_title">Voed contact toe</string>
<string name="face_to_face">Je moet een persoon in levenden lijve ontmoeten om die als contact toe te voegen.\n\nDit voortkomt dat anderen zich als jou voor kunnen doen of in de toekomst je berichten kunnen lezen.</string>
<string name="continue_button">Ga verder</string>
<string name="connection_failed">Connectie is mislukt</string>
@@ -225,8 +222,6 @@
<item quantity="one">%d post</item>
<item quantity="other">%d posts</item>
</plurals>
<string name="forum_new_entry_posted">Forumbericht gepubliceerd</string>
<string name="forum_new_message_hint">Nieuw bericht</string>
<string name="forum_message_reply_hint">Nieuwe reactie</string>
<string name="btn_reply">Antwoord</string>
<string name="forum_leave">Verlaat forum</string>
@@ -309,15 +304,10 @@
<string name="blogs_rss_feeds_manage_empty_state">Geen RSS-feeds om te tonen\n\nTap op het +-icoon om een feed te importeren</string>
<string name="blogs_rss_feeds_manage_error">Er was een probleem met het laden van je feeds. Probeer het later nog een keer.</string>
<!--Settings Display-->
<string name="pref_language_title">Taal &amp; regio</string>
<string name="pref_language_changed">Deze instelling zal werken wanneer u Briar opnieuw opstart. Gelieve uit te loggen en Briar opnieuw te starten.</string>
<string name="pref_language_default">Systeemstandaard</string>
<string name="display_settings_title">Weergeven</string>
<string name="pref_theme_title">Thema</string>
<string name="pref_theme_light">Licht</string>
<string name="pref_theme_dark">Donker</string>
<string name="pref_theme_auto">Automatisch (overdag)</string>
<string name="pref_theme_system">Systeemstandaard</string>
<!--Settings Network-->
<string name="network_settings_title">Netwerken</string>
<string name="bluetooth_setting">Verbind via Bluetooth</string>
@@ -330,7 +320,6 @@
<!--Settings Security and Panic-->
<string name="security_settings_title">Beveiliging</string>
<string name="change_password">Wijzig wachtwoord</string>
<string name="current_password">Huidig wachtwoord</string>
<string name="choose_new_password">Nieuw wachtwoord</string>
<string name="confirm_new_password">Nieuw wachtwoord bevestigen</string>
<string name="password_changed">Wachtwoord is gewijzigd</string>
@@ -351,8 +340,6 @@
<string name="uninstall_setting_summary">Dit vereist een handmatige bevestiging op een paniekmoment</string>
<!--Settings Notifications-->
<string name="notification_settings_title">Meldingen</string>
<string name="notify_sign_in_title">Herinner me om in te loggen</string>
<string name="notify_sign_in_summary">Stuur een herinnering wanneer de telefoon opstart of als de app is bijgewerkt</string>
<string name="notify_private_messages_setting_title">Privéberichten</string>
<string name="notify_private_messages_setting_summary">Toon meldingen voor privéberichten</string>
<string name="notify_private_messages_setting_summary_26">Configureer alarmen voor privéberichten</string>

View File

@@ -65,6 +65,7 @@
<string name="transport_lan">Wi-Fi</string>
<!--Notifications-->
<string name="reminder_notification_title">Wylogowano z Briar</string>
<string name="reminder_notification_text">Dotknij aby zalogować się z powrotem lub przesuń aby pominąć.</string>
<string name="reminder_notification_channel_title">Przypomnienie o zalogowaniu</string>
<string name="ongoing_notification_title">Zalogowany w Briar</string>
<string name="ongoing_notification_text">Dotknij aby otworzyć Briar</string>

View File

@@ -64,9 +64,8 @@
<string name="transport_lan">Wi-Fi</string>
<!--Notifications-->
<string name="reminder_notification_title">Ieșire din Briar</string>
<string name="reminder_notification_text">Atingeți pentru autentificare.</string>
<string name="reminder_notification_text">Atingeți pentru autentificare sau glisați pentru anulare.</string>
<string name="reminder_notification_channel_title">Reamintire autentificare Briar</string>
<string name="reminder_notification_dismiss">Renunță</string>
<string name="ongoing_notification_title">Autentificat în Briar</string>
<string name="ongoing_notification_text">Atingeți pentru a deschide Briar</string>
<plurals name="private_message_notification_text">
@@ -362,8 +361,6 @@
<string name="uninstall_setting_summary">Aceasta necesită o confirmare manuală în timpul unui eveniment de panică</string>
<!--Settings Notifications-->
<string name="notification_settings_title">Notificări</string>
<string name="notify_sign_in_title">Reamintește-mi să mă autentific</string>
<string name="notify_sign_in_summary">Arată o notificare atunci când dispozitivul pornește sau aplicația a fost actualizată</string>
<string name="notify_private_messages_setting_title">Mesaje private</string>
<string name="notify_private_messages_setting_summary">Arată alerte pentru mesajele private</string>
<string name="notify_private_messages_setting_summary_26">Configurare alerte pentru mesajele private</string>

View File

@@ -65,9 +65,8 @@
<string name="transport_lan">Wi-Fi</string>
<!--Notifications-->
<string name="reminder_notification_title">Выход из Briar</string>
<string name="reminder_notification_text">Нажмите, чтобы снова войти.</string>
<string name="reminder_notification_text">Коснитесь, чтобы вернуться или прокрутите, чтобы закрыть.</string>
<string name="reminder_notification_channel_title">Briar Напоминание о входе</string>
<string name="reminder_notification_dismiss">Отклонить</string>
<string name="ongoing_notification_title">Выполнен вход в Briar</string>
<string name="ongoing_notification_text">Коснитесь, чтобы открыть Briar</string>
<plurals name="private_message_notification_text">
@@ -371,8 +370,6 @@
<string name="uninstall_setting_summary">Это потребует вашего подтверждения</string>
<!--Settings Notifications-->
<string name="notification_settings_title">Уведомления</string>
<string name="notify_sign_in_title">Напомнить мне войти</string>
<string name="notify_sign_in_summary">Показывать напоминание при запуске телефона или обновлении приложения.</string>
<string name="notify_private_messages_setting_title">Личные сообщения</string>
<string name="notify_private_messages_setting_summary">Показывать оповещения для личных сообщений</string>
<string name="notify_private_messages_setting_summary_26">Настройка оповещений для личных сообщений</string>

View File

@@ -63,9 +63,8 @@
<string name="transport_lan">Wi-Fi</string>
<!--Notifications-->
<string name="reminder_notification_title">U dol nga Briar-i</string>
<string name="reminder_notification_text">Prekeni që të ribëhet hyrja.</string>
<string name="reminder_notification_text">Që të rifuteni, prekeni, ose fërkojeni për ta hedhur tej.</string>
<string name="reminder_notification_channel_title">Kujtues Hyrjeje Briar</string>
<string name="reminder_notification_dismiss">Hidhe tej</string>
<string name="ongoing_notification_title">Hytë në Briar</string>
<string name="ongoing_notification_text">Prekeni, që të hapet Briar-i</string>
<plurals name="private_message_notification_text">
@@ -351,8 +350,6 @@
<string name="uninstall_setting_summary">Kjo lyp ripohim dorazi, në rast akti paniku</string>
<!--Settings Notifications-->
<string name="notification_settings_title">Njoftime</string>
<string name="notify_sign_in_title">Rikujtomë të bëj hyrjen</string>
<string name="notify_sign_in_summary">Shfaq një kujtues kur niset telefoni ose aplikacioni është përditësuar</string>
<string name="notify_private_messages_setting_title">Mesazhe private</string>
<string name="notify_private_messages_setting_summary">Shfaq sinjalizime për mesazhe private</string>
<string name="notify_private_messages_setting_summary_26">Formësoni sinjalizimet për mesazhe private</string>

View File

@@ -9,7 +9,7 @@
<string name="setup_doze_title">后台连接</string>
<string name="setup_doze_intro">为了收到消息Briar 需要保持后台连接。</string>
<string name="setup_doze_explanation">为了收到消息Briar 需要保持后台连接。请禁用电量优化选项以使 Briar 保持连接。</string>
<string name="setup_doze_button">允许连接</string>
<string name="setup_doze_button">允许连接</string>
<string name="choose_nickname">设置昵称</string>
<string name="choose_password">设置密码</string>
<string name="confirm_password">确认密码</string>
@@ -61,10 +61,6 @@
<string name="transport_bt">蓝牙</string>
<string name="transport_lan">无线局域网</string>
<!--Notifications-->
<string name="reminder_notification_title">退出登录 Briar</string>
<string name="reminder_notification_text">轻按以重新登录。</string>
<string name="reminder_notification_channel_title">Briar 登录提醒</string>
<string name="reminder_notification_dismiss">解散</string>
<string name="ongoing_notification_title">登录 Briar</string>
<string name="ongoing_notification_text">轻触以打开 Briar</string>
<plurals name="private_message_notification_text">
@@ -216,8 +212,6 @@
<plurals name="posts">
<item quantity="other">%d 条帖子</item>
</plurals>
<string name="forum_new_entry_posted">论坛帖子已发布</string>
<string name="forum_new_message_hint">新帖子</string>
<string name="forum_message_reply_hint">新回复</string>
<string name="btn_reply">回复</string>
<string name="forum_leave">退出论坛</string>
@@ -288,7 +282,7 @@
<string name="blogs_rss_feeds_import_button">导入</string>
<string name="blogs_rss_feeds_import_hint">输入 RSS 订阅链接</string>
<string name="blogs_rss_feeds_import_error">抱歉!导入订阅时出错。</string>
<string name="blogs_rss_feeds_manage">管理 RSS 订阅</string>
<string name="blogs_rss_feeds_manage">管理 RSS 订阅</string>
<string name="blogs_rss_feeds_manage_imported">已导入:</string>
<string name="blogs_rss_feeds_manage_author">作者:</string>
<string name="blogs_rss_feeds_manage_updated">最后更新于:</string>
@@ -299,15 +293,6 @@
<string name="blogs_rss_feeds_manage_empty_state">没有订阅内容\n\n点击 + 号导入一个 RSS 信息流</string>
<string name="blogs_rss_feeds_manage_error">加载订阅时出错。请稍候再试。</string>
<!--Settings Display-->
<string name="pref_language_title">语言 &amp; 区域</string>
<string name="pref_language_changed">这些设置会在 Briar 重启后生效。请登出并重启 Briar。</string>
<string name="pref_language_default">系统默认</string>
<string name="display_settings_title">显示</string>
<string name="pref_theme_title">主题</string>
<string name="pref_theme_light">浅色</string>
<string name="pref_theme_dark">深色</string>
<string name="pref_theme_auto">自动(按照时间)</string>
<string name="pref_theme_system">系统默认</string>
<!--Settings Network-->
<string name="network_settings_title">网络</string>
<string name="bluetooth_setting">通过蓝牙连接</string>
@@ -320,9 +305,6 @@
<!--Settings Security and Panic-->
<string name="security_settings_title">安全</string>
<string name="change_password">更改密码</string>
<string name="current_password">当前密码</string>
<string name="choose_new_password">新密码</string>
<string name="confirm_new_password">确认新密码</string>
<string name="password_changed">密码已更改。</string>
<string name="panic_setting">创建应急开关</string>
<string name="panic_setting_title">应急开关</string>
@@ -341,8 +323,6 @@
<string name="uninstall_setting_summary">这需要在紧急事件中进行人工确认</string>
<!--Settings Notifications-->
<string name="notification_settings_title">消息提醒</string>
<string name="notify_sign_in_title">提醒我登录</string>
<string name="notify_sign_in_summary">当手机开机或应用更新时,显示提示</string>
<string name="notify_private_messages_setting_title">私信</string>
<string name="notify_private_messages_setting_summary">显示私信通知</string>
<string name="notify_private_messages_setting_summary_26">配置私聊消息通知</string>

View File

@@ -1,22 +1,20 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<color name="briar_blue">#2D3E50</color>
<color name="briar_blue_dark">#222E3C</color>
<color name="briar_blue_very_dark">#0F1720</color>
<color name="briar_blue_dark">#0F1720</color>
<color name="briar_blue_light">#4F6C8C</color>
<color name="briar_green">#5C940D</color>
<color name="briar_blue_light2">#5a7da3</color>
<color name="briar_green_light">#95D220</color>
<color name="briar_link">#2A93C6</color>
<color name="briar_link">#06B9FF</color>
<color name="window_background">#fffafafa</color>
<color name="card_background">@color/cardview_light_background</color>
<color name="item_background_highlight">#DCDCDC</color>
<color name="action_bar_text">#FFFFFF</color>
<color name="private_message_date_inverse">#e0e0e0</color>
<color name="forum_avatar_shadow">#99000000</color>
<color name="briar_primary">@color/briar_blue</color>
<color name="briar_primary_dark">@color/briar_blue_very_dark</color>
<color name="briar_primary_dark">@color/briar_blue_dark</color>
<color name="briar_accent">@color/briar_blue</color>
@@ -29,10 +27,8 @@
<color name="briar_text_secondary_inverse">#b4ffffff</color>
<color name="briar_text_tertiary_inverse">#80ffffff</color>
<color name="preference_category">@color/briar_blue_light</color>
<color name="preference_category_background">@color/window_background</color>
<color name="briar_button_positive">@color/briar_link</color>
<color name="briar_button_neutral">@color/briar_blue_light</color>
<color name="briar_button_negative">#ff0000</color>
<color name="briar_button_text_disabled">#28000000</color>
<color name="briar_warning_background">#ff0000</color>
@@ -41,4 +37,6 @@
<color name="thread_item_background">#eceff1</color>
<color name="thread_item_highlight">#ffffff</color>
<color name="divider">#c1c1c1</color>
<color name="spinner_border">#61000000</color> <!-- 38% Black -->
</resources>

View File

@@ -69,9 +69,9 @@
<!-- Notifications -->
<string name="reminder_notification_title">Signed out of Briar</string>
<string name="reminder_notification_text">Tap to sign back in.</string>
<string name="reminder_notification_text">Tap to sign back in or swipe to dismiss.</string>
<string name="reminder_notification_channel_title">Briar Sign-in Reminder</string>
<string name="reminder_notification_dismiss">Dismiss</string>
<string name="reminder_notification_do_not_show_again">Don\'t show again</string>
<string name="ongoing_notification_title">Signed into Briar</string>
<string name="ongoing_notification_text">Touch to open Briar.</string>
<plurals name="private_message_notification_text">
@@ -375,7 +375,7 @@
<!-- Settings Notifications -->
<string name="notification_settings_title">Notifications</string>
<string name="notify_sign_in_title">Remind me to sign in</string>
<string name="notify_sign_in_summary">Show a reminder when the phone starts or the app has been updated</string>
<string name="notify_sign_in_summary">Show a reminder when the phone starts or the app got updated</string>
<string name="notify_private_messages_setting_title">Private messages</string>
<string name="notify_private_messages_setting_summary">Show alerts for private messages</string>
<string name="notify_private_messages_setting_summary_26">Configure alerts for private messages</string>

View File

@@ -45,11 +45,6 @@
<item name="android:textSize">@dimen/text_size_medium</item>
</style>
<style name="BriarButtonFlat.Neutral" parent="Widget.AppCompat.Button.Borderless">
<item name="android:textColor">@color/briar_button_neutral</item>
<item name="android:textSize">@dimen/text_size_medium</item>
</style>
<style name="BriarButtonFlat.Positive.Tiny" parent="BriarButtonFlat.Positive">
<item name="android:textSize">@dimen/text_size_tiny</item>
<item name="android:padding">@dimen/margin_medium</item>
@@ -88,7 +83,6 @@
<style name="BriarCard" parent="CardView">
<item name="cardUseCompatPadding">true</item>
<item name="cardBackgroundColor">@color/card_background</item>
<item name="android:layout_margin">@dimen/margin_small</item>
</style>

View File

@@ -6,9 +6,7 @@
<item name="colorPrimaryDark">@color/briar_primary_dark</item>
<item name="colorAccent">@color/briar_accent</item>
<item name="android:textColorLink">@color/briar_text_link</item>
<item name="android:windowBackground">@color/window_background</item>
<item name="android:windowAnimationStyle">@style/ActivityAnimation</item>
<item name="alertDialogTheme">@style/BriarDialogTheme.Neutral</item>
<item name="preferenceTheme">@style/PreferenceThemeOverlay.v14.Material</item>
</style>
@@ -30,10 +28,8 @@
<item name="colorPrimaryDark">@color/briar_primary_dark</item>
<item name="colorAccent">@color/briar_accent</item>
<item name="buttonBarPositiveButtonStyle">@style/BriarButtonFlat.Positive</item>
<item name="buttonBarNeutralButtonStyle">@style/BriarButtonFlat.Neutral</item>
<item name="buttonBarNegativeButtonStyle">@style/BriarButtonFlat.Negative</item>
<item name="android:textColorLink">@color/briar_text_link</item>
<item name="android:windowBackground">@color/window_background</item>
<item name="android:windowAnimationStyle">@style/DialogAnimation</item>
<item name="android:filterTouchesWhenObscured">true</item>
</style>
@@ -43,13 +39,6 @@
<item name="android:filterTouchesWhenObscured">false</item>
</style>
<!-- Uses neutral colors for the buttons -->
<style name="BriarDialogTheme.Neutral" parent="BriarDialogTheme">
<item name="buttonBarPositiveButtonStyle">@style/BriarButtonFlat.Neutral</item>
<item name="buttonBarNeutralButtonStyle">@style/BriarButtonFlat.Neutral</item>
<item name="buttonBarNegativeButtonStyle">@style/BriarButtonFlat.Neutral</item>
</style>
<style name="DialogAnimation" parent="@android:style/Animation.Dialog">
<item name="android:windowEnterAnimation">@anim/fade_in</item>
<item name="android:windowExitAnimation">@anim/fade_out</item>

View File

@@ -23,7 +23,7 @@ public class TestBriarApplication extends Application
Logger.getLogger(TestBriarApplication.class.getName());
private AndroidComponent applicationComponent;
private volatile SharedPreferences prefs;
private SharedPreferences prefs;
@Override
public void onCreate() {

View File

@@ -0,0 +1,368 @@
package org.briarproject.briar.android.account;
import android.app.Application;
import android.content.SharedPreferences;
import android.content.SharedPreferences.Editor;
import org.briarproject.bramble.api.crypto.CryptoComponent;
import org.briarproject.bramble.api.crypto.SecretKey;
import org.briarproject.bramble.api.db.DatabaseConfig;
import org.briarproject.bramble.test.BrambleMockTestCase;
import org.jmock.Expectations;
import org.junit.After;
import org.junit.Test;
import java.io.File;
import java.io.IOException;
import static junit.framework.Assert.assertEquals;
import static junit.framework.Assert.assertFalse;
import static junit.framework.Assert.assertNull;
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.deleteTestDirectory;
import static org.briarproject.bramble.test.TestUtils.getRandomBytes;
import static org.briarproject.bramble.test.TestUtils.getSecretKey;
import static org.briarproject.bramble.test.TestUtils.getTestDirectory;
import static org.briarproject.bramble.util.StringUtils.getRandomString;
import static org.briarproject.bramble.util.StringUtils.toHexString;
import static org.briarproject.briar.android.TestDatabaseKeyUtils.loadDatabaseKey;
import static org.briarproject.briar.android.TestDatabaseKeyUtils.storeDatabaseKey;
import static org.hamcrest.Matchers.samePropertyValuesAs;
public class AndroidAccountManagerImplTest extends BrambleMockTestCase {
private final CryptoComponent cryptoComponent =
context.mock(CryptoComponent.class);
private final SharedPreferences prefs =
context.mock(SharedPreferences.class);
private final DatabaseConfig databaseConfig =
context.mock(DatabaseConfig.class);
private final Editor editor = context.mock(Editor.class);
private final String authorName = getRandomString(MAX_AUTHOR_NAME_LENGTH);
private final String password = "some.strong.pass";
private final String oldPassword = "some.old.pass";
private final String newPassword = "some.new.pass";
private final SecretKey key = getSecretKey();
private final byte[] keyBytes = key.getBytes();
private final byte[] encryptedKey = getRandomBytes(123);
private final String encryptedKeyHex = toHexString(encryptedKey);
private final String oldEncryptedKeyHex = toHexString(getRandomBytes(123));
private final byte[] oldEncryptedKey = getRandomBytes(123);
private final byte[] newEncryptedKey = getRandomBytes(123);
private final File testDir = getTestDirectory();
private final File keyDir = new File(testDir, "key");
private final File keyFile = new File(keyDir, "db.key");
private final File keyBackupFile = new File(keyDir, "db.key.bak");
@Test
public void createAccount() throws IOException {
context.checking(new Expectations() {{
// Generate a database key
oneOf(cryptoComponent).generateSecretKey();
will(returnValue(key));
// Attach the author name and database key to the database config
oneOf(databaseConfig).setEncryptionKey(key);
// Encrypt the key with the password
oneOf(cryptoComponent)
.encryptWithPassword(key.getBytes(), password);
will(returnValue(encryptedKey));
// Store the encrypted key
allowing(databaseConfig).getDatabaseKeyDirectory();
will(returnValue(keyDir));
}});
getAndroidAccountManagerImpl().createAccount(authorName, password);
assertTrue(keyFile.exists());
assertTrue(keyBackupFile.exists());
assertEquals(toHexString(encryptedKey), loadDatabaseKey(keyFile));
assertEquals(toHexString(encryptedKey), loadDatabaseKey(keyBackupFile));
}
@Test
public void testChangePasswordReturnsTrue() throws Exception {
context.checking(new Expectations() {{
// Look up the encrypted DB key
oneOf(prefs).getString("key", null);
will(returnValue(null));
allowing(databaseConfig).getDatabaseKeyDirectory();
will(returnValue(keyDir));
// Decrypt and re-encrypt the key
oneOf(cryptoComponent)
.decryptWithPassword(oldEncryptedKey, oldPassword);
will(returnValue(key.getBytes()));
oneOf(cryptoComponent)
.encryptWithPassword(key.getBytes(), newPassword);
will(returnValue(newEncryptedKey));
}});
assertFalse(keyFile.exists());
assertFalse(keyBackupFile.exists());
storeDatabaseKey(keyFile, toHexString(oldEncryptedKey));
storeDatabaseKey(keyBackupFile, toHexString(oldEncryptedKey));
AndroidAccountManagerImpl accountManager =
getAndroidAccountManagerImpl();
assertTrue(accountManager.changePassword(oldPassword, newPassword));
assertTrue(keyFile.exists());
assertTrue(keyBackupFile.exists());
assertEquals(toHexString(newEncryptedKey), loadDatabaseKey(keyFile));
assertEquals(toHexString(newEncryptedKey),
loadDatabaseKey(keyBackupFile));
}
@Test
public void testChangePasswordReturnsFalseIfOldPasswordIsWrong()
throws Exception {
context.checking(new Expectations() {{
// Look up the encrypted DB key
oneOf(prefs).getString("key", null);
will(returnValue(null));
allowing(databaseConfig).getDatabaseKeyDirectory();
will(returnValue(keyDir));
// Try to decrypt the key - the password is wrong
oneOf(cryptoComponent)
.decryptWithPassword(oldEncryptedKey, oldPassword);
will(returnValue(null));
}});
assertFalse(keyFile.exists());
assertFalse(keyBackupFile.exists());
storeDatabaseKey(keyFile, toHexString(oldEncryptedKey));
storeDatabaseKey(keyBackupFile, toHexString(oldEncryptedKey));
AndroidAccountManagerImpl accountManager =
getAndroidAccountManagerImpl();
assertFalse(accountManager.changePassword(oldPassword, newPassword));
assertTrue(keyFile.exists());
assertTrue(keyBackupFile.exists());
assertEquals(toHexString(oldEncryptedKey), loadDatabaseKey(keyFile));
assertEquals(toHexString(oldEncryptedKey),
loadDatabaseKey(keyBackupFile));
}
@Test
public void testValidatePasswordReturnsTrue() throws Exception {
context.checking(new Expectations() {{
// Look up the encrypted DB key
oneOf(prefs).getString("key", null);
will(returnValue(null));
allowing(databaseConfig).getDatabaseKeyDirectory();
will(returnValue(keyDir));
// Decrypt the key
oneOf(cryptoComponent)
.decryptWithPassword(encryptedKey, password);
will(returnValue(keyBytes));
oneOf(databaseConfig)
.setEncryptionKey(with(samePropertyValuesAs(key)));
}});
assertFalse(keyFile.exists());
assertFalse(keyBackupFile.exists());
storeDatabaseKey(keyFile, toHexString(encryptedKey));
storeDatabaseKey(keyBackupFile, toHexString(encryptedKey));
AndroidAccountManagerImpl accountManager =
getAndroidAccountManagerImpl();
assertTrue(accountManager.validatePassword(password));
}
@Test
public void testValidatePasswordReturnsFalseIfPasswordIsWrong()
throws Exception {
context.checking(new Expectations() {{
// Look up the encrypted DB key
oneOf(prefs).getString("key", null);
will(returnValue(null));
allowing(databaseConfig).getDatabaseKeyDirectory();
will(returnValue(keyDir));
// Decrypt the key
oneOf(cryptoComponent)
.decryptWithPassword(encryptedKey, password);
will(returnValue(null));
}});
assertFalse(keyFile.exists());
assertFalse(keyBackupFile.exists());
storeDatabaseKey(keyFile, toHexString(encryptedKey));
storeDatabaseKey(keyBackupFile, toHexString(encryptedKey));
AndroidAccountManagerImpl accountManager =
getAndroidAccountManagerImpl();
assertFalse(accountManager.validatePassword(password));
}
@Test
public void testDbKeyIsMigratedFromPreferencesToFile() throws Exception {
context.checking(new Expectations() {{
oneOf(prefs).getString("key", null);
will(returnValue(encryptedKeyHex));
allowing(databaseConfig).getDatabaseKeyDirectory();
will(returnValue(keyDir));
oneOf(prefs).edit();
will(returnValue(editor));
oneOf(editor).remove("key");
will(returnValue(editor));
oneOf(editor).commit();
will(returnValue(true));
}});
assertFalse(keyFile.exists());
assertFalse(keyBackupFile.exists());
AndroidAccountManagerImpl c = getAndroidAccountManagerImpl();
assertEquals(encryptedKeyHex, c.getEncryptedDatabaseKey());
assertTrue(keyFile.exists());
assertTrue(keyBackupFile.exists());
assertEquals(encryptedKeyHex, loadDatabaseKey(keyFile));
assertEquals(encryptedKeyHex, loadDatabaseKey(keyBackupFile));
}
@Test
public void testDbKeyIsLoadedFromPrimaryFile() throws Exception {
context.checking(new Expectations() {{
oneOf(prefs).getString("key", null);
will(returnValue(null));
allowing(databaseConfig).getDatabaseKeyDirectory();
will(returnValue(keyDir));
}});
assertFalse(keyFile.exists());
assertFalse(keyBackupFile.exists());
storeDatabaseKey(keyFile, encryptedKeyHex);
assertTrue(keyFile.exists());
assertFalse(keyBackupFile.exists());
assertEquals(encryptedKeyHex, loadDatabaseKey(keyFile));
AndroidAccountManagerImpl c = getAndroidAccountManagerImpl();
assertEquals(encryptedKeyHex, c.getEncryptedDatabaseKey());
assertTrue(keyFile.exists());
assertFalse(keyBackupFile.exists());
assertEquals(encryptedKeyHex, loadDatabaseKey(keyFile));
}
@Test
public void testDbKeyIsLoadedFromBackupFile() throws Exception {
context.checking(new Expectations() {{
oneOf(prefs).getString("key", null);
will(returnValue(null));
allowing(databaseConfig).getDatabaseKeyDirectory();
will(returnValue(keyDir));
}});
assertFalse(keyFile.exists());
assertFalse(keyBackupFile.exists());
storeDatabaseKey(keyBackupFile, encryptedKeyHex);
assertFalse(keyFile.exists());
assertTrue(keyBackupFile.exists());
assertEquals(encryptedKeyHex, loadDatabaseKey(keyBackupFile));
AndroidAccountManagerImpl c = getAndroidAccountManagerImpl();
assertEquals(encryptedKeyHex, c.getEncryptedDatabaseKey());
assertFalse(keyFile.exists());
assertTrue(keyBackupFile.exists());
assertEquals(encryptedKeyHex, loadDatabaseKey(keyBackupFile));
}
@Test
public void testDbKeyIsNullIfNotFound() {
context.checking(new Expectations() {{
oneOf(prefs).getString("key", null);
will(returnValue(null));
allowing(databaseConfig).getDatabaseKeyDirectory();
will(returnValue(keyDir));
}});
assertFalse(keyFile.exists());
assertFalse(keyBackupFile.exists());
AndroidAccountManagerImpl c = getAndroidAccountManagerImpl();
assertNull(c.getEncryptedDatabaseKey());
assertFalse(keyFile.exists());
assertFalse(keyBackupFile.exists());
}
@Test
public void testStoringDbKeyOverwritesPrimary() throws Exception {
context.checking(new Expectations() {{
allowing(databaseConfig).getDatabaseKeyDirectory();
will(returnValue(keyDir));
}});
assertFalse(keyFile.exists());
assertFalse(keyBackupFile.exists());
storeDatabaseKey(keyFile, oldEncryptedKeyHex);
assertTrue(keyFile.exists());
assertFalse(keyBackupFile.exists());
assertEquals(oldEncryptedKeyHex, loadDatabaseKey(keyFile));
AndroidAccountManagerImpl c = getAndroidAccountManagerImpl();
assertTrue(c.storeEncryptedDatabaseKey(encryptedKeyHex));
assertTrue(keyFile.exists());
assertTrue(keyBackupFile.exists());
assertEquals(encryptedKeyHex, loadDatabaseKey(keyFile));
assertEquals(encryptedKeyHex, loadDatabaseKey(keyBackupFile));
}
@Test
public void testStoringDbKeyOverwritesBackup() throws Exception {
context.checking(new Expectations() {{
allowing(databaseConfig).getDatabaseKeyDirectory();
will(returnValue(keyDir));
}});
assertFalse(keyFile.exists());
assertFalse(keyBackupFile.exists());
storeDatabaseKey(keyBackupFile, oldEncryptedKeyHex);
assertFalse(keyFile.exists());
assertTrue(keyBackupFile.exists());
assertEquals(oldEncryptedKeyHex, loadDatabaseKey(keyBackupFile));
AndroidAccountManagerImpl c = getAndroidAccountManagerImpl();
assertTrue(c.storeEncryptedDatabaseKey(encryptedKeyHex));
assertTrue(keyFile.exists());
assertTrue(keyBackupFile.exists());
assertEquals(encryptedKeyHex, loadDatabaseKey(keyFile));
assertEquals(encryptedKeyHex, loadDatabaseKey(keyBackupFile));
}
@After
public void tearDown() {
deleteTestDirectory(testDir);
}
private AndroidAccountManagerImpl getAndroidAccountManagerImpl() {
// app is only needed for deleting account
Application app = null;
//noinspection ConstantConditions
return new AndroidAccountManagerImpl(cryptoComponent, databaseConfig,
app, prefs);
}
}

View File

@@ -1,4 +1,4 @@
package org.briarproject.briar.android.login;
package org.briarproject.briar.android.account;
import android.support.design.widget.TextInputLayout;
import android.view.View;
@@ -7,6 +7,7 @@ import android.widget.EditText;
import org.briarproject.briar.R;
import org.briarproject.briar.android.TestBriarApplication;
import org.briarproject.briar.android.login.StrengthMeter;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;

View File

@@ -1,10 +1,11 @@
package org.briarproject.briar.android.login;
package org.briarproject.briar.android.account;
import android.support.design.widget.TextInputLayout;
import android.widget.EditText;
import org.briarproject.briar.R;
import org.briarproject.briar.android.TestBriarApplication;
import org.briarproject.briar.android.account.SetupActivity;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;

View File

@@ -1,11 +1,10 @@
package org.briarproject.briar.android.login;
package org.briarproject.briar.android.account;
import android.content.SharedPreferences;
import android.content.pm.ApplicationInfo;
import org.briarproject.bramble.api.account.AccountManager;
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;
@@ -18,22 +17,17 @@ import java.io.File;
import java.util.concurrent.Executor;
import java.util.concurrent.atomic.AtomicBoolean;
import static junit.framework.Assert.assertEquals;
import static junit.framework.Assert.assertFalse;
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.deleteTestDirectory;
import static org.briarproject.bramble.test.TestUtils.getRandomBytes;
import static org.briarproject.bramble.test.TestUtils.getSecretKey;
import static org.briarproject.bramble.test.TestUtils.getTestDirectory;
import static org.briarproject.bramble.util.StringUtils.getRandomString;
import static org.briarproject.bramble.util.StringUtils.toHexString;
import static org.briarproject.briar.android.TestDatabaseKeyUtils.loadDatabaseKey;
public class SetupControllerImplTest extends BrambleMockTestCase {
private final SharedPreferences briarPrefs =
context.mock(SharedPreferences.class);
private final AccountManager accountManager =
context.mock(AccountManager.class);
private final DatabaseConfig databaseConfig =
context.mock(DatabaseConfig.class);
private final CryptoComponent crypto = context.mock(CryptoComponent.class);
@@ -45,8 +39,6 @@ public class SetupControllerImplTest extends BrambleMockTestCase {
private final String authorName = getRandomString(MAX_AUTHOR_NAME_LENGTH);
private final String password = "some.strong.pass";
private final byte[] encryptedKey = getRandomBytes(123);
private final SecretKey key = getSecretKey();
private final File testDir = getTestDirectory();
private final File keyDir = new File(testDir, "key");
private final File keyFile = new File(keyDir, "db.key");
@@ -74,25 +66,15 @@ public class SetupControllerImplTest extends BrambleMockTestCase {
will(returnValue(authorName));
oneOf(setupActivity).getPassword();
will(returnValue(password));
// 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(encryptedKey));
// Store the encrypted key
allowing(databaseConfig).getDatabaseKeyDirectory();
will(returnValue(keyDir));
oneOf(accountManager).createAccount(authorName, password);
}});
assertFalse(keyFile.exists());
assertFalse(keyBackupFile.exists());
SetupControllerImpl s = new SetupControllerImpl(briarPrefs,
databaseConfig, cryptoExecutor, crypto, estimator);
SetupControllerImpl s =
new SetupControllerImpl(accountManager, cryptoExecutor, crypto,
estimator);
s.setSetupActivity(setupActivity);
AtomicBoolean called = new AtomicBoolean(false);
@@ -100,11 +82,6 @@ public class SetupControllerImplTest extends BrambleMockTestCase {
s.setPassword(password);
s.createAccount(result -> called.set(true));
assertTrue(called.get());
assertTrue(keyFile.exists());
assertTrue(keyBackupFile.exists());
assertEquals(toHexString(encryptedKey), loadDatabaseKey(keyFile));
assertEquals(toHexString(encryptedKey), loadDatabaseKey(keyBackupFile));
}
@After

View File

@@ -1,205 +0,0 @@
package org.briarproject.briar.android.controller;
import android.content.SharedPreferences;
import android.content.SharedPreferences.Editor;
import org.briarproject.bramble.api.db.DatabaseConfig;
import org.briarproject.bramble.test.BrambleMockTestCase;
import org.jmock.Expectations;
import org.junit.After;
import org.junit.Test;
import java.io.File;
import static junit.framework.Assert.assertEquals;
import static junit.framework.Assert.assertFalse;
import static junit.framework.Assert.assertNull;
import static junit.framework.Assert.assertTrue;
import static org.briarproject.bramble.test.TestUtils.deleteTestDirectory;
import static org.briarproject.bramble.test.TestUtils.getRandomBytes;
import static org.briarproject.bramble.test.TestUtils.getTestDirectory;
import static org.briarproject.bramble.util.StringUtils.toHexString;
import static org.briarproject.briar.android.TestDatabaseKeyUtils.loadDatabaseKey;
import static org.briarproject.briar.android.TestDatabaseKeyUtils.storeDatabaseKey;
public class ConfigControllerImplTest extends BrambleMockTestCase {
private final SharedPreferences prefs =
context.mock(SharedPreferences.class);
private final DatabaseConfig databaseConfig =
context.mock(DatabaseConfig.class);
private final Editor editor = context.mock(Editor.class);
private final byte[] encryptedKey = getRandomBytes(123);
private final String encryptedKeyHex = toHexString(encryptedKey);
private final String oldEncryptedKeyHex = toHexString(getRandomBytes(123));
private final File testDir = getTestDirectory();
private final File keyDir = new File(testDir, "key");
private final File keyFile = new File(keyDir, "db.key");
private final File keyBackupFile = new File(keyDir, "db.key.bak");
@Test
public void testDbKeyIsMigratedFromPreferencesToFile() throws Exception {
context.checking(new Expectations() {{
oneOf(prefs).getString("key", null);
will(returnValue(encryptedKeyHex));
allowing(databaseConfig).getDatabaseKeyDirectory();
will(returnValue(keyDir));
oneOf(prefs).edit();
will(returnValue(editor));
oneOf(editor).remove("key");
will(returnValue(editor));
oneOf(editor).commit();
will(returnValue(true));
}});
assertFalse(keyFile.exists());
assertFalse(keyBackupFile.exists());
ConfigControllerImpl c = new ConfigControllerImpl(prefs,
databaseConfig);
assertEquals(encryptedKeyHex, c.getEncryptedDatabaseKey());
assertTrue(keyFile.exists());
assertTrue(keyBackupFile.exists());
assertEquals(encryptedKeyHex, loadDatabaseKey(keyFile));
assertEquals(encryptedKeyHex, loadDatabaseKey(keyBackupFile));
}
@Test
public void testDbKeyIsLoadedFromPrimaryFile() throws Exception {
context.checking(new Expectations() {{
oneOf(prefs).getString("key", null);
will(returnValue(null));
allowing(databaseConfig).getDatabaseKeyDirectory();
will(returnValue(keyDir));
}});
assertFalse(keyFile.exists());
assertFalse(keyBackupFile.exists());
storeDatabaseKey(keyFile, encryptedKeyHex);
assertTrue(keyFile.exists());
assertFalse(keyBackupFile.exists());
assertEquals(encryptedKeyHex, loadDatabaseKey(keyFile));
ConfigControllerImpl c = new ConfigControllerImpl(prefs,
databaseConfig);
assertEquals(encryptedKeyHex, c.getEncryptedDatabaseKey());
assertTrue(keyFile.exists());
assertFalse(keyBackupFile.exists());
assertEquals(encryptedKeyHex, loadDatabaseKey(keyFile));
}
@Test
public void testDbKeyIsLoadedFromBackupFile() throws Exception {
context.checking(new Expectations() {{
oneOf(prefs).getString("key", null);
will(returnValue(null));
allowing(databaseConfig).getDatabaseKeyDirectory();
will(returnValue(keyDir));
}});
assertFalse(keyFile.exists());
assertFalse(keyBackupFile.exists());
storeDatabaseKey(keyBackupFile, encryptedKeyHex);
assertFalse(keyFile.exists());
assertTrue(keyBackupFile.exists());
assertEquals(encryptedKeyHex, loadDatabaseKey(keyBackupFile));
ConfigControllerImpl c = new ConfigControllerImpl(prefs,
databaseConfig);
assertEquals(encryptedKeyHex, c.getEncryptedDatabaseKey());
assertFalse(keyFile.exists());
assertTrue(keyBackupFile.exists());
assertEquals(encryptedKeyHex, loadDatabaseKey(keyBackupFile));
}
@Test
public void testDbKeyIsNullIfNotFound() {
context.checking(new Expectations() {{
oneOf(prefs).getString("key", null);
will(returnValue(null));
allowing(databaseConfig).getDatabaseKeyDirectory();
will(returnValue(keyDir));
}});
assertFalse(keyFile.exists());
assertFalse(keyBackupFile.exists());
ConfigControllerImpl c = new ConfigControllerImpl(prefs,
databaseConfig);
assertNull(c.getEncryptedDatabaseKey());
assertFalse(keyFile.exists());
assertFalse(keyBackupFile.exists());
}
@Test
public void testStoringDbKeyOverwritesPrimary() throws Exception {
context.checking(new Expectations() {{
allowing(databaseConfig).getDatabaseKeyDirectory();
will(returnValue(keyDir));
}});
assertFalse(keyFile.exists());
assertFalse(keyBackupFile.exists());
storeDatabaseKey(keyFile, oldEncryptedKeyHex);
assertTrue(keyFile.exists());
assertFalse(keyBackupFile.exists());
assertEquals(oldEncryptedKeyHex, loadDatabaseKey(keyFile));
ConfigController c = new ConfigControllerImpl(prefs,
databaseConfig);
assertTrue(c.storeEncryptedDatabaseKey(encryptedKeyHex));
assertTrue(keyFile.exists());
assertTrue(keyBackupFile.exists());
assertEquals(encryptedKeyHex, loadDatabaseKey(keyFile));
assertEquals(encryptedKeyHex, loadDatabaseKey(keyBackupFile));
}
@Test
public void testStoringDbKeyOverwritesBackup() throws Exception {
context.checking(new Expectations() {{
allowing(databaseConfig).getDatabaseKeyDirectory();
will(returnValue(keyDir));
}});
assertFalse(keyFile.exists());
assertFalse(keyBackupFile.exists());
storeDatabaseKey(keyBackupFile, oldEncryptedKeyHex);
assertFalse(keyFile.exists());
assertTrue(keyBackupFile.exists());
assertEquals(oldEncryptedKeyHex, loadDatabaseKey(keyBackupFile));
ConfigController c = new ConfigControllerImpl(prefs,
databaseConfig);
assertTrue(c.storeEncryptedDatabaseKey(encryptedKeyHex));
assertTrue(keyFile.exists());
assertTrue(keyBackupFile.exists());
assertEquals(encryptedKeyHex, loadDatabaseKey(keyFile));
assertEquals(encryptedKeyHex, loadDatabaseKey(keyBackupFile));
}
@After
public void tearDown() {
deleteTestDirectory(testDir);
}
}

View File

@@ -45,7 +45,7 @@ public class TestForumActivity extends ForumActivity {
protected BriarController provideBriarController(
BriarControllerImpl briarController) {
BriarController c = Mockito.mock(BriarController.class);
Mockito.when(c.hasEncryptionKey()).thenReturn(true);
Mockito.when(c.signedIn()).thenReturn(true);
return c;
}

View File

@@ -1,37 +1,23 @@
package org.briarproject.briar.android.login;
import android.content.SharedPreferences;
import org.briarproject.bramble.api.account.AccountManager;
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.jmock.Expectations;
import org.junit.After;
import org.junit.Test;
import java.io.File;
import java.util.concurrent.Executor;
import java.util.concurrent.atomic.AtomicBoolean;
import static junit.framework.Assert.assertEquals;
import static junit.framework.Assert.assertFalse;
import static junit.framework.Assert.assertTrue;
import static org.briarproject.bramble.test.TestUtils.deleteTestDirectory;
import static org.briarproject.bramble.test.TestUtils.getRandomBytes;
import static org.briarproject.bramble.test.TestUtils.getSecretKey;
import static org.briarproject.bramble.test.TestUtils.getTestDirectory;
import static org.briarproject.bramble.util.StringUtils.toHexString;
import static org.briarproject.briar.android.TestDatabaseKeyUtils.loadDatabaseKey;
import static org.briarproject.briar.android.TestDatabaseKeyUtils.storeDatabaseKey;
public class PasswordControllerImplTest extends BrambleMockTestCase {
private final SharedPreferences briarPrefs =
context.mock(SharedPreferences.class);
private final DatabaseConfig databaseConfig =
context.mock(DatabaseConfig.class);
private final AccountManager accountManager =
context.mock(AccountManager.class);
private final CryptoComponent crypto = context.mock(CryptoComponent.class);
private final PasswordStrengthEstimator estimator =
context.mock(PasswordStrengthEstimator.class);
@@ -40,85 +26,37 @@ public class PasswordControllerImplTest extends BrambleMockTestCase {
private final String oldPassword = "some.old.pass";
private final String newPassword = "some.new.pass";
private final byte[] oldEncryptedKey = getRandomBytes(123);
private final byte[] newEncryptedKey = getRandomBytes(123);
private final byte[] key = getSecretKey().getBytes();
private final File testDir = getTestDirectory();
private final File keyDir = new File(testDir, "key");
private final File keyFile = new File(keyDir, "db.key");
private final File keyBackupFile = new File(keyDir, "db.key.bak");
@Test
public void testChangePasswordReturnsTrue() throws Exception {
public void testChangePasswordReturnsTrue() {
context.checking(new Expectations() {{
// Look up the encrypted DB key
oneOf(briarPrefs).getString("key", null);
will(returnValue(null));
allowing(databaseConfig).getDatabaseKeyDirectory();
will(returnValue(keyDir));
// Decrypt and re-encrypt the key
oneOf(crypto).decryptWithPassword(oldEncryptedKey, oldPassword);
will(returnValue(key));
oneOf(crypto).encryptWithPassword(key, newPassword);
will(returnValue(newEncryptedKey));
oneOf(accountManager).changePassword(oldPassword, newPassword);
will(returnValue(true));
}});
assertFalse(keyFile.exists());
assertFalse(keyBackupFile.exists());
storeDatabaseKey(keyFile, toHexString(oldEncryptedKey));
storeDatabaseKey(keyBackupFile, toHexString(oldEncryptedKey));
PasswordControllerImpl p = new PasswordControllerImpl(briarPrefs,
databaseConfig, cryptoExecutor, crypto, estimator);
PasswordControllerImpl p =
new PasswordControllerImpl(accountManager, cryptoExecutor,
crypto, estimator);
AtomicBoolean capturedResult = new AtomicBoolean(false);
p.changePassword(oldPassword, newPassword, capturedResult::set);
assertTrue(capturedResult.get());
assertTrue(keyFile.exists());
assertTrue(keyBackupFile.exists());
assertEquals(toHexString(newEncryptedKey), loadDatabaseKey(keyFile));
assertEquals(toHexString(newEncryptedKey),
loadDatabaseKey(keyBackupFile));
}
@Test
public void testChangePasswordReturnsFalseIfOldPasswordIsWrong()
throws Exception {
public void testChangePasswordReturnsFalseIfOldPasswordIsWrong() {
context.checking(new Expectations() {{
// Look up the encrypted DB key
oneOf(briarPrefs).getString("key", null);
will(returnValue(null));
allowing(databaseConfig).getDatabaseKeyDirectory();
will(returnValue(keyDir));
// Try to decrypt the key - the password is wrong
oneOf(crypto).decryptWithPassword(oldEncryptedKey, oldPassword);
will(returnValue(null));
oneOf(accountManager).changePassword(oldPassword, newPassword);
will(returnValue(false));
}});
assertFalse(keyFile.exists());
assertFalse(keyBackupFile.exists());
storeDatabaseKey(keyFile, toHexString(oldEncryptedKey));
storeDatabaseKey(keyBackupFile, toHexString(oldEncryptedKey));
PasswordControllerImpl p = new PasswordControllerImpl(briarPrefs,
databaseConfig, cryptoExecutor, crypto, estimator);
PasswordControllerImpl p =
new PasswordControllerImpl(accountManager, cryptoExecutor,
crypto, estimator);
AtomicBoolean capturedResult = new AtomicBoolean(true);
p.changePassword(oldPassword, newPassword, capturedResult::set);
assertFalse(capturedResult.get());
assertTrue(keyFile.exists());
assertTrue(keyBackupFile.exists());
assertEquals(toHexString(oldEncryptedKey), loadDatabaseKey(keyFile));
assertEquals(toHexString(oldEncryptedKey),
loadDatabaseKey(keyBackupFile));
}
@After
public void tearDown() {
deleteTestDirectory(testDir);
}
}