TrustKeysActivity.java

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