diff --git a/androidTest/com/b44t/messenger/uitests/offline/SharingTest.java b/androidTest/com/b44t/messenger/uitests/offline/SharingTest.java index 17fdd680f..3ada98b3c 100644 --- a/androidTest/com/b44t/messenger/uitests/offline/SharingTest.java +++ b/androidTest/com/b44t/messenger/uitests/offline/SharingTest.java @@ -205,6 +205,25 @@ public class SharingTest { onView(withHint(R.string.chat_input_placeholder)).check(matches(withText("Veeery important draft"))); } + /** + * Regression test: + * + * If you save your contacts's emails in the contacts app of the phone, there are buttons to call + * them and also to write an email to them. + * + * If you click the email button, Delta Chat opened but instead of opening a chat with that contact, + * the chat list was show and "share with" was displayed at the top + */ + @Test + public void testOpenChatFromContacts() { + Intent i = new Intent(Intent.ACTION_SENDTO); + i.setData(Uri.parse("mailto:bob%40example.org")); + i.setPackage(getInstrumentation().getTargetContext().getPackageName()); + activityRule.getScenario().onActivity(a -> a.startActivity(i)); + + onView(withId(R.id.subtitle)).check(matches(withText("bob@example.org"))); + } + @After public void cleanup() { TestUtils.cleanup(); diff --git a/jni/dc_wrapper.c b/jni/dc_wrapper.c index 802fce7bb..d55d6c9e4 100644 --- a/jni/dc_wrapper.c +++ b/jni/dc_wrapper.c @@ -223,13 +223,12 @@ static dc_accounts_t* get_dc_accounts(JNIEnv *env, jobject obj) } -JNIEXPORT jlong Java_com_b44t_messenger_DcAccounts_createAccountsCPtr(JNIEnv *env, jobject obj, jstring osname, jstring dir) +JNIEXPORT jlong Java_com_b44t_messenger_DcAccounts_createAccountsCPtr(JNIEnv *env, jobject obj, jstring dir) { - CHAR_REF(osname); CHAR_REF(dir); - jlong accountsCPtr = (jlong)dc_accounts_new(osnamePtr, dirPtr); + int writable = 1; + jlong accountsCPtr = (jlong)dc_accounts_new(dirPtr, writable); CHAR_UNREF(dir); - CHAR_UNREF(osname); return accountsCPtr; } diff --git a/src/com/b44t/messenger/DcAccounts.java b/src/com/b44t/messenger/DcAccounts.java index 671bb6caf..c959ff69e 100644 --- a/src/com/b44t/messenger/DcAccounts.java +++ b/src/com/b44t/messenger/DcAccounts.java @@ -2,8 +2,8 @@ package com.b44t.messenger; public class DcAccounts { - public DcAccounts(String osName, String dir) { - accountsCPtr = createAccountsCPtr(osName, dir); + public DcAccounts(String dir) { + accountsCPtr = createAccountsCPtr(dir); } @Override @@ -36,7 +36,7 @@ public class DcAccounts { // working with raw c-data private long accountsCPtr; // CAVE: the name is referenced in the JNI - private native long createAccountsCPtr (String osName, String dir); + private native long createAccountsCPtr (String dir); private native void unrefAccountsCPtr (); private native long getEventEmitterCPtr (); private native long getJsonrpcInstanceCPtr (); diff --git a/src/org/thoughtcrime/securesms/ApplicationContext.java b/src/org/thoughtcrime/securesms/ApplicationContext.java index e34f6646c..63b588062 100644 --- a/src/org/thoughtcrime/securesms/ApplicationContext.java +++ b/src/org/thoughtcrime/securesms/ApplicationContext.java @@ -92,7 +92,7 @@ public class ApplicationContext extends MultiDexApplication { System.loadLibrary("native-utils"); - dcAccounts = new DcAccounts("Android "+BuildConfig.VERSION_NAME, new File(getFilesDir(), "accounts").getAbsolutePath()); + dcAccounts = new DcAccounts(new File(getFilesDir(), "accounts").getAbsolutePath()); rpc = new Rpc(dcAccounts.getJsonrpcInstance()); AccountManager.getInstance().migrateToDcAccounts(this); int[] allAccounts = dcAccounts.getAll(); diff --git a/src/org/thoughtcrime/securesms/ConversationActivity.java b/src/org/thoughtcrime/securesms/ConversationActivity.java index cf415364c..99f25c68b 100644 --- a/src/org/thoughtcrime/securesms/ConversationActivity.java +++ b/src/org/thoughtcrime/securesms/ConversationActivity.java @@ -1624,9 +1624,10 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity if (dcChat.isProtectionBroken()) { messageRequestBottomView.setBlockText(R.string.more_info_desktop); - messageRequestBottomView.setBlockOnClickListener(v -> DcHelper.showVerificationBrokenDialog(this, recipient.getName())); + String name = dcContext.getContact(recipient.getDcContact().getId()).getDisplayName(); + messageRequestBottomView.setBlockOnClickListener(v -> DcHelper.showVerificationBrokenDialog(this, name)); - messageRequestBottomView.setQuestion(getString(R.string.chat_protection_broken, recipient.getName())); + messageRequestBottomView.setQuestion(getString(R.string.chat_protection_broken, name)); messageRequestBottomView.setAcceptText(R.string.ok); } else if (dcChat.getType() == DcChat.DC_CHAT_TYPE_GROUP) { diff --git a/src/org/thoughtcrime/securesms/NewConversationActivity.java b/src/org/thoughtcrime/securesms/NewConversationActivity.java index aa48935b5..2818e604c 100644 --- a/src/org/thoughtcrime/securesms/NewConversationActivity.java +++ b/src/org/thoughtcrime/securesms/NewConversationActivity.java @@ -17,7 +17,6 @@ package org.thoughtcrime.securesms; import android.content.Intent; -import android.net.MailTo; import android.net.Uri; import android.os.Bundle; import android.util.Log; @@ -31,11 +30,7 @@ import com.b44t.messenger.DcContact; import com.b44t.messenger.DcContext; import org.thoughtcrime.securesms.connect.DcHelper; - -import java.io.UnsupportedEncodingException; -import java.net.URLDecoder; -import java.util.HashMap; -import java.util.Map; +import org.thoughtcrime.securesms.util.MailtoUtil; import static org.thoughtcrime.securesms.ConversationActivity.CHAT_ID_EXTRA; import static org.thoughtcrime.securesms.ConversationActivity.TEXT_EXTRA; @@ -51,11 +46,6 @@ import static org.thoughtcrime.securesms.util.RelayUtil.isRelayingMessageContent public class NewConversationActivity extends ContactSelectionActivity { private static final String TAG = NewConversationActivity.class.getSimpleName(); - public static final String MAILTO = "mailto"; - private static final String SUBJECT = "subject"; - private static final String BODY = "body"; - private static final String QUERY_SEPARATOR = "&"; - private static final String KEY_VALUE_SEPARATOR = "="; @Override public void onCreate(Bundle bundle, boolean ready) { @@ -73,19 +63,14 @@ public class NewConversationActivity extends ContactSelectionActivity { Uri uri = intent.getData(); if(uri != null) { String scheme = uri.getScheme(); - if(scheme != null && scheme.equals(MAILTO) ) { - String textToShare = getTextToShare(uri); - MailTo mailto = MailTo.parse(uri.toString()); - String recipientsList = mailto.getTo(); - if(recipientsList != null && !recipientsList.trim().isEmpty()) { - String[] recipientsArray = recipientsList.trim().split(","); - if (recipientsArray.length >= 1) { - String recipient = recipientsArray[0]; - if (textToShare != null && !textToShare.isEmpty()) { - getIntent().putExtra(TEXT_EXTRA, textToShare); - } - onContactSelected(DcContact.DC_CONTACT_ID_NEW_CONTACT, recipient); + if(MailtoUtil.isMailto(uri)) { + String textToShare = MailtoUtil.getText(uri); + String[] recipientsArray = MailtoUtil.getRecipients(uri); + if (recipientsArray.length >= 1) { + if (!textToShare.isEmpty()) { + getIntent().putExtra(TEXT_EXTRA, textToShare); } + onContactSelected(DcContact.DC_CONTACT_ID_NEW_CONTACT, recipientsArray[0]); } else { Intent shareIntent = new Intent(this, ShareActivity.class); shareIntent.putExtra(Intent.EXTRA_TEXT, textToShare); @@ -101,37 +86,6 @@ public class NewConversationActivity extends ContactSelectionActivity { } } - private String getTextToShare(Uri uri) { - Map mailtoQueryMap = getMailtoQueryMap(uri); - String textToShare = mailtoQueryMap.get(SUBJECT); - String body = mailtoQueryMap.get(BODY); - if (body != null && !body.isEmpty()) { - if (textToShare != null && !textToShare.isEmpty()) { - textToShare += "\n" + body; - } else { - textToShare = body; - } - } - return textToShare; - } - - private Map getMailtoQueryMap(Uri uri) { - Map mailtoQueryMap = new HashMap<>(); - String query = uri.getEncodedQuery(); - if (query != null && !query.isEmpty()) { - String[] queryArray = query.split(QUERY_SEPARATOR); - for(String queryEntry : queryArray) { - String[] queryEntryArray = queryEntry.split(KEY_VALUE_SEPARATOR); - try { - mailtoQueryMap.put(queryEntryArray[0], URLDecoder.decode(queryEntryArray[1], "UTF-8")); - } catch (UnsupportedEncodingException e) { - e.printStackTrace(); - } - } - } - return mailtoQueryMap; - } - @Override public void onContactSelected(int specialId, String addr) { final DcContext dcContext = DcHelper.getContext(this); diff --git a/src/org/thoughtcrime/securesms/ShareActivity.java b/src/org/thoughtcrime/securesms/ShareActivity.java index 92710d00f..2f8b8adb9 100644 --- a/src/org/thoughtcrime/securesms/ShareActivity.java +++ b/src/org/thoughtcrime/securesms/ShareActivity.java @@ -112,6 +112,18 @@ public class ShareActivity extends PassphraseRequiredActionBarActivity implement streamExtras.add(uri); } else if (getIntent().getParcelableArrayListExtra(Intent.EXTRA_STREAM) != null) { streamExtras = getIntent().getParcelableArrayListExtra(Intent.EXTRA_STREAM); + } else { + Uri uri = getIntent().getData(); + if (MailtoUtil.isMailto(uri)) { + String[] extraEmail = getIntent().getStringArrayExtra(Intent.EXTRA_EMAIL); + if (extraEmail == null || extraEmail.length == 0) { + getIntent().putExtra(Intent.EXTRA_EMAIL, MailtoUtil.getRecipients(uri)); + } + String text = getIntent().getStringExtra(Intent.EXTRA_TEXT); + if (text == null || text.isEmpty()) { + getIntent().putExtra(Intent.EXTRA_TEXT, MailtoUtil.getText(uri)); + } + } } if (needsFilePermission(streamExtras)) { diff --git a/src/org/thoughtcrime/securesms/util/MailtoUtil.java b/src/org/thoughtcrime/securesms/util/MailtoUtil.java new file mode 100644 index 000000000..c5d962488 --- /dev/null +++ b/src/org/thoughtcrime/securesms/util/MailtoUtil.java @@ -0,0 +1,64 @@ +package org.thoughtcrime.securesms.util; + +import android.net.MailTo; +import android.net.Uri; + +import java.io.UnsupportedEncodingException; +import java.net.URLDecoder; +import java.util.HashMap; +import java.util.Map; + +public class MailtoUtil { + private static final String MAILTO = "mailto"; + private static final String SUBJECT = "subject"; + private static final String BODY = "body"; + private static final String QUERY_SEPARATOR = "&"; + private static final String KEY_VALUE_SEPARATOR = "="; + + public static boolean isMailto(Uri uri) { + return uri != null && MAILTO.equals(uri.getScheme()); + } + + public static String[] getRecipients(Uri uri) { + String[] recipientsArray = new String[0]; + if (uri != null) { + MailTo mailto = MailTo.parse(uri.toString()); + String recipientsList = mailto.getTo(); + if(recipientsList != null && !recipientsList.trim().isEmpty()) { + recipientsArray = recipientsList.trim().split(","); + } + } + return recipientsArray; + } + + public static String getText(Uri uri) { + Map mailtoQueryMap = getMailtoQueryMap(uri); + String textToShare = mailtoQueryMap.get(SUBJECT); + String body = mailtoQueryMap.get(BODY); + if (body != null && !body.isEmpty()) { + if (textToShare != null && !textToShare.isEmpty()) { + textToShare += "\n" + body; + } else { + textToShare = body; + } + } + return textToShare != null? textToShare : ""; + } + + private static Map getMailtoQueryMap(Uri uri) { + Map mailtoQueryMap = new HashMap<>(); + String query = uri.getEncodedQuery(); + if (query != null && !query.isEmpty()) { + String[] queryArray = query.split(QUERY_SEPARATOR); + for(String queryEntry : queryArray) { + String[] queryEntryArray = queryEntry.split(KEY_VALUE_SEPARATOR); + try { + mailtoQueryMap.put(queryEntryArray[0], URLDecoder.decode(queryEntryArray[1], "UTF-8")); + } catch (UnsupportedEncodingException e) { + e.printStackTrace(); + } + } + } + return mailtoQueryMap; + } +}