diff --git a/briar-android/res/drawable-hdpi/rating_bad.png b/briar-android/res/drawable-hdpi/rating_bad.png new file mode 100644 index 0000000000000000000000000000000000000000..4d332cc92e47bbaaa094105944721a7400b6abe4 Binary files /dev/null and b/briar-android/res/drawable-hdpi/rating_bad.png differ diff --git a/briar-android/res/drawable-hdpi/rating_good.png b/briar-android/res/drawable-hdpi/rating_good.png new file mode 100644 index 0000000000000000000000000000000000000000..f612bab60e2553211c7c55a836ccac63fc44951d Binary files /dev/null and b/briar-android/res/drawable-hdpi/rating_good.png differ diff --git a/briar-android/res/drawable-mdpi/rating_bad.png b/briar-android/res/drawable-mdpi/rating_bad.png new file mode 100644 index 0000000000000000000000000000000000000000..5c5982ac649369ba8fa4c379c462a0f550ff2903 Binary files /dev/null and b/briar-android/res/drawable-mdpi/rating_bad.png differ diff --git a/briar-android/res/drawable-mdpi/rating_good.png b/briar-android/res/drawable-mdpi/rating_good.png new file mode 100644 index 0000000000000000000000000000000000000000..16fce26e1c2e484a855638960cca2ddebb93f115 Binary files /dev/null and b/briar-android/res/drawable-mdpi/rating_good.png differ diff --git a/briar-android/res/drawable-xhdpi/rating_bad.png b/briar-android/res/drawable-xhdpi/rating_bad.png new file mode 100644 index 0000000000000000000000000000000000000000..a8ad06ad9926fb4948f790f4699b1dd740c47d4c Binary files /dev/null and b/briar-android/res/drawable-xhdpi/rating_bad.png differ diff --git a/briar-android/res/drawable-xhdpi/rating_good.png b/briar-android/res/drawable-xhdpi/rating_good.png new file mode 100644 index 0000000000000000000000000000000000000000..225eaea5f258984ccc6d015598dc431e9af8978a Binary files /dev/null and b/briar-android/res/drawable-xhdpi/rating_good.png differ diff --git a/briar-android/src/net/sf/briar/android/groups/GroupActivity.java b/briar-android/src/net/sf/briar/android/groups/GroupActivity.java index 8ed287306acf942eaf298ed4440fb4441f9806ee..c0ae2820ec1ebb690dc7a47a1e7cd114ae6749fe 100644 --- a/briar-android/src/net/sf/briar/android/groups/GroupActivity.java +++ b/briar-android/src/net/sf/briar/android/groups/GroupActivity.java @@ -4,11 +4,14 @@ import static android.view.Gravity.CENTER_HORIZONTAL; import static android.widget.LinearLayout.VERTICAL; import static java.util.logging.Level.INFO; import static java.util.logging.Level.WARNING; +import static net.sf.briar.api.Rating.UNRATED; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; +import java.util.HashMap; import java.util.List; +import java.util.Map; import java.util.concurrent.Executor; import java.util.logging.Logger; @@ -19,17 +22,20 @@ import net.sf.briar.android.BriarService; import net.sf.briar.android.BriarService.BriarServiceConnection; import net.sf.briar.android.widgets.CommonLayoutParams; import net.sf.briar.android.widgets.HorizontalBorder; +import net.sf.briar.api.Rating; import net.sf.briar.api.db.DatabaseComponent; import net.sf.briar.api.db.DatabaseExecutor; import net.sf.briar.api.db.DbException; import net.sf.briar.api.db.GroupMessageHeader; +import net.sf.briar.api.db.NoSuchSubscriptionException; import net.sf.briar.api.db.event.DatabaseEvent; import net.sf.briar.api.db.event.DatabaseListener; import net.sf.briar.api.db.event.MessageAddedEvent; import net.sf.briar.api.db.event.MessageExpiredEvent; -import net.sf.briar.api.db.event.SubscriptionAddedEvent; +import net.sf.briar.api.db.event.RatingChangedEvent; import net.sf.briar.api.db.event.SubscriptionRemovedEvent; import net.sf.briar.api.messaging.Author; +import net.sf.briar.api.messaging.AuthorId; import net.sf.briar.api.messaging.GroupId; import android.content.Intent; import android.os.Bundle; @@ -121,8 +127,23 @@ OnClickListener, OnItemClickListener { db.getMessageHeaders(groupId); if(LOG.isLoggable(INFO)) LOG.info("Loaded " + headers.size() + " headers"); + // Load the ratings for the authors + Map<Author, Rating> ratings = new HashMap<Author, Rating>(); + for(GroupMessageHeader h : headers) { + Author a = h.getAuthor(); + if(a != null && !ratings.containsKey(a)) + ratings.put(a, db.getRating(a.getId())); + } + ratings = Collections.unmodifiableMap(ratings); // Update the conversation - updateConversation(headers); + updateConversation(headers, ratings); + } catch(NoSuchSubscriptionException e) { + if(LOG.isLoggable(INFO)) LOG.info("Subscription removed"); + runOnUiThread(new Runnable() { + public void run() { + finish(); + } + }); } catch(DbException e) { if(LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e); @@ -136,7 +157,8 @@ OnClickListener, OnItemClickListener { } private void updateConversation( - final Collection<GroupMessageHeader> headers) { + final Collection<GroupMessageHeader> headers, + final Map<Author, Rating> ratings) { runOnUiThread(new Runnable() { public void run() { List<GroupMessageHeader> sort = @@ -147,7 +169,9 @@ OnClickListener, OnItemClickListener { for(GroupMessageHeader h : sort) { if(firstUnread == -1 && !h.isRead()) firstUnread = adapter.getCount(); - adapter.add(h); + Author a = h.getAuthor(); + if(a == null) adapter.add(new GroupItem(h, UNRATED)); + else adapter.add(new GroupItem(h, ratings.get(a))); } if(firstUnread == -1) list.setSelection(adapter.getCount() - 1); else list.setSelection(firstUnread); @@ -169,15 +193,36 @@ OnClickListener, OnItemClickListener { } else if(e instanceof MessageExpiredEvent) { if(LOG.isLoggable(INFO)) LOG.info("Message removed, reloading"); reloadMessageHeaders(); - } else if(e instanceof SubscriptionAddedEvent) { - if(LOG.isLoggable(INFO)) LOG.info("Group added, reloading"); - reloadMessageHeaders(); + } else if(e instanceof RatingChangedEvent) { + RatingChangedEvent r = (RatingChangedEvent) e; + updateRating(r.getAuthorId(), r.getRating()); } else if(e instanceof SubscriptionRemovedEvent) { - if(LOG.isLoggable(INFO)) LOG.info("Group removed, reloading"); - reloadMessageHeaders(); + SubscriptionRemovedEvent s = (SubscriptionRemovedEvent) e; + if(s.getGroupId().equals(groupId)) { + if(LOG.isLoggable(INFO)) LOG.info("Subscription removed"); + finish(); + } } } + private void updateRating(final AuthorId a, final Rating r) { + runOnUiThread(new Runnable() { + public void run() { + boolean affected = false; + int count = adapter.getCount(); + for(int i = 0; i < count; i++) { + GroupItem item = adapter.getItem(i); + Author author = item.getAuthor(); + if(author != null && author.getId().equals(a)) { + item.setRating(r); + affected = true; + } + } + if(affected) list.invalidate(); + } + }); + } + public void onClick(View view) { Intent i = new Intent(this, WriteGroupMessageActivity.class); i.putExtra("net.sf.briar.GROUP_ID", groupId.getBytes()); @@ -191,7 +236,7 @@ OnClickListener, OnItemClickListener { } private void showMessage(int position) { - GroupMessageHeader item = adapter.getItem(position); + GroupItem item = adapter.getItem(position); Intent i = new Intent(this, ReadGroupMessageActivity.class); i.putExtra("net.sf.briar.GROUP_ID", groupId.getBytes()); i.putExtra("net.sf.briar.GROUP_NAME", groupName); @@ -203,6 +248,7 @@ OnClickListener, OnItemClickListener { i.putExtra("net.sf.briar.ANONYMOUS", false); i.putExtra("net.sf.briar.AUTHOR_ID", author.getId().getBytes()); i.putExtra("net.sf.briar.AUTHOR_NAME", author.getName()); + i.putExtra("net.sf.briar.RATING", item.getRating().toString()); } i.putExtra("net.sf.briar.CONTENT_TYPE", item.getContentType()); i.putExtra("net.sf.briar.TIMESTAMP", item.getTimestamp()); diff --git a/briar-android/src/net/sf/briar/android/groups/GroupAdapter.java b/briar-android/src/net/sf/briar/android/groups/GroupAdapter.java index 17915c8d45abe00087b8e98784b6a36b26c4e0a6..10f8b11722ab76c8301f87d7ca59f7dd2da70d9f 100644 --- a/briar-android/src/net/sf/briar/android/groups/GroupAdapter.java +++ b/briar-android/src/net/sf/briar/android/groups/GroupAdapter.java @@ -5,13 +5,15 @@ import static android.view.Gravity.CENTER_VERTICAL; import static android.widget.LinearLayout.HORIZONTAL; import static android.widget.LinearLayout.VERTICAL; import static java.text.DateFormat.SHORT; +import static net.sf.briar.api.Rating.BAD; +import static net.sf.briar.api.Rating.GOOD; import java.util.ArrayList; import net.sf.briar.R; import net.sf.briar.android.widgets.CommonLayoutParams; import net.sf.briar.android.widgets.HorizontalSpace; -import net.sf.briar.api.db.GroupMessageHeader; +import net.sf.briar.api.Rating; import net.sf.briar.api.messaging.Author; import android.content.Context; import android.content.res.Resources; @@ -23,16 +25,16 @@ import android.widget.ImageView; import android.widget.LinearLayout; import android.widget.TextView; -class GroupAdapter extends ArrayAdapter<GroupMessageHeader> { +class GroupAdapter extends ArrayAdapter<GroupItem> { GroupAdapter(Context ctx) { super(ctx, android.R.layout.simple_expandable_list_item_1, - new ArrayList<GroupMessageHeader>()); + new ArrayList<GroupItem>()); } @Override public View getView(int position, View convertView, ViewGroup parent) { - GroupMessageHeader item = getItem(position); + GroupItem item = getItem(position); Context ctx = getContext(); // FIXME: Use a RelativeLayout LinearLayout layout = new LinearLayout(ctx); @@ -44,12 +46,28 @@ class GroupAdapter extends ArrayAdapter<GroupMessageHeader> { innerLayout.setLayoutParams(CommonLayoutParams.WRAP_WRAP_1); innerLayout.setOrientation(VERTICAL); - Author author = item.getAuthor(); + LinearLayout innerInnerLayout = new LinearLayout(ctx); + innerInnerLayout.setOrientation(HORIZONTAL); + innerInnerLayout.setGravity(CENTER_VERTICAL); + + Rating rating = item.getRating(); + if(rating == GOOD) { + ImageView good = new ImageView(ctx); + good.setPadding(0, 10, 10, 10); + good.setImageResource(R.drawable.rating_good); + innerInnerLayout.addView(good); + } else if(rating == BAD) { + ImageView bad = new ImageView(ctx); + bad.setPadding(0, 10, 10, 10); + bad.setImageResource(R.drawable.rating_bad); + innerInnerLayout.addView(bad); + } TextView name = new TextView(ctx); name.setTextSize(18); name.setMaxLines(1); name.setPadding(10, 10, 10, 10); + Author author = item.getAuthor(); Resources res = ctx.getResources(); if(author == null) { name.setTextColor(res.getColor(R.color.anonymous_author)); @@ -58,7 +76,8 @@ class GroupAdapter extends ArrayAdapter<GroupMessageHeader> { name.setTextColor(res.getColor(R.color.pseudonymous_author)); name.setText(author.getName()); } - innerLayout.addView(name); + innerInnerLayout.addView(name); + innerLayout.addView(innerInnerLayout); if(item.getContentType().equals("text/plain")) { TextView subject = new TextView(ctx); @@ -69,15 +88,12 @@ class GroupAdapter extends ArrayAdapter<GroupMessageHeader> { subject.setText(item.getSubject()); innerLayout.addView(subject); } else { - LinearLayout innerInnerLayout = new LinearLayout(ctx); - innerInnerLayout.setOrientation(HORIZONTAL); ImageView attachment = new ImageView(ctx); attachment.setPadding(10, 0, 10, 10); attachment.setImageResource(R.drawable.content_attachment); innerInnerLayout.addView(attachment); - innerInnerLayout.addView(new HorizontalSpace(ctx)); - innerLayout.addView(innerInnerLayout); } + innerInnerLayout.addView(new HorizontalSpace(ctx)); layout.addView(innerLayout); TextView date = new TextView(ctx); diff --git a/briar-android/src/net/sf/briar/android/groups/GroupItem.java b/briar-android/src/net/sf/briar/android/groups/GroupItem.java new file mode 100644 index 0000000000000000000000000000000000000000..3e6cb182136fd264721795132e4b5178b242a142 --- /dev/null +++ b/briar-android/src/net/sf/briar/android/groups/GroupItem.java @@ -0,0 +1,50 @@ +package net.sf.briar.android.groups; + +import net.sf.briar.api.Rating; +import net.sf.briar.api.db.GroupMessageHeader; +import net.sf.briar.api.messaging.Author; +import net.sf.briar.api.messaging.MessageId; + +// This class is not thread-safe +class GroupItem { + + private final GroupMessageHeader header; + private Rating rating; + + GroupItem(GroupMessageHeader header, Rating rating) { + this.header = header; + this.rating = rating; + } + + MessageId getId() { + return header.getId(); + } + + Author getAuthor() { + return header.getAuthor(); + } + + String getContentType() { + return header.getContentType(); + } + + String getSubject() { + return header.getSubject(); + } + + long getTimestamp() { + return header.getTimestamp(); + } + + boolean isRead() { + return header.isRead(); + } + + Rating getRating() { + return rating; + } + + void setRating(Rating rating) { + this.rating = rating; + } +} diff --git a/briar-android/src/net/sf/briar/android/groups/GroupListActivity.java b/briar-android/src/net/sf/briar/android/groups/GroupListActivity.java index 5c0c3beecf8e5b9c99e5ee571c86e6d9ea816035..ee38bfd8d8b997cb04d839d6007388daec71178c 100644 --- a/briar-android/src/net/sf/briar/android/groups/GroupListActivity.java +++ b/briar-android/src/net/sf/briar/android/groups/GroupListActivity.java @@ -4,6 +4,8 @@ import static android.view.Gravity.CENTER_HORIZONTAL; import static android.widget.LinearLayout.VERTICAL; import static java.util.logging.Level.INFO; import static java.util.logging.Level.WARNING; +import static net.sf.briar.api.Rating.BAD; +import static net.sf.briar.api.Rating.GOOD; import java.io.IOException; import java.security.GeneralSecurityException; @@ -131,8 +133,10 @@ implements OnClickListener, DatabaseListener { PrivateKey privateKey = keyPair.getPrivate(); Author author = authorFactory.createAuthor("Batman", publicKey); + db.setRating(author.getId(), BAD); Author author1 = authorFactory.createAuthor("Duckman", publicKey); + db.setRating(author1.getId(), GOOD); // Insert some fake groups and make them visible Group group = groupFactory.createGroup("DisneyLeaks"); db.subscribe(group); diff --git a/briar-android/src/net/sf/briar/android/groups/ReadGroupMessageActivity.java b/briar-android/src/net/sf/briar/android/groups/ReadGroupMessageActivity.java index d5750019ba58a3137df5a79cc18ddbb119621a9a..61b4183e588d90492d6f2569e1b3eb33a065fbe2 100644 --- a/briar-android/src/net/sf/briar/android/groups/ReadGroupMessageActivity.java +++ b/briar-android/src/net/sf/briar/android/groups/ReadGroupMessageActivity.java @@ -2,11 +2,16 @@ package net.sf.briar.android.groups; import static android.view.Gravity.CENTER; import static android.view.Gravity.CENTER_VERTICAL; +import static android.view.View.GONE; +import static android.view.View.VISIBLE; import static android.widget.LinearLayout.HORIZONTAL; import static android.widget.LinearLayout.VERTICAL; import static java.text.DateFormat.SHORT; import static java.util.logging.Level.INFO; import static java.util.logging.Level.WARNING; +import static net.sf.briar.api.Rating.BAD; +import static net.sf.briar.api.Rating.GOOD; +import static net.sf.briar.api.Rating.UNRATED; import java.io.UnsupportedEncodingException; import java.util.concurrent.Executor; @@ -19,10 +24,12 @@ import net.sf.briar.android.BriarService.BriarServiceConnection; import net.sf.briar.android.widgets.CommonLayoutParams; import net.sf.briar.android.widgets.HorizontalBorder; import net.sf.briar.android.widgets.HorizontalSpace; +import net.sf.briar.api.Rating; import net.sf.briar.api.android.BundleEncrypter; import net.sf.briar.api.db.DatabaseComponent; import net.sf.briar.api.db.DatabaseExecutor; import net.sf.briar.api.db.DbException; +import net.sf.briar.api.db.NoSuchMessageException; import net.sf.briar.api.messaging.AuthorId; import net.sf.briar.api.messaging.GroupId; import net.sf.briar.api.messaging.MessageId; @@ -33,6 +40,7 @@ import android.text.format.DateUtils; import android.view.View; import android.view.View.OnClickListener; import android.widget.ImageButton; +import android.widget.ImageView; import android.widget.LinearLayout; import android.widget.ScrollView; import android.widget.TextView; @@ -60,8 +68,11 @@ implements OnClickListener { private MessageId messageId = null; private AuthorId authorId = null; private String authorName = null; + private Rating rating = UNRATED; private boolean read; - private ImageButton readButton = null, prevButton = null, nextButton = null; + private ImageView thumb = null; + private ImageButton goodButton = null, badButton = null, readButton = null; + private ImageButton prevButton = null, nextButton = null; private ImageButton replyButton = null; private TextView content = null; @@ -86,6 +97,8 @@ implements OnClickListener { authorId = new AuthorId(id); authorName = i.getStringExtra("net.sf.briar.AUTHOR_NAME"); if(authorName == null) throw new IllegalStateException(); + String r = i.getStringExtra("net.sf.briar.RATING"); + if(r != null) rating = Rating.valueOf(r); } String contentType = i.getStringExtra("net.sf.briar.CONTENT_TYPE"); if(contentType == null) throw new IllegalStateException(); @@ -117,6 +130,13 @@ implements OnClickListener { header.setOrientation(HORIZONTAL); header.setGravity(CENTER_VERTICAL); + thumb = new ImageView(this); + thumb.setPadding(0, 10, 10, 10); + if(rating == GOOD) thumb.setImageResource(R.drawable.rating_good); + else if(rating == BAD) thumb.setImageResource(R.drawable.rating_bad); + else thumb.setVisibility(GONE); + header.addView(thumb); + TextView author = new TextView(this); // Give me all the unused width author.setLayoutParams(CommonLayoutParams.WRAP_WRAP_1); @@ -158,6 +178,23 @@ implements OnClickListener { footer.setOrientation(HORIZONTAL); footer.setGravity(CENTER); + goodButton = new ImageButton(this); + goodButton.setBackgroundResource(0); + goodButton.setImageResource(R.drawable.rating_good); + if(authorName == null) goodButton.setEnabled(false); + else goodButton.setOnClickListener(this); + footer.addView(goodButton); + footer.addView(new HorizontalSpace(this)); + + badButton = new ImageButton(this); + badButton.setBackgroundResource(0); + badButton.setImageResource(R.drawable.rating_bad); + badButton.setOnClickListener(this); + if(authorName == null) badButton.setEnabled(false); + else badButton.setOnClickListener(this); + footer.addView(badButton); + footer.addView(new HorizontalSpace(this)); + readButton = new ImageButton(this); readButton.setBackgroundResource(0); if(read) readButton.setImageResource(R.drawable.content_unread); @@ -241,6 +278,13 @@ implements OnClickListener { content.setText(text); } }); + } catch(NoSuchMessageException e) { + if(LOG.isLoggable(INFO)) LOG.info("Message removed"); + runOnUiThread(new Runnable() { + public void run() { + finish(); + } + }); } catch(DbException e) { if(LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e); @@ -268,7 +312,13 @@ implements OnClickListener { } public void onClick(View view) { - if(view == readButton) { + if(view == goodButton) { + if(rating == BAD) setRatingInDatabase(UNRATED); + else if(rating == UNRATED) setRatingInDatabase(GOOD); + } else if(view == badButton) { + if(rating == GOOD) setRatingInDatabase(UNRATED); + else if(rating == UNRATED) setRatingInDatabase(BAD); + } else if(view == readButton) { setReadInDatabase(!read); } else if(view == prevButton) { setResult(RESULT_PREV); @@ -285,4 +335,42 @@ implements OnClickListener { finish(); } } + + private void setRatingInDatabase(final Rating r) { + final DatabaseComponent db = this.db; + final AuthorId authorId = this.authorId; + dbExecutor.execute(new Runnable() { + public void run() { + try { + serviceConnection.waitForStartup(); + db.setRating(authorId, r); + setRatingInUi(r); + } catch(DbException e) { + if(LOG.isLoggable(WARNING)) + LOG.log(WARNING, e.toString(), e); + } catch(InterruptedException e) { + if(LOG.isLoggable(INFO)) + LOG.info("Interrupted while waiting for service"); + Thread.currentThread().interrupt(); + } + } + }); + } + + private void setRatingInUi(final Rating r) { + runOnUiThread(new Runnable() { + public void run() { + ReadGroupMessageActivity.this.rating = r; + if(r == GOOD) { + thumb.setImageResource(R.drawable.rating_good); + thumb.setVisibility(VISIBLE); + } else if(r == BAD) { + thumb.setImageResource(R.drawable.rating_bad); + thumb.setVisibility(VISIBLE); + } else { + thumb.setVisibility(GONE); + } + } + }); + } } diff --git a/briar-android/src/net/sf/briar/android/messages/ConversationActivity.java b/briar-android/src/net/sf/briar/android/messages/ConversationActivity.java index b382e920ee2553ed4477be64aab9c25065a2ef3f..f130f17374933e72a9b63f1a2372116ffde96d67 100644 --- a/briar-android/src/net/sf/briar/android/messages/ConversationActivity.java +++ b/briar-android/src/net/sf/briar/android/messages/ConversationActivity.java @@ -23,7 +23,9 @@ import net.sf.briar.api.ContactId; import net.sf.briar.api.db.DatabaseComponent; import net.sf.briar.api.db.DatabaseExecutor; import net.sf.briar.api.db.DbException; +import net.sf.briar.api.db.NoSuchContactException; import net.sf.briar.api.db.PrivateMessageHeader; +import net.sf.briar.api.db.event.ContactRemovedEvent; import net.sf.briar.api.db.event.DatabaseEvent; import net.sf.briar.api.db.event.DatabaseListener; import net.sf.briar.api.db.event.MessageAddedEvent; @@ -120,6 +122,13 @@ implements DatabaseListener, OnClickListener, OnItemClickListener { LOG.info("Loaded " + headers.size() + " headers"); // Update the conversation updateConversation(headers); + } catch(NoSuchContactException e) { + if(LOG.isLoggable(INFO)) LOG.info("Contact removed"); + runOnUiThread(new Runnable() { + public void run() { + finish(); + } + }); } catch(DbException e) { if(LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e); @@ -173,7 +182,13 @@ implements DatabaseListener, OnClickListener, OnItemClickListener { } public void eventOccurred(DatabaseEvent e) { - if(e instanceof MessageAddedEvent) { + if(e instanceof ContactRemovedEvent) { + ContactRemovedEvent c = (ContactRemovedEvent) e; + if(c.getContactId().equals(contactId)) { + if(LOG.isLoggable(INFO)) LOG.info("Contact removed"); + finish(); + } + } else if(e instanceof MessageAddedEvent) { if(LOG.isLoggable(INFO)) LOG.info("Message added, reloading"); reloadMessageHeaders(); } else if(e instanceof MessageExpiredEvent) { diff --git a/briar-android/src/net/sf/briar/android/messages/ReadPrivateMessageActivity.java b/briar-android/src/net/sf/briar/android/messages/ReadPrivateMessageActivity.java index afe0944578c549bc4b61bba270f150c8c6db5a6b..222bb307f29cbb5d51340e76618d17bee1f79cc0 100644 --- a/briar-android/src/net/sf/briar/android/messages/ReadPrivateMessageActivity.java +++ b/briar-android/src/net/sf/briar/android/messages/ReadPrivateMessageActivity.java @@ -24,6 +24,7 @@ import net.sf.briar.api.android.BundleEncrypter; import net.sf.briar.api.db.DatabaseComponent; import net.sf.briar.api.db.DatabaseExecutor; import net.sf.briar.api.db.DbException; +import net.sf.briar.api.db.NoSuchMessageException; import net.sf.briar.api.messaging.MessageId; import android.content.Intent; import android.os.Bundle; @@ -226,6 +227,13 @@ implements OnClickListener { content.setText(text); } }); + } catch(NoSuchMessageException e) { + if(LOG.isLoggable(INFO)) LOG.info("Message removed"); + runOnUiThread(new Runnable() { + public void run() { + finish(); + } + }); } catch(DbException e) { if(LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e); diff --git a/briar-api/src/net/sf/briar/api/crypto/CryptoExecutor.java b/briar-api/src/net/sf/briar/api/crypto/CryptoExecutor.java index 346ed893873589647d31d04d1e78085016433883..8e3ba8dc9cbcb4a9542e823ac3fd01914c0e37bc 100644 --- a/briar-api/src/net/sf/briar/api/crypto/CryptoExecutor.java +++ b/briar-api/src/net/sf/briar/api/crypto/CryptoExecutor.java @@ -1,5 +1,6 @@ package net.sf.briar.api.crypto; +import static java.lang.annotation.ElementType.FIELD; import static java.lang.annotation.ElementType.PARAMETER; import static java.lang.annotation.RetentionPolicy.RUNTIME; @@ -10,6 +11,6 @@ import com.google.inject.BindingAnnotation; /** Annotation for injecting the executor for long-running crypto tasks. */ @BindingAnnotation -@Target({ PARAMETER }) +@Target({ FIELD, PARAMETER }) @Retention(RUNTIME) public @interface CryptoExecutor {} diff --git a/briar-api/src/net/sf/briar/api/db/event/RatingChangedEvent.java b/briar-api/src/net/sf/briar/api/db/event/RatingChangedEvent.java index aec11c50f2de58b730c96822132b42e984f74a20..2c2bf6d7aa8a5da1bab7e3bf1f58b0d3d6275f55 100644 --- a/briar-api/src/net/sf/briar/api/db/event/RatingChangedEvent.java +++ b/briar-api/src/net/sf/briar/api/db/event/RatingChangedEvent.java @@ -13,7 +13,7 @@ public class RatingChangedEvent extends DatabaseEvent { this.rating = rating; } - public AuthorId getAuthor() { + public AuthorId getAuthorId() { return author; } diff --git a/briar-core/src/net/sf/briar/messaging/duplex/DuplexConnection.java b/briar-core/src/net/sf/briar/messaging/duplex/DuplexConnection.java index 9b56a720bff76a68937105d613f304699ed65431..2681ec67b5ed200457b0641d3ea0f2521203066f 100644 --- a/briar-core/src/net/sf/briar/messaging/duplex/DuplexConnection.java +++ b/briar-core/src/net/sf/briar/messaging/duplex/DuplexConnection.java @@ -86,7 +86,7 @@ abstract class DuplexConnection implements DatabaseListener { protected final ContactId contactId; protected final TransportId transportId; - private final Executor dbExecutor, verificationExecutor; + private final Executor dbExecutor, cryptoExecutor; private final MessageVerifier messageVerifier; private final long maxLatency; private final AtomicBoolean canSendOffer, disposed; @@ -97,7 +97,7 @@ abstract class DuplexConnection implements DatabaseListener { private volatile PacketWriter writer = null; DuplexConnection(@DatabaseExecutor Executor dbExecutor, - @CryptoExecutor Executor verificationExecutor, + @CryptoExecutor Executor cryptoExecutor, MessageVerifier messageVerifier, DatabaseComponent db, ConnectionRegistry connRegistry, ConnectionReaderFactory connReaderFactory, @@ -106,7 +106,7 @@ abstract class DuplexConnection implements DatabaseListener { PacketWriterFactory packetWriterFactory, ConnectionContext ctx, DuplexTransportConnection transport) { this.dbExecutor = dbExecutor; - this.verificationExecutor = verificationExecutor; + this.cryptoExecutor = cryptoExecutor; this.messageVerifier = messageVerifier; this.db = db; this.connRegistry = connRegistry; @@ -171,7 +171,7 @@ abstract class DuplexConnection implements DatabaseListener { dbExecutor.execute(new ReceiveAck(a)); } else if(reader.hasMessage()) { UnverifiedMessage m = reader.readMessage(); - verificationExecutor.execute(new VerifyMessage(m)); + cryptoExecutor.execute(new VerifyMessage(m)); } else if(reader.hasOffer()) { Offer o = reader.readOffer(); dbExecutor.execute(new ReceiveOffer(o)); diff --git a/briar-core/src/net/sf/briar/messaging/duplex/DuplexConnectionFactoryImpl.java b/briar-core/src/net/sf/briar/messaging/duplex/DuplexConnectionFactoryImpl.java index 2c98cbf690327c548a1629b04932aa8df3a6f020..f141fce031e54e0f3658207fe0a6e3bcb8dd8873 100644 --- a/briar-core/src/net/sf/briar/messaging/duplex/DuplexConnectionFactoryImpl.java +++ b/briar-core/src/net/sf/briar/messaging/duplex/DuplexConnectionFactoryImpl.java @@ -28,7 +28,7 @@ class DuplexConnectionFactoryImpl implements DuplexConnectionFactory { private static final Logger LOG = Logger.getLogger(DuplexConnectionFactoryImpl.class.getName()); - private final Executor dbExecutor, verificationExecutor; + private final Executor dbExecutor, cryptoExecutor; private final MessageVerifier messageVerifier; private final DatabaseComponent db; private final KeyManager keyManager; @@ -40,7 +40,7 @@ class DuplexConnectionFactoryImpl implements DuplexConnectionFactory { @Inject DuplexConnectionFactoryImpl(@DatabaseExecutor Executor dbExecutor, - @CryptoExecutor Executor verificationExecutor, + @CryptoExecutor Executor cryptoExecutor, MessageVerifier messageVerifier, DatabaseComponent db, KeyManager keyManager, ConnectionRegistry connRegistry, ConnectionReaderFactory connReaderFactory, @@ -48,7 +48,7 @@ class DuplexConnectionFactoryImpl implements DuplexConnectionFactory { PacketReaderFactory packetReaderFactory, PacketWriterFactory packetWriterFactory) { this.dbExecutor = dbExecutor; - this.verificationExecutor = verificationExecutor; + this.cryptoExecutor = cryptoExecutor; this.messageVerifier = messageVerifier; this.db = db; this.keyManager = keyManager; @@ -62,7 +62,7 @@ class DuplexConnectionFactoryImpl implements DuplexConnectionFactory { public void createIncomingConnection(ConnectionContext ctx, DuplexTransportConnection transport) { final DuplexConnection conn = new IncomingDuplexConnection(dbExecutor, - verificationExecutor, messageVerifier, db, connRegistry, + cryptoExecutor, messageVerifier, db, connRegistry, connReaderFactory, connWriterFactory, packetReaderFactory, packetWriterFactory, ctx, transport); Runnable write = new Runnable() { @@ -88,7 +88,7 @@ class DuplexConnectionFactoryImpl implements DuplexConnectionFactory { return; } final DuplexConnection conn = new OutgoingDuplexConnection(dbExecutor, - verificationExecutor, messageVerifier, db, connRegistry, + cryptoExecutor, messageVerifier, db, connRegistry, connReaderFactory, connWriterFactory, packetReaderFactory, packetWriterFactory, ctx, transport); Runnable write = new Runnable() { diff --git a/briar-core/src/net/sf/briar/messaging/duplex/IncomingDuplexConnection.java b/briar-core/src/net/sf/briar/messaging/duplex/IncomingDuplexConnection.java index 08e955af9b4f4e9111ab1a4d3dbc10aef70043c4..61fe58c97a7ae61d036bc4ddbe853afaeda39cf3 100644 --- a/briar-core/src/net/sf/briar/messaging/duplex/IncomingDuplexConnection.java +++ b/briar-core/src/net/sf/briar/messaging/duplex/IncomingDuplexConnection.java @@ -20,7 +20,7 @@ import net.sf.briar.api.transport.ConnectionWriterFactory; class IncomingDuplexConnection extends DuplexConnection { IncomingDuplexConnection(@DatabaseExecutor Executor dbExecutor, - @CryptoExecutor Executor verificationExecutor, + @CryptoExecutor Executor cryptoExecutor, MessageVerifier messageVerifier, DatabaseComponent db, ConnectionRegistry connRegistry, ConnectionReaderFactory connReaderFactory, @@ -28,9 +28,9 @@ class IncomingDuplexConnection extends DuplexConnection { PacketReaderFactory packetReaderFactory, PacketWriterFactory packetWriterFactory, ConnectionContext ctx, DuplexTransportConnection transport) { - super(dbExecutor, verificationExecutor, messageVerifier, db, - connRegistry, connReaderFactory, connWriterFactory, - packetReaderFactory, packetWriterFactory, ctx, transport); + super(dbExecutor, cryptoExecutor, messageVerifier, db, connRegistry, + connReaderFactory, connWriterFactory, packetReaderFactory, + packetWriterFactory, ctx, transport); } @Override diff --git a/briar-core/src/net/sf/briar/messaging/duplex/OutgoingDuplexConnection.java b/briar-core/src/net/sf/briar/messaging/duplex/OutgoingDuplexConnection.java index 2a852a45c14ce4b78a6daf361c0e8b7684d9988a..e59adb983f933102ef8bafd437d005b01a5ce424 100644 --- a/briar-core/src/net/sf/briar/messaging/duplex/OutgoingDuplexConnection.java +++ b/briar-core/src/net/sf/briar/messaging/duplex/OutgoingDuplexConnection.java @@ -20,7 +20,7 @@ import net.sf.briar.api.transport.ConnectionWriterFactory; class OutgoingDuplexConnection extends DuplexConnection { OutgoingDuplexConnection(@DatabaseExecutor Executor dbExecutor, - @CryptoExecutor Executor verificationExecutor, + @CryptoExecutor Executor cryptoExecutor, MessageVerifier messageVerifier, DatabaseComponent db, ConnectionRegistry connRegistry, ConnectionReaderFactory connReaderFactory, @@ -28,9 +28,9 @@ class OutgoingDuplexConnection extends DuplexConnection { PacketReaderFactory packetReaderFactory, PacketWriterFactory packetWriterFactory, ConnectionContext ctx, DuplexTransportConnection transport) { - super(dbExecutor, verificationExecutor, messageVerifier, db, - connRegistry, connReaderFactory, connWriterFactory, - packetReaderFactory, packetWriterFactory, ctx, transport); + super(dbExecutor, cryptoExecutor, messageVerifier, db, connRegistry, + connReaderFactory, connWriterFactory, packetReaderFactory, + packetWriterFactory, ctx, transport); } @Override diff --git a/briar-core/src/net/sf/briar/messaging/simplex/IncomingSimplexConnection.java b/briar-core/src/net/sf/briar/messaging/simplex/IncomingSimplexConnection.java index bac3930cabc0cfca536f688a8b7f40e23e38c766..cfb18c5039fba8c6b1d44b1c25f77cacf4cc9525 100644 --- a/briar-core/src/net/sf/briar/messaging/simplex/IncomingSimplexConnection.java +++ b/briar-core/src/net/sf/briar/messaging/simplex/IncomingSimplexConnection.java @@ -39,7 +39,7 @@ class IncomingSimplexConnection { private static final Logger LOG = Logger.getLogger(IncomingSimplexConnection.class.getName()); - private final Executor dbExecutor, verificationExecutor; + private final Executor dbExecutor, cryptoExecutor; private final MessageVerifier messageVerifier; private final DatabaseComponent db; private final ConnectionRegistry connRegistry; @@ -51,14 +51,14 @@ class IncomingSimplexConnection { private final TransportId transportId; IncomingSimplexConnection(@DatabaseExecutor Executor dbExecutor, - @CryptoExecutor Executor verificationExecutor, + @CryptoExecutor Executor cryptoExecutor, MessageVerifier messageVerifier, DatabaseComponent db, ConnectionRegistry connRegistry, ConnectionReaderFactory connReaderFactory, PacketReaderFactory packetReaderFactory, ConnectionContext ctx, SimplexTransportReader transport) { this.dbExecutor = dbExecutor; - this.verificationExecutor = verificationExecutor; + this.cryptoExecutor = cryptoExecutor; this.messageVerifier = messageVerifier; this.db = db; this.connRegistry = connRegistry; @@ -84,7 +84,7 @@ class IncomingSimplexConnection { dbExecutor.execute(new ReceiveAck(a)); } else if(reader.hasMessage()) { UnverifiedMessage m = reader.readMessage(); - verificationExecutor.execute(new VerifyMessage(m)); + cryptoExecutor.execute(new VerifyMessage(m)); } else if(reader.hasRetentionAck()) { RetentionAck a = reader.readRetentionAck(); dbExecutor.execute(new ReceiveRetentionAck(a)); diff --git a/briar-core/src/net/sf/briar/messaging/simplex/SimplexConnectionFactoryImpl.java b/briar-core/src/net/sf/briar/messaging/simplex/SimplexConnectionFactoryImpl.java index 5764c512b3a47610988bcf12fc4d5d80d872e633..b7f5ecdd3b11b688624532fecd65f0ccfe3b78d0 100644 --- a/briar-core/src/net/sf/briar/messaging/simplex/SimplexConnectionFactoryImpl.java +++ b/briar-core/src/net/sf/briar/messaging/simplex/SimplexConnectionFactoryImpl.java @@ -29,7 +29,7 @@ class SimplexConnectionFactoryImpl implements SimplexConnectionFactory { private static final Logger LOG = Logger.getLogger(SimplexConnectionFactoryImpl.class.getName()); - private final Executor dbExecutor, verificationExecutor; + private final Executor dbExecutor, cryptoExecutor; private final MessageVerifier messageVerifier; private final DatabaseComponent db; private final KeyManager keyManager; @@ -41,7 +41,7 @@ class SimplexConnectionFactoryImpl implements SimplexConnectionFactory { @Inject SimplexConnectionFactoryImpl(@DatabaseExecutor Executor dbExecutor, - @CryptoExecutor Executor verificationExecutor, + @CryptoExecutor Executor cryptoExecutor, MessageVerifier messageVerifier, DatabaseComponent db, KeyManager keyManager, ConnectionRegistry connRegistry, ConnectionReaderFactory connReaderFactory, @@ -49,7 +49,7 @@ class SimplexConnectionFactoryImpl implements SimplexConnectionFactory { PacketReaderFactory packetReaderFactory, PacketWriterFactory packetWriterFactory) { this.dbExecutor = dbExecutor; - this.verificationExecutor = verificationExecutor; + this.cryptoExecutor = cryptoExecutor; this.messageVerifier = messageVerifier; this.db = db; this.keyManager = keyManager; @@ -60,10 +60,11 @@ class SimplexConnectionFactoryImpl implements SimplexConnectionFactory { this.packetWriterFactory = packetWriterFactory; } - public void createIncomingConnection(ConnectionContext ctx, SimplexTransportReader r) { + public void createIncomingConnection(ConnectionContext ctx, + SimplexTransportReader r) { final IncomingSimplexConnection conn = new IncomingSimplexConnection( - dbExecutor, verificationExecutor, messageVerifier, db, - connRegistry, connReaderFactory, packetReaderFactory, ctx, r); + dbExecutor, cryptoExecutor, messageVerifier, db, connRegistry, + connReaderFactory, packetReaderFactory, ctx, r); Runnable read = new Runnable() { public void run() { conn.read();