TrustKeysActivity.java

  1package eu.siacs.conversations.ui;
  2
  3import android.content.Intent;
  4import android.os.Bundle;
  5import android.util.Log;
  6import android.view.View;
  7import android.view.View.OnClickListener;
  8import android.widget.Button;
  9import android.widget.CompoundButton;
 10import android.widget.LinearLayout;
 11import android.widget.TextView;
 12
 13import org.whispersystems.libaxolotl.IdentityKey;
 14
 15
 16import java.util.HashMap;
 17import java.util.Map;
 18import java.util.Set;
 19
 20import eu.siacs.conversations.Config;
 21import eu.siacs.conversations.R;
 22import eu.siacs.conversations.crypto.axolotl.AxolotlService;
 23import eu.siacs.conversations.crypto.axolotl.AxolotlService.SQLiteAxolotlStore.Trust;
 24import eu.siacs.conversations.entities.Account;
 25import eu.siacs.conversations.entities.Contact;
 26import eu.siacs.conversations.entities.Conversation;
 27import eu.siacs.conversations.xmpp.OnNewKeysAvailable;
 28import eu.siacs.conversations.xmpp.jid.InvalidJidException;
 29import eu.siacs.conversations.xmpp.jid.Jid;
 30
 31public class TrustKeysActivity extends XmppActivity implements OnNewKeysAvailable {
 32	private Jid accountJid;
 33	private Jid contactJid;
 34
 35	private Contact contact;
 36	private TextView ownKeysTitle;
 37	private LinearLayout ownKeys;
 38	private LinearLayout ownKeysCard;
 39	private TextView foreignKeysTitle;
 40	private LinearLayout foreignKeys;
 41	private LinearLayout foreignKeysCard;
 42	private Button mSaveButton;
 43	private Button mCancelButton;
 44
 45	private final Map<IdentityKey, Boolean> ownKeysToTrust = new HashMap<>();
 46	private final Map<IdentityKey, Boolean> foreignKeysToTrust = new HashMap<>();
 47
 48	private final OnClickListener mSaveButtonListener = new OnClickListener() {
 49		@Override
 50		public void onClick(View v) {
 51			commitTrusts();
 52			Intent data = new Intent();
 53			data.putExtra("choice", getIntent().getIntExtra("choice", ConversationActivity.ATTACHMENT_CHOICE_INVALID));
 54			setResult(RESULT_OK, data);
 55			finish();
 56		}
 57	};
 58
 59	private final OnClickListener mCancelButtonListener = new OnClickListener() {
 60		@Override
 61		public void onClick(View v) {
 62			setResult(RESULT_CANCELED);
 63			finish();
 64		}
 65	};
 66
 67	@Override
 68	protected void refreshUiReal() {
 69		invalidateOptionsMenu();
 70		populateView();
 71	}
 72
 73	@Override
 74	protected String getShareableUri() {
 75		if (contact != null) {
 76			return contact.getShareableUri();
 77		} else {
 78			return "";
 79		}
 80	}
 81
 82	@Override
 83	protected void onCreate(final Bundle savedInstanceState) {
 84		super.onCreate(savedInstanceState);
 85		setContentView(R.layout.activity_trust_keys);
 86		try {
 87			this.accountJid = Jid.fromString(getIntent().getExtras().getString("account"));
 88		} catch (final InvalidJidException ignored) {
 89		}
 90		try {
 91			this.contactJid = Jid.fromString(getIntent().getExtras().getString("contact"));
 92		} catch (final InvalidJidException ignored) {
 93		}
 94
 95		ownKeysTitle = (TextView) findViewById(R.id.own_keys_title);
 96		ownKeys = (LinearLayout) findViewById(R.id.own_keys_details);
 97		ownKeysCard = (LinearLayout) findViewById(R.id.own_keys_card);
 98		foreignKeysTitle = (TextView) findViewById(R.id.foreign_keys_title);
 99		foreignKeys = (LinearLayout) findViewById(R.id.foreign_keys_details);
100		foreignKeysCard = (LinearLayout) findViewById(R.id.foreign_keys_card);
101		mCancelButton = (Button) findViewById(R.id.cancel_button);
102		mCancelButton.setOnClickListener(mCancelButtonListener);
103		mSaveButton = (Button) findViewById(R.id.save_button);
104		mSaveButton.setOnClickListener(mSaveButtonListener);
105
106
107		if (getActionBar() != null) {
108			getActionBar().setHomeButtonEnabled(true);
109			getActionBar().setDisplayHomeAsUpEnabled(true);
110		}
111	}
112
113	private void populateView() {
114		setTitle(getString(R.string.trust_keys));
115		ownKeys.removeAllViews();
116		foreignKeys.removeAllViews();
117		boolean hasOwnKeys = false;
118		boolean hasForeignKeys = false;
119		for(final IdentityKey identityKey : ownKeysToTrust.keySet()) {
120			hasOwnKeys = true;
121			addFingerprintRowWithListeners(ownKeys, contact.getAccount(), identityKey,
122					Trust.fromBoolean(ownKeysToTrust.get(identityKey)), false,
123					new CompoundButton.OnCheckedChangeListener() {
124						@Override
125						public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
126							ownKeysToTrust.put(identityKey, isChecked);
127							refreshUi();
128							xmppConnectionService.updateAccountUi();
129							xmppConnectionService.updateConversationUi();
130						}
131					},
132					null
133			);
134		}
135		for(final IdentityKey identityKey : foreignKeysToTrust.keySet()) {
136			hasForeignKeys = true;
137			addFingerprintRowWithListeners(foreignKeys, contact.getAccount(), identityKey,
138					Trust.fromBoolean(foreignKeysToTrust.get(identityKey)), false,
139					new CompoundButton.OnCheckedChangeListener() {
140						@Override
141						public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
142							foreignKeysToTrust.put(identityKey, isChecked);
143							refreshUi();
144							xmppConnectionService.updateAccountUi();
145							xmppConnectionService.updateConversationUi();
146						}
147					},
148					null
149			);
150		}
151
152		if(hasOwnKeys) {
153			ownKeysTitle.setText(accountJid.toString());
154			ownKeysCard.setVisibility(View.VISIBLE);
155		}
156		if(hasForeignKeys) {
157			foreignKeysTitle.setText(contactJid.toString());
158			foreignKeysCard.setVisibility(View.VISIBLE);
159		}
160	}
161
162	private void getFingerprints(final Account account) {
163		Set<IdentityKey> ownKeysSet = account.getAxolotlService().getPendingKeys();
164		for(final IdentityKey identityKey : ownKeysSet) {
165			if(!ownKeysToTrust.containsKey(identityKey)) {
166				ownKeysToTrust.put(identityKey, false);
167			}
168		}
169		Set<IdentityKey> foreignKeysSet = account.getAxolotlService().getPendingKeys(contact);
170		for(final IdentityKey identityKey : foreignKeysSet) {
171			if(!foreignKeysToTrust.containsKey(identityKey)) {
172				foreignKeysToTrust.put(identityKey, false);
173			}
174		}
175	}
176
177	@Override
178	public void onBackendConnected() {
179		if ((accountJid != null) && (contactJid != null)) {
180			final Account account = xmppConnectionService
181				.findAccountByJid(accountJid);
182			if (account == null) {
183				return;
184			}
185			this.contact = account.getRoster().getContact(contactJid);
186			ownKeysToTrust.clear();
187			foreignKeysToTrust.clear();
188			getFingerprints(account);
189
190			Conversation conversation = xmppConnectionService.findOrCreateConversation(account, contactJid, false);
191			if(account.getAxolotlService().hasPendingKeyFetches(conversation)) {
192				lock();
193			}
194
195			populateView();
196		}
197	}
198
199	@Override
200	public void onNewKeysAvailable() {
201		runOnUiThread(new Runnable() {
202			@Override
203			public void run() {
204				final Account account = xmppConnectionService
205						.findAccountByJid(accountJid);
206				unlock();
207				getFingerprints(account);
208				refreshUi();
209			}
210		});
211	}
212
213	private void commitTrusts() {
214		for(IdentityKey identityKey:ownKeysToTrust.keySet()) {
215			contact.getAccount().getAxolotlService().setFingerprintTrust(
216					identityKey.getFingerprint().replaceAll("\\s", ""),
217					Trust.fromBoolean(ownKeysToTrust.get(identityKey)));
218		}
219		for(IdentityKey identityKey:foreignKeysToTrust.keySet()) {
220			contact.getAccount().getAxolotlService().setFingerprintTrust(
221					identityKey.getFingerprint().replaceAll("\\s", ""),
222					Trust.fromBoolean(foreignKeysToTrust.get(identityKey)));
223		}
224	}
225
226	private void unlock() {
227		mSaveButton.setEnabled(true);
228		mSaveButton.setText(getString(R.string.done));
229		mSaveButton.setTextColor(getPrimaryTextColor());
230	}
231
232	private void lock() {
233		mSaveButton.setEnabled(false);
234		mSaveButton.setText(getString(R.string.fetching_keys));
235		mSaveButton.setTextColor(getSecondaryTextColor());
236	}
237}