Merge remote-tracking branch 'origin/master' into 2329-translations-for-trust-indicator-view-trust-levels

This commit is contained in:
johndoe4221
2022-06-15 12:19:24 +02:00
14 changed files with 302 additions and 41 deletions

View File

@@ -35,6 +35,9 @@ public interface MailboxSettingsManager {
void recordSuccessfulConnection(Transaction txn, long now)
throws DbException;
void recordSuccessfulConnection(Transaction txn, long now,
List<MailboxVersion> versions) throws DbException;
void recordFailedConnectionAttempt(Transaction txn, long now)
throws DbException;

View File

@@ -9,10 +9,12 @@ import org.briarproject.bramble.api.mailbox.MailboxPairingTask;
import org.briarproject.bramble.api.mailbox.MailboxProperties;
import org.briarproject.bramble.api.mailbox.MailboxSettingsManager;
import org.briarproject.bramble.api.mailbox.MailboxStatus;
import org.briarproject.bramble.api.mailbox.MailboxVersion;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import org.briarproject.bramble.api.system.Clock;
import java.io.IOException;
import java.util.List;
import java.util.concurrent.Executor;
import java.util.logging.Logger;
@@ -98,34 +100,35 @@ class MailboxManagerImpl implements MailboxManager {
@Override
public boolean checkConnection() {
boolean success;
List<MailboxVersion> versions = null;
try {
MailboxProperties props = db.transactionWithNullableResult(true,
mailboxSettingsManager::getOwnMailboxProperties);
if (props == null) throw new DbException();
success = api.checkStatus(props);
versions = api.getServerSupports(props);
} catch (DbException e) {
logException(LOG, WARNING, e);
// we don't treat this is a failure to record
return false;
} catch (IOException | MailboxApi.ApiException e) {
// we record this as a failure
success = false;
logException(LOG, WARNING, e);
}
try {
recordCheckResult(success);
recordCheckResult(versions);
} catch (DbException e) {
logException(LOG, WARNING, e);
}
return success;
return versions != null;
}
private void recordCheckResult(boolean success) throws DbException {
private void recordCheckResult(@Nullable List<MailboxVersion> versions)
throws DbException {
long now = clock.currentTimeMillis();
db.transaction(false, txn -> {
if (success) {
mailboxSettingsManager.recordSuccessfulConnection(txn, now);
if (versions != null) {
mailboxSettingsManager
.recordSuccessfulConnection(txn, now, versions);
} else {
mailboxSettingsManager.recordFailedConnectionAttempt(txn, now);
}

View File

@@ -77,13 +77,7 @@ class MailboxSettingsManagerImpl implements MailboxSettingsManager {
s.put(SETTINGS_KEY_ONION, p.getBaseUrl());
s.put(SETTINGS_KEY_TOKEN, p.getAuthToken().toString());
List<MailboxVersion> serverSupports = p.getServerSupports();
int[] ints = new int[serverSupports.size() * 2];
int i = 0;
for (MailboxVersion v : serverSupports) {
ints[i++] = v.getMajor();
ints[i++] = v.getMinor();
}
s.putIntArray(SETTINGS_KEY_SERVER_SUPPORTS, ints);
encodeServerSupports(serverSupports, s);
settingsManager.mergeSettings(txn, s, SETTINGS_NAMESPACE);
for (MailboxHook hook : hooks) {
hook.mailboxPaired(txn, p.getOnion(), p.getServerSupports());
@@ -121,14 +115,30 @@ class MailboxSettingsManagerImpl implements MailboxSettingsManager {
@Override
public void recordSuccessfulConnection(Transaction txn, long now)
throws DbException {
Settings oldSettings =
settingsManager.getSettings(txn, SETTINGS_NAMESPACE);
recordSuccessfulConnection(txn, now, null);
}
@Override
public void recordSuccessfulConnection(Transaction txn, long now,
@Nullable List<MailboxVersion> versions) throws DbException {
Settings s = new Settings();
// fetch version that the server supports first
List<MailboxVersion> serverSupports;
if (versions == null) {
Settings oldSettings =
settingsManager.getSettings(txn, SETTINGS_NAMESPACE);
serverSupports = parseServerSupports(oldSettings);
} else {
serverSupports = versions;
// store new versions
encodeServerSupports(serverSupports, s);
}
// now record the successful connection
s.putLong(SETTINGS_KEY_LAST_ATTEMPT, now);
s.putLong(SETTINGS_KEY_LAST_SUCCESS, now);
s.putInt(SETTINGS_KEY_ATTEMPTS, 0);
settingsManager.mergeSettings(txn, s, SETTINGS_NAMESPACE);
List<MailboxVersion> serverSupports = parseServerSupports(oldSettings);
// broadcast status event
MailboxStatus status = new MailboxStatus(now, now, 0, serverSupports);
txn.attach(new OwnMailboxConnectionStatusEvent(status));
}
@@ -171,6 +181,17 @@ class MailboxSettingsManagerImpl implements MailboxSettingsManager {
return filename;
}
private void encodeServerSupports(List<MailboxVersion> serverSupports,
Settings s) {
int[] ints = new int[serverSupports.size() * 2];
int i = 0;
for (MailboxVersion v : serverSupports) {
ints[i++] = v.getMajor();
ints[i++] = v.getMinor();
}
s.putIntArray(SETTINGS_KEY_SERVER_SUPPORTS, ints);
}
private List<MailboxVersion> parseServerSupports(Settings s)
throws DbException {
if (!s.containsKey(SETTINGS_KEY_SERVER_SUPPORTS)) return emptyList();

View File

@@ -0,0 +1,128 @@
package org.briarproject.bramble.mailbox;
import org.briarproject.bramble.api.db.DbException;
import org.briarproject.bramble.api.db.Transaction;
import org.briarproject.bramble.api.db.TransactionManager;
import org.briarproject.bramble.api.mailbox.MailboxProperties;
import org.briarproject.bramble.api.mailbox.MailboxSettingsManager;
import org.briarproject.bramble.api.mailbox.event.OwnMailboxConnectionStatusEvent;
import org.briarproject.bramble.api.system.Clock;
import org.briarproject.bramble.test.BrambleMockTestCase;
import org.briarproject.bramble.test.DbExpectations;
import org.junit.Test;
import java.io.IOException;
import java.util.Random;
import java.util.concurrent.Executor;
import static org.briarproject.bramble.api.mailbox.MailboxConstants.CLIENT_SUPPORTS;
import static org.briarproject.bramble.test.TestUtils.getMailboxProperties;
import static org.briarproject.bramble.test.TestUtils.hasEvent;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
public class MailboxManagerImplTest extends BrambleMockTestCase {
private final Executor ioExecutor = context.mock(Executor.class);
private final MailboxApi api = context.mock(MailboxApi.class);
private final TransactionManager db =
context.mock(TransactionManager.class);
private final MailboxSettingsManager mailboxSettingsManager =
context.mock(MailboxSettingsManager.class);
private final MailboxPairingTaskFactory pairingTaskFactory =
context.mock(MailboxPairingTaskFactory.class);
private final Clock clock =
context.mock(Clock.class);
private final MailboxManagerImpl manager = new MailboxManagerImpl(
ioExecutor, api, db, mailboxSettingsManager, pairingTaskFactory,
clock);
@Test
public void testDbExceptionDoesNotRecordFailure() throws Exception {
Transaction txn = new Transaction(null, true);
context.checking(new DbExpectations() {{
oneOf(db).transactionWithNullableResult(with(true),
withNullableDbCallable(txn));
oneOf(mailboxSettingsManager).getOwnMailboxProperties(txn);
will(throwException(new DbException()));
}});
assertFalse(manager.checkConnection());
assertFalse(hasEvent(txn, OwnMailboxConnectionStatusEvent.class));
}
@Test
public void testIOExceptionDoesRecordFailure() throws Exception {
Transaction txn = new Transaction(null, true);
Transaction txn2 = new Transaction(null, false);
MailboxProperties props = getMailboxProperties(true, CLIENT_SUPPORTS);
long now = new Random().nextLong();
context.checking(new DbExpectations() {{
oneOf(db).transactionWithNullableResult(with(true),
withNullableDbCallable(txn));
oneOf(mailboxSettingsManager).getOwnMailboxProperties(txn);
will(returnValue(props));
oneOf(api).getServerSupports(props);
will(throwException(new IOException()));
oneOf(clock).currentTimeMillis();
will(returnValue(now));
oneOf(db).transaction(with(false), withDbRunnable(txn2));
oneOf(mailboxSettingsManager)
.recordFailedConnectionAttempt(txn2, now);
}});
assertFalse(manager.checkConnection());
}
@Test
public void testApiExceptionDoesRecordFailure() throws Exception {
Transaction txn = new Transaction(null, true);
Transaction txn2 = new Transaction(null, false);
MailboxProperties props = getMailboxProperties(true, CLIENT_SUPPORTS);
long now = new Random().nextLong();
context.checking(new DbExpectations() {{
oneOf(db).transactionWithNullableResult(with(true),
withNullableDbCallable(txn));
oneOf(mailboxSettingsManager).getOwnMailboxProperties(txn);
will(returnValue(props));
oneOf(api).getServerSupports(props);
will(throwException(new MailboxApi.ApiException()));
oneOf(clock).currentTimeMillis();
will(returnValue(now));
oneOf(db).transaction(with(false), withDbRunnable(txn2));
oneOf(mailboxSettingsManager)
.recordFailedConnectionAttempt(txn2, now);
}});
assertFalse(manager.checkConnection());
}
@Test
public void testConnectionSuccess() throws Exception {
Transaction txn = new Transaction(null, true);
Transaction txn2 = new Transaction(null, false);
MailboxProperties props = getMailboxProperties(true, CLIENT_SUPPORTS);
long now = new Random().nextLong();
context.checking(new DbExpectations() {{
oneOf(db).transactionWithNullableResult(with(true),
withNullableDbCallable(txn));
oneOf(mailboxSettingsManager).getOwnMailboxProperties(txn);
will(returnValue(props));
oneOf(api).getServerSupports(props);
will(returnValue(CLIENT_SUPPORTS));
oneOf(clock).currentTimeMillis();
will(returnValue(now));
oneOf(db).transaction(with(false), withDbRunnable(txn2));
oneOf(mailboxSettingsManager)
.recordSuccessfulConnection(txn2, now, CLIENT_SUPPORTS);
}});
assertTrue(manager.checkConnection());
}
}

View File

@@ -18,6 +18,7 @@ import java.util.List;
import java.util.Random;
import static java.util.Arrays.asList;
import static java.util.Collections.singletonList;
import static org.briarproject.bramble.mailbox.MailboxSettingsManagerImpl.SETTINGS_KEY_ATTEMPTS;
import static org.briarproject.bramble.mailbox.MailboxSettingsManagerImpl.SETTINGS_KEY_LAST_ATTEMPT;
import static org.briarproject.bramble.mailbox.MailboxSettingsManagerImpl.SETTINGS_KEY_LAST_SUCCESS;
@@ -165,6 +166,28 @@ public class MailboxSettingsManagerImplTest extends BrambleMockTestCase {
hasEvent(txn, OwnMailboxConnectionStatusEvent.class);
}
@Test
public void testRecordsSuccessWithVersions() throws Exception {
Transaction txn = new Transaction(null, false);
List<MailboxVersion> versions = singletonList(new MailboxVersion(2, 1));
Settings expectedSettings = new Settings();
expectedSettings.putLong(SETTINGS_KEY_LAST_ATTEMPT, now);
expectedSettings.putLong(SETTINGS_KEY_LAST_SUCCESS, now);
expectedSettings.putInt(SETTINGS_KEY_ATTEMPTS, 0);
expectedSettings.putInt(SETTINGS_KEY_SERVER_SUPPORTS, 0);
int[] newVersionsInts = {2, 1};
expectedSettings
.putIntArray(SETTINGS_KEY_SERVER_SUPPORTS, newVersionsInts);
context.checking(new Expectations() {{
oneOf(settingsManager).mergeSettings(txn, expectedSettings,
SETTINGS_NAMESPACE);
}});
manager.recordSuccessfulConnection(txn, now, versions);
hasEvent(txn, OwnMailboxConnectionStatusEvent.class);
}
@Test
public void testRecordsFailureOnFirstAttempt() throws Exception {
testRecordsFailure(new Settings(), 0);

View File

@@ -100,7 +100,7 @@ dependencies {
implementation project(path: ':briar-core', configuration: 'default')
implementation project(path: ':bramble-core', configuration: 'default')
implementation project(':bramble-android')
implementation 'org.briarproject:dont-kill-me-lib:0.2.2'
implementation 'org.briarproject:dont-kill-me-lib:0.2.5'
implementation 'androidx.fragment:fragment:1.3.4'
implementation 'androidx.preference:preference:1.1.1'

View File

@@ -493,9 +493,6 @@
<queries>
<package android:name="info.guardianproject.ripple" />
<package android:name="com.huawei.systemmanager" />
<package android:name="com.huawei.powergenie" />
<package android:name="com.evenwell.PowerMonitor" />
<intent>
<action android:name="android.intent.action.VIEW" />

View File

@@ -32,7 +32,8 @@ public class DozeFragment extends SetupFragment
private DozeView dozeView;
private HuaweiProtectedAppsView huaweiProtectedAppsView;
private HuaweiAppLaunchView huaweiAppLaunchView;
private XiaomiView xiaomiView;
private XiaomiRecentAppsView xiaomiRecentAppsView;
private XiaomiLockAppsView xiaomiLockAppsView;
private Button next;
private boolean secondAttempt = false;
@@ -54,8 +55,10 @@ public class DozeFragment extends SetupFragment
huaweiProtectedAppsView.setOnCheckedChangedListener(this);
huaweiAppLaunchView = v.findViewById(R.id.huaweiAppLaunchView);
huaweiAppLaunchView.setOnCheckedChangedListener(this);
xiaomiView = v.findViewById(R.id.xiaomiView);
xiaomiView.setOnCheckedChangedListener(this);
xiaomiRecentAppsView = v.findViewById(R.id.xiaomiRecentAppsView);
xiaomiRecentAppsView.setOnCheckedChangedListener(this);
xiaomiLockAppsView = v.findViewById(R.id.xiaomiLockAppsView);
xiaomiLockAppsView.setOnCheckedChangedListener(this);
next = v.findViewById(R.id.next);
ProgressBar progressBar = v.findViewById(R.id.progress);
@@ -102,7 +105,8 @@ public class DozeFragment extends SetupFragment
next.setEnabled(dozeView.isChecked() &&
huaweiProtectedAppsView.isChecked() &&
huaweiAppLaunchView.isChecked() &&
xiaomiView.isChecked());
xiaomiRecentAppsView.isChecked() &&
xiaomiLockAppsView.isChecked());
}
@SuppressLint("BatteryLife")

View File

@@ -50,7 +50,7 @@ class DozeView extends PowerView {
onButtonClickListener.run();
}
public void setOnButtonClickListener(Runnable runnable) {
void setOnButtonClickListener(Runnable runnable) {
onButtonClickListener = runnable;
}

View File

@@ -0,0 +1,72 @@
package org.briarproject.briar.android.account;
import android.content.Context;
import android.util.AttributeSet;
import android.widget.Toast;
import org.briarproject.bramble.api.nullsafety.NotNullByDefault;
import org.briarproject.briar.R;
import java.util.logging.Logger;
import javax.annotation.Nullable;
import androidx.annotation.StringRes;
import androidx.annotation.UiThread;
import static android.widget.Toast.LENGTH_LONG;
import static java.util.logging.Level.WARNING;
import static java.util.logging.Logger.getLogger;
import static org.briarproject.android.dontkillmelib.XiaomiUtils.getXiaomiLockAppsIntent;
import static org.briarproject.android.dontkillmelib.XiaomiUtils.xiaomiLockAppsNeedsToBeShown;
import static org.briarproject.bramble.util.LogUtils.logException;
@UiThread
@NotNullByDefault
class XiaomiLockAppsView extends PowerView {
private static final Logger LOG =
getLogger(XiaomiLockAppsView.class.getName());
public XiaomiLockAppsView(Context context) {
this(context, null);
}
public XiaomiLockAppsView(Context context, @Nullable AttributeSet attrs) {
this(context, attrs, 0);
}
public XiaomiLockAppsView(Context context, @Nullable AttributeSet attrs,
int defStyleAttr) {
super(context, attrs, defStyleAttr);
setText(R.string.dnkm_xiaomi_lock_apps_text);
setButtonText(R.string.dnkm_xiaomi_lock_apps_button);
}
@Override
public boolean needsToBeShown() {
return xiaomiLockAppsNeedsToBeShown(getContext());
}
@Override
@StringRes
protected int getHelpText() {
return R.string.dnkm_xiaomi_lock_apps_help;
}
@Override
protected void onButtonClick() {
try {
getContext().startActivity(getXiaomiLockAppsIntent());
setChecked(true);
return;
} catch (SecurityException e) {
logException(LOG, WARNING, e);
}
Toast.makeText(getContext(),
R.string.dnkm_xiaomi_lock_apps_error_toast,
LENGTH_LONG).show();
// Let the user continue with setup
setChecked(true);
}
}

View File

@@ -1,6 +1,5 @@
package org.briarproject.briar.android.account;
import android.content.Context;
import android.util.AttributeSet;
@@ -12,23 +11,23 @@ import javax.annotation.Nullable;
import androidx.annotation.StringRes;
import androidx.annotation.UiThread;
import static org.briarproject.android.dontkillmelib.XiaomiUtils.isMiuiTenOrLater;
import static org.briarproject.android.dontkillmelib.XiaomiUtils.isXiaomiOrRedmiDevice;
import static org.briarproject.android.dontkillmelib.XiaomiUtils.isMiuiVersionAtLeast;
import static org.briarproject.android.dontkillmelib.XiaomiUtils.xiaomiRecentAppsNeedsToBeShown;
import static org.briarproject.briar.android.util.UiUtils.showOnboardingDialog;
@UiThread
@NotNullByDefault
class XiaomiView extends PowerView {
class XiaomiRecentAppsView extends PowerView {
public XiaomiView(Context context) {
public XiaomiRecentAppsView(Context context) {
this(context, null);
}
public XiaomiView(Context context, @Nullable AttributeSet attrs) {
public XiaomiRecentAppsView(Context context, @Nullable AttributeSet attrs) {
this(context, attrs, 0);
}
public XiaomiView(Context context, @Nullable AttributeSet attrs,
public XiaomiRecentAppsView(Context context, @Nullable AttributeSet attrs,
int defStyleAttr) {
super(context, attrs, defStyleAttr);
setText(R.string.dnkm_xiaomi_text);
@@ -37,7 +36,7 @@ class XiaomiView extends PowerView {
@Override
public boolean needsToBeShown() {
return isXiaomiOrRedmiDevice();
return xiaomiRecentAppsNeedsToBeShown();
}
@Override
@@ -48,7 +47,7 @@ class XiaomiView extends PowerView {
@Override
protected void onButtonClick() {
int bodyRes = isMiuiTenOrLater()
int bodyRes = isMiuiVersionAtLeast(10, 0)
? R.string.dnkm_xiaomi_dialog_body_new
: R.string.dnkm_xiaomi_dialog_body_old;
showOnboardingDialog(getContext(), getContext().getString(bodyRes));

View File

@@ -38,8 +38,8 @@
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/huaweiProtectedAppsView" />
<org.briarproject.briar.android.account.XiaomiView
android:id="@+id/xiaomiView"
<org.briarproject.briar.android.account.XiaomiRecentAppsView
android:id="@+id/xiaomiRecentAppsView"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingBottom="@dimen/margin_large"
@@ -47,6 +47,15 @@
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/huaweiAppLaunchView" />
<org.briarproject.briar.android.account.XiaomiLockAppsView
android:id="@+id/xiaomiLockAppsView"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingBottom="@dimen/margin_large"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/xiaomiRecentAppsView" />
<Button
android:id="@+id/next"
style="@style/BriarButton"
@@ -57,7 +66,7 @@
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/xiaomiView"
app:layout_constraintTop_toBottomOf="@+id/xiaomiLockAppsView"
app:layout_constraintVertical_bias="1.0"
tools:enabled="true" />

View File

@@ -31,7 +31,9 @@
<string name="dnkm_xiaomi_button">Protect Briar</string>
<string name="dnkm_xiaomi_help">If Briar is not locked to the recent apps list, it will be unable to run in the background.</string>
<string name="dnkm_xiaomi_dialog_body_old">1. Open the recent apps list (also called the app switcher)\n\n2. Swipe down on the image of Briar to show the padlock icon\n\n3. If the padlock is not locked, tap to lock it</string>
<string name="dnkm_xiaomi_dialog_body_new">1. Open the recent apps list (also called the app switcher)\n\n2. Press and hold the image of Briar until the padlock button appears\n\n3. If the padlock is not locked, tap to lock it</string>
<string name="dnkm_xiaomi_dialog_body_new">1. Open the recent apps list (also called the app switcher)\n\n2. If Briar has a small image of a padlock next to its name then you don\'t need to do anything\n\n3. If there\'s no padlock, press and hold the image of Briar until the padlock button appears, then tap it</string>
<string name="dnkm_xiaomi_lock_apps_text">Please tap the button below to open the security settings. Tap \"Boost speed\", then tap \"Lock apps\", and make sure Briar is set to \"Locked\".</string>
<string name="dnkm_xiaomi_lock_apps_help">If Briar is not set to \"Locked\" in the \"Lock apps\" screen, it will be unable to run in the background.</string>
<!-- Login -->
<string name="enter_password">Password</string>

View File

@@ -184,7 +184,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.bouncycastle:bcprov-jdk15on:1.65:bcprov-jdk15on-1.65.jar:e78f96eb59066c94c94fb2d6b5eb80f52feac6f5f9776898634f8addec6e2137',
'org.briarproject:dont-kill-me-lib:0.2.2:dont-kill-me-lib-0.2.2.aar:5e95bf79abe1342fb15be6757ac23be165127f052b93055ef1a796e5b8d6ab8a',
'org.briarproject:dont-kill-me-lib:0.2.5:dont-kill-me-lib-0.2.5.aar:55cd9d511b7016ab573905d64bc54e222e2633144d36389192b8b34485b31b9d',
'org.checkerframework:checker-compat-qual:2.5.3:checker-compat-qual-2.5.3.jar:d76b9afea61c7c082908023f0cbc1427fab9abd2df915c8b8a3e7a509bccbc6d',
'org.checkerframework:checker-qual:2.5.2:checker-qual-2.5.2.jar:64b02691c8b9d4e7700f8ee2e742dce7ea2c6e81e662b7522c9ee3bf568c040a',
'org.checkerframework:checker-qual:3.5.0:checker-qual-3.5.0.jar:729990b3f18a95606fc2573836b6958bcdb44cb52bfbd1b7aa9c339cff35a5a4',