offer a more convienient way to disable omemo from trust keys dialog

This commit is contained in:
Daniel Gultsch 2018-03-15 13:37:08 +01:00
parent 1bfc0b8da6
commit 64f040b631
5 changed files with 177 additions and 124 deletions

View File

@ -77,6 +77,7 @@ public class AxolotlService implements OnAdvancedStreamFeaturesLoaded {
private final Map<Jid, Set<Integer>> deviceIds; private final Map<Jid, Set<Integer>> deviceIds;
private final Map<String, XmppAxolotlMessage> messageCache; private final Map<String, XmppAxolotlMessage> messageCache;
private final FetchStatusMap fetchStatusMap; private final FetchStatusMap fetchStatusMap;
private final Map<Jid, Boolean> fetchDeviceListStatus = new HashMap<>();
private final HashMap<Jid, List<OnDeviceIdsFetched>> fetchDeviceIdsMap = new HashMap<>(); private final HashMap<Jid, List<OnDeviceIdsFetched>> fetchDeviceIdsMap = new HashMap<>();
private final SerialSingleThreadExecutor executor; private final SerialSingleThreadExecutor executor;
private int numPublishTriesOnEmptyPep = 0; private int numPublishTriesOnEmptyPep = 0;
@ -97,6 +98,20 @@ public class AxolotlService implements OnAdvancedStreamFeaturesLoaded {
} }
} }
private boolean hasErrorFetchingDeviceList(Jid jid) {
Boolean status = fetchDeviceListStatus.get(jid);
return status != null && !status;
}
public boolean hasErrorFetchingDeviceList(List<Jid> jids) {
for(Jid jid : jids) {
if (hasErrorFetchingDeviceList(jid)) {
return true;
}
}
return false;
}
public boolean fetchMapHasErrors(List<Jid> jids) { public boolean fetchMapHasErrors(List<Jid> jids) {
for (Jid jid : jids) { for (Jid jid : jids) {
if (deviceIds.get(jid) != null) { if (deviceIds.get(jid) != null) {
@ -361,6 +376,7 @@ public class AxolotlService implements OnAdvancedStreamFeaturesLoaded {
public void clearErrorsInFetchStatusMap(Jid jid) { public void clearErrorsInFetchStatusMap(Jid jid) {
fetchStatusMap.clearErrorFor(jid); fetchStatusMap.clearErrorFor(jid);
fetchDeviceListStatus.remove(jid);
} }
public void regenerateKeys(boolean wipeOther) { public void regenerateKeys(boolean wipeOther) {
@ -368,6 +384,7 @@ public class AxolotlService implements OnAdvancedStreamFeaturesLoaded {
sessions.clear(); sessions.clear();
fetchStatusMap.clear(); fetchStatusMap.clear();
fetchDeviceIdsMap.clear(); fetchDeviceIdsMap.clear();
fetchDeviceListStatus.clear();
publishBundlesIfNeeded(true, wipeOther); publishBundlesIfNeeded(true, wipeOther);
} }
@ -960,26 +977,29 @@ public class AxolotlService implements OnAdvancedStreamFeaturesLoaded {
this.fetchDeviceIdsMap.put(jid, callbacks); this.fetchDeviceIdsMap.put(jid, callbacks);
Log.d(Config.LOGTAG, account.getJid().asBareJid() + ": fetching device ids for " + jid); Log.d(Config.LOGTAG, account.getJid().asBareJid() + ": fetching device ids for " + jid);
IqPacket packet = mXmppConnectionService.getIqGenerator().retrieveDeviceIds(jid); IqPacket packet = mXmppConnectionService.getIqGenerator().retrieveDeviceIds(jid);
mXmppConnectionService.sendIqPacket(account, packet, new OnIqPacketReceived() { mXmppConnectionService.sendIqPacket(account, packet, (account, response) -> {
@Override
public void onIqPacketReceived(Account account, IqPacket packet) {
synchronized (fetchDeviceIdsMap) { synchronized (fetchDeviceIdsMap) {
List<OnDeviceIdsFetched> callbacks = fetchDeviceIdsMap.remove(jid); List<OnDeviceIdsFetched> callbacks1 = fetchDeviceIdsMap.remove(jid);
if (packet.getType() == IqPacket.TYPE.RESULT) { if (response.getType() == IqPacket.TYPE.RESULT) {
Element item = mXmppConnectionService.getIqParser().getItem(packet); fetchDeviceListStatus.put(jid, true);
Element item = mXmppConnectionService.getIqParser().getItem(response);
Set<Integer> deviceIds = mXmppConnectionService.getIqParser().deviceIds(item); Set<Integer> deviceIds = mXmppConnectionService.getIqParser().deviceIds(item);
registerDevices(jid, deviceIds); registerDevices(jid, deviceIds);
if (callbacks != null) { if (callbacks1 != null) {
for (OnDeviceIdsFetched callback : callbacks) { for (OnDeviceIdsFetched callback1 : callbacks1) {
callback.fetched(jid, deviceIds); callback1.fetched(jid, deviceIds);
} }
} }
} else { } else {
Log.d(Config.LOGTAG, packet.toString()); if (response.getType() == IqPacket.TYPE.TIMEOUT) {
if (callbacks != null) { fetchDeviceListStatus.remove(jid);
for (OnDeviceIdsFetched callback : callbacks) { } else {
callback.fetched(jid, null); fetchDeviceListStatus.put(jid, false);
} }
Log.d(Config.LOGTAG, response.toString());
if (callbacks1 != null) {
for (OnDeviceIdsFetched callback1 : callbacks1) {
callback1.fetched(jid, null);
} }
} }
} }
@ -993,16 +1013,13 @@ public class AxolotlService implements OnAdvancedStreamFeaturesLoaded {
final ArrayList<Jid> unfinishedJids = new ArrayList<>(jids); final ArrayList<Jid> unfinishedJids = new ArrayList<>(jids);
synchronized (unfinishedJids) { synchronized (unfinishedJids) {
for (Jid jid : unfinishedJids) { for (Jid jid : unfinishedJids) {
fetchDeviceIds(jid, new OnDeviceIdsFetched() { fetchDeviceIds(jid, (j, deviceIds) -> {
@Override
public void fetched(Jid jid, Set<Integer> deviceIds) {
synchronized (unfinishedJids) { synchronized (unfinishedJids) {
unfinishedJids.remove(jid); unfinishedJids.remove(j);
if (unfinishedJids.size() == 0 && callback != null) { if (unfinishedJids.size() == 0 && callback != null) {
callback.fetched(); callback.fetched();
} }
} }
}
}); });
} }
} }

View File

@ -653,11 +653,11 @@ public class ConversationFragment extends XmppFragment implements EditMessage.Ke
break; break;
case Message.ENCRYPTION_AXOLOTL: case Message.ENCRYPTION_AXOLOTL:
if (!trustKeysIfNeeded(REQUEST_TRUST_KEYS_TEXT)) { if (!trustKeysIfNeeded(REQUEST_TRUST_KEYS_TEXT)) {
sendAxolotlMessage(message); sendMessage(message);
} }
break; break;
default: default:
sendPlainTextMessage(message); sendMessage(message);
} }
} }
@ -724,7 +724,7 @@ public class ConversationFragment extends XmppFragment implements EditMessage.Ke
case REQUEST_TRUST_KEYS_TEXT: case REQUEST_TRUST_KEYS_TEXT:
final String body = this.binding.textinput.getText().toString(); final String body = this.binding.textinput.getText().toString();
Message message = new Message(conversation, body, conversation.getNextEncryption()); Message message = new Message(conversation, body, conversation.getNextEncryption());
sendAxolotlMessage(message); sendMessage(message);
break; break;
case REQUEST_TRUST_KEYS_MENU: case REQUEST_TRUST_KEYS_MENU:
int choice = data.getIntExtra("choice", ATTACHMENT_CHOICE_INVALID); int choice = data.getIntExtra("choice", ATTACHMENT_CHOICE_INVALID);
@ -2222,7 +2222,7 @@ public class ConversationFragment extends XmppFragment implements EditMessage.Ke
this.binding.snackbar.setVisibility(View.GONE); this.binding.snackbar.setVisibility(View.GONE);
} }
protected void sendPlainTextMessage(Message message) { protected void sendMessage(Message message) {
activity.xmppConnectionService.sendMessage(message); activity.xmppConnectionService.sendMessage(message);
messageSent(); messageSent();
} }
@ -2339,11 +2339,6 @@ public class ConversationFragment extends XmppFragment implements EditMessage.Ke
builder.create().show(); builder.create().show();
} }
protected void sendAxolotlMessage(final Message message) {
activity.xmppConnectionService.sendMessage(message);
messageSent();
}
public void appendText(String text) { public void appendText(String text) {
if (text == null) { if (text == null) {
return; return;

View File

@ -1,5 +1,6 @@
package eu.siacs.conversations.ui; package eu.siacs.conversations.ui;
import android.app.AlertDialog;
import android.content.Intent; import android.content.Intent;
import android.databinding.DataBindingUtil; import android.databinding.DataBindingUtil;
import android.os.Bundle; import android.os.Bundle;
@ -10,7 +11,6 @@ import android.view.Menu;
import android.view.MenuItem; import android.view.MenuItem;
import android.view.View; import android.view.View;
import android.view.View.OnClickListener; import android.view.View.OnClickListener;
import android.widget.CompoundButton;
import android.widget.Toast; import android.widget.Toast;
import org.whispersystems.libsignal.IdentityKey; import org.whispersystems.libsignal.IdentityKey;
@ -29,7 +29,9 @@ import eu.siacs.conversations.crypto.axolotl.FingerprintStatus;
import eu.siacs.conversations.databinding.ActivityTrustKeysBinding; import eu.siacs.conversations.databinding.ActivityTrustKeysBinding;
import eu.siacs.conversations.databinding.KeysCardBinding; import eu.siacs.conversations.databinding.KeysCardBinding;
import eu.siacs.conversations.entities.Account; import eu.siacs.conversations.entities.Account;
import eu.siacs.conversations.entities.Contact;
import eu.siacs.conversations.entities.Conversation; import eu.siacs.conversations.entities.Conversation;
import eu.siacs.conversations.entities.Message;
import eu.siacs.conversations.utils.CryptoHelper; import eu.siacs.conversations.utils.CryptoHelper;
import eu.siacs.conversations.utils.IrregularUnicodeDetector; import eu.siacs.conversations.utils.IrregularUnicodeDetector;
import eu.siacs.conversations.utils.XmppUri; import eu.siacs.conversations.utils.XmppUri;
@ -38,33 +40,21 @@ import rocks.xmpp.addr.Jid;
public class TrustKeysActivity extends OmemoActivity implements OnKeyStatusUpdated { public class TrustKeysActivity extends OmemoActivity implements OnKeyStatusUpdated {
private List<Jid> contactJids;
private Account mAccount;
private Conversation mConversation;
private AtomicBoolean mUseCameraHintShown = new AtomicBoolean(false);
private AxolotlService.FetchStatus lastFetchReport = AxolotlService.FetchStatus.SUCCESS;
private final Map<String, Boolean> ownKeysToTrust = new HashMap<>(); private final Map<String, Boolean> ownKeysToTrust = new HashMap<>();
private final Map<Jid,Map<String, Boolean>> foreignKeysToTrust = new HashMap<>(); private final Map<Jid, Map<String, Boolean>> foreignKeysToTrust = new HashMap<>();
private final OnClickListener mCancelButtonListener = v -> {
private final OnClickListener mSaveButtonListener = new OnClickListener() {
@Override
public void onClick(View v) {
commitTrusts();
finishOk();
}
};
private final OnClickListener mCancelButtonListener = new OnClickListener() {
@Override
public void onClick(View v) {
setResult(RESULT_CANCELED); setResult(RESULT_CANCELED);
finish(); finish();
}
}; };
private List<Jid> contactJids;
private Account mAccount;
private Conversation mConversation;
private final OnClickListener mSaveButtonListener = v -> {
commitTrusts();
finishOk(false);
};
private AtomicBoolean mUseCameraHintShown = new AtomicBoolean(false);
private AxolotlService.FetchStatus lastFetchReport = AxolotlService.FetchStatus.SUCCESS;
private Toast mUseCameraHintToast = null; private Toast mUseCameraHintToast = null;
private ActivityTrustKeysBinding binding; private ActivityTrustKeysBinding binding;
@ -77,9 +67,9 @@ public class TrustKeysActivity extends OmemoActivity implements OnKeyStatusUpdat
@Override @Override
protected void onCreate(final Bundle savedInstanceState) { protected void onCreate(final Bundle savedInstanceState) {
super.onCreate(savedInstanceState); super.onCreate(savedInstanceState);
this.binding = DataBindingUtil.setContentView(this,R.layout.activity_trust_keys); this.binding = DataBindingUtil.setContentView(this, R.layout.activity_trust_keys);
this.contactJids = new ArrayList<>(); this.contactJids = new ArrayList<>();
for(String jid : getIntent().getStringArrayExtra("contacts")) { for (String jid : getIntent().getStringArrayExtra("contacts")) {
try { try {
this.contactJids.add(Jid.of(jid)); this.contactJids.add(Jid.of(jid));
} catch (IllegalArgumentException e) { } catch (IllegalArgumentException e) {
@ -97,7 +87,7 @@ public class TrustKeysActivity extends OmemoActivity implements OnKeyStatusUpdat
} }
if (savedInstanceState != null) { if (savedInstanceState != null) {
mUseCameraHintShown.set(savedInstanceState.getBoolean("camera_hint_shown",false)); mUseCameraHintShown.set(savedInstanceState.getBoolean("camera_hint_shown", false));
} }
} }
@ -116,9 +106,9 @@ public class TrustKeysActivity extends OmemoActivity implements OnKeyStatusUpdat
} }
private void showCameraToast() { private void showCameraToast() {
mUseCameraHintToast = Toast.makeText(this,R.string.use_camera_icon_to_scan_barcode,Toast.LENGTH_LONG); mUseCameraHintToast = Toast.makeText(this, R.string.use_camera_icon_to_scan_barcode, Toast.LENGTH_LONG);
ActionBar actionBar = getSupportActionBar(); ActionBar actionBar = getSupportActionBar();
mUseCameraHintToast.setGravity(Gravity.TOP | Gravity.END, 0 ,actionBar == null ? 0 : actionBar.getHeight()); mUseCameraHintToast.setGravity(Gravity.TOP | Gravity.END, 0, actionBar == null ? 0 : actionBar.getHeight());
mUseCameraHintToast.show(); mUseCameraHintToast.show();
} }
@ -151,19 +141,19 @@ public class TrustKeysActivity extends OmemoActivity implements OnKeyStatusUpdat
&& mAccount != null && mAccount != null
&& uri.hasFingerprints() && uri.hasFingerprints()
&& mAccount.getAxolotlService().getCryptoTargets(mConversation).contains(uri.getJid())) { && mAccount.getAxolotlService().getCryptoTargets(mConversation).contains(uri.getJid())) {
boolean performedVerification = xmppConnectionService.verifyFingerprints(mAccount.getRoster().getContact(uri.getJid()),uri.getFingerprints()); boolean performedVerification = xmppConnectionService.verifyFingerprints(mAccount.getRoster().getContact(uri.getJid()), uri.getFingerprints());
boolean keys = reloadFingerprints(); boolean keys = reloadFingerprints();
if (performedVerification && !keys && !hasNoOtherTrustedKeys() && !hasPendingKeyFetches()) { if (performedVerification && !keys && !hasNoOtherTrustedKeys() && !hasPendingKeyFetches()) {
Toast.makeText(this,R.string.all_omemo_keys_have_been_verified, Toast.LENGTH_SHORT).show(); Toast.makeText(this, R.string.all_omemo_keys_have_been_verified, Toast.LENGTH_SHORT).show();
finishOk(); finishOk(false);
return; return;
} else if (performedVerification) { } else if (performedVerification) {
Toast.makeText(this,R.string.verified_fingerprints,Toast.LENGTH_SHORT).show(); Toast.makeText(this, R.string.verified_fingerprints, Toast.LENGTH_SHORT).show();
} }
} else { } else {
reloadFingerprints(); reloadFingerprints();
Log.d(Config.LOGTAG,"xmpp uri was: "+uri.getJid()+" has Fingerprints: "+Boolean.toString(uri.hasFingerprints())); Log.d(Config.LOGTAG, "xmpp uri was: " + uri.getJid() + " has Fingerprints: " + Boolean.toString(uri.hasFingerprints()));
Toast.makeText(this,R.string.barcode_does_not_contain_fingerprints_for_this_conversation,Toast.LENGTH_SHORT).show(); Toast.makeText(this, R.string.barcode_does_not_contain_fingerprints_for_this_conversation, Toast.LENGTH_SHORT).show();
} }
populateView(); populateView();
} }
@ -174,26 +164,23 @@ public class TrustKeysActivity extends OmemoActivity implements OnKeyStatusUpdat
binding.foreignKeys.removeAllViews(); binding.foreignKeys.removeAllViews();
boolean hasOwnKeys = false; boolean hasOwnKeys = false;
boolean hasForeignKeys = false; boolean hasForeignKeys = false;
for(final String fingerprint : ownKeysToTrust.keySet()) { for (final String fingerprint : ownKeysToTrust.keySet()) {
hasOwnKeys = true; hasOwnKeys = true;
addFingerprintRowWithListeners(binding.ownKeysDetails, mAccount, fingerprint, false, addFingerprintRowWithListeners(binding.ownKeysDetails, mAccount, fingerprint, false,
FingerprintStatus.createActive(ownKeysToTrust.get(fingerprint)), false, false, FingerprintStatus.createActive(ownKeysToTrust.get(fingerprint)), false, false,
new CompoundButton.OnCheckedChangeListener() { (buttonView, isChecked) -> {
@Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
ownKeysToTrust.put(fingerprint, isChecked); ownKeysToTrust.put(fingerprint, isChecked);
// own fingerprints have no impact on locked status. // own fingerprints have no impact on locked status.
} }
}
); );
} }
synchronized (this.foreignKeysToTrust) { synchronized (this.foreignKeysToTrust) {
for (Map.Entry<Jid, Map<String, Boolean>> entry : foreignKeysToTrust.entrySet()) { for (Map.Entry<Jid, Map<String, Boolean>> entry : foreignKeysToTrust.entrySet()) {
hasForeignKeys = true; hasForeignKeys = true;
KeysCardBinding keysCardBinding = DataBindingUtil.inflate(getLayoutInflater(),R.layout.keys_card, binding.foreignKeys,false); KeysCardBinding keysCardBinding = DataBindingUtil.inflate(getLayoutInflater(), R.layout.keys_card, binding.foreignKeys, false);
final Jid jid = entry.getKey(); final Jid jid = entry.getKey();
keysCardBinding.foreignKeysTitle.setText(IrregularUnicodeDetector.style(this,jid)); keysCardBinding.foreignKeysTitle.setText(IrregularUnicodeDetector.style(this, jid));
keysCardBinding.foreignKeysTitle.setOnClickListener(v -> switchToContactDetails(mAccount.getRoster().getContact(jid))); keysCardBinding.foreignKeysTitle.setOnClickListener(v -> switchToContactDetails(mAccount.getRoster().getContact(jid)));
final Map<String, Boolean> fingerprints = entry.getValue(); final Map<String, Boolean> fingerprints = entry.getValue();
for (final String fingerprint : fingerprints.keySet()) { for (final String fingerprint : fingerprints.keySet()) {
@ -223,30 +210,37 @@ public class TrustKeysActivity extends OmemoActivity implements OnKeyStatusUpdat
} }
} }
if ((hasOwnKeys || foreignActuallyHasKeys()) && isCameraFeatureAvailable() && mUseCameraHintShown.compareAndSet(false,true)) { if ((hasOwnKeys || foreignActuallyHasKeys()) && isCameraFeatureAvailable() && mUseCameraHintShown.compareAndSet(false, true)) {
showCameraToast(); showCameraToast();
} }
binding.ownKeysTitle.setText(mAccount.getJid().asBareJid().toString()); binding.ownKeysTitle.setText(mAccount.getJid().asBareJid().toString());
binding.ownKeysCard.setVisibility(hasOwnKeys ? View.VISIBLE : View.GONE); binding.ownKeysCard.setVisibility(hasOwnKeys ? View.VISIBLE : View.GONE);
binding.foreignKeys.setVisibility(hasForeignKeys ? View.VISIBLE : View.GONE); binding.foreignKeys.setVisibility(hasForeignKeys ? View.VISIBLE : View.GONE);
if(hasPendingKeyFetches()) { if (hasPendingKeyFetches()) {
setFetching(); setFetching();
lock(); lock();
} else { } else {
if (!hasForeignKeys && hasNoOtherTrustedKeys()) { if (!hasForeignKeys && hasNoOtherTrustedKeys()) {
binding.keyErrorMessageCard.setVisibility(View.VISIBLE); binding.keyErrorMessageCard.setVisibility(View.VISIBLE);
if (lastFetchReport == AxolotlService.FetchStatus.ERROR boolean lastReportWasError = lastFetchReport == AxolotlService.FetchStatus.ERROR;
|| mAccount.getAxolotlService().fetchMapHasErrors(contactJids)) { boolean errorFetchingBundle = mAccount.getAxolotlService().fetchMapHasErrors(contactJids);
if (anyWithoutMutualPresenceSubscription(contactJids)) { boolean errorFetchingDeviceList = mAccount.getAxolotlService().hasErrorFetchingDeviceList(contactJids);
binding.keyErrorMessage.setText(R.string.error_no_keys_to_trust_presence); boolean anyWithoutMutualPresenceSubscription = anyWithoutMutualPresenceSubscription(contactJids);
if (errorFetchingDeviceList) {
binding.keyErrorMessage.setVisibility(View.VISIBLE);
binding.keyErrorMessage.setText(R.string.error_trustkey_device_list);
} else if (errorFetchingBundle || lastReportWasError) {
binding.keyErrorMessage.setVisibility(View.VISIBLE);
binding.keyErrorMessage.setText(R.string.error_trustkey_bundle);
} else { } else {
binding.keyErrorMessage.setText(R.string.error_no_keys_to_trust_server_error); binding.keyErrorMessage.setVisibility(View.GONE);
}
} else {
binding.keyErrorMessage.setText(R.string.error_no_keys_to_trust);
} }
this.binding.keyErrorHintMutual.setVisibility(anyWithoutMutualPresenceSubscription ? View.VISIBLE : View.GONE);
Contact contact = mAccount.getRoster().getContact(contactJids.get(0));
binding.keyErrorGeneral.setText(getString(R.string.error_trustkey_general, contact.getDisplayName()));
binding.ownKeysDetails.removeAllViews(); binding.ownKeysDetails.removeAllViews();
binding.disableButton.setOnClickListener(this::disableEncryptionDialog);
binding.ownKeysCard.setVisibility(View.GONE); binding.ownKeysCard.setVisibility(View.GONE);
binding.foreignKeys.removeAllViews(); binding.foreignKeys.removeAllViews();
binding.foreignKeys.setVisibility(View.GONE); binding.foreignKeys.setVisibility(View.GONE);
@ -256,8 +250,21 @@ public class TrustKeysActivity extends OmemoActivity implements OnKeyStatusUpdat
} }
} }
private boolean anyWithoutMutualPresenceSubscription(List<Jid> contactJids){ private void disableEncryptionDialog(View view) {
for(Jid jid : contactJids) { AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setTitle(R.string.disable_encryption);
builder.setMessage(R.string.disable_encryption_message);
builder.setPositiveButton(R.string.disable_now, (dialog, which) -> {
mConversation.setNextEncryption(Message.ENCRYPTION_NONE);
xmppConnectionService.updateConversation(mConversation);
finishOk(true);
});
builder.setNegativeButton(R.string.cancel, null);
builder.create().show();
}
private boolean anyWithoutMutualPresenceSubscription(List<Jid> contactJids) {
for (Jid jid : contactJids) {
if (!mAccount.getRoster().getContact(jid).mutualPresenceSubscription()) { if (!mAccount.getRoster().getContact(jid).mutualPresenceSubscription()) {
return true; return true;
} }
@ -277,13 +284,13 @@ public class TrustKeysActivity extends OmemoActivity implements OnKeyStatusUpdat
} }
private boolean reloadFingerprints() { private boolean reloadFingerprints() {
List<Jid> acceptedTargets = mConversation == null ? new ArrayList<Jid>() : mConversation.getAcceptedCryptoTargets(); List<Jid> acceptedTargets = mConversation == null ? new ArrayList<>() : mConversation.getAcceptedCryptoTargets();
ownKeysToTrust.clear(); ownKeysToTrust.clear();
AxolotlService service = this.mAccount.getAxolotlService(); AxolotlService service = this.mAccount.getAxolotlService();
Set<IdentityKey> ownKeysSet = service.getKeysWithTrust(FingerprintStatus.createActiveUndecided()); Set<IdentityKey> ownKeysSet = service.getKeysWithTrust(FingerprintStatus.createActiveUndecided());
for(final IdentityKey identityKey : ownKeysSet) { for (final IdentityKey identityKey : ownKeysSet) {
final String fingerprint = CryptoHelper.bytesToHex(identityKey.getPublicKey().serialize()); final String fingerprint = CryptoHelper.bytesToHex(identityKey.getPublicKey().serialize());
if(!ownKeysToTrust.containsKey(fingerprint)) { if (!ownKeysToTrust.containsKey(fingerprint)) {
ownKeysToTrust.put(fingerprint, false); ownKeysToTrust.put(fingerprint, false);
} }
} }
@ -344,18 +351,16 @@ public class TrustKeysActivity extends OmemoActivity implements OnKeyStatusUpdat
final boolean keysToTrust = reloadFingerprints(); final boolean keysToTrust = reloadFingerprints();
if (report != null) { if (report != null) {
lastFetchReport = report; lastFetchReport = report;
runOnUiThread(new Runnable() { runOnUiThread(() -> {
@Override
public void run() {
if (mUseCameraHintToast != null && !keysToTrust) { if (mUseCameraHintToast != null && !keysToTrust) {
mUseCameraHintToast.cancel(); mUseCameraHintToast.cancel();
} }
switch (report) { switch (report) {
case ERROR: case ERROR:
Toast.makeText(TrustKeysActivity.this,R.string.error_fetching_omemo_key,Toast.LENGTH_SHORT).show(); Toast.makeText(TrustKeysActivity.this, R.string.error_fetching_omemo_key, Toast.LENGTH_SHORT).show();
break; break;
case SUCCESS_TRUSTED: case SUCCESS_TRUSTED:
Toast.makeText(TrustKeysActivity.this,R.string.blindly_trusted_omemo_keys,Toast.LENGTH_LONG).show(); Toast.makeText(TrustKeysActivity.this, R.string.blindly_trusted_omemo_keys, Toast.LENGTH_LONG).show();
break; break;
case SUCCESS_VERIFIED: case SUCCESS_VERIFIED:
Toast.makeText(TrustKeysActivity.this, Toast.makeText(TrustKeysActivity.this,
@ -363,32 +368,27 @@ public class TrustKeysActivity extends OmemoActivity implements OnKeyStatusUpdat
Toast.LENGTH_LONG).show(); Toast.LENGTH_LONG).show();
break; break;
} }
}
}); });
} }
if (keysToTrust || hasPendingKeyFetches() || hasNoOtherTrustedKeys()) { if (keysToTrust || hasPendingKeyFetches() || hasNoOtherTrustedKeys()) {
refreshUi(); refreshUi();
} else { } else {
runOnUiThread(new Runnable() { runOnUiThread(() -> finishOk(false));
@Override
public void run() {
finishOk();
}
});
} }
} }
private void finishOk() { private void finishOk(boolean disabled) {
Intent data = new Intent(); Intent data = new Intent();
data.putExtra("choice", getIntent().getIntExtra("choice", ConversationFragment.ATTACHMENT_CHOICE_INVALID)); data.putExtra("choice", getIntent().getIntExtra("choice", ConversationFragment.ATTACHMENT_CHOICE_INVALID));
data.putExtra("disabled", disabled);
setResult(RESULT_OK, data); setResult(RESULT_OK, data);
finish(); finish();
} }
private void commitTrusts() { private void commitTrusts() {
for(final String fingerprint :ownKeysToTrust.keySet()) { for (final String fingerprint : ownKeysToTrust.keySet()) {
mAccount.getAxolotlService().setFingerprintTrust( mAccount.getAxolotlService().setFingerprintTrust(
fingerprint, fingerprint,
FingerprintStatus.createActive(ownKeysToTrust.get(fingerprint))); FingerprintStatus.createActive(ownKeysToTrust.get(fingerprint)));

View File

@ -27,6 +27,10 @@
android:layout_marginTop="@dimen/activity_vertical_margin" android:layout_marginTop="@dimen/activity_vertical_margin"
android:visibility="gone"> android:visibility="gone">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<LinearLayout <LinearLayout
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
@ -38,14 +42,44 @@
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:text="@string/error_trustkeys_title" android:text="@string/error_trustkeys_title"
android:textAppearance="@style/TextAppearance.AppCompat.Title"/> android:textAppearance="@style/TextAppearance.AppCompat.Title"
android:layout_marginBottom="8sp"/>
<TextView <TextView
android:id="@+id/key_error_message" android:id="@+id/key_error_message"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:padding="8dp" android:textAppearance="@style/TextAppearance.AppCompat.Subhead"/>
android:textAppearance="@style/TextAppearance.AppCompat.Body1"/> <TextView
android:id="@+id/key_error_general"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textAppearance="@style/TextAppearance.Conversations.Body1"/>
<TextView
android:layout_marginTop="8sp"
android:id="@+id/key_error_hint_mutual"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textAppearance="@style/TextAppearance.Conversations.Body1.Secondary"
android:text="@string/error_trustkey_hint_mutual"/>
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_gravity="right"
android:gravity="right">
<Button
android:id="@+id/disable_button"
style="?android:attr/borderlessButtonStyle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:minWidth="0dp"
android:paddingLeft="16dp"
android:paddingRight="16dp"
android:text="@string/disable_encryption"
android:textColor="@color/accent"/>
</LinearLayout>
</LinearLayout> </LinearLayout>
</android.support.v7.widget.CardView> </android.support.v7.widget.CardView>

View File

@ -363,7 +363,7 @@
<string name="error_no_keys_to_trust_server_error">There are no usable keys available for this contact.\nFetching new keys from the server has been unsuccessful. Maybe there is something wrong with your contacts server.</string> <string name="error_no_keys_to_trust_server_error">There are no usable keys available for this contact.\nFetching new keys from the server has been unsuccessful. Maybe there is something wrong with your contacts server.</string>
<string name="error_no_keys_to_trust_presence">There are no usable keys available for this contact.\nMake sure you have mutual presence subscription.</string> <string name="error_no_keys_to_trust_presence">There are no usable keys available for this contact.\nMake sure you have mutual presence subscription.</string>
<string name="error_no_keys_to_trust">There are no usable keys available for this contact. If you have purged any of their keys, they need to generate new ones.</string> <string name="error_no_keys_to_trust">There are no usable keys available for this contact. If you have purged any of their keys, they need to generate new ones.</string>
<string name="error_trustkeys_title">Error</string> <string name="error_trustkeys_title">Something went wrong</string>
<string name="fetching_history_from_server">Fetching history from server</string> <string name="fetching_history_from_server">Fetching history from server</string>
<string name="no_more_history_on_server">No more history on server</string> <string name="no_more_history_on_server">No more history on server</string>
<string name="updating">Updating…</string> <string name="updating">Updating…</string>
@ -727,4 +727,11 @@
<string name="pref_scroll_to_bottom_summary">Scroll down after sending a message</string> <string name="pref_scroll_to_bottom_summary">Scroll down after sending a message</string>
<string name="edit_status_message_title">Edit Status Message</string> <string name="edit_status_message_title">Edit Status Message</string>
<string name="edit_status_message">Edit status message</string> <string name="edit_status_message">Edit status message</string>
<string name="disable_encryption">Disable encryption</string>
<string name="error_trustkey_general">Conversations is unable to send encrypted messages to %1$s. This may be due to your contact using an outdated server or client that can not handle OMEMO.</string>
<string name="error_trustkey_device_list">Unable to fetch device list</string>
<string name="error_trustkey_bundle">Unable to fetch device bundles</string>
<string name="error_trustkey_hint_mutual">Hint: In some cases this can be fixed by adding each other your contact lists.</string>
<string name="disable_encryption_message">Are you sure you want to disable OMEMO encryption for this conversation?\nThis will allow your server administrator to read your messages, but it might be the only way to communicate with people using outdated clients.</string>
<string name="disable_now">Disable now</string>
</resources> </resources>