Loading k9mail/src/main/java/com/fsck/k9/activity/compose/RecipientLoader.java +17 −15 Original line number Diff line number Diff line Loading @@ -85,6 +85,7 @@ public class RecipientLoader extends AsyncTaskLoader<List<Recipient>> { private final Uri contactUri; private final Uri lookupKeyUri; private final String cryptoProvider; private final ContentResolver contentResolver; private List<Recipient> cachedRecipients; private ForceLoadContentObserver observerContact, observerKey; Loading @@ -97,6 +98,8 @@ public class RecipientLoader extends AsyncTaskLoader<List<Recipient>> { this.addresses = null; this.contactUri = null; this.cryptoProvider = cryptoProvider; contentResolver = context.getContentResolver(); } public RecipientLoader(Context context, String cryptoProvider, Address... addresses) { Loading @@ -106,6 +109,8 @@ public class RecipientLoader extends AsyncTaskLoader<List<Recipient>> { this.contactUri = null; this.cryptoProvider = cryptoProvider; this.lookupKeyUri = null; contentResolver = context.getContentResolver(); } public RecipientLoader(Context context, String cryptoProvider, Uri contactUri, boolean isLookupKey) { Loading @@ -115,6 +120,8 @@ public class RecipientLoader extends AsyncTaskLoader<List<Recipient>> { this.contactUri = isLookupKey ? null : contactUri; this.lookupKeyUri = isLookupKey ? contactUri : null; this.cryptoProvider = cryptoProvider; contentResolver = context.getContentResolver(); } @Override Loading Loading @@ -154,7 +161,7 @@ public class RecipientLoader extends AsyncTaskLoader<List<Recipient>> { Cursor cursor; try { Uri queryUri = Uri.parse("content://" + cryptoProvider + ".provider.exported/autocrypt_status"); cursor = getContext().getContentResolver().query(queryUri, PROJECTION_CRYPTO_ADDRESSES, null, cursor = contentResolver.query(queryUri, PROJECTION_CRYPTO_ADDRESSES, null, new String[] { "%" + query + "%" }, null); if (cursor == null) { Loading Loading @@ -195,7 +202,7 @@ public class RecipientLoader extends AsyncTaskLoader<List<Recipient>> { private void fillContactDataFromEmailContentUri(Uri contactUri, List<Recipient> recipients, Map<String, Recipient> recipientMap) { Cursor cursor = getContext().getContentResolver().query(contactUri, PROJECTION, null, null, null); Cursor cursor = contentResolver.query(contactUri, PROJECTION, null, null, null); if (cursor == null) { return; Loading @@ -207,14 +214,14 @@ public class RecipientLoader extends AsyncTaskLoader<List<Recipient>> { private void fillContactDataFromLookupKey(Uri lookupKeyUri, List<Recipient> recipients, Map<String, Recipient> recipientMap) { // We could use the contact id from the URI directly, but getting it from the lookup key is safer Uri contactContentUri = Contacts.lookupContact(getContext().getContentResolver(), lookupKeyUri); Uri contactContentUri = Contacts.lookupContact(contentResolver, lookupKeyUri); if (contactContentUri == null) { return; } String contactIdStr = getContactIdFromContactUri(contactContentUri); Cursor cursor = getContext().getContentResolver().query( Cursor cursor = contentResolver.query( ContactsContract.CommonDataKinds.Email.CONTENT_URI, PROJECTION, ContactsContract.CommonDataKinds.Email.CONTACT_ID + "=?", new String[] { contactIdStr }, null); Loading @@ -236,7 +243,7 @@ public class RecipientLoader extends AsyncTaskLoader<List<Recipient>> { Uri queryUriForNickname = ContactsContract.Data.CONTENT_URI; return getContext().getContentResolver().query(queryUriForNickname, return contentResolver.query(queryUriForNickname, PROJECTION_NICKNAME, ContactsContract.CommonDataKinds.Nickname.NAME + " LIKE ? AND " + Data.MIMETYPE + " = ?", Loading @@ -261,7 +268,7 @@ public class RecipientLoader extends AsyncTaskLoader<List<Recipient>> { private void registerContentObserver() { if (observerContact != null) { observerContact = new ForceLoadContentObserver(); getContext().getContentResolver().registerContentObserver(Email.CONTENT_URI, false, observerContact); contentResolver.registerContentObserver(Email.CONTENT_URI, false, observerContact); } } Loading @@ -271,8 +278,6 @@ public class RecipientLoader extends AsyncTaskLoader<List<Recipient>> { boolean hasContact = false; final ContentResolver contentResolver = getContext().getContentResolver(); Uri queryUri = Email.CONTENT_URI; Cursor nicknameCursor = getNicknameCursor(nickname); Loading Loading @@ -303,8 +308,6 @@ public class RecipientLoader extends AsyncTaskLoader<List<Recipient>> { private boolean fillContactDataFromNameAndEmail(String query, List<Recipient> recipients, Map<String, Recipient> recipientMap) { ContentResolver contentResolver = getContext().getContentResolver(); query = "%" + query + "%"; Uri queryUri = Email.CONTENT_URI; Loading Loading @@ -391,8 +394,7 @@ public class RecipientLoader extends AsyncTaskLoader<List<Recipient>> { Cursor cursor; Uri queryUri = Uri.parse("content://" + cryptoProvider + ".provider.exported/autocrypt_status"); try { cursor = getContext().getContentResolver().query(queryUri, PROJECTION_CRYPTO_STATUS, null, recipientAddresses, null); cursor = contentResolver.query(queryUri, PROJECTION_CRYPTO_STATUS, null, recipientAddresses, null); } catch (SecurityException e) { // TODO escalate error to crypto status? return; Loading Loading @@ -436,7 +438,7 @@ public class RecipientLoader extends AsyncTaskLoader<List<Recipient>> { if (observerKey != null) { observerKey = new ForceLoadContentObserver(); getContext().getContentResolver().registerContentObserver(queryUri, false, observerKey); contentResolver.registerContentObserver(queryUri, false, observerKey); } } Loading Loading @@ -472,10 +474,10 @@ public class RecipientLoader extends AsyncTaskLoader<List<Recipient>> { super.onAbandon(); if (observerKey != null) { getContext().getContentResolver().unregisterContentObserver(observerKey); contentResolver.unregisterContentObserver(observerKey); } if (observerContact != null) { getContext().getContentResolver().unregisterContentObserver(observerContact); contentResolver.unregisterContentObserver(observerContact); } } } k9mail/src/test/java/com/fsck/k9/activity/compose/RecipientLoaderTest.java 0 → 100644 +144 −0 Original line number Diff line number Diff line package com.fsck.k9.activity.compose; import java.util.List; import android.content.ContentResolver; import android.content.Context; import android.database.MatrixCursor; import android.net.Uri; import com.fsck.k9.K9RobolectricTestRunner; import com.fsck.k9.mail.Address; import com.fsck.k9.view.RecipientSelectView.Recipient; import com.fsck.k9.view.RecipientSelectView.RecipientCryptoStatus; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; import static org.junit.Assert.*; import static org.mockito.AdditionalMatchers.aryEq; import static org.mockito.Matchers.any; import static org.mockito.Matchers.eq; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; @SuppressWarnings("WeakerAccess") @RunWith(K9RobolectricTestRunner.class) public class RecipientLoaderTest { static final String CRYPTO_PROVIDER = "cryptoProvider"; static final String[] PROJECTION_CRYPTO_ADDRESSES = { "address", "uid_address" }; static final String[] PROJECTION_CRYPTO_STATUS = { "address", "uid_key_status", "autocrypt_key_status" }; static final Address CONTACT_ADDRESS_1 = Address.parse("Contact Name <address@example.org>")[0]; static final Address CONTACT_ADDRESS_2 = Address.parse("Other Contact Name <address_two@example.org>")[0]; static final String QUERYSTRING = "querystring"; Context context; ContentResolver contentResolver; @Before public void setUp() throws Exception { context = mock(Context.class); contentResolver = mock(ContentResolver.class); when(context.getContentResolver()).thenReturn(contentResolver); } @Test public void queryCryptoProvider() throws Exception { RecipientLoader recipientLoader = new RecipientLoader(context, CRYPTO_PROVIDER, QUERYSTRING); setupQueryCryptoProvider("%" + QUERYSTRING + "%", CONTACT_ADDRESS_1, CONTACT_ADDRESS_2); List<Recipient> recipients = recipientLoader.loadInBackground(); assertEquals(2, recipients.size()); assertEquals(CONTACT_ADDRESS_1, recipients.get(0).address); assertEquals(CONTACT_ADDRESS_2, recipients.get(1).address); assertEquals(RecipientCryptoStatus.UNAVAILABLE, recipients.get(0).getCryptoStatus()); } @Test public void queryCryptoStatus_unavailable() throws Exception { RecipientLoader recipientLoader = new RecipientLoader(context, CRYPTO_PROVIDER, CONTACT_ADDRESS_1); setupCryptoProviderStatus(CONTACT_ADDRESS_1, "0", "0"); List<Recipient> recipients = recipientLoader.loadInBackground(); assertEquals(1, recipients.size()); Recipient recipient = recipients.get(0); assertEquals(CONTACT_ADDRESS_1, recipient.address); assertEquals(RecipientCryptoStatus.UNAVAILABLE, recipient.getCryptoStatus()); } @Test public void queryCryptoStatus_autocrypt_untrusted() throws Exception { RecipientLoader recipientLoader = new RecipientLoader(context, CRYPTO_PROVIDER, CONTACT_ADDRESS_1); setupCryptoProviderStatus(CONTACT_ADDRESS_1, "0", "1"); List<Recipient> recipients = recipientLoader.loadInBackground(); assertEquals(1, recipients.size()); Recipient recipient = recipients.get(0); assertEquals(CONTACT_ADDRESS_1, recipient.address); assertEquals(RecipientCryptoStatus.AVAILABLE_UNTRUSTED, recipient.getCryptoStatus()); } @Test public void queryCryptoStatus_autocrypt_trusted() throws Exception { RecipientLoader recipientLoader = new RecipientLoader(context, CRYPTO_PROVIDER, CONTACT_ADDRESS_1); setupCryptoProviderStatus(CONTACT_ADDRESS_1, "0", "2"); List<Recipient> recipients = recipientLoader.loadInBackground(); assertEquals(1, recipients.size()); Recipient recipient = recipients.get(0); assertEquals(CONTACT_ADDRESS_1, recipient.address); assertEquals(RecipientCryptoStatus.AVAILABLE_TRUSTED, recipient.getCryptoStatus()); } @Test public void queryCryptoStatus_withHigherUidStatus() throws Exception { RecipientLoader recipientLoader = new RecipientLoader(context, CRYPTO_PROVIDER, CONTACT_ADDRESS_1); setupCryptoProviderStatus(CONTACT_ADDRESS_1, "2", "1"); List<Recipient> recipients = recipientLoader.loadInBackground(); assertEquals(1, recipients.size()); Recipient recipient = recipients.get(0); assertEquals(CONTACT_ADDRESS_1, recipient.address); assertEquals(RecipientCryptoStatus.AVAILABLE_TRUSTED, recipient.getCryptoStatus()); } private void setupQueryCryptoProvider(String queriedAddress, Address... contactAddresses) { MatrixCursor cursor = new MatrixCursor(PROJECTION_CRYPTO_ADDRESSES); for (Address contactAddress : contactAddresses) { cursor.addRow(new String[] { queriedAddress, contactAddress.toString() }); } when(contentResolver .query(eq(Uri.parse("content://" + CRYPTO_PROVIDER + ".provider.exported/autocrypt_status")), aryEq(PROJECTION_CRYPTO_ADDRESSES), any(String.class), aryEq(new String[] { queriedAddress }), any(String.class))).thenReturn(cursor); } private void setupCryptoProviderStatus(Address address, String uidStatus, String autocryptStatus) { MatrixCursor cursorCryptoStatus = new MatrixCursor(PROJECTION_CRYPTO_STATUS); cursorCryptoStatus.addRow(new String[] { address.getAddress(), uidStatus, autocryptStatus }); when(contentResolver .query(eq(Uri.parse("content://" + CRYPTO_PROVIDER + ".provider.exported/autocrypt_status")), aryEq(PROJECTION_CRYPTO_STATUS), any(String.class), aryEq(new String[] { address.getAddress() }), any(String.class))).thenReturn(cursorCryptoStatus); } } No newline at end of file Loading
k9mail/src/main/java/com/fsck/k9/activity/compose/RecipientLoader.java +17 −15 Original line number Diff line number Diff line Loading @@ -85,6 +85,7 @@ public class RecipientLoader extends AsyncTaskLoader<List<Recipient>> { private final Uri contactUri; private final Uri lookupKeyUri; private final String cryptoProvider; private final ContentResolver contentResolver; private List<Recipient> cachedRecipients; private ForceLoadContentObserver observerContact, observerKey; Loading @@ -97,6 +98,8 @@ public class RecipientLoader extends AsyncTaskLoader<List<Recipient>> { this.addresses = null; this.contactUri = null; this.cryptoProvider = cryptoProvider; contentResolver = context.getContentResolver(); } public RecipientLoader(Context context, String cryptoProvider, Address... addresses) { Loading @@ -106,6 +109,8 @@ public class RecipientLoader extends AsyncTaskLoader<List<Recipient>> { this.contactUri = null; this.cryptoProvider = cryptoProvider; this.lookupKeyUri = null; contentResolver = context.getContentResolver(); } public RecipientLoader(Context context, String cryptoProvider, Uri contactUri, boolean isLookupKey) { Loading @@ -115,6 +120,8 @@ public class RecipientLoader extends AsyncTaskLoader<List<Recipient>> { this.contactUri = isLookupKey ? null : contactUri; this.lookupKeyUri = isLookupKey ? contactUri : null; this.cryptoProvider = cryptoProvider; contentResolver = context.getContentResolver(); } @Override Loading Loading @@ -154,7 +161,7 @@ public class RecipientLoader extends AsyncTaskLoader<List<Recipient>> { Cursor cursor; try { Uri queryUri = Uri.parse("content://" + cryptoProvider + ".provider.exported/autocrypt_status"); cursor = getContext().getContentResolver().query(queryUri, PROJECTION_CRYPTO_ADDRESSES, null, cursor = contentResolver.query(queryUri, PROJECTION_CRYPTO_ADDRESSES, null, new String[] { "%" + query + "%" }, null); if (cursor == null) { Loading Loading @@ -195,7 +202,7 @@ public class RecipientLoader extends AsyncTaskLoader<List<Recipient>> { private void fillContactDataFromEmailContentUri(Uri contactUri, List<Recipient> recipients, Map<String, Recipient> recipientMap) { Cursor cursor = getContext().getContentResolver().query(contactUri, PROJECTION, null, null, null); Cursor cursor = contentResolver.query(contactUri, PROJECTION, null, null, null); if (cursor == null) { return; Loading @@ -207,14 +214,14 @@ public class RecipientLoader extends AsyncTaskLoader<List<Recipient>> { private void fillContactDataFromLookupKey(Uri lookupKeyUri, List<Recipient> recipients, Map<String, Recipient> recipientMap) { // We could use the contact id from the URI directly, but getting it from the lookup key is safer Uri contactContentUri = Contacts.lookupContact(getContext().getContentResolver(), lookupKeyUri); Uri contactContentUri = Contacts.lookupContact(contentResolver, lookupKeyUri); if (contactContentUri == null) { return; } String contactIdStr = getContactIdFromContactUri(contactContentUri); Cursor cursor = getContext().getContentResolver().query( Cursor cursor = contentResolver.query( ContactsContract.CommonDataKinds.Email.CONTENT_URI, PROJECTION, ContactsContract.CommonDataKinds.Email.CONTACT_ID + "=?", new String[] { contactIdStr }, null); Loading @@ -236,7 +243,7 @@ public class RecipientLoader extends AsyncTaskLoader<List<Recipient>> { Uri queryUriForNickname = ContactsContract.Data.CONTENT_URI; return getContext().getContentResolver().query(queryUriForNickname, return contentResolver.query(queryUriForNickname, PROJECTION_NICKNAME, ContactsContract.CommonDataKinds.Nickname.NAME + " LIKE ? AND " + Data.MIMETYPE + " = ?", Loading @@ -261,7 +268,7 @@ public class RecipientLoader extends AsyncTaskLoader<List<Recipient>> { private void registerContentObserver() { if (observerContact != null) { observerContact = new ForceLoadContentObserver(); getContext().getContentResolver().registerContentObserver(Email.CONTENT_URI, false, observerContact); contentResolver.registerContentObserver(Email.CONTENT_URI, false, observerContact); } } Loading @@ -271,8 +278,6 @@ public class RecipientLoader extends AsyncTaskLoader<List<Recipient>> { boolean hasContact = false; final ContentResolver contentResolver = getContext().getContentResolver(); Uri queryUri = Email.CONTENT_URI; Cursor nicknameCursor = getNicknameCursor(nickname); Loading Loading @@ -303,8 +308,6 @@ public class RecipientLoader extends AsyncTaskLoader<List<Recipient>> { private boolean fillContactDataFromNameAndEmail(String query, List<Recipient> recipients, Map<String, Recipient> recipientMap) { ContentResolver contentResolver = getContext().getContentResolver(); query = "%" + query + "%"; Uri queryUri = Email.CONTENT_URI; Loading Loading @@ -391,8 +394,7 @@ public class RecipientLoader extends AsyncTaskLoader<List<Recipient>> { Cursor cursor; Uri queryUri = Uri.parse("content://" + cryptoProvider + ".provider.exported/autocrypt_status"); try { cursor = getContext().getContentResolver().query(queryUri, PROJECTION_CRYPTO_STATUS, null, recipientAddresses, null); cursor = contentResolver.query(queryUri, PROJECTION_CRYPTO_STATUS, null, recipientAddresses, null); } catch (SecurityException e) { // TODO escalate error to crypto status? return; Loading Loading @@ -436,7 +438,7 @@ public class RecipientLoader extends AsyncTaskLoader<List<Recipient>> { if (observerKey != null) { observerKey = new ForceLoadContentObserver(); getContext().getContentResolver().registerContentObserver(queryUri, false, observerKey); contentResolver.registerContentObserver(queryUri, false, observerKey); } } Loading Loading @@ -472,10 +474,10 @@ public class RecipientLoader extends AsyncTaskLoader<List<Recipient>> { super.onAbandon(); if (observerKey != null) { getContext().getContentResolver().unregisterContentObserver(observerKey); contentResolver.unregisterContentObserver(observerKey); } if (observerContact != null) { getContext().getContentResolver().unregisterContentObserver(observerContact); contentResolver.unregisterContentObserver(observerContact); } } }
k9mail/src/test/java/com/fsck/k9/activity/compose/RecipientLoaderTest.java 0 → 100644 +144 −0 Original line number Diff line number Diff line package com.fsck.k9.activity.compose; import java.util.List; import android.content.ContentResolver; import android.content.Context; import android.database.MatrixCursor; import android.net.Uri; import com.fsck.k9.K9RobolectricTestRunner; import com.fsck.k9.mail.Address; import com.fsck.k9.view.RecipientSelectView.Recipient; import com.fsck.k9.view.RecipientSelectView.RecipientCryptoStatus; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; import static org.junit.Assert.*; import static org.mockito.AdditionalMatchers.aryEq; import static org.mockito.Matchers.any; import static org.mockito.Matchers.eq; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; @SuppressWarnings("WeakerAccess") @RunWith(K9RobolectricTestRunner.class) public class RecipientLoaderTest { static final String CRYPTO_PROVIDER = "cryptoProvider"; static final String[] PROJECTION_CRYPTO_ADDRESSES = { "address", "uid_address" }; static final String[] PROJECTION_CRYPTO_STATUS = { "address", "uid_key_status", "autocrypt_key_status" }; static final Address CONTACT_ADDRESS_1 = Address.parse("Contact Name <address@example.org>")[0]; static final Address CONTACT_ADDRESS_2 = Address.parse("Other Contact Name <address_two@example.org>")[0]; static final String QUERYSTRING = "querystring"; Context context; ContentResolver contentResolver; @Before public void setUp() throws Exception { context = mock(Context.class); contentResolver = mock(ContentResolver.class); when(context.getContentResolver()).thenReturn(contentResolver); } @Test public void queryCryptoProvider() throws Exception { RecipientLoader recipientLoader = new RecipientLoader(context, CRYPTO_PROVIDER, QUERYSTRING); setupQueryCryptoProvider("%" + QUERYSTRING + "%", CONTACT_ADDRESS_1, CONTACT_ADDRESS_2); List<Recipient> recipients = recipientLoader.loadInBackground(); assertEquals(2, recipients.size()); assertEquals(CONTACT_ADDRESS_1, recipients.get(0).address); assertEquals(CONTACT_ADDRESS_2, recipients.get(1).address); assertEquals(RecipientCryptoStatus.UNAVAILABLE, recipients.get(0).getCryptoStatus()); } @Test public void queryCryptoStatus_unavailable() throws Exception { RecipientLoader recipientLoader = new RecipientLoader(context, CRYPTO_PROVIDER, CONTACT_ADDRESS_1); setupCryptoProviderStatus(CONTACT_ADDRESS_1, "0", "0"); List<Recipient> recipients = recipientLoader.loadInBackground(); assertEquals(1, recipients.size()); Recipient recipient = recipients.get(0); assertEquals(CONTACT_ADDRESS_1, recipient.address); assertEquals(RecipientCryptoStatus.UNAVAILABLE, recipient.getCryptoStatus()); } @Test public void queryCryptoStatus_autocrypt_untrusted() throws Exception { RecipientLoader recipientLoader = new RecipientLoader(context, CRYPTO_PROVIDER, CONTACT_ADDRESS_1); setupCryptoProviderStatus(CONTACT_ADDRESS_1, "0", "1"); List<Recipient> recipients = recipientLoader.loadInBackground(); assertEquals(1, recipients.size()); Recipient recipient = recipients.get(0); assertEquals(CONTACT_ADDRESS_1, recipient.address); assertEquals(RecipientCryptoStatus.AVAILABLE_UNTRUSTED, recipient.getCryptoStatus()); } @Test public void queryCryptoStatus_autocrypt_trusted() throws Exception { RecipientLoader recipientLoader = new RecipientLoader(context, CRYPTO_PROVIDER, CONTACT_ADDRESS_1); setupCryptoProviderStatus(CONTACT_ADDRESS_1, "0", "2"); List<Recipient> recipients = recipientLoader.loadInBackground(); assertEquals(1, recipients.size()); Recipient recipient = recipients.get(0); assertEquals(CONTACT_ADDRESS_1, recipient.address); assertEquals(RecipientCryptoStatus.AVAILABLE_TRUSTED, recipient.getCryptoStatus()); } @Test public void queryCryptoStatus_withHigherUidStatus() throws Exception { RecipientLoader recipientLoader = new RecipientLoader(context, CRYPTO_PROVIDER, CONTACT_ADDRESS_1); setupCryptoProviderStatus(CONTACT_ADDRESS_1, "2", "1"); List<Recipient> recipients = recipientLoader.loadInBackground(); assertEquals(1, recipients.size()); Recipient recipient = recipients.get(0); assertEquals(CONTACT_ADDRESS_1, recipient.address); assertEquals(RecipientCryptoStatus.AVAILABLE_TRUSTED, recipient.getCryptoStatus()); } private void setupQueryCryptoProvider(String queriedAddress, Address... contactAddresses) { MatrixCursor cursor = new MatrixCursor(PROJECTION_CRYPTO_ADDRESSES); for (Address contactAddress : contactAddresses) { cursor.addRow(new String[] { queriedAddress, contactAddress.toString() }); } when(contentResolver .query(eq(Uri.parse("content://" + CRYPTO_PROVIDER + ".provider.exported/autocrypt_status")), aryEq(PROJECTION_CRYPTO_ADDRESSES), any(String.class), aryEq(new String[] { queriedAddress }), any(String.class))).thenReturn(cursor); } private void setupCryptoProviderStatus(Address address, String uidStatus, String autocryptStatus) { MatrixCursor cursorCryptoStatus = new MatrixCursor(PROJECTION_CRYPTO_STATUS); cursorCryptoStatus.addRow(new String[] { address.getAddress(), uidStatus, autocryptStatus }); when(contentResolver .query(eq(Uri.parse("content://" + CRYPTO_PROVIDER + ".provider.exported/autocrypt_status")), aryEq(PROJECTION_CRYPTO_STATUS), any(String.class), aryEq(new String[] { address.getAddress() }), any(String.class))).thenReturn(cursorCryptoStatus); } } No newline at end of file