Convert signal.js and preload.js to Typescript

This commit is contained in:
Scott Nonnenberg 2022-06-13 14:39:35 -07:00 committed by GitHub
parent e18510e41c
commit 2464e0a9c1
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
94 changed files with 2113 additions and 1848 deletions

View file

@ -55,7 +55,6 @@ import * as Errors from '../types/errors';
import { isEnabled } from '../RemoteConfig';
import { SignalService as Proto } from '../protobuf';
import type { UnprocessedType } from '../textsecure.d';
import { deriveGroupFields, MASTER_KEY_LENGTH } from '../groups';
import createTaskWithTimeout from './TaskWithTimeout';
@ -81,6 +80,7 @@ import type {
ProcessedSent,
ProcessedEnvelope,
IRequestHandler,
UnprocessedType,
} from './Types.d';
import {
EmptyEvent,
@ -114,6 +114,7 @@ import * as log from '../logging/log';
import * as durations from '../util/durations';
import { areArraysMatchingSets } from '../util/areArraysMatchingSets';
import { generateBlurHash } from '../util/generateBlurHash';
import { APPLICATION_OCTET_STREAM } from '../types/MIME';
const GROUPV1_ID_LENGTH = 16;
const GROUPV2_ID_LENGTH = 32;
@ -1800,8 +1801,14 @@ export default class MessageReceiver
}
if (msg.textAttachment) {
const { text } = msg.textAttachment;
if (!text) {
throw new Error('Text attachments must have text!');
}
attachments.push({
size: msg.textAttachment.text?.length,
size: text.length,
contentType: APPLICATION_OCTET_STREAM,
textAttachment: msg.textAttachment,
blurHash: generateBlurHash(
(msg.textAttachment.color ||

View file

@ -38,7 +38,11 @@ import type {
WebAPIType,
} from './WebAPI';
import createTaskWithTimeout from './TaskWithTimeout';
import type { CallbackResultType } from './Types.d';
import type {
CallbackResultType,
StorageServiceCallOptionsType,
StorageServiceCredentials,
} from './Types.d';
import type {
SerializedCertificateType,
SendLogCallbackType,
@ -47,10 +51,6 @@ import OutgoingMessage from './OutgoingMessage';
import type { CDSResponseType } from './CDSSocketManager';
import * as Bytes from '../Bytes';
import { getRandomBytes, getZeroes, encryptAttachment } from '../Crypto';
import type {
StorageServiceCallOptionsType,
StorageServiceCredentials,
} from '../textsecure.d';
import {
MessageError,
SignedPreKeyRotationError,
@ -73,6 +73,7 @@ import {
numberToEmailType,
numberToAddressType,
} from '../types/EmbeddedContact';
import type { StickerWithHydratedData } from '../types/Stickers';
export type SendMetadataType = {
[identifier: string]: {
@ -106,13 +107,7 @@ type GroupCallUpdateType = {
eraId: string;
};
export type StickerType = {
packId: string;
stickerId: number;
packKey: string;
data: Readonly<AttachmentType>;
emoji?: string;
export type StickerType = StickerWithHydratedData & {
attachmentPointer?: Proto.IAttachmentPointer;
};
@ -631,7 +626,7 @@ export default class MessageSender {
);
}
getRandomPadding(): Uint8Array {
static getRandomPadding(): Uint8Array {
// Generate a random int from 1 and 512
const buffer = getRandomBytes(2);
const paddingLength = (new Uint16Array(buffer)[0] & 0x1ff) + 1;
@ -996,7 +991,7 @@ export default class MessageSender {
};
}
createSyncMessage(): Proto.SyncMessage {
static createSyncMessage(): Proto.SyncMessage {
const syncMessage = new Proto.SyncMessage();
syncMessage.padding = this.getRandomPadding();
@ -1287,7 +1282,7 @@ export default class MessageSender {
];
}
const syncMessage = this.createSyncMessage();
const syncMessage = MessageSender.createSyncMessage();
syncMessage.sent = sentMessage;
const contentMessage = new Proto.Content();
contentMessage.syncMessage = syncMessage;
@ -1303,12 +1298,12 @@ export default class MessageSender {
});
}
getRequestBlockSyncMessage(): SingleProtoJobData {
static getRequestBlockSyncMessage(): SingleProtoJobData {
const myUuid = window.textsecure.storage.user.getCheckedUuid();
const request = new Proto.SyncMessage.Request();
request.type = Proto.SyncMessage.Request.Type.BLOCKED;
const syncMessage = this.createSyncMessage();
const syncMessage = MessageSender.createSyncMessage();
syncMessage.request = request;
const contentMessage = new Proto.Content();
contentMessage.syncMessage = syncMessage;
@ -1326,12 +1321,12 @@ export default class MessageSender {
};
}
getRequestConfigurationSyncMessage(): SingleProtoJobData {
static getRequestConfigurationSyncMessage(): SingleProtoJobData {
const myUuid = window.textsecure.storage.user.getCheckedUuid();
const request = new Proto.SyncMessage.Request();
request.type = Proto.SyncMessage.Request.Type.CONFIGURATION;
const syncMessage = this.createSyncMessage();
const syncMessage = MessageSender.createSyncMessage();
syncMessage.request = request;
const contentMessage = new Proto.Content();
contentMessage.syncMessage = syncMessage;
@ -1349,7 +1344,7 @@ export default class MessageSender {
};
}
getRequestGroupSyncMessage(): SingleProtoJobData {
static getRequestGroupSyncMessage(): SingleProtoJobData {
const myUuid = window.textsecure.storage.user.getCheckedUuid();
const request = new Proto.SyncMessage.Request();
@ -1372,7 +1367,7 @@ export default class MessageSender {
};
}
getRequestContactSyncMessage(): SingleProtoJobData {
static getRequestContactSyncMessage(): SingleProtoJobData {
const myUuid = window.textsecure.storage.user.getCheckedUuid();
const request = new Proto.SyncMessage.Request();
@ -1395,7 +1390,7 @@ export default class MessageSender {
};
}
getRequestPniIdentitySyncMessage(): SingleProtoJobData {
static getRequestPniIdentitySyncMessage(): SingleProtoJobData {
const myUuid = window.textsecure.storage.user.getCheckedUuid();
const request = new Proto.SyncMessage.Request();
@ -1418,7 +1413,7 @@ export default class MessageSender {
};
}
getFetchManifestSyncMessage(): SingleProtoJobData {
static getFetchManifestSyncMessage(): SingleProtoJobData {
const myUuid = window.textsecure.storage.user.getCheckedUuid();
const fetchLatest = new Proto.SyncMessage.FetchLatest();
@ -1442,7 +1437,7 @@ export default class MessageSender {
};
}
getFetchLocalProfileSyncMessage(): SingleProtoJobData {
static getFetchLocalProfileSyncMessage(): SingleProtoJobData {
const myUuid = window.textsecure.storage.user.getCheckedUuid();
const fetchLatest = new Proto.SyncMessage.FetchLatest();
@ -1466,7 +1461,7 @@ export default class MessageSender {
};
}
getRequestKeySyncMessage(): SingleProtoJobData {
static getRequestKeySyncMessage(): SingleProtoJobData {
const myUuid = window.textsecure.storage.user.getCheckedUuid();
const request = new Proto.SyncMessage.Request();
@ -1500,7 +1495,7 @@ export default class MessageSender {
): Promise<CallbackResultType> {
const myUuid = window.textsecure.storage.user.getCheckedUuid();
const syncMessage = this.createSyncMessage();
const syncMessage = MessageSender.createSyncMessage();
syncMessage.read = [];
for (let i = 0; i < reads.length; i += 1) {
const proto = new Proto.SyncMessage.Read({
@ -1534,7 +1529,7 @@ export default class MessageSender {
): Promise<CallbackResultType> {
const myUuid = window.textsecure.storage.user.getCheckedUuid();
const syncMessage = this.createSyncMessage();
const syncMessage = MessageSender.createSyncMessage();
syncMessage.viewed = views.map(
view =>
new Proto.SyncMessage.Viewed({
@ -1577,7 +1572,7 @@ export default class MessageSender {
const myUuid = window.textsecure.storage.user.getCheckedUuid();
const syncMessage = this.createSyncMessage();
const syncMessage = MessageSender.createSyncMessage();
const viewOnceOpen = new Proto.SyncMessage.ViewOnceOpen();
if (senderE164 !== undefined) {
@ -1601,7 +1596,7 @@ export default class MessageSender {
});
}
getMessageRequestResponseSync(
static getMessageRequestResponseSync(
options: Readonly<{
threadE164?: string;
threadUuid?: string;
@ -1611,7 +1606,7 @@ export default class MessageSender {
): SingleProtoJobData {
const myUuid = window.textsecure.storage.user.getCheckedUuid();
const syncMessage = this.createSyncMessage();
const syncMessage = MessageSender.createSyncMessage();
const response = new Proto.SyncMessage.MessageRequestResponse();
if (options.threadE164 !== undefined) {
@ -1642,7 +1637,7 @@ export default class MessageSender {
};
}
getStickerPackSync(
static getStickerPackSync(
operations: ReadonlyArray<{
packId: string;
packKey: string;
@ -1663,7 +1658,7 @@ export default class MessageSender {
return operation;
});
const syncMessage = this.createSyncMessage();
const syncMessage = MessageSender.createSyncMessage();
syncMessage.stickerPackOperation = packOperations;
const contentMessage = new Proto.Content();
@ -1682,7 +1677,7 @@ export default class MessageSender {
};
}
getVerificationSync(
static getVerificationSync(
destinationE164: string | undefined,
destinationUuid: string | undefined,
state: number,
@ -1694,7 +1689,7 @@ export default class MessageSender {
throw new Error('syncVerification: Neither e164 nor UUID were provided');
}
const padding = this.getRandomPadding();
const padding = MessageSender.getRandomPadding();
const verified = new Proto.Verified();
verified.state = state;
@ -1707,7 +1702,7 @@ export default class MessageSender {
verified.identityKey = identityKey;
verified.nullMessage = padding;
const syncMessage = this.createSyncMessage();
const syncMessage = MessageSender.createSyncMessage();
syncMessage.verified = verified;
const contentMessage = new Proto.Content();
@ -1832,7 +1827,7 @@ export default class MessageSender {
});
}
getNullMessage({
static getNullMessage({
uuid,
e164,
padding,
@ -1848,7 +1843,7 @@ export default class MessageSender {
throw new Error('sendNullMessage: Got neither uuid nor e164!');
}
nullMessage.padding = padding || this.getRandomPadding();
nullMessage.padding = padding || MessageSender.getRandomPadding();
const contentMessage = new Proto.Content();
contentMessage.nullMessage = nullMessage;

View file

@ -29,19 +29,12 @@ class SyncRequestInner extends EventTarget {
timeoutMillis: number;
constructor(
private sender: MessageSender,
private receiver: MessageReceiver,
timeoutMillis?: number
) {
constructor(private receiver: MessageReceiver, timeoutMillis?: number) {
super();
if (
!(sender instanceof MessageSender) ||
!(receiver instanceof MessageReceiver)
) {
if (!(receiver instanceof MessageReceiver)) {
throw new Error(
'Tried to construct a SyncRequest without MessageSender and MessageReceiver'
'Tried to construct a SyncRequest without MessageReceiver'
);
}
@ -61,8 +54,6 @@ class SyncRequestInner extends EventTarget {
}
this.started = true;
const { sender } = this;
if (window.ConversationController.areWePrimaryDevice()) {
log.warn('SyncRequest.start: We are primary device; returning early');
return;
@ -73,10 +64,12 @@ class SyncRequestInner extends EventTarget {
);
try {
await Promise.all([
singleProtoJobQueue.add(sender.getRequestConfigurationSyncMessage()),
singleProtoJobQueue.add(sender.getRequestBlockSyncMessage()),
singleProtoJobQueue.add(sender.getRequestContactSyncMessage()),
singleProtoJobQueue.add(sender.getRequestGroupSyncMessage()),
singleProtoJobQueue.add(
MessageSender.getRequestConfigurationSyncMessage()
),
singleProtoJobQueue.add(MessageSender.getRequestBlockSyncMessage()),
singleProtoJobQueue.add(MessageSender.getRequestContactSyncMessage()),
singleProtoJobQueue.add(MessageSender.getRequestGroupSyncMessage()),
]);
} catch (error: unknown) {
log.error(
@ -135,12 +128,8 @@ export default class SyncRequest {
handler: EventHandler
) => void;
constructor(
sender: MessageSender,
receiver: MessageReceiver,
timeoutMillis?: number
) {
const inner = new SyncRequestInner(sender, receiver, timeoutMillis);
constructor(receiver: MessageReceiver, timeoutMillis?: number) {
const inner = new SyncRequestInner(receiver, timeoutMillis);
this.inner = inner;
this.addEventListener = inner.addEventListener.bind(inner);
this.removeEventListener = inner.removeEventListener.bind(inner);

View file

@ -6,6 +6,7 @@ import type { IncomingWebSocketRequest } from './WebsocketResources';
import type { UUID } from '../types/UUID';
import type { TextAttachmentType } from '../types/Attachment';
import { GiftBadgeStates } from '../components/conversation/Message';
import { MIMEType } from '../types/MIME';
export {
IdentityKeyType,
@ -97,9 +98,9 @@ export type ProcessedAttachment = {
cdnId?: string;
cdnKey?: string;
digest?: string;
contentType?: string;
contentType: MIMEType;
key?: string;
size?: number;
size: number;
fileName?: string;
flags?: number;
width?: number;

View file

@ -52,10 +52,6 @@ import { calculateAgreement, generateKeyPair } from '../Curve';
import * as linkPreviewFetch from '../linkPreviews/linkPreviewFetch';
import { isBadgeImageFileUrlValid } from '../badges/isBadgeImageFileUrlValid';
import type {
StorageServiceCallOptionsType,
StorageServiceCredentials,
} from '../textsecure.d';
import { SocketManager } from './SocketManager';
import type { CDSResponseType } from './CDSSocketManager';
import { CDSSocketManager } from './CDSSocketManager';
@ -64,7 +60,12 @@ import { SignalService as Proto } from '../protobuf';
import { HTTPError } from './Errors';
import type MessageSender from './SendMessage';
import type { WebAPICredentials, IRequestHandler } from './Types.d';
import type {
WebAPICredentials,
IRequestHandler,
StorageServiceCallOptionsType,
StorageServiceCredentials,
} from './Types.d';
import { handleStatusCode, translateError } from './Utils';
import * as log from '../logging/log';
import { maybeParseUrl } from '../util/url';
@ -601,16 +602,16 @@ type InitializeOptionsType = {
directoryUrl?: string;
directoryEnclaveId?: string;
directoryTrustAnchor?: string;
directoryV2Url: string;
directoryV2PublicKey: string;
directoryV2CodeHashes: ReadonlyArray<string>;
directoryV2Url?: string;
directoryV2PublicKey?: string;
directoryV2CodeHashes?: ReadonlyArray<string>;
cdnUrlObject: {
readonly '0': string;
readonly [propName: string]: string;
};
certificateAuthority: string;
contentProxyUrl: string;
proxyUrl: string;
proxyUrl: string | undefined;
version: string;
};
@ -1018,6 +1019,13 @@ export type ProxiedRequestOptionsType = {
end?: number;
};
export type TopLevelType = {
multiRecipient200ResponseSchema: typeof multiRecipient200ResponseSchema;
multiRecipient409ResponseSchema: typeof multiRecipient409ResponseSchema;
multiRecipient410ResponseSchema: typeof multiRecipient410ResponseSchema;
initialize: (options: InitializeOptionsType) => WebAPIConnectType;
};
// We first set up the data that won't change during this session of the app
export function initialize({
url,
@ -1138,8 +1146,15 @@ export function initialize({
socketManager.authenticate({ username, password });
}
const cdsUrl = directoryV2Url || directoryUrl;
if (!cdsUrl) {
throw new Error('No CDS url available!');
}
if (!directoryV2PublicKey || !directoryV2CodeHashes?.length) {
throw new Error('No CDS public key or code hashes available');
}
const cdsSocketManager = new CDSSocketManager({
url: directoryV2Url,
url: cdsUrl,
publicKey: directoryV2PublicKey,
codeHashes: directoryV2CodeHashes,
certificateAuthority,

View file

@ -12,7 +12,25 @@ import { Storage } from './Storage';
import * as WebAPI from './WebAPI';
import WebSocketResource from './WebsocketResources';
export const textsecure = {
export type TextSecureType = {
utils: typeof utils;
storage: Storage;
AccountManager: typeof AccountManager;
ContactBuffer: typeof ContactBuffer;
EventTarget: typeof EventTarget;
GroupBuffer: typeof GroupBuffer;
MessageReceiver: typeof MessageReceiver;
MessageSender: typeof MessageSender;
SyncRequest: typeof SyncRequest;
WebAPI: typeof WebAPI;
WebSocketResource: typeof WebSocketResource;
server?: WebAPI.WebAPIType;
messaging?: MessageSender;
};
export const textsecure: TextSecureType = {
utils,
storage: new Storage(),
@ -26,5 +44,3 @@ export const textsecure = {
WebAPI,
WebSocketResource,
};
export default textsecure;

View file

@ -26,6 +26,7 @@ import type {
} from './Types.d';
import { WarnOnlyError } from './Errors';
import { GiftBadgeStates } from '../components/conversation/Message';
import { APPLICATION_OCTET_STREAM, stringToMIMEType } from '../types/MIME';
const FLAGS = Proto.DataMessage.Flags;
export const ATTACHMENT_MAX = 32;
@ -47,12 +48,21 @@ export function processAttachment(
const { cdnId } = attachment;
const hasCdnId = Long.isLong(cdnId) ? !cdnId.isZero() : Boolean(cdnId);
const { contentType, digest, key, size } = attachment;
if (!size) {
throw new Error('Missing size on incoming attachment!');
}
return {
...shallowDropNull(attachment),
cdnId: hasCdnId ? String(cdnId) : undefined,
key: attachment.key ? Bytes.toBase64(attachment.key) : undefined,
digest: attachment.digest ? Bytes.toBase64(attachment.digest) : undefined,
contentType: contentType
? stringToMIMEType(contentType)
: APPLICATION_OCTET_STREAM,
digest: digest ? Bytes.toBase64(digest) : undefined,
key: key ? Bytes.toBase64(key) : undefined,
size,
};
}