Removes groupv1 protos
This commit is contained in:
parent
6c70cd450b
commit
8aac997b4f
13 changed files with 21 additions and 373 deletions
|
@ -189,7 +189,7 @@
|
||||||
"@electron/fuses": "1.5.0",
|
"@electron/fuses": "1.5.0",
|
||||||
"@formatjs/intl": "2.6.7",
|
"@formatjs/intl": "2.6.7",
|
||||||
"@mixer/parallel-prettier": "2.0.3",
|
"@mixer/parallel-prettier": "2.0.3",
|
||||||
"@signalapp/mock-server": "3.2.1",
|
"@signalapp/mock-server": "3.2.3",
|
||||||
"@storybook/addon-a11y": "6.5.6",
|
"@storybook/addon-a11y": "6.5.6",
|
||||||
"@storybook/addon-actions": "6.5.6",
|
"@storybook/addon-actions": "6.5.6",
|
||||||
"@storybook/addon-controls": "6.5.6",
|
"@storybook/addon-controls": "6.5.6",
|
||||||
|
|
|
@ -315,10 +315,10 @@ message DataMessage {
|
||||||
STRIKETHROUGH = 4;
|
STRIKETHROUGH = 4;
|
||||||
MONOSPACE = 5;
|
MONOSPACE = 5;
|
||||||
}
|
}
|
||||||
|
|
||||||
optional uint32 start = 1;
|
optional uint32 start = 1;
|
||||||
optional uint32 length = 2;
|
optional uint32 length = 2;
|
||||||
|
|
||||||
oneof associatedValue {
|
oneof associatedValue {
|
||||||
string mentionUuid = 3;
|
string mentionUuid = 3;
|
||||||
Style style = 4;
|
Style style = 4;
|
||||||
|
@ -493,10 +493,6 @@ message SyncMessage {
|
||||||
optional bool complete = 2 [default = false];
|
optional bool complete = 2 [default = false];
|
||||||
}
|
}
|
||||||
|
|
||||||
message Groups {
|
|
||||||
optional AttachmentPointer blob = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
message Blocked {
|
message Blocked {
|
||||||
repeated string numbers = 1;
|
repeated string numbers = 1;
|
||||||
repeated string uuids = 3;
|
repeated string uuids = 3;
|
||||||
|
@ -507,7 +503,7 @@ message SyncMessage {
|
||||||
enum Type {
|
enum Type {
|
||||||
UNKNOWN = 0;
|
UNKNOWN = 0;
|
||||||
CONTACTS = 1;
|
CONTACTS = 1;
|
||||||
GROUPS = 2;
|
reserved /* GROUPS */ 2;
|
||||||
BLOCKED = 3;
|
BLOCKED = 3;
|
||||||
CONFIGURATION = 4;
|
CONFIGURATION = 4;
|
||||||
KEYS = 5;
|
KEYS = 5;
|
||||||
|
@ -623,7 +619,7 @@ message SyncMessage {
|
||||||
|
|
||||||
optional Sent sent = 1;
|
optional Sent sent = 1;
|
||||||
optional Contacts contacts = 2;
|
optional Contacts contacts = 2;
|
||||||
optional Groups groups = 3;
|
reserved /* groups */ 3;
|
||||||
optional Request request = 4;
|
optional Request request = 4;
|
||||||
repeated Read read = 5;
|
repeated Read read = 5;
|
||||||
optional Blocked blocked = 6;
|
optional Blocked blocked = 6;
|
||||||
|
@ -695,29 +691,6 @@ message ContactDetails {
|
||||||
optional uint32 inboxPosition = 10;
|
optional uint32 inboxPosition = 10;
|
||||||
}
|
}
|
||||||
|
|
||||||
message GroupDetails {
|
|
||||||
message Avatar {
|
|
||||||
optional string contentType = 1;
|
|
||||||
optional uint32 length = 2;
|
|
||||||
}
|
|
||||||
|
|
||||||
message Member {
|
|
||||||
optional string uuid = 1;
|
|
||||||
optional string e164 = 2;
|
|
||||||
}
|
|
||||||
|
|
||||||
optional bytes id = 1;
|
|
||||||
optional string name = 2;
|
|
||||||
repeated string membersE164 = 3;
|
|
||||||
repeated Member members = 9;
|
|
||||||
optional Avatar avatar = 4;
|
|
||||||
optional bool active = 5 [default = true];
|
|
||||||
optional uint32 expireTimer = 6;
|
|
||||||
optional string color = 7;
|
|
||||||
optional bool blocked = 8;
|
|
||||||
optional uint32 inboxPosition = 10;
|
|
||||||
}
|
|
||||||
|
|
||||||
message PniSignatureMessage {
|
message PniSignatureMessage {
|
||||||
optional bytes pni = 1;
|
optional bytes pni = 1;
|
||||||
// Signature *by* the PNI identity key *of* the ACI identity key
|
// Signature *by* the PNI identity key *of* the ACI identity key
|
||||||
|
|
102
ts/background.ts
102
ts/background.ts
|
@ -22,7 +22,6 @@ import createTaskWithTimeout, {
|
||||||
} from './textsecure/TaskWithTimeout';
|
} from './textsecure/TaskWithTimeout';
|
||||||
import type {
|
import type {
|
||||||
MessageAttributesType,
|
MessageAttributesType,
|
||||||
ConversationAttributesType,
|
|
||||||
ReactionAttributesType,
|
ReactionAttributesType,
|
||||||
} from './model-types.d';
|
} from './model-types.d';
|
||||||
import * as Bytes from './Bytes';
|
import * as Bytes from './Bytes';
|
||||||
|
@ -87,7 +86,6 @@ import type {
|
||||||
EnvelopeUnsealedEvent,
|
EnvelopeUnsealedEvent,
|
||||||
ErrorEvent,
|
ErrorEvent,
|
||||||
FetchLatestEvent,
|
FetchLatestEvent,
|
||||||
GroupEvent,
|
|
||||||
InvalidPlaintextEvent,
|
InvalidPlaintextEvent,
|
||||||
KeysEvent,
|
KeysEvent,
|
||||||
MessageEvent,
|
MessageEvent,
|
||||||
|
@ -108,7 +106,7 @@ import type {
|
||||||
import type { WebAPIType } from './textsecure/WebAPI';
|
import type { WebAPIType } from './textsecure/WebAPI';
|
||||||
import * as KeyChangeListener from './textsecure/KeyChangeListener';
|
import * as KeyChangeListener from './textsecure/KeyChangeListener';
|
||||||
import { UpdateKeysListener } from './textsecure/UpdateKeysListener';
|
import { UpdateKeysListener } from './textsecure/UpdateKeysListener';
|
||||||
import { isDirectConversation, isGroupV2 } from './util/whatTypeOfConversation';
|
import { isDirectConversation } from './util/whatTypeOfConversation';
|
||||||
import { BackOff, FIBONACCI_TIMEOUTS } from './util/BackOff';
|
import { BackOff, FIBONACCI_TIMEOUTS } from './util/BackOff';
|
||||||
import { AppViewType } from './state/ducks/app';
|
import { AppViewType } from './state/ducks/app';
|
||||||
import type { BadgesStateType } from './state/ducks/badges';
|
import type { BadgesStateType } from './state/ducks/badges';
|
||||||
|
@ -137,7 +135,6 @@ import { ReadStatus } from './messages/MessageReadStatus';
|
||||||
import type { SendStateByConversationId } from './messages/MessageSendState';
|
import type { SendStateByConversationId } from './messages/MessageSendState';
|
||||||
import { SendStatus } from './messages/MessageSendState';
|
import { SendStatus } from './messages/MessageSendState';
|
||||||
import * as AttachmentDownloads from './messageModifiers/AttachmentDownloads';
|
import * as AttachmentDownloads from './messageModifiers/AttachmentDownloads';
|
||||||
import * as Conversation from './types/Conversation';
|
|
||||||
import * as Stickers from './types/Stickers';
|
import * as Stickers from './types/Stickers';
|
||||||
import * as Errors from './types/errors';
|
import * as Errors from './types/errors';
|
||||||
import { SignalService as Proto } from './protobuf';
|
import { SignalService as Proto } from './protobuf';
|
||||||
|
@ -359,14 +356,6 @@ export async function startApp(): Promise<void> {
|
||||||
'contactSync',
|
'contactSync',
|
||||||
queuedEventListener(onContactSync)
|
queuedEventListener(onContactSync)
|
||||||
);
|
);
|
||||||
messageReceiver.addEventListener(
|
|
||||||
'group',
|
|
||||||
queuedEventListener(onGroupReceived)
|
|
||||||
);
|
|
||||||
messageReceiver.addEventListener(
|
|
||||||
'groupSync',
|
|
||||||
queuedEventListener(onGroupSyncComplete)
|
|
||||||
);
|
|
||||||
messageReceiver.addEventListener(
|
messageReceiver.addEventListener(
|
||||||
'sent',
|
'sent',
|
||||||
queuedEventListener(onSentMessage, false)
|
queuedEventListener(onSentMessage, false)
|
||||||
|
@ -573,12 +562,7 @@ export async function startApp(): Promise<void> {
|
||||||
window.setImmediate = window.nodeSetImmediate;
|
window.setImmediate = window.nodeSetImmediate;
|
||||||
|
|
||||||
const { Message } = window.Signal.Types;
|
const { Message } = window.Signal.Types;
|
||||||
const {
|
const { upgradeMessageSchema } = window.Signal.Migrations;
|
||||||
upgradeMessageSchema,
|
|
||||||
writeNewAttachmentData,
|
|
||||||
deleteAttachmentData,
|
|
||||||
doesAttachmentExist,
|
|
||||||
} = window.Signal.Migrations;
|
|
||||||
|
|
||||||
log.info('background page reloaded');
|
log.info('background page reloaded');
|
||||||
log.info('environment:', window.getEnvironment());
|
log.info('environment:', window.getEnvironment());
|
||||||
|
@ -1954,11 +1938,10 @@ export async function startApp(): Promise<void> {
|
||||||
MessageSender.getRequestConfigurationSyncMessage()
|
MessageSender.getRequestConfigurationSyncMessage()
|
||||||
),
|
),
|
||||||
singleProtoJobQueue.add(MessageSender.getRequestBlockSyncMessage()),
|
singleProtoJobQueue.add(MessageSender.getRequestBlockSyncMessage()),
|
||||||
singleProtoJobQueue.add(MessageSender.getRequestGroupSyncMessage()),
|
runStorageService(),
|
||||||
singleProtoJobQueue.add(
|
singleProtoJobQueue.add(
|
||||||
MessageSender.getRequestContactSyncMessage()
|
MessageSender.getRequestContactSyncMessage()
|
||||||
),
|
),
|
||||||
runStorageService(),
|
|
||||||
]);
|
]);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
log.error(
|
log.error(
|
||||||
|
@ -2311,85 +2294,6 @@ export async function startApp(): Promise<void> {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
async function onGroupSyncComplete(): Promise<void> {
|
|
||||||
log.info('onGroupSyncComplete');
|
|
||||||
await window.storage.put('synced_at', Date.now());
|
|
||||||
}
|
|
||||||
|
|
||||||
// Note: this handler is only for v1 groups received via 'group sync' messages
|
|
||||||
async function onGroupReceived(ev: GroupEvent): Promise<void> {
|
|
||||||
const details = ev.groupDetails;
|
|
||||||
const { id } = details;
|
|
||||||
|
|
||||||
const conversation = await window.ConversationController.getOrCreateAndWait(
|
|
||||||
id,
|
|
||||||
'group'
|
|
||||||
);
|
|
||||||
if (isGroupV2(conversation.attributes)) {
|
|
||||||
log.warn('Got group sync for v2 group: ', conversation.idForLogging());
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const memberConversations = details.membersE164.map(e164 =>
|
|
||||||
window.ConversationController.getOrCreate(e164, 'private')
|
|
||||||
);
|
|
||||||
|
|
||||||
const members = memberConversations.map(c => c.get('id'));
|
|
||||||
|
|
||||||
const updates: Partial<ConversationAttributesType> = {
|
|
||||||
name: details.name,
|
|
||||||
members,
|
|
||||||
type: 'group',
|
|
||||||
inbox_position: details.inboxPosition,
|
|
||||||
};
|
|
||||||
|
|
||||||
if (details.active) {
|
|
||||||
updates.left = false;
|
|
||||||
} else {
|
|
||||||
updates.left = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (details.blocked) {
|
|
||||||
conversation.block();
|
|
||||||
} else {
|
|
||||||
conversation.unblock();
|
|
||||||
}
|
|
||||||
|
|
||||||
conversation.set(updates);
|
|
||||||
|
|
||||||
// Update the conversation avatar only if new avatar exists and hash differs
|
|
||||||
const { avatar } = details;
|
|
||||||
if (avatar && avatar.data) {
|
|
||||||
const newAttributes = await Conversation.maybeUpdateAvatar(
|
|
||||||
conversation.attributes,
|
|
||||||
avatar.data,
|
|
||||||
{
|
|
||||||
writeNewAttachmentData,
|
|
||||||
deleteAttachmentData,
|
|
||||||
doesAttachmentExist,
|
|
||||||
}
|
|
||||||
);
|
|
||||||
conversation.set(newAttributes);
|
|
||||||
}
|
|
||||||
|
|
||||||
window.Signal.Data.updateConversation(conversation.attributes);
|
|
||||||
|
|
||||||
const { expireTimer } = details;
|
|
||||||
const isValidExpireTimer = typeof expireTimer === 'number';
|
|
||||||
if (!isValidExpireTimer) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
await conversation.updateExpirationTimer(expireTimer, {
|
|
||||||
// Note: because it's our conversationId, this notification will be marked read. But
|
|
||||||
// setting this will make 'isSetByOther' check true.
|
|
||||||
source: window.ConversationController.getOurConversationId(),
|
|
||||||
fromSync: true,
|
|
||||||
receivedAt: ev.receivedAtCounter,
|
|
||||||
reason: 'group sync',
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
// Received:
|
// Received:
|
||||||
async function handleMessageReceivedProfileUpdate({
|
async function handleMessageReceivedProfileUpdate({
|
||||||
data,
|
data,
|
||||||
|
|
|
@ -6,7 +6,7 @@ import protobuf from '../protobuf/wrap';
|
||||||
|
|
||||||
import * as Bytes from '../Bytes';
|
import * as Bytes from '../Bytes';
|
||||||
import { SignalService as Proto } from '../protobuf';
|
import { SignalService as Proto } from '../protobuf';
|
||||||
import { ContactBuffer, GroupBuffer } from '../textsecure/ContactsParser';
|
import { ContactBuffer } from '../textsecure/ContactsParser';
|
||||||
|
|
||||||
const { Writer } = protobuf;
|
const { Writer } = protobuf;
|
||||||
|
|
||||||
|
@ -70,58 +70,4 @@ describe('ContactsParser', () => {
|
||||||
assert.strictEqual(count, 3);
|
assert.strictEqual(count, 3);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('GroupBuffer', () => {
|
|
||||||
function getTestBuffer(): Uint8Array {
|
|
||||||
const avatarBuffer = generateAvatar();
|
|
||||||
|
|
||||||
const groupInfoBuffer = Proto.GroupDetails.encode({
|
|
||||||
id: new Uint8Array([1, 3, 3, 7]),
|
|
||||||
name: 'Hackers',
|
|
||||||
membersE164: ['cereal', 'burn', 'phreak', 'joey'],
|
|
||||||
avatar: { contentType: 'image/jpeg', length: avatarBuffer.length },
|
|
||||||
}).finish();
|
|
||||||
|
|
||||||
const writer = new Writer();
|
|
||||||
writer.bytes(groupInfoBuffer);
|
|
||||||
const prefixedGroup = writer.finish();
|
|
||||||
|
|
||||||
const chunks: Array<Uint8Array> = [];
|
|
||||||
for (let i = 0; i < 3; i += 1) {
|
|
||||||
chunks.push(prefixedGroup);
|
|
||||||
chunks.push(avatarBuffer);
|
|
||||||
}
|
|
||||||
|
|
||||||
return Bytes.concatenate(chunks);
|
|
||||||
}
|
|
||||||
|
|
||||||
it('parses an array buffer of groups', () => {
|
|
||||||
const bytes = getTestBuffer();
|
|
||||||
const groupBuffer = new GroupBuffer(bytes);
|
|
||||||
let group = groupBuffer.next();
|
|
||||||
let count = 0;
|
|
||||||
while (group !== undefined) {
|
|
||||||
count += 1;
|
|
||||||
assert.strictEqual(group.name, 'Hackers');
|
|
||||||
assert.deepEqual(group.id, new Uint8Array([1, 3, 3, 7]));
|
|
||||||
assert.sameMembers(group.membersE164, [
|
|
||||||
'cereal',
|
|
||||||
'burn',
|
|
||||||
'phreak',
|
|
||||||
'joey',
|
|
||||||
]);
|
|
||||||
assert.strictEqual(group.avatar?.contentType, 'image/jpeg');
|
|
||||||
assert.strictEqual(group.avatar?.length, 255);
|
|
||||||
assert.strictEqual(group.avatar?.data.byteLength, 255);
|
|
||||||
const avatarBytes = new Uint8Array(
|
|
||||||
group.avatar?.data || new Uint8Array(0)
|
|
||||||
);
|
|
||||||
for (let j = 0; j < 255; j += 1) {
|
|
||||||
assert.strictEqual(avatarBytes[j], j);
|
|
||||||
}
|
|
||||||
group = groupBuffer.next();
|
|
||||||
}
|
|
||||||
assert.strictEqual(count, 3);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
|
|
|
@ -72,7 +72,7 @@ describe('editing', function needsName() {
|
||||||
await bootstrap.teardown();
|
await bootstrap.teardown();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('handles outgoing edited messages phone -> desktop', async () => {
|
it('handles outgoing edited messages phone to desktop', async () => {
|
||||||
const { phone, desktop } = bootstrap;
|
const { phone, desktop } = bootstrap;
|
||||||
|
|
||||||
const window = await app.getWindow();
|
const window = await app.getWindow();
|
||||||
|
@ -130,7 +130,7 @@ describe('editing', function needsName() {
|
||||||
assert.strictEqual(await messages.count(), 1, 'message count');
|
assert.strictEqual(await messages.count(), 1, 'message count');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('handles incoming edited messages contact -> desktop', async () => {
|
it('handles incoming edited messages contact to desktop', async () => {
|
||||||
const { contacts, desktop } = bootstrap;
|
const { contacts, desktop } = bootstrap;
|
||||||
|
|
||||||
const window = await app.getWindow();
|
const window = await app.getWindow();
|
||||||
|
|
|
@ -31,8 +31,6 @@ type MessageWithAvatar<Message extends OptionalFields> = Omit<
|
||||||
expireTimer?: DurationInSeconds;
|
expireTimer?: DurationInSeconds;
|
||||||
};
|
};
|
||||||
|
|
||||||
export type ModifiedGroupDetails = MessageWithAvatar<Proto.GroupDetails>;
|
|
||||||
|
|
||||||
export type ModifiedContactDetails = MessageWithAvatar<Proto.ContactDetails>;
|
export type ModifiedContactDetails = MessageWithAvatar<Proto.ContactDetails>;
|
||||||
|
|
||||||
/* eslint-disable @typescript-eslint/brace-style -- Prettier conflicts with ESLint */
|
/* eslint-disable @typescript-eslint/brace-style -- Prettier conflicts with ESLint */
|
||||||
|
@ -107,41 +105,6 @@ abstract class ParserBase<
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export class GroupBuffer extends ParserBase<
|
|
||||||
Proto.GroupDetails,
|
|
||||||
typeof Proto.GroupDetails,
|
|
||||||
ModifiedGroupDetails
|
|
||||||
> {
|
|
||||||
constructor(arrayBuffer: Uint8Array) {
|
|
||||||
super(arrayBuffer, Proto.GroupDetails);
|
|
||||||
}
|
|
||||||
|
|
||||||
public override next(): ModifiedGroupDetails | undefined {
|
|
||||||
const proto = this.decodeDelimited();
|
|
||||||
if (!proto) {
|
|
||||||
return undefined;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!proto.members) {
|
|
||||||
return proto;
|
|
||||||
}
|
|
||||||
|
|
||||||
return {
|
|
||||||
...proto,
|
|
||||||
members: proto.members.map((member, i) => {
|
|
||||||
if (!member.uuid) {
|
|
||||||
return member;
|
|
||||||
}
|
|
||||||
|
|
||||||
return {
|
|
||||||
...member,
|
|
||||||
uuid: normalizeUuid(member.uuid, `GroupBuffer.member[${i}].uuid`),
|
|
||||||
};
|
|
||||||
}),
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export class ContactBuffer extends ParserBase<
|
export class ContactBuffer extends ParserBase<
|
||||||
Proto.ContactDetails,
|
Proto.ContactDetails,
|
||||||
typeof Proto.ContactDetails,
|
typeof Proto.ContactDetails,
|
||||||
|
|
|
@ -72,7 +72,7 @@ import type { EventHandler } from './EventTarget';
|
||||||
import EventTarget from './EventTarget';
|
import EventTarget from './EventTarget';
|
||||||
import { downloadAttachment } from './downloadAttachment';
|
import { downloadAttachment } from './downloadAttachment';
|
||||||
import type { IncomingWebSocketRequest } from './WebsocketResources';
|
import type { IncomingWebSocketRequest } from './WebsocketResources';
|
||||||
import { ContactBuffer, GroupBuffer } from './ContactsParser';
|
import { ContactBuffer } from './ContactsParser';
|
||||||
import type { WebAPIType } from './WebAPI';
|
import type { WebAPIType } from './WebAPI';
|
||||||
import type { Storage } from './Storage';
|
import type { Storage } from './Storage';
|
||||||
import { WarnOnlyError } from './Errors';
|
import { WarnOnlyError } from './Errors';
|
||||||
|
@ -112,8 +112,6 @@ import {
|
||||||
ReadSyncEvent,
|
ReadSyncEvent,
|
||||||
ViewSyncEvent,
|
ViewSyncEvent,
|
||||||
ContactSyncEvent,
|
ContactSyncEvent,
|
||||||
GroupEvent,
|
|
||||||
GroupSyncEvent,
|
|
||||||
StoryRecipientUpdateEvent,
|
StoryRecipientUpdateEvent,
|
||||||
CallEventSyncEvent,
|
CallEventSyncEvent,
|
||||||
} from './messageReceiverEvents';
|
} from './messageReceiverEvents';
|
||||||
|
@ -622,16 +620,6 @@ export default class MessageReceiver
|
||||||
handler: (ev: ContactSyncEvent) => void
|
handler: (ev: ContactSyncEvent) => void
|
||||||
): void;
|
): void;
|
||||||
|
|
||||||
public override addEventListener(
|
|
||||||
name: 'group',
|
|
||||||
handler: (ev: GroupEvent) => void
|
|
||||||
): void;
|
|
||||||
|
|
||||||
public override addEventListener(
|
|
||||||
name: 'groupSync',
|
|
||||||
handler: (ev: GroupSyncEvent) => void
|
|
||||||
): void;
|
|
||||||
|
|
||||||
public override addEventListener(
|
public override addEventListener(
|
||||||
name: 'envelopeQueued',
|
name: 'envelopeQueued',
|
||||||
handler: (ev: EnvelopeQueuedEvent) => void
|
handler: (ev: EnvelopeQueuedEvent) => void
|
||||||
|
@ -2998,10 +2986,6 @@ export default class MessageReceiver
|
||||||
// before moving on since it updates conversation state.
|
// before moving on since it updates conversation state.
|
||||||
return this.handleContacts(envelope, syncMessage.contacts);
|
return this.handleContacts(envelope, syncMessage.contacts);
|
||||||
}
|
}
|
||||||
if (syncMessage.groups) {
|
|
||||||
void this.handleGroups(envelope, syncMessage.groups);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (syncMessage.blocked) {
|
if (syncMessage.blocked) {
|
||||||
return this.handleBlocked(envelope, syncMessage.blocked);
|
return this.handleBlocked(envelope, syncMessage.blocked);
|
||||||
}
|
}
|
||||||
|
@ -3454,63 +3438,6 @@ export default class MessageReceiver
|
||||||
log.info('handleContacts: finished');
|
log.info('handleContacts: finished');
|
||||||
}
|
}
|
||||||
|
|
||||||
private async handleGroups(
|
|
||||||
envelope: ProcessedEnvelope,
|
|
||||||
groups: Proto.SyncMessage.IGroups
|
|
||||||
): Promise<void> {
|
|
||||||
const logId = getEnvelopeId(envelope);
|
|
||||||
log.info('group sync');
|
|
||||||
log.info(`MessageReceiver: handleGroups ${logId}`);
|
|
||||||
const { blob } = groups;
|
|
||||||
|
|
||||||
this.removeFromCache(envelope);
|
|
||||||
|
|
||||||
logUnexpectedUrgentValue(envelope, 'groupSync');
|
|
||||||
|
|
||||||
if (!blob) {
|
|
||||||
throw new Error('MessageReceiver.handleGroups: blob field was missing');
|
|
||||||
}
|
|
||||||
|
|
||||||
// Note: we do not return here because we don't want to block the next message on
|
|
||||||
// this attachment download and a lot of processing of that attachment.
|
|
||||||
const attachmentPointer = await this.handleAttachment(blob, {
|
|
||||||
disableRetries: true,
|
|
||||||
timeout: 90 * SECOND,
|
|
||||||
});
|
|
||||||
const groupBuffer = new GroupBuffer(attachmentPointer.data);
|
|
||||||
let groupDetails = groupBuffer.next();
|
|
||||||
const promises = [];
|
|
||||||
while (groupDetails) {
|
|
||||||
const { id } = groupDetails;
|
|
||||||
strictAssert(id, 'Group details without id');
|
|
||||||
|
|
||||||
if (id.byteLength !== 16) {
|
|
||||||
log.error(
|
|
||||||
`onGroupReceived: Id was ${id} bytes, expected 16 bytes. Dropping group.`
|
|
||||||
);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
const ev = new GroupEvent(
|
|
||||||
{
|
|
||||||
...groupDetails,
|
|
||||||
id: Bytes.toBinary(id),
|
|
||||||
},
|
|
||||||
envelope.receivedAtCounter
|
|
||||||
);
|
|
||||||
const promise = this.dispatchAndWait(logId, ev).catch(e => {
|
|
||||||
log.error('error processing group', e);
|
|
||||||
});
|
|
||||||
groupDetails = groupBuffer.next();
|
|
||||||
promises.push(promise);
|
|
||||||
}
|
|
||||||
|
|
||||||
await Promise.all(promises);
|
|
||||||
|
|
||||||
const ev = new GroupSyncEvent();
|
|
||||||
return this.dispatchAndWait(logId, ev);
|
|
||||||
}
|
|
||||||
|
|
||||||
private async handleBlocked(
|
private async handleBlocked(
|
||||||
envelope: ProcessedEnvelope,
|
envelope: ProcessedEnvelope,
|
||||||
blocked: Proto.SyncMessage.IBlocked
|
blocked: Proto.SyncMessage.IBlocked
|
||||||
|
|
|
@ -1367,30 +1367,6 @@ export default class MessageSender {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
static getRequestGroupSyncMessage(): SingleProtoJobData {
|
|
||||||
const myUuid = window.textsecure.storage.user.getCheckedUuid();
|
|
||||||
|
|
||||||
const request = new Proto.SyncMessage.Request();
|
|
||||||
request.type = Proto.SyncMessage.Request.Type.GROUPS;
|
|
||||||
const syncMessage = this.createSyncMessage();
|
|
||||||
syncMessage.request = request;
|
|
||||||
const contentMessage = new Proto.Content();
|
|
||||||
contentMessage.syncMessage = syncMessage;
|
|
||||||
|
|
||||||
const { ContentHint } = Proto.UnidentifiedSenderMessage.Message;
|
|
||||||
|
|
||||||
return {
|
|
||||||
contentHint: ContentHint.RESENDABLE,
|
|
||||||
identifier: myUuid.toString(),
|
|
||||||
isSyncMessage: true,
|
|
||||||
protoBase64: Bytes.toBase64(
|
|
||||||
Proto.Content.encode(contentMessage).finish()
|
|
||||||
),
|
|
||||||
type: 'groupSyncRequest',
|
|
||||||
urgent: false,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
static getRequestContactSyncMessage(): SingleProtoJobData {
|
static getRequestContactSyncMessage(): SingleProtoJobData {
|
||||||
const myUuid = window.textsecure.storage.user.getCheckedUuid();
|
const myUuid = window.textsecure.storage.user.getCheckedUuid();
|
||||||
|
|
||||||
|
|
|
@ -7,7 +7,7 @@
|
||||||
import type { EventHandler } from './EventTarget';
|
import type { EventHandler } from './EventTarget';
|
||||||
import EventTarget from './EventTarget';
|
import EventTarget from './EventTarget';
|
||||||
import MessageReceiver from './MessageReceiver';
|
import MessageReceiver from './MessageReceiver';
|
||||||
import type { ContactSyncEvent, GroupSyncEvent } from './messageReceiverEvents';
|
import type { ContactSyncEvent } from './messageReceiverEvents';
|
||||||
import MessageSender from './SendMessage';
|
import MessageSender from './SendMessage';
|
||||||
import { assertDev } from '../util/assert';
|
import { assertDev } from '../util/assert';
|
||||||
import * as log from '../logging/log';
|
import * as log from '../logging/log';
|
||||||
|
@ -19,14 +19,10 @@ class SyncRequestInner extends EventTarget {
|
||||||
|
|
||||||
contactSync?: boolean;
|
contactSync?: boolean;
|
||||||
|
|
||||||
groupSync?: boolean;
|
|
||||||
|
|
||||||
timeout: any;
|
timeout: any;
|
||||||
|
|
||||||
oncontact: (event: ContactSyncEvent) => void;
|
oncontact: (event: ContactSyncEvent) => void;
|
||||||
|
|
||||||
ongroup: (event: GroupSyncEvent) => void;
|
|
||||||
|
|
||||||
timeoutMillis: number;
|
timeoutMillis: number;
|
||||||
|
|
||||||
constructor(private receiver: MessageReceiver, timeoutMillis?: number) {
|
constructor(private receiver: MessageReceiver, timeoutMillis?: number) {
|
||||||
|
@ -41,9 +37,6 @@ class SyncRequestInner extends EventTarget {
|
||||||
this.oncontact = this.onContactSyncComplete.bind(this);
|
this.oncontact = this.onContactSyncComplete.bind(this);
|
||||||
receiver.addEventListener('contactSync', this.oncontact);
|
receiver.addEventListener('contactSync', this.oncontact);
|
||||||
|
|
||||||
this.ongroup = this.onGroupSyncComplete.bind(this);
|
|
||||||
receiver.addEventListener('groupSync', this.ongroup);
|
|
||||||
|
|
||||||
this.timeoutMillis = timeoutMillis || 60000;
|
this.timeoutMillis = timeoutMillis || 60000;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -72,7 +65,6 @@ class SyncRequestInner extends EventTarget {
|
||||||
),
|
),
|
||||||
singleProtoJobQueue.add(MessageSender.getRequestBlockSyncMessage()),
|
singleProtoJobQueue.add(MessageSender.getRequestBlockSyncMessage()),
|
||||||
singleProtoJobQueue.add(MessageSender.getRequestContactSyncMessage()),
|
singleProtoJobQueue.add(MessageSender.getRequestContactSyncMessage()),
|
||||||
singleProtoJobQueue.add(MessageSender.getRequestGroupSyncMessage()),
|
|
||||||
]);
|
]);
|
||||||
} catch (error: unknown) {
|
} catch (error: unknown) {
|
||||||
log.error(
|
log.error(
|
||||||
|
@ -89,20 +81,15 @@ class SyncRequestInner extends EventTarget {
|
||||||
this.update();
|
this.update();
|
||||||
}
|
}
|
||||||
|
|
||||||
onGroupSyncComplete() {
|
|
||||||
this.groupSync = true;
|
|
||||||
this.update();
|
|
||||||
}
|
|
||||||
|
|
||||||
update() {
|
update() {
|
||||||
if (this.contactSync && this.groupSync) {
|
if (this.contactSync) {
|
||||||
this.dispatchEvent(new Event('success'));
|
this.dispatchEvent(new Event('success'));
|
||||||
this.cleanup();
|
this.cleanup();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
onTimeout() {
|
onTimeout() {
|
||||||
if (this.contactSync || this.groupSync) {
|
if (this.contactSync) {
|
||||||
this.dispatchEvent(new Event('success'));
|
this.dispatchEvent(new Event('success'));
|
||||||
} else {
|
} else {
|
||||||
this.dispatchEvent(new Event('timeout'));
|
this.dispatchEvent(new Event('timeout'));
|
||||||
|
@ -113,7 +100,6 @@ class SyncRequestInner extends EventTarget {
|
||||||
cleanup() {
|
cleanup() {
|
||||||
clearTimeout(this.timeout);
|
clearTimeout(this.timeout);
|
||||||
this.receiver.removeEventListener('contactsync', this.oncontact);
|
this.receiver.removeEventListener('contactsync', this.oncontact);
|
||||||
this.receiver.removeEventListener('groupSync', this.ongroup);
|
|
||||||
delete this.listeners;
|
delete this.listeners;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,7 +5,7 @@ import EventTarget from './EventTarget';
|
||||||
import AccountManager from './AccountManager';
|
import AccountManager from './AccountManager';
|
||||||
import MessageReceiver from './MessageReceiver';
|
import MessageReceiver from './MessageReceiver';
|
||||||
import utils from './Helpers';
|
import utils from './Helpers';
|
||||||
import { ContactBuffer, GroupBuffer } from './ContactsParser';
|
import { ContactBuffer } from './ContactsParser';
|
||||||
import SyncRequest from './SyncRequest';
|
import SyncRequest from './SyncRequest';
|
||||||
import MessageSender from './SendMessage';
|
import MessageSender from './SendMessage';
|
||||||
import { Storage } from './Storage';
|
import { Storage } from './Storage';
|
||||||
|
@ -19,7 +19,6 @@ export type TextSecureType = {
|
||||||
AccountManager: typeof AccountManager;
|
AccountManager: typeof AccountManager;
|
||||||
ContactBuffer: typeof ContactBuffer;
|
ContactBuffer: typeof ContactBuffer;
|
||||||
EventTarget: typeof EventTarget;
|
EventTarget: typeof EventTarget;
|
||||||
GroupBuffer: typeof GroupBuffer;
|
|
||||||
MessageReceiver: typeof MessageReceiver;
|
MessageReceiver: typeof MessageReceiver;
|
||||||
MessageSender: typeof MessageSender;
|
MessageSender: typeof MessageSender;
|
||||||
SyncRequest: typeof SyncRequest;
|
SyncRequest: typeof SyncRequest;
|
||||||
|
@ -37,7 +36,6 @@ export const textsecure: TextSecureType = {
|
||||||
AccountManager,
|
AccountManager,
|
||||||
ContactBuffer,
|
ContactBuffer,
|
||||||
EventTarget,
|
EventTarget,
|
||||||
GroupBuffer,
|
|
||||||
MessageReceiver,
|
MessageReceiver,
|
||||||
MessageSender,
|
MessageSender,
|
||||||
SyncRequest,
|
SyncRequest,
|
||||||
|
|
|
@ -11,10 +11,7 @@ import type {
|
||||||
ProcessedDataMessage,
|
ProcessedDataMessage,
|
||||||
ProcessedSent,
|
ProcessedSent,
|
||||||
} from './Types.d';
|
} from './Types.d';
|
||||||
import type {
|
import type { ModifiedContactDetails } from './ContactsParser';
|
||||||
ModifiedContactDetails,
|
|
||||||
ModifiedGroupDetails,
|
|
||||||
} from './ContactsParser';
|
|
||||||
|
|
||||||
export class EmptyEvent extends Event {
|
export class EmptyEvent extends Event {
|
||||||
constructor() {
|
constructor() {
|
||||||
|
@ -84,26 +81,6 @@ export class ContactSyncEvent extends Event {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export type GroupEventData = Omit<ModifiedGroupDetails, 'id'> &
|
|
||||||
Readonly<{
|
|
||||||
id: string;
|
|
||||||
}>;
|
|
||||||
|
|
||||||
export class GroupEvent extends Event {
|
|
||||||
constructor(
|
|
||||||
public readonly groupDetails: GroupEventData,
|
|
||||||
public readonly receivedAtCounter: number
|
|
||||||
) {
|
|
||||||
super('group');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export class GroupSyncEvent extends Event {
|
|
||||||
constructor() {
|
|
||||||
super('groupSync');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Emitted right before we do full decrypt on a message, but after Sealed Sender unseal
|
// Emitted right before we do full decrypt on a message, but after Sealed Sender unseal
|
||||||
export class EnvelopeUnsealedEvent extends Event {
|
export class EnvelopeUnsealedEvent extends Event {
|
||||||
constructor(public readonly envelope: ProcessedEnvelope) {
|
constructor(public readonly envelope: ProcessedEnvelope) {
|
||||||
|
|
|
@ -43,7 +43,6 @@ export const sendTypesEnum = z.enum([
|
||||||
'blockSyncRequest',
|
'blockSyncRequest',
|
||||||
'configurationSyncRequest',
|
'configurationSyncRequest',
|
||||||
'contactSyncRequest', // urgent because it blocks the link process
|
'contactSyncRequest', // urgent because it blocks the link process
|
||||||
'groupSyncRequest',
|
|
||||||
'keySyncRequest', // urgent because it blocks the link process
|
'keySyncRequest', // urgent because it blocks the link process
|
||||||
'pniIdentitySyncRequest', // urgent because we need our PNI to be fully functional
|
'pniIdentitySyncRequest', // urgent because we need our PNI to be fully functional
|
||||||
|
|
||||||
|
@ -51,7 +50,6 @@ export const sendTypesEnum = z.enum([
|
||||||
'blockSync',
|
'blockSync',
|
||||||
'configurationSync',
|
'configurationSync',
|
||||||
'contactSync',
|
'contactSync',
|
||||||
'groupSync',
|
|
||||||
'keySync',
|
'keySync',
|
||||||
'pniIdentitySync',
|
'pniIdentitySync',
|
||||||
|
|
||||||
|
|
|
@ -2284,10 +2284,10 @@
|
||||||
node-gyp-build "^4.2.3"
|
node-gyp-build "^4.2.3"
|
||||||
uuid "^8.3.0"
|
uuid "^8.3.0"
|
||||||
|
|
||||||
"@signalapp/mock-server@3.2.1":
|
"@signalapp/mock-server@3.2.3":
|
||||||
version "3.2.1"
|
version "3.2.3"
|
||||||
resolved "https://registry.yarnpkg.com/@signalapp/mock-server/-/mock-server-3.2.1.tgz#36fd3e72b44dbcb6c82fdb27bbf56f8393e8f065"
|
resolved "https://registry.yarnpkg.com/@signalapp/mock-server/-/mock-server-3.2.3.tgz#86cebfb1d5e8054f88acc0dcb05c7e18a600dea1"
|
||||||
integrity sha512-irT4U3e8Lve9HODGIlXx+vElONaPNe7Ks9QRoSPSR4o0DbUX/g+zUxfEu7gjEi0CQI8OKxcJHe7e5DbE8mvXng==
|
integrity sha512-JTrrYbYZLyTva/9RPsP18QXYge2Rog9uw7vCEADmTpZbJ4jO3HRw6+viuCKiExpa+Kooe1LgbFfyH3n5iTxRQg==
|
||||||
dependencies:
|
dependencies:
|
||||||
"@signalapp/libsignal-client" "^0.29.0"
|
"@signalapp/libsignal-client" "^0.29.0"
|
||||||
debug "^4.3.2"
|
debug "^4.3.2"
|
||||||
|
|
Loading…
Reference in a new issue