From 5bc576249b1059d8c7823f050bdacb30741385ce Mon Sep 17 00:00:00 2001
From: Audric Ackermann <audric@loki.network>
Date: Wed, 30 Mar 2022 08:50:08 +1100
Subject: [PATCH] move signal.js to TS

---
 js/modules/.eslintrc                        | 14 --------------
 js/modules/crypto.js                        | 21 ---------------------
 js/modules/signal.js                        | 17 -----------------
 libtextsecure/crypto.js                     | 10 ++++++++--
 preload.js                                  |  6 ++----
 ts/interactions/conversationInteractions.ts |  3 ++-
 ts/mains/main_renderer.ts                   | 14 +++++++-------
 ts/node/signal.ts                           | 12 ++++++++++++
 ts/receiver/queuedJob.ts                    |  3 ++-
 ts/window.d.ts                              |  2 --
 10 files changed, 33 insertions(+), 69 deletions(-)
 delete mode 100644 js/modules/.eslintrc
 delete mode 100644 js/modules/crypto.js
 delete mode 100644 js/modules/signal.js
 create mode 100644 ts/node/signal.ts

diff --git a/js/modules/.eslintrc b/js/modules/.eslintrc
deleted file mode 100644
index 705203794..000000000
--- a/js/modules/.eslintrc
+++ /dev/null
@@ -1,14 +0,0 @@
-{
-  "env": {
-    "browser": false,
-    "commonjs": true,
-    "node": false
-  },
-  "globals": {
-    "console": true,
-    "setTimeout": true
-  },
-  "parserOptions": {
-    "sourceType": "module"
-  }
-}
diff --git a/js/modules/crypto.js b/js/modules/crypto.js
deleted file mode 100644
index d60d0811e..000000000
--- a/js/modules/crypto.js
+++ /dev/null
@@ -1,21 +0,0 @@
-/* eslint-env browser */
-/* global dcodeIO */
-
-/* eslint-disable camelcase, no-bitwise */
-
-module.exports = {
-  bytesFromString,
-  getRandomBytes,
-};
-
-// Utility
-
-function bytesFromString(string) {
-  return dcodeIO.ByteBuffer.wrap(string, 'utf8').toArrayBuffer();
-}
-
-function getRandomBytes(n) {
-  const bytes = new Uint8Array(n);
-  window.crypto.getRandomValues(bytes);
-  return bytes;
-}
diff --git a/js/modules/signal.js b/js/modules/signal.js
deleted file mode 100644
index bebade759..000000000
--- a/js/modules/signal.js
+++ /dev/null
@@ -1,17 +0,0 @@
-// The idea with this file is to make it webpackable for the style guide
-
-const Crypto = require('./crypto');
-const Data = require('../../ts/data/data');
-const OS = require('../../ts/OS');
-const Util = require('../../ts/util');
-
-exports.setup = () => {
-  Data.init();
-
-  return {
-    Crypto,
-    Data,
-    OS,
-    Util,
-  };
-};
diff --git a/libtextsecure/crypto.js b/libtextsecure/crypto.js
index afe1ce752..feeb28be4 100644
--- a/libtextsecure/crypto.js
+++ b/libtextsecure/crypto.js
@@ -28,6 +28,12 @@
     return crypto.subtle.digest({ name: 'SHA-256' }, data);
   }
 
+  function getRandomBytesFromLength(n) {
+    const bytes = new Uint8Array(n);
+    crypto.getRandomValues(bytes);
+    return bytes;
+  }
+
   window.textsecure = window.textsecure || {};
   window.textsecure.crypto = {
     decryptAttachment(encryptedBin, keys, theirDigest) {
@@ -89,7 +95,7 @@
       });
     },
     encryptProfile(data, key) {
-      const iv = libsignal.crypto.getRandomBytes(PROFILE_IV_LENGTH);
+      const iv = getRandomBytesFromLength(PROFILE_IV_LENGTH);
       if (key.byteLength !== PROFILE_KEY_LENGTH) {
         throw new Error('Got invalid length profile key');
       }
@@ -166,7 +172,7 @@
     },
 
     getRandomBytes(size) {
-      return libsignal.crypto.getRandomBytes(size);
+      return getRandomBytesFromLength(size);
     },
   };
 })();
diff --git a/preload.js b/preload.js
index 89e8a9bbe..109db2fdb 100644
--- a/preload.js
+++ b/preload.js
@@ -182,10 +182,10 @@ if (config.proxyUrl) {
 }
 window.nodeSetImmediate = setImmediate;
 
-const Signal = require('./js/modules/signal');
+const Signal = require('./ts/node/signal');
 const i18n = require('./ts/util/i18n');
 
-window.Signal = Signal.setup();
+window.Signal = Signal.setupSignal();
 
 window.getSwarmPollingInstance = require('./ts/session/apis/snode_api').getSwarmPollingInstance;
 
@@ -226,8 +226,6 @@ window.i18n = i18n.setupi18n(localFromEnv, localeMessages);
 window.moment = require('moment');
 window.libsession = require('./ts/session');
 
