From 6a91d44e08acf10a4d55867842171dc8768f50ca Mon Sep 17 00:00:00 2001 From: Audric Ackermann Date: Tue, 30 Jun 2020 16:58:28 +1000 Subject: [PATCH] pass the db id to our messagesender message and clean a few files --- js/models/conversations.js | 19 ++++-- js/models/messages.js | 103 ++++-------------------------- js/views/inbox_view.js | 3 +- libtextsecure/errors.js | 20 ------ libtextsecure/outgoing_message.js | 16 +---- 5 files changed, 30 insertions(+), 131 deletions(-) diff --git a/js/models/conversations.js b/js/models/conversations.js index ea432f57a..8e39c9b98 100644 --- a/js/models/conversations.js +++ b/js/models/conversations.js @@ -1267,6 +1267,7 @@ Message: Whisper.Message, }); message.set({ id }); + message.markPendingSend(); this.set({ lastMessage: model.getNotificationText(), @@ -1307,6 +1308,7 @@ // FIXME audric add back profileKey const lokiProfile = this.getOurProfile(); const chatMessage = new libsession.Messages.Outgoing.ChatMessage({ + identifier: id, body: messageBody, timestamp: Date.now(), attachments: finalAttachments, @@ -1322,10 +1324,7 @@ await message.markMessageSyncOnly(); // sending is done in the 'private' case below } - const options = {}; - options.messageType = message.get('type'); - options.isPublic = this.isPublic(); if (this.isPublic()) { // FIXME audric add back attachments, quote, preview const openGroup = { @@ -1334,6 +1333,7 @@ conversationId: this.id, }; const openGroupParams = { + identifier: id, body, timestamp: Date.now(), group: openGroup, @@ -1346,7 +1346,6 @@ return null; } - options.sessionRestoration = sessionRestoration; const destinationPubkey = new libsession.Types.PubKey(destination); // Handle Group Invitation Message if (groupInvitation) { @@ -1358,6 +1357,8 @@ const groupInvitMessage = new libsession.Messages.Outgoing.GroupInvitationMessage( { + identifier: id, + timestamp: Date.now(), serverName: groupInvitation.name, channelId: groupInvitation.channelId, serverAddress: groupInvitation.address, @@ -1379,6 +1380,8 @@ if (this.isMediumGroup()) { const mediumGroupChatMessage = new libsession.Messages.Outgoing.MediumGroupChatMessage( { + identifier: id, + timestamp: chatMessage.timestamp, chatMessage, groupId: destination, } @@ -1395,7 +1398,9 @@ } else { const closedGroupChatMessage = new libsession.Messages.Outgoing.ClosedGroupChatMessage( { + identifier: id, chatMessage, + timestamp: chatMessage.timestamp, groupId: destination, } ); @@ -1642,6 +1647,7 @@ } const expireUpdate = { + identifier: id, timestamp: message.get('sent_at'), expireTimer, profileKey, @@ -1822,6 +1828,7 @@ const createParams = { timestamp: Date.now(), groupId: id, + identifier: messageId, groupSecretKey: secretKey, members: members.map(pkHex => StringView.hexToArrayBuffer(pkHex)), groupName: name, @@ -1833,7 +1840,7 @@ const mediumGroupCreateMessage = new libsession.Messages.Outgoing.MediumGroupCreateMessage( createParams ); - message.trigger('pending'); + message.markPendingSend(); members.forEach(member => { const memberPubKey = new libsession.Types.PubKey(member); @@ -1847,6 +1854,7 @@ const updateParams = { timestamp: Date.now(), + identifier: messageId, groupId: this.id, name: this.get('name'), avatar: this.get('avatar'), @@ -1922,6 +1930,7 @@ const quitGroup = { timestamp: Date.now(), groupId: this.id, + identifier: id, }; const quitGroupMessage = new libsession.Messages.Outgoing.ClosedGroupLeaveMessage( quitGroup diff --git a/js/models/messages.js b/js/models/messages.js index 36787bd7f..01d7bc8cc 100644 --- a/js/models/messages.js +++ b/js/models/messages.js @@ -991,6 +991,10 @@ }); }, + markPendingSend() { + this.trigger('pending'); // I don't this does anything + }, + // One caller today: event handler for the 'Retry Send' entry in triple-dot menu async retrySend() { if (!textsecure.messaging) { @@ -1039,12 +1043,13 @@ // const previewWithData = await loadPreviewData(this.get('preview')); const chatMessage = new libsession.Messages.Outgoing.ChatMessage({ body, + identifier: this.id, timestamp: this.get('sent_at'), expireTimer: this.get('expireTimer'), }); // Special-case the self-send case - we send only a sync message if (recipients.length === 1 && recipients[0] === this.OUR_NUMBER) { - this.trigger('pending'); + this.markPendingSend(); // FIXME audric add back profileKey await this.markMessageSyncOnly(); // sending is done in the private case below @@ -1053,19 +1058,20 @@ if (conversation.isPrivate()) { const [number] = recipients; const recipientPubKey = new libsession.Types.PubKey(number); - this.trigger('pending'); + this.markPendingSend(); return libsession .getMessageQueue() .sendUsingMultiDevice(recipientPubKey, chatMessage); } - this.trigger('pending'); + this.markPendingSend(); // TODO should we handle open groups message here too? and mediumgroups // Not sure there is the concept of retrySend for those const closedGroupChatMessage = new libsession.Messages.Outgoing.ClosedGroupChatMessage( { chatMessage, + identifier: this.id, groupId: this.get('conversationId'), } ); @@ -1126,7 +1132,7 @@ // Special-case the self-send case - we send only a sync message if (number === this.OUR_NUMBER) { - this.trigger('pending'); + this.markPendingSend(); await this.markMessageSyncOnly(); // sending is done in the private case below } @@ -1134,7 +1140,7 @@ const recipientPubKey = new libsession.Types.PubKey(number); if (conversation.isPrivate()) { - this.trigger('pending'); + this.markPendingSend(); return libsession .getMessageQueue() .sendUsingMultiDevice(recipientPubKey, chatMessage); @@ -1147,7 +1153,7 @@ } ); // resend tries to send the message to that specific user only in the context of a closed group - this.trigger('pending'); + this.markPendingSend(); return libsession .getMessageQueue() .sendUsingMultiDevice(recipientPubKey, closedGroupChatMessage); @@ -1286,92 +1292,7 @@ Message: Whisper.Message, }); }, - send(promise) { - this.trigger('pending'); - return promise - .then(async result => { - this.trigger('done'); - - // This is used by sendSyncMessage, then set to null - if (!this.get('synced') && result.dataMessage) { - this.set({ dataMessage: result.dataMessage }); - } - - const sentTo = this.get('sent_to') || []; - this.set({ - sent_to: _.union(sentTo, result.successfulNumbers), - sent: true, - expirationStartTimestamp: Date.now(), - unidentifiedDeliveries: result.unidentifiedDeliveries, - }); - - await window.Signal.Data.saveMessage(this.attributes, { - Message: Whisper.Message, - }); - - this.trigger('sent', this); - }) - .catch(result => { - this.trigger('done'); - if (result.dataMessage) { - this.set({ dataMessage: result.dataMessage }); - } - - let promises = []; - - if (result instanceof Error) { - this.saveErrors(result); - if (result.name === 'SignedPreKeyRotationError') { - promises.push(getAccountManager().rotateSignedPreKey()); - } else if (result.name === 'OutgoingIdentityKeyError') { - const c = ConversationController.get(result.number); - promises.push(c.getProfiles()); - } - } else { - if (result.successfulNumbers.length > 0) { - const sentTo = this.get('sent_to') || []; - - // In groups, we don't treat unregistered users as a user-visible - // error. The message will look successful, but the details - // screen will show that we didn't send to these unregistered users. - const filteredErrors = _.reject( - result.errors, - error => error.name === 'UnregisteredUserError' - ); - - // We don't start the expiration timer if there are real errors - // left after filtering out all of the unregistered user errors. - const expirationStartTimestamp = filteredErrors.length - ? null - : Date.now(); - - this.saveErrors(filteredErrors); - - this.set({ - sent_to: _.union(sentTo, result.successfulNumbers), - sent: true, - expirationStartTimestamp, - unidentifiedDeliveries: result.unidentifiedDeliveries, - }); - } else { - this.saveErrors(result.errors); - } - promises = promises.concat( - _.map(result.errors, error => { - if (error.name === 'OutgoingIdentityKeyError') { - const c = ConversationController.get(error.number); - promises.push(c.getProfiles()); - } - }) - ); - } - - this.trigger('send-error', this.get('errors')); - - return Promise.all(promises); - }); - }, someRecipientsFailed() { const c = this.getConversation(); diff --git a/js/views/inbox_view.js b/js/views/inbox_view.js index d57b6a824..df4be9b87 100644 --- a/js/views/inbox_view.js +++ b/js/views/inbox_view.js @@ -9,7 +9,8 @@ i18n, Whisper, textsecure, - Signal + Signal, + _ */ // eslint-disable-next-line func-names diff --git a/libtextsecure/errors.js b/libtextsecure/errors.js index 70ec36d5b..fca487f0a 100644 --- a/libtextsecure/errors.js +++ b/libtextsecure/errors.js @@ -108,25 +108,6 @@ } inherit(ReplayableError, MessageError); - function UnregisteredUserError(number, httpError) { - this.message = httpError.message; - this.name = 'UnregisteredUserError'; - - Error.call(this, this.message); - - // Maintains proper stack trace, where our error was thrown (only available on V8) - // via https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Error - if (Error.captureStackTrace) { - Error.captureStackTrace(this); - } - - this.number = number; - this.code = httpError.code; - - appendStack(this, httpError); - } - inherit(Error, UnregisteredUserError); - function EmptySwarmError(number, message) { // eslint-disable-next-line prefer-destructuring this.number = number.split('.')[0]; @@ -276,7 +257,6 @@ } } - window.textsecure.UnregisteredUserError = UnregisteredUserError; window.textsecure.SendMessageNetworkError = SendMessageNetworkError; window.textsecure.IncomingIdentityKeyError = IncomingIdentityKeyError; window.textsecure.OutgoingIdentityKeyError = OutgoingIdentityKeyError; diff --git a/libtextsecure/outgoing_message.js b/libtextsecure/outgoing_message.js index 68e2466b0..685e2e0c2 100644 --- a/libtextsecure/outgoing_message.js +++ b/libtextsecure/outgoing_message.js @@ -281,14 +281,7 @@ OutgoingMessage.prototype = { }).then(results => results.every(value => value === true)); }) .catch(e => { - if (e.name === 'HTTPError' && e.code === 404) { - if (device !== 1) { - return this.removeDeviceIdsForNumber(number, [device]); - } - throw new textsecure.UnregisteredUserError(number, e); - } else { - throw e; - } + throw e; }) ); }); @@ -312,12 +305,7 @@ OutgoingMessage.prototype = { await lokiMessageAPI.sendMessage(pubKey, data, timestamp, ttl, options); } catch (e) { if (e.name === 'HTTPError' && e.code !== 409 && e.code !== 410) { - // 409 and 410 should bubble and be handled by doSendMessage - // 404 should throw UnregisteredUserError - // all other network errors can be retried later. - if (e.code === 404) { - throw new textsecure.UnregisteredUserError(number, e); - } + throw new textsecure.SendMessageNetworkError(number, '', e, timestamp); } else if (e.name === 'TimedOutError') { throw new textsecure.PoWError(number, e);