From 75b7788fa96dc10de4e9ecb5dc9bf5324e7ba9fd Mon Sep 17 00:00:00 2001 From: Audric Ackermann Date: Fri, 15 Jan 2021 10:56:49 +1100 Subject: [PATCH] remove stuff related to web api --- Gruntfile.js | 3 - js/background.js | 80 +--- js/models/conversations.js | 13 +- js/modules/web_api.js | 356 ---------------- libloki/api.js | 127 ------ libloki/test/index.html | 1 - libtextsecure/account_manager.js | 10 +- libtextsecure/index.d.ts | 2 +- libtextsecure/message_receiver.js | 40 +- libtextsecure/sendmessage.js | 388 ------------------ libtextsecure/storage/user.js | 12 - libtextsecure/sync_request.js | 88 ---- libtextsecure/test/fake_web_api.js | 13 - libtextsecure/test/helpers_test.js | 29 -- libtextsecure/test/index.html | 3 - libtextsecure/test/message_receiver_test.js | 104 ----- libtextsecure/test/websocket_test.js | 66 --- preload.js | 6 - test/fixtures_test.js | 1 - test/index.html | 1 - test/models/conversations_test.js | 2 +- .../session/LeftPaneMessageSection.tsx | 5 +- ts/receiver/closedGroupsV2.ts | 4 - ts/receiver/multidevice.ts | 6 - ts/receiver/syncMessages.ts | 3 - ts/session/groupv2/index.ts | 9 - .../content/sync/RequestSyncMessage.ts | 36 -- .../content/sync/VerifiedSyncMessage.ts | 37 -- .../messages/outgoing/content/sync/index.ts | 2 - ts/session/utils/SyncMessage.ts | 219 ++++++++-- ts/util/lint/exceptions.json | 24 -- ts/window.d.ts | 3 - 32 files changed, 217 insertions(+), 1476 deletions(-) delete mode 100644 js/modules/web_api.js delete mode 100644 libloki/api.js delete mode 100644 libtextsecure/sendmessage.js delete mode 100644 libtextsecure/sync_request.js delete mode 100644 libtextsecure/test/fake_web_api.js delete mode 100644 libtextsecure/test/helpers_test.js delete mode 100644 libtextsecure/test/message_receiver_test.js delete mode 100644 libtextsecure/test/websocket_test.js delete mode 100644 ts/session/messages/outgoing/content/sync/RequestSyncMessage.ts delete mode 100644 ts/session/messages/outgoing/content/sync/VerifiedSyncMessage.ts diff --git a/Gruntfile.js b/Gruntfile.js index 8248a61b0..a9cdc8b1e 100644 --- a/Gruntfile.js +++ b/Gruntfile.js @@ -90,8 +90,6 @@ module.exports = grunt => { 'libtextsecure/websocket-resources.js', 'libtextsecure/http-resources.js', 'libtextsecure/message_receiver.js', - 'libtextsecure/sendmessage.js', - 'libtextsecure/sync_request.js', 'libtextsecure/contacts_parser.js', 'libtextsecure/ProvisioningCipher.js', 'libtextsecure/task_with_timeout.js', @@ -100,7 +98,6 @@ module.exports = grunt => { }, libloki: { src: [ - 'libloki/api.js', 'libloki/crypto.js', 'libloki/service_nodes.js', 'libloki/storage.js', diff --git a/js/background.js b/js/background.js index 409f81787..90d628613 100644 --- a/js/background.js +++ b/js/background.js @@ -113,12 +113,6 @@ textsecure.startWorker('js/libsignal-protocol-worker.js'); Whisper.KeyChangeListener.init(textsecure.storage.protocol); let messageReceiver; - window.getSocketStatus = () => { - if (messageReceiver) { - return messageReceiver.getStatus(); - } - return -1; - }; Whisper.events = _.clone(Backbone.Events); Whisper.events.isListenedTo = eventName => Whisper.events._events ? !!Whisper.events._events[eventName] : false; @@ -1038,9 +1032,6 @@ }); } - window.getSyncRequest = () => - new textsecure.SyncRequest(textsecure.messaging, messageReceiver); - let disconnectTimer = null; function onOffline() { window.log.info('offline'); @@ -1060,7 +1051,7 @@ window.removeEventListener('online', onOnline); window.addEventListener('offline', onOffline); - if (disconnectTimer && isSocketOnline()) { + if (disconnectTimer) { window.log.warn('Already online. Had a blip in online/offline status.'); clearTimeout(disconnectTimer); disconnectTimer = null; @@ -1074,13 +1065,6 @@ connect(); } - function isSocketOnline() { - const socketStatus = window.getSocketStatus(); - return ( - socketStatus === WebSocket.CONNECTING || socketStatus === WebSocket.OPEN - ); - } - async function disconnect() { window.log.info('disconnect'); @@ -1124,14 +1108,8 @@ if (messageReceiver) { await messageReceiver.close(); } - const mySignalingKey = storage.get('signaling_key'); connectCount += 1; - const options = { - retryCached: connectCount === 1, - serverTrustRoot: window.getServerTrustRoot(), - }; - Whisper.Notifications.disable(); // avoid notification flood until empty setTimeout(() => { Whisper.Notifications.enable(); @@ -1152,18 +1130,18 @@ ); window.lokiPublicChatAPI = null; window.feeds = []; - messageReceiver = new textsecure.MessageReceiver(mySignalingKey, options); + messageReceiver = new textsecure.MessageReceiver(); messageReceiver.addEventListener( 'message', window.DataMessageReceiver.handleMessageEvent ); - window.textsecure.messaging = new textsecure.MessageSender(); + window.textsecure.messaging = true; return; } initAPIs(); await initSpecialConversations(); - messageReceiver = new textsecure.MessageReceiver(mySignalingKey, options); + messageReceiver = new textsecure.MessageReceiver(); messageReceiver.addEventListener( 'message', window.DataMessageReceiver.handleMessageEvent @@ -1180,55 +1158,7 @@ logger: window.log, }); - window.textsecure.messaging = new textsecure.MessageSender(); - - // On startup after upgrading to a new version, request a contact sync - // (but only if we're not the primary device) - if ( - !firstRun && - connectCount === 1 && - newVersion && - // eslint-disable-next-line eqeqeq - textsecure.storage.user.getDeviceId() != '1' - ) { - window.getSyncRequest(); - } - - const deviceId = textsecure.storage.user.getDeviceId(); - if (firstRun === true && deviceId !== '1') { - const hasThemeSetting = Boolean(storage.get('theme-setting')); - if (!hasThemeSetting && textsecure.storage.get('userAgent') === 'OWI') { - storage.put('theme-setting', 'ios'); - } - const syncRequest = new textsecure.SyncRequest( - textsecure.messaging, - messageReceiver - ); - Whisper.events.trigger('contactsync:begin'); - syncRequest.addEventListener('success', () => { - window.log.info('sync successful'); - storage.put('synced_at', Date.now()); - Whisper.events.trigger('contactsync'); - }); - syncRequest.addEventListener('timeout', () => { - window.log.error('sync timed out'); - Whisper.events.trigger('contactsync'); - }); - - if (Whisper.Import.isComplete()) { - const { CONFIGURATION } = textsecure.protobuf.SyncMessage.Request.Type; - const { RequestSyncMessage } = window.libsession.Messages.Outgoing; - - const requestConfigurationSyncMessage = new RequestSyncMessage({ - timestamp: Date.now(), - reqestType: CONFIGURATION, - }); - await libsession - .getMessageQueue() - .sendSyncMessage(requestConfigurationSyncMessage); - // sending of the message is handled in the 'private' case below - } - } + window.textsecure.messaging = true; libsession.Protocols.SessionProtocol.checkSessionRequestExpiry().catch( e => { diff --git a/js/models/conversations.js b/js/models/conversations.js index 03861a967..506930975 100644 --- a/js/models/conversations.js +++ b/js/models/conversations.js @@ -217,7 +217,7 @@ : BlockedNumberController.blockGroup(this.id); await promise; this.commit(); - await textsecure.messaging.sendBlockedListSyncMessage(); + await libsession.Utils.SyncMessageUtils.sendBlockedListSyncMessage(); }, async unblock() { if (!this.id || this.isPublic() || this.isRss()) { @@ -228,7 +228,7 @@ : BlockedNumberController.unblockGroup(this.id); await promise; this.commit(); - await textsecure.messaging.sendBlockedListSyncMessage(); + await libsession.Utils.SyncMessageUtils.sendBlockedListSyncMessage(); }, async bumpTyping() { if (this.isPublic() || this.isMediumGroup()) { @@ -612,13 +612,6 @@ local: !options.viaSyncMessage, }); } - if (!options.viaSyncMessage) { - await this.sendVerifySyncMessage(this.id, verified); - } - }, - async sendVerifySyncMessage(number, state) { - const key = await textsecure.storage.protocol.loadIdentityKey(number); - return textsecure.messaging.syncVerification(number, state, key); }, isVerified() { if (this.isPrivate()) { @@ -1690,7 +1683,7 @@ window.log.info(`Sending ${read.length} read receipts`); // Because syncReadMessages sends to our other devices, and sendReadReceipts goes // to a contact, we need accessKeys for both. - await textsecure.messaging.syncReadMessages(read); + await libsession.Utils.SyncMessageUtils.syncReadMessages(read); if (storage.get('read-receipt-setting')) { await Promise.all( diff --git a/js/modules/web_api.js b/js/modules/web_api.js deleted file mode 100644 index efe82f9ad..000000000 --- a/js/modules/web_api.js +++ /dev/null @@ -1,356 +0,0 @@ -const fetch = require('node-fetch'); -const { Agent } = require('https'); - -/* global Buffer, setTimeout, log, _ */ - -/* eslint-disable more/no-then, no-bitwise, no-nested-ternary */ - -function _btoa(str) { - let buffer; - - if (str instanceof Buffer) { - buffer = str; - } else { - buffer = Buffer.from(str.toString(), 'binary'); - } - - return buffer.toString('base64'); -} - -const _call = object => Object.prototype.toString.call(object); - -const ArrayBufferToString = _call(new ArrayBuffer()); -const Uint8ArrayToString = _call(new Uint8Array()); - -function _getString(thing) { - if (typeof thing !== 'string') { - if (_call(thing) === Uint8ArrayToString) { - return String.fromCharCode.apply(null, thing); - } - if (_call(thing) === ArrayBufferToString) { - return _getString(new Uint8Array(thing)); - } - } - return thing; -} - -function _validateResponse(response, schema) { - try { - // eslint-disable-next-line guard-for-in, no-restricted-syntax - for (const i in schema) { - switch (schema[i]) { - case 'object': - case 'string': - case 'number': - // eslint-disable-next-line valid-typeof - if (typeof response[i] !== schema[i]) { - return false; - } - break; - default: - } - } - } catch (ex) { - return false; - } - return true; -} - -const FIVE_MINUTES = 1000 * 60 * 5; -const agents = { - unauth: null, - auth: null, -}; - -function getContentType(response) { - if (response.headers && response.headers.get) { - return response.headers.get('content-type'); - } - - return null; -} - -function _promiseAjax(providedUrl, options) { - return new Promise((resolve, reject) => { - const url = providedUrl || `${options.host}/${options.path}`; - if (options.disableLogs) { - log.info( - `${options.type} [REDACTED_URL]${ - options.unauthenticated ? ' (unauth)' : '' - }` - ); - } else { - log.info( - `${options.type} ${url}${options.unauthenticated ? ' (unauth)' : ''}` - ); - } - - const timeout = - typeof options.timeout !== 'undefined' ? options.timeout : 10000; - - const { proxyUrl } = options; - const agentType = options.unauthenticated ? 'unauth' : 'auth'; - const cacheKey = `${proxyUrl}-${agentType}`; - - const { timestamp } = agents[cacheKey] || {}; - if (!timestamp || timestamp + FIVE_MINUTES < Date.now()) { - if (timestamp) { - log.info(`Cycling agent for type ${cacheKey}`); - } - agents[cacheKey] = { - agent: new Agent({ keepAlive: true }), - timestamp: Date.now(), - }; - } - const { agent } = agents[cacheKey]; - - const fetchOptions = { - method: options.type, - body: options.data || null, - headers: { - 'User-Agent': 'Session', - 'X-Loki-Messenger-Agent': 'OWD', - ...options.headers, - }, - redirect: options.redirect, - agent, - ca: options.certificateAuthority, - timeout, - }; - - if (fetchOptions.body instanceof ArrayBuffer) { - // node-fetch doesn't support ArrayBuffer, only node Buffer - const contentLength = fetchOptions.body.byteLength; - fetchOptions.body = Buffer.from(fetchOptions.body); - - // node-fetch doesn't set content-length like S3 requires - fetchOptions.headers['Content-Length'] = contentLength; - } - - const { accessKey, unauthenticated } = options; - if (unauthenticated) { - if (!accessKey) { - throw new Error( - '_promiseAjax: mode is aunathenticated, but accessKey was not provided' - ); - } - // Access key is already a Base64 string - fetchOptions.headers['Unidentified-Access-Key'] = accessKey; - } else if (options.user && options.password) { - const user = _getString(options.user); - const password = _getString(options.password); - const auth = _btoa(`${user}:${password}`); - fetchOptions.headers.Authorization = `Basic ${auth}`; - } - - if (options.contentType) { - fetchOptions.headers['Content-Type'] = options.contentType; - } - - fetch(url, fetchOptions) - .then(response => { - let resultPromise; - if ( - options.responseType === 'json' && - response.headers.get('Content-Type') === 'application/json' - ) { - resultPromise = response.json(); - } else if ( - options.responseType === 'arraybuffer' || - options.responseType === 'arraybufferwithdetails' - ) { - resultPromise = response.buffer(); - } else { - resultPromise = response.text(); - } - - return resultPromise.then(result => { - if ( - options.responseType === 'arraybuffer' || - options.responseType === 'arraybufferwithdetails' - ) { - // eslint-disable-next-line no-param-reassign - result = result.buffer.slice( - result.byteOffset, - result.byteOffset + result.byteLength - ); - } - if (options.responseType === 'json') { - if (options.validateResponse) { - if (!_validateResponse(result, options.validateResponse)) { - if (options.disableLogs) { - log.info( - options.type, - '[REDACTED_URL]', - response.status, - 'Error' - ); - } else { - log.error(options.type, url, response.status, 'Error'); - } - return reject( - HTTPError( - 'promiseAjax: invalid response', - response.status, - result, - options.stack - ) - ); - } - } - } - if (response.status >= 0 && response.status < 400) { - if (options.disableLogs) { - log.info( - options.type, - '[REDACTED_URL]', - response.status, - 'Success' - ); - } else { - log.info(options.type, url, response.status, 'Success'); - } - if (options.responseType === 'arraybufferwithdetails') { - return resolve({ - data: result, - contentType: getContentType(response), - response, - }); - } - return resolve(result, response.status); - } - - if (options.disableLogs) { - log.info(options.type, '[REDACTED_URL]', response.status, 'Error'); - } else { - log.error(options.type, url, response.status, 'Error'); - } - return reject( - HTTPError( - 'promiseAjax: error response', - response.status, - result, - options.stack - ) - ); - }); - }) - .catch(e => { - if (options.disableLogs) { - log.error(options.type, '[REDACTED_URL]', 0, 'Error'); - } else { - log.error(options.type, url, 0, 'Error'); - } - const stack = `${e.stack}\nInitial stack:\n${options.stack}`; - reject(HTTPError('promiseAjax catch', 0, e.toString(), stack)); - }); - }); -} - -function _retryAjax(url, options, providedLimit, providedCount) { - const count = (providedCount || 0) + 1; - const limit = providedLimit || 3; - return _promiseAjax(url, options).catch(e => { - if (e.name === 'HTTPError' && e.code === -1 && count < limit) { - return new Promise(resolve => { - setTimeout(() => { - resolve(_retryAjax(url, options, limit, count)); - }, 1000); - }); - } - throw e; - }); -} - -function _outerAjax(url, options) { - // eslint-disable-next-line no-param-reassign - options.stack = new Error().stack; // just in case, save stack here. - return _retryAjax(url, options); -} - -function HTTPError(message, providedCode, response, stack) { - const code = providedCode > 999 || providedCode < 100 ? -1 : providedCode; - const e = new Error(`${message}; code: ${code}`); - e.name = 'HTTPError'; - e.code = code; - e.stack += `\nOriginal stack:\n${stack}`; - if (response) { - e.response = response; - } - return e; -} - -module.exports = { - initialize, -}; - -// We first set up the data that won't change during this session of the app -function initialize() { - // Thanks to function-hoisting, we can put this return statement before all of the - // below function definitions. - return { - connect, - }; - - // Then we connect to the server with user-specific information. This is the only API - // exposed to the browser context, ensuring that it can't connect to arbitrary - // locations. - function connect() { - // Thanks, function hoisting! - return { - getAttachment, - getProxiedSize, - makeProxiedRequest, - }; - - function getAttachment(fileUrl) { - return _outerAjax(fileUrl, { - contentType: 'application/octet-stream', - responseType: 'arraybuffer', - timeout: 0, - type: 'GET', - }); - } - - // eslint-disable-next-line no-shadow - async function getProxiedSize(url) { - const result = await _outerAjax(url, { - processData: false, - responseType: 'arraybufferwithdetails', - proxyUrl: '', - type: 'HEAD', - disableLogs: true, - }); - - const { response } = result; - if (!response.headers || !response.headers.get) { - throw new Error('getProxiedSize: Problem retrieving header value'); - } - - const size = response.headers.get('content-length'); - return parseInt(size, 10); - } - - // eslint-disable-next-line no-shadow - function makeProxiedRequest(url, options = {}) { - const { returnArrayBuffer, start, end } = options; - let headers; - - if (_.isNumber(start) && _.isNumber(end)) { - headers = { - Range: `bytes=${start}-${end}`, - }; - } - - return _outerAjax(url, { - processData: false, - responseType: returnArrayBuffer ? 'arraybufferwithdetails' : null, - proxyUrl: '', - type: 'GET', - redirect: 'follow', - disableLogs: true, - headers, - }); - } - } -} diff --git a/libloki/api.js b/libloki/api.js deleted file mode 100644 index 3f669a57f..000000000 --- a/libloki/api.js +++ /dev/null @@ -1,127 +0,0 @@ -/* global window, textsecure, libsession */ -/* eslint-disable no-bitwise */ - -// eslint-disable-next-line func-names -(function() { - window.libloki = window.libloki || {}; - - const DebugFlagsEnum = { - GROUP_SYNC_MESSAGES: 1, - CONTACT_SYNC_MESSAGES: 2, - FALLBACK_MESSAGES: 8, - SESSION_BACKGROUND_MESSAGE: 32, - GROUP_REQUEST_INFO: 64, - // If you add any new flag, be sure it is bitwise safe! (unique and 2 multiples) - ALL: 65535, - }; - - const debugFlags = DebugFlagsEnum.ALL; - - const debugLogFn = (...args) => { - if (window.lokiFeatureFlags.debugMessageLogs) { - window.log.warn(...args); - } - }; - - function logGroupSync(...args) { - if (debugFlags & DebugFlagsEnum.GROUP_SYNC_MESSAGES) { - debugLogFn(...args); - } - } - - function logGroupRequestInfo(...args) { - if (debugFlags & DebugFlagsEnum.GROUP_REQUEST_INFO) { - debugLogFn(...args); - } - } - - function logContactSync(...args) { - if (debugFlags & DebugFlagsEnum.CONTACT_SYNC_MESSAGES) { - debugLogFn(...args); - } - } - - function logBackgroundMessage(...args) { - if (debugFlags & DebugFlagsEnum.SESSION_BACKGROUND_MESSAGE) { - debugLogFn(...args); - } - } - - async function createContactSyncMessage(sessionContacts) { - if (sessionContacts.length === 0) { - return null; - } - - const rawContacts = await Promise.all( - sessionContacts.map(async conversation => { - const profile = conversation.getLokiProfile(); - const name = profile - ? profile.displayName - : conversation.getProfileName(); - const status = await conversation.safeGetVerified(); - - return { - name, - number: conversation.getNumber(), - nickname: conversation.getNickname(), - blocked: conversation.isBlocked(), - expireTimer: conversation.get('expireTimer'), - verifiedStatus: status, - }; - }) - ); - - return new libsession.Messages.Outgoing.ContactSyncMessage({ - timestamp: Date.now(), - rawContacts, - }); - } - - function createGroupSyncMessage(sessionGroup) { - // We are getting a single open group here - - const rawGroup = { - id: sessionGroup.id, - name: sessionGroup.get('name'), - members: sessionGroup.get('members') || [], - blocked: sessionGroup.isBlocked(), - expireTimer: sessionGroup.get('expireTimer'), - admins: sessionGroup.get('groupAdmins') || [], - }; - - return new libsession.Messages.Outgoing.ClosedGroupSyncMessage({ - timestamp: Date.now(), - rawGroup, - }); - } - - async function sendSessionRequestsToMembers(members = []) { - // For every member, trigger a session request if needed - members.forEach(async memberStr => { - const ourPubKey = textsecure.storage.user.getNumber(); - if (memberStr !== ourPubKey) { - const memberPubkey = new libsession.Types.PubKey(memberStr); - await window - .getConversationController() - .getOrCreateAndWait(memberStr, 'private'); - await libsession.Protocols.SessionProtocol.sendSessionRequestIfNeeded( - memberPubkey - ); - } - }); - } - - const debug = { - logContactSync, - logGroupSync, - logBackgroundMessage, - logGroupRequestInfo, - }; - - window.libloki.api = { - sendSessionRequestsToMembers, - createContactSyncMessage, - createGroupSyncMessage, - debug, - }; -})(); diff --git a/libloki/test/index.html b/libloki/test/index.html index f18213d6f..ab8dadb36 100644 --- a/libloki/test/index.html +++ b/libloki/test/index.html @@ -24,7 +24,6 @@ - diff --git a/libtextsecure/account_manager.js b/libtextsecure/account_manager.js index 6a18e8c98..9de7471cb 100644 --- a/libtextsecure/account_manager.js +++ b/libtextsecure/account_manager.js @@ -530,9 +530,13 @@ const conversations = window .getConversationController() .getConversations(); - await textsecure.messaging.sendGroupSyncMessage(conversations); - await textsecure.messaging.sendOpenGroupsSyncMessage(conversations); - await textsecure.messaging.sendContactSyncMessage(); + await libsession.Utils.SyncMessageUtils.sendGroupSyncMessage( + conversations + ); + await libsession.Utils.SyncMessageUtils.sendOpenGroupsSyncMessage( + conversations + ); + await libsession.Utils.SyncMessageUtils.sendContactSyncMessage(); }, 5000); }, validatePubKeyHex(pubKey) { diff --git a/libtextsecure/index.d.ts b/libtextsecure/index.d.ts index e1cb5efa4..1f74b7a2e 100644 --- a/libtextsecure/index.d.ts +++ b/libtextsecure/index.d.ts @@ -1,7 +1,7 @@ import { LibTextsecureCryptoInterface } from './crypto'; export interface LibTextsecure { - messaging: any; + messaging: boolean; crypto: LibTextsecureCryptoInterface; storage: any; SendMessageNetworkError: any; diff --git a/libtextsecure/message_receiver.js b/libtextsecure/message_receiver.js index c5e69273c..40615e6d5 100644 --- a/libtextsecure/message_receiver.js +++ b/libtextsecure/message_receiver.js @@ -1,24 +1,17 @@ /* global window: false */ /* global callWorker: false */ /* global textsecure: false */ -/* global WebSocket: false */ /* global Event: false */ /* global dcodeIO: false */ /* global lokiPublicChatAPI: false */ /* global feeds: false */ -/* global WebAPI: false */ /* eslint-disable more/no-then */ /* eslint-disable no-unreachable */ let openGroupBound = false; -function MessageReceiver(username, password, signalingKey) { - this.count = 0; - - this.signalingKey = signalingKey; - this.server = WebAPI.connect(); - +function MessageReceiver() { this.pending = Promise.resolve(); // only do this once to prevent duplicates @@ -58,7 +51,6 @@ MessageReceiver.prototype.extend({ return; } - this.count = 0; if (this.hasConnected) { const ev = new Event('reconnect'); this.dispatchEvent(ev); @@ -94,8 +86,6 @@ MessageReceiver.prototype.extend({ if (lokiPublicChatAPI) { await lokiPublicChatAPI.close(); } - - return this.drain(); }, onopen() { window.log.info('websocket open'); @@ -112,42 +102,18 @@ MessageReceiver.prototype.extend({ this.calledClose ); }, - drain() { - const { incoming } = this; - this.incoming = []; - - // This promise will resolve when there are no more messages to be processed. - return Promise.all(incoming); - }, - getStatus() { - if (this.hasConnected) { - return WebSocket.CLOSED; - } - return -1; - }, }); window.textsecure = window.textsecure || {}; -textsecure.MessageReceiver = function MessageReceiverWrapper( - username, - password, - signalingKey, - options -) { - const messageReceiver = new MessageReceiver( - username, - password, - signalingKey, - options - ); +textsecure.MessageReceiver = function MessageReceiverWrapper() { + const messageReceiver = new MessageReceiver(); this.addEventListener = messageReceiver.addEventListener.bind( messageReceiver ); this.removeEventListener = messageReceiver.removeEventListener.bind( messageReceiver ); - this.getStatus = messageReceiver.getStatus.bind(messageReceiver); this.close = messageReceiver.close.bind(messageReceiver); this.stopProcessing = messageReceiver.stopProcessing.bind(messageReceiver); diff --git a/libtextsecure/sendmessage.js b/libtextsecure/sendmessage.js deleted file mode 100644 index ec7ca550d..000000000 --- a/libtextsecure/sendmessage.js +++ /dev/null @@ -1,388 +0,0 @@ -/* global textsecure, WebAPI, window, libloki, _, libsession */ - -/* eslint-disable more/no-then, no-bitwise */ - -function stringToArrayBuffer(str) { - if (typeof str !== 'string') { - throw new Error('Passed non-string to stringToArrayBuffer'); - } - const res = new ArrayBuffer(str.length); - const uint = new Uint8Array(res); - for (let i = 0; i < str.length; i += 1) { - uint[i] = str.charCodeAt(i); - } - return res; -} - -function Message(options) { - this.body = options.body; - this.attachments = options.attachments || []; - this.quote = options.quote; - this.preview = options.preview; - this.group = options.group; - this.flags = options.flags; - this.recipients = options.recipients; - this.timestamp = options.timestamp; - this.needsSync = options.needsSync; - this.expireTimer = options.expireTimer; - this.profileKey = options.profileKey; - this.profile = options.profile; - this.groupInvitation = options.groupInvitation; - this.sessionRestoration = options.sessionRestoration || false; - - if (!(this.recipients instanceof Array)) { - throw new Error('Invalid recipient list'); - } - - if (!this.group && this.recipients.length !== 1) { - throw new Error('Invalid recipient list for non-group'); - } - - if (typeof this.timestamp !== 'number') { - throw new Error('Invalid timestamp'); - } - - if (this.expireTimer !== undefined && this.expireTimer !== null) { - if (typeof this.expireTimer !== 'number' || !(this.expireTimer >= 0)) { - throw new Error('Invalid expireTimer'); - } - } - - if (this.attachments) { - if (!(this.attachments instanceof Array)) { - throw new Error('Invalid message attachments'); - } - } - if (this.flags !== undefined) { - if (typeof this.flags !== 'number') { - throw new Error('Invalid message flags'); - } - } - if (this.isEndSession()) { - if ( - this.body !== null || - this.group !== null || - this.attachments.length !== 0 - ) { - throw new Error('Invalid end session message'); - } - } else { - if ( - typeof this.timestamp !== 'number' || - (this.body && typeof this.body !== 'string') - ) { - throw new Error('Invalid message body'); - } - if (this.group) { - if ( - typeof this.group.id !== 'string' || - typeof this.group.type !== 'number' - ) { - throw new Error('Invalid group context'); - } - } - } -} - -Message.prototype = { - constructor: Message, - isEndSession() { - return this.flags & textsecure.protobuf.DataMessage.Flags.END_SESSION; - }, - toProto() { - if (this.dataMessage instanceof textsecure.protobuf.DataMessage) { - return this.dataMessage; - } - const proto = new textsecure.protobuf.DataMessage(); - if (this.body) { - proto.body = this.body; - } - proto.attachments = this.attachmentPointers; - if (this.flags) { - proto.flags = this.flags; - } - if (this.group) { - proto.group = new textsecure.protobuf.GroupContext(); - proto.group.id = stringToArrayBuffer(this.group.id); - proto.group.type = this.group.type; - } - if (Array.isArray(this.preview)) { - proto.preview = this.preview.map(preview => { - const item = new textsecure.protobuf.DataMessage.Preview(); - item.title = preview.title; - item.url = preview.url; - item.image = preview.image || null; - return item; - }); - } - if (this.quote) { - const { QuotedAttachment } = textsecure.protobuf.DataMessage.Quote; - const { Quote } = textsecure.protobuf.DataMessage; - - proto.quote = new Quote(); - const { quote } = proto; - - quote.id = this.quote.id; - quote.author = this.quote.author; - quote.text = this.quote.text; - quote.attachments = (this.quote.attachments || []).map(attachment => { - const quotedAttachment = new QuotedAttachment(); - - quotedAttachment.contentType = attachment.contentType; - quotedAttachment.fileName = attachment.fileName; - if (attachment.attachmentPointer) { - quotedAttachment.thumbnail = attachment.attachmentPointer; - } - - return quotedAttachment; - }); - } - if (this.expireTimer) { - proto.expireTimer = this.expireTimer; - } - - if (this.profileKey) { - proto.profileKey = this.profileKey; - } - - // Set the loki profile - if (this.profile) { - const profile = new textsecure.protobuf.DataMessage.LokiProfile(); - if (this.profile.displayName) { - profile.displayName = this.profile.displayName; - } - - const conversation = window - .getConversationController() - .get(textsecure.storage.user.getNumber()); - const avatarPointer = conversation.get('avatarPointer'); - if (avatarPointer) { - profile.avatar = avatarPointer; - } - proto.profile = profile; - } - - if (this.groupInvitation) { - proto.groupInvitation = new textsecure.protobuf.DataMessage.GroupInvitation( - { - serverAddress: this.groupInvitation.serverAddress, - channelId: this.groupInvitation.channelId, - serverName: this.groupInvitation.serverName, - } - ); - } - - if (this.sessionRestoration) { - proto.flags = textsecure.protobuf.DataMessage.Flags.SESSION_RESTORE; - } - - this.dataMessage = proto; - return proto; - }, - toArrayBuffer() { - return this.toProto().toArrayBuffer(); - }, -}; - -function MessageSender() { - // Currently only used for getProxiedSize() and makeProxiedRequest(), which are only used for fetching previews - this.server = WebAPI.connect(); -} - -MessageSender.prototype = { - constructor: MessageSender, - - async sendContactSyncMessage(convos) { - let convosToSync; - if (!convos) { - convosToSync = await libsession.Utils.SyncMessageUtils.getSyncContacts(); - } else { - convosToSync = convos; - } - - if (convosToSync.size === 0) { - window.log.info('No contacts to sync.'); - - return Promise.resolve(); - } - libloki.api.debug.logContactSync( - 'Triggering contact sync message with:', - convosToSync - ); - - // We need to sync across 3 contacts at a time - // This is to avoid hitting storage server limit - const chunked = _.chunk(convosToSync, 3); - const syncMessages = await Promise.all( - chunked.map(c => libloki.api.createContactSyncMessage(c)) - ); - - const syncPromises = syncMessages.map(syncMessage => - libsession.getMessageQueue().sendSyncMessage(syncMessage) - ); - - return Promise.all(syncPromises); - }, - - sendGroupSyncMessage(conversations) { - // If we havn't got a primaryDeviceKey then we are in the middle of pairing - // primaryDevicePubKey is set to our own number if we are the master device - const primaryDeviceKey = window.storage.get('primaryDevicePubKey'); - if (!primaryDeviceKey) { - window.log.debug('sendGroupSyncMessage: no primary device pubkey'); - return Promise.resolve(); - } - // We only want to sync across closed groups that we haven't left - const activeGroups = conversations.filter( - c => c.isClosedGroup() && !c.get('left') && !c.get('isKickedFromGroup') - ); - if (activeGroups.length === 0) { - window.log.info('No closed group to sync.'); - return Promise.resolve(); - } - - const mediumGroups = activeGroups.filter(c => c.isMediumGroup()); - - window.libsession.ClosedGroupV2.syncMediumGroups(mediumGroups); - - const legacyGroups = activeGroups.filter(c => !c.isMediumGroup()); - - // We need to sync across 1 group at a time - // This is because we could hit the storage server limit with one group - const syncPromises = legacyGroups - .map(c => libloki.api.createGroupSyncMessage(c)) - .map(syncMessage => - libsession.getMessageQueue().sendSyncMessage(syncMessage) - ); - - return Promise.all(syncPromises); - }, - - async sendOpenGroupsSyncMessage(convos) { - // If we havn't got a primaryDeviceKey then we are in the middle of pairing - // primaryDevicePubKey is set to our own number if we are the master device - const primaryDeviceKey = window.storage.get('primaryDevicePubKey'); - if (!primaryDeviceKey) { - return Promise.resolve(); - } - const conversations = Array.isArray(convos) ? convos : [convos]; - - const openGroupsConvos = await libsession.Utils.SyncMessageUtils.filterOpenGroupsConvos( - conversations - ); - - if (!openGroupsConvos.length) { - window.log.info('No open groups to sync'); - return Promise.resolve(); - } - - // Send the whole list of open groups in a single message - const openGroupsDetails = openGroupsConvos.map(conversation => ({ - url: conversation.id, - channelId: conversation.get('channelId'), - })); - const openGroupsSyncParams = { - timestamp: Date.now(), - openGroupsDetails, - }; - const openGroupsSyncMessage = new libsession.Messages.Outgoing.OpenGroupSyncMessage( - openGroupsSyncParams - ); - - return libsession.getMessageQueue().sendSyncMessage(openGroupsSyncMessage); - }, - async sendBlockedListSyncMessage() { - // If we havn't got a primaryDeviceKey then we are in the middle of pairing - // primaryDevicePubKey is set to our own number if we are the master device - const primaryDeviceKey = window.storage.get('primaryDevicePubKey'); - if (!primaryDeviceKey) { - return Promise.resolve(); - } - - const currentlyBlockedNumbers = window.BlockedNumberController.getBlockedNumbers(); - - // currently we only sync user blocked, not groups - const blockedSyncMessage = new libsession.Messages.Outgoing.BlockedListSyncMessage( - { - timestamp: Date.now(), - numbers: currentlyBlockedNumbers, - groups: [], - } - ); - return libsession.getMessageQueue().sendSyncMessage(blockedSyncMessage); - }, - syncReadMessages(reads) { - const myDevice = textsecure.storage.user.getDeviceId(); - // FIXME currently not in used - if (myDevice !== 1 && myDevice !== '1') { - const syncReadMessages = new libsession.Messages.Outgoing.SyncReadMessage( - { - timestamp: Date.now(), - readMessages: reads, - } - ); - return libsession.getMessageQueue().sendSyncMessage(syncReadMessages); - } - - return Promise.resolve(); - }, - async syncVerification(destination, state, identityKey) { - const myDevice = textsecure.storage.user.getDeviceId(); - // FIXME currently not in used - if (myDevice === 1 || myDevice === '1') { - return Promise.resolve(); - } - // send a session established message (used as a nullMessage) - const destinationPubKey = new libsession.Types.PubKey(destination); - - const sessionEstablished = new window.libsession.Messages.Outgoing.SessionEstablishedMessage( - { timestamp: Date.now() } - ); - const { padding } = sessionEstablished; - await libsession - .getMessageQueue() - .send(destinationPubKey, sessionEstablished); - - const verifiedSyncParams = { - state, - destination: destinationPubKey, - identityKey, - padding, - timestamp: Date.now(), - }; - const verifiedSyncMessage = new window.libsession.Messages.Outgoing.VerifiedSyncMessage( - verifiedSyncParams - ); - - return libsession.getMessageQueue().sendSyncMessage(verifiedSyncMessage); - }, - - makeProxiedRequest(url, options) { - return this.server.makeProxiedRequest(url, options); - }, - getProxiedSize(url) { - return this.server.getProxiedSize(url); - }, -}; - -window.textsecure = window.textsecure || {}; - -textsecure.MessageSender = function MessageSenderWrapper() { - const sender = new MessageSender(); - this.sendContactSyncMessage = sender.sendContactSyncMessage.bind(sender); - this.sendGroupSyncMessage = sender.sendGroupSyncMessage.bind(sender); - this.sendOpenGroupsSyncMessage = sender.sendOpenGroupsSyncMessage.bind( - sender - ); - this.syncReadMessages = sender.syncReadMessages.bind(sender); - this.syncVerification = sender.syncVerification.bind(sender); - this.makeProxiedRequest = sender.makeProxiedRequest.bind(sender); - this.getProxiedSize = sender.getProxiedSize.bind(sender); - this.sendBlockedListSyncMessage = sender.sendBlockedListSyncMessage.bind( - sender - ); -}; - -textsecure.MessageSender.prototype = { - constructor: textsecure.MessageSender, -}; diff --git a/libtextsecure/storage/user.js b/libtextsecure/storage/user.js index 3e17b80af..64e0cac7d 100644 --- a/libtextsecure/storage/user.js +++ b/libtextsecure/storage/user.js @@ -35,17 +35,5 @@ getDeviceName() { return textsecure.storage.get('device_name'); }, - - setDeviceNameEncrypted() { - return textsecure.storage.put('deviceNameEncrypted', true); - }, - - getDeviceNameEncrypted() { - return textsecure.storage.get('deviceNameEncrypted'); - }, - - getSignalingKey() { - return textsecure.storage.get('signaling_key'); - }, }; })(); diff --git a/libtextsecure/sync_request.js b/libtextsecure/sync_request.js deleted file mode 100644 index 3a5f25ff2..000000000 --- a/libtextsecure/sync_request.js +++ /dev/null @@ -1,88 +0,0 @@ -/* global Event, textsecure, window, libsession */ - -/* eslint-disable more/no-then */ - -// eslint-disable-next-line func-names -(function() { - window.textsecure = window.textsecure || {}; - - async function SyncRequest() { - // this.receiver = receiver; - - window.log.info('SyncRequest created. Sending config sync request...'); - const { CONFIGURATION } = textsecure.protobuf.SyncMessage.Request.Type; - const { RequestSyncMessage } = window.libsession.Messages.Outgoing; - - const requestConfigurationSyncMessage = new RequestSyncMessage({ - timestamp: Date.now(), - reqestType: CONFIGURATION, - }); - - await libsession - .getMessageQueue() - .sendSyncMessage(requestConfigurationSyncMessage); - - window.log.info('SyncRequest now sending contact sync message...'); - const { CONTACTS } = textsecure.protobuf.SyncMessage.Request.Type; - const requestContactSyncMessage = new RequestSyncMessage({ - timestamp: Date.now(), - reqestType: CONTACTS, - }); - await libsession - .getMessageQueue() - .sendSyncMessage(requestContactSyncMessage); - - window.log.info('SyncRequest now sending group sync messsage...'); - const { GROUPS } = textsecure.protobuf.SyncMessage.Request.Type; - const requestGroupSyncMessage = new RequestSyncMessage({ - timestamp: Date.now(), - reqestType: GROUPS, - }); - await libsession.getMessageQueue().sendSyncMessage(requestGroupSyncMessage); - - this.timeout = setTimeout(this.onTimeout.bind(this), 60000); - } - - SyncRequest.prototype = new textsecure.EventTarget(); - SyncRequest.prototype.extend({ - constructor: SyncRequest, - onContactSyncComplete() { - this.contactSync = true; - this.update(); - }, - onGroupSyncComplete() { - this.groupSync = true; - this.update(); - }, - update() { - if (this.contactSync && this.groupSync) { - this.dispatchEvent(new Event('success')); - this.cleanup(); - } - }, - onTimeout() { - if (this.contactSync || this.groupSync) { - this.dispatchEvent(new Event('success')); - } else { - this.dispatchEvent(new Event('timeout')); - } - this.cleanup(); - }, - cleanup() { - clearTimeout(this.timeout); - delete this.listeners; - }, - }); - - textsecure.SyncRequest = function SyncRequestWrapper() { - const syncRequest = new SyncRequest(); - this.addEventListener = syncRequest.addEventListener.bind(syncRequest); - this.removeEventListener = syncRequest.removeEventListener.bind( - syncRequest - ); - }; - - textsecure.SyncRequest.prototype = { - constructor: textsecure.SyncRequest, - }; -})(); diff --git a/libtextsecure/test/fake_web_api.js b/libtextsecure/test/fake_web_api.js deleted file mode 100644 index 3c38a806d..000000000 --- a/libtextsecure/test/fake_web_api.js +++ /dev/null @@ -1,13 +0,0 @@ -window.setImmediate = window.nodeSetImmediate; - -const fakeCall = () => Promise.resolve(); - -const fakeAPI = { - getAttachment: fakeCall, - putAttachment: fakeCall, - putAvatar: fakeCall, -}; - -window.WebAPI = { - connect: () => fakeAPI, -}; diff --git a/libtextsecure/test/helpers_test.js b/libtextsecure/test/helpers_test.js deleted file mode 100644 index 66ecb83e7..000000000 --- a/libtextsecure/test/helpers_test.js +++ /dev/null @@ -1,29 +0,0 @@ -describe('Helpers', () => { - describe('ArrayBuffer->String conversion', () => { - it('works', () => { - const b = new ArrayBuffer(3); - const a = new Uint8Array(b); - a[0] = 0; - a[1] = 255; - a[2] = 128; - assert.equal(getString(b), '\x00\xff\x80'); - }); - }); - - describe('stringToArrayBuffer', () => { - it('returns ArrayBuffer when passed string', () => { - const anArrayBuffer = new ArrayBuffer(1); - const typedArray = new Uint8Array(anArrayBuffer); - typedArray[0] = 'a'.charCodeAt(0); - assertEqualArrayBuffers(stringToArrayBuffer('a'), anArrayBuffer); - }); - it('throws an error when passed a non string', () => { - const notStringable = [{}, undefined, null, new ArrayBuffer()]; - notStringable.forEach(notString => { - assert.throw(() => { - stringToArrayBuffer(notString); - }, Error); - }); - }); - }); -}); diff --git a/libtextsecure/test/index.html b/libtextsecure/test/index.html index ca6acd91f..bcbe5cd0b 100644 --- a/libtextsecure/test/index.html +++ b/libtextsecure/test/index.html @@ -12,7 +12,6 @@
- @@ -29,8 +28,6 @@ - - diff --git a/libtextsecure/test/message_receiver_test.js b/libtextsecure/test/message_receiver_test.js deleted file mode 100644 index cff0f3b0c..000000000 --- a/libtextsecure/test/message_receiver_test.js +++ /dev/null @@ -1,104 +0,0 @@ -/* global libsignal, textsecure, SignalProtocolStore */ - -describe('MessageReceiver', () => { - textsecure.storage.impl = new SignalProtocolStore(); - const { WebSocket } = window; - const number = '+19999999999'; - const deviceId = 1; - const signalingKey = libsignal.crypto.getRandomBytes(32 + 20); - - before(() => { - window.WebSocket = MockSocket; - textsecure.storage.user.setNumberAndDeviceId(number, deviceId, 'name'); - textsecure.storage.put('password', 'password'); - textsecure.storage.put('signaling_key', signalingKey); - }); - after(() => { - window.WebSocket = WebSocket; - }); - - describe('connecting', () => { - const attrs = { - type: textsecure.protobuf.Envelope.Type.CIPHERTEXT, - source: number, - sourceDevice: deviceId, - timestamp: Date.now(), - }; - const websocketmessage = new textsecure.protobuf.WebSocketMessage({ - type: textsecure.protobuf.WebSocketMessage.Type.REQUEST, - request: { verb: 'PUT', path: '/messages' }, - }); - - before(done => { - const signal = new textsecure.protobuf.Envelope(attrs).toArrayBuffer(); - - const aesKey = signalingKey.slice(0, 32); - const macKey = signalingKey.slice(32, 32 + 20); - - window.crypto.subtle - .importKey('raw', aesKey, { name: 'AES-CBC' }, false, ['encrypt']) - .then(key => { - const iv = libsignal.crypto.getRandomBytes(16); - window.crypto.subtle - .encrypt({ name: 'AES-CBC', iv: new Uint8Array(iv) }, key, signal) - .then(ciphertext => { - window.crypto.subtle - .importKey( - 'raw', - macKey, - { name: 'HMAC', hash: { name: 'SHA-256' } }, - false, - ['sign'] - ) - .then(innerKey => { - window.crypto.subtle - .sign({ name: 'HMAC', hash: 'SHA-256' }, innerKey, signal) - .then(mac => { - const version = new Uint8Array([1]); - const message = dcodeIO.ByteBuffer.concat([ - version, - iv, - ciphertext, - mac, - ]); - websocketmessage.request.body = message.toArrayBuffer(); - done(); - }); - }); - }); - }); - }); - - it('connects', done => { - const mockServer = new MockServer( - `ws://localhost:8080/v1/websocket/?login=${encodeURIComponent( - number - )}.1&password=password` - ); - - mockServer.on('connection', server => { - server.send(new Blob([websocketmessage.toArrayBuffer()])); - }); - - window.addEventListener('textsecure:message', ev => { - const signal = ev.proto; - const keys = Object.keys(attrs); - - for (let i = 0, max = keys.length; i < max; i += 1) { - const key = keys[i]; - assert.strictEqual(attrs[key], signal[key]); - } - assert.strictEqual(signal.message.body, 'hello'); - mockServer.close(); - - done(); - }); - - window.messageReceiver = new textsecure.MessageReceiver( - 'signalingKey' - // 'ws://localhost:8080', - // window, - ); - }); - }); -}); diff --git a/libtextsecure/test/websocket_test.js b/libtextsecure/test/websocket_test.js deleted file mode 100644 index dcaa749fd..000000000 --- a/libtextsecure/test/websocket_test.js +++ /dev/null @@ -1,66 +0,0 @@ -/* global TextSecureWebSocket */ - -describe('TextSecureWebSocket', () => { - const RealWebSocket = window.WebSocket; - before(() => { - window.WebSocket = MockSocket; - }); - after(() => { - window.WebSocket = RealWebSocket; - }); - it('connects and disconnects', done => { - const mockServer = new MockServer('ws://localhost:8080'); - mockServer.on('connection', server => { - socket.close(); - server.close(); - done(); - }); - const socket = new TextSecureWebSocket('ws://localhost:8080'); - }); - - it('sends and receives', done => { - const mockServer = new MockServer('ws://localhost:8080'); - mockServer.on('connection', server => { - server.on('message', () => { - server.send('ack'); - server.close(); - }); - }); - const socket = new TextSecureWebSocket('ws://localhost:8080'); - socket.onmessage = response => { - assert.strictEqual(response.data, 'ack'); - socket.close(); - done(); - }; - socket.send('syn'); - }); - - it('exposes the socket status', done => { - const mockServer = new MockServer('ws://localhost:8082'); - mockServer.on('connection', server => { - assert.strictEqual(socket.getStatus(), WebSocket.OPEN); - server.close(); - socket.close(); - }); - const socket = new TextSecureWebSocket('ws://localhost:8082'); - socket.onclose = () => { - assert.strictEqual(socket.getStatus(), WebSocket.CLOSING); - done(); - }; - }); - - it('reconnects', function thisNeeded(done) { - this.timeout(60000); - const mockServer = new MockServer('ws://localhost:8082'); - const socket = new TextSecureWebSocket('ws://localhost:8082'); - socket.onclose = () => { - const secondServer = new MockServer('ws://localhost:8082'); - secondServer.on('connection', server => { - socket.close(); - server.close(); - done(); - }); - }; - mockServer.close(); - }); -}); diff --git a/preload.js b/preload.js index e07cfa0b6..d77c89618 100644 --- a/preload.js +++ b/preload.js @@ -340,10 +340,6 @@ if (config.proxyUrl) { window.nodeSetImmediate = setImmediate; -const { initialize: initializeWebAPI } = require('./js/modules/web_api'); - -window.WebAPI = initializeWebAPI(); - window.seedNodeList = JSON.parse(config.seedNodeList); const { OnionAPI } = require('./ts/session/onions'); @@ -461,7 +457,6 @@ window.lokiFeatureFlags = { useFileOnionRequests: true, useFileOnionRequestsV2: true, // more compact encoding of files in response onionRequestHops: 3, - debugMessageLogs: process.env.ENABLE_MESSAGE_LOGS, useMultiDevice: false, }; @@ -497,7 +492,6 @@ if (config.environment.includes('test-integration')) { useOnionRequests: false, useFileOnionRequests: false, useOnionRequestsV2: false, - debugMessageLogs: true, useMultiDevice: false, }; /* eslint-disable global-require, import/no-extraneous-dependencies */ diff --git a/test/fixtures_test.js b/test/fixtures_test.js index c879e8827..3916b7751 100644 --- a/test/fixtures_test.js +++ b/test/fixtures_test.js @@ -5,7 +5,6 @@ describe('Fixtures', () => { before(async () => { // NetworkStatusView checks this method every five seconds while showing - window.getSocketStatus = () => WebSocket.OPEN; await clearDatabase(); await textsecure.storage.user.setNumberAndDeviceId( diff --git a/test/index.html b/test/index.html index aa90e2af5..8d0121856 100644 --- a/test/index.html +++ b/test/index.html @@ -166,7 +166,6 @@ {{/isError}} - diff --git a/test/models/conversations_test.js b/test/models/conversations_test.js index ab05f7fb8..e9d59c37d 100644 --- a/test/models/conversations_test.js +++ b/test/models/conversations_test.js @@ -3,7 +3,7 @@ // 'use strict'; // FIXME audric enable back those test describe('ConversationCollection', () => { - // textsecure.messaging = new textsecure.MessageSender(); + // textsecure.messaging = true; // before(clearDatabase); // after(clearDatabase); // it('should be ordered newest to oldest', () => { diff --git a/ts/components/session/LeftPaneMessageSection.tsx b/ts/components/session/LeftPaneMessageSection.tsx index 051b19435..4e59f9818 100644 --- a/ts/components/session/LeftPaneMessageSection.tsx +++ b/ts/components/session/LeftPaneMessageSection.tsx @@ -31,6 +31,7 @@ import { ToastUtils } from '../../session/utils'; import { DefaultTheme } from 'styled-components'; import { LeftPaneSectionHeader } from './LeftPaneSectionHeader'; import { ConversationController } from '../../session/conversations'; +import { sendOpenGroupsSyncMessage } from '../../session/utils/SyncMessage'; export interface Props { searchTerm: string; @@ -456,9 +457,7 @@ export class LeftPaneMessageSection extends React.Component { if (openGroupConversation) { // if no errors happened, trigger a sync with just this open group // so our other devices joins it - await window.textsecure.messaging.sendOpenGroupsSyncMessage( - openGroupConversation - ); + await sendOpenGroupsSyncMessage([openGroupConversation]); } else { window.log.error( 'Joined an opengroup but did not find ther corresponding conversation' diff --git a/ts/receiver/closedGroupsV2.ts b/ts/receiver/closedGroupsV2.ts index d6846f573..2db5a1cd0 100644 --- a/ts/receiver/closedGroupsV2.ts +++ b/ts/receiver/closedGroupsV2.ts @@ -366,10 +366,6 @@ async function handleUpdateClosedGroupV2( diff.newName ) { await ClosedGroupV2.addUpdateMessage(convo, diff, 'incoming'); - if (diff.joiningMembers?.length) { - // send a session request for all the members we do not have a session with - await window.libloki.api.sendSessionRequestsToMembers(members); - } } convo.set('name', name); diff --git a/ts/receiver/multidevice.ts b/ts/receiver/multidevice.ts index 2bac7cb41..64aee5f9e 100644 --- a/ts/receiver/multidevice.ts +++ b/ts/receiver/multidevice.ts @@ -303,12 +303,6 @@ async function onContactReceived(details: any) { const { Errors } = window.Signal.Types; const id = details.number; - libloki.api.debug.logContactSync( - 'Got sync contact message with', - id, - ' details:', - details - ); if (id === textsecure.storage.user.getNumber()) { // special case for syncing details about ourselves diff --git a/ts/receiver/syncMessages.ts b/ts/receiver/syncMessages.ts index 326ebbd10..53cf8bade 100644 --- a/ts/receiver/syncMessages.ts +++ b/ts/receiver/syncMessages.ts @@ -159,9 +159,6 @@ async function handleOpenGroups( openGroups: Array ) { const groupsArray = openGroups.map(openGroup => openGroup.url); - window.libloki.api.debug.logGroupSync( - `Received GROUP_SYNC with open groups: [${groupsArray}]` - ); openGroups.forEach(({ url, channelId }) => { window.attemptConnection(url, channelId); }); diff --git a/ts/session/groupv2/index.ts b/ts/session/groupv2/index.ts index 7e73723ce..74d78d1ff 100644 --- a/ts/session/groupv2/index.ts +++ b/ts/session/groupv2/index.ts @@ -199,17 +199,8 @@ export function buildGroupDiff( } export async function updateOrCreateClosedGroupV2(details: GroupInfo) { - const { libloki } = window; - const { id } = details; - libloki.api.debug.logGroupSync( - 'Got sync group message v2with group id', - id, - ' details:', - details - ); - const conversation = await ConversationController.getInstance().getOrCreateAndWait( id, 'group' diff --git a/ts/session/messages/outgoing/content/sync/RequestSyncMessage.ts b/ts/session/messages/outgoing/content/sync/RequestSyncMessage.ts deleted file mode 100644 index 716e26562..000000000 --- a/ts/session/messages/outgoing/content/sync/RequestSyncMessage.ts +++ /dev/null @@ -1,36 +0,0 @@ -import { SyncMessage } from './SyncMessage'; -import { SignalService } from '../../../../../protobuf'; -import { MessageParams } from '../../Message'; -import { Constants } from '../../../..'; - -interface RequestSyncMessageParams extends MessageParams { - requestType: SignalService.SyncMessage.Request.Type; -} - -export abstract class RequestSyncMessage extends SyncMessage { - private readonly requestType: SignalService.SyncMessage.Request.Type; - - constructor(params: RequestSyncMessageParams) { - super({ timestamp: params.timestamp, identifier: params.identifier }); - this.requestType = params.requestType; - } - - public ttl(): number { - return Constants.TTL_DEFAULT.REGULAR_MESSAGE; - } - - public contentProto(): SignalService.Content { - return new SignalService.Content({ - syncMessage: this.syncProto(), - }); - } - - protected syncProto(): SignalService.SyncMessage { - const syncMessage = super.syncProto(); - syncMessage.request = new SignalService.SyncMessage.Request({ - type: this.requestType, - }); - - return syncMessage; - } -} diff --git a/ts/session/messages/outgoing/content/sync/VerifiedSyncMessage.ts b/ts/session/messages/outgoing/content/sync/VerifiedSyncMessage.ts deleted file mode 100644 index ee9fd0c69..000000000 --- a/ts/session/messages/outgoing/content/sync/VerifiedSyncMessage.ts +++ /dev/null @@ -1,37 +0,0 @@ -import { SyncMessage } from './SyncMessage'; -import { SignalService } from '../../../../../protobuf'; -import { MessageParams } from '../../Message'; -import { PubKey } from '../../../../types'; - -interface VerifiedSyncMessageParams extends MessageParams { - padding: Buffer; - identityKey: Uint8Array; - destination: PubKey; - state: SignalService.Verified.State; -} - -export abstract class VerifiedSyncMessage extends SyncMessage { - public readonly state: SignalService.Verified.State; - public readonly destination: PubKey; - public readonly identityKey: Uint8Array; - public readonly padding: Buffer; - - constructor(params: VerifiedSyncMessageParams) { - super({ timestamp: params.timestamp, identifier: params.identifier }); - this.state = params.state; - this.destination = params.destination; - this.identityKey = params.identityKey; - this.padding = params.padding; - } - - protected syncProto(): SignalService.SyncMessage { - const syncMessage = super.syncProto(); - syncMessage.verified = new SignalService.Verified(); - syncMessage.verified.state = this.state; - syncMessage.verified.destination = this.destination.key; - syncMessage.verified.identityKey = this.identityKey; - syncMessage.verified.nullMessage = this.padding; - - return syncMessage; - } -} diff --git a/ts/session/messages/outgoing/content/sync/index.ts b/ts/session/messages/outgoing/content/sync/index.ts index bfb24b2a9..33cdf05ca 100644 --- a/ts/session/messages/outgoing/content/sync/index.ts +++ b/ts/session/messages/outgoing/content/sync/index.ts @@ -1,9 +1,7 @@ -export * from './RequestSyncMessage'; export * from './ContactSyncMessage'; export * from './ClosedGroupSyncMessage'; export * from './OpenGroupSyncMessage'; export * from './SyncMessage'; export * from './SentSyncMessage'; export * from './SyncReadMessage'; -export * from './VerifiedSyncMessage'; export * from './BlockedListSyncMessage'; diff --git a/ts/session/utils/SyncMessage.ts b/ts/session/utils/SyncMessage.ts index bb2baaf26..ebea91f60 100644 --- a/ts/session/utils/SyncMessage.ts +++ b/ts/session/utils/SyncMessage.ts @@ -1,15 +1,22 @@ import * as _ from 'lodash'; -import { UserUtil } from '../../util'; +import { BlockedNumberController, UserUtil } from '../../util'; import { getAllConversations } from '../../../js/modules/data'; import { MultiDeviceProtocol } from '../protocols'; import ByteBuffer from 'bytebuffer'; import { + BlockedListSyncMessage, + ClosedGroupSyncMessage, ContentMessage, DataMessage, + OpenGroupSyncMessage, SentSyncMessage, + SyncReadMessage, } from '../messages/outgoing'; import { PubKey } from '../types'; import { ConversationController } from '../conversations'; +import { ConversationModel } from '../../../js/models/conversations'; +import { getMessageQueue } from '../instance'; +import { syncMediumGroups } from '../groupv2'; export function getSentSyncMessage(params: { message: ContentMessage; @@ -32,14 +39,13 @@ export function getSentSyncMessage(params: { }); } -export async function getSyncContacts(): Promise | undefined> { +export async function getSyncContacts(): Promise> { const thisDevice = await UserUtil.getCurrentDevicePubKey(); if (!thisDevice) { return []; } - const primaryDevice = await MultiDeviceProtocol.getPrimaryDevice(thisDevice); const conversations = await getAllConversations({ ConversationCollection: window.Whisper.ConversationCollection, }); @@ -55,28 +61,8 @@ export async function getSyncContacts(): Promise | undefined> { !!c.get('active_at') ) || []; - const secondaryContactsPartial = conversations.filter( - c => - c.isPrivate() && - !c.isOurLocalDevice() && - !c.isBlocked() && - c.attributes.secondaryStatus && - !!c.get('active_at') - ); - - const secondaryContactsPromise = secondaryContactsPartial.map(async c => - ConversationController.getInstance().getOrCreateAndWait( - c.getPrimaryDevicePubKey(), - 'private' - ) - ); - - const secondaryContacts = (await Promise.all(secondaryContactsPromise)) - // Filter out our primary key if it was added here - .filter(c => c.id !== primaryDevice.key); - // Return unique contacts - return _.uniqBy([...primaryContacts, ...secondaryContacts], 'id'); + return primaryContacts; } export async function filterOpenGroupsConvos( @@ -110,3 +96,188 @@ export function serialiseByteBuffers(buffers: Array): ByteBuffer { result.reset(); return result; } + +export async function sendContactSyncMessage(convos: Array) { + throw new Error('Still in use?'); + + // let convosToSync: Array; + // if (!convos?.length) { + // convosToSync = await getSyncContacts(); + // } else { + // convosToSync = convos; + // } + + // if (convosToSync?.length === 0) { + // window.log.info('No contacts to sync.'); + + // return Promise.resolve(); + // } + + // // We need to sync across 3 contacts at a time + // // This is to avoid hitting storage server limit + // const chunked = _.chunk(convosToSync, 3); + // const syncMessages = await Promise.all( + // chunked.map(c => createContactSyncMessage(c)) + // ); + + // const syncPromises = syncMessages.map(syncMessage => + // getMessageQueue().sendSyncMessage(syncMessage) + // ); + + // return Promise.all(syncPromises); +} + +function createGroupSyncMessage(sessionGroup: any) { + // We are getting a single open group here + + // const rawGroup = { + // id: sessionGroup.id, + // name: sessionGroup.get('name'), + // members: sessionGroup.get('members') || [], + // blocked: sessionGroup.isBlocked(), + // expireTimer: sessionGroup.get('expireTimer'), + // admins: sessionGroup.get('groupAdmins') || [], + // }; + + throw new Error('Still in use?'); + + // return new ClosedGroupSyncMessage({ + // timestamp: Date.now(), + // rawGroup, + // }); +} + +async function createContactSyncMessage(sessionContacts: Array) { + if (sessionContacts.length === 0) { + return null; + } + + const rawContacts = await Promise.all( + sessionContacts.map(async conversation => { + const profile = conversation.getLokiProfile(); + const name = profile + ? profile.displayName + : conversation.getProfileName(); + const status = await conversation.safeGetVerified(); + + return { + name, + number: conversation.getNumber(), + nickname: conversation.getNickname(), + blocked: conversation.isBlocked(), + expireTimer: conversation.get('expireTimer'), + verifiedStatus: status, + }; + }) + ); + + throw new Error('Still in use?'); + + // return new ContactSyncMessage({ + // timestamp: Date.now(), + // rawContacts, + // }); +} + +export async function sendGroupSyncMessage( + conversations: Array +) { + throw new Error('Still in use?'); + + // If we havn't got a primaryDeviceKey then we are in the middle of pairing + // primaryDevicePubKey is set to our own number if we are the master device + // const primaryDeviceKey = window.storage.get('primaryDevicePubKey'); + // if (!primaryDeviceKey) { + // window.log.debug('sendGroupSyncMessage: no primary device pubkey'); + // return Promise.resolve(); + // } + // // We only want to sync across closed groups that we haven't left + // const activeGroups = conversations.filter( + // c => c.isClosedGroup() && !c.get('left') && !c.get('isKickedFromGroup') + // ); + // if (activeGroups.length === 0) { + // window.log.info('No closed group to sync.'); + // return Promise.resolve(); + // } + + // const mediumGroups = activeGroups.filter(c => c.isMediumGroup()); + + // syncMediumGroups(mediumGroups); + + // const legacyGroups = activeGroups.filter(c => !c.isMediumGroup()); + + // // We need to sync across 1 group at a time + // // This is because we could hit the storage server limit with one group + // const syncPromises = legacyGroups + // .map(c => createGroupSyncMessage(c)) + // .map(syncMessage => getMessageQueue().sendSyncMessage(syncMessage)); + + // return Promise.all(syncPromises); +} + +export async function sendOpenGroupsSyncMessage( + convos: Array +) { + throw new Error('Still in use?'); + + // If we havn't got a primaryDeviceKey then we are in the middle of pairing + // primaryDevicePubKey is set to our own number if we are the master device + // const primaryDeviceKey = (await UserUtil.getPrimary()).key; + // if (!primaryDeviceKey) { + // return Promise.resolve(); + // } + // const conversations = Array.isArray(convos) ? convos : [convos]; + + // const openGroupsConvos = await filterOpenGroupsConvos(conversations); + + // if (!openGroupsConvos?.length) { + // window.log.info('No open groups to sync'); + // return Promise.resolve(); + // } + + // // Send the whole list of open groups in a single message + // const openGroupsDetails = openGroupsConvos.map(conversation => ({ + // url: conversation.id, + // channelId: conversation.get('channelId'), + // })); + // const openGroupsSyncParams = { + // timestamp: Date.now(), + // openGroupsDetails, + // }; + // const openGroupsSyncMessage = new OpenGroupSyncMessage(openGroupsSyncParams); + + // return getMessageQueue().sendSyncMessage(openGroupsSyncMessage); +} + +export async function sendBlockedListSyncMessage() { + throw new Error('Still in use?'); + + // If we havn't got a primaryDeviceKey then we are in the middle of pairing + // primaryDevicePubKey is set to our own number if we are the master device + // const primaryDeviceKey = window.storage.get('primaryDevicePubKey'); + // if (!primaryDeviceKey) { + // return Promise.resolve(); + // } + + // const currentlyBlockedNumbers = BlockedNumberController.getBlockedNumbers(); + + // // currently we only sync user blocked, not groups + // const blockedSyncMessage = new BlockedListSyncMessage({ + // timestamp: Date.now(), + // numbers: currentlyBlockedNumbers, + // groups: [], + // }); + // return getMessageQueue().sendSyncMessage(blockedSyncMessage); +} + +export async function syncReadMessages() { + return; + // FIXME currently not in used + // const syncReadMessages = new SyncReadMessage( + // { + // timestamp: Date.now(), + // readMessages: reads, + // } + // ); + // return libsession.getMessageQueue().sendSyncMessage(syncReadMessages); +} diff --git a/ts/util/lint/exceptions.json b/ts/util/lint/exceptions.json index 3a30faedb..e931394ac 100644 --- a/ts/util/lint/exceptions.json +++ b/ts/util/lint/exceptions.json @@ -965,30 +965,6 @@ "reasonCategory": "falseMatch", "updated": "2018-09-19T18:13:29.628Z" }, - { - "rule": "jQuery-wrap(", - "path": "libtextsecure/sync_request.js", - "line": " wrap(sender.sendRequestConfigurationSyncMessage(sendOptions));", - "lineNumber": 33, - "reasonCategory": "falseMatch", - "updated": "2018-11-28T19:48:16.607Z" - }, - { - "rule": "jQuery-wrap(", - "path": "libtextsecure/sync_request.js", - "line": " wrap(sender.sendRequestContactSyncMessage(sendOptions))", - "lineNumber": 36, - "reasonCategory": "falseMatch", - "updated": "2018-10-05T23:12:28.961Z" - }, - { - "rule": "jQuery-wrap(", - "path": "libtextsecure/sync_request.js", - "line": " return wrap(sender.sendRequestGroupSyncMessage(sendOptions));", - "lineNumber": 39, - "reasonCategory": "falseMatch", - "updated": "2018-10-05T23:12:28.961Z" - }, { "rule": "jQuery-wrap(", "path": "node_modules/@babel/runtime/node_modules/regenerator-runtime/runtime.js", diff --git a/ts/window.d.ts b/ts/window.d.ts index e5bc15198..69817b898 100644 --- a/ts/window.d.ts +++ b/ts/window.d.ts @@ -41,7 +41,6 @@ declare global { StringView: any; StubAppDotNetApi: any; StubMessageAPI: any; - WebAPI: any; Whisper: any; attemptConnection: ConversationType; clearLocalData: any; @@ -67,7 +66,6 @@ declare global { useFileOnionRequests: boolean; useFileOnionRequestsV2: boolean; onionRequestHops: number; - debugMessageLogs: boolean; useMultiDevice: boolean; }; lokiFileServerAPI: LokiFileServerInstance; @@ -116,7 +114,6 @@ declare global { setClockParams: any; clientClockSynced: number | undefined; inboxStore: Store; - getSocketStatus: any; actionsCreators: any; extension: { expired: (boolean) => void;