-window.Signal.Data = require('./ts/data/data');
-
 window.addEventListener('contextmenu', e => {
   const editable = e.target.closest('textarea, input, [contenteditable="true"]');
   const link = e.target.closest('a');
diff --git a/ts/interactions/conversationInteractions.ts b/ts/interactions/conversationInteractions.ts
index 2e035b4df..c54089c16 100644
--- a/ts/interactions/conversationInteractions.ts
+++ b/ts/interactions/conversationInteractions.ts
@@ -46,6 +46,7 @@ import { processNewAttachment } from '../types/MessageAttachment';
 import { urlToBlob } from '../types/attachments/VisualAttachment';
 import { MIME } from '../types';
 import { setLastProfileUpdateTimestamp } from '../util/storage';
+import { getSodium } from '../session/crypto';
 
 export const getCompleteUrlForV2ConvoId = async (convoId: string) => {
   if (convoId.match(openGroupV2ConversationIdRegex)) {
@@ -389,7 +390,7 @@ export async function uploadOurAvatar(newAvatarDecrypted?: ArrayBuffer) {
   let decryptedAvatarData;
   if (newAvatarDecrypted) {
     // Encrypt with a new key every time
-    profileKey = window.libsignal.crypto.getRandomBytes(32) as Uint8Array;
+    profileKey = (await getSodium()).randombytes_buf(32);
     decryptedAvatarData = newAvatarDecrypted;
   } else {
     // this is a reupload. no need to generate a new profileKey
diff --git a/ts/mains/main_renderer.ts b/ts/mains/main_renderer.ts
index e74f252cf..9e53481eb 100644
--- a/ts/mains/main_renderer.ts
+++ b/ts/mains/main_renderer.ts
@@ -179,24 +179,24 @@ Storage.onready(async () => {
   }
 });
 
-function manageExpiringData() {
-  window.Signal.Data.cleanSeenMessages();
-  window.Signal.Data.cleanLastHashes();
+async function manageExpiringData() {
+  await Data.cleanSeenMessages();
+  await Data.cleanLastHashes();
   setTimeout(manageExpiringData, 1000 * 60 * 60);
 }
 
 // tslint:disable-next-line: max-func-body-length
 async function start() {
-  manageExpiringData();
+  void manageExpiringData();
   window.dispatchEvent(new Event('storage_ready'));
 
   window.log.info('Cleanup: starting...');
 
-  const results = await Promise.all([window.Signal.Data.getOutgoingWithoutExpiresAt()]);
+  const results = await Promise.all([Data.getOutgoingWithoutExpiresAt()]);
 
   // Combine the models
   const messagesForCleanup = results.reduce(
-    (array, current) => array.concat(current.toArray()),
+    (array, current) => array.concat((current as any).toArray()),
     []
   );
 
@@ -210,7 +210,7 @@ async function start() {
       }
 
       window.log.info(`Cleanup: Deleting unsent message ${sentAt}`);
-      await window.Signal.Data.removeMessage(message.id);
+      await Data.removeMessage(message.id);
     })
   );
   window.log.info('Cleanup: complete');
diff --git a/ts/node/signal.ts b/ts/node/signal.ts
new file mode 100644
index 000000000..c1aef2a43
--- /dev/null
+++ b/ts/node/signal.ts
@@ -0,0 +1,12 @@
+// The idea with this file is to make it webpackable for the style guide
+
+import * as Data from '../../ts/data/data';
+import * as Util from '../../ts/util';
+
+export const setupSignal = () => {
+  Data.init();
+
+  return {
+    Util,
+  };
+};
diff --git a/ts/receiver/queuedJob.ts b/ts/receiver/queuedJob.ts
index 7e1ad3268..3ce440558 100644
--- a/ts/receiver/queuedJob.ts
+++ b/ts/receiver/queuedJob.ts
@@ -14,9 +14,10 @@ import { UserUtils } from '../session/utils';
 import { showMessageRequestBanner } from '../state/ducks/userConfig';
 import { MessageDirection } from '../models/messageType';
 import { LinkPreviews } from '../util/linkPreviews';
+import { GoogleChrome } from '../util';
 
 function contentTypeSupported(type: string): boolean {
-  const Chrome = window.Signal.Util.GoogleChrome;
+  const Chrome = GoogleChrome;
   return Chrome.isImageTypeSupported(type) || Chrome.isVideoTypeSupported(type);
 }
 
diff --git a/ts/window.d.ts b/ts/window.d.ts
index 8c6387576..95f0ab241 100644
--- a/ts/window.d.ts
+++ b/ts/window.d.ts
@@ -2,7 +2,6 @@ import {} from 'styled-components/cssprop';
 
 import { LocalizerType } from '../ts/types/Util';
 import { LibsignalProtocol } from '../../libtextsecure/libsignal-protocol';
-import { SignalInterface } from '../../js/modules/signal';
 import { LibTextsecure } from '../libtextsecure';
 
 import { Store } from 'redux';
@@ -22,7 +21,6 @@ declare global {
     Lodash: any;
     SessionSnodeAPI: any;
     Session: any;
-    Signal: SignalInterface;
     StubAppDotNetApi: any;
     StringView: any;
     StubMessageAPI: any;