obtain crypto status through dry-run signencrypt call
This commit is contained in:
parent
99786e0884
commit
cfb7a53cd4
8 changed files with 236 additions and 115 deletions
|
@ -647,12 +647,11 @@ public class MessageCompose extends K9Activity implements OnClickListener,
|
|||
builder = SimpleMessageBuilder.newInstance();
|
||||
}
|
||||
|
||||
recipientPresenter.builderSetProperties(builder);
|
||||
|
||||
builder.setSubject(Utility.stripNewLines(subjectView.getText().toString()))
|
||||
.setSentDate(new Date())
|
||||
.setHideTimeZone(K9.hideTimeZone())
|
||||
.setTo(recipientPresenter.getToAddresses())
|
||||
.setCc(recipientPresenter.getCcAddresses())
|
||||
.setBcc(recipientPresenter.getBccAddresses())
|
||||
.setInReplyTo(repliedToMessageId)
|
||||
.setReferences(referencedMessageIds)
|
||||
.setRequestReadReceipt(requestReadReceipt)
|
||||
|
|
|
@ -8,8 +8,8 @@ import com.fsck.k9.activity.compose.RecipientMvpView.CryptoSpecialModeDisplayTyp
|
|||
import com.fsck.k9.activity.compose.RecipientMvpView.CryptoStatusDisplayType;
|
||||
import com.fsck.k9.activity.compose.RecipientPresenter.CryptoMode;
|
||||
import com.fsck.k9.activity.compose.RecipientPresenter.CryptoProviderState;
|
||||
import com.fsck.k9.message.PgpMessageBuilder.CryptoProviderDryRunStatus;
|
||||
import com.fsck.k9.view.RecipientSelectView.Recipient;
|
||||
import com.fsck.k9.view.RecipientSelectView.RecipientCryptoStatus;
|
||||
|
||||
/** This is an immutable object which contains all relevant metadata entered
|
||||
* during e-mail composition to apply cryptographic operations before sending
|
||||
|
@ -19,25 +19,16 @@ public class ComposeCryptoStatus {
|
|||
|
||||
|
||||
private CryptoProviderState cryptoProviderState;
|
||||
private CryptoMode cryptoMode;
|
||||
private boolean allKeysAvailable;
|
||||
private boolean allKeysVerified;
|
||||
private boolean hasRecipients;
|
||||
private Long signingKeyId;
|
||||
private Long selfEncryptKeyId;
|
||||
private String[] recipientAddresses;
|
||||
private boolean enablePgpInline;
|
||||
private CryptoMode cryptoMode;
|
||||
private CryptoProviderDryRunStatus cryptoProviderDryRunStatus;
|
||||
|
||||
|
||||
public long[] getEncryptKeyIds() {
|
||||
if (selfEncryptKeyId == null) {
|
||||
return null;
|
||||
}
|
||||
return new long[] { selfEncryptKeyId };
|
||||
}
|
||||
|
||||
public String[] getRecipientAddresses() {
|
||||
return recipientAddresses;
|
||||
boolean isCryptoStatusRecipientDependent() {
|
||||
return cryptoProviderState == CryptoProviderState.OK && cryptoMode != CryptoMode.DISABLE;
|
||||
}
|
||||
|
||||
public Long getSigningKeyId() {
|
||||
|
@ -60,22 +51,34 @@ public class ComposeCryptoStatus {
|
|||
throw new AssertionError("all CryptoProviderStates must be handled!");
|
||||
}
|
||||
|
||||
if (cryptoMode == CryptoMode.DISABLE) {
|
||||
return CryptoStatusDisplayType.DISABLED;
|
||||
}
|
||||
|
||||
if (cryptoProviderDryRunStatus == null) {
|
||||
throw new IllegalStateException("Display type must be obtained from provider!");
|
||||
}
|
||||
|
||||
if (cryptoProviderDryRunStatus == CryptoProviderDryRunStatus.ERROR) {
|
||||
return CryptoStatusDisplayType.ERROR;
|
||||
}
|
||||
|
||||
switch (cryptoMode) {
|
||||
case PRIVATE:
|
||||
if (!hasRecipients) {
|
||||
if (cryptoProviderDryRunStatus == CryptoProviderDryRunStatus.NO_RECIPIENTS) {
|
||||
return CryptoStatusDisplayType.PRIVATE_EMPTY;
|
||||
} else if (allKeysAvailable && allKeysVerified) {
|
||||
} else if (cryptoProviderDryRunStatus == CryptoProviderDryRunStatus.OK_KEYS_CONFIRMED) {
|
||||
return CryptoStatusDisplayType.PRIVATE_TRUSTED;
|
||||
} else if (allKeysAvailable) {
|
||||
} else if (cryptoProviderDryRunStatus == CryptoProviderDryRunStatus.OK_KEYS_UNCONFIRMED) {
|
||||
return CryptoStatusDisplayType.PRIVATE_UNTRUSTED;
|
||||
}
|
||||
return CryptoStatusDisplayType.PRIVATE_NOKEY;
|
||||
case OPPORTUNISTIC:
|
||||
if (!hasRecipients) {
|
||||
if (cryptoProviderDryRunStatus == CryptoProviderDryRunStatus.NO_RECIPIENTS) {
|
||||
return CryptoStatusDisplayType.OPPORTUNISTIC_EMPTY;
|
||||
} else if (allKeysAvailable && allKeysVerified) {
|
||||
} else if (cryptoProviderDryRunStatus == CryptoProviderDryRunStatus.OK_KEYS_CONFIRMED) {
|
||||
return CryptoStatusDisplayType.OPPORTUNISTIC_TRUSTED;
|
||||
} else if (allKeysAvailable) {
|
||||
} else if (cryptoProviderDryRunStatus == CryptoProviderDryRunStatus.OK_KEYS_UNCONFIRMED) {
|
||||
return CryptoStatusDisplayType.OPPORTUNISTIC_UNTRUSTED;
|
||||
}
|
||||
return CryptoStatusDisplayType.OPPORTUNISTIC_NOKEY;
|
||||
|
@ -120,12 +123,12 @@ public class ComposeCryptoStatus {
|
|||
return cryptoMode == CryptoMode.OPPORTUNISTIC;
|
||||
}
|
||||
|
||||
public boolean isSignOnly() {
|
||||
boolean isSignOnly() {
|
||||
return cryptoMode == CryptoMode.SIGN_ONLY;
|
||||
}
|
||||
|
||||
public boolean isSigningEnabled() {
|
||||
return cryptoMode != CryptoMode.DISABLE && signingKeyId != null;
|
||||
return cryptoMode != CryptoMode.DISABLE;
|
||||
}
|
||||
|
||||
public boolean isPgpInlineModeEnabled() {
|
||||
|
@ -140,6 +143,14 @@ public class ComposeCryptoStatus {
|
|||
return cryptoProviderState == CryptoProviderState.OK;
|
||||
}
|
||||
|
||||
public String[] getRecipientAddresses() {
|
||||
return recipientAddresses;
|
||||
}
|
||||
|
||||
public boolean hasRecipients() {
|
||||
return recipientAddresses.length > 0;
|
||||
}
|
||||
|
||||
public static class ComposeCryptoStatusBuilder {
|
||||
|
||||
private CryptoProviderState cryptoProviderState;
|
||||
|
@ -159,12 +170,12 @@ public class ComposeCryptoStatus {
|
|||
return this;
|
||||
}
|
||||
|
||||
public ComposeCryptoStatusBuilder setSigningKeyId(long signingKeyId) {
|
||||
public ComposeCryptoStatusBuilder setSigningKeyId(Long signingKeyId) {
|
||||
this.signingKeyId = signingKeyId;
|
||||
return this;
|
||||
}
|
||||
|
||||
public ComposeCryptoStatusBuilder setSelfEncryptId(long selfEncryptKeyId) {
|
||||
public ComposeCryptoStatusBuilder setSelfEncryptId(Long selfEncryptKeyId) {
|
||||
this.selfEncryptKeyId = selfEncryptKeyId;
|
||||
return this;
|
||||
}
|
||||
|
@ -194,28 +205,14 @@ public class ComposeCryptoStatus {
|
|||
}
|
||||
|
||||
ArrayList<String> recipientAddresses = new ArrayList<>();
|
||||
boolean allKeysAvailable = true;
|
||||
boolean allKeysVerified = true;
|
||||
boolean hasRecipients = !recipients.isEmpty();
|
||||
for (Recipient recipient : recipients) {
|
||||
RecipientCryptoStatus cryptoStatus = recipient.getCryptoStatus();
|
||||
recipientAddresses.add(recipient.address.getAddress());
|
||||
if (cryptoStatus.isAvailable()) {
|
||||
if (cryptoStatus == RecipientCryptoStatus.AVAILABLE_UNTRUSTED) {
|
||||
allKeysVerified = false;
|
||||
}
|
||||
} else {
|
||||
allKeysAvailable = false;
|
||||
}
|
||||
}
|
||||
|
||||
ComposeCryptoStatus result = new ComposeCryptoStatus();
|
||||
result.cryptoProviderState = cryptoProviderState;
|
||||
result.cryptoMode = cryptoMode;
|
||||
result.recipientAddresses = recipientAddresses.toArray(new String[0]);
|
||||
result.allKeysAvailable = allKeysAvailable;
|
||||
result.allKeysVerified = allKeysVerified;
|
||||
result.hasRecipients = hasRecipients;
|
||||
result.signingKeyId = signingKeyId;
|
||||
result.selfEncryptKeyId = selfEncryptKeyId;
|
||||
result.enablePgpInline = enablePgpInline;
|
||||
|
@ -223,8 +220,20 @@ public class ComposeCryptoStatus {
|
|||
}
|
||||
}
|
||||
|
||||
ComposeCryptoStatus withCryptoProviderRecipientStatus(CryptoProviderDryRunStatus cryptoProviderDryRunStatus) {
|
||||
ComposeCryptoStatus result = new ComposeCryptoStatus();
|
||||
result.cryptoProviderState = cryptoProviderState;
|
||||
result.cryptoMode = cryptoMode;
|
||||
result.recipientAddresses = recipientAddresses;
|
||||
result.signingKeyId = signingKeyId;
|
||||
result.selfEncryptKeyId = selfEncryptKeyId;
|
||||
result.enablePgpInline = enablePgpInline;
|
||||
result.cryptoProviderDryRunStatus = cryptoProviderDryRunStatus;
|
||||
return result;
|
||||
}
|
||||
|
||||
public enum SendErrorState {
|
||||
PROVIDER_ERROR, SIGN_KEY_NOT_CONFIGURED, PRIVATE_BUT_MISSING_KEYS
|
||||
PROVIDER_ERROR
|
||||
}
|
||||
|
||||
public SendErrorState getSendErrorStateOrNull() {
|
||||
|
@ -232,14 +241,6 @@ public class ComposeCryptoStatus {
|
|||
// TODO: be more specific about this error
|
||||
return SendErrorState.PROVIDER_ERROR;
|
||||
}
|
||||
boolean isSignKeyMissing = signingKeyId == null;
|
||||
if (isSignKeyMissing) {
|
||||
return SendErrorState.SIGN_KEY_NOT_CONFIGURED;
|
||||
}
|
||||
boolean isPrivateModeAndNotAllKeysAvailable = cryptoMode == CryptoMode.PRIVATE && !allKeysAvailable;
|
||||
if (isPrivateModeAndNotAllKeysAvailable) {
|
||||
return SendErrorState.PRIVATE_BUT_MISSING_KEYS;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
|
|
@ -36,7 +36,9 @@ import com.fsck.k9.mail.Flag;
|
|||
import com.fsck.k9.mail.Message;
|
||||
import com.fsck.k9.mail.Message.RecipientType;
|
||||
import com.fsck.k9.message.ComposePgpInlineDecider;
|
||||
import com.fsck.k9.message.MessageBuilder;
|
||||
import com.fsck.k9.message.PgpMessageBuilder;
|
||||
import com.fsck.k9.message.PgpMessageBuilder.CryptoProviderDryRunStatus;
|
||||
import com.fsck.k9.view.RecipientSelectView.Recipient;
|
||||
import org.openintents.openpgp.IOpenPgpService2;
|
||||
import org.openintents.openpgp.util.OpenPgpApi;
|
||||
|
@ -69,9 +71,9 @@ public class RecipientPresenter implements PermissionPingCallback {
|
|||
private Account account;
|
||||
private String openPgpProvider;
|
||||
private Boolean hasContactPicker;
|
||||
private ComposeCryptoStatus cachedCryptoStatus;
|
||||
private PendingIntent pendingUserInteractionIntent;
|
||||
private CryptoProviderState cryptoProviderState = CryptoProviderState.UNCONFIGURED;
|
||||
private ComposeCryptoStatus cachedCryptoStatus;
|
||||
private OpenPgpServiceConnection openPgpServiceConnection;
|
||||
|
||||
|
||||
|
@ -352,38 +354,42 @@ public class RecipientPresenter implements PermissionPingCallback {
|
|||
pendingUserInteractionIntent = null;
|
||||
}
|
||||
|
||||
recipientMvpView.showCryptoStatus(getCurrentCryptoStatus().getCryptoStatusDisplayType());
|
||||
recipientMvpView.showCryptoSpecialMode(getCurrentCryptoStatus().getCryptoSpecialModeDisplayType());
|
||||
Long accountCryptoKey = account.getCryptoKey();
|
||||
if (accountCryptoKey == Account.NO_OPENPGP_KEY) {
|
||||
accountCryptoKey = null;
|
||||
}
|
||||
|
||||
ComposeCryptoStatus composeCryptoStatus = new ComposeCryptoStatusBuilder()
|
||||
.setCryptoProviderState(cryptoProviderState)
|
||||
.setCryptoMode(currentCryptoMode)
|
||||
.setEnablePgpInline(cryptoEnablePgpInline)
|
||||
.setRecipients(getAllRecipients())
|
||||
.setSigningKeyId(accountCryptoKey)
|
||||
.setSelfEncryptId(accountCryptoKey)
|
||||
.build();
|
||||
|
||||
if (composeCryptoStatus.isCryptoStatusRecipientDependent()) {
|
||||
PgpMessageBuilder pgpMessageBuilder = PgpMessageBuilder.newInstance();
|
||||
builderSetProperties(pgpMessageBuilder);
|
||||
pgpMessageBuilder.setCryptoStatus(composeCryptoStatus);
|
||||
|
||||
CryptoProviderDryRunStatus cryptoProviderDryRunStatus =
|
||||
pgpMessageBuilder.retrieveCryptoProviderRecipientStatus();
|
||||
|
||||
composeCryptoStatus = composeCryptoStatus.withCryptoProviderRecipientStatus(cryptoProviderDryRunStatus);
|
||||
}
|
||||
|
||||
cachedCryptoStatus = composeCryptoStatus;
|
||||
recipientMvpView.showCryptoStatus(composeCryptoStatus.getCryptoStatusDisplayType());
|
||||
recipientMvpView.showCryptoSpecialMode(composeCryptoStatus.getCryptoSpecialModeDisplayType());
|
||||
}
|
||||
|
||||
public ComposeCryptoStatus getCurrentCryptoStatus() {
|
||||
if (cachedCryptoStatus == null) {
|
||||
ComposeCryptoStatusBuilder builder = new ComposeCryptoStatusBuilder()
|
||||
.setCryptoProviderState(cryptoProviderState)
|
||||
.setCryptoMode(currentCryptoMode)
|
||||
.setEnablePgpInline(cryptoEnablePgpInline)
|
||||
.setRecipients(getAllRecipients());
|
||||
|
||||
long accountCryptoKey = account.getCryptoKey();
|
||||
if (accountCryptoKey != Account.NO_OPENPGP_KEY) {
|
||||
// TODO split these into individual settings? maybe after key is bound to identity
|
||||
builder.setSigningKeyId(accountCryptoKey);
|
||||
builder.setSelfEncryptId(accountCryptoKey);
|
||||
}
|
||||
|
||||
cachedCryptoStatus = builder.build();
|
||||
}
|
||||
|
||||
return cachedCryptoStatus;
|
||||
}
|
||||
|
||||
public boolean isForceTextMessageFormat() {
|
||||
if (cryptoEnablePgpInline) {
|
||||
ComposeCryptoStatus cryptoStatus = getCurrentCryptoStatus();
|
||||
return cryptoStatus.isEncryptionEnabled() || cryptoStatus.isSigningEnabled();
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
return cryptoEnablePgpInline;
|
||||
}
|
||||
|
||||
void onToTokenAdded() {
|
||||
|
@ -589,12 +595,6 @@ public class RecipientPresenter implements PermissionPingCallback {
|
|||
case PROVIDER_ERROR:
|
||||
recipientMvpView.showErrorOpenPgpConnection();
|
||||
break;
|
||||
case SIGN_KEY_NOT_CONFIGURED:
|
||||
recipientMvpView.showErrorMissingSignKey();
|
||||
break;
|
||||
case PRIVATE_BUT_MISSING_KEYS:
|
||||
recipientMvpView.showErrorPrivateButMissingKeys();
|
||||
break;
|
||||
default:
|
||||
throw new AssertionError("not all error states handled, this is a bug!");
|
||||
}
|
||||
|
@ -720,9 +720,16 @@ public class RecipientPresenter implements PermissionPingCallback {
|
|||
}
|
||||
|
||||
|
||||
public void builderSetProperties(PgpMessageBuilder pgpBuilder) {
|
||||
pgpBuilder.setOpenPgpApi(getOpenPgpApi());
|
||||
pgpBuilder.setCryptoStatus(getCurrentCryptoStatus());
|
||||
public void builderSetProperties(MessageBuilder messageBuilder) {
|
||||
messageBuilder.setTo(getToAddresses());
|
||||
messageBuilder.setCc(getCcAddresses());
|
||||
messageBuilder.setBcc(getBccAddresses());
|
||||
|
||||
if (messageBuilder instanceof PgpMessageBuilder) {
|
||||
PgpMessageBuilder pgpMessageBuilder = (PgpMessageBuilder) messageBuilder;
|
||||
pgpMessageBuilder.setOpenPgpApi(getOpenPgpApi());
|
||||
pgpMessageBuilder.setCryptoStatus(getCurrentCryptoStatus());
|
||||
}
|
||||
}
|
||||
|
||||
public void onMenuSetPgpInline(boolean enablePgpInline) {
|
||||
|
@ -773,10 +780,9 @@ public class RecipientPresenter implements PermissionPingCallback {
|
|||
}
|
||||
|
||||
void onClickCryptoSpecialModeIndicator() {
|
||||
ComposeCryptoStatus currentCryptoStatus = getCurrentCryptoStatus();
|
||||
if (currentCryptoStatus.isSignOnly()) {
|
||||
if (currentCryptoMode == CryptoMode.SIGN_ONLY) {
|
||||
recipientMvpView.showOpenPgpSignOnlyDialog(false);
|
||||
} else if (currentCryptoStatus.isPgpInlineModeEnabled()) {
|
||||
} else if (cryptoEnablePgpInline) {
|
||||
recipientMvpView.showOpenPgpInlineDialog(false);
|
||||
} else {
|
||||
throw new IllegalStateException("This icon should not be clickable while no special mode is active!");
|
||||
|
@ -804,7 +810,7 @@ public class RecipientPresenter implements PermissionPingCallback {
|
|||
PRIVATE,
|
||||
}
|
||||
|
||||
public static interface RecipientsChangedListener {
|
||||
public void onRecipientsChanged();
|
||||
public interface RecipientsChangedListener {
|
||||
void onRecipientsChanged();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -113,6 +113,10 @@ public class PgpMessageBuilder extends MessageBuilder {
|
|||
throw new MessagingException("Attachments are not supported in PGP/INLINE format!");
|
||||
}
|
||||
|
||||
if (shouldEncrypt && !cryptoStatus.hasRecipients()) {
|
||||
throw new MessagingException("Must have recipients to build message!");
|
||||
}
|
||||
|
||||
if (pgpApiIntent == null) {
|
||||
pgpApiIntent = buildOpenPgpApiIntent(shouldSign, shouldEncrypt, isPgpInlineMode);
|
||||
}
|
||||
|
@ -131,8 +135,7 @@ public class PgpMessageBuilder extends MessageBuilder {
|
|||
}
|
||||
|
||||
@NonNull
|
||||
private Intent buildOpenPgpApiIntent(boolean shouldSign, boolean shouldEncrypt, boolean isPgpInlineMode)
|
||||
throws MessagingException {
|
||||
private Intent buildOpenPgpApiIntent(boolean shouldSign, boolean shouldEncrypt, boolean isPgpInlineMode) {
|
||||
Intent pgpApiIntent;
|
||||
if (shouldEncrypt) {
|
||||
if (!shouldSign) {
|
||||
|
@ -141,18 +144,8 @@ public class PgpMessageBuilder extends MessageBuilder {
|
|||
// pgpApiIntent = new Intent(shouldSign ? OpenPgpApi.ACTION_SIGN_AND_ENCRYPT : OpenPgpApi.ACTION_ENCRYPT);
|
||||
pgpApiIntent = new Intent(OpenPgpApi.ACTION_SIGN_AND_ENCRYPT);
|
||||
|
||||
long[] encryptKeyIds = cryptoStatus.getEncryptKeyIds();
|
||||
if (encryptKeyIds != null) {
|
||||
pgpApiIntent.putExtra(OpenPgpApi.EXTRA_KEY_IDS, encryptKeyIds);
|
||||
}
|
||||
|
||||
if(!isDraft()) {
|
||||
String[] encryptRecipientAddresses = cryptoStatus.getRecipientAddresses();
|
||||
boolean hasRecipientAddresses = encryptRecipientAddresses != null && encryptRecipientAddresses.length > 0;
|
||||
if (!hasRecipientAddresses) {
|
||||
throw new MessagingException("encryption is enabled, but no recipient specified!");
|
||||
}
|
||||
pgpApiIntent.putExtra(OpenPgpApi.EXTRA_USER_IDS, encryptRecipientAddresses);
|
||||
pgpApiIntent.putExtra(OpenPgpApi.EXTRA_USER_IDS, cryptoStatus.getRecipientAddresses());
|
||||
pgpApiIntent.putExtra(OpenPgpApi.EXTRA_OPPORTUNISTIC_ENCRYPTION, cryptoStatus.isEncryptionOpportunistic());
|
||||
}
|
||||
} else {
|
||||
|
@ -333,4 +326,47 @@ public class PgpMessageBuilder extends MessageBuilder {
|
|||
public void setCryptoStatus(ComposeCryptoStatus cryptoStatus) {
|
||||
this.cryptoStatus = cryptoStatus;
|
||||
}
|
||||
|
||||
public CryptoProviderDryRunStatus retrieveCryptoProviderRecipientStatus() {
|
||||
boolean shouldSign = cryptoStatus.isSigningEnabled();
|
||||
boolean shouldEncrypt = cryptoStatus.isEncryptionEnabled();
|
||||
boolean isPgpInlineMode = cryptoStatus.isPgpInlineModeEnabled();
|
||||
|
||||
Intent apiIntent = buildOpenPgpApiIntent(shouldSign, shouldEncrypt, isPgpInlineMode);
|
||||
apiIntent.putExtra(OpenPgpApi.EXTRA_DRY_RUN, true);
|
||||
|
||||
Intent result = openPgpApi.executeApi(apiIntent, (InputStream) null, null);
|
||||
switch (result.getIntExtra(OpenPgpApi.RESULT_CODE, OpenPgpApi.RESULT_CODE_ERROR)) {
|
||||
case OpenPgpApi.RESULT_CODE_SUCCESS:
|
||||
if (result.getBooleanExtra(OpenPgpApi.RESULT_KEYS_CONFIRMED, false)) {
|
||||
return CryptoProviderDryRunStatus.OK_KEYS_CONFIRMED;
|
||||
} else {
|
||||
return CryptoProviderDryRunStatus.OK_KEYS_UNCONFIRMED;
|
||||
}
|
||||
case OpenPgpApi.RESULT_CODE_ERROR:
|
||||
OpenPgpError error = result.getParcelableExtra(OpenPgpApi.RESULT_ERROR);
|
||||
if (error == null) {
|
||||
return CryptoProviderDryRunStatus.ERROR;
|
||||
}
|
||||
switch (error.getErrorId()) {
|
||||
case OpenPgpError.NO_USER_IDS:
|
||||
return CryptoProviderDryRunStatus.NO_RECIPIENTS;
|
||||
case OpenPgpError.OPPORTUNISTIC_MISSING_KEYS:
|
||||
return CryptoProviderDryRunStatus.OK_KEYS_MISSING;
|
||||
}
|
||||
|
||||
case OpenPgpApi.RESULT_CODE_USER_INTERACTION_REQUIRED:
|
||||
// should never happen, so treat as error!
|
||||
default:
|
||||
return CryptoProviderDryRunStatus.ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
public enum CryptoProviderDryRunStatus {
|
||||
NO_RECIPIENTS,
|
||||
OK_KEYS_MISSING,
|
||||
OK_KEYS_UNCONFIRMED,
|
||||
OK_KEYS_CONFIRMED,
|
||||
ERROR
|
||||
}
|
||||
}
|
||||
|
|
|
@ -110,7 +110,7 @@
|
|||
tools:visibility="visible"
|
||||
android:inAnimation="@anim/fade_in"
|
||||
android:outAnimation="@anim/fade_out"
|
||||
custom:previewInitialChild="2">
|
||||
custom:previewInitialChild="7">
|
||||
|
||||
<ImageView
|
||||
android:layout_width="wrap_content"
|
||||
|
@ -246,6 +246,14 @@
|
|||
|
||||
</FrameLayout>
|
||||
|
||||
<ImageView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center"
|
||||
android:src="@drawable/status_lock_opportunistic"
|
||||
android:tint="?attr/openpgp_grey"
|
||||
/>
|
||||
|
||||
</com.fsck.k9.view.ToolableViewAnimator>
|
||||
|
||||
</LinearLayout>
|
||||
|
|
|
@ -26,6 +26,7 @@ import org.junit.Before;
|
|||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.openintents.openpgp.IOpenPgpService2;
|
||||
import org.openintents.openpgp.OpenPgpError;
|
||||
import org.openintents.openpgp.util.OpenPgpApi;
|
||||
import org.openintents.openpgp.util.OpenPgpServiceConnection;
|
||||
import org.openintents.openpgp.util.ShadowOpenPgpAsyncTask;
|
||||
|
@ -60,6 +61,7 @@ public class RecipientPresenterTest {
|
|||
private Account account;
|
||||
private RecipientMvpView recipientMvpView;
|
||||
private RecipientPresenter.RecipientsChangedListener listener;
|
||||
private Intent noUserIdsResultIntent;
|
||||
|
||||
|
||||
@Before
|
||||
|
@ -76,6 +78,11 @@ public class RecipientPresenterTest {
|
|||
recipientPresenter = new RecipientPresenter(
|
||||
context, loaderManager, recipientMvpView, account, composePgpInlineDecider, replyToParser, listener);
|
||||
recipientPresenter.updateCryptoStatus();
|
||||
|
||||
noUserIdsResultIntent = new Intent();
|
||||
noUserIdsResultIntent.putExtra(OpenPgpApi.RESULT_CODE, OpenPgpApi.RESULT_CODE_ERROR);
|
||||
noUserIdsResultIntent.putExtra(
|
||||
OpenPgpApi.RESULT_ERROR, new OpenPgpError(OpenPgpError.NO_USER_IDS, "dummy error msg"));
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -124,7 +131,7 @@ public class RecipientPresenterTest {
|
|||
|
||||
@Test
|
||||
public void getCurrentCryptoStatus_withCryptoProvider() throws Exception {
|
||||
setupCryptoProvider();
|
||||
setupCryptoProvider(noUserIdsResultIntent);
|
||||
|
||||
ComposeCryptoStatus status = recipientPresenter.getCurrentCryptoStatus();
|
||||
|
||||
|
@ -134,8 +141,8 @@ public class RecipientPresenterTest {
|
|||
}
|
||||
|
||||
@Test
|
||||
public void getCurrentCryptoStatus_withOpportunistic() throws Exception {
|
||||
setupCryptoProvider();
|
||||
public void getCurrentCryptoStatus_withOpportunisticEmpty() throws Exception {
|
||||
setupCryptoProvider(noUserIdsResultIntent);
|
||||
|
||||
recipientPresenter.onCryptoModeChanged(CryptoMode.OPPORTUNISTIC);
|
||||
ComposeCryptoStatus status = recipientPresenter.getCurrentCryptoStatus();
|
||||
|
@ -145,9 +152,71 @@ public class RecipientPresenterTest {
|
|||
assertTrue(status.shouldUsePgpMessageBuilder());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getCurrentCryptoStatus_withOpportunistic() throws Exception {
|
||||
Intent resultIntent = new Intent();
|
||||
resultIntent.putExtra(OpenPgpApi.RESULT_CODE, OpenPgpApi.RESULT_CODE_SUCCESS);
|
||||
resultIntent.putExtra(OpenPgpApi.RESULT_KEYS_CONFIRMED, false);
|
||||
setupCryptoProvider(resultIntent);
|
||||
|
||||
recipientPresenter.onCryptoModeChanged(CryptoMode.OPPORTUNISTIC);
|
||||
ComposeCryptoStatus status = recipientPresenter.getCurrentCryptoStatus();
|
||||
|
||||
assertEquals(CryptoStatusDisplayType.OPPORTUNISTIC_UNTRUSTED, status.getCryptoStatusDisplayType());
|
||||
assertTrue(status.isProviderStateOk());
|
||||
assertTrue(status.shouldUsePgpMessageBuilder());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getCurrentCryptoStatus_withOpportunistic__missingKeys() throws Exception {
|
||||
Intent resultIntent = new Intent();
|
||||
resultIntent.putExtra(OpenPgpApi.RESULT_CODE, OpenPgpApi.RESULT_CODE_ERROR);
|
||||
resultIntent.putExtra(OpenPgpApi.RESULT_ERROR, new OpenPgpError(OpenPgpError.OPPORTUNISTIC_MISSING_KEYS,
|
||||
"dummy error msg"));
|
||||
setupCryptoProvider(resultIntent);
|
||||
|
||||
recipientPresenter.onCryptoModeChanged(CryptoMode.OPPORTUNISTIC);
|
||||
ComposeCryptoStatus status = recipientPresenter.getCurrentCryptoStatus();
|
||||
|
||||
assertEquals(CryptoStatusDisplayType.OPPORTUNISTIC_NOKEY, status.getCryptoStatusDisplayType());
|
||||
assertTrue(status.isProviderStateOk());
|
||||
assertTrue(status.shouldUsePgpMessageBuilder());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getCurrentCryptoStatus_withOpportunistic__privateMissingKeys() throws Exception {
|
||||
Intent resultIntent = new Intent();
|
||||
resultIntent.putExtra(OpenPgpApi.RESULT_CODE, OpenPgpApi.RESULT_CODE_ERROR);
|
||||
resultIntent.putExtra(OpenPgpApi.RESULT_ERROR, new OpenPgpError(OpenPgpError.OPPORTUNISTIC_MISSING_KEYS,
|
||||
"dummy error msg"));
|
||||
setupCryptoProvider(resultIntent);
|
||||
|
||||
recipientPresenter.onCryptoModeChanged(CryptoMode.PRIVATE);
|
||||
ComposeCryptoStatus status = recipientPresenter.getCurrentCryptoStatus();
|
||||
|
||||
assertEquals(CryptoStatusDisplayType.PRIVATE_NOKEY, status.getCryptoStatusDisplayType());
|
||||
assertTrue(status.isProviderStateOk());
|
||||
assertTrue(status.shouldUsePgpMessageBuilder());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getCurrentCryptoStatus_withOpportunistic__confirmed() throws Exception {
|
||||
Intent resultIntent = new Intent();
|
||||
resultIntent.putExtra(OpenPgpApi.RESULT_CODE, OpenPgpApi.RESULT_CODE_SUCCESS);
|
||||
resultIntent.putExtra(OpenPgpApi.RESULT_KEYS_CONFIRMED, true);
|
||||
setupCryptoProvider(resultIntent);
|
||||
|
||||
recipientPresenter.onCryptoModeChanged(CryptoMode.OPPORTUNISTIC);
|
||||
ComposeCryptoStatus status = recipientPresenter.getCurrentCryptoStatus();
|
||||
|
||||
assertEquals(CryptoStatusDisplayType.OPPORTUNISTIC_TRUSTED, status.getCryptoStatusDisplayType());
|
||||
assertTrue(status.isProviderStateOk());
|
||||
assertTrue(status.shouldUsePgpMessageBuilder());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getCurrentCryptoStatus_withModeDisabled() throws Exception {
|
||||
setupCryptoProvider();
|
||||
setupCryptoProvider(noUserIdsResultIntent);
|
||||
|
||||
recipientPresenter.onCryptoModeChanged(CryptoMode.DISABLE);
|
||||
ComposeCryptoStatus status = recipientPresenter.getCurrentCryptoStatus();
|
||||
|
@ -159,7 +228,7 @@ public class RecipientPresenterTest {
|
|||
|
||||
@Test
|
||||
public void getCurrentCryptoStatus_withModePrivate() throws Exception {
|
||||
setupCryptoProvider();
|
||||
setupCryptoProvider(noUserIdsResultIntent);
|
||||
|
||||
recipientPresenter.onCryptoModeChanged(CryptoMode.PRIVATE);
|
||||
ComposeCryptoStatus status = recipientPresenter.getCurrentCryptoStatus();
|
||||
|
@ -171,7 +240,7 @@ public class RecipientPresenterTest {
|
|||
|
||||
@Test
|
||||
public void getCurrentCryptoStatus_withModeSignOnly() throws Exception {
|
||||
setupCryptoProvider();
|
||||
setupCryptoProvider(noUserIdsResultIntent);
|
||||
|
||||
recipientPresenter.onMenuSetSignOnly(true);
|
||||
ComposeCryptoStatus status = recipientPresenter.getCurrentCryptoStatus();
|
||||
|
@ -184,7 +253,7 @@ public class RecipientPresenterTest {
|
|||
|
||||
@Test
|
||||
public void getCurrentCryptoStatus_withModeInline() throws Exception {
|
||||
setupCryptoProvider();
|
||||
setupCryptoProvider(noUserIdsResultIntent);
|
||||
|
||||
recipientPresenter.onMenuSetPgpInline(true);
|
||||
ComposeCryptoStatus status = recipientPresenter.getCurrentCryptoStatus();
|
||||
|
@ -248,7 +317,7 @@ public class RecipientPresenterTest {
|
|||
verify(listener).onRecipientsChanged();
|
||||
}
|
||||
|
||||
private void setupCryptoProvider() throws android.os.RemoteException {
|
||||
private void setupCryptoProvider(Intent returnedIntent) throws android.os.RemoteException {
|
||||
Account account = mock(Account.class);
|
||||
OpenPgpServiceConnection openPgpServiceConnection = mock(OpenPgpServiceConnection.class);
|
||||
IOpenPgpService2 openPgpService2 = mock(IOpenPgpService2.class);
|
||||
|
@ -260,7 +329,7 @@ public class RecipientPresenterTest {
|
|||
when(openPgpServiceConnection.isBound()).thenReturn(true);
|
||||
when(openPgpServiceConnection.getService()).thenReturn(openPgpService2);
|
||||
when(openPgpService2.execute(any(Intent.class), any(ParcelFileDescriptor.class), any(Integer.class)))
|
||||
.thenReturn(permissionPingIntent);
|
||||
.thenReturn(permissionPingIntent, returnedIntent);
|
||||
|
||||
Robolectric.getBackgroundThreadScheduler().pause();
|
||||
recipientPresenter.setOpenPgpServiceConnection(openPgpServiceConnection, CRYPTO_PROVIDER);
|
||||
|
|
|
@ -275,7 +275,6 @@ public class PgpMessageBuilderTest {
|
|||
|
||||
Intent expectedApiIntent = new Intent(OpenPgpApi.ACTION_SIGN_AND_ENCRYPT);
|
||||
expectedApiIntent.putExtra(OpenPgpApi.EXTRA_SIGN_KEY_ID, TEST_SIGN_KEY_ID);
|
||||
expectedApiIntent.putExtra(OpenPgpApi.EXTRA_KEY_IDS, new long[] { TEST_SELF_ENCRYPT_KEY_ID });
|
||||
expectedApiIntent.putExtra(OpenPgpApi.EXTRA_REQUEST_ASCII_ARMOR, true);
|
||||
expectedApiIntent.putExtra(OpenPgpApi.EXTRA_OPPORTUNISTIC_ENCRYPTION, false);
|
||||
expectedApiIntent.putExtra(OpenPgpApi.EXTRA_USER_IDS, cryptoStatus.getRecipientAddresses());
|
||||
|
@ -328,7 +327,6 @@ public class PgpMessageBuilderTest {
|
|||
|
||||
Intent expectedApiIntent = new Intent(OpenPgpApi.ACTION_SIGN_AND_ENCRYPT);
|
||||
expectedApiIntent.putExtra(OpenPgpApi.EXTRA_SIGN_KEY_ID, TEST_SIGN_KEY_ID);
|
||||
expectedApiIntent.putExtra(OpenPgpApi.EXTRA_KEY_IDS, new long[] { TEST_SELF_ENCRYPT_KEY_ID });
|
||||
expectedApiIntent.putExtra(OpenPgpApi.EXTRA_REQUEST_ASCII_ARMOR, true);
|
||||
expectedApiIntent.putExtra(OpenPgpApi.EXTRA_OPPORTUNISTIC_ENCRYPTION, false);
|
||||
expectedApiIntent.putExtra(OpenPgpApi.EXTRA_USER_IDS, cryptoStatus.getRecipientAddresses());
|
||||
|
|
|
@ -256,6 +256,10 @@ public class OpenPgpApi {
|
|||
public static final int AUTOCRYPT_STATUS_AVAILABLE = 2;
|
||||
public static final int AUTOCRYPT_STATUS_MUTUAL = 3;
|
||||
|
||||
// TODO remove again
|
||||
public static final String EXTRA_DRY_RUN = "dry_run";
|
||||
public static final String RESULT_KEYS_CONFIRMED = "keys_confirmed";
|
||||
|
||||
// optional extras:
|
||||
public static final String EXTRA_PASSPHRASE = "passphrase";
|
||||
public static final String EXTRA_ORIGINAL_FILENAME = "original_filename";
|
||||
|
|
Loading…
Reference in a new issue