compose: improve handling if crypto provider is not available
This commit is contained in:
parent
7b0c94f6bb
commit
eac65df806
8 changed files with 225 additions and 71 deletions
|
@ -109,8 +109,11 @@ import org.htmlcleaner.CleanerProperties;
|
|||
import org.htmlcleaner.HtmlCleaner;
|
||||
import org.htmlcleaner.SimpleHtmlSerializer;
|
||||
import org.htmlcleaner.TagNode;
|
||||
import org.openintents.openpgp.IOpenPgpService2;
|
||||
import org.openintents.openpgp.util.OpenPgpApi;
|
||||
import org.openintents.openpgp.util.OpenPgpServiceConnection;
|
||||
import org.openintents.openpgp.util.OpenPgpServiceConnection.OnBound;
|
||||
|
||||
|
||||
@SuppressWarnings("deprecation")
|
||||
public class MessageCompose extends K9Activity implements OnClickListener,
|
||||
|
@ -695,7 +698,17 @@ public class MessageCompose extends K9Activity implements OnClickListener,
|
|||
// attachKeyCheckBox = (CheckBox) findViewById(R.id.cb_attach_key);
|
||||
// attachKeyCheckBox.setEnabled(mAccount.getCryptoKey() != 0);
|
||||
|
||||
mOpenPgpServiceConnection = new OpenPgpServiceConnection(this, mOpenPgpProvider);
|
||||
mOpenPgpServiceConnection = new OpenPgpServiceConnection(this, mOpenPgpProvider, new OnBound() {
|
||||
@Override
|
||||
public void onBound(IOpenPgpService2 service) {
|
||||
recipientPresenter.onCryptoProviderBound();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onError(Exception e) {
|
||||
recipientPresenter.onCryptoProviderError(e);
|
||||
}
|
||||
});
|
||||
mOpenPgpServiceConnection.bindToService();
|
||||
|
||||
updateMessageFormat();
|
||||
|
@ -1320,16 +1333,17 @@ public class MessageCompose extends K9Activity implements OnClickListener,
|
|||
return;
|
||||
}
|
||||
|
||||
if (resultCode != RESULT_OK) {
|
||||
return;
|
||||
}
|
||||
if (data == null) {
|
||||
if ((requestCode & REQUEST_MASK_RECIPIENT_PRESENTER) == REQUEST_MASK_RECIPIENT_PRESENTER) {
|
||||
requestCode ^= REQUEST_MASK_RECIPIENT_PRESENTER;
|
||||
recipientPresenter.onActivityResult(resultCode, requestCode, data);
|
||||
return;
|
||||
}
|
||||
|
||||
if ((requestCode & REQUEST_MASK_RECIPIENT_PRESENTER) == REQUEST_MASK_RECIPIENT_PRESENTER) {
|
||||
requestCode ^= REQUEST_MASK_RECIPIENT_PRESENTER;
|
||||
recipientPresenter.onActivityResult(requestCode, data);
|
||||
if (resultCode != RESULT_OK) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (data == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -3015,4 +3029,12 @@ public class MessageCompose extends K9Activity implements OnClickListener,
|
|||
}
|
||||
}
|
||||
|
||||
public void launchUserInteractionPendingIntent(PendingIntent pendingIntent, int requestCode) {
|
||||
requestCode |= REQUEST_MASK_RECIPIENT_PRESENTER;
|
||||
try {
|
||||
startIntentSenderForResult(pendingIntent.getIntentSender(), requestCode, null, 0, 0, 0);
|
||||
} catch (SendIntentException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -65,14 +65,23 @@ public class ComposeCryptoStatus {
|
|||
return CryptoStatusDisplayType.OPPORTUNISTIC_NOKEY;
|
||||
case SIGN_ONLY:
|
||||
return CryptoStatusDisplayType.SIGN_ONLY;
|
||||
default:
|
||||
case DISABLE:
|
||||
return CryptoStatusDisplayType.DISABLED;
|
||||
case ERROR:
|
||||
return CryptoStatusDisplayType.ERROR;
|
||||
default:
|
||||
case UNINITIALIZED:
|
||||
return CryptoStatusDisplayType.UNINITIALIZED;
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isPgpErrorState() {
|
||||
return cryptoMode == CryptoMode.ERROR;
|
||||
}
|
||||
|
||||
public boolean shouldUsePgpMessageBuilder() {
|
||||
return cryptoMode != CryptoMode.DISABLE;
|
||||
return cryptoMode == CryptoMode.PRIVATE || cryptoMode == CryptoMode.OPPORTUNISTIC
|
||||
|| cryptoMode == CryptoMode.SIGN_ONLY;
|
||||
}
|
||||
|
||||
public boolean isEncryptionEnabled() {
|
||||
|
@ -129,7 +138,7 @@ public class ComposeCryptoStatus {
|
|||
|
||||
ArrayList<String> keyReferences = new ArrayList<>();
|
||||
boolean allKeysAvailable = true;
|
||||
boolean allKeysVerified = true;
|
||||
boolean allKeysVerified = !recipients.isEmpty();
|
||||
for (Recipient recipient : recipients) {
|
||||
RecipientCryptoStatus cryptoStatus = recipient.getCryptoStatus();
|
||||
if (cryptoStatus.isAvailable()) {
|
||||
|
|
|
@ -255,9 +255,14 @@ public class RecipientLoader extends AsyncTaskLoader<List<Recipient>> {
|
|||
List<String> recipientList = new ArrayList<>(recipientMap.keySet());
|
||||
String[] recipientAddresses = recipientList.toArray(new String[recipientList.size()]);
|
||||
|
||||
Cursor cursor;
|
||||
Uri queryUri = Uri.parse("content://" + cryptoProvider + ".provider.exported/email_status");
|
||||
Cursor cursor = getContext().getContentResolver().query(queryUri, PROJECTION_CRYPTO_STATUS, null,
|
||||
recipientAddresses, null);
|
||||
try {
|
||||
cursor = getContext().getContentResolver().query(queryUri, PROJECTION_CRYPTO_STATUS, null,
|
||||
recipientAddresses, null);
|
||||
} catch (SecurityException e) {
|
||||
return;
|
||||
}
|
||||
|
||||
initializeCryptoStatusForAllRecipients(recipientMap);
|
||||
|
||||
|
|
|
@ -6,6 +6,7 @@ import java.util.List;
|
|||
|
||||
import android.animation.Animator;
|
||||
import android.animation.AnimatorListenerAdapter;
|
||||
import android.app.PendingIntent;
|
||||
import android.text.TextWatcher;
|
||||
import android.view.View;
|
||||
import android.view.View.OnClickListener;
|
||||
|
@ -25,11 +26,13 @@ import com.fsck.k9.view.RecipientSelectView.TokenListener;
|
|||
|
||||
|
||||
public class RecipientMvpView implements OnFocusChangeListener, OnClickListener {
|
||||
private static final int VIEW_INDEX_HIDDEN = -1;
|
||||
private static final int VIEW_INDEX_CRYPTO_STATUS_DISABLED = 0;
|
||||
private static final int VIEW_INDEX_CRYPTO_STATUS_NO_KEY = 1;
|
||||
private static final int VIEW_INDEX_CRYPTO_STATUS_UNTRUSTED = 2;
|
||||
private static final int VIEW_INDEX_CRYPTO_STATUS_TRUSTED = 3;
|
||||
private static final int VIEW_INDEX_CRYPTO_STATUS_SIGN_ONLY = 4;
|
||||
private static final int VIEW_INDEX_CRYPTO_STATUS_ERROR = 1;
|
||||
private static final int VIEW_INDEX_CRYPTO_STATUS_NO_KEY = 2;
|
||||
private static final int VIEW_INDEX_CRYPTO_STATUS_UNTRUSTED = 3;
|
||||
private static final int VIEW_INDEX_CRYPTO_STATUS_TRUSTED = 4;
|
||||
private static final int VIEW_INDEX_CRYPTO_STATUS_SIGN_ONLY = 5;
|
||||
|
||||
private static final int VIEW_INDEX_BCC_EXPANDER_VISIBLE = 0;
|
||||
private static final int VIEW_INDEX_BCC_EXPANDER_HIDDEN = 1;
|
||||
|
@ -223,20 +226,6 @@ public class RecipientMvpView implements OnFocusChangeListener, OnClickListener
|
|||
return bccView.getObjects();
|
||||
}
|
||||
|
||||
public void hideCryptoStatus() {
|
||||
if (cryptoStatusView.getVisibility() == View.GONE) {
|
||||
return;
|
||||
}
|
||||
|
||||
cryptoStatusView.animate().translationX(100).setDuration(300).setListener(new AnimatorListenerAdapter() {
|
||||
@Override
|
||||
public void onAnimationEnd(Animator animation) {
|
||||
super.onAnimationEnd(animation);
|
||||
cryptoStatusView.setVisibility(View.GONE);
|
||||
}
|
||||
}).start();
|
||||
}
|
||||
|
||||
public boolean recipientToHasUncompletedText() {
|
||||
return toView.hasUncompletedText();
|
||||
}
|
||||
|
@ -261,17 +250,16 @@ public class RecipientMvpView implements OnFocusChangeListener, OnClickListener
|
|||
bccView.setError(bccView.getContext().getString(R.string.compose_error_incomplete_recipient));
|
||||
}
|
||||
|
||||
public void showMissingSignKeyError() {
|
||||
Toast.makeText(activity, R.string.compose_error_no_signing_key, Toast.LENGTH_LONG).show();
|
||||
}
|
||||
public void showCryptoStatus(final CryptoStatusDisplayType cryptoStatusDisplayType) {
|
||||
boolean shouldBeHidden = cryptoStatusDisplayType.childToDisplay == VIEW_INDEX_HIDDEN;
|
||||
if (shouldBeHidden) {
|
||||
hideCryptoStatus();
|
||||
return;
|
||||
}
|
||||
|
||||
public void showPrivateAndIncompleteError() {
|
||||
Toast.makeText(activity, R.string.compose_error_private_missing_keys, Toast.LENGTH_LONG).show();
|
||||
}
|
||||
|
||||
public void showCryptoStatus(final CryptoStatusDisplayType childToDisplay) {
|
||||
if (cryptoStatusView.getVisibility() == View.VISIBLE) {
|
||||
switchCryptoStatus(childToDisplay);
|
||||
boolean alreadyVisible = cryptoStatusView.getVisibility() == View.VISIBLE;
|
||||
if (alreadyVisible) {
|
||||
switchCryptoStatus(cryptoStatusDisplayType);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -280,7 +268,22 @@ public class RecipientMvpView implements OnFocusChangeListener, OnClickListener
|
|||
cryptoStatusView.animate().translationX(0).setDuration(300).setListener(new AnimatorListenerAdapter() {
|
||||
@Override
|
||||
public void onAnimationEnd(Animator animation) {
|
||||
switchCryptoStatus(childToDisplay);
|
||||
switchCryptoStatus(cryptoStatusDisplayType);
|
||||
}
|
||||
}).start();
|
||||
}
|
||||
|
||||
|
||||
private void hideCryptoStatus() {
|
||||
if (cryptoStatusView.getVisibility() == View.GONE) {
|
||||
return;
|
||||
}
|
||||
|
||||
cryptoStatusView.animate().translationX(100).setDuration(300).setListener(new AnimatorListenerAdapter() {
|
||||
@Override
|
||||
public void onAnimationEnd(Animator animation) {
|
||||
super.onAnimationEnd(animation);
|
||||
cryptoStatusView.setVisibility(View.GONE);
|
||||
}
|
||||
}).start();
|
||||
}
|
||||
|
@ -297,8 +300,23 @@ public class RecipientMvpView implements OnFocusChangeListener, OnClickListener
|
|||
}
|
||||
|
||||
public void showErrorContactNoAddress() {
|
||||
String errorMessage = activity.getString(R.string.error_contact_address_not_found);
|
||||
Toast.makeText(activity, errorMessage, Toast.LENGTH_LONG).show();
|
||||
Toast.makeText(activity, R.string.error_contact_address_not_found, Toast.LENGTH_LONG).show();
|
||||
}
|
||||
|
||||
public void showErrorOpenPgpConnection() {
|
||||
Toast.makeText(activity, R.string.error_crypto_provider_connect, Toast.LENGTH_LONG).show();
|
||||
}
|
||||
|
||||
public void showErrorOpenPgpUserInteractionRequired() {
|
||||
Toast.makeText(activity, R.string.error_crypto_provider_ui_required, Toast.LENGTH_LONG).show();
|
||||
}
|
||||
|
||||
public void showErrorMissingSignKey() {
|
||||
Toast.makeText(activity, R.string.compose_error_no_signing_key, Toast.LENGTH_LONG).show();
|
||||
}
|
||||
|
||||
public void showErrorPrivateButMissingKeys() {
|
||||
Toast.makeText(activity, R.string.compose_error_private_missing_keys, Toast.LENGTH_LONG).show();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -342,7 +360,16 @@ public class RecipientMvpView implements OnFocusChangeListener, OnClickListener
|
|||
dialog.show(activity.getFragmentManager(), "crypto_settings");
|
||||
}
|
||||
|
||||
public void checkOpenPgpServicePermission(RecipientPresenter recipientPresenter) {
|
||||
activity.getOpenPgpApi().checkPermissionPing(recipientPresenter);
|
||||
}
|
||||
|
||||
public void launchUserInteractionPendingIntent(PendingIntent pendingIntent, int requestCode) {
|
||||
activity.launchUserInteractionPendingIntent(pendingIntent, requestCode);
|
||||
}
|
||||
|
||||
public enum CryptoStatusDisplayType {
|
||||
UNINITIALIZED(VIEW_INDEX_HIDDEN),
|
||||
DISABLED(VIEW_INDEX_CRYPTO_STATUS_DISABLED),
|
||||
SIGN_ONLY(VIEW_INDEX_CRYPTO_STATUS_SIGN_ONLY),
|
||||
OPPORTUNISTIC_NOKEY(VIEW_INDEX_CRYPTO_STATUS_NO_KEY),
|
||||
|
@ -350,7 +377,8 @@ public class RecipientMvpView implements OnFocusChangeListener, OnClickListener
|
|||
OPPORTUNISTIC_TRUSTED(VIEW_INDEX_CRYPTO_STATUS_TRUSTED),
|
||||
PRIVATE_NOKEY(VIEW_INDEX_CRYPTO_STATUS_NO_KEY),
|
||||
PRIVATE_UNTRUSTED(VIEW_INDEX_CRYPTO_STATUS_UNTRUSTED),
|
||||
PRIVATE_TRUSTED(VIEW_INDEX_CRYPTO_STATUS_TRUSTED);
|
||||
PRIVATE_TRUSTED(VIEW_INDEX_CRYPTO_STATUS_TRUSTED),
|
||||
ERROR(VIEW_INDEX_CRYPTO_STATUS_ERROR);
|
||||
|
||||
|
||||
final int childToDisplay;
|
||||
|
|
|
@ -6,17 +6,22 @@ import java.util.Arrays;
|
|||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.app.PendingIntent;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.content.pm.ResolveInfo;
|
||||
import android.net.Uri;
|
||||
import android.os.Bundle;
|
||||
import android.util.Log;
|
||||
import android.view.Menu;
|
||||
|
||||
import com.fsck.k9.Account;
|
||||
import com.fsck.k9.Identity;
|
||||
import com.fsck.k9.K9;
|
||||
import com.fsck.k9.R;
|
||||
import com.fsck.k9.activity.MessageCompose;
|
||||
import com.fsck.k9.activity.compose.ComposeCryptoStatus.ComposeCryptoStatusBuilder;
|
||||
import com.fsck.k9.helper.Contacts;
|
||||
import com.fsck.k9.helper.MailTo;
|
||||
|
@ -27,15 +32,18 @@ import com.fsck.k9.mail.Message.RecipientType;
|
|||
import com.fsck.k9.mail.MessagingException;
|
||||
import com.fsck.k9.mailstore.LocalMessage;
|
||||
import com.fsck.k9.view.RecipientSelectView.Recipient;
|
||||
import org.openintents.openpgp.util.OpenPgpApi;
|
||||
import org.openintents.openpgp.util.OpenPgpApi.PermissionPingCallback;
|
||||
|
||||
|
||||
public class RecipientPresenter {
|
||||
public class RecipientPresenter implements PermissionPingCallback {
|
||||
private static final String STATE_KEY_CC_SHOWN = "state:ccShown";
|
||||
private static final String STATE_KEY_BCC_SHOWN = "state:bccShown";
|
||||
|
||||
private static final int CONTACT_PICKER_TO = 1;
|
||||
private static final int CONTACT_PICKER_CC = 2;
|
||||
private static final int CONTACT_PICKER_BCC = 3;
|
||||
private static final int OPENPGP_USER_INTERACTION = 4;
|
||||
|
||||
|
||||
private final Context context;
|
||||
|
@ -44,8 +52,9 @@ public class RecipientPresenter {
|
|||
private String cryptoProvider;
|
||||
private RecipientType lastFocusedType = RecipientType.TO;
|
||||
private Boolean hasContactPicker;
|
||||
private CryptoMode currentCryptoMode = CryptoMode.OPPORTUNISTIC;
|
||||
private CryptoMode currentCryptoMode = CryptoMode.UNINITIALIZED;
|
||||
private ComposeCryptoStatus currentCryptoStatus;
|
||||
private PendingIntent pendingUserInteractionIntent;
|
||||
|
||||
|
||||
public RecipientPresenter(Context context, RecipientMvpView recipientMvpView, Account account) {
|
||||
|
@ -301,8 +310,6 @@ public class RecipientPresenter {
|
|||
}
|
||||
|
||||
public void updateCryptoStatus() {
|
||||
List<Recipient> recipients = getAllRecipients();
|
||||
|
||||
ComposeCryptoStatusBuilder builder = new ComposeCryptoStatusBuilder()
|
||||
.setCryptoMode(currentCryptoMode)
|
||||
.setRecipients(getAllRecipients());
|
||||
|
@ -315,13 +322,6 @@ public class RecipientPresenter {
|
|||
}
|
||||
|
||||
currentCryptoStatus = builder.build();
|
||||
|
||||
boolean hasNoCryptoProviderOrRecipients = cryptoProvider == null || recipients.isEmpty();
|
||||
if (hasNoCryptoProviderOrRecipients) {
|
||||
recipientMvpView.hideCryptoStatus();
|
||||
return;
|
||||
}
|
||||
|
||||
recipientMvpView.showCryptoStatus(currentCryptoStatus.getCryptoStatusDisplayType());
|
||||
}
|
||||
|
||||
|
@ -438,13 +438,21 @@ public class RecipientPresenter {
|
|||
recipientMvpView.showContactPicker(requestCode);
|
||||
}
|
||||
|
||||
public void onActivityResult(int requestCode, Intent data) {
|
||||
if (requestCode != CONTACT_PICKER_TO && requestCode != CONTACT_PICKER_CC && requestCode != CONTACT_PICKER_BCC) {
|
||||
return;
|
||||
public void onActivityResult(int resultCode, int requestCode, Intent data) {
|
||||
switch (requestCode) {
|
||||
case CONTACT_PICKER_TO:
|
||||
case CONTACT_PICKER_CC:
|
||||
case CONTACT_PICKER_BCC:
|
||||
if (resultCode != Activity.RESULT_OK || data == null) {
|
||||
return;
|
||||
}
|
||||
RecipientType recipientType = recipientTypeFromRequestCode(requestCode);
|
||||
addRecipientFromContactUri(recipientType, data.getData());
|
||||
break;
|
||||
case OPENPGP_USER_INTERACTION:
|
||||
recipientMvpView.checkOpenPgpServicePermission(this);
|
||||
break;
|
||||
}
|
||||
|
||||
RecipientType recipientType = recipientTypeFromRequestCode(requestCode);
|
||||
addRecipientFromContactUri(recipientType, data.getData());
|
||||
}
|
||||
|
||||
private static int recipientTypeToRequestCode(RecipientType type) {
|
||||
|
@ -482,6 +490,16 @@ public class RecipientPresenter {
|
|||
}
|
||||
|
||||
public void onClickCryptoStatus() {
|
||||
if (currentCryptoMode == CryptoMode.ERROR) {
|
||||
if (pendingUserInteractionIntent != null) {
|
||||
recipientMvpView
|
||||
.launchUserInteractionPendingIntent(pendingUserInteractionIntent, OPENPGP_USER_INTERACTION);
|
||||
pendingUserInteractionIntent = null;
|
||||
} else {
|
||||
recipientMvpView.checkOpenPgpServicePermission(this);
|
||||
}
|
||||
return;
|
||||
}
|
||||
recipientMvpView.showCryptoDialog(currentCryptoMode);
|
||||
}
|
||||
|
||||
|
@ -510,22 +528,67 @@ public class RecipientPresenter {
|
|||
}
|
||||
|
||||
ComposeCryptoStatus cryptoStatus = getCurrentCryptoStatus();
|
||||
if (cryptoStatus.isPgpErrorState()) {
|
||||
// TODO: be more specific about this error
|
||||
recipientMvpView.showErrorOpenPgpConnection();
|
||||
return false;
|
||||
}
|
||||
if (cryptoStatus.isMissingSignKey()) {
|
||||
recipientMvpView.showMissingSignKeyError();
|
||||
recipientMvpView.showErrorMissingSignKey();
|
||||
return false;
|
||||
}
|
||||
if (cryptoStatus.isPrivateAndIncomplete()) {
|
||||
recipientMvpView.showPrivateAndIncompleteError();
|
||||
recipientMvpView.showErrorPrivateButMissingKeys();
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public void onCryptoProviderBound() {
|
||||
recipientMvpView.checkOpenPgpServicePermission(this);
|
||||
}
|
||||
|
||||
public void onCryptoProviderError(Exception e) {
|
||||
// TODO handle error case better
|
||||
recipientMvpView.showErrorOpenPgpConnection();
|
||||
currentCryptoMode = CryptoMode.ERROR;
|
||||
Log.e(K9.LOG_TAG, "error connecting to crypto provider!", e);
|
||||
updateCryptoStatus();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPgpPermissionCheckResult(Intent result) {
|
||||
int resultCode = result.getIntExtra(OpenPgpApi.RESULT_CODE, OpenPgpApi.RESULT_CODE_ERROR);
|
||||
switch (resultCode) {
|
||||
case OpenPgpApi.RESULT_CODE_SUCCESS:
|
||||
if (currentCryptoMode == CryptoMode.UNINITIALIZED || currentCryptoMode == CryptoMode.ERROR) {
|
||||
// TODO initialize to other values under some circumstances, e.g. if we reply to an encrypted e-mail
|
||||
currentCryptoMode = CryptoMode.OPPORTUNISTIC;
|
||||
}
|
||||
break;
|
||||
|
||||
case OpenPgpApi.RESULT_CODE_USER_INTERACTION_REQUIRED:
|
||||
recipientMvpView.showErrorOpenPgpUserInteractionRequired();
|
||||
pendingUserInteractionIntent = result.getParcelableExtra(OpenPgpApi.RESULT_INTENT);
|
||||
currentCryptoMode = CryptoMode.ERROR;
|
||||
break;
|
||||
|
||||
case OpenPgpApi.RESULT_CODE_ERROR:
|
||||
default:
|
||||
recipientMvpView.showErrorOpenPgpConnection();
|
||||
currentCryptoMode = CryptoMode.ERROR;
|
||||
break;
|
||||
}
|
||||
updateCryptoStatus();
|
||||
}
|
||||
|
||||
public enum CryptoMode {
|
||||
PRIVATE,
|
||||
OPPORTUNISTIC,
|
||||
SIGN_ONLY,
|
||||
UNINITIALIZED,
|
||||
DISABLE,
|
||||
SIGN_ONLY,
|
||||
OPPORTUNISTIC,
|
||||
PRIVATE,
|
||||
ERROR,
|
||||
}
|
||||
}
|
||||
|
|
|
@ -62,6 +62,14 @@
|
|||
android:tint="@color/openpgp_grey"
|
||||
/>
|
||||
|
||||
<ImageView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center"
|
||||
android:src="@drawable/status_lock_error"
|
||||
android:tint="@color/openpgp_red"
|
||||
/>
|
||||
|
||||
<ImageView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
|
@ -74,7 +82,7 @@
|
|||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center"
|
||||
android:src="@drawable/status_lock_error"
|
||||
android:src="@drawable/status_lock_opportunistic"
|
||||
android:tint="@color/openpgp_orange"
|
||||
/>
|
||||
|
||||
|
|
|
@ -1133,11 +1133,15 @@ Please submit bug reports, contribute new features and ask questions at
|
|||
<string name="address_type_mobile">Mobile</string>
|
||||
<string name="warn_search_disabled">Search in message bodies is disabled in this development version!</string>
|
||||
<string name="compose_error_no_draft_folder">No Drafts folder configured for this account!</string>
|
||||
<string name="compose_error_no_signing_key">Signing requested, but no key selected!</string>
|
||||
<string name="compose_error_private_missing_keys">Private mode enabled, but cannot encrypt to all recipients!</string>
|
||||
<string name="compose_not_saving_unencrypted">Draft NOT saved without encryption!</string>
|
||||
<string name="compose_error_pgp_error">Error with OpenPGP provider. Check your settings!</string>
|
||||
<string name="compose_error_no_signing_key">No key configured for signing! Please check your settings.</string>
|
||||
<string name="compose_error_private_missing_keys">Private mode is enabled, but some recipients do not have keys!</string>
|
||||
<string name="crypto_mode_disabled">Never Sign or Encrypt.</string>
|
||||
<string name="crypto_mode_sign_only">Always Sign, Never Encrypt.</string>
|
||||
<string name="crypto_mode_opportunistic">Always Sign, Encrypt if possible.</string>
|
||||
<string name="crypto_mode_private">Always Sign, Always Encrypt.</string>
|
||||
<string name="error_crypto_provider_connect">Cannot connect to crypto provider, check your settings or click crypto icon to retry!</string>
|
||||
<string name="error_crypto_provider_ui_required">Crypto provider access denied, click crypto icon to retry!</string>
|
||||
|
||||
</resources>
|
||||
|
|
|
@ -57,6 +57,8 @@ public class OpenPgpApi {
|
|||
* PendingIntent RESULT_INTENT (if RESULT_CODE == RESULT_CODE_USER_INTERACTION_REQUIRED)
|
||||
*/
|
||||
|
||||
public static final String ACTION_CHECK_PERMISSION = "org.openintents.openpgp.action.CHECK_PERMISSION";
|
||||
|
||||
/**
|
||||
* DEPRECATED
|
||||
* Same as ACTION_CLEARTEXT_SIGN
|
||||
|
@ -203,7 +205,6 @@ public class OpenPgpApi {
|
|||
*/
|
||||
public static final String ACTION_GET_KEY = "org.openintents.openpgp.action.GET_KEY";
|
||||
|
||||
|
||||
/* Intent extras */
|
||||
public static final String EXTRA_API_VERSION = "api_version";
|
||||
|
||||
|
@ -418,4 +419,18 @@ public class OpenPgpApi {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
public interface PermissionPingCallback {
|
||||
void onPgpPermissionCheckResult(Intent result);
|
||||
}
|
||||
|
||||
public void checkPermissionPing(final PermissionPingCallback permissionPingCallback) {
|
||||
Intent intent = new Intent(OpenPgpApi.ACTION_CHECK_PERMISSION);
|
||||
executeApiAsync(intent, null, null, new IOpenPgpCallback() {
|
||||
@Override
|
||||
public void onReturn(Intent result) {
|
||||
permissionPingCallback.onPgpPermissionCheckResult(result);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue