Skip to content

Commit

Permalink
Add AutocryptKeyTransferActivity
Browse files Browse the repository at this point in the history
  • Loading branch information
Valodim authored and cketti committed May 20, 2018
1 parent 20b28e8 commit 6794a15
Show file tree
Hide file tree
Showing 16 changed files with 604 additions and 4 deletions.
6 changes: 6 additions & 0 deletions k9mail/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -191,6 +191,12 @@
android:label="@string/folder_settings_title"
android:theme="@android:style/Theme.Dialog"/>

<activity
android:name=".ui.endtoend.AutocryptKeyTransferActivity"
android:configChanges="locale"
android:label="@string/ac_transfer_title"
/>

<activity
android:name=".activity.FolderList"
android:configChanges="locale"
Expand Down
11 changes: 11 additions & 0 deletions k9mail/src/main/java/com/fsck/k9/ActivityExtensions.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package com.fsck.k9

import android.app.Activity
import android.support.annotation.StringRes
import android.widget.Toast

fun Activity.finishWithErrorToast(@StringRes errorRes: Int, vararg formatArgs: String) {
val text = getString(errorRes, *formatArgs)
Toast.makeText(this, text, Toast.LENGTH_LONG).show()
finish()
}
12 changes: 9 additions & 3 deletions k9mail/src/main/java/com/fsck/k9/DI.kt
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,9 @@ package com.fsck.k9

import android.app.Application
import com.fsck.k9.controller.MessagingController
import com.fsck.k9.crypto.openPgpModule
import com.fsck.k9.mail.TransportProvider
import com.fsck.k9.ui.endtoend.endToEndUiModule
import com.fsck.k9.ui.settings.settingsUiModule
import com.fsck.k9.widget.unread.unreadWidgetModule
import org.koin.Koin
Expand All @@ -17,12 +20,15 @@ object DI {
private val mainModule = applicationContext {
bean { Preferences.getPreferences(get()) }
bean { MessagingController.getInstance(get()) }
bean { TransportProvider() }
}

val appModules = listOf(
mainModule,
settingsUiModule,
unreadWidgetModule
mainModule,
settingsUiModule,
unreadWidgetModule,
endToEndUiModule,
openPgpModule
)

@JvmStatic fun start(application: Application) {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
package com.fsck.k9.autocrypt;


import java.util.Date;

import android.content.res.Resources;

import com.fsck.k9.K9;
import com.fsck.k9.R;
import com.fsck.k9.mail.Address;
import com.fsck.k9.mail.Flag;
import com.fsck.k9.mail.Message;
import com.fsck.k9.mail.Message.RecipientType;
import com.fsck.k9.mail.MessagingException;
import com.fsck.k9.mail.internet.MimeBodyPart;
import com.fsck.k9.mail.internet.MimeHeader;
import com.fsck.k9.mail.internet.MimeMessage;
import com.fsck.k9.mail.internet.MimeMessageHelper;
import com.fsck.k9.mail.internet.MimeMultipart;
import com.fsck.k9.mail.internet.TextBody;
import com.fsck.k9.mailstore.BinaryMemoryBody;


public class AutocryptTransferMessageUtil {
public static Message createAutocryptTransferMessage(Resources resources, byte[] data, Address address) {
try {
String subjectText = resources.getString(R.string.ac_transfer_msg_subject);
String messageText = resources.getString(R.string.ac_transfer_msg_body);

MimeBodyPart textBodyPart = new MimeBodyPart(new TextBody(messageText));
MimeBodyPart dataBodyPart = new MimeBodyPart(new BinaryMemoryBody(data, "7bit"));
dataBodyPart.setHeader(MimeHeader.HEADER_CONTENT_TYPE, "application/autocrypt-setup");
dataBodyPart.setHeader(MimeHeader.HEADER_CONTENT_DISPOSITION, "attachment; filename=\"autocrypt-setup-message\"");

MimeMultipart messageBody = MimeMultipart.newInstance();
messageBody.addBodyPart(textBodyPart);
messageBody.addBodyPart(dataBodyPart);

MimeMessage message = new MimeMessage();
MimeMessageHelper.setBody(message, messageBody);

Date nowDate = new Date();

message.setFlag(Flag.X_DOWNLOADED_FULL, true);
message.setSubject(subjectText);
message.setHeader("Autocrypt-Setup-Message", "v1");
message.setInternalDate(nowDate);
message.addSentDate(nowDate, K9.hideTimeZone());
message.setFrom(address);
message.setRecipients(RecipientType.TO, new Address[] { address });

return message;
} catch (MessagingException e) {
throw new AssertionError(e);
}
}
}
8 changes: 8 additions & 0 deletions k9mail/src/main/java/com/fsck/k9/crypto/KoinModule.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package com.fsck.k9.crypto

import org.koin.dsl.module.applicationContext
import org.openintents.openpgp.OpenPgpApiManager

val openPgpModule = applicationContext {
factory { params -> OpenPgpApiManager(get(), params["lifecycle"]) }
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,132 @@
package com.fsck.k9.ui.endtoend


import android.app.PendingIntent
import android.content.Context
import android.content.Intent
import android.content.IntentSender.SendIntentException
import android.os.Build
import android.os.Bundle
import android.transition.TransitionInflater
import android.transition.TransitionManager
import android.view.View
import com.fsck.k9.R
import com.fsck.k9.activity.K9Activity
import com.fsck.k9.finishWithErrorToast
import com.fsck.k9.mail.TransportProvider
import com.fsck.k9.view.StatusIndicator
import kotlinx.android.synthetic.main.crypto_key_transfer.*
import org.koin.android.architecture.ext.viewModel
import org.koin.android.ext.android.inject
import org.openintents.openpgp.OpenPgpApiManager
import timber.log.Timber


class AutocryptKeyTransferActivity : K9Activity() {
private val viewModel: AutocryptKeyTransferViewModel by viewModel()
private val transportProvider: TransportProvider by inject()
private val openPgpApiManager: OpenPgpApiManager by inject { mapOf("lifecycle" to lifecycle) }
private lateinit var presenter: AutocryptKeyTransferPresenter

override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.crypto_key_transfer)

val account = intent.getStringExtra(EXTRA_ACCOUNT)

presenter = AutocryptKeyTransferPresenter(applicationContext, this, viewModel, openPgpApiManager, transportProvider)
presenter.initFromIntent(account)

transfer_send_button.setOnClickListener { presenter.onClickTransferSend() }
transfer_show_code_button.setOnClickListener { presenter.onClickShowTransferCode() }
}

fun setAddress(address: String) {
transfer_address_1.text = address
transfer_address_2.text = address
}

fun sceneBegin() {
transfer_send_button.visibility = View.VISIBLE
transfer_msg_info.visibility = View.VISIBLE
transfer_layout_generating.visibility = View.GONE
transfer_layout_sending.visibility = View.GONE
transfer_layout_finish.visibility = View.GONE
transfer_show_code_button.visibility = View.GONE
}

fun sceneGeneratingAndSending() {
setupSceneTransition()

transfer_send_button.visibility = View.GONE
transfer_msg_info.visibility = View.GONE
transfer_layout_generating.visibility = View.VISIBLE
transfer_layout_sending.visibility = View.VISIBLE
transfer_layout_finish.visibility = View.GONE
transfer_show_code_button.visibility = View.GONE
}

fun sceneFinished() {
setupSceneTransition()

transfer_send_button.visibility = View.GONE
transfer_msg_info.visibility = View.GONE
transfer_layout_generating.visibility = View.VISIBLE
transfer_layout_sending.visibility = View.VISIBLE
transfer_layout_finish.visibility = View.VISIBLE
transfer_show_code_button.visibility = View.VISIBLE
}

fun setLoadingStateGenerating() {
transfer_progress_generating.setDisplayedChild(StatusIndicator.Status.PROGRESS)
transfer_progress_sending.setDisplayedChild(StatusIndicator.Status.IDLE)
}

fun setLoadingStateSending() {
transfer_progress_generating.setDisplayedChild(StatusIndicator.Status.OK)
transfer_progress_sending.setDisplayedChild(StatusIndicator.Status.PROGRESS)
}

fun setLoadingStateSendingFailed() {
transfer_progress_generating.setDisplayedChild(StatusIndicator.Status.OK)
transfer_progress_sending.setDisplayedChild(StatusIndicator.Status.ERROR)
}

fun setLoadingStateFinished() {
transfer_progress_generating.setDisplayedChild(StatusIndicator.Status.OK)
transfer_progress_sending.setDisplayedChild(StatusIndicator.Status.OK)
}

fun finishWithInvalidAccountError() {
finishWithErrorToast(R.string.toast_account_not_found)
}

fun finishWithProviderConnectError(providerName: String) {
finishWithErrorToast(R.string.toast_openpgp_provider_error, providerName)
}

fun launchUserInteractionPendingIntent(pendingIntent: PendingIntent) {
try {
startIntentSender(pendingIntent.intentSender, null, 0, 0, 0)
} catch (e: SendIntentException) {
Timber.e(e)
}
}

private fun setupSceneTransition() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
val transition = TransitionInflater.from(this).inflateTransition(R.transition.transfer_transitions)
TransitionManager.beginDelayedTransition(findViewById(android.R.id.content), transition)
}
}

companion object {
private const val EXTRA_ACCOUNT = "account"

fun createIntent(context: Context, accountUuid: String): Intent {
val intent = Intent(context, AutocryptKeyTransferActivity::class.java)
intent.putExtra(EXTRA_ACCOUNT, accountUuid)
return intent
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
package com.fsck.k9.ui.endtoend

import android.app.PendingIntent
import android.arch.lifecycle.LiveData
import android.content.Intent
import android.content.res.Resources
import com.fsck.k9.Account
import com.fsck.k9.autocrypt.AutocryptTransferMessageUtil
import com.fsck.k9.mail.Address
import com.fsck.k9.mail.Message
import kotlinx.coroutines.experimental.android.UI
import kotlinx.coroutines.experimental.launch
import org.jetbrains.anko.coroutines.experimental.bg
import org.openintents.openpgp.util.OpenPgpApi
import java.io.ByteArrayOutputStream
import java.io.InputStream

class AutocryptKeyTransferLiveData : LiveData<AutocryptKeyTransferLiveData.AutocryptSetupMessage>() {
fun loadAutocryptSetupMessageAsync(resources: Resources, openPgpApi: OpenPgpApi, account: Account) {
launch(UI) {
val setupMessage = bg {
loadAutocryptSetupMessage(resources, openPgpApi, account)
}

value = setupMessage.await()
}
}

private fun loadAutocryptSetupMessage(resources: Resources, openPgpApi: OpenPgpApi, account: Account): AutocryptSetupMessage {
val keyIds = longArrayOf(account.openPgpKey)
val address = Address.parse(account.getIdentity(0).email)[0]

val intent = Intent(OpenPgpApi.ACTION_AUTOCRYPT_KEY_TRANSFER)
intent.putExtra(OpenPgpApi.EXTRA_KEY_IDS, keyIds)
val baos = ByteArrayOutputStream()
val result = openPgpApi.executeApi(intent, null as InputStream?, baos)

val keyData = baos.toByteArray()
val pi: PendingIntent = result.getParcelableExtra(OpenPgpApi.RESULT_INTENT)

val setupMessage = AutocryptTransferMessageUtil.createAutocryptTransferMessage(resources, keyData, address)

return AutocryptSetupMessage(pi, setupMessage)
}

data class AutocryptSetupMessage(val showTransferCodePi: PendingIntent, val setupMessage: Message)
}
Loading

0 comments on commit 6794a15

Please sign in to comment.