From 83766433da17c566a4fce389473b70e8b2ca8b49 Mon Sep 17 00:00:00 2001 From: Moxie Marlinspike Date: Tue, 16 Feb 2016 11:16:52 -0800 Subject: [PATCH] Include group 'active' flag in device sync message. // FREEBIE --- .../api/messages/multidevice/DeviceGroup.java | 15 ++- .../multidevice/DeviceGroupsInputStream.java | 3 +- .../multidevice/DeviceGroupsOutputStream.java | 1 + .../internal/push/TextSecureProtos.java | 94 +++++++++++++++++-- protobuf/TextSecure.proto | 9 +- 5 files changed, 106 insertions(+), 16 deletions(-) diff --git a/java/src/main/java/org/whispersystems/textsecure/api/messages/multidevice/DeviceGroup.java b/java/src/main/java/org/whispersystems/textsecure/api/messages/multidevice/DeviceGroup.java index d5ce63baf6..6ee51f4c94 100644 --- a/java/src/main/java/org/whispersystems/textsecure/api/messages/multidevice/DeviceGroup.java +++ b/java/src/main/java/org/whispersystems/textsecure/api/messages/multidevice/DeviceGroup.java @@ -11,12 +11,14 @@ public class DeviceGroup { private final Optional name; private final List members; private final Optional avatar; + private final boolean active; - public DeviceGroup(byte[] id, Optional name, List members, Optional avatar) { - this.id = id; - this.name = name; - this.members = members; - this.avatar = avatar; + public DeviceGroup(byte[] id, Optional name, List members, Optional avatar, boolean active) { + this.id = id; + this.name = name; + this.members = members; + this.avatar = avatar; + this.active = active; } public Optional getAvatar() { @@ -35,4 +37,7 @@ public class DeviceGroup { return members; } + public boolean isActive() { + return active; + } } diff --git a/java/src/main/java/org/whispersystems/textsecure/api/messages/multidevice/DeviceGroupsInputStream.java b/java/src/main/java/org/whispersystems/textsecure/api/messages/multidevice/DeviceGroupsInputStream.java index f15fa82b8e..652f1481ee 100644 --- a/java/src/main/java/org/whispersystems/textsecure/api/messages/multidevice/DeviceGroupsInputStream.java +++ b/java/src/main/java/org/whispersystems/textsecure/api/messages/multidevice/DeviceGroupsInputStream.java @@ -30,6 +30,7 @@ public class DeviceGroupsInputStream extends ChunkedInputStream{ Optional name = Optional.fromNullable(details.getName()); List members = details.getMembersList(); Optional avatar = Optional.absent(); + boolean active = details.getActive(); if (details.hasAvatar()) { long avatarLength = details.getAvatar().getLength(); @@ -39,7 +40,7 @@ public class DeviceGroupsInputStream extends ChunkedInputStream{ avatar = Optional.of(new TextSecureAttachmentStream(avatarStream, avatarContentType, avatarLength, null)); } - return new DeviceGroup(id, name, members, avatar); + return new DeviceGroup(id, name, members, avatar, active); } } diff --git a/java/src/main/java/org/whispersystems/textsecure/api/messages/multidevice/DeviceGroupsOutputStream.java b/java/src/main/java/org/whispersystems/textsecure/api/messages/multidevice/DeviceGroupsOutputStream.java index aae9639d1c..75096bb073 100644 --- a/java/src/main/java/org/whispersystems/textsecure/api/messages/multidevice/DeviceGroupsOutputStream.java +++ b/java/src/main/java/org/whispersystems/textsecure/api/messages/multidevice/DeviceGroupsOutputStream.java @@ -44,6 +44,7 @@ public class DeviceGroupsOutputStream extends ChunkedOutputStream { } groupDetails.addAllMembers(group.getMembers()); + groupDetails.setActive(group.isActive()); byte[] serializedContactDetails = groupDetails.build().toByteArray(); diff --git a/java/src/main/java/org/whispersystems/textsecure/internal/push/TextSecureProtos.java b/java/src/main/java/org/whispersystems/textsecure/internal/push/TextSecureProtos.java index ee3d6b2861..c88b314df7 100644 --- a/java/src/main/java/org/whispersystems/textsecure/internal/push/TextSecureProtos.java +++ b/java/src/main/java/org/whispersystems/textsecure/internal/push/TextSecureProtos.java @@ -9798,6 +9798,16 @@ public final class TextSecureProtos { * optional .textsecure.GroupDetails.Avatar avatar = 4; */ org.whispersystems.textsecure.internal.push.TextSecureProtos.GroupDetails.AvatarOrBuilder getAvatarOrBuilder(); + + // optional bool active = 5 [default = true]; + /** + * optional bool active = 5 [default = true]; + */ + boolean hasActive(); + /** + * optional bool active = 5 [default = true]; + */ + boolean getActive(); } /** * Protobuf type {@code textsecure.GroupDetails} @@ -9881,6 +9891,11 @@ public final class TextSecureProtos { bitField0_ |= 0x00000004; break; } + case 40: { + bitField0_ |= 0x00000008; + active_ = input.readBool(); + break; + } } } } catch (com.google.protobuf.InvalidProtocolBufferException e) { @@ -10587,11 +10602,28 @@ public final class TextSecureProtos { return avatar_; } + // optional bool active = 5 [default = true]; + public static final int ACTIVE_FIELD_NUMBER = 5; + private boolean active_; + /** + * optional bool active = 5 [default = true]; + */ + public boolean hasActive() { + return ((bitField0_ & 0x00000008) == 0x00000008); + } + /** + * optional bool active = 5 [default = true]; + */ + public boolean getActive() { + return active_; + } + private void initFields() { id_ = com.google.protobuf.ByteString.EMPTY; name_ = ""; members_ = com.google.protobuf.LazyStringArrayList.EMPTY; avatar_ = org.whispersystems.textsecure.internal.push.TextSecureProtos.GroupDetails.Avatar.getDefaultInstance(); + active_ = true; } private byte memoizedIsInitialized = -1; public final boolean isInitialized() { @@ -10617,6 +10649,9 @@ public final class TextSecureProtos { if (((bitField0_ & 0x00000004) == 0x00000004)) { output.writeMessage(4, avatar_); } + if (((bitField0_ & 0x00000008) == 0x00000008)) { + output.writeBool(5, active_); + } getUnknownFields().writeTo(output); } @@ -10647,6 +10682,10 @@ public final class TextSecureProtos { size += com.google.protobuf.CodedOutputStream .computeMessageSize(4, avatar_); } + if (((bitField0_ & 0x00000008) == 0x00000008)) { + size += com.google.protobuf.CodedOutputStream + .computeBoolSize(5, active_); + } size += getUnknownFields().getSerializedSize(); memoizedSerializedSize = size; return size; @@ -10776,6 +10815,8 @@ public final class TextSecureProtos { avatarBuilder_.clear(); } bitField0_ = (bitField0_ & ~0x00000008); + active_ = true; + bitField0_ = (bitField0_ & ~0x00000010); return this; } @@ -10826,6 +10867,10 @@ public final class TextSecureProtos { } else { result.avatar_ = avatarBuilder_.build(); } + if (((from_bitField0_ & 0x00000010) == 0x00000010)) { + to_bitField0_ |= 0x00000008; + } + result.active_ = active_; result.bitField0_ = to_bitField0_; onBuilt(); return result; @@ -10863,6 +10908,9 @@ public final class TextSecureProtos { if (other.hasAvatar()) { mergeAvatar(other.getAvatar()); } + if (other.hasActive()) { + setActive(other.getActive()); + } this.mergeUnknownFields(other.getUnknownFields()); return this; } @@ -11210,6 +11258,39 @@ public final class TextSecureProtos { return avatarBuilder_; } + // optional bool active = 5 [default = true]; + private boolean active_ = true; + /** + * optional bool active = 5 [default = true]; + */ + public boolean hasActive() { + return ((bitField0_ & 0x00000010) == 0x00000010); + } + /** + * optional bool active = 5 [default = true]; + */ + public boolean getActive() { + return active_; + } + /** + * optional bool active = 5 [default = true]; + */ + public Builder setActive(boolean value) { + bitField0_ |= 0x00000010; + active_ = value; + onChanged(); + return this; + } + /** + * optional bool active = 5 [default = true]; + */ + public Builder clearActive() { + bitField0_ = (bitField0_ & ~0x00000010); + active_ = true; + onChanged(); + return this; + } + // @@protoc_insertion_point(builder_scope:textsecure.GroupDetails) } @@ -11338,12 +11419,13 @@ public final class TextSecureProtos { "\016\n\006number\030\001 \001(\t\022\014\n\004name\030\002 \001(\t\0221\n\006avatar\030" + "\003 \001(\0132!.textsecure.ContactDetails.Avatar" + "\032-\n\006Avatar\022\023\n\013contentType\030\001 \001(\t\022\016\n\006lengt" + - "h\030\002 \001(\r\"\231\001\n\014GroupDetails\022\n\n\002id\030\001 \001(\014\022\014\n\004" + + "h\030\002 \001(\r\"\257\001\n\014GroupDetails\022\n\n\002id\030\001 \001(\014\022\014\n\004" + "name\030\002 \001(\t\022\017\n\007members\030\003 \003(\t\022/\n\006avatar\030\004 ", - "\001(\0132\037.textsecure.GroupDetails.Avatar\032-\n\006" + - "Avatar\022\023\n\013contentType\030\001 \001(\t\022\016\n\006length\030\002 " + - "\001(\rB?\n+org.whispersystems.textsecure.int" + - "ernal.pushB\020TextSecureProtos" + "\001(\0132\037.textsecure.GroupDetails.Avatar\022\024\n\006" + + "active\030\005 \001(\010:\004true\032-\n\006Avatar\022\023\n\013contentT" + + "ype\030\001 \001(\t\022\016\n\006length\030\002 \001(\rB?\n+org.whisper" + + "systems.textsecure.internal.pushB\020TextSe" + + "cureProtos" }; com.google.protobuf.Descriptors.FileDescriptor.InternalDescriptorAssigner assigner = new com.google.protobuf.Descriptors.FileDescriptor.InternalDescriptorAssigner() { @@ -11427,7 +11509,7 @@ public final class TextSecureProtos { internal_static_textsecure_GroupDetails_fieldAccessorTable = new com.google.protobuf.GeneratedMessage.FieldAccessorTable( internal_static_textsecure_GroupDetails_descriptor, - new java.lang.String[] { "Id", "Name", "Members", "Avatar", }); + new java.lang.String[] { "Id", "Name", "Members", "Avatar", "Active", }); internal_static_textsecure_GroupDetails_Avatar_descriptor = internal_static_textsecure_GroupDetails_descriptor.getNestedTypes().get(0); internal_static_textsecure_GroupDetails_Avatar_fieldAccessorTable = new diff --git a/protobuf/TextSecure.proto b/protobuf/TextSecure.proto index 91514c4bc9..f927ae4584 100644 --- a/protobuf/TextSecure.proto +++ b/protobuf/TextSecure.proto @@ -107,8 +107,9 @@ message GroupDetails { optional uint32 length = 2; } - optional bytes id = 1; - optional string name = 2; - repeated string members = 3; - optional Avatar avatar = 4; + optional bytes id = 1; + optional string name = 2; + repeated string members = 3; + optional Avatar avatar = 4; + optional bool active = 5 [default = true]; }