diff --git a/src/main/java/eu/siacs/conversations/ui/OmemoActivity.java b/src/main/java/eu/siacs/conversations/ui/OmemoActivity.java index d7dfc2203..e63024c43 100644 --- a/src/main/java/eu/siacs/conversations/ui/OmemoActivity.java +++ b/src/main/java/eu/siacs/conversations/ui/OmemoActivity.java @@ -1,6 +1,7 @@ package eu.siacs.conversations.ui; import android.databinding.DataBindingUtil; +import android.net.Uri; import android.support.v7.app.AlertDialog; import android.content.Intent; import android.os.Bundle; @@ -28,219 +29,224 @@ import eu.siacs.conversations.utils.XmppUri; public abstract class OmemoActivity extends XmppActivity { - private Account mSelectedAccount; - private String mSelectedFingerprint; + private Account mSelectedAccount; + private String mSelectedFingerprint; - protected XmppUri mPendingFingerprintVerificationUri = null; + protected XmppUri mPendingFingerprintVerificationUri = null; - @Override - public void onCreateContextMenu(ContextMenu menu, View v, ContextMenu.ContextMenuInfo menuInfo) { - super.onCreateContextMenu(menu,v,menuInfo); - Object account = v.getTag(R.id.TAG_ACCOUNT); - Object fingerprint = v.getTag(R.id.TAG_FINGERPRINT); - Object fingerprintStatus = v.getTag(R.id.TAG_FINGERPRINT_STATUS); - if (account != null - && fingerprint != null - && account instanceof Account - && fingerprintStatus != null - && fingerprint instanceof String - && fingerprintStatus instanceof FingerprintStatus) { - getMenuInflater().inflate(R.menu.omemo_key_context, menu); - MenuItem distrust = menu.findItem(R.id.distrust_key); - MenuItem verifyScan = menu.findItem(R.id.verify_scan); - if (this instanceof TrustKeysActivity) { - distrust.setVisible(false); - verifyScan.setVisible(false); - } else { - FingerprintStatus status = (FingerprintStatus) fingerprintStatus; - if (!status.isActive() || status.isVerified()) { - verifyScan.setVisible(false); - } - distrust.setVisible(status.isVerified() || (!status.isActive() && status.isTrusted())); - } - this.mSelectedAccount = (Account) account; - this.mSelectedFingerprint = (String) fingerprint; - } - } + @Override + public void onCreateContextMenu(ContextMenu menu, View v, ContextMenu.ContextMenuInfo menuInfo) { + super.onCreateContextMenu(menu, v, menuInfo); + Object account = v.getTag(R.id.TAG_ACCOUNT); + Object fingerprint = v.getTag(R.id.TAG_FINGERPRINT); + Object fingerprintStatus = v.getTag(R.id.TAG_FINGERPRINT_STATUS); + if (account != null + && fingerprint != null + && account instanceof Account + && fingerprintStatus != null + && fingerprint instanceof String + && fingerprintStatus instanceof FingerprintStatus) { + getMenuInflater().inflate(R.menu.omemo_key_context, menu); + MenuItem distrust = menu.findItem(R.id.distrust_key); + MenuItem verifyScan = menu.findItem(R.id.verify_scan); + if (this instanceof TrustKeysActivity) { + distrust.setVisible(false); + verifyScan.setVisible(false); + } else { + FingerprintStatus status = (FingerprintStatus) fingerprintStatus; + if (!status.isActive() || status.isVerified()) { + verifyScan.setVisible(false); + } + distrust.setVisible(status.isVerified() || (!status.isActive() && status.isTrusted())); + } + this.mSelectedAccount = (Account) account; + this.mSelectedFingerprint = (String) fingerprint; + } + } - @Override - public boolean onContextItemSelected(MenuItem item) { - switch (item.getItemId()) { - case R.id.distrust_key: - showPurgeKeyDialog(mSelectedAccount,mSelectedFingerprint); - break; - case R.id.copy_omemo_key: - copyOmemoFingerprint(mSelectedFingerprint); - break; - case R.id.verify_scan: - //new IntentIntegrator(this).initiateScan(Arrays.asList("AZTEC","QR_CODE")); - break; - } - return true; - } + @Override + public boolean onContextItemSelected(MenuItem item) { + switch (item.getItemId()) { + case R.id.distrust_key: + showPurgeKeyDialog(mSelectedAccount, mSelectedFingerprint); + break; + case R.id.copy_omemo_key: + copyOmemoFingerprint(mSelectedFingerprint); + break; + case R.id.verify_scan: + ScanActivity.scan(this); + break; + } + return true; + } - @Override - public void onActivityResult(int requestCode, int resultCode, Intent intent) { - /*IntentResult scanResult = IntentIntegrator.parseActivityResult(requestCode, resultCode, intent); - if (scanResult != null && scanResult.getFormatName() != null) { - String data = scanResult.getContents(); - XmppUri uri = new XmppUri(data); - if (xmppConnectionServiceBound) { - processFingerprintVerification(uri); - } else { - this.mPendingFingerprintVerificationUri =uri; - } - }*/ - } + @Override + public void onActivityResult(int requestCode, int resultCode, Intent intent) { + super.onActivityResult(requestCode, requestCode, intent); + if (requestCode == ScanActivity.REQUEST_SCAN_QR_CODE && resultCode == RESULT_OK) { + String result = intent.getStringExtra(ScanActivity.INTENT_EXTRA_RESULT); + XmppUri uri = new XmppUri(result == null ? "" : result); + if (xmppConnectionServiceBound) { + processFingerprintVerification(uri); + } else { + this.mPendingFingerprintVerificationUri = uri; + } + } + } - protected abstract void processFingerprintVerification(XmppUri uri); + protected abstract void processFingerprintVerification(XmppUri uri); - protected void copyOmemoFingerprint(String fingerprint) { - if (copyTextToClipboard(CryptoHelper.prettifyFingerprint(fingerprint.substring(2)), R.string.omemo_fingerprint)) { - Toast.makeText( - this, - R.string.toast_message_omemo_fingerprint, - Toast.LENGTH_SHORT).show(); - } - } + protected void copyOmemoFingerprint(String fingerprint) { + if (copyTextToClipboard(CryptoHelper.prettifyFingerprint(fingerprint.substring(2)), R.string.omemo_fingerprint)) { + Toast.makeText( + this, + R.string.toast_message_omemo_fingerprint, + Toast.LENGTH_SHORT).show(); + } + } - protected void addFingerprintRow(LinearLayout keys, final XmppAxolotlSession session, boolean highlight) { - final Account account = session.getAccount(); - final String fingerprint = session.getFingerprint(); - addFingerprintRowWithListeners(keys, - session.getAccount(), - fingerprint, - highlight, - session.getTrust(), - true, - true, - (buttonView, isChecked) -> account.getAxolotlService().setFingerprintTrust(fingerprint, FingerprintStatus.createActive(isChecked))); - } + protected void addFingerprintRow(LinearLayout keys, final XmppAxolotlSession session, boolean highlight) { + final Account account = session.getAccount(); + final String fingerprint = session.getFingerprint(); + addFingerprintRowWithListeners(keys, + session.getAccount(), + fingerprint, + highlight, + session.getTrust(), + true, + true, + (buttonView, isChecked) -> account.getAxolotlService().setFingerprintTrust(fingerprint, FingerprintStatus.createActive(isChecked))); + } - protected void addFingerprintRowWithListeners(LinearLayout keys, final Account account, - final String fingerprint, - boolean highlight, - FingerprintStatus status, - boolean showTag, - boolean undecidedNeedEnablement, - CompoundButton.OnCheckedChangeListener - onCheckedChangeListener) { - ContactKeyBinding binding = DataBindingUtil.inflate(getLayoutInflater(),R.layout.contact_key,keys,true); - if (Config.X509_VERIFICATION && status.getTrust() == FingerprintStatus.Trust.VERIFIED_X509) { - binding.key.setOnClickListener(v -> showX509Certificate(account,fingerprint)); - binding.keyType.setOnClickListener(v -> showX509Certificate(account,fingerprint)); - } - binding.tglTrust.setVisibility(View.VISIBLE); - registerForContextMenu(binding.getRoot()); - binding.getRoot().setTag(R.id.TAG_ACCOUNT,account); - binding.getRoot().setTag(R.id.TAG_FINGERPRINT,fingerprint); - binding.getRoot().setTag(R.id.TAG_FINGERPRINT_STATUS,status); - boolean x509 = Config.X509_VERIFICATION && status.getTrust() == FingerprintStatus.Trust.VERIFIED_X509; - final View.OnClickListener toast; - binding.tglTrust.setChecked(status.isTrusted()); + protected void addFingerprintRowWithListeners(LinearLayout keys, final Account account, + final String fingerprint, + boolean highlight, + FingerprintStatus status, + boolean showTag, + boolean undecidedNeedEnablement, + CompoundButton.OnCheckedChangeListener + onCheckedChangeListener) { + ContactKeyBinding binding = DataBindingUtil.inflate(getLayoutInflater(), R.layout.contact_key, keys, true); + if (Config.X509_VERIFICATION && status.getTrust() == FingerprintStatus.Trust.VERIFIED_X509) { + binding.key.setOnClickListener(v -> showX509Certificate(account, fingerprint)); + binding.keyType.setOnClickListener(v -> showX509Certificate(account, fingerprint)); + } + binding.tglTrust.setVisibility(View.VISIBLE); + registerForContextMenu(binding.getRoot()); + binding.getRoot().setTag(R.id.TAG_ACCOUNT, account); + binding.getRoot().setTag(R.id.TAG_FINGERPRINT, fingerprint); + binding.getRoot().setTag(R.id.TAG_FINGERPRINT_STATUS, status); + boolean x509 = Config.X509_VERIFICATION && status.getTrust() == FingerprintStatus.Trust.VERIFIED_X509; + final View.OnClickListener toast; + binding.tglTrust.setChecked(status.isTrusted()); - if (status.isActive()){ - binding.key.setTextColor(getPrimaryTextColor()); - binding.keyType.setTextColor(getSecondaryTextColor()); - if (status.isVerified()) { - binding.verifiedFingerprint.setVisibility(View.VISIBLE); - binding.verifiedFingerprint.setAlpha(1.0f); - binding.tglTrust.setVisibility(View.GONE); - binding.verifiedFingerprint.setOnClickListener(v -> replaceToast(getString(R.string.this_device_has_been_verified), false)); - toast = null; - } else { - binding.verifiedFingerprint.setVisibility(View.GONE); - binding.tglTrust.setVisibility(View.VISIBLE); - binding.tglTrust.setOnCheckedChangeListener(onCheckedChangeListener); - if (status.getTrust() == FingerprintStatus.Trust.UNDECIDED && undecidedNeedEnablement) { - binding.buttonEnableDevice.setVisibility(View.VISIBLE); - binding.buttonEnableDevice.setOnClickListener(v -> { - account.getAxolotlService().setFingerprintTrust(fingerprint,FingerprintStatus.createActive(false)); - binding.buttonEnableDevice.setVisibility(View.GONE); - binding.tglTrust.setVisibility(View.VISIBLE); - }); - binding.tglTrust.setVisibility(View.GONE); - } else { - binding.tglTrust.setOnClickListener(null); - binding.tglTrust.setEnabled(true); - } - toast = v -> hideToast(); - } - } else { - binding.key.setTextColor(getTertiaryTextColor()); - binding.keyType.setTextColor(getTertiaryTextColor()); - toast = v -> replaceToast(getString(R.string.this_device_is_no_longer_in_use), false); - if (status.isVerified()) { - binding.tglTrust.setVisibility(View.GONE); - binding.verifiedFingerprint.setVisibility(View.VISIBLE); - binding.verifiedFingerprint.setAlpha(0.4368f); - binding.verifiedFingerprint.setOnClickListener(toast); - } else { - binding.tglTrust.setVisibility(View.VISIBLE); - binding.verifiedFingerprint.setVisibility(View.GONE); - binding.tglTrust.setEnabled(false); - } - } + if (status.isActive()) { + binding.key.setTextColor(getPrimaryTextColor()); + binding.keyType.setTextColor(getSecondaryTextColor()); + if (status.isVerified()) { + binding.verifiedFingerprint.setVisibility(View.VISIBLE); + binding.verifiedFingerprint.setAlpha(1.0f); + binding.tglTrust.setVisibility(View.GONE); + binding.verifiedFingerprint.setOnClickListener(v -> replaceToast(getString(R.string.this_device_has_been_verified), false)); + toast = null; + } else { + binding.verifiedFingerprint.setVisibility(View.GONE); + binding.tglTrust.setVisibility(View.VISIBLE); + binding.tglTrust.setOnCheckedChangeListener(onCheckedChangeListener); + if (status.getTrust() == FingerprintStatus.Trust.UNDECIDED && undecidedNeedEnablement) { + binding.buttonEnableDevice.setVisibility(View.VISIBLE); + binding.buttonEnableDevice.setOnClickListener(v -> { + account.getAxolotlService().setFingerprintTrust(fingerprint, FingerprintStatus.createActive(false)); + binding.buttonEnableDevice.setVisibility(View.GONE); + binding.tglTrust.setVisibility(View.VISIBLE); + }); + binding.tglTrust.setVisibility(View.GONE); + } else { + binding.tglTrust.setOnClickListener(null); + binding.tglTrust.setEnabled(true); + } + toast = v -> hideToast(); + } + } else { + binding.key.setTextColor(getTertiaryTextColor()); + binding.keyType.setTextColor(getTertiaryTextColor()); + toast = v -> replaceToast(getString(R.string.this_device_is_no_longer_in_use), false); + if (status.isVerified()) { + binding.tglTrust.setVisibility(View.GONE); + binding.verifiedFingerprint.setVisibility(View.VISIBLE); + binding.verifiedFingerprint.setAlpha(0.4368f); + binding.verifiedFingerprint.setOnClickListener(toast); + } else { + binding.tglTrust.setVisibility(View.VISIBLE); + binding.verifiedFingerprint.setVisibility(View.GONE); + binding.tglTrust.setEnabled(false); + } + } - binding.getRoot().setOnClickListener(toast); - binding.key.setOnClickListener(toast); - binding.keyType.setOnClickListener(toast); - if (showTag) { - binding.keyType.setText(getString(x509 ? R.string.omemo_fingerprint_x509 : R.string.omemo_fingerprint)); - } else { - binding.keyType.setVisibility(View.GONE); - } - if (highlight) { - binding.keyType.setTextColor(ContextCompat.getColor(this, R.color.accent)); - binding.keyType.setText(getString(x509 ? R.string.omemo_fingerprint_x509_selected_message : R.string.omemo_fingerprint_selected_message)); - } else { - binding.keyType.setText(getString(x509 ? R.string.omemo_fingerprint_x509 : R.string.omemo_fingerprint)); - } + binding.getRoot().setOnClickListener(toast); + binding.key.setOnClickListener(toast); + binding.keyType.setOnClickListener(toast); + if (showTag) { + binding.keyType.setText(getString(x509 ? R.string.omemo_fingerprint_x509 : R.string.omemo_fingerprint)); + } else { + binding.keyType.setVisibility(View.GONE); + } + if (highlight) { + binding.keyType.setTextColor(ContextCompat.getColor(this, R.color.accent)); + binding.keyType.setText(getString(x509 ? R.string.omemo_fingerprint_x509_selected_message : R.string.omemo_fingerprint_selected_message)); + } else { + binding.keyType.setText(getString(x509 ? R.string.omemo_fingerprint_x509 : R.string.omemo_fingerprint)); + } - binding.key.setText(CryptoHelper.prettifyFingerprint(fingerprint.substring(2))); - } + binding.key.setText(CryptoHelper.prettifyFingerprint(fingerprint.substring(2))); + } - public void showPurgeKeyDialog(final Account account, final String fingerprint) { - AlertDialog.Builder builder = new AlertDialog.Builder(this); - builder.setTitle(R.string.distrust_omemo_key); - builder.setMessage(R.string.distrust_omemo_key_text); - builder.setNegativeButton(getString(R.string.cancel), null); - builder.setPositiveButton(R.string.confirm, - (dialog, which) -> { - account.getAxolotlService().distrustFingerprint(fingerprint); - refreshUi(); - }); - builder.create().show(); - } + public void showPurgeKeyDialog(final Account account, final String fingerprint) { + AlertDialog.Builder builder = new AlertDialog.Builder(this); + builder.setTitle(R.string.distrust_omemo_key); + builder.setMessage(R.string.distrust_omemo_key_text); + builder.setNegativeButton(getString(R.string.cancel), null); + builder.setPositiveButton(R.string.confirm, + (dialog, which) -> { + account.getAxolotlService().distrustFingerprint(fingerprint); + refreshUi(); + }); + builder.create().show(); + } - private void showX509Certificate(Account account, String fingerprint) { - X509Certificate x509Certificate = account.getAxolotlService().getFingerprintCertificate(fingerprint); - if (x509Certificate != null) { - showCertificateInformationDialog(CryptoHelper.extractCertificateInformation(x509Certificate)); - } else { - Toast.makeText(this,R.string.certificate_not_found, Toast.LENGTH_SHORT).show(); - } - } + private void showX509Certificate(Account account, String fingerprint) { + X509Certificate x509Certificate = account.getAxolotlService().getFingerprintCertificate(fingerprint); + if (x509Certificate != null) { + showCertificateInformationDialog(CryptoHelper.extractCertificateInformation(x509Certificate)); + } else { + Toast.makeText(this, R.string.certificate_not_found, Toast.LENGTH_SHORT).show(); + } + } - private void showCertificateInformationDialog(Bundle bundle) { - View view = getLayoutInflater().inflate(R.layout.certificate_information, null); - final String not_available = getString(R.string.certicate_info_not_available); - TextView subject_cn = (TextView) view.findViewById(R.id.subject_cn); - TextView subject_o = (TextView) view.findViewById(R.id.subject_o); - TextView issuer_cn = (TextView) view.findViewById(R.id.issuer_cn); - TextView issuer_o = (TextView) view.findViewById(R.id.issuer_o); - TextView sha1 = (TextView) view.findViewById(R.id.sha1); + private void showCertificateInformationDialog(Bundle bundle) { + View view = getLayoutInflater().inflate(R.layout.certificate_information, null); + final String not_available = getString(R.string.certicate_info_not_available); + TextView subject_cn = (TextView) view.findViewById(R.id.subject_cn); + TextView subject_o = (TextView) view.findViewById(R.id.subject_o); + TextView issuer_cn = (TextView) view.findViewById(R.id.issuer_cn); + TextView issuer_o = (TextView) view.findViewById(R.id.issuer_o); + TextView sha1 = (TextView) view.findViewById(R.id.sha1); - subject_cn.setText(bundle.getString("subject_cn", not_available)); - subject_o.setText(bundle.getString("subject_o", not_available)); - issuer_cn.setText(bundle.getString("issuer_cn", not_available)); - issuer_o.setText(bundle.getString("issuer_o", not_available)); - sha1.setText(bundle.getString("sha1", not_available)); + subject_cn.setText(bundle.getString("subject_cn", not_available)); + subject_o.setText(bundle.getString("subject_o", not_available)); + issuer_cn.setText(bundle.getString("issuer_cn", not_available)); + issuer_o.setText(bundle.getString("issuer_o", not_available)); + sha1.setText(bundle.getString("sha1", not_available)); - AlertDialog.Builder builder = new AlertDialog.Builder(this); - builder.setTitle(R.string.certificate_information); - builder.setView(view); - builder.setPositiveButton(R.string.ok, null); - builder.create().show(); - } + AlertDialog.Builder builder = new AlertDialog.Builder(this); + builder.setTitle(R.string.certificate_information); + builder.setView(view); + builder.setPositiveButton(R.string.ok, null); + builder.create().show(); + } + + @Override + public void onRequestPermissionsResult(int requestCode, String permissions[], int[] grantResults) { + ScanActivity.onRequestPermissionResult(this, requestCode, grantResults); + } } diff --git a/src/main/java/eu/siacs/conversations/ui/ScanActivity.java b/src/main/java/eu/siacs/conversations/ui/ScanActivity.java index 149b9e2ef..24f3e82af 100644 --- a/src/main/java/eu/siacs/conversations/ui/ScanActivity.java +++ b/src/main/java/eu/siacs/conversations/ui/ScanActivity.java @@ -54,6 +54,7 @@ import android.view.TextureView; import android.view.TextureView.SurfaceTextureListener; import android.view.View; import android.view.WindowManager; +import android.widget.Toast; import eu.siacs.conversations.Config; import eu.siacs.conversations.R; @@ -67,6 +68,9 @@ import eu.siacs.conversations.ui.widget.ScannerView; public final class ScanActivity extends Activity implements SurfaceTextureListener, ActivityCompat.OnRequestPermissionsResultCallback { public static final String INTENT_EXTRA_RESULT = "result"; + public static final int REQUEST_SCAN_QR_CODE = 0x0987; + private static final int REQUEST_CAMERA_PERMISSIONS_TO_SCAN = 0x6789; + private static final long VIBRATE_DURATION = 50L; private static final long AUTO_FOCUS_INTERVAL_MS = 2500L; private static boolean DISABLE_CONTINUOUS_AUTOFOCUS = Build.MODEL.equals("GT-I9100") // Galaxy S2 @@ -263,7 +267,30 @@ public final class ScanActivity extends Activity implements SurfaceTextureListen } private void postFinish() { - new Handler().postDelayed(() -> finish(), 50); + new Handler().postDelayed(this::finish, 50); + } + + public static void scan(Activity activity) { + if (ContextCompat.checkSelfPermission(activity, Manifest.permission.CAMERA) == PackageManager.PERMISSION_GRANTED) { + Intent intent = new Intent(activity, ScanActivity.class); + activity.startActivityForResult(intent, REQUEST_SCAN_QR_CODE); + } else { + ActivityCompat.requestPermissions(activity, new String[]{Manifest.permission.CAMERA}, REQUEST_CAMERA_PERMISSIONS_TO_SCAN); + } + + } + + public static void onRequestPermissionResult(Activity activity, int requestCode, int[] grantResults) { + if (requestCode != REQUEST_CAMERA_PERMISSIONS_TO_SCAN) { + return; + } + if (grantResults.length > 0) { + if (grantResults[0] == PackageManager.PERMISSION_GRANTED) { + scan(activity); + } else { + Toast.makeText(activity, R.string.qr_code_scanner_needs_access_to_camera, Toast.LENGTH_SHORT).show(); + } + } } private final class AutoFocusRunnable implements Runnable { diff --git a/src/main/java/eu/siacs/conversations/ui/TrustKeysActivity.java b/src/main/java/eu/siacs/conversations/ui/TrustKeysActivity.java index 6cb0cd891..761e865b3 100644 --- a/src/main/java/eu/siacs/conversations/ui/TrustKeysActivity.java +++ b/src/main/java/eu/siacs/conversations/ui/TrustKeysActivity.java @@ -133,6 +133,7 @@ public class TrustKeysActivity extends OmemoActivity implements OnKeyStatusUpdat if (hasPendingKeyFetches()) { Toast.makeText(this, R.string.please_wait_for_keys_to_be_fetched, Toast.LENGTH_SHORT).show(); } else { + ScanActivity.scan(this); //new IntentIntegrator(this).initiateScan(Arrays.asList("AZTEC","QR_CODE")); return true; }