1
0
mirror of https://github.com/matrix-org/matrix-js-sdk.git synced 2025-11-28 05:03:59 +03:00

Merge branch 'develop' into kegan/indexeddb

This commit is contained in:
Kegan Dougal
2017-01-26 14:29:30 +00:00
66 changed files with 2559 additions and 2190 deletions

View File

@@ -1,4 +1,5 @@
module.exports = { module.exports = {
parser: "babel-eslint",
parserOptions: { parserOptions: {
ecmaVersion: 6, ecmaVersion: 6,
sourceType: "module", sourceType: "module",
@@ -11,12 +12,20 @@ module.exports = {
}, },
extends: ["eslint:recommended", "google"], extends: ["eslint:recommended", "google"],
rules: { rules: {
// rules we've always adhered to // rules we've always adhered to or now do
"max-len": ["error", { "max-len": ["error", {
code: 90, code: 90,
ignoreComments: true, ignoreComments: true,
}], }],
curly: ["error", "multi-line"], curly: ["error", "multi-line"],
"prefer-const": ["error"],
"comma-dangle": ["error", {
arrays: "always-multiline",
objects: "always-multiline",
imports: "always-multiline",
exports: "always-multiline",
functions: "always-multiline",
}],
// loosen jsdoc requirements a little // loosen jsdoc requirements a little
"require-jsdoc": ["error", { "require-jsdoc": ["error", {
@@ -47,8 +56,7 @@ module.exports = {
// we set these to warnings, and assert that the number // we set these to warnings, and assert that the number
// of warnings doesn't exceed a given threshold // of warnings doesn't exceed a given threshold
"no-var": ["warn"], "no-var": ["warn"],
"comma-dangle": ["warn"], "brace-style": ["warn", "1tbs", {"allowSingleLine": true}],
"brace-style": ["warn"],
"prefer-rest-params": ["warn"], "prefer-rest-params": ["warn"],
"prefer-spread": ["warn"], "prefer-spread": ["warn"],
"one-var": ["warn"], "one-var": ["warn"],

1
.gitignore vendored
View File

@@ -8,6 +8,7 @@ out
reports reports
/dist /dist
/lib /lib
/specbuild
# version file and tarball created by 'npm pack' # version file and tarball created by 'npm pack'
/git-revision.txt /git-revision.txt

View File

@@ -1,3 +1,6 @@
language: node_js language: node_js
node_js: node_js:
- node # Latest stable version of nodejs. - node # Latest stable version of nodejs.
script:
- npm run lint
- npm run test

View File

@@ -1,3 +1,26 @@
Changes in [0.7.4](https://github.com/matrix-org/matrix-js-sdk/releases/tag/v0.7.4) (2017-01-16)
================================================================================================
[Full Changelog](https://github.com/matrix-org/matrix-js-sdk/compare/v0.7.4-rc.1...v0.7.4)
* Fix non-conference calling
Changes in [0.7.4-rc.1](https://github.com/matrix-org/matrix-js-sdk/releases/tag/v0.7.4-rc.1) (2017-01-13)
==========================================================================================================
[Full Changelog](https://github.com/matrix-org/matrix-js-sdk/compare/v0.7.3...v0.7.4-rc.1)
* Remove babel-polyfill
[\#321](https://github.com/matrix-org/matrix-js-sdk/pull/321)
* Update build process for ES6
[\#320](https://github.com/matrix-org/matrix-js-sdk/pull/320)
* 'babel' is not a babel package anymore
[\#319](https://github.com/matrix-org/matrix-js-sdk/pull/319)
* Add Babel for ES6 support
[\#318](https://github.com/matrix-org/matrix-js-sdk/pull/318)
* Move screen sharing check/error
[\#317](https://github.com/matrix-org/matrix-js-sdk/pull/317)
* release.sh: Bail early if there are uncommitted changes
[\#316](https://github.com/matrix-org/matrix-js-sdk/pull/316)
Changes in [0.7.3](https://github.com/matrix-org/matrix-js-sdk/releases/tag/v0.7.3) (2017-01-04) Changes in [0.7.3](https://github.com/matrix-org/matrix-js-sdk/releases/tag/v0.7.3) (2017-01-04)
================================================================================================ ================================================================================================
[Full Changelog](https://github.com/matrix-org/matrix-js-sdk/compare/v0.7.2...v0.7.3) [Full Changelog](https://github.com/matrix-org/matrix-js-sdk/compare/v0.7.2...v0.7.3)

View File

@@ -1,9 +1,12 @@
#!/bin/bash -l #!/bin/bash -l
set -x
export NVM_DIR="/home/jenkins/.nvm" export NVM_DIR="/home/jenkins/.nvm"
[ -s "$NVM_DIR/nvm.sh" ] && . "$NVM_DIR/nvm.sh" [ -s "$NVM_DIR/nvm.sh" ] && . "$NVM_DIR/nvm.sh"
nvm use 6
npm install nvm use 6 || exit $?
npm install || exit $?
RC=0 RC=0

View File

@@ -1,18 +1,19 @@
{ {
"name": "matrix-js-sdk", "name": "matrix-js-sdk",
"version": "0.7.3", "version": "0.7.4",
"description": "Matrix Client-Server SDK for Javascript", "description": "Matrix Client-Server SDK for Javascript",
"main": "index.js", "main": "index.js",
"scripts": { "scripts": {
"test": "istanbul cover --report cobertura --config .istanbul.yml -i \"lib/**/*.js\" jasmine-node -- spec --verbose --junitreport --captureExceptions", "buildtest": "babel -s -d specbuild spec",
"check": "jasmine-node spec --verbose --junitreport --captureExceptions", "test": "npm run buildtest && istanbul cover --report cobertura --config .istanbul.yml -i \"lib/**/*.js\" jasmine-node -- specbuild --verbose --junitreport --captureExceptions",
"check": "npm run buildtest && jasmine-node specbuild --verbose --junitreport --captureExceptions",
"gendoc": "jsdoc -r lib -P package.json -R README.md -d .jsdoc", "gendoc": "jsdoc -r lib -P package.json -R README.md -d .jsdoc",
"start": "babel -s -w -d lib src", "start": "babel -s -w -d lib src",
"build": "babel -s -d lib src && rimraf dist && mkdir dist && browserify --exclude olm browser-index.js -o dist/browser-matrix.js --ignore-missing && uglifyjs -c -m -o dist/browser-matrix.min.js dist/browser-matrix.js", "build": "babel -s -d lib src && rimraf dist && mkdir dist && browserify --exclude olm browser-index.js -o dist/browser-matrix.js --ignore-missing && uglifyjs -c -m -o dist/browser-matrix.min.js dist/browser-matrix.js",
"dist": "npm run build", "dist": "npm run build",
"watch": "watchify --exclude olm browser-index.js -o dist/browser-matrix-dev.js -v", "watch": "watchify --exclude olm browser-index.js -o dist/browser-matrix-dev.js -v",
"lint": "eslint --max-warnings 146 src spec", "lint": "eslint --max-warnings 121 src spec",
"prepublish": "npm run lint && npm run build && git rev-parse HEAD > git-revision.txt" "prepublish": "npm run build && git rev-parse HEAD > git-revision.txt"
}, },
"repository": { "repository": {
"url": "https://github.com/matrix-org/matrix-js-sdk" "url": "https://github.com/matrix-org/matrix-js-sdk"
@@ -52,6 +53,7 @@
}, },
"devDependencies": { "devDependencies": {
"babel-cli": "^6.18.0", "babel-cli": "^6.18.0",
"babel-eslint": "^7.1.1",
"babel-preset-es2015": "^6.18.0", "babel-preset-es2015": "^6.18.0",
"eslint": "^3.13.1", "eslint": "^3.13.1",
"eslint-config-google": "^0.7.1", "eslint-config-google": "^0.7.1",
@@ -63,6 +65,6 @@
"watchify": "^3.2.1" "watchify": "^3.2.1"
}, },
"optionalDependencies": { "optionalDependencies": {
"olm": "https://matrix.org/packages/npm/olm/olm-2.1.0.tgz" "olm": "https://matrix.org/packages/npm/olm/olm-2.2.1.tgz"
} }
} }

View File

@@ -40,8 +40,8 @@ MockStorageApi.prototype = {
return this.keys[index]; return this.keys[index];
}, },
_recalc: function() { _recalc: function() {
let keys = []; const keys = [];
for (let k in this.data) { for (const k in this.data) {
if (!this.data.hasOwnProperty(k)) { if (!this.data.hasOwnProperty(k)) {
continue; continue;
} }

View File

@@ -1,21 +1,21 @@
"use strict"; "use strict";
let sdk = require("../.."); const sdk = require("../..");
let q = require("q"); const q = require("q");
let HttpBackend = require("../mock-request"); const HttpBackend = require("../mock-request");
let utils = require("../../lib/utils"); const utils = require("../../lib/utils");
let test_utils = require("../test-utils"); const testUtils = require("../test-utils");
let aliHttpBackend; let aliHttpBackend;
let bobHttpBackend; let bobHttpBackend;
let aliClient; let aliClient;
let roomId = "!room:localhost"; const roomId = "!room:localhost";
let aliUserId = "@ali:localhost"; const aliUserId = "@ali:localhost";
let aliDeviceId = "zxcvb"; const aliDeviceId = "zxcvb";
let aliAccessToken = "aseukfgwef"; const aliAccessToken = "aseukfgwef";
let bobClient; let bobClient;
let bobUserId = "@bob:localhost"; const bobUserId = "@bob:localhost";
let bobDeviceId = "bvcxz"; const bobDeviceId = "bvcxz";
let bobAccessToken = "fewgfkuesa"; const bobAccessToken = "fewgfkuesa";
let bobOneTimeKeys; let bobOneTimeKeys;
let aliDeviceKeys; let aliDeviceKeys;
let bobDeviceKeys; let bobDeviceKeys;
@@ -38,8 +38,8 @@ let bobMessages;
* {one_time_keys: {}, device_keys: {}} * {one_time_keys: {}, device_keys: {}}
*/ */
function expectKeyUpload(deviceId, httpBackend) { function expectKeyUpload(deviceId, httpBackend) {
let uploadPath = "/keys/upload/" + deviceId; const uploadPath = "/keys/upload/" + deviceId;
let keys = {}; const keys = {};
httpBackend.when("POST", uploadPath).respond(200, function(path, content) { httpBackend.when("POST", uploadPath).respond(200, function(path, content) {
expect(content.one_time_keys).not.toBeDefined(); expect(content.one_time_keys).not.toBeDefined();
@@ -53,7 +53,7 @@ function expectKeyUpload(deviceId, httpBackend) {
expect(content.one_time_keys).toBeDefined(); expect(content.one_time_keys).toBeDefined();
expect(content.one_time_keys).not.toEqual({}); expect(content.one_time_keys).not.toEqual({});
let count = 0; let count = 0;
for (let key in content.one_time_keys) { for (const key in content.one_time_keys) {
if (content.one_time_keys.hasOwnProperty(key)) { if (content.one_time_keys.hasOwnProperty(key)) {
count++; count++;
} }
@@ -105,7 +105,7 @@ function expectBobKeyUpload() {
} }
function bobUploadsKeys() { function bobUploadsKeys() {
bobClient.uploadKeys(5).catch(test_utils.failTest); bobClient.uploadKeys(5).catch(testUtils.failTest);
return expectBobKeyUpload(); return expectBobKeyUpload();
} }
@@ -119,11 +119,11 @@ function expectAliQueryKeys() {
// can't query keys before bob has uploaded them // can't query keys before bob has uploaded them
expect(bobDeviceKeys).toBeDefined(); expect(bobDeviceKeys).toBeDefined();
let bobKeys = {}; const bobKeys = {};
bobKeys[bobDeviceId] = bobDeviceKeys; bobKeys[bobDeviceId] = bobDeviceKeys;
aliHttpBackend.when("POST", "/keys/query").respond(200, function(path, content) { aliHttpBackend.when("POST", "/keys/query").respond(200, function(path, content) {
expect(content.device_keys[bobUserId]).toEqual({}); expect(content.device_keys[bobUserId]).toEqual({});
let result = {}; const result = {};
result[bobUserId] = bobKeys; result[bobUserId] = bobKeys;
return {device_keys: result}; return {device_keys: result};
}); });
@@ -139,11 +139,11 @@ function expectBobQueryKeys() {
// can't query keys before ali has uploaded them // can't query keys before ali has uploaded them
expect(aliDeviceKeys).toBeDefined(); expect(aliDeviceKeys).toBeDefined();
let aliKeys = {}; const aliKeys = {};
aliKeys[aliDeviceId] = aliDeviceKeys; aliKeys[aliDeviceId] = aliDeviceKeys;
bobHttpBackend.when("POST", "/keys/query").respond(200, function(path, content) { bobHttpBackend.when("POST", "/keys/query").respond(200, function(path, content) {
expect(content.device_keys[aliUserId]).toEqual({}); expect(content.device_keys[aliUserId]).toEqual({});
let result = {}; const result = {};
result[aliUserId] = aliKeys; result[aliUserId] = aliKeys;
return {device_keys: result}; return {device_keys: result};
}); });
@@ -160,16 +160,17 @@ function expectAliClaimKeys() {
expect(bobOneTimeKeys).toBeDefined(); expect(bobOneTimeKeys).toBeDefined();
aliHttpBackend.when("POST", "/keys/claim").respond(200, function(path, content) { aliHttpBackend.when("POST", "/keys/claim").respond(200, function(path, content) {
let claimType = content.one_time_keys[bobUserId][bobDeviceId]; const claimType = content.one_time_keys[bobUserId][bobDeviceId];
expect(claimType).toEqual("signed_curve25519"); expect(claimType).toEqual("signed_curve25519");
for (var keyId in bobOneTimeKeys) { let keyId = null;
for (keyId in bobOneTimeKeys) {
if (bobOneTimeKeys.hasOwnProperty(keyId)) { if (bobOneTimeKeys.hasOwnProperty(keyId)) {
if (keyId.indexOf(claimType + ":") === 0) { if (keyId.indexOf(claimType + ":") === 0) {
break; break;
} }
} }
} }
let result = {}; const result = {};
result[bobUserId] = {}; result[bobUserId] = {};
result[bobUserId][bobDeviceId] = {}; result[bobUserId][bobDeviceId] = {};
result[bobUserId][bobDeviceId][keyId] = bobOneTimeKeys[keyId]; result[bobUserId][bobDeviceId][keyId] = bobOneTimeKeys[keyId];
@@ -184,7 +185,7 @@ function aliDownloadsKeys() {
// can't query keys before bob has uploaded them // can't query keys before bob has uploaded them
expect(bobDeviceEd25519Key).toBeDefined(); expect(bobDeviceEd25519Key).toBeDefined();
let p1 = aliClient.downloadKeys([bobUserId]).then(function() { const p1 = aliClient.downloadKeys([bobUserId]).then(function() {
expect(aliClient.listDeviceKeys(bobUserId)).toEqual([{ expect(aliClient.listDeviceKeys(bobUserId)).toEqual([{
id: "bvcxz", id: "bvcxz",
key: bobDeviceEd25519Key, key: bobDeviceEd25519Key,
@@ -193,12 +194,12 @@ function aliDownloadsKeys() {
display_name: null, display_name: null,
}]); }]);
}); });
let p2 = expectAliQueryKeys(); const p2 = expectAliQueryKeys();
// check that the localStorage is updated as we expect (not sure this is // check that the localStorage is updated as we expect (not sure this is
// an integration test, but meh) // an integration test, but meh)
return q.all([p1, p2]).then(function() { return q.all([p1, p2]).then(function() {
let devices = aliStorage.getEndToEndDevicesForUser(bobUserId); const devices = aliStorage.getEndToEndDevicesForUser(bobUserId);
expect(devices[bobDeviceId].keys).toEqual(bobDeviceKeys.keys); expect(devices[bobDeviceId].keys).toEqual(bobDeviceKeys.keys);
expect(devices[bobDeviceId].verified). expect(devices[bobDeviceId].verified).
toBe(0); // DeviceVerification.UNVERIFIED toBe(0); // DeviceVerification.UNVERIFIED
@@ -278,7 +279,7 @@ function expectAliSendMessageRequest() {
return expectSendMessageRequest(aliHttpBackend).then(function(content) { return expectSendMessageRequest(aliHttpBackend).then(function(content) {
aliMessages.push(content); aliMessages.push(content);
expect(utils.keys(content.ciphertext)).toEqual([bobDeviceCurve25519Key]); expect(utils.keys(content.ciphertext)).toEqual([bobDeviceCurve25519Key]);
let ciphertext = content.ciphertext[bobDeviceCurve25519Key]; const ciphertext = content.ciphertext[bobDeviceCurve25519Key];
expect(ciphertext).toBeDefined(); expect(ciphertext).toBeDefined();
return ciphertext; return ciphertext;
}); });
@@ -292,10 +293,10 @@ function expectAliSendMessageRequest() {
function expectBobSendMessageRequest() { function expectBobSendMessageRequest() {
return expectSendMessageRequest(bobHttpBackend).then(function(content) { return expectSendMessageRequest(bobHttpBackend).then(function(content) {
bobMessages.push(content); bobMessages.push(content);
let aliKeyId = "curve25519:" + aliDeviceId; const aliKeyId = "curve25519:" + aliDeviceId;
let aliDeviceCurve25519Key = aliDeviceKeys.keys[aliKeyId]; const aliDeviceCurve25519Key = aliDeviceKeys.keys[aliKeyId];
expect(utils.keys(content.ciphertext)).toEqual([aliDeviceCurve25519Key]); expect(utils.keys(content.ciphertext)).toEqual([aliDeviceCurve25519Key]);
let ciphertext = content.ciphertext[aliDeviceCurve25519Key]; const ciphertext = content.ciphertext[aliDeviceCurve25519Key];
expect(ciphertext).toBeDefined(); expect(ciphertext).toBeDefined();
return ciphertext; return ciphertext;
}); });
@@ -303,12 +304,12 @@ function expectBobSendMessageRequest() {
function sendMessage(client) { function sendMessage(client) {
return client.sendMessage( return client.sendMessage(
roomId, {msgtype: "m.text", body: "Hello, World"} roomId, {msgtype: "m.text", body: "Hello, World"},
); );
} }
function expectSendMessageRequest(httpBackend) { function expectSendMessageRequest(httpBackend) {
let path = "/send/m.room.encrypted/"; const path = "/send/m.room.encrypted/";
let sent; let sent;
httpBackend.when("PUT", path).respond(200, function(path, content) { httpBackend.when("PUT", path).respond(200, function(path, content) {
sent = content; sent = content;
@@ -322,17 +323,17 @@ function expectSendMessageRequest(httpBackend) {
} }
function aliRecvMessage() { function aliRecvMessage() {
let message = bobMessages.shift(); const message = bobMessages.shift();
return recvMessage(aliHttpBackend, aliClient, bobUserId, message); return recvMessage(aliHttpBackend, aliClient, bobUserId, message);
} }
function bobRecvMessage() { function bobRecvMessage() {
let message = aliMessages.shift(); const message = aliMessages.shift();
return recvMessage(bobHttpBackend, bobClient, aliUserId, message); return recvMessage(bobHttpBackend, bobClient, aliUserId, message);
} }
function recvMessage(httpBackend, client, sender, message) { function recvMessage(httpBackend, client, sender, message) {
let syncData = { const syncData = {
next_batch: "x", next_batch: "x",
rooms: { rooms: {
join: { join: {
@@ -343,7 +344,7 @@ function recvMessage(httpBackend, client, sender, message) {
syncData.rooms.join[roomId] = { syncData.rooms.join[roomId] = {
timeline: { timeline: {
events: [ events: [
test_utils.mkEvent({ testUtils.mkEvent({
type: "m.room.encrypted", type: "m.room.encrypted",
room: roomId, room: roomId,
content: message, content: message,
@@ -353,8 +354,8 @@ function recvMessage(httpBackend, client, sender, message) {
}, },
}; };
httpBackend.when("GET", "/sync").respond(200, syncData); httpBackend.when("GET", "/sync").respond(200, syncData);
let deferred = q.defer(); const deferred = q.defer();
let onEvent = function(event) { const onEvent = function(event) {
console.log(client.credentials.userId + " received event", console.log(client.credentials.userId + " received event",
event); event);
@@ -382,12 +383,12 @@ function recvMessage(httpBackend, client, sender, message) {
function aliStartClient() { function aliStartClient() {
expectAliKeyUpload().catch(test_utils.failTest); expectAliKeyUpload().catch(testUtils.failTest);
// ali will try to query her own keys on start // ali will try to query her own keys on start
aliHttpBackend.when("POST", "/keys/query").respond(200, function(path, content) { aliHttpBackend.when("POST", "/keys/query").respond(200, function(path, content) {
expect(content.device_keys[aliUserId]).toEqual({}); expect(content.device_keys[aliUserId]).toEqual({});
let result = {}; const result = {};
result[aliUserId] = {}; result[aliUserId] = {};
return {device_keys: result}; return {device_keys: result};
}); });
@@ -399,12 +400,12 @@ function aliStartClient() {
} }
function bobStartClient() { function bobStartClient() {
expectBobKeyUpload().catch(test_utils.failTest); expectBobKeyUpload().catch(testUtils.failTest);
// bob will try to query his own keys on start // bob will try to query his own keys on start
bobHttpBackend.when("POST", "/keys/query").respond(200, function(path, content) { bobHttpBackend.when("POST", "/keys/query").respond(200, function(path, content) {
expect(content.device_keys[bobUserId]).toEqual({}); expect(content.device_keys[bobUserId]).toEqual({});
let result = {}; const result = {};
result[bobUserId] = {}; result[bobUserId] = {};
return {device_keys: result}; return {device_keys: result};
}); });
@@ -428,7 +429,7 @@ function startClient(httpBackend, client) {
httpBackend.when("POST", "/filter").respond(200, { filter_id: "fid" }); httpBackend.when("POST", "/filter").respond(200, { filter_id: "fid" });
// send a sync response including our test room. // send a sync response including our test room.
let syncData = { const syncData = {
next_batch: "x", next_batch: "x",
rooms: { rooms: {
join: { }, join: { },
@@ -437,11 +438,11 @@ function startClient(httpBackend, client) {
syncData.rooms.join[roomId] = { syncData.rooms.join[roomId] = {
state: { state: {
events: [ events: [
test_utils.mkMembership({ testUtils.mkMembership({
mship: "join", mship: "join",
user: aliUserId, user: aliUserId,
}), }),
test_utils.mkMembership({ testUtils.mkMembership({
mship: "join", mship: "join",
user: bobUserId, user: bobUserId,
}), }),
@@ -463,9 +464,9 @@ describe("MatrixClient crypto", function() {
} }
beforeEach(function() { beforeEach(function() {
test_utils.beforeEach(this); // eslint-disable-line no-invalid-this testUtils.beforeEach(this); // eslint-disable-line no-invalid-this
aliStorage = new sdk.WebStorageSessionStore(new test_utils.MockStorageApi()); aliStorage = new sdk.WebStorageSessionStore(new testUtils.MockStorageApi());
aliHttpBackend = new HttpBackend(); aliHttpBackend = new HttpBackend();
aliClient = sdk.createClient({ aliClient = sdk.createClient({
baseUrl: "http://alis.server", baseUrl: "http://alis.server",
@@ -476,7 +477,7 @@ describe("MatrixClient crypto", function() {
request: aliHttpBackend.requestFn, request: aliHttpBackend.requestFn,
}); });
bobStorage = new sdk.WebStorageSessionStore(new test_utils.MockStorageApi()); bobStorage = new sdk.WebStorageSessionStore(new testUtils.MockStorageApi());
bobHttpBackend = new HttpBackend(); bobHttpBackend = new HttpBackend();
bobClient = sdk.createClient({ bobClient = sdk.createClient({
baseUrl: "http://bobs.server", baseUrl: "http://bobs.server",
@@ -509,30 +510,30 @@ describe("MatrixClient crypto", function() {
}, },
}); });
let p1 = aliClient.downloadKeys(['@bob:id']); const p1 = aliClient.downloadKeys(['@bob:id']);
let p2 = aliHttpBackend.flush('/keys/query', 1); const p2 = aliHttpBackend.flush('/keys/query', 1);
q.all([p1, p2]).then(function() { q.all([p1, p2]).then(function() {
let devices = aliStorage.getEndToEndDevicesForUser('@bob:id'); const devices = aliStorage.getEndToEndDevicesForUser('@bob:id');
expect(utils.keys(devices).length).toEqual(0); expect(utils.keys(devices).length).toEqual(0);
// request again: should be no more requests // request again: should be no more requests
return aliClient.downloadKeys(['@bob:id']); return aliClient.downloadKeys(['@bob:id']);
}).nodeify(done); }).nodeify(done);
} },
); );
it("Bob uploads without one-time keys and with one-time keys", function(done) { it("Bob uploads without one-time keys and with one-time keys", function(done) {
q() q()
.then(bobUploadsKeys) .then(bobUploadsKeys)
.catch(test_utils.failTest).done(done); .catch(testUtils.failTest).done(done);
}); });
it("Ali downloads Bobs keys", function(done) { it("Ali downloads Bobs keys", function(done) {
q() q()
.then(bobUploadsKeys) .then(bobUploadsKeys)
.then(aliDownloadsKeys) .then(aliDownloadsKeys)
.catch(test_utils.failTest).done(done); .catch(testUtils.failTest).done(done);
}); });
it("Ali gets keys with an invalid signature", function(done) { it("Ali gets keys with an invalid signature", function(done) {
@@ -550,13 +551,13 @@ describe("MatrixClient crypto", function() {
// should get an empty list // should get an empty list
expect(aliClient.listDeviceKeys(bobUserId)).toEqual([]); expect(aliClient.listDeviceKeys(bobUserId)).toEqual([]);
}) })
.catch(test_utils.failTest).done(done); .catch(testUtils.failTest).done(done);
}); });
it("Ali gets keys with an incorrect userId", function(done) { it("Ali gets keys with an incorrect userId", function(done) {
let eveUserId = "@eve:localhost"; const eveUserId = "@eve:localhost";
let bobDeviceKeys = { const bobDeviceKeys = {
algorithms: ['m.olm.v1.curve25519-aes-sha2', 'm.megolm.v1.aes-sha2'], algorithms: ['m.olm.v1.curve25519-aes-sha2', 'm.megolm.v1.aes-sha2'],
device_id: 'bvcxz', device_id: 'bvcxz',
keys: { keys: {
@@ -572,26 +573,26 @@ describe("MatrixClient crypto", function() {
}, },
}; };
let bobKeys = {}; const bobKeys = {};
bobKeys[bobDeviceId] = bobDeviceKeys; bobKeys[bobDeviceId] = bobDeviceKeys;
aliHttpBackend.when("POST", "/keys/query").respond(200, function(path, content) { aliHttpBackend.when("POST", "/keys/query").respond(200, function(path, content) {
let result = {}; const result = {};
result[bobUserId] = bobKeys; result[bobUserId] = bobKeys;
return {device_keys: result}; return {device_keys: result};
}); });
q.all( q.all(
aliClient.downloadKeys([bobUserId, eveUserId]), aliClient.downloadKeys([bobUserId, eveUserId]),
aliHttpBackend.flush("/keys/query", 1) aliHttpBackend.flush("/keys/query", 1),
).then(function() { ).then(function() {
// should get an empty list // should get an empty list
expect(aliClient.listDeviceKeys(bobUserId)).toEqual([]); expect(aliClient.listDeviceKeys(bobUserId)).toEqual([]);
expect(aliClient.listDeviceKeys(eveUserId)).toEqual([]); expect(aliClient.listDeviceKeys(eveUserId)).toEqual([]);
}).catch(test_utils.failTest).done(done); }).catch(testUtils.failTest).done(done);
}); });
it("Ali gets keys with an incorrect deviceId", function(done) { it("Ali gets keys with an incorrect deviceId", function(done) {
let bobDeviceKeys = { const bobDeviceKeys = {
algorithms: ['m.olm.v1.curve25519-aes-sha2', 'm.megolm.v1.aes-sha2'], algorithms: ['m.olm.v1.curve25519-aes-sha2', 'm.megolm.v1.aes-sha2'],
device_id: 'bad_device', device_id: 'bad_device',
keys: { keys: {
@@ -607,21 +608,21 @@ describe("MatrixClient crypto", function() {
}, },
}; };
let bobKeys = {}; const bobKeys = {};
bobKeys[bobDeviceId] = bobDeviceKeys; bobKeys[bobDeviceId] = bobDeviceKeys;
aliHttpBackend.when("POST", "/keys/query").respond(200, function(path, content) { aliHttpBackend.when("POST", "/keys/query").respond(200, function(path, content) {
let result = {}; const result = {};
result[bobUserId] = bobKeys; result[bobUserId] = bobKeys;
return {device_keys: result}; return {device_keys: result};
}); });
q.all( q.all(
aliClient.downloadKeys([bobUserId]), aliClient.downloadKeys([bobUserId]),
aliHttpBackend.flush("/keys/query", 1) aliHttpBackend.flush("/keys/query", 1),
).then(function() { ).then(function() {
// should get an empty list // should get an empty list
expect(aliClient.listDeviceKeys(bobUserId)).toEqual([]); expect(aliClient.listDeviceKeys(bobUserId)).toEqual([]);
}).catch(test_utils.failTest).done(done); }).catch(testUtils.failTest).done(done);
}); });
it("Ali enables encryption", function(done) { it("Ali enables encryption", function(done) {
@@ -629,7 +630,7 @@ describe("MatrixClient crypto", function() {
.then(bobUploadsKeys) .then(bobUploadsKeys)
.then(aliStartClient) .then(aliStartClient)
.then(aliEnablesEncryption) .then(aliEnablesEncryption)
.catch(test_utils.failTest).done(done); .catch(testUtils.failTest).done(done);
}); });
it("Ali sends a message", function(done) { it("Ali sends a message", function(done) {
@@ -638,7 +639,7 @@ describe("MatrixClient crypto", function() {
.then(aliStartClient) .then(aliStartClient)
.then(aliEnablesEncryption) .then(aliEnablesEncryption)
.then(aliSendsFirstMessage) .then(aliSendsFirstMessage)
.catch(test_utils.failTest).nodeify(done); .catch(testUtils.failTest).nodeify(done);
}); });
it("Bob receives a message", function(done) { it("Bob receives a message", function(done) {
@@ -649,7 +650,7 @@ describe("MatrixClient crypto", function() {
.then(aliSendsFirstMessage) .then(aliSendsFirstMessage)
.then(bobStartClient) .then(bobStartClient)
.then(bobRecvMessage) .then(bobRecvMessage)
.catch(test_utils.failTest).done(done); .catch(testUtils.failTest).done(done);
}); });
it("Bob receives a message with a bogus sender", function(done) { it("Bob receives a message with a bogus sender", function(done) {
@@ -660,8 +661,8 @@ describe("MatrixClient crypto", function() {
.then(aliSendsFirstMessage) .then(aliSendsFirstMessage)
.then(bobStartClient) .then(bobStartClient)
.then(function() { .then(function() {
let message = aliMessages.shift(); const message = aliMessages.shift();
let syncData = { const syncData = {
next_batch: "x", next_batch: "x",
rooms: { rooms: {
join: { join: {
@@ -672,7 +673,7 @@ describe("MatrixClient crypto", function() {
syncData.rooms.join[roomId] = { syncData.rooms.join[roomId] = {
timeline: { timeline: {
events: [ events: [
test_utils.mkEvent({ testUtils.mkEvent({
type: "m.room.encrypted", type: "m.room.encrypted",
room: roomId, room: roomId,
content: message, content: message,
@@ -683,8 +684,8 @@ describe("MatrixClient crypto", function() {
}; };
bobHttpBackend.when("GET", "/sync").respond(200, syncData); bobHttpBackend.when("GET", "/sync").respond(200, syncData);
let deferred = q.defer(); const deferred = q.defer();
let onEvent = function(event) { const onEvent = function(event) {
console.log(bobClient.credentials.userId + " received event", console.log(bobClient.credentials.userId + " received event",
event); event);
@@ -706,7 +707,7 @@ describe("MatrixClient crypto", function() {
bobHttpBackend.flush(); bobHttpBackend.flush();
return deferred.promise; return deferred.promise;
}) })
.catch(test_utils.failTest).done(done); .catch(testUtils.failTest).done(done);
}); });
it("Ali blocks Bob's device", function(done) { it("Ali blocks Bob's device", function(done) {
@@ -717,8 +718,8 @@ describe("MatrixClient crypto", function() {
.then(aliDownloadsKeys) .then(aliDownloadsKeys)
.then(function() { .then(function() {
aliClient.setDeviceBlocked(bobUserId, bobDeviceId, true); aliClient.setDeviceBlocked(bobUserId, bobDeviceId, true);
let p1 = sendMessage(aliClient); const p1 = sendMessage(aliClient);
let p2 = expectAliQueryKeys() const p2 = expectAliQueryKeys()
.then(expectAliClaimKeys) .then(expectAliClaimKeys)
.then(function() { .then(function() {
return expectSendMessageRequest(aliHttpBackend); return expectSendMessageRequest(aliHttpBackend);
@@ -727,7 +728,7 @@ describe("MatrixClient crypto", function() {
expect(sentContent.ciphertext).toEqual({}); expect(sentContent.ciphertext).toEqual({});
}); });
return q.all([p1, p2]); return q.all([p1, p2]);
}).catch(test_utils.failTest).nodeify(done); }).catch(testUtils.failTest).nodeify(done);
}); });
it("Bob receives two pre-key messages", function(done) { it("Bob receives two pre-key messages", function(done) {
@@ -740,7 +741,7 @@ describe("MatrixClient crypto", function() {
.then(bobRecvMessage) .then(bobRecvMessage)
.then(aliSendsMessage) .then(aliSendsMessage)
.then(bobRecvMessage) .then(bobRecvMessage)
.catch(test_utils.failTest).done(done); .catch(testUtils.failTest).done(done);
}); });
it("Bob replies to the message", function(done) { it("Bob replies to the message", function(done) {
@@ -755,7 +756,7 @@ describe("MatrixClient crypto", function() {
.then(bobSendsReplyMessage).then(function(ciphertext) { .then(bobSendsReplyMessage).then(function(ciphertext) {
expect(ciphertext.type).toEqual(1); expect(ciphertext.type).toEqual(1);
}).then(aliRecvMessage) }).then(aliRecvMessage)
.catch(test_utils.failTest).done(done); .catch(testUtils.failTest).done(done);
}); });
@@ -764,11 +765,11 @@ describe("MatrixClient crypto", function() {
.then(bobUploadsKeys) .then(bobUploadsKeys)
.then(aliStartClient) .then(aliStartClient)
.then(function() { .then(function() {
let syncData = { const syncData = {
next_batch: '2', next_batch: '2',
to_device: { to_device: {
events: [ events: [
test_utils.mkEvent({ testUtils.mkEvent({
content: { content: {
device_id: 'TEST_DEVICE', device_id: 'TEST_DEVICE',
rooms: [], rooms: [],

View File

@@ -1,14 +1,14 @@
"use strict"; "use strict";
let sdk = require("../.."); const sdk = require("../..");
let HttpBackend = require("../mock-request"); const HttpBackend = require("../mock-request");
let utils = require("../test-utils"); const utils = require("../test-utils");
describe("MatrixClient events", function() { describe("MatrixClient events", function() {
let baseUrl = "http://localhost.or.something"; const baseUrl = "http://localhost.or.something";
let client; let client;
let httpBackend; let httpBackend;
let selfUserId = "@alice:localhost"; const selfUserId = "@alice:localhost";
let selfAccessToken = "aseukfgwef"; const selfAccessToken = "aseukfgwef";
beforeEach(function() { beforeEach(function() {
utils.beforeEach(this); // eslint-disable-line no-invalid-this utils.beforeEach(this); // eslint-disable-line no-invalid-this
@@ -29,7 +29,7 @@ describe("MatrixClient events", function() {
}); });
describe("emissions", function() { describe("emissions", function() {
let SYNC_DATA = { const SYNC_DATA = {
next_batch: "s_5_3", next_batch: "s_5_3",
presence: { presence: {
events: [ events: [
@@ -67,7 +67,7 @@ describe("MatrixClient events", function() {
}, },
}, },
}; };
let NEXT_SYNC_DATA = { const NEXT_SYNC_DATA = {
next_batch: "e_6_7", next_batch: "e_6_7",
rooms: { rooms: {
join: { join: {
@@ -108,7 +108,7 @@ describe("MatrixClient events", function() {
SYNC_DATA.rooms.join["!erufh:bar"].timeline.events, SYNC_DATA.rooms.join["!erufh:bar"].timeline.events,
SYNC_DATA.rooms.join["!erufh:bar"].state.events, SYNC_DATA.rooms.join["!erufh:bar"].state.events,
NEXT_SYNC_DATA.rooms.join["!erufh:bar"].timeline.events, NEXT_SYNC_DATA.rooms.join["!erufh:bar"].timeline.events,
NEXT_SYNC_DATA.rooms.join["!erufh:bar"].ephemeral.events NEXT_SYNC_DATA.rooms.join["!erufh:bar"].ephemeral.events,
); );
client.on("event", function(event) { client.on("event", function(event) {
@@ -121,7 +121,7 @@ describe("MatrixClient events", function() {
} }
} }
expect(found).toBe( expect(found).toBe(
true, "Unexpected 'event' emitted: " + event.getType() true, "Unexpected 'event' emitted: " + event.getType(),
); );
}); });
@@ -129,7 +129,7 @@ describe("MatrixClient events", function() {
httpBackend.flush().done(function() { httpBackend.flush().done(function() {
expect(expectedEvents.length).toEqual( expect(expectedEvents.length).toEqual(
0, "Failed to see all events from /sync calls" 0, "Failed to see all events from /sync calls",
); );
done(); done();
}); });
@@ -149,7 +149,7 @@ describe("MatrixClient events", function() {
expect(event.event).toEqual(SYNC_DATA.presence.events[0]); expect(event.event).toEqual(SYNC_DATA.presence.events[0]);
expect(user.presence).toEqual( expect(user.presence).toEqual(
SYNC_DATA.presence.events[0].content.presence SYNC_DATA.presence.events[0].content.presence,
); );
}); });
client.startClient(); client.startClient();
@@ -182,13 +182,13 @@ describe("MatrixClient events", function() {
httpBackend.flush().done(function() { httpBackend.flush().done(function() {
expect(roomInvokeCount).toEqual( expect(roomInvokeCount).toEqual(
1, "Room fired wrong number of times." 1, "Room fired wrong number of times.",
); );
expect(roomNameInvokeCount).toEqual( expect(roomNameInvokeCount).toEqual(
1, "Room.name fired wrong number of times." 1, "Room.name fired wrong number of times.",
); );
expect(timelineFireCount).toEqual( expect(timelineFireCount).toEqual(
3, "Room.timeline fired the wrong number of times" 3, "Room.timeline fired the wrong number of times",
); );
done(); done();
}); });
@@ -198,7 +198,7 @@ describe("MatrixClient events", function() {
httpBackend.when("GET", "/sync").respond(200, SYNC_DATA); httpBackend.when("GET", "/sync").respond(200, SYNC_DATA);
httpBackend.when("GET", "/sync").respond(200, NEXT_SYNC_DATA); httpBackend.when("GET", "/sync").respond(200, NEXT_SYNC_DATA);
let roomStateEventTypes = [ const roomStateEventTypes = [
"m.room.member", "m.room.create", "m.room.member", "m.room.create",
]; ];
let eventsInvokeCount = 0; let eventsInvokeCount = 0;
@@ -206,9 +206,9 @@ describe("MatrixClient events", function() {
let newMemberInvokeCount = 0; let newMemberInvokeCount = 0;
client.on("RoomState.events", function(event, state) { client.on("RoomState.events", function(event, state) {
eventsInvokeCount++; eventsInvokeCount++;
let index = roomStateEventTypes.indexOf(event.getType()); const index = roomStateEventTypes.indexOf(event.getType());
expect(index).not.toEqual( expect(index).not.toEqual(
-1, "Unexpected room state event type: " + event.getType() -1, "Unexpected room state event type: " + event.getType(),
); );
if (index >= 0) { if (index >= 0) {
roomStateEventTypes.splice(index, 1); roomStateEventTypes.splice(index, 1);
@@ -231,13 +231,13 @@ describe("MatrixClient events", function() {
httpBackend.flush().done(function() { httpBackend.flush().done(function() {
expect(membersInvokeCount).toEqual( expect(membersInvokeCount).toEqual(
1, "RoomState.members fired wrong number of times" 1, "RoomState.members fired wrong number of times",
); );
expect(newMemberInvokeCount).toEqual( expect(newMemberInvokeCount).toEqual(
1, "RoomState.newMember fired wrong number of times" 1, "RoomState.newMember fired wrong number of times",
); );
expect(eventsInvokeCount).toEqual( expect(eventsInvokeCount).toEqual(
2, "RoomState.events fired wrong number of times" 2, "RoomState.events fired wrong number of times",
); );
done(); done();
}); });
@@ -270,16 +270,16 @@ describe("MatrixClient events", function() {
httpBackend.flush().done(function() { httpBackend.flush().done(function() {
expect(typingInvokeCount).toEqual( expect(typingInvokeCount).toEqual(
1, "RoomMember.typing fired wrong number of times" 1, "RoomMember.typing fired wrong number of times",
); );
expect(powerLevelInvokeCount).toEqual( expect(powerLevelInvokeCount).toEqual(
0, "RoomMember.powerLevel fired wrong number of times" 0, "RoomMember.powerLevel fired wrong number of times",
); );
expect(nameInvokeCount).toEqual( expect(nameInvokeCount).toEqual(
0, "RoomMember.name fired wrong number of times" 0, "RoomMember.name fired wrong number of times",
); );
expect(membershipInvokeCount).toEqual( expect(membershipInvokeCount).toEqual(
1, "RoomMember.membership fired wrong number of times" 1, "RoomMember.membership fired wrong number of times",
); );
done(); done();
}); });
@@ -297,7 +297,7 @@ describe("MatrixClient events", function() {
httpBackend.flush().done(function() { httpBackend.flush().done(function() {
expect(sessionLoggedOutCount).toEqual( expect(sessionLoggedOutCount).toEqual(
1, "Session.logged_out fired wrong number of times" 1, "Session.logged_out fired wrong number of times",
); );
done(); done();
}); });

View File

@@ -1,29 +1,29 @@
"use strict"; "use strict";
let q = require("q"); const q = require("q");
let sdk = require("../.."); const sdk = require("../..");
let HttpBackend = require("../mock-request"); const HttpBackend = require("../mock-request");
let utils = require("../test-utils"); const utils = require("../test-utils");
let EventTimeline = sdk.EventTimeline; const EventTimeline = sdk.EventTimeline;
let baseUrl = "http://localhost.or.something"; const baseUrl = "http://localhost.or.something";
let userId = "@alice:localhost"; const userId = "@alice:localhost";
let userName = "Alice"; const userName = "Alice";
let accessToken = "aseukfgwef"; const accessToken = "aseukfgwef";
let roomId = "!foo:bar"; const roomId = "!foo:bar";
let otherUserId = "@bob:localhost"; const otherUserId = "@bob:localhost";
let USER_MEMBERSHIP_EVENT = utils.mkMembership({ const USER_MEMBERSHIP_EVENT = utils.mkMembership({
room: roomId, mship: "join", user: userId, name: userName, room: roomId, mship: "join", user: userId, name: userName,
}); });
let ROOM_NAME_EVENT = utils.mkEvent({ const ROOM_NAME_EVENT = utils.mkEvent({
type: "m.room.name", room: roomId, user: otherUserId, type: "m.room.name", room: roomId, user: otherUserId,
content: { content: {
name: "Old room name", name: "Old room name",
}, },
}); });
let INITIAL_SYNC_DATA = { const INITIAL_SYNC_DATA = {
next_batch: "s_5_3", next_batch: "s_5_3",
rooms: { rooms: {
join: { join: {
@@ -57,7 +57,7 @@ let INITIAL_SYNC_DATA = {
}, },
}; };
let EVENTS = [ const EVENTS = [
utils.mkMessage({ utils.mkMessage({
room: roomId, user: userId, msg: "we", room: roomId, user: userId, msg: "we",
}), }),
@@ -81,7 +81,7 @@ function startClient(httpBackend, client) {
client.startClient(); client.startClient();
// set up a promise which will resolve once the client is initialised // set up a promise which will resolve once the client is initialised
let deferred = q.defer(); const deferred = q.defer();
client.on("sync", function(state) { client.on("sync", function(state) {
console.log("sync", state); console.log("sync", state);
if (state != "SYNCING") { if (state != "SYNCING") {
@@ -118,10 +118,10 @@ describe("getEventTimeline support", function() {
accessToken: accessToken, accessToken: accessToken,
}); });
startClient(httpBackend, client startClient(httpBackend, client,
).then(function() { ).then(function() {
let room = client.getRoom(roomId); const room = client.getRoom(roomId);
let timelineSet = room.getTimelineSets()[0]; const timelineSet = room.getTimelineSets()[0];
expect(function() { expect(function() {
client.getEventTimeline(timelineSet, "event"); client.getEventTimeline(timelineSet, "event");
}).toThrow(); }).toThrow();
@@ -136,10 +136,10 @@ describe("getEventTimeline support", function() {
timelineSupport: true, timelineSupport: true,
}); });
startClient(httpBackend, client startClient(httpBackend, client,
).then(function() { ).then(function() {
let room = client.getRoom(roomId); const room = client.getRoom(roomId);
let timelineSet = room.getTimelineSets()[0]; const timelineSet = room.getTimelineSets()[0];
expect(function() { expect(function() {
client.getEventTimeline(timelineSet, "event"); client.getEventTimeline(timelineSet, "event");
}).not.toThrow(); }).not.toThrow();
@@ -159,7 +159,7 @@ describe("getEventTimeline support", function() {
}); });
let room; let room;
startClient(httpBackend, client startClient(httpBackend, client,
).then(function() { ).then(function() {
room = client.getRoom(roomId); room = client.getRoom(roomId);
@@ -220,7 +220,8 @@ describe("getEventTimeline support", function() {
}); });
describe("MatrixClient event timelines", function() { describe("MatrixClient event timelines", function() {
let client, httpBackend; let client = null;
let httpBackend = null;
beforeEach(function(done) { beforeEach(function(done) {
utils.beforeEach(this); // eslint-disable-line no-invalid-this utils.beforeEach(this); // eslint-disable-line no-invalid-this
@@ -245,8 +246,8 @@ describe("MatrixClient event timelines", function() {
describe("getEventTimeline", function() { describe("getEventTimeline", function() {
it("should create a new timeline for new events", function(done) { it("should create a new timeline for new events", function(done) {
let room = client.getRoom(roomId); const room = client.getRoom(roomId);
let timelineSet = room.getTimelineSets()[0]; const timelineSet = room.getTimelineSets()[0];
httpBackend.when("GET", "/rooms/!foo%3Abar/context/event1%3Abar") httpBackend.when("GET", "/rooms/!foo%3Abar/context/event1%3Abar")
.respond(200, function() { .respond(200, function() {
return { return {
@@ -278,8 +279,8 @@ describe("MatrixClient event timelines", function() {
}); });
it("should return existing timeline for known events", function(done) { it("should return existing timeline for known events", function(done) {
let room = client.getRoom(roomId); const room = client.getRoom(roomId);
let timelineSet = room.getTimelineSets()[0]; const timelineSet = room.getTimelineSets()[0];
httpBackend.when("GET", "/sync").respond(200, { httpBackend.when("GET", "/sync").respond(200, {
next_batch: "s_5_4", next_batch: "s_5_4",
rooms: { rooms: {
@@ -310,8 +311,8 @@ describe("MatrixClient event timelines", function() {
}); });
it("should update timelines where they overlap a previous /sync", function(done) { it("should update timelines where they overlap a previous /sync", function(done) {
let room = client.getRoom(roomId); const room = client.getRoom(roomId);
let timelineSet = room.getTimelineSets()[0]; const timelineSet = room.getTimelineSets()[0];
httpBackend.when("GET", "/sync").respond(200, { httpBackend.when("GET", "/sync").respond(200, {
next_batch: "s_5_4", next_batch: "s_5_4",
rooms: { rooms: {
@@ -342,7 +343,7 @@ describe("MatrixClient event timelines", function() {
}); });
client.on("sync", function() { client.on("sync", function() {
client.getEventTimeline(timelineSet, EVENTS[2].event_id client.getEventTimeline(timelineSet, EVENTS[2].event_id,
).then(function(tl) { ).then(function(tl) {
expect(tl.getEvents().length).toEqual(4); expect(tl.getEvents().length).toEqual(4);
expect(tl.getEvents()[0].event).toEqual(EVENTS[1]); expect(tl.getEvents()[0].event).toEqual(EVENTS[1]);
@@ -360,8 +361,8 @@ describe("MatrixClient event timelines", function() {
it("should join timelines where they overlap a previous /context", it("should join timelines where they overlap a previous /context",
function(done) { function(done) {
let room = client.getRoom(roomId); const room = client.getRoom(roomId);
let timelineSet = room.getTimelineSets()[0]; const timelineSet = room.getTimelineSets()[0];
// we fetch event 0, then 2, then 3, and finally 1. 1 is returned // we fetch event 0, then 2, then 3, and finally 1. 1 is returned
// with context which joins them all up. // with context which joins them all up.
@@ -417,8 +418,9 @@ describe("MatrixClient event timelines", function() {
}; };
}); });
let tl0, tl3; let tl0;
client.getEventTimeline(timelineSet, EVENTS[0].event_id let tl3;
client.getEventTimeline(timelineSet, EVENTS[0].event_id,
).then(function(tl) { ).then(function(tl) {
expect(tl.getEvents().length).toEqual(1); expect(tl.getEvents().length).toEqual(1);
tl0 = tl; tl0 = tl;
@@ -453,8 +455,8 @@ describe("MatrixClient event timelines", function() {
}); });
it("should fail gracefully if there is no event field", function(done) { it("should fail gracefully if there is no event field", function(done) {
let room = client.getRoom(roomId); const room = client.getRoom(roomId);
let timelineSet = room.getTimelineSets()[0]; const timelineSet = room.getTimelineSets()[0];
// we fetch event 0, then 2, then 3, and finally 1. 1 is returned // we fetch event 0, then 2, then 3, and finally 1. 1 is returned
// with context which joins them all up. // with context which joins them all up.
httpBackend.when("GET", "/rooms/!foo%3Abar/context/event1") httpBackend.when("GET", "/rooms/!foo%3Abar/context/event1")
@@ -468,7 +470,7 @@ describe("MatrixClient event timelines", function() {
}; };
}); });
client.getEventTimeline(timelineSet, "event1" client.getEventTimeline(timelineSet, "event1",
).then(function(tl) { ).then(function(tl) {
// could do with a fail() // could do with a fail()
expect(true).toBeFalsy(); expect(true).toBeFalsy();
@@ -482,8 +484,8 @@ describe("MatrixClient event timelines", function() {
describe("paginateEventTimeline", function() { describe("paginateEventTimeline", function() {
it("should allow you to paginate backwards", function(done) { it("should allow you to paginate backwards", function(done) {
let room = client.getRoom(roomId); const room = client.getRoom(roomId);
let timelineSet = room.getTimelineSets()[0]; const timelineSet = room.getTimelineSets()[0];
httpBackend.when("GET", "/rooms/!foo%3Abar/context/" + httpBackend.when("GET", "/rooms/!foo%3Abar/context/" +
encodeURIComponent(EVENTS[0].event_id)) encodeURIComponent(EVENTS[0].event_id))
@@ -500,7 +502,7 @@ describe("MatrixClient event timelines", function() {
httpBackend.when("GET", "/rooms/!foo%3Abar/messages") httpBackend.when("GET", "/rooms/!foo%3Abar/messages")
.check(function(req) { .check(function(req) {
let params = req.queryParams; const params = req.queryParams;
expect(params.dir).toEqual("b"); expect(params.dir).toEqual("b");
expect(params.from).toEqual("start_token0"); expect(params.from).toEqual("start_token0");
expect(params.limit).toEqual(30); expect(params.limit).toEqual(30);
@@ -512,7 +514,7 @@ describe("MatrixClient event timelines", function() {
}); });
let tl; let tl;
client.getEventTimeline(timelineSet, EVENTS[0].event_id client.getEventTimeline(timelineSet, EVENTS[0].event_id,
).then(function(tl0) { ).then(function(tl0) {
tl = tl0; tl = tl0;
return client.paginateEventTimeline(tl, {backwards: true}); return client.paginateEventTimeline(tl, {backwards: true});
@@ -533,8 +535,8 @@ describe("MatrixClient event timelines", function() {
it("should allow you to paginate forwards", function(done) { it("should allow you to paginate forwards", function(done) {
let room = client.getRoom(roomId); const room = client.getRoom(roomId);
let timelineSet = room.getTimelineSets()[0]; const timelineSet = room.getTimelineSets()[0];
httpBackend.when("GET", "/rooms/!foo%3Abar/context/" + httpBackend.when("GET", "/rooms/!foo%3Abar/context/" +
encodeURIComponent(EVENTS[0].event_id)) encodeURIComponent(EVENTS[0].event_id))
@@ -551,7 +553,7 @@ describe("MatrixClient event timelines", function() {
httpBackend.when("GET", "/rooms/!foo%3Abar/messages") httpBackend.when("GET", "/rooms/!foo%3Abar/messages")
.check(function(req) { .check(function(req) {
let params = req.queryParams; const params = req.queryParams;
expect(params.dir).toEqual("f"); expect(params.dir).toEqual("f");
expect(params.from).toEqual("end_token0"); expect(params.from).toEqual("end_token0");
expect(params.limit).toEqual(20); expect(params.limit).toEqual(20);
@@ -563,7 +565,7 @@ describe("MatrixClient event timelines", function() {
}); });
let tl; let tl;
client.getEventTimeline(timelineSet, EVENTS[0].event_id client.getEventTimeline(timelineSet, EVENTS[0].event_id,
).then(function(tl0) { ).then(function(tl0) {
tl = tl0; tl = tl0;
return client.paginateEventTimeline( return client.paginateEventTimeline(
@@ -585,8 +587,8 @@ describe("MatrixClient event timelines", function() {
}); });
describe("event timeline for sent events", function() { describe("event timeline for sent events", function() {
let TXN_ID = "txn1"; const TXN_ID = "txn1";
let event = utils.mkMessage({ const event = utils.mkMessage({
room: roomId, user: userId, msg: "a body", room: roomId, user: userId, msg: "a body",
}); });
event.unsigned = {transaction_id: TXN_ID}; event.unsigned = {transaction_id: TXN_ID};
@@ -616,8 +618,8 @@ describe("MatrixClient event timelines", function() {
}); });
it("should work when /send returns before /sync", function(done) { it("should work when /send returns before /sync", function(done) {
let room = client.getRoom(roomId); const room = client.getRoom(roomId);
let timelineSet = room.getTimelineSets()[0]; const timelineSet = room.getTimelineSets()[0];
client.sendTextMessage(roomId, "a body", TXN_ID).then(function(res) { client.sendTextMessage(roomId, "a body", TXN_ID).then(function(res) {
expect(res.event_id).toEqual(event.event_id); expect(res.event_id).toEqual(event.event_id);
@@ -640,8 +642,8 @@ describe("MatrixClient event timelines", function() {
}); });
it("should work when /send returns after /sync", function(done) { it("should work when /send returns after /sync", function(done) {
let room = client.getRoom(roomId); const room = client.getRoom(roomId);
let timelineSet = room.getTimelineSets()[0]; const timelineSet = room.getTimelineSets()[0];
// initiate the send, and set up checks to be done when it completes // initiate the send, and set up checks to be done when it completes
// - but note that it won't complete until after the /sync does, below. // - but note that it won't complete until after the /sync does, below.
@@ -673,10 +675,10 @@ describe("MatrixClient event timelines", function() {
// https://github.com/vector-im/vector-web/issues/1389 // https://github.com/vector-im/vector-web/issues/1389
// a state event, followed by a redaction thereof // a state event, followed by a redaction thereof
let event = utils.mkMembership({ const event = utils.mkMembership({
room: roomId, mship: "join", user: otherUserId, room: roomId, mship: "join", user: otherUserId,
}); });
let redaction = utils.mkEvent({ const redaction = utils.mkEvent({
type: "m.room.redaction", type: "m.room.redaction",
room_id: roomId, room_id: roomId,
sender: otherUserId, sender: otherUserId,
@@ -684,7 +686,7 @@ describe("MatrixClient event timelines", function() {
}); });
redaction.redacts = event.event_id; redaction.redacts = event.event_id;
let syncData = { const syncData = {
next_batch: "batch1", next_batch: "batch1",
rooms: { rooms: {
join: {}, join: {},
@@ -702,12 +704,12 @@ describe("MatrixClient event timelines", function() {
httpBackend.when("GET", "/sync").respond(200, syncData); httpBackend.when("GET", "/sync").respond(200, syncData);
httpBackend.flush().then(function() { httpBackend.flush().then(function() {
let room = client.getRoom(roomId); const room = client.getRoom(roomId);
let tl = room.getLiveTimeline(); const tl = room.getLiveTimeline();
expect(tl.getEvents().length).toEqual(3); expect(tl.getEvents().length).toEqual(3);
expect(tl.getEvents()[1].isRedacted()).toBe(true); expect(tl.getEvents()[1].isRedacted()).toBe(true);
let sync2 = { const sync2 = {
next_batch: "batch2", next_batch: "batch2",
rooms: { rooms: {
join: {}, join: {},
@@ -728,8 +730,8 @@ describe("MatrixClient event timelines", function() {
return httpBackend.flush(); return httpBackend.flush();
}).then(function() { }).then(function() {
let room = client.getRoom(roomId); const room = client.getRoom(roomId);
let tl = room.getLiveTimeline(); const tl = room.getLiveTimeline();
expect(tl.getEvents().length).toEqual(1); expect(tl.getEvents().length).toEqual(1);
}).catch(utils.failTest).done(done); }).catch(utils.failTest).done(done);
}); });

View File

@@ -1,25 +1,28 @@
"use strict"; "use strict";
let sdk = require("../.."); const sdk = require("../..");
let HttpBackend = require("../mock-request"); const HttpBackend = require("../mock-request");
let publicGlobals = require("../../lib/matrix"); const publicGlobals = require("../../lib/matrix");
let Room = publicGlobals.Room; const Room = publicGlobals.Room;
let MatrixInMemoryStore = publicGlobals.MatrixInMemoryStore; const MatrixInMemoryStore = publicGlobals.MatrixInMemoryStore;
let Filter = publicGlobals.Filter; const Filter = publicGlobals.Filter;
let utils = require("../test-utils"); const utils = require("../test-utils");
let MockStorageApi = require("../MockStorageApi"); const MockStorageApi = require("../MockStorageApi");
describe("MatrixClient", function() { describe("MatrixClient", function() {
let baseUrl = "http://localhost.or.something"; const baseUrl = "http://localhost.or.something";
let client, httpBackend, store, sessionStore; let client = null;
let userId = "@alice:localhost"; let httpBackend = null;
let accessToken = "aseukfgwef"; let store = null;
let sessionStore = null;
const userId = "@alice:localhost";
const accessToken = "aseukfgwef";
beforeEach(function() { beforeEach(function() {
utils.beforeEach(this); // eslint-disable-line no-invalid-this utils.beforeEach(this); // eslint-disable-line no-invalid-this
httpBackend = new HttpBackend(); httpBackend = new HttpBackend();
store = new MatrixInMemoryStore(); store = new MatrixInMemoryStore();
let mockStorage = new MockStorageApi(); const mockStorage = new MockStorageApi();
sessionStore = new sdk.WebStorageSessionStore(mockStorage); sessionStore = new sdk.WebStorageSessionStore(mockStorage);
sdk.request(httpBackend.requestFn); sdk.request(httpBackend.requestFn);
@@ -38,10 +41,10 @@ describe("MatrixClient", function() {
}); });
describe("uploadContent", function() { describe("uploadContent", function() {
let buf = new Buffer('hello world'); const buf = new Buffer('hello world');
it("should upload the file", function(done) { it("should upload the file", function(done) {
httpBackend.when( httpBackend.when(
"POST", "/_matrix/media/v1/upload" "POST", "/_matrix/media/v1/upload",
).check(function(req) { ).check(function(req) {
expect(req.data).toEqual(buf); expect(req.data).toEqual(buf);
expect(req.queryParams.filename).toEqual("hi.txt"); expect(req.queryParams.filename).toEqual("hi.txt");
@@ -51,7 +54,7 @@ describe("MatrixClient", function() {
expect(req.opts.timeout).toBe(undefined); expect(req.opts.timeout).toBe(undefined);
}).respond(200, "content"); }).respond(200, "content");
let prom = client.uploadContent({ const prom = client.uploadContent({
stream: buf, stream: buf,
name: "hi.txt", name: "hi.txt",
type: "text/plain", type: "text/plain",
@@ -59,7 +62,7 @@ describe("MatrixClient", function() {
expect(prom).toBeDefined(); expect(prom).toBeDefined();
let uploads = client.getCurrentUploads(); const uploads = client.getCurrentUploads();
expect(uploads.length).toEqual(1); expect(uploads.length).toEqual(1);
expect(uploads[0].promise).toBe(prom); expect(uploads[0].promise).toBe(prom);
expect(uploads[0].loaded).toEqual(0); expect(uploads[0].loaded).toEqual(0);
@@ -68,7 +71,7 @@ describe("MatrixClient", function() {
// for backwards compatibility, we return the raw JSON // for backwards compatibility, we return the raw JSON
expect(response).toEqual("content"); expect(response).toEqual("content");
let uploads = client.getCurrentUploads(); const uploads = client.getCurrentUploads();
expect(uploads.length).toEqual(0); expect(uploads.length).toEqual(0);
}).catch(utils.failTest).done(done); }).catch(utils.failTest).done(done);
@@ -77,7 +80,7 @@ describe("MatrixClient", function() {
it("should parse the response if rawResponse=false", function(done) { it("should parse the response if rawResponse=false", function(done) {
httpBackend.when( httpBackend.when(
"POST", "/_matrix/media/v1/upload" "POST", "/_matrix/media/v1/upload",
).check(function(req) { ).check(function(req) {
expect(req.opts.json).toBeFalsy(); expect(req.opts.json).toBeFalsy();
}).respond(200, JSON.stringify({ "content_uri": "uri" })); }).respond(200, JSON.stringify({ "content_uri": "uri" }));
@@ -98,7 +101,7 @@ describe("MatrixClient", function() {
it("should parse errors into a MatrixError", function(done) { it("should parse errors into a MatrixError", function(done) {
// opts.json is false, so request returns unparsed json. // opts.json is false, so request returns unparsed json.
httpBackend.when( httpBackend.when(
"POST", "/_matrix/media/v1/upload" "POST", "/_matrix/media/v1/upload",
).check(function(req) { ).check(function(req) {
expect(req.data).toEqual(buf); expect(req.data).toEqual(buf);
expect(req.opts.json).toBeFalsy(); expect(req.opts.json).toBeFalsy();
@@ -123,13 +126,13 @@ describe("MatrixClient", function() {
}); });
it("should return a promise which can be cancelled", function(done) { it("should return a promise which can be cancelled", function(done) {
let prom = client.uploadContent({ const prom = client.uploadContent({
stream: buf, stream: buf,
name: "hi.txt", name: "hi.txt",
type: "text/plain", type: "text/plain",
}); });
let uploads = client.getCurrentUploads(); const uploads = client.getCurrentUploads();
expect(uploads.length).toEqual(1); expect(uploads.length).toEqual(1);
expect(uploads[0].promise).toBe(prom); expect(uploads[0].promise).toBe(prom);
expect(uploads[0].loaded).toEqual(0); expect(uploads[0].loaded).toEqual(0);
@@ -139,19 +142,19 @@ describe("MatrixClient", function() {
}, function(error) { }, function(error) {
expect(error).toEqual("aborted"); expect(error).toEqual("aborted");
let uploads = client.getCurrentUploads(); const uploads = client.getCurrentUploads();
expect(uploads.length).toEqual(0); expect(uploads.length).toEqual(0);
}).catch(utils.failTest).done(done); }).catch(utils.failTest).done(done);
let r = client.cancelUpload(prom); const r = client.cancelUpload(prom);
expect(r).toBe(true); expect(r).toBe(true);
}); });
}); });
describe("joinRoom", function() { describe("joinRoom", function() {
it("should no-op if you've already joined a room", function() { it("should no-op if you've already joined a room", function() {
let roomId = "!foo:bar"; const roomId = "!foo:bar";
let room = new Room(roomId); const room = new Room(roomId);
room.addLiveEvents([ room.addLiveEvents([
utils.mkMembership({ utils.mkMembership({
user: userId, room: roomId, mship: "join", event: true, user: userId, room: roomId, mship: "join", event: true,
@@ -164,10 +167,10 @@ describe("MatrixClient", function() {
}); });
describe("getFilter", function() { describe("getFilter", function() {
let filterId = "f1lt3r1d"; const filterId = "f1lt3r1d";
it("should return a filter from the store if allowCached", function(done) { it("should return a filter from the store if allowCached", function(done) {
let filter = Filter.fromJson(userId, filterId, { const filter = Filter.fromJson(userId, filterId, {
event_format: "client", event_format: "client",
}); });
store.storeFilter(filter); store.storeFilter(filter);
@@ -180,15 +183,15 @@ describe("MatrixClient", function() {
it("should do an HTTP request if !allowCached even if one exists", it("should do an HTTP request if !allowCached even if one exists",
function(done) { function(done) {
let httpFilterDefinition = { const httpFilterDefinition = {
event_format: "federation", event_format: "federation",
}; };
httpBackend.when( httpBackend.when(
"GET", "/user/" + encodeURIComponent(userId) + "/filter/" + filterId "GET", "/user/" + encodeURIComponent(userId) + "/filter/" + filterId,
).respond(200, httpFilterDefinition); ).respond(200, httpFilterDefinition);
let storeFilter = Filter.fromJson(userId, filterId, { const storeFilter = Filter.fromJson(userId, filterId, {
event_format: "client", event_format: "client",
}); });
store.storeFilter(storeFilter); store.storeFilter(storeFilter);
@@ -202,13 +205,13 @@ describe("MatrixClient", function() {
it("should do an HTTP request if nothing is in the cache and then store it", it("should do an HTTP request if nothing is in the cache and then store it",
function(done) { function(done) {
let httpFilterDefinition = { const httpFilterDefinition = {
event_format: "federation", event_format: "federation",
}; };
expect(store.getFilter(userId, filterId)).toBeNull(); expect(store.getFilter(userId, filterId)).toBeNull();
httpBackend.when( httpBackend.when(
"GET", "/user/" + encodeURIComponent(userId) + "/filter/" + filterId "GET", "/user/" + encodeURIComponent(userId) + "/filter/" + filterId,
).respond(200, httpFilterDefinition); ).respond(200, httpFilterDefinition);
client.getFilter(userId, filterId, true).done(function(gotFilter) { client.getFilter(userId, filterId, true).done(function(gotFilter) {
expect(gotFilter.getDefinition()).toEqual(httpFilterDefinition); expect(gotFilter.getDefinition()).toEqual(httpFilterDefinition);
@@ -221,17 +224,17 @@ describe("MatrixClient", function() {
}); });
describe("createFilter", function() { describe("createFilter", function() {
let filterId = "f1llllllerid"; const filterId = "f1llllllerid";
it("should do an HTTP request and then store the filter", function(done) { it("should do an HTTP request and then store the filter", function(done) {
expect(store.getFilter(userId, filterId)).toBeNull(); expect(store.getFilter(userId, filterId)).toBeNull();
let filterDefinition = { const filterDefinition = {
event_format: "client", event_format: "client",
}; };
httpBackend.when( httpBackend.when(
"POST", "/user/" + encodeURIComponent(userId) + "/filter" "POST", "/user/" + encodeURIComponent(userId) + "/filter",
).check(function(req) { ).check(function(req) {
expect(req.data).toEqual(filterDefinition); expect(req.data).toEqual(filterDefinition);
}).respond(200, { }).respond(200, {
@@ -249,7 +252,7 @@ describe("MatrixClient", function() {
}); });
describe("searching", function() { describe("searching", function() {
let response = { const response = {
search_categories: { search_categories: {
room_events: { room_events: {
count: 24, count: 24,
@@ -294,9 +297,9 @@ describe("MatrixClient", function() {
describe("downloadKeys", function() { describe("downloadKeys", function() {
it("should do an HTTP request and then store the keys", function(done) { it("should do an HTTP request and then store the keys", function(done) {
let ed25519key = "7wG2lzAqbjcyEkOP7O4gU7ItYcn+chKzh5sT/5r2l78"; const ed25519key = "7wG2lzAqbjcyEkOP7O4gU7ItYcn+chKzh5sT/5r2l78";
// ed25519key = client.getDeviceEd25519Key(); // ed25519key = client.getDeviceEd25519Key();
let borisKeys = { const borisKeys = {
dev1: { dev1: {
algorithms: ["1"], algorithms: ["1"],
device_id: "dev1", device_id: "dev1",
@@ -312,7 +315,7 @@ describe("MatrixClient", function() {
user_id: "boris", user_id: "boris",
}, },
}; };
let chazKeys = { const chazKeys = {
dev2: { dev2: {
algorithms: ["2"], algorithms: ["2"],
device_id: "dev2", device_id: "dev2",
@@ -373,16 +376,16 @@ describe("MatrixClient", function() {
}); });
describe("deleteDevice", function() { describe("deleteDevice", function() {
let auth = {a: 1}; const auth = {a: 1};
it("should pass through an auth dict", function(done) { it("should pass through an auth dict", function(done) {
httpBackend.when( httpBackend.when(
"DELETE", "/_matrix/client/unstable/devices/my_device" "DELETE", "/_matrix/client/unstable/devices/my_device",
).check(function(req) { ).check(function(req) {
expect(req.data).toEqual({auth: auth}); expect(req.data).toEqual({auth: auth});
}).respond(200); }).respond(200);
client.deleteDevice( client.deleteDevice(
"my_device", auth "my_device", auth,
).catch(utils.failTest).done(done); ).catch(utils.failTest).done(done);
httpBackend.flush(); httpBackend.flush();
@@ -391,7 +394,7 @@ describe("MatrixClient", function() {
}); });
function assertObjectContains(obj, expected) { function assertObjectContains(obj, expected) {
for (let k in expected) { for (const k in expected) {
if (expected.hasOwnProperty(k)) { if (expected.hasOwnProperty(k)) {
expect(obj[k]).toEqual(expected[k]); expect(obj[k]).toEqual(expected[k]);
} }

View File

@@ -1,17 +1,18 @@
"use strict"; "use strict";
let sdk = require("../.."); const sdk = require("../..");
let MatrixClient = sdk.MatrixClient; const MatrixClient = sdk.MatrixClient;
let HttpBackend = require("../mock-request"); const HttpBackend = require("../mock-request");
let utils = require("../test-utils"); const utils = require("../test-utils");
describe("MatrixClient opts", function() { describe("MatrixClient opts", function() {
let baseUrl = "http://localhost.or.something"; const baseUrl = "http://localhost.or.something";
let client, httpBackend; let client = null;
let userId = "@alice:localhost"; let httpBackend = null;
let userB = "@bob:localhost"; const userId = "@alice:localhost";
let accessToken = "aseukfgwef"; const userB = "@bob:localhost";
let roomId = "!foo:bar"; const accessToken = "aseukfgwef";
let syncData = { const roomId = "!foo:bar";
const syncData = {
next_batch: "s_5_3", next_batch: "s_5_3",
presence: {}, presence: {},
rooms: { rooms: {
@@ -78,7 +79,7 @@ describe("MatrixClient opts", function() {
}); });
it("should be able to send messages", function(done) { it("should be able to send messages", function(done) {
let eventId = "$flibble:wibble"; const eventId = "$flibble:wibble";
httpBackend.when("PUT", "/txn1").respond(200, { httpBackend.when("PUT", "/txn1").respond(200, {
event_id: eventId, event_id: eventId,
}); });
@@ -90,16 +91,16 @@ describe("MatrixClient opts", function() {
}); });
it("should be able to sync / get new events", function(done) { it("should be able to sync / get new events", function(done) {
let expectedEventTypes = [ // from /initialSync const expectedEventTypes = [ // from /initialSync
"m.room.message", "m.room.name", "m.room.member", "m.room.member", "m.room.message", "m.room.name", "m.room.member", "m.room.member",
"m.room.create", "m.room.create",
]; ];
client.on("event", function(event) { client.on("event", function(event) {
expect(expectedEventTypes.indexOf(event.getType())).not.toEqual( expect(expectedEventTypes.indexOf(event.getType())).not.toEqual(
-1, "Recv unexpected event type: " + event.getType() -1, "Recv unexpected event type: " + event.getType(),
); );
expectedEventTypes.splice( expectedEventTypes.splice(
expectedEventTypes.indexOf(event.getType()), 1 expectedEventTypes.indexOf(event.getType()), 1,
); );
}); });
httpBackend.when("GET", "/pushrules").respond(200, {}); httpBackend.when("GET", "/pushrules").respond(200, {});
@@ -112,7 +113,7 @@ describe("MatrixClient opts", function() {
return httpBackend.flush("/sync", 1); return httpBackend.flush("/sync", 1);
}).done(function() { }).done(function() {
expect(expectedEventTypes.length).toEqual( expect(expectedEventTypes.length).toEqual(
0, "Expected to see event types: " + expectedEventTypes 0, "Expected to see event types: " + expectedEventTypes,
); );
done(); done();
}); });

View File

@@ -1,16 +1,17 @@
"use strict"; "use strict";
let sdk = require("../.."); const sdk = require("../..");
let HttpBackend = require("../mock-request"); const HttpBackend = require("../mock-request");
let utils = require("../test-utils"); const utils = require("../test-utils");
let EventStatus = sdk.EventStatus; const EventStatus = sdk.EventStatus;
describe("MatrixClient retrying", function() { describe("MatrixClient retrying", function() {
let baseUrl = "http://localhost.or.something"; const baseUrl = "http://localhost.or.something";
let client, httpBackend; let client = null;
let httpBackend = null;
let scheduler; let scheduler;
let userId = "@alice:localhost"; const userId = "@alice:localhost";
let accessToken = "aseukfgwef"; const accessToken = "aseukfgwef";
let roomId = "!room:here"; const roomId = "!room:here";
let room; let room;
beforeEach(function() { beforeEach(function() {
@@ -50,7 +51,6 @@ describe("MatrixClient retrying", function() {
it("should mark events as EventStatus.CANCELLED when cancelled", function(done) { it("should mark events as EventStatus.CANCELLED when cancelled", function(done) {
// send a couple of events; the second will be queued // send a couple of events; the second will be queued
let ev1, ev2;
client.sendMessage(roomId, "m1").then(function(ev) { client.sendMessage(roomId, "m1").then(function(ev) {
expect(ev).toEqual(ev1); expect(ev).toEqual(ev1);
}); });
@@ -59,10 +59,10 @@ describe("MatrixClient retrying", function() {
}); });
// both events should be in the timeline at this point // both events should be in the timeline at this point
let tl = room.getLiveTimeline().getEvents(); const tl = room.getLiveTimeline().getEvents();
expect(tl.length).toEqual(2); expect(tl.length).toEqual(2);
ev1 = tl[0]; const ev1 = tl[0];
ev2 = tl[1]; const ev2 = tl[1];
expect(ev1.status).toEqual(EventStatus.SENDING); expect(ev1.status).toEqual(EventStatus.SENDING);
expect(ev2.status).toEqual(EventStatus.SENDING); expect(ev2.status).toEqual(EventStatus.SENDING);

View File

@@ -1,28 +1,29 @@
"use strict"; "use strict";
let sdk = require("../.."); const sdk = require("../..");
let EventStatus = sdk.EventStatus; const EventStatus = sdk.EventStatus;
let HttpBackend = require("../mock-request"); const HttpBackend = require("../mock-request");
let utils = require("../test-utils"); const utils = require("../test-utils");
describe("MatrixClient room timelines", function() { describe("MatrixClient room timelines", function() {
let baseUrl = "http://localhost.or.something"; const baseUrl = "http://localhost.or.something";
let client, httpBackend; let client = null;
let userId = "@alice:localhost"; let httpBackend = null;
let userName = "Alice"; const userId = "@alice:localhost";
let accessToken = "aseukfgwef"; const userName = "Alice";
let roomId = "!foo:bar"; const accessToken = "aseukfgwef";
let otherUserId = "@bob:localhost"; const roomId = "!foo:bar";
let USER_MEMBERSHIP_EVENT = utils.mkMembership({ const otherUserId = "@bob:localhost";
const USER_MEMBERSHIP_EVENT = utils.mkMembership({
room: roomId, mship: "join", user: userId, name: userName, room: roomId, mship: "join", user: userId, name: userName,
}); });
let ROOM_NAME_EVENT = utils.mkEvent({ const ROOM_NAME_EVENT = utils.mkEvent({
type: "m.room.name", room: roomId, user: otherUserId, type: "m.room.name", room: roomId, user: otherUserId,
content: { content: {
name: "Old room name", name: "Old room name",
}, },
}); });
let NEXT_SYNC_DATA; let NEXT_SYNC_DATA;
let SYNC_DATA = { const SYNC_DATA = {
next_batch: "s_5_3", next_batch: "s_5_3",
rooms: { rooms: {
join: { join: {
@@ -81,7 +82,7 @@ describe("MatrixClient room timelines", function() {
if (e.__prev_event === undefined) { if (e.__prev_event === undefined) {
throw new Error( throw new Error(
"setNextSyncData needs the prev state set to '__prev_event' " + "setNextSyncData needs the prev state set to '__prev_event' " +
"for " + e.type "for " + e.type,
); );
} }
if (e.__prev_event !== null) { if (e.__prev_event !== null) {
@@ -134,7 +135,7 @@ describe("MatrixClient room timelines", function() {
if (state !== "PREPARED") { if (state !== "PREPARED") {
return; return;
} }
let room = client.getRoom(roomId); const room = client.getRoom(roomId);
expect(room.timeline.length).toEqual(1); expect(room.timeline.length).toEqual(1);
client.sendTextMessage(roomId, "I am a fish", "txn1"); client.sendTextMessage(roomId, "I am a fish", "txn1");
@@ -143,7 +144,7 @@ describe("MatrixClient room timelines", function() {
// check status // check status
expect(room.timeline[1].status).toEqual(EventStatus.SENDING); expect(room.timeline[1].status).toEqual(EventStatus.SENDING);
// check member // check member
let member = room.timeline[1].sender; const member = room.timeline[1].sender;
expect(member.userId).toEqual(userId); expect(member.userId).toEqual(userId);
expect(member.name).toEqual(userName); expect(member.name).toEqual(userName);
@@ -156,12 +157,12 @@ describe("MatrixClient room timelines", function() {
it("should be updated correctly when the send request finishes " + it("should be updated correctly when the send request finishes " +
"BEFORE the event comes down the event stream", function(done) { "BEFORE the event comes down the event stream", function(done) {
let eventId = "$foo:bar"; const eventId = "$foo:bar";
httpBackend.when("PUT", "/txn1").respond(200, { httpBackend.when("PUT", "/txn1").respond(200, {
event_id: eventId, event_id: eventId,
}); });
let ev = utils.mkMessage({ const ev = utils.mkMessage({
body: "I am a fish", user: userId, room: roomId, body: "I am a fish", user: userId, room: roomId,
}); });
ev.event_id = eventId; ev.event_id = eventId;
@@ -172,7 +173,7 @@ describe("MatrixClient room timelines", function() {
if (state !== "PREPARED") { if (state !== "PREPARED") {
return; return;
} }
let room = client.getRoom(roomId); const room = client.getRoom(roomId);
client.sendTextMessage(roomId, "I am a fish", "txn1").done( client.sendTextMessage(roomId, "I am a fish", "txn1").done(
function() { function() {
expect(room.timeline[1].getId()).toEqual(eventId); expect(room.timeline[1].getId()).toEqual(eventId);
@@ -188,12 +189,12 @@ describe("MatrixClient room timelines", function() {
it("should be updated correctly when the send request finishes " + it("should be updated correctly when the send request finishes " +
"AFTER the event comes down the event stream", function(done) { "AFTER the event comes down the event stream", function(done) {
let eventId = "$foo:bar"; const eventId = "$foo:bar";
httpBackend.when("PUT", "/txn1").respond(200, { httpBackend.when("PUT", "/txn1").respond(200, {
event_id: eventId, event_id: eventId,
}); });
let ev = utils.mkMessage({ const ev = utils.mkMessage({
body: "I am a fish", user: userId, room: roomId, body: "I am a fish", user: userId, room: roomId,
}); });
ev.event_id = eventId; ev.event_id = eventId;
@@ -204,8 +205,8 @@ describe("MatrixClient room timelines", function() {
if (state !== "PREPARED") { if (state !== "PREPARED") {
return; return;
} }
let room = client.getRoom(roomId); const room = client.getRoom(roomId);
let promise = client.sendTextMessage(roomId, "I am a fish", "txn1"); const promise = client.sendTextMessage(roomId, "I am a fish", "txn1");
httpBackend.flush("/sync", 1).done(function() { httpBackend.flush("/sync", 1).done(function() {
expect(room.timeline.length).toEqual(2); expect(room.timeline.length).toEqual(2);
httpBackend.flush("/txn1", 1); httpBackend.flush("/txn1", 1);
@@ -222,7 +223,7 @@ describe("MatrixClient room timelines", function() {
describe("paginated events", function() { describe("paginated events", function() {
let sbEvents; let sbEvents;
let sbEndTok = "pagin_end"; const sbEndTok = "pagin_end";
beforeEach(function() { beforeEach(function() {
sbEvents = []; sbEvents = [];
@@ -241,7 +242,7 @@ describe("MatrixClient room timelines", function() {
if (state !== "PREPARED") { if (state !== "PREPARED") {
return; return;
} }
let room = client.getRoom(roomId); const room = client.getRoom(roomId);
expect(room.timeline.length).toEqual(1); expect(room.timeline.length).toEqual(1);
client.scrollback(room).done(function() { client.scrollback(room).done(function() {
@@ -267,14 +268,14 @@ describe("MatrixClient room timelines", function() {
// <Bob> hello // <Bob> hello
// make an m.room.member event for alice's join // make an m.room.member event for alice's join
let joinMshipEvent = utils.mkMembership({ const joinMshipEvent = utils.mkMembership({
mship: "join", user: userId, room: roomId, name: "Old Alice", mship: "join", user: userId, room: roomId, name: "Old Alice",
url: null, url: null,
}); });
// make an m.room.member event with prev_content for alice's nick // make an m.room.member event with prev_content for alice's nick
// change // change
let oldMshipEvent = utils.mkMembership({ const oldMshipEvent = utils.mkMembership({
mship: "join", user: userId, room: roomId, name: userName, mship: "join", user: userId, room: roomId, name: userName,
url: "mxc://some/url", url: "mxc://some/url",
}); });
@@ -301,17 +302,17 @@ describe("MatrixClient room timelines", function() {
if (state !== "PREPARED") { if (state !== "PREPARED") {
return; return;
} }
let room = client.getRoom(roomId); const room = client.getRoom(roomId);
// sync response // sync response
expect(room.timeline.length).toEqual(1); expect(room.timeline.length).toEqual(1);
client.scrollback(room).done(function() { client.scrollback(room).done(function() {
expect(room.timeline.length).toEqual(5); expect(room.timeline.length).toEqual(5);
let joinMsg = room.timeline[0]; const joinMsg = room.timeline[0];
expect(joinMsg.sender.name).toEqual("Old Alice"); expect(joinMsg.sender.name).toEqual("Old Alice");
let oldMsg = room.timeline[1]; const oldMsg = room.timeline[1];
expect(oldMsg.sender.name).toEqual("Old Alice"); expect(oldMsg.sender.name).toEqual("Old Alice");
let newMsg = room.timeline[3]; const newMsg = room.timeline[3];
expect(newMsg.sender.name).toEqual(userName); expect(newMsg.sender.name).toEqual(userName);
done(); done();
}); });
@@ -337,7 +338,7 @@ describe("MatrixClient room timelines", function() {
if (state !== "PREPARED") { if (state !== "PREPARED") {
return; return;
} }
let room = client.getRoom(roomId); const room = client.getRoom(roomId);
expect(room.timeline.length).toEqual(1); expect(room.timeline.length).toEqual(1);
client.scrollback(room).done(function() { client.scrollback(room).done(function() {
@@ -365,7 +366,7 @@ describe("MatrixClient room timelines", function() {
if (state !== "PREPARED") { if (state !== "PREPARED") {
return; return;
} }
let room = client.getRoom(roomId); const room = client.getRoom(roomId);
expect(room.oldState.paginationToken).toBeDefined(); expect(room.oldState.paginationToken).toBeDefined();
client.scrollback(room, 1).done(function() { client.scrollback(room, 1).done(function() {
@@ -383,7 +384,7 @@ describe("MatrixClient room timelines", function() {
describe("new events", function() { describe("new events", function() {
it("should be added to the right place in the timeline", function(done) { it("should be added to the right place in the timeline", function(done) {
let eventData = [ const eventData = [
utils.mkMessage({user: userId, room: roomId}), utils.mkMessage({user: userId, room: roomId}),
utils.mkMessage({user: userId, room: roomId}), utils.mkMessage({user: userId, room: roomId}),
]; ];
@@ -393,7 +394,7 @@ describe("MatrixClient room timelines", function() {
if (state !== "PREPARED") { if (state !== "PREPARED") {
return; return;
} }
let room = client.getRoom(roomId); const room = client.getRoom(roomId);
let index = 0; let index = 0;
client.on("Room.timeline", function(event, rm, toStart) { client.on("Room.timeline", function(event, rm, toStart) {
@@ -408,10 +409,10 @@ describe("MatrixClient room timelines", function() {
expect(index).toEqual(2); expect(index).toEqual(2);
expect(room.timeline.length).toEqual(3); expect(room.timeline.length).toEqual(3);
expect(room.timeline[2].event).toEqual( expect(room.timeline[2].event).toEqual(
eventData[1] eventData[1],
); );
expect(room.timeline[1].event).toEqual( expect(room.timeline[1].event).toEqual(
eventData[0] eventData[0],
); );
}).catch(utils.failTest).done(done); }).catch(utils.failTest).done(done);
}); });
@@ -419,7 +420,7 @@ describe("MatrixClient room timelines", function() {
}); });
it("should set the right event.sender values", function(done) { it("should set the right event.sender values", function(done) {
let eventData = [ const eventData = [
utils.mkMessage({user: userId, room: roomId}), utils.mkMessage({user: userId, room: roomId}),
utils.mkMembership({ utils.mkMembership({
user: userId, room: roomId, mship: "join", name: "New Name", user: userId, room: roomId, mship: "join", name: "New Name",
@@ -433,10 +434,10 @@ describe("MatrixClient room timelines", function() {
if (state !== "PREPARED") { if (state !== "PREPARED") {
return; return;
} }
let room = client.getRoom(roomId); const room = client.getRoom(roomId);
httpBackend.flush("/sync", 1).then(function() { httpBackend.flush("/sync", 1).then(function() {
let preNameEvent = room.timeline[room.timeline.length - 3]; const preNameEvent = room.timeline[room.timeline.length - 3];
let postNameEvent = room.timeline[room.timeline.length - 1]; const postNameEvent = room.timeline[room.timeline.length - 1];
expect(preNameEvent.sender.name).toEqual(userName); expect(preNameEvent.sender.name).toEqual(userName);
expect(postNameEvent.sender.name).toEqual("New Name"); expect(postNameEvent.sender.name).toEqual("New Name");
}).catch(utils.failTest).done(done); }).catch(utils.failTest).done(done);
@@ -445,7 +446,7 @@ describe("MatrixClient room timelines", function() {
}); });
it("should set the right room.name", function(done) { it("should set the right room.name", function(done) {
let secondRoomNameEvent = utils.mkEvent({ const secondRoomNameEvent = utils.mkEvent({
user: userId, room: roomId, type: "m.room.name", content: { user: userId, room: roomId, type: "m.room.name", content: {
name: "Room 2", name: "Room 2",
}, },
@@ -457,7 +458,7 @@ describe("MatrixClient room timelines", function() {
if (state !== "PREPARED") { if (state !== "PREPARED") {
return; return;
} }
let room = client.getRoom(roomId); const room = client.getRoom(roomId);
let nameEmitCount = 0; let nameEmitCount = 0;
client.on("Room.name", function(rm) { client.on("Room.name", function(rm) {
nameEmitCount += 1; nameEmitCount += 1;
@@ -467,7 +468,7 @@ describe("MatrixClient room timelines", function() {
expect(nameEmitCount).toEqual(1); expect(nameEmitCount).toEqual(1);
expect(room.name).toEqual("Room 2"); expect(room.name).toEqual("Room 2");
// do another round // do another round
let thirdRoomNameEvent = utils.mkEvent({ const thirdRoomNameEvent = utils.mkEvent({
user: userId, room: roomId, type: "m.room.name", content: { user: userId, room: roomId, type: "m.room.name", content: {
name: "Room 3", name: "Room 3",
}, },
@@ -486,9 +487,9 @@ describe("MatrixClient room timelines", function() {
}); });
it("should set the right room members", function(done) { it("should set the right room members", function(done) {
let userC = "@cee:bar"; const userC = "@cee:bar";
let userD = "@dee:bar"; const userD = "@dee:bar";
let eventData = [ const eventData = [
utils.mkMembership({ utils.mkMembership({
user: userC, room: roomId, mship: "join", name: "C", user: userC, room: roomId, mship: "join", name: "C",
}), }),
@@ -504,16 +505,16 @@ describe("MatrixClient room timelines", function() {
if (state !== "PREPARED") { if (state !== "PREPARED") {
return; return;
} }
let room = client.getRoom(roomId); const room = client.getRoom(roomId);
httpBackend.flush("/sync", 1).then(function() { httpBackend.flush("/sync", 1).then(function() {
expect(room.currentState.getMembers().length).toEqual(4); expect(room.currentState.getMembers().length).toEqual(4);
expect(room.currentState.getMember(userC).name).toEqual("C"); expect(room.currentState.getMember(userC).name).toEqual("C");
expect(room.currentState.getMember(userC).membership).toEqual( expect(room.currentState.getMember(userC).membership).toEqual(
"join" "join",
); );
expect(room.currentState.getMember(userD).name).toEqual(userD); expect(room.currentState.getMember(userD).name).toEqual(userD);
expect(room.currentState.getMember(userD).membership).toEqual( expect(room.currentState.getMember(userD).membership).toEqual(
"invite" "invite",
); );
}).catch(utils.failTest).done(done); }).catch(utils.failTest).done(done);
}); });
@@ -523,7 +524,7 @@ describe("MatrixClient room timelines", function() {
describe("gappy sync", function() { describe("gappy sync", function() {
it("should copy the last known state to the new timeline", function(done) { it("should copy the last known state to the new timeline", function(done) {
let eventData = [ const eventData = [
utils.mkMessage({user: userId, room: roomId}), utils.mkMessage({user: userId, room: roomId}),
]; ];
setNextSyncData(eventData); setNextSyncData(eventData);
@@ -533,7 +534,7 @@ describe("MatrixClient room timelines", function() {
if (state !== "PREPARED") { if (state !== "PREPARED") {
return; return;
} }
let room = client.getRoom(roomId); const room = client.getRoom(roomId);
httpBackend.flush("/messages", 1); httpBackend.flush("/messages", 1);
httpBackend.flush("/sync", 1).done(function() { httpBackend.flush("/sync", 1).done(function() {
@@ -542,11 +543,11 @@ describe("MatrixClient room timelines", function() {
expect(room.currentState.getMembers().length).toEqual(2); expect(room.currentState.getMembers().length).toEqual(2);
expect(room.currentState.getMember(userId).name).toEqual(userName); expect(room.currentState.getMember(userId).name).toEqual(userName);
expect(room.currentState.getMember(userId).membership).toEqual( expect(room.currentState.getMember(userId).membership).toEqual(
"join" "join",
); );
expect(room.currentState.getMember(otherUserId).name).toEqual("Bob"); expect(room.currentState.getMember(otherUserId).name).toEqual("Bob");
expect(room.currentState.getMember(otherUserId).membership).toEqual( expect(room.currentState.getMember(otherUserId).membership).toEqual(
"join" "join",
); );
done(); done();
}); });
@@ -555,7 +556,7 @@ describe("MatrixClient room timelines", function() {
}); });
it("should emit a 'Room.timelineReset' event", function(done) { it("should emit a 'Room.timelineReset' event", function(done) {
let eventData = [ const eventData = [
utils.mkMessage({user: userId, room: roomId}), utils.mkMessage({user: userId, room: roomId}),
]; ];
setNextSyncData(eventData); setNextSyncData(eventData);
@@ -565,7 +566,7 @@ describe("MatrixClient room timelines", function() {
if (state !== "PREPARED") { if (state !== "PREPARED") {
return; return;
} }
let room = client.getRoom(roomId); const room = client.getRoom(roomId);
let emitCount = 0; let emitCount = 0;
client.on("Room.timelineReset", function(emitRoom) { client.on("Room.timelineReset", function(emitRoom) {

View File

@@ -1,21 +1,22 @@
"use strict"; "use strict";
let sdk = require("../.."); const sdk = require("../..");
let HttpBackend = require("../mock-request"); const HttpBackend = require("../mock-request");
let utils = require("../test-utils"); const utils = require("../test-utils");
let MatrixEvent = sdk.MatrixEvent; const MatrixEvent = sdk.MatrixEvent;
let EventTimeline = sdk.EventTimeline; const EventTimeline = sdk.EventTimeline;
describe("MatrixClient syncing", function() { describe("MatrixClient syncing", function() {
let baseUrl = "http://localhost.or.something"; const baseUrl = "http://localhost.or.something";
let client, httpBackend; let client = null;
let selfUserId = "@alice:localhost"; let httpBackend = null;
let selfAccessToken = "aseukfgwef"; const selfUserId = "@alice:localhost";
let otherUserId = "@bob:localhost"; const selfAccessToken = "aseukfgwef";
let userA = "@alice:bar"; const otherUserId = "@bob:localhost";
let userB = "@bob:bar"; const userA = "@alice:bar";
let userC = "@claire:bar"; const userB = "@bob:bar";
let roomOne = "!foo:localhost"; const userC = "@claire:bar";
let roomTwo = "!bar:localhost"; const roomOne = "!foo:localhost";
const roomTwo = "!bar:localhost";
beforeEach(function() { beforeEach(function() {
utils.beforeEach(this); // eslint-disable-line no-invalid-this utils.beforeEach(this); // eslint-disable-line no-invalid-this
@@ -36,7 +37,7 @@ describe("MatrixClient syncing", function() {
}); });
describe("startClient", function() { describe("startClient", function() {
let syncData = { const syncData = {
next_batch: "batch_token", next_batch: "batch_token",
rooms: {}, rooms: {},
presence: {}, presence: {},
@@ -68,7 +69,7 @@ describe("MatrixClient syncing", function() {
}); });
describe("resolving invites to profile info", function() { describe("resolving invites to profile info", function() {
let syncData = { const syncData = {
next_batch: "s_5_3", next_batch: "s_5_3",
presence: { presence: {
events: [], events: [],
@@ -113,7 +114,7 @@ describe("MatrixClient syncing", function() {
syncData.rooms.join[roomOne].state.events.push( syncData.rooms.join[roomOne].state.events.push(
utils.mkMembership({ utils.mkMembership({
room: roomOne, mship: "invite", user: userC, room: roomOne, mship: "invite", user: userC,
}) }),
); );
httpBackend.when("GET", "/sync").respond(200, syncData); httpBackend.when("GET", "/sync").respond(200, syncData);
@@ -121,7 +122,7 @@ describe("MatrixClient syncing", function() {
200, { 200, {
avatar_url: "mxc://flibble/wibble", avatar_url: "mxc://flibble/wibble",
displayname: "The Boss", displayname: "The Boss",
} },
); );
client.startClient({ client.startClient({
@@ -129,10 +130,10 @@ describe("MatrixClient syncing", function() {
}); });
httpBackend.flush().done(function() { httpBackend.flush().done(function() {
let member = client.getRoom(roomOne).getMember(userC); const member = client.getRoom(roomOne).getMember(userC);
expect(member.name).toEqual("The Boss"); expect(member.name).toEqual("The Boss");
expect( expect(
member.getAvatarUrl("home.server.url", null, null, null, false) member.getAvatarUrl("home.server.url", null, null, null, false),
).toBeDefined(); ).toBeDefined();
done(); done();
}); });
@@ -147,7 +148,7 @@ describe("MatrixClient syncing", function() {
syncData.rooms.join[roomOne].state.events.push( syncData.rooms.join[roomOne].state.events.push(
utils.mkMembership({ utils.mkMembership({
room: roomOne, mship: "invite", user: userC, room: roomOne, mship: "invite", user: userC,
}) }),
); );
httpBackend.when("GET", "/sync").respond(200, syncData); httpBackend.when("GET", "/sync").respond(200, syncData);
@@ -157,7 +158,7 @@ describe("MatrixClient syncing", function() {
}); });
httpBackend.flush().done(function() { httpBackend.flush().done(function() {
let member = client.getRoom(roomOne).getMember(userC); const member = client.getRoom(roomOne).getMember(userC);
expect(member.name).toEqual("The Ghost"); expect(member.name).toEqual("The Ghost");
done(); done();
}); });
@@ -172,7 +173,7 @@ describe("MatrixClient syncing", function() {
syncData.rooms.join[roomOne].state.events.push( syncData.rooms.join[roomOne].state.events.push(
utils.mkMembership({ utils.mkMembership({
room: roomOne, mship: "invite", user: userC, room: roomOne, mship: "invite", user: userC,
}) }),
); );
httpBackend.when("GET", "/sync").respond(200, syncData); httpBackend.when("GET", "/sync").respond(200, syncData);
@@ -198,7 +199,7 @@ describe("MatrixClient syncing", function() {
syncData.rooms.join[roomOne].state.events.push( syncData.rooms.join[roomOne].state.events.push(
utils.mkMembership({ utils.mkMembership({
room: roomOne, mship: "invite", user: userC, room: roomOne, mship: "invite", user: userC,
}) }),
); );
httpBackend.when("GET", "/sync").respond(200, syncData); httpBackend.when("GET", "/sync").respond(200, syncData);
@@ -206,10 +207,10 @@ describe("MatrixClient syncing", function() {
client.startClient(); client.startClient();
httpBackend.flush().done(function() { httpBackend.flush().done(function() {
let member = client.getRoom(roomOne).getMember(userC); const member = client.getRoom(roomOne).getMember(userC);
expect(member.name).toEqual(userC); expect(member.name).toEqual(userC);
expect( expect(
member.getAvatarUrl("home.server.url", null, null, null, false) member.getAvatarUrl("home.server.url", null, null, null, false),
).toBeNull(); ).toBeNull();
done(); done();
}); });
@@ -217,7 +218,7 @@ describe("MatrixClient syncing", function() {
}); });
describe("users", function() { describe("users", function() {
let syncData = { const syncData = {
next_batch: "nb", next_batch: "nb",
presence: { presence: {
events: [ events: [
@@ -246,10 +247,10 @@ describe("MatrixClient syncing", function() {
}); });
describe("room state", function() { describe("room state", function() {
let msgText = "some text here"; const msgText = "some text here";
let otherDisplayName = "Bob Smith"; const otherDisplayName = "Bob Smith";
let syncData = { const syncData = {
rooms: { rooms: {
join: { join: {
@@ -314,7 +315,7 @@ describe("MatrixClient syncing", function() {
}, },
}; };
let nextSyncData = { const nextSyncData = {
rooms: { rooms: {
join: { join: {
@@ -358,10 +359,10 @@ describe("MatrixClient syncing", function() {
client.startClient(); client.startClient();
httpBackend.flush().done(function() { httpBackend.flush().done(function() {
let room = client.getRoom(roomOne); const room = client.getRoom(roomOne);
// should have clobbered the name to the one from /events // should have clobbered the name to the one from /events
expect(room.name).toEqual( expect(room.name).toEqual(
nextSyncData.rooms.join[roomOne].state.events[0].content.name nextSyncData.rooms.join[roomOne].state.events[0].content.name,
); );
done(); done();
}); });
@@ -374,7 +375,7 @@ describe("MatrixClient syncing", function() {
client.startClient(); client.startClient();
httpBackend.flush().done(function() { httpBackend.flush().done(function() {
let room = client.getRoom(roomTwo); const room = client.getRoom(roomTwo);
// should have added the message from /events // should have added the message from /events
expect(room.timeline.length).toEqual(2); expect(room.timeline.length).toEqual(2);
expect(room.timeline[1].getContent().body).toEqual(msgText); expect(room.timeline[1].getContent().body).toEqual(msgText);
@@ -388,7 +389,7 @@ describe("MatrixClient syncing", function() {
client.startClient(); client.startClient();
httpBackend.flush().done(function() { httpBackend.flush().done(function() {
let room = client.getRoom(roomTwo); const room = client.getRoom(roomTwo);
// should use the display name of the other person. // should use the display name of the other person.
expect(room.name).toEqual(otherDisplayName); expect(room.name).toEqual(otherDisplayName);
done(); done();
@@ -402,7 +403,7 @@ describe("MatrixClient syncing", function() {
client.startClient(); client.startClient();
httpBackend.flush().done(function() { httpBackend.flush().done(function() {
let room = client.getRoom(roomTwo); const room = client.getRoom(roomTwo);
let member = room.getMember(otherUserId); let member = room.getMember(otherUserId);
expect(member).toBeDefined(); expect(member).toBeDefined();
expect(member.typing).toEqual(true); expect(member.typing).toEqual(true);
@@ -424,7 +425,7 @@ describe("MatrixClient syncing", function() {
describe("timeline", function() { describe("timeline", function() {
beforeEach(function() { beforeEach(function() {
let syncData = { const syncData = {
next_batch: "batch_token", next_batch: "batch_token",
rooms: { rooms: {
join: {}, join: {},
@@ -448,7 +449,7 @@ describe("MatrixClient syncing", function() {
}); });
it("should set the back-pagination token on new rooms", function(done) { it("should set the back-pagination token on new rooms", function(done) {
let syncData = { const syncData = {
next_batch: "batch_token", next_batch: "batch_token",
rooms: { rooms: {
join: {}, join: {},
@@ -468,8 +469,8 @@ describe("MatrixClient syncing", function() {
httpBackend.when("GET", "/sync").respond(200, syncData); httpBackend.when("GET", "/sync").respond(200, syncData);
httpBackend.flush().then(function() { httpBackend.flush().then(function() {
let room = client.getRoom(roomTwo); const room = client.getRoom(roomTwo);
let tok = room.getLiveTimeline() const tok = room.getLiveTimeline()
.getPaginationToken(EventTimeline.BACKWARDS); .getPaginationToken(EventTimeline.BACKWARDS);
expect(tok).toEqual("roomtwotok"); expect(tok).toEqual("roomtwotok");
done(); done();
@@ -477,7 +478,7 @@ describe("MatrixClient syncing", function() {
}); });
it("should set the back-pagination token on gappy syncs", function(done) { it("should set the back-pagination token on gappy syncs", function(done) {
let syncData = { const syncData = {
next_batch: "batch_token", next_batch: "batch_token",
rooms: { rooms: {
join: {}, join: {},
@@ -501,15 +502,15 @@ describe("MatrixClient syncing", function() {
client.on("Room.timelineReset", function(room) { client.on("Room.timelineReset", function(room) {
resetCallCount++; resetCallCount++;
let tl = room.getLiveTimeline(); const tl = room.getLiveTimeline();
expect(tl.getEvents().length).toEqual(0); expect(tl.getEvents().length).toEqual(0);
let tok = tl.getPaginationToken(EventTimeline.BACKWARDS); const tok = tl.getPaginationToken(EventTimeline.BACKWARDS);
expect(tok).toEqual("newerTok"); expect(tok).toEqual("newerTok");
}); });
httpBackend.flush().then(function() { httpBackend.flush().then(function() {
let room = client.getRoom(roomOne); const room = client.getRoom(roomOne);
let tl = room.getLiveTimeline(); const tl = room.getLiveTimeline();
expect(tl.getEvents().length).toEqual(1); expect(tl.getEvents().length).toEqual(1);
expect(resetCallCount).toEqual(1); expect(resetCallCount).toEqual(1);
done(); done();
@@ -518,7 +519,7 @@ describe("MatrixClient syncing", function() {
}); });
describe("receipts", function() { describe("receipts", function() {
let syncData = { const syncData = {
rooms: { rooms: {
join: { join: {
@@ -567,8 +568,8 @@ describe("MatrixClient syncing", function() {
}); });
it("should sync receipts from /sync.", function(done) { it("should sync receipts from /sync.", function(done) {
let ackEvent = syncData.rooms.join[roomOne].timeline.events[0]; const ackEvent = syncData.rooms.join[roomOne].timeline.events[0];
let receipt = {}; const receipt = {};
receipt[ackEvent.event_id] = { receipt[ackEvent.event_id] = {
"m.read": {}, "m.read": {},
}; };
@@ -585,7 +586,7 @@ describe("MatrixClient syncing", function() {
client.startClient(); client.startClient();
httpBackend.flush().done(function() { httpBackend.flush().done(function() {
let room = client.getRoom(roomOne); const room = client.getRoom(roomOne);
expect(room.getReceiptsForEvent(new MatrixEvent(ackEvent))).toEqual([{ expect(room.getReceiptsForEvent(new MatrixEvent(ackEvent))).toEqual([{
type: "m.read", type: "m.read",
userId: userC, userId: userC,
@@ -646,7 +647,7 @@ describe("MatrixClient syncing", function() {
}); });
it("should set the back-pagination token on left rooms", function(done) { it("should set the back-pagination token on left rooms", function(done) {
let syncData = { const syncData = {
next_batch: "batch_token", next_batch: "batch_token",
rooms: { rooms: {
leave: {}, leave: {},
@@ -671,8 +672,8 @@ describe("MatrixClient syncing", function() {
httpBackend.when("GET", "/sync").respond(200, syncData); httpBackend.when("GET", "/sync").respond(200, syncData);
client.syncLeftRooms().then(function() { client.syncLeftRooms().then(function() {
let room = client.getRoom(roomTwo); const room = client.getRoom(roomTwo);
let tok = room.getLiveTimeline().getPaginationToken( const tok = room.getLiveTimeline().getPaginationToken(
EventTimeline.BACKWARDS); EventTimeline.BACKWARDS);
expect(tok).toEqual("pagTok"); expect(tok).toEqual("pagTok");

View File

@@ -17,19 +17,20 @@ limitations under the License.
"use strict"; "use strict";
let Olm = null;
try { try {
var Olm = require('olm'); Olm = require('olm');
} catch (e) {} } catch (e) {}
let anotherjson = require('another-json'); const anotherjson = require('another-json');
let q = require('q'); const q = require('q');
let sdk = require('../..'); const sdk = require('../..');
let utils = require('../../lib/utils'); const utils = require('../../lib/utils');
let test_utils = require('../test-utils'); const testUtils = require('../test-utils');
let MockHttpBackend = require('../mock-request'); const MockHttpBackend = require('../mock-request');
let ROOM_ID = "!room:id"; const ROOM_ID = "!room:id";
/** /**
* Wrapper for a MockStorageApi, MockHttpBackend and MatrixClient * Wrapper for a MockStorageApi, MockHttpBackend and MatrixClient
@@ -43,7 +44,7 @@ function TestClient(userId, deviceId, accessToken) {
this.userId = userId; this.userId = userId;
this.deviceId = deviceId; this.deviceId = deviceId;
this.storage = new sdk.WebStorageSessionStore(new test_utils.MockStorageApi()); this.storage = new sdk.WebStorageSessionStore(new testUtils.MockStorageApi());
this.httpBackend = new MockHttpBackend(); this.httpBackend = new MockHttpBackend();
this.client = sdk.createClient({ this.client = sdk.createClient({
baseUrl: "http://test.server", baseUrl: "http://test.server",
@@ -66,7 +67,7 @@ function TestClient(userId, deviceId, accessToken) {
* @return {Promise} * @return {Promise}
*/ */
TestClient.prototype.start = function(existingDevices) { TestClient.prototype.start = function(existingDevices) {
let self = this; const self = this;
this.httpBackend.when("GET", "/pushrules").respond(200, {}); this.httpBackend.when("GET", "/pushrules").respond(200, {});
this.httpBackend.when("POST", "/filter").respond(200, { filter_id: "fid" }); this.httpBackend.when("POST", "/filter").respond(200, { filter_id: "fid" });
@@ -114,8 +115,8 @@ TestClient.prototype.stop = function() {
* @return {string} base64 device key * @return {string} base64 device key
*/ */
TestClient.prototype.getDeviceKey = function() { TestClient.prototype.getDeviceKey = function() {
let key_id = 'curve25519:' + this.deviceId; const keyId = 'curve25519:' + this.deviceId;
return this.deviceKeys.keys[key_id]; return this.deviceKeys.keys[keyId];
}; };
@@ -125,8 +126,8 @@ TestClient.prototype.getDeviceKey = function() {
* @return {string} base64 device key * @return {string} base64 device key
*/ */
TestClient.prototype.getSigningKey = function() { TestClient.prototype.getSigningKey = function() {
let key_id = 'ed25519:' + this.deviceId; const keyId = 'ed25519:' + this.deviceId;
return this.deviceKeys.keys[key_id]; return this.deviceKeys.keys[keyId];
}; };
/** /**
@@ -137,12 +138,12 @@ TestClient.prototype.getSigningKey = function() {
* @return {Olm.Session} * @return {Olm.Session}
*/ */
function createOlmSession(olmAccount, recipientTestClient) { function createOlmSession(olmAccount, recipientTestClient) {
let otk_id = utils.keys(recipientTestClient.oneTimeKeys)[0]; const otkId = utils.keys(recipientTestClient.oneTimeKeys)[0];
let otk = recipientTestClient.oneTimeKeys[otk_id]; const otk = recipientTestClient.oneTimeKeys[otkId];
let session = new Olm.Session(); const session = new Olm.Session();
session.create_outbound( session.create_outbound(
olmAccount, recipientTestClient.getDeviceKey(), otk.key olmAccount, recipientTestClient.getDeviceKey(), otk.key,
); );
return session; return session;
} }
@@ -165,7 +166,7 @@ function encryptOlmEvent(opts) {
expect(opts.p2pSession).toBeDefined(); expect(opts.p2pSession).toBeDefined();
expect(opts.recipient).toBeDefined(); expect(opts.recipient).toBeDefined();
let plaintext = { const plaintext = {
content: opts.plaincontent || {}, content: opts.plaincontent || {},
recipient: opts.recipient.userId, recipient: opts.recipient.userId,
recipient_keys: { recipient_keys: {
@@ -175,7 +176,7 @@ function encryptOlmEvent(opts) {
type: opts.plaintype || 'm.test', type: opts.plaintype || 'm.test',
}; };
let event = { const event = {
content: { content: {
algorithm: 'm.olm.v1.curve25519-aes-sha2', algorithm: 'm.olm.v1.curve25519-aes-sha2',
ciphertext: {}, ciphertext: {},
@@ -204,7 +205,7 @@ function encryptMegolmEvent(opts) {
expect(opts.senderKey).toBeDefined(); expect(opts.senderKey).toBeDefined();
expect(opts.groupSession).toBeDefined(); expect(opts.groupSession).toBeDefined();
let plaintext = opts.plaintext || {}; const plaintext = opts.plaintext || {};
if (!plaintext.content) { if (!plaintext.content) {
plaintext.content = { plaintext.content = {
body: '42', body: '42',
@@ -267,10 +268,10 @@ function encryptGroupSessionKey(opts) {
* @return {object} event * @return {object} event
*/ */
function getSyncResponse(roomMembers) { function getSyncResponse(roomMembers) {
let roomResponse = { const roomResponse = {
state: { state: {
events: [ events: [
test_utils.mkEvent({ testUtils.mkEvent({
type: 'm.room.encryption', type: 'm.room.encryption',
skey: '', skey: '',
content: { content: {
@@ -283,14 +284,14 @@ function getSyncResponse(roomMembers) {
for (let i = 0; i < roomMembers.length; i++) { for (let i = 0; i < roomMembers.length; i++) {
roomResponse.state.events.push( roomResponse.state.events.push(
test_utils.mkMembership({ testUtils.mkMembership({
mship: 'join', mship: 'join',
sender: roomMembers[i], sender: roomMembers[i],
}) }),
); );
} }
let syncResponse = { const syncResponse = {
next_batch: 1, next_batch: 1,
rooms: { rooms: {
join: {}, join: {},
@@ -318,8 +319,8 @@ describe("megolm", function() {
* @returns {Object} The fake query response * @returns {Object} The fake query response
*/ */
function getTestKeysQueryResponse(userId) { function getTestKeysQueryResponse(userId) {
let testE2eKeys = JSON.parse(testOlmAccount.identity_keys()); const testE2eKeys = JSON.parse(testOlmAccount.identity_keys());
let testDeviceKeys = { const testDeviceKeys = {
algorithms: ['m.olm.v1.curve25519-aes-sha2', 'm.megolm.v1.aes-sha2'], algorithms: ['m.olm.v1.curve25519-aes-sha2', 'm.megolm.v1.aes-sha2'],
device_id: 'DEVICE_ID', device_id: 'DEVICE_ID',
keys: { keys: {
@@ -328,14 +329,14 @@ describe("megolm", function() {
}, },
user_id: userId, user_id: userId,
}; };
let j = anotherjson.stringify(testDeviceKeys); const j = anotherjson.stringify(testDeviceKeys);
let sig = testOlmAccount.sign(j); const sig = testOlmAccount.sign(j);
testDeviceKeys.signatures = {}; testDeviceKeys.signatures = {};
testDeviceKeys.signatures[userId] = { testDeviceKeys.signatures[userId] = {
'ed25519:DEVICE_ID': sig, 'ed25519:DEVICE_ID': sig,
}; };
let queryResponse = { const queryResponse = {
device_keys: {}, device_keys: {},
}; };
@@ -355,22 +356,22 @@ describe("megolm", function() {
*/ */
function getTestKeysClaimResponse(userId) { function getTestKeysClaimResponse(userId) {
testOlmAccount.generate_one_time_keys(1); testOlmAccount.generate_one_time_keys(1);
let testOneTimeKeys = JSON.parse(testOlmAccount.one_time_keys()); const testOneTimeKeys = JSON.parse(testOlmAccount.one_time_keys());
testOlmAccount.mark_keys_as_published(); testOlmAccount.mark_keys_as_published();
let keyId = utils.keys(testOneTimeKeys.curve25519)[0]; const keyId = utils.keys(testOneTimeKeys.curve25519)[0];
let oneTimeKey = testOneTimeKeys.curve25519[keyId]; const oneTimeKey = testOneTimeKeys.curve25519[keyId];
let keyResult = { const keyResult = {
'key': oneTimeKey, 'key': oneTimeKey,
}; };
let j = anotherjson.stringify(keyResult); const j = anotherjson.stringify(keyResult);
let sig = testOlmAccount.sign(j); const sig = testOlmAccount.sign(j);
keyResult.signatures = {}; keyResult.signatures = {};
keyResult.signatures[userId] = { keyResult.signatures[userId] = {
'ed25519:DEVICE_ID': sig, 'ed25519:DEVICE_ID': sig,
}; };
let claimResponse = {one_time_keys: {}}; const claimResponse = {one_time_keys: {}};
claimResponse.one_time_keys[userId] = { claimResponse.one_time_keys[userId] = {
'DEVICE_ID': {}, 'DEVICE_ID': {},
}; };
@@ -380,15 +381,15 @@ describe("megolm", function() {
} }
beforeEach(function() { beforeEach(function() {
test_utils.beforeEach(this); // eslint-disable-line no-invalid-this testUtils.beforeEach(this); // eslint-disable-line no-invalid-this
aliceTestClient = new TestClient( aliceTestClient = new TestClient(
"@alice:localhost", "xzcvb", "akjgkrgjs" "@alice:localhost", "xzcvb", "akjgkrgjs",
); );
testOlmAccount = new Olm.Account(); testOlmAccount = new Olm.Account();
testOlmAccount.create(); testOlmAccount.create();
let testE2eKeys = JSON.parse(testOlmAccount.identity_keys()); const testE2eKeys = JSON.parse(testOlmAccount.identity_keys());
testSenderKey = testE2eKeys.curve25519; testSenderKey = testE2eKeys.curve25519;
}); });
@@ -398,13 +399,13 @@ describe("megolm", function() {
it("Alice receives a megolm message", function(done) { it("Alice receives a megolm message", function(done) {
return aliceTestClient.start().then(function() { return aliceTestClient.start().then(function() {
let p2pSession = createOlmSession(testOlmAccount, aliceTestClient); const p2pSession = createOlmSession(testOlmAccount, aliceTestClient);
let groupSession = new Olm.OutboundGroupSession(); const groupSession = new Olm.OutboundGroupSession();
groupSession.create(); groupSession.create();
// make the room_key event // make the room_key event
let roomKeyEncrypted = encryptGroupSessionKey({ const roomKeyEncrypted = encryptGroupSessionKey({
senderKey: testSenderKey, senderKey: testSenderKey,
recipient: aliceTestClient, recipient: aliceTestClient,
p2pSession: p2pSession, p2pSession: p2pSession,
@@ -413,14 +414,14 @@ describe("megolm", function() {
}); });
// encrypt a message with the group session // encrypt a message with the group session
let messageEncrypted = encryptMegolmEvent({ const messageEncrypted = encryptMegolmEvent({
senderKey: testSenderKey, senderKey: testSenderKey,
groupSession: groupSession, groupSession: groupSession,
room_id: ROOM_ID, room_id: ROOM_ID,
}); });
// Alice gets both the events in a single sync // Alice gets both the events in a single sync
let syncResponse = { const syncResponse = {
next_batch: 1, next_batch: 1,
to_device: { to_device: {
events: [roomKeyEncrypted], events: [roomKeyEncrypted],
@@ -438,21 +439,21 @@ describe("megolm", function() {
aliceTestClient.httpBackend.when("GET", "/sync").respond(200, syncResponse); aliceTestClient.httpBackend.when("GET", "/sync").respond(200, syncResponse);
return aliceTestClient.httpBackend.flush("/sync", 1); return aliceTestClient.httpBackend.flush("/sync", 1);
}).then(function() { }).then(function() {
let room = aliceTestClient.client.getRoom(ROOM_ID); const room = aliceTestClient.client.getRoom(ROOM_ID);
let event = room.getLiveTimeline().getEvents()[0]; const event = room.getLiveTimeline().getEvents()[0];
expect(event.getContent().body).toEqual('42'); expect(event.getContent().body).toEqual('42');
}).nodeify(done); }).nodeify(done);
}); });
it("Alice gets a second room_key message", function(done) { it("Alice gets a second room_key message", function(done) {
return aliceTestClient.start().then(function() { return aliceTestClient.start().then(function() {
let p2pSession = createOlmSession(testOlmAccount, aliceTestClient); const p2pSession = createOlmSession(testOlmAccount, aliceTestClient);
let groupSession = new Olm.OutboundGroupSession(); const groupSession = new Olm.OutboundGroupSession();
groupSession.create(); groupSession.create();
// make the room_key event // make the room_key event
let roomKeyEncrypted1 = encryptGroupSessionKey({ const roomKeyEncrypted1 = encryptGroupSessionKey({
senderKey: testSenderKey, senderKey: testSenderKey,
recipient: aliceTestClient, recipient: aliceTestClient,
p2pSession: p2pSession, p2pSession: p2pSession,
@@ -461,7 +462,7 @@ describe("megolm", function() {
}); });
// encrypt a message with the group session // encrypt a message with the group session
let messageEncrypted = encryptMegolmEvent({ const messageEncrypted = encryptMegolmEvent({
senderKey: testSenderKey, senderKey: testSenderKey,
groupSession: groupSession, groupSession: groupSession,
room_id: ROOM_ID, room_id: ROOM_ID,
@@ -469,7 +470,7 @@ describe("megolm", function() {
// make a second room_key event now that we have advanced the group // make a second room_key event now that we have advanced the group
// session. // session.
let roomKeyEncrypted2 = encryptGroupSessionKey({ const roomKeyEncrypted2 = encryptGroupSessionKey({
senderKey: testSenderKey, senderKey: testSenderKey,
recipient: aliceTestClient, recipient: aliceTestClient,
p2pSession: p2pSession, p2pSession: p2pSession,
@@ -488,7 +489,7 @@ describe("megolm", function() {
// on the second sync, send the advanced room key, along with the // on the second sync, send the advanced room key, along with the
// message. This simulates the situation where Alice has been sent a // message. This simulates the situation where Alice has been sent a
// later copy of the room key and is reloading the client. // later copy of the room key and is reloading the client.
let syncResponse2 = { const syncResponse2 = {
next_batch: 2, next_batch: 2,
to_device: { to_device: {
events: [roomKeyEncrypted2], events: [roomKeyEncrypted2],
@@ -506,8 +507,8 @@ describe("megolm", function() {
return aliceTestClient.httpBackend.flush("/sync", 2); return aliceTestClient.httpBackend.flush("/sync", 2);
}).then(function() { }).then(function() {
let room = aliceTestClient.client.getRoom(ROOM_ID); const room = aliceTestClient.client.getRoom(ROOM_ID);
let event = room.getLiveTimeline().getEvents()[0]; const event = room.getLiveTimeline().getEvents()[0];
expect(event.getContent().body).toEqual('42'); expect(event.getContent().body).toEqual('42');
}).nodeify(done); }).nodeify(done);
}); });
@@ -516,12 +517,12 @@ describe("megolm", function() {
let p2pSession; let p2pSession;
return aliceTestClient.start().then(function() { return aliceTestClient.start().then(function() {
let syncResponse = getSyncResponse(['@bob:xyz']); const syncResponse = getSyncResponse(['@bob:xyz']);
// establish an olm session with alice // establish an olm session with alice
p2pSession = createOlmSession(testOlmAccount, aliceTestClient); p2pSession = createOlmSession(testOlmAccount, aliceTestClient);
let olmEvent = encryptOlmEvent({ const olmEvent = encryptOlmEvent({
senderKey: testSenderKey, senderKey: testSenderKey,
recipient: aliceTestClient, recipient: aliceTestClient,
p2pSession: p2pSession, p2pSession: p2pSession,
@@ -534,15 +535,15 @@ describe("megolm", function() {
}).then(function() { }).then(function() {
let inboundGroupSession; let inboundGroupSession;
aliceTestClient.httpBackend.when('POST', '/keys/query').respond( aliceTestClient.httpBackend.when('POST', '/keys/query').respond(
200, getTestKeysQueryResponse('@bob:xyz') 200, getTestKeysQueryResponse('@bob:xyz'),
); );
aliceTestClient.httpBackend.when( aliceTestClient.httpBackend.when(
'PUT', '/sendToDevice/m.room.encrypted/' 'PUT', '/sendToDevice/m.room.encrypted/',
).respond(200, function(path, content) { ).respond(200, function(path, content) {
let m = content.messages['@bob:xyz'].DEVICE_ID; const m = content.messages['@bob:xyz'].DEVICE_ID;
let ct = m.ciphertext[testSenderKey]; const ct = m.ciphertext[testSenderKey];
let decrypted = JSON.parse(p2pSession.decrypt(ct.type, ct.body)); const decrypted = JSON.parse(p2pSession.decrypt(ct.type, ct.body));
expect(decrypted.type).toEqual('m.room_key'); expect(decrypted.type).toEqual('m.room_key');
inboundGroupSession = new Olm.InboundGroupSession(); inboundGroupSession = new Olm.InboundGroupSession();
@@ -551,14 +552,14 @@ describe("megolm", function() {
}); });
aliceTestClient.httpBackend.when( aliceTestClient.httpBackend.when(
'PUT', '/send/' 'PUT', '/send/',
).respond(200, function(path, content) { ).respond(200, function(path, content) {
let ct = content.ciphertext; const ct = content.ciphertext;
let r = inboundGroupSession.decrypt(ct); const r = inboundGroupSession.decrypt(ct);
console.log('Decrypted received megolm message', r); console.log('Decrypted received megolm message', r);
expect(r.message_index).toEqual(0); expect(r.message_index).toEqual(0);
let decrypted = JSON.parse(r.plaintext); const decrypted = JSON.parse(r.plaintext);
expect(decrypted.type).toEqual('m.room.message'); expect(decrypted.type).toEqual('m.room.message');
expect(decrypted.content.body).toEqual('test'); expect(decrypted.content.body).toEqual('test');
@@ -576,7 +577,7 @@ describe("megolm", function() {
it("Alice shouldn't do a second /query for non-e2e-capable devices", function(done) { it("Alice shouldn't do a second /query for non-e2e-capable devices", function(done) {
return aliceTestClient.start().then(function() { return aliceTestClient.start().then(function() {
let syncResponse = getSyncResponse(['@bob:xyz']); const syncResponse = getSyncResponse(['@bob:xyz']);
aliceTestClient.httpBackend.when('GET', '/sync').respond(200, syncResponse); aliceTestClient.httpBackend.when('GET', '/sync').respond(200, syncResponse);
return aliceTestClient.httpBackend.flush('/sync', 1); return aliceTestClient.httpBackend.flush('/sync', 1);
@@ -597,7 +598,7 @@ describe("megolm", function() {
console.log("Telling alice to send a megolm message"); console.log("Telling alice to send a megolm message");
aliceTestClient.httpBackend.when( aliceTestClient.httpBackend.when(
'PUT', '/send/' 'PUT', '/send/',
).respond(200, { ).respond(200, {
event_id: '$event_id', event_id: '$event_id',
}); });
@@ -612,12 +613,12 @@ describe("megolm", function() {
it("We shouldn't attempt to send to blocked devices", function(done) { it("We shouldn't attempt to send to blocked devices", function(done) {
return aliceTestClient.start().then(function() { return aliceTestClient.start().then(function() {
let syncResponse = getSyncResponse(['@bob:xyz']); const syncResponse = getSyncResponse(['@bob:xyz']);
// establish an olm session with alice // establish an olm session with alice
let p2pSession = createOlmSession(testOlmAccount, aliceTestClient); const p2pSession = createOlmSession(testOlmAccount, aliceTestClient);
let olmEvent = encryptOlmEvent({ const olmEvent = encryptOlmEvent({
senderKey: testSenderKey, senderKey: testSenderKey,
recipient: aliceTestClient, recipient: aliceTestClient,
p2pSession: p2pSession, p2pSession: p2pSession,
@@ -631,7 +632,7 @@ describe("megolm", function() {
console.log('Forcing alice to download our device keys'); console.log('Forcing alice to download our device keys');
aliceTestClient.httpBackend.when('POST', '/keys/query').respond( aliceTestClient.httpBackend.when('POST', '/keys/query').respond(
200, getTestKeysQueryResponse('@bob:xyz') 200, getTestKeysQueryResponse('@bob:xyz'),
); );
return q.all([ return q.all([
@@ -644,7 +645,7 @@ describe("megolm", function() {
console.log('Telling alice to send a megolm message'); console.log('Telling alice to send a megolm message');
aliceTestClient.httpBackend.when( aliceTestClient.httpBackend.when(
'PUT', '/send/' 'PUT', '/send/',
).respond(200, { ).respond(200, {
event_id: '$event_id', event_id: '$event_id',
}); });
@@ -661,12 +662,12 @@ describe("megolm", function() {
let megolmSessionId; let megolmSessionId;
return aliceTestClient.start().then(function() { return aliceTestClient.start().then(function() {
let syncResponse = getSyncResponse(['@bob:xyz']); const syncResponse = getSyncResponse(['@bob:xyz']);
// establish an olm session with alice // establish an olm session with alice
p2pSession = createOlmSession(testOlmAccount, aliceTestClient); p2pSession = createOlmSession(testOlmAccount, aliceTestClient);
let olmEvent = encryptOlmEvent({ const olmEvent = encryptOlmEvent({
senderKey: testSenderKey, senderKey: testSenderKey,
recipient: aliceTestClient, recipient: aliceTestClient,
p2pSession: p2pSession, p2pSession: p2pSession,
@@ -680,17 +681,17 @@ describe("megolm", function() {
console.log('Telling alice to send a megolm message'); console.log('Telling alice to send a megolm message');
aliceTestClient.httpBackend.when('POST', '/keys/query').respond( aliceTestClient.httpBackend.when('POST', '/keys/query').respond(
200, getTestKeysQueryResponse('@bob:xyz') 200, getTestKeysQueryResponse('@bob:xyz'),
); );
aliceTestClient.httpBackend.when( aliceTestClient.httpBackend.when(
'PUT', '/sendToDevice/m.room.encrypted/' 'PUT', '/sendToDevice/m.room.encrypted/',
).respond(200, function(path, content) { ).respond(200, function(path, content) {
console.log('sendToDevice: ', content); console.log('sendToDevice: ', content);
let m = content.messages['@bob:xyz'].DEVICE_ID; const m = content.messages['@bob:xyz'].DEVICE_ID;
let ct = m.ciphertext[testSenderKey]; const ct = m.ciphertext[testSenderKey];
expect(ct.type).toEqual(1); // normal message expect(ct.type).toEqual(1); // normal message
let decrypted = JSON.parse(p2pSession.decrypt(ct.type, ct.body)); const decrypted = JSON.parse(p2pSession.decrypt(ct.type, ct.body));
console.log('decrypted sendToDevice:', decrypted); console.log('decrypted sendToDevice:', decrypted);
expect(decrypted.type).toEqual('m.room_key'); expect(decrypted.type).toEqual('m.room_key');
megolmSessionId = decrypted.content.session_id; megolmSessionId = decrypted.content.session_id;
@@ -698,7 +699,7 @@ describe("megolm", function() {
}); });
aliceTestClient.httpBackend.when( aliceTestClient.httpBackend.when(
'PUT', '/send/' 'PUT', '/send/',
).respond(200, function(path, content) { ).respond(200, function(path, content) {
console.log('/send:', content); console.log('/send:', content);
expect(content.session_id).toEqual(megolmSessionId); expect(content.session_id).toEqual(megolmSessionId);
@@ -717,7 +718,7 @@ describe("megolm", function() {
console.log('Telling alice to send another megolm message'); console.log('Telling alice to send another megolm message');
aliceTestClient.httpBackend.when( aliceTestClient.httpBackend.when(
'PUT', '/send/' 'PUT', '/send/',
).respond(200, function(path, content) { ).respond(200, function(path, content) {
console.log('/send:', content); console.log('/send:', content);
expect(content.session_id).not.toEqual(megolmSessionId); expect(content.session_id).not.toEqual(megolmSessionId);
@@ -743,10 +744,10 @@ describe("megolm", function() {
let decrypted; let decrypted;
return aliceTestClient.start( return aliceTestClient.start(
getTestKeysQueryResponse(aliceTestClient.userId) getTestKeysQueryResponse(aliceTestClient.userId),
).then(function() { ).then(function() {
// an encrypted room with just alice // an encrypted room with just alice
let syncResponse = { const syncResponse = {
next_batch: 1, next_batch: 1,
rooms: { rooms: {
join: {}, join: {},
@@ -755,14 +756,14 @@ describe("megolm", function() {
syncResponse.rooms.join[ROOM_ID] = { syncResponse.rooms.join[ROOM_ID] = {
state: { state: {
events: [ events: [
test_utils.mkEvent({ testUtils.mkEvent({
type: 'm.room.encryption', type: 'm.room.encryption',
skey: '', skey: '',
content: { content: {
algorithm: 'm.megolm.v1.aes-sha2', algorithm: 'm.megolm.v1.aes-sha2',
}, },
}), }),
test_utils.mkMembership({ testUtils.mkMembership({
mship: 'join', mship: 'join',
sender: aliceTestClient.userId, sender: aliceTestClient.userId,
}), }),
@@ -781,16 +782,16 @@ describe("megolm", function() {
}); });
aliceTestClient.httpBackend.when( aliceTestClient.httpBackend.when(
'PUT', '/sendToDevice/m.room.encrypted/' 'PUT', '/sendToDevice/m.room.encrypted/',
).respond(200, function(path, content) { ).respond(200, function(path, content) {
console.log("sendToDevice: ", content); console.log("sendToDevice: ", content);
let m = content.messages[aliceTestClient.userId].DEVICE_ID; const m = content.messages[aliceTestClient.userId].DEVICE_ID;
let ct = m.ciphertext[testSenderKey]; const ct = m.ciphertext[testSenderKey];
expect(ct.type).toEqual(0); // pre-key message expect(ct.type).toEqual(0); // pre-key message
p2pSession = new Olm.Session(); p2pSession = new Olm.Session();
p2pSession.create_inbound(testOlmAccount, ct.body); p2pSession.create_inbound(testOlmAccount, ct.body);
let decrypted = JSON.parse(p2pSession.decrypt(ct.type, ct.body)); const decrypted = JSON.parse(p2pSession.decrypt(ct.type, ct.body));
expect(decrypted.type).toEqual('m.room_key'); expect(decrypted.type).toEqual('m.room_key');
inboundGroupSession = new Olm.InboundGroupSession(); inboundGroupSession = new Olm.InboundGroupSession();
@@ -799,10 +800,10 @@ describe("megolm", function() {
}); });
aliceTestClient.httpBackend.when( aliceTestClient.httpBackend.when(
'PUT', '/send/' 'PUT', '/send/',
).respond(200, function(path, content) { ).respond(200, function(path, content) {
let ct = content.ciphertext; const ct = content.ciphertext;
let r = inboundGroupSession.decrypt(ct); const r = inboundGroupSession.decrypt(ct);
console.log('Decrypted received megolm message', r); console.log('Decrypted received megolm message', r);
decrypted = JSON.parse(r.plaintext); decrypted = JSON.parse(r.plaintext);
@@ -831,11 +832,11 @@ describe("megolm", function() {
let sendPromise; let sendPromise;
aliceTestClient.httpBackend.when( aliceTestClient.httpBackend.when(
'PUT', '/sendToDevice/m.room.encrypted/' 'PUT', '/sendToDevice/m.room.encrypted/',
).respond(200, function(path, content) { ).respond(200, function(path, content) {
let m = content.messages['@bob:xyz'].DEVICE_ID; const m = content.messages['@bob:xyz'].DEVICE_ID;
let ct = m.ciphertext[testSenderKey]; const ct = m.ciphertext[testSenderKey];
let decrypted = JSON.parse(p2pSession.decrypt(ct.type, ct.body)); const decrypted = JSON.parse(p2pSession.decrypt(ct.type, ct.body));
expect(decrypted.type).toEqual('m.room_key'); expect(decrypted.type).toEqual('m.room_key');
inboundGroupSession = new Olm.InboundGroupSession(); inboundGroupSession = new Olm.InboundGroupSession();
@@ -844,14 +845,14 @@ describe("megolm", function() {
}); });
aliceTestClient.httpBackend.when( aliceTestClient.httpBackend.when(
'PUT', '/send/' 'PUT', '/send/',
).respond(200, function(path, content) { ).respond(200, function(path, content) {
let ct = content.ciphertext; const ct = content.ciphertext;
let r = inboundGroupSession.decrypt(ct); const r = inboundGroupSession.decrypt(ct);
console.log('Decrypted received megolm message', r); console.log('Decrypted received megolm message', r);
expect(r.message_index).toEqual(0); expect(r.message_index).toEqual(0);
let decrypted = JSON.parse(r.plaintext); const decrypted = JSON.parse(r.plaintext);
expect(decrypted.type).toEqual('m.room.message'); expect(decrypted.type).toEqual('m.room.message');
expect(decrypted.content.body).toEqual('test'); expect(decrypted.content.body).toEqual('test');
@@ -861,12 +862,12 @@ describe("megolm", function() {
}); });
return aliceTestClient.start().then(function() { return aliceTestClient.start().then(function() {
let syncResponse = getSyncResponse(['@bob:xyz']); const syncResponse = getSyncResponse(['@bob:xyz']);
// establish an olm session with alice // establish an olm session with alice
p2pSession = createOlmSession(testOlmAccount, aliceTestClient); p2pSession = createOlmSession(testOlmAccount, aliceTestClient);
let olmEvent = encryptOlmEvent({ const olmEvent = encryptOlmEvent({
senderKey: testSenderKey, senderKey: testSenderKey,
recipient: aliceTestClient, recipient: aliceTestClient,
p2pSession: p2pSession, p2pSession: p2pSession,
@@ -886,7 +887,7 @@ describe("megolm", function() {
sendPromise = aliceTestClient.client.sendTextMessage(ROOM_ID, 'test'); sendPromise = aliceTestClient.client.sendTextMessage(ROOM_ID, 'test');
}).then(function() { }).then(function() {
aliceTestClient.httpBackend.when('POST', '/keys/query').respond( aliceTestClient.httpBackend.when('POST', '/keys/query').respond(
200, getTestKeysQueryResponse('@bob:xyz') 200, getTestKeysQueryResponse('@bob:xyz'),
); );
return aliceTestClient.httpBackend.flush(); return aliceTestClient.httpBackend.flush();
@@ -894,4 +895,89 @@ describe("megolm", function() {
return q.all([downloadPromise, sendPromise]); return q.all([downloadPromise, sendPromise]);
}).nodeify(done); }).nodeify(done);
}); });
it("Alice exports megolm keys and imports them to a new device", function(done) {
let messageEncrypted;
return aliceTestClient.start().then(() => {
const p2pSession = createOlmSession(
testOlmAccount, aliceTestClient,
);
const groupSession = new Olm.OutboundGroupSession();
groupSession.create();
// make the room_key event
const roomKeyEncrypted = encryptGroupSessionKey({
senderKey: testSenderKey,
recipient: aliceTestClient,
p2pSession: p2pSession,
groupSession: groupSession,
room_id: ROOM_ID,
});
// encrypt a message with the group session
messageEncrypted = encryptMegolmEvent({
senderKey: testSenderKey,
groupSession: groupSession,
room_id: ROOM_ID,
});
// Alice gets both the events in a single sync
const syncResponse = {
next_batch: 1,
to_device: {
events: [roomKeyEncrypted],
},
rooms: {
join: {},
},
};
syncResponse.rooms.join[ROOM_ID] = {
timeline: {
events: [messageEncrypted],
},
};
aliceTestClient.httpBackend.when("GET", "/sync").respond(200, syncResponse);
return aliceTestClient.httpBackend.flush("/sync", 1);
}).then(function() {
const room = aliceTestClient.client.getRoom(ROOM_ID);
const event = room.getLiveTimeline().getEvents()[0];
expect(event.getContent().body).toEqual('42');
return aliceTestClient.client.exportRoomKeys();
}).then(function(exported) {
// start a new client
aliceTestClient.stop();
aliceTestClient = new TestClient(
"@alice:localhost", "device2", "access_token2",
);
aliceTestClient.client.importRoomKeys(exported);
return aliceTestClient.start();
}).then(function() {
const syncResponse = {
next_batch: 1,
rooms: {
join: {},
},
};
syncResponse.rooms.join[ROOM_ID] = {
timeline: {
events: [messageEncrypted],
},
};
aliceTestClient.httpBackend.when("GET", "/sync").respond(200, syncResponse);
return aliceTestClient.httpBackend.flush("/sync", 1);
}).then(function() {
const room = aliceTestClient.client.getRoom(ROOM_ID);
const event = room.getLiveTimeline().getEvents()[0];
expect(event.getContent().body).toEqual('42');
}).nodeify(done);
});
}); });

View File

@@ -1,5 +1,5 @@
"use strict"; "use strict";
let q = require("q"); const q = require("q");
/** /**
* Construct a mock HTTP backend, heavily inspired by Angular.js. * Construct a mock HTTP backend, heavily inspired by Angular.js.
@@ -8,15 +8,15 @@ let q = require("q");
function HttpBackend() { function HttpBackend() {
this.requests = []; this.requests = [];
this.expectedRequests = []; this.expectedRequests = [];
let self = this; const self = this;
// the request function dependency that the SDK needs. // the request function dependency that the SDK needs.
this.requestFn = function(opts, callback) { this.requestFn = function(opts, callback) {
let req = new Request(opts, callback); const req = new Request(opts, callback);
console.log("HTTP backend received request: %s", req); console.log("HTTP backend received request: %s", req);
self.requests.push(req); self.requests.push(req);
let abort = function() { const abort = function() {
let idx = self.requests.indexOf(req); const idx = self.requests.indexOf(req);
if (idx >= 0) { if (idx >= 0) {
console.log("Aborting HTTP request: %s %s", opts.method, console.log("Aborting HTTP request: %s %s", opts.method,
opts.uri); opts.uri);
@@ -38,18 +38,18 @@ HttpBackend.prototype = {
* @return {Promise} resolved when there is nothing left to flush. * @return {Promise} resolved when there is nothing left to flush.
*/ */
flush: function(path, numToFlush) { flush: function(path, numToFlush) {
let defer = q.defer(); const defer = q.defer();
let self = this; const self = this;
let flushed = 0; let flushed = 0;
let triedWaiting = false; let triedWaiting = false;
console.log( console.log(
"HTTP backend flushing... (path=%s numToFlush=%s)", path, numToFlush "HTTP backend flushing... (path=%s numToFlush=%s)", path, numToFlush,
); );
let tryFlush = function() { const tryFlush = function() {
// if there's more real requests and more expected requests, flush 'em. // if there's more real requests and more expected requests, flush 'em.
console.log( console.log(
" trying to flush queue => reqs=%s expected=%s [%s]", " trying to flush queue => reqs=%s expected=%s [%s]",
self.requests.length, self.expectedRequests.length, path self.requests.length, self.expectedRequests.length, path,
); );
if (self._takeFromQueue(path)) { if (self._takeFromQueue(path)) {
// try again on the next tick. // try again on the next tick.
@@ -84,8 +84,11 @@ HttpBackend.prototype = {
*/ */
_takeFromQueue: function(path) { _takeFromQueue: function(path) {
let req = null; let req = null;
let i, j; let i;
let matchingReq, expectedReq, testResponse = null; let j;
let matchingReq = null;
let expectedReq = null;
let testResponse = null;
for (i = 0; i < this.requests.length; i++) { for (i = 0; i < this.requests.length; i++) {
req = this.requests[i]; req = this.requests[i];
for (j = 0; j < this.expectedRequests.length; j++) { for (j = 0; j < this.expectedRequests.length; j++) {
@@ -119,7 +122,7 @@ HttpBackend.prototype = {
body = body(req.path, req.data); body = body(req.path, req.data);
} }
req.callback( req.callback(
testResponse.err, testResponse.response, body testResponse.err, testResponse.response, body,
); );
matchingReq = null; matchingReq = null;
} }
@@ -134,10 +137,10 @@ HttpBackend.prototype = {
* Makes sure that the SDK hasn't sent any more requests to the backend. * Makes sure that the SDK hasn't sent any more requests to the backend.
*/ */
verifyNoOutstandingRequests: function() { verifyNoOutstandingRequests: function() {
let firstOutstandingReq = this.requests[0] || {}; const firstOutstandingReq = this.requests[0] || {};
expect(this.requests.length).toEqual(0, expect(this.requests.length).toEqual(0,
"Expected no more HTTP requests but received request to " + "Expected no more HTTP requests but received request to " +
firstOutstandingReq.path firstOutstandingReq.path,
); );
}, },
@@ -145,9 +148,9 @@ HttpBackend.prototype = {
* Makes sure that the test doesn't have any unresolved requests. * Makes sure that the test doesn't have any unresolved requests.
*/ */
verifyNoOutstandingExpectation: function() { verifyNoOutstandingExpectation: function() {
let firstOutstandingExpectation = this.expectedRequests[0] || {}; const firstOutstandingExpectation = this.expectedRequests[0] || {};
expect(this.expectedRequests.length).toEqual(0, expect(this.expectedRequests.length).toEqual(0,
"Expected to see HTTP request for " + firstOutstandingExpectation.path "Expected to see HTTP request for " + firstOutstandingExpectation.path,
); );
}, },
@@ -159,7 +162,7 @@ HttpBackend.prototype = {
* @return {Request} An expected request. * @return {Request} An expected request.
*/ */
when: function(method, path, data) { when: function(method, path, data) {
let pendingReq = new ExpectedRequest(method, path, data); const pendingReq = new ExpectedRequest(method, path, data);
this.expectedRequests.push(pendingReq); this.expectedRequests.push(pendingReq);
return pendingReq; return pendingReq;
}, },

View File

@@ -1,6 +1,6 @@
"use strict"; "use strict";
let sdk = require(".."); const sdk = require("..");
let MatrixEvent = sdk.MatrixEvent; const MatrixEvent = sdk.MatrixEvent;
/** /**
* Perform common actions before each test case, e.g. printing the test case * Perform common actions before each test case, e.g. printing the test case
@@ -8,7 +8,7 @@ let MatrixEvent = sdk.MatrixEvent;
* @param {TestCase} testCase The test case that is about to be run. * @param {TestCase} testCase The test case that is about to be run.
*/ */
module.exports.beforeEach = function(testCase) { module.exports.beforeEach = function(testCase) {
let desc = testCase.suite.description + " : " + testCase.description; const desc = testCase.suite.description + " : " + testCase.description;
console.log(desc); console.log(desc);
console.log(new Array(1 + desc.length).join("=")); console.log(new Array(1 + desc.length).join("="));
}; };
@@ -22,13 +22,13 @@ module.exports.beforeEach = function(testCase) {
module.exports.mock = function(constr, name) { module.exports.mock = function(constr, name) {
// By Tim Buschtöns // By Tim Buschtöns
// http://eclipsesource.com/blogs/2014/03/27/mocks-in-jasmine-tests/ // http://eclipsesource.com/blogs/2014/03/27/mocks-in-jasmine-tests/
let HelperConstr = new Function(); // jshint ignore:line const HelperConstr = new Function(); // jshint ignore:line
HelperConstr.prototype = constr.prototype; HelperConstr.prototype = constr.prototype;
let result = new HelperConstr(); const result = new HelperConstr();
result.jasmineToString = function() { result.jasmineToString = function() {
return "mock" + (name ? " of " + name : ""); return "mock" + (name ? " of " + name : "");
}; };
for (let key in constr.prototype) { // eslint-disable-line guard-for-in for (const key in constr.prototype) { // eslint-disable-line guard-for-in
try { try {
if (constr.prototype[key] instanceof Function) { if (constr.prototype[key] instanceof Function) {
result[key] = jasmine.createSpy((name || "mock") + '.' + key); result[key] = jasmine.createSpy((name || "mock") + '.' + key);
@@ -57,7 +57,7 @@ module.exports.mkEvent = function(opts) {
if (!opts.type || !opts.content) { if (!opts.type || !opts.content) {
throw new Error("Missing .type or .content =>" + JSON.stringify(opts)); throw new Error("Missing .type or .content =>" + JSON.stringify(opts));
} }
let event = { const event = {
type: opts.type, type: opts.type,
room_id: opts.room, room_id: opts.room,
sender: opts.sender || opts.user, // opts.user for backwards-compat sender: opts.sender || opts.user, // opts.user for backwards-compat
@@ -83,7 +83,7 @@ module.exports.mkPresence = function(opts) {
if (!opts.user) { if (!opts.user) {
throw new Error("Missing user"); throw new Error("Missing user");
} }
let event = { const event = {
event_id: "$" + Math.random() + "-" + Math.random(), event_id: "$" + Math.random() + "-" + Math.random(),
type: "m.presence", type: "m.presence",
sender: opts.sender || opts.user, // opts.user for backwards-compat sender: opts.sender || opts.user, // opts.user for backwards-compat
@@ -193,6 +193,12 @@ module.exports.MockStorageApi = function() {
this.data = {}; this.data = {};
}; };
module.exports.MockStorageApi.prototype = { module.exports.MockStorageApi.prototype = {
get length() {
return Object.keys(this.data).length;
},
key: function(i) {
return Object.keys(this.data)[i];
},
setItem: function(k, v) { setItem: function(k, v) {
this.data[k] = v; this.data[k] = v;
}, },

View File

@@ -1,9 +1,9 @@
"use strict"; "use strict";
let ContentRepo = require("../../lib/content-repo"); const ContentRepo = require("../../lib/content-repo");
let testUtils = require("../test-utils"); const testUtils = require("../test-utils");
describe("ContentRepo", function() { describe("ContentRepo", function() {
let baseUrl = "https://my.home.server"; const baseUrl = "https://my.home.server";
beforeEach(function() { beforeEach(function() {
testUtils.beforeEach(this); // eslint-disable-line no-invalid-this testUtils.beforeEach(this); // eslint-disable-line no-invalid-this
@@ -11,24 +11,24 @@ describe("ContentRepo", function() {
describe("getHttpUriForMxc", function() { describe("getHttpUriForMxc", function() {
it("should do nothing to HTTP URLs when allowing direct links", function() { it("should do nothing to HTTP URLs when allowing direct links", function() {
let httpUrl = "http://example.com/image.jpeg"; const httpUrl = "http://example.com/image.jpeg";
expect( expect(
ContentRepo.getHttpUriForMxc( ContentRepo.getHttpUriForMxc(
baseUrl, httpUrl, undefined, undefined, undefined, true baseUrl, httpUrl, undefined, undefined, undefined, true,
) ),
).toEqual(httpUrl); ).toEqual(httpUrl);
}); });
it("should return the empty string HTTP URLs by default", function() { it("should return the empty string HTTP URLs by default", function() {
let httpUrl = "http://example.com/image.jpeg"; const httpUrl = "http://example.com/image.jpeg";
expect(ContentRepo.getHttpUriForMxc(baseUrl, httpUrl)).toEqual(""); expect(ContentRepo.getHttpUriForMxc(baseUrl, httpUrl)).toEqual("");
}); });
it("should return a download URL if no width/height/resize are specified", it("should return a download URL if no width/height/resize are specified",
function() { function() {
let mxcUri = "mxc://server.name/resourceid"; const mxcUri = "mxc://server.name/resourceid";
expect(ContentRepo.getHttpUriForMxc(baseUrl, mxcUri)).toEqual( expect(ContentRepo.getHttpUriForMxc(baseUrl, mxcUri)).toEqual(
baseUrl + "/_matrix/media/v1/download/server.name/resourceid" baseUrl + "/_matrix/media/v1/download/server.name/resourceid",
); );
}); });
@@ -38,27 +38,27 @@ describe("ContentRepo", function() {
it("should return a thumbnail URL if a width/height/resize is specified", it("should return a thumbnail URL if a width/height/resize is specified",
function() { function() {
let mxcUri = "mxc://server.name/resourceid"; const mxcUri = "mxc://server.name/resourceid";
expect(ContentRepo.getHttpUriForMxc(baseUrl, mxcUri, 32, 64, "crop")).toEqual( expect(ContentRepo.getHttpUriForMxc(baseUrl, mxcUri, 32, 64, "crop")).toEqual(
baseUrl + "/_matrix/media/v1/thumbnail/server.name/resourceid" + baseUrl + "/_matrix/media/v1/thumbnail/server.name/resourceid" +
"?width=32&height=64&method=crop" "?width=32&height=64&method=crop",
); );
}); });
it("should put fragments from mxc:// URIs after any query parameters", it("should put fragments from mxc:// URIs after any query parameters",
function() { function() {
let mxcUri = "mxc://server.name/resourceid#automade"; const mxcUri = "mxc://server.name/resourceid#automade";
expect(ContentRepo.getHttpUriForMxc(baseUrl, mxcUri, 32)).toEqual( expect(ContentRepo.getHttpUriForMxc(baseUrl, mxcUri, 32)).toEqual(
baseUrl + "/_matrix/media/v1/thumbnail/server.name/resourceid" + baseUrl + "/_matrix/media/v1/thumbnail/server.name/resourceid" +
"?width=32#automade" "?width=32#automade",
); );
}); });
it("should put fragments from mxc:// URIs at the end of the HTTP URI", it("should put fragments from mxc:// URIs at the end of the HTTP URI",
function() { function() {
let mxcUri = "mxc://server.name/resourceid#automade"; const mxcUri = "mxc://server.name/resourceid#automade";
expect(ContentRepo.getHttpUriForMxc(baseUrl, mxcUri)).toEqual( expect(ContentRepo.getHttpUriForMxc(baseUrl, mxcUri)).toEqual(
baseUrl + "/_matrix/media/v1/download/server.name/resourceid#automade" baseUrl + "/_matrix/media/v1/download/server.name/resourceid#automade",
); );
}); });
}); });
@@ -71,21 +71,21 @@ describe("ContentRepo", function() {
it("should set w/h by default to 96", function() { it("should set w/h by default to 96", function() {
expect(ContentRepo.getIdenticonUri(baseUrl, "foobar")).toEqual( expect(ContentRepo.getIdenticonUri(baseUrl, "foobar")).toEqual(
baseUrl + "/_matrix/media/v1/identicon/foobar" + baseUrl + "/_matrix/media/v1/identicon/foobar" +
"?width=96&height=96" "?width=96&height=96",
); );
}); });
it("should be able to set custom w/h", function() { it("should be able to set custom w/h", function() {
expect(ContentRepo.getIdenticonUri(baseUrl, "foobar", 32, 64)).toEqual( expect(ContentRepo.getIdenticonUri(baseUrl, "foobar", 32, 64)).toEqual(
baseUrl + "/_matrix/media/v1/identicon/foobar" + baseUrl + "/_matrix/media/v1/identicon/foobar" +
"?width=32&height=64" "?width=32&height=64",
); );
}); });
it("should URL encode the identicon string", function() { it("should URL encode the identicon string", function() {
expect(ContentRepo.getIdenticonUri(baseUrl, "foo#bar", 32, 64)).toEqual( expect(ContentRepo.getIdenticonUri(baseUrl, "foo#bar", 32, 64)).toEqual(
baseUrl + "/_matrix/media/v1/identicon/foo%23bar" + baseUrl + "/_matrix/media/v1/identicon/foo%23bar" +
"?width=32&height=64" "?width=32&height=64",
); );
}); });
}); });

View File

@@ -1,7 +1,7 @@
"use strict"; "use strict";
let Crypto = require("../../lib/crypto"); const Crypto = require("../../lib/crypto");
let sdk = require("../.."); const sdk = require("../..");
describe("Crypto", function() { describe("Crypto", function() {
if (!sdk.CRYPTO_ENABLED) { if (!sdk.CRYPTO_ENABLED) {

View File

@@ -1,7 +1,7 @@
"use strict"; "use strict";
let sdk = require("../.."); const sdk = require("../..");
let EventTimeline = sdk.EventTimeline; const EventTimeline = sdk.EventTimeline;
let utils = require("../test-utils"); const utils = require("../test-utils");
function mockRoomStates(timeline) { function mockRoomStates(timeline) {
timeline._startState = utils.mock(sdk.RoomState, "startState"); timeline._startState = utils.mock(sdk.RoomState, "startState");
@@ -9,16 +9,16 @@ function mockRoomStates(timeline) {
} }
describe("EventTimeline", function() { describe("EventTimeline", function() {
let roomId = "!foo:bar"; const roomId = "!foo:bar";
let userA = "@alice:bar"; const userA = "@alice:bar";
let userB = "@bertha:bar"; const userB = "@bertha:bar";
let timeline; let timeline;
beforeEach(function() { beforeEach(function() {
utils.beforeEach(this); // eslint-disable-line no-invalid-this utils.beforeEach(this); // eslint-disable-line no-invalid-this
// XXX: this is a horrid hack; should use sinon or something instead to mock // XXX: this is a horrid hack; should use sinon or something instead to mock
let timelineSet = { room: { roomId: roomId }}; const timelineSet = { room: { roomId: roomId }};
timelineSet.room.getUnfilteredTimelineSet = function() { timelineSet.room.getUnfilteredTimelineSet = function() {
return timelineSet; return timelineSet;
}; };
@@ -28,7 +28,7 @@ describe("EventTimeline", function() {
describe("construction", function() { describe("construction", function() {
it("getRoomId should get room id", function() { it("getRoomId should get room id", function() {
let v = timeline.getRoomId(); const v = timeline.getRoomId();
expect(v).toEqual(roomId); expect(v).toEqual(roomId);
}); });
}); });
@@ -39,7 +39,7 @@ describe("EventTimeline", function() {
}); });
it("should copy state events to start and end state", function() { it("should copy state events to start and end state", function() {
let events = [ const events = [
utils.mkMembership({ utils.mkMembership({
room: roomId, mship: "invite", user: userB, skey: userA, room: roomId, mship: "invite", user: userB, skey: userA,
event: true, event: true,
@@ -52,21 +52,21 @@ describe("EventTimeline", function() {
]; ];
timeline.initialiseState(events); timeline.initialiseState(events);
expect(timeline._startState.setStateEvents).toHaveBeenCalledWith( expect(timeline._startState.setStateEvents).toHaveBeenCalledWith(
events events,
); );
expect(timeline._endState.setStateEvents).toHaveBeenCalledWith( expect(timeline._endState.setStateEvents).toHaveBeenCalledWith(
events events,
); );
}); });
it("should raise an exception if called after events are added", function() { it("should raise an exception if called after events are added", function() {
let event = const event =
utils.mkMessage({ utils.mkMessage({
room: roomId, user: userA, msg: "Adam stole the plushies", room: roomId, user: userA, msg: "Adam stole the plushies",
event: true, event: true,
}); });
let state = [ const state = [
utils.mkMembership({ utils.mkMembership({
room: roomId, mship: "invite", user: userB, skey: userA, room: roomId, mship: "invite", user: userB, skey: userA,
event: true, event: true,
@@ -105,8 +105,8 @@ describe("EventTimeline", function() {
}); });
it("setNeighbouringTimeline should set neighbour", function() { it("setNeighbouringTimeline should set neighbour", function() {
let prev = {a: "a"}; const prev = {a: "a"};
let next = {b: "b"}; const next = {b: "b"};
timeline.setNeighbouringTimeline(prev, EventTimeline.BACKWARDS); timeline.setNeighbouringTimeline(prev, EventTimeline.BACKWARDS);
timeline.setNeighbouringTimeline(next, EventTimeline.FORWARDS); timeline.setNeighbouringTimeline(next, EventTimeline.FORWARDS);
expect(timeline.getNeighbouringTimeline(EventTimeline.BACKWARDS)).toBe(prev); expect(timeline.getNeighbouringTimeline(EventTimeline.BACKWARDS)).toBe(prev);
@@ -114,8 +114,8 @@ describe("EventTimeline", function() {
}); });
it("setNeighbouringTimeline should throw if called twice", function() { it("setNeighbouringTimeline should throw if called twice", function() {
let prev = {a: "a"}; const prev = {a: "a"};
let next = {b: "b"}; const next = {b: "b"};
expect(function() { expect(function() {
timeline.setNeighbouringTimeline(prev, EventTimeline.BACKWARDS); timeline.setNeighbouringTimeline(prev, EventTimeline.BACKWARDS);
}).not.toThrow(); }).not.toThrow();
@@ -141,7 +141,7 @@ describe("EventTimeline", function() {
mockRoomStates(timeline); mockRoomStates(timeline);
}); });
let events = [ const events = [
utils.mkMessage({ utils.mkMessage({
room: roomId, user: userA, msg: "hungry hungry hungry", room: roomId, user: userA, msg: "hungry hungry hungry",
event: true, event: true,
@@ -154,7 +154,7 @@ describe("EventTimeline", function() {
it("should be able to add events to the end", function() { it("should be able to add events to the end", function() {
timeline.addEvent(events[0], false); timeline.addEvent(events[0], false);
let initialIndex = timeline.getBaseIndex(); const initialIndex = timeline.getBaseIndex();
timeline.addEvent(events[1], false); timeline.addEvent(events[1], false);
expect(timeline.getBaseIndex()).toEqual(initialIndex); expect(timeline.getBaseIndex()).toEqual(initialIndex);
expect(timeline.getEvents().length).toEqual(2); expect(timeline.getEvents().length).toEqual(2);
@@ -164,7 +164,7 @@ describe("EventTimeline", function() {
it("should be able to add events to the start", function() { it("should be able to add events to the start", function() {
timeline.addEvent(events[0], true); timeline.addEvent(events[0], true);
let initialIndex = timeline.getBaseIndex(); const initialIndex = timeline.getBaseIndex();
timeline.addEvent(events[1], true); timeline.addEvent(events[1], true);
expect(timeline.getBaseIndex()).toEqual(initialIndex + 1); expect(timeline.getBaseIndex()).toEqual(initialIndex + 1);
expect(timeline.getEvents().length).toEqual(2); expect(timeline.getEvents().length).toEqual(2);
@@ -173,12 +173,12 @@ describe("EventTimeline", function() {
}); });
it("should set event.sender for new and old events", function() { it("should set event.sender for new and old events", function() {
let sentinel = { const sentinel = {
userId: userA, userId: userA,
membership: "join", membership: "join",
name: "Alice", name: "Alice",
}; };
let oldSentinel = { const oldSentinel = {
userId: userA, userId: userA,
membership: "join", membership: "join",
name: "Old Alice", name: "Old Alice",
@@ -198,11 +198,11 @@ describe("EventTimeline", function() {
return null; return null;
}); });
let newEv = utils.mkEvent({ const newEv = utils.mkEvent({
type: "m.room.name", room: roomId, user: userA, event: true, type: "m.room.name", room: roomId, user: userA, event: true,
content: { name: "New Room Name" }, content: { name: "New Room Name" },
}); });
let oldEv = utils.mkEvent({ const oldEv = utils.mkEvent({
type: "m.room.name", room: roomId, user: userA, event: true, type: "m.room.name", room: roomId, user: userA, event: true,
content: { name: "Old Room Name" }, content: { name: "Old Room Name" },
}); });
@@ -215,12 +215,12 @@ describe("EventTimeline", function() {
it("should set event.target for new and old m.room.member events", it("should set event.target for new and old m.room.member events",
function() { function() {
let sentinel = { const sentinel = {
userId: userA, userId: userA,
membership: "join", membership: "join",
name: "Alice", name: "Alice",
}; };
let oldSentinel = { const oldSentinel = {
userId: userA, userId: userA,
membership: "join", membership: "join",
name: "Old Alice", name: "Old Alice",
@@ -240,10 +240,10 @@ describe("EventTimeline", function() {
return null; return null;
}); });
let newEv = utils.mkMembership({ const newEv = utils.mkMembership({
room: roomId, mship: "invite", user: userB, skey: userA, event: true, room: roomId, mship: "invite", user: userB, skey: userA, event: true,
}); });
let oldEv = utils.mkMembership({ const oldEv = utils.mkMembership({
room: roomId, mship: "ban", user: userB, skey: userA, event: true, room: roomId, mship: "ban", user: userB, skey: userA, event: true,
}); });
timeline.addEvent(newEv, false); timeline.addEvent(newEv, false);
@@ -254,7 +254,7 @@ describe("EventTimeline", function() {
it("should call setStateEvents on the right RoomState with the right " + it("should call setStateEvents on the right RoomState with the right " +
"forwardLooking value for new events", function() { "forwardLooking value for new events", function() {
let events = [ const events = [
utils.mkMembership({ utils.mkMembership({
room: roomId, mship: "invite", user: userB, skey: userA, event: true, room: roomId, mship: "invite", user: userB, skey: userA, event: true,
}), }),
@@ -284,7 +284,7 @@ describe("EventTimeline", function() {
it("should call setStateEvents on the right RoomState with the right " + it("should call setStateEvents on the right RoomState with the right " +
"forwardLooking value for old events", function() { "forwardLooking value for old events", function() {
let events = [ const events = [
utils.mkMembership({ utils.mkMembership({
room: roomId, mship: "invite", user: userB, skey: userA, event: true, room: roomId, mship: "invite", user: userB, skey: userA, event: true,
}), }),
@@ -313,7 +313,7 @@ describe("EventTimeline", function() {
}); });
describe("removeEvent", function() { describe("removeEvent", function() {
let events = [ const events = [
utils.mkMessage({ utils.mkMessage({
room: roomId, user: userA, msg: "hungry hungry hungry", room: roomId, user: userA, msg: "hungry hungry hungry",
event: true, event: true,
@@ -365,7 +365,7 @@ describe("EventTimeline", function() {
function() { function() {
timeline.addEvent(events[0], true); timeline.addEvent(events[0], true);
timeline.removeEvent(events[0].getId()); timeline.removeEvent(events[0].getId());
let initialIndex = timeline.getBaseIndex(); const initialIndex = timeline.getBaseIndex();
timeline.addEvent(events[1], false); timeline.addEvent(events[1], false);
timeline.addEvent(events[2], false); timeline.addEvent(events[2], false);
expect(timeline.getBaseIndex()).toEqual(initialIndex); expect(timeline.getBaseIndex()).toEqual(initialIndex);

View File

@@ -1,11 +1,11 @@
"use strict"; "use strict";
let sdk = require("../.."); const sdk = require("../..");
let Filter = sdk.Filter; const Filter = sdk.Filter;
let utils = require("../test-utils"); const utils = require("../test-utils");
describe("Filter", function() { describe("Filter", function() {
let filterId = "f1lt3ring15g00d4ursoul"; const filterId = "f1lt3ring15g00d4ursoul";
let userId = "@sir_arthur_david:humming.tiger"; const userId = "@sir_arthur_david:humming.tiger";
let filter; let filter;
beforeEach(function() { beforeEach(function() {
@@ -15,10 +15,10 @@ describe("Filter", function() {
describe("fromJson", function() { describe("fromJson", function() {
it("create a new Filter from the provided values", function() { it("create a new Filter from the provided values", function() {
let definition = { const definition = {
event_fields: ["type", "content"], event_fields: ["type", "content"],
}; };
let f = Filter.fromJson(userId, filterId, definition); const f = Filter.fromJson(userId, filterId, definition);
expect(f.getDefinition()).toEqual(definition); expect(f.getDefinition()).toEqual(definition);
expect(f.userId).toEqual(userId); expect(f.userId).toEqual(userId);
expect(f.filterId).toEqual(filterId); expect(f.filterId).toEqual(filterId);
@@ -40,7 +40,7 @@ describe("Filter", function() {
describe("setDefinition/getDefinition", function() { describe("setDefinition/getDefinition", function() {
it("should set and get the filter body", function() { it("should set and get the filter body", function() {
let definition = { const definition = {
event_format: "client", event_format: "client",
}; };
filter.setDefinition(definition); filter.setDefinition(definition);

View File

@@ -15,12 +15,12 @@ limitations under the License.
*/ */
"use strict"; "use strict";
let q = require("q"); const q = require("q");
let sdk = require("../.."); const sdk = require("../..");
let utils = require("../test-utils"); const utils = require("../test-utils");
let InteractiveAuth = sdk.InteractiveAuth; const InteractiveAuth = sdk.InteractiveAuth;
let MatrixError = sdk.MatrixError; const MatrixError = sdk.MatrixError;
describe("InteractiveAuth", function() { describe("InteractiveAuth", function() {
beforeEach(function() { beforeEach(function() {
@@ -28,10 +28,10 @@ describe("InteractiveAuth", function() {
}); });
it("should start an auth stage and complete it", function(done) { it("should start an auth stage and complete it", function(done) {
let doRequest = jasmine.createSpy('doRequest'); const doRequest = jasmine.createSpy('doRequest');
let startAuthStage = jasmine.createSpy('startAuthStage'); const startAuthStage = jasmine.createSpy('startAuthStage');
let ia = new InteractiveAuth({ const ia = new InteractiveAuth({
doRequest: doRequest, doRequest: doRequest,
startAuthStage: startAuthStage, startAuthStage: startAuthStage,
authData: { authData: {
@@ -60,7 +60,7 @@ describe("InteractiveAuth", function() {
}); });
// .. which should trigger a call here // .. which should trigger a call here
let requestRes = {"a": "b"}; const requestRes = {"a": "b"};
doRequest.andCallFake(function(authData) { doRequest.andCallFake(function(authData) {
expect(authData).toEqual({ expect(authData).toEqual({
session: "sessionId", session: "sessionId",
@@ -78,10 +78,10 @@ describe("InteractiveAuth", function() {
}); });
it("should make a request if no authdata is provided", function(done) { it("should make a request if no authdata is provided", function(done) {
let doRequest = jasmine.createSpy('doRequest'); const doRequest = jasmine.createSpy('doRequest');
let startAuthStage = jasmine.createSpy('startAuthStage'); const startAuthStage = jasmine.createSpy('startAuthStage');
let ia = new InteractiveAuth({ const ia = new InteractiveAuth({
doRequest: doRequest, doRequest: doRequest,
startAuthStage: startAuthStage, startAuthStage: startAuthStage,
}); });
@@ -93,7 +93,7 @@ describe("InteractiveAuth", function() {
doRequest.andCallFake(function(authData) { doRequest.andCallFake(function(authData) {
console.log("request1", authData); console.log("request1", authData);
expect(authData).toBe(null); expect(authData).toBe(null);
let err = new MatrixError({ const err = new MatrixError({
session: "sessionId", session: "sessionId",
flows: [ flows: [
{ stages: ["logintype"] }, { stages: ["logintype"] },
@@ -107,7 +107,7 @@ describe("InteractiveAuth", function() {
}); });
// .. which should be followed by a call to startAuthStage // .. which should be followed by a call to startAuthStage
let requestRes = {"a": "b"}; const requestRes = {"a": "b"};
startAuthStage.andCallFake(function(stage) { startAuthStage.andCallFake(function(stage) {
expect(stage).toEqual("logintype"); expect(stage).toEqual("logintype");
expect(ia.getSessionId()).toEqual("sessionId"); expect(ia.getSessionId()).toEqual("sessionId");

View File

@@ -1,40 +1,40 @@
"use strict"; "use strict";
let q = require("q"); const q = require("q");
let sdk = require("../.."); const sdk = require("../..");
let MatrixClient = sdk.MatrixClient; const MatrixClient = sdk.MatrixClient;
let utils = require("../test-utils"); const utils = require("../test-utils");
describe("MatrixClient", function() { describe("MatrixClient", function() {
let userId = "@alice:bar"; const userId = "@alice:bar";
let identityServerUrl = "https://identity.server"; const identityServerUrl = "https://identity.server";
let identityServerDomain = "identity.server"; const identityServerDomain = "identity.server";
let client; let client;
let store; let store;
let scheduler; let scheduler;
let KEEP_ALIVE_PATH = "/_matrix/client/versions"; const KEEP_ALIVE_PATH = "/_matrix/client/versions";
let PUSH_RULES_RESPONSE = { const PUSH_RULES_RESPONSE = {
method: "GET", method: "GET",
path: "/pushrules/", path: "/pushrules/",
data: {}, data: {},
}; };
let FILTER_PATH = "/user/" + encodeURIComponent(userId) + "/filter"; const FILTER_PATH = "/user/" + encodeURIComponent(userId) + "/filter";
let FILTER_RESPONSE = { const FILTER_RESPONSE = {
method: "POST", method: "POST",
path: FILTER_PATH, path: FILTER_PATH,
data: { filter_id: "f1lt3r" }, data: { filter_id: "f1lt3r" },
}; };
let SYNC_DATA = { const SYNC_DATA = {
next_batch: "s_5_3", next_batch: "s_5_3",
presence: { events: [] }, presence: { events: [] },
rooms: {}, rooms: {},
}; };
let SYNC_RESPONSE = { const SYNC_RESPONSE = {
method: "GET", method: "GET",
path: "/sync", path: "/sync",
data: SYNC_DATA, data: SYNC_DATA,
@@ -59,8 +59,8 @@ describe("MatrixClient", function() {
if (path === KEEP_ALIVE_PATH && acceptKeepalives) { if (path === KEEP_ALIVE_PATH && acceptKeepalives) {
return q(); return q();
} }
let next = httpLookups.shift(); const next = httpLookups.shift();
let logLine = ( const logLine = (
"MatrixClient[UT] RECV " + method + " " + path + " " + "MatrixClient[UT] RECV " + method + " " + path + " " +
"EXPECT " + (next ? next.method : next) + " " + (next ? next.path : next) "EXPECT " + (next ? next.method : next) + " " + (next ? next.path : next)
); );
@@ -75,7 +75,7 @@ describe("MatrixClient", function() {
expect(false).toBe( expect(false).toBe(
true, ">1 pending request. You should probably handle them. " + true, ">1 pending request. You should probably handle them. " +
"PENDING: " + JSON.stringify(pendingLookup) + " JUST GOT: " + "PENDING: " + JSON.stringify(pendingLookup) + " JUST GOT: " +
method + " " + path method + " " + path,
); );
} }
pendingLookup = { pendingLookup = {
@@ -88,7 +88,7 @@ describe("MatrixClient", function() {
if (next.path === path && next.method === method) { if (next.path === path && next.method === method) {
console.log( console.log(
"MatrixClient[UT] Matched. Returning " + "MatrixClient[UT] Matched. Returning " +
(next.error ? "BAD" : "GOOD") + " response" (next.error ? "BAD" : "GOOD") + " response",
); );
if (next.expectBody) { if (next.expectBody) {
expect(next.expectBody).toEqual(data); expect(next.expectBody).toEqual(data);
@@ -176,9 +176,9 @@ describe("MatrixClient", function() {
httpLookups = []; httpLookups = [];
httpLookups.push(PUSH_RULES_RESPONSE); httpLookups.push(PUSH_RULES_RESPONSE);
httpLookups.push(SYNC_RESPONSE); httpLookups.push(SYNC_RESPONSE);
let filterId = "ehfewf"; const filterId = "ehfewf";
store.getFilterIdByName.andReturn(filterId); store.getFilterIdByName.andReturn(filterId);
let filter = new sdk.Filter(0, filterId); const filter = new sdk.Filter(0, filterId);
filter.setDefinition({"room": {"timeline": {"limit": 8}}}); filter.setDefinition({"room": {"timeline": {"limit": 8}}});
store.getFilter.andReturn(filter); store.getFilter.andReturn(filter);
client.startClient(); client.startClient();
@@ -220,7 +220,7 @@ describe("MatrixClient", function() {
// and they all need to be stored! // and they all need to be stored!
return "FILTER_SYNC_" + userId + (suffix ? "_" + suffix : ""); return "FILTER_SYNC_" + userId + (suffix ? "_" + suffix : "");
} }
let invalidFilterId = 'invalidF1lt3r'; const invalidFilterId = 'invalidF1lt3r';
httpLookups = []; httpLookups = [];
httpLookups.push({ httpLookups.push({
method: "GET", method: "GET",
@@ -236,9 +236,9 @@ describe("MatrixClient", function() {
httpLookups.push(FILTER_RESPONSE); httpLookups.push(FILTER_RESPONSE);
store.getFilterIdByName.andReturn(invalidFilterId); store.getFilterIdByName.andReturn(invalidFilterId);
let filterName = getFilterName(client.credentials.userId); const filterName = getFilterName(client.credentials.userId);
client.store.setFilterIdByName(filterName, invalidFilterId); client.store.setFilterIdByName(filterName, invalidFilterId);
let filter = new sdk.Filter(client.credentials.userId); const filter = new sdk.Filter(client.credentials.userId);
client.getOrCreateFilter(filterName, filter).then(function(filterId) { client.getOrCreateFilter(filterName, filter).then(function(filterId) {
expect(filterId).toEqual(FILTER_RESPONSE.data.filter_id); expect(filterId).toEqual(FILTER_RESPONSE.data.filter_id);
@@ -290,7 +290,7 @@ describe("MatrixClient", function() {
if (state === "ERROR" && httpLookups.length > 0) { if (state === "ERROR" && httpLookups.length > 0) {
expect(httpLookups.length).toEqual(1); expect(httpLookups.length).toEqual(1);
expect(client.retryImmediately()).toBe( expect(client.retryImmediately()).toBe(
true, "retryImmediately returned false" true, "retryImmediately returned false",
); );
jasmine.Clock.tick(1); jasmine.Clock.tick(1);
} else if (state === "RECONNECTING" && httpLookups.length > 0) { } else if (state === "RECONNECTING" && httpLookups.length > 0) {
@@ -332,9 +332,9 @@ describe("MatrixClient", function() {
describe("emitted sync events", function() { describe("emitted sync events", function() {
function syncChecker(expectedStates, done) { function syncChecker(expectedStates, done) {
return function syncListener(state, old) { return function syncListener(state, old) {
let expected = expectedStates.shift(); const expected = expectedStates.shift();
console.log( console.log(
"'sync' curr=%s old=%s EXPECT=%s", state, old, expected "'sync' curr=%s old=%s EXPECT=%s", state, old, expected,
); );
if (!expected) { if (!expected) {
done(); done();
@@ -352,14 +352,14 @@ describe("MatrixClient", function() {
} }
it("should transition null -> PREPARED after the first /sync", function(done) { it("should transition null -> PREPARED after the first /sync", function(done) {
let expectedStates = []; const expectedStates = [];
expectedStates.push(["PREPARED", null]); expectedStates.push(["PREPARED", null]);
client.on("sync", syncChecker(expectedStates, done)); client.on("sync", syncChecker(expectedStates, done));
client.startClient(); client.startClient();
}); });
it("should transition null -> ERROR after a failed /filter", function(done) { it("should transition null -> ERROR after a failed /filter", function(done) {
let expectedStates = []; const expectedStates = [];
httpLookups = []; httpLookups = [];
httpLookups.push(PUSH_RULES_RESPONSE); httpLookups.push(PUSH_RULES_RESPONSE);
httpLookups.push({ httpLookups.push({
@@ -372,7 +372,7 @@ describe("MatrixClient", function() {
it("should transition ERROR -> PREPARED after /sync if prev failed", it("should transition ERROR -> PREPARED after /sync if prev failed",
function(done) { function(done) {
let expectedStates = []; const expectedStates = [];
acceptKeepalives = false; acceptKeepalives = false;
httpLookups = []; httpLookups = [];
httpLookups.push(PUSH_RULES_RESPONSE); httpLookups.push(PUSH_RULES_RESPONSE);
@@ -399,7 +399,7 @@ describe("MatrixClient", function() {
}); });
it("should transition PREPARED -> SYNCING after /sync", function(done) { it("should transition PREPARED -> SYNCING after /sync", function(done) {
let expectedStates = []; const expectedStates = [];
expectedStates.push(["PREPARED", null]); expectedStates.push(["PREPARED", null]);
expectedStates.push(["SYNCING", "PREPARED"]); expectedStates.push(["SYNCING", "PREPARED"]);
client.on("sync", syncChecker(expectedStates, done)); client.on("sync", syncChecker(expectedStates, done));
@@ -408,7 +408,7 @@ describe("MatrixClient", function() {
it("should transition SYNCING -> ERROR after a failed /sync", function(done) { it("should transition SYNCING -> ERROR after a failed /sync", function(done) {
acceptKeepalives = false; acceptKeepalives = false;
let expectedStates = []; const expectedStates = [];
httpLookups.push({ httpLookups.push({
method: "GET", path: "/sync", error: { errcode: "NONONONONO" }, method: "GET", path: "/sync", error: { errcode: "NONONONONO" },
}); });
@@ -427,7 +427,7 @@ describe("MatrixClient", function() {
xit("should transition ERROR -> SYNCING after /sync if prev failed", xit("should transition ERROR -> SYNCING after /sync if prev failed",
function(done) { function(done) {
let expectedStates = []; const expectedStates = [];
httpLookups.push({ httpLookups.push({
method: "GET", path: "/sync", error: { errcode: "NONONONONO" }, method: "GET", path: "/sync", error: { errcode: "NONONONONO" },
}); });
@@ -442,7 +442,7 @@ describe("MatrixClient", function() {
it("should transition SYNCING -> SYNCING on subsequent /sync successes", it("should transition SYNCING -> SYNCING on subsequent /sync successes",
function(done) { function(done) {
let expectedStates = []; const expectedStates = [];
httpLookups.push(SYNC_RESPONSE); httpLookups.push(SYNC_RESPONSE);
httpLookups.push(SYNC_RESPONSE); httpLookups.push(SYNC_RESPONSE);
@@ -455,7 +455,7 @@ describe("MatrixClient", function() {
it("should transition ERROR -> ERROR if keepalive keeps failing", function(done) { it("should transition ERROR -> ERROR if keepalive keeps failing", function(done) {
acceptKeepalives = false; acceptKeepalives = false;
let expectedStates = []; const expectedStates = [];
httpLookups.push({ httpLookups.push({
method: "GET", path: "/sync", error: { errcode: "NONONONONO" }, method: "GET", path: "/sync", error: { errcode: "NONONONONO" },
}); });
@@ -479,7 +479,7 @@ describe("MatrixClient", function() {
}); });
describe("inviteByEmail", function() { describe("inviteByEmail", function() {
let roomId = "!foo:bar"; const roomId = "!foo:bar";
it("should send an invite HTTP POST", function() { it("should send an invite HTTP POST", function() {
httpLookups = [{ httpLookups = [{

View File

@@ -1,18 +1,18 @@
"use strict"; "use strict";
let PushProcessor = require("../../lib/pushprocessor"); const PushProcessor = require("../../lib/pushprocessor");
let utils = require("../test-utils"); const utils = require("../test-utils");
describe('NotificationService', function() { describe('NotificationService', function() {
let testUserId = "@ali:matrix.org"; const testUserId = "@ali:matrix.org";
let testDisplayName = "Alice M"; const testDisplayName = "Alice M";
let testRoomId = "!fl1bb13:localhost"; const testRoomId = "!fl1bb13:localhost";
let testEvent; let testEvent;
let pushProcessor; let pushProcessor;
// These would be better if individual rules were configured in the tests themselves. // These would be better if individual rules were configured in the tests themselves.
let matrixClient = { const matrixClient = {
getRoom: function() { getRoom: function() {
return { return {
currentState: { currentState: {
@@ -213,25 +213,25 @@ describe('NotificationService', function() {
it('should bing on a user ID.', function() { it('should bing on a user ID.', function() {
testEvent.event.content.body = "Hello @ali:matrix.org, how are you?"; testEvent.event.content.body = "Hello @ali:matrix.org, how are you?";
let actions = pushProcessor.actionsForEvent(testEvent); const actions = pushProcessor.actionsForEvent(testEvent);
expect(actions.tweaks.highlight).toEqual(true); expect(actions.tweaks.highlight).toEqual(true);
}); });
it('should bing on a partial user ID with an @.', function() { it('should bing on a partial user ID with an @.', function() {
testEvent.event.content.body = "Hello @ali, how are you?"; testEvent.event.content.body = "Hello @ali, how are you?";
let actions = pushProcessor.actionsForEvent(testEvent); const actions = pushProcessor.actionsForEvent(testEvent);
expect(actions.tweaks.highlight).toEqual(true); expect(actions.tweaks.highlight).toEqual(true);
}); });
it('should bing on a partial user ID without @.', function() { it('should bing on a partial user ID without @.', function() {
testEvent.event.content.body = "Hello ali, how are you?"; testEvent.event.content.body = "Hello ali, how are you?";
let actions = pushProcessor.actionsForEvent(testEvent); const actions = pushProcessor.actionsForEvent(testEvent);
expect(actions.tweaks.highlight).toEqual(true); expect(actions.tweaks.highlight).toEqual(true);
}); });
it('should bing on a case-insensitive user ID.', function() { it('should bing on a case-insensitive user ID.', function() {
testEvent.event.content.body = "Hello @AlI:matrix.org, how are you?"; testEvent.event.content.body = "Hello @AlI:matrix.org, how are you?";
let actions = pushProcessor.actionsForEvent(testEvent); const actions = pushProcessor.actionsForEvent(testEvent);
expect(actions.tweaks.highlight).toEqual(true); expect(actions.tweaks.highlight).toEqual(true);
}); });
@@ -239,13 +239,13 @@ describe('NotificationService', function() {
it('should bing on a display name.', function() { it('should bing on a display name.', function() {
testEvent.event.content.body = "Hello Alice M, how are you?"; testEvent.event.content.body = "Hello Alice M, how are you?";
let actions = pushProcessor.actionsForEvent(testEvent); const actions = pushProcessor.actionsForEvent(testEvent);
expect(actions.tweaks.highlight).toEqual(true); expect(actions.tweaks.highlight).toEqual(true);
}); });
it('should bing on a case-insensitive display name.', function() { it('should bing on a case-insensitive display name.', function() {
testEvent.event.content.body = "Hello ALICE M, how are you?"; testEvent.event.content.body = "Hello ALICE M, how are you?";
let actions = pushProcessor.actionsForEvent(testEvent); const actions = pushProcessor.actionsForEvent(testEvent);
expect(actions.tweaks.highlight).toEqual(true); expect(actions.tweaks.highlight).toEqual(true);
}); });
@@ -253,19 +253,19 @@ describe('NotificationService', function() {
it('should bing on a bing word.', function() { it('should bing on a bing word.', function() {
testEvent.event.content.body = "I really like coffee"; testEvent.event.content.body = "I really like coffee";
let actions = pushProcessor.actionsForEvent(testEvent); const actions = pushProcessor.actionsForEvent(testEvent);
expect(actions.tweaks.highlight).toEqual(true); expect(actions.tweaks.highlight).toEqual(true);
}); });
it('should bing on case-insensitive bing words.', function() { it('should bing on case-insensitive bing words.', function() {
testEvent.event.content.body = "Coffee is great"; testEvent.event.content.body = "Coffee is great";
let actions = pushProcessor.actionsForEvent(testEvent); const actions = pushProcessor.actionsForEvent(testEvent);
expect(actions.tweaks.highlight).toEqual(true); expect(actions.tweaks.highlight).toEqual(true);
}); });
it('should bing on wildcard (.*) bing words.', function() { it('should bing on wildcard (.*) bing words.', function() {
testEvent.event.content.body = "It was foomahbar I think."; testEvent.event.content.body = "It was foomahbar I think.";
let actions = pushProcessor.actionsForEvent(testEvent); const actions = pushProcessor.actionsForEvent(testEvent);
expect(actions.tweaks.highlight).toEqual(true); expect(actions.tweaks.highlight).toEqual(true);
}); });
@@ -280,7 +280,7 @@ describe('NotificationService', function() {
it('should bing on character range ([a-z]) bing words.', function() { it('should bing on character range ([a-z]) bing words.', function() {
testEvent.event.content.body = "I ate 6 pies"; testEvent.event.content.body = "I ate 6 pies";
let actions = pushProcessor.actionsForEvent(testEvent); const actions = pushProcessor.actionsForEvent(testEvent);
expect(actions.tweaks.highlight).toEqual(true); expect(actions.tweaks.highlight).toEqual(true);
}); });
@@ -297,7 +297,7 @@ describe('NotificationService', function() {
it('should gracefully handle bad input.', function() { it('should gracefully handle bad input.', function() {
testEvent.event.content.body = { "foo": "bar" }; testEvent.event.content.body = { "foo": "bar" };
let actions = pushProcessor.actionsForEvent(testEvent); const actions = pushProcessor.actionsForEvent(testEvent);
expect(actions.tweaks.highlight).toEqual(false); expect(actions.tweaks.highlight).toEqual(false);
}); });
}); });

View File

@@ -1,10 +1,10 @@
"use strict"; "use strict";
let callbacks = require("../../lib/realtime-callbacks"); const callbacks = require("../../lib/realtime-callbacks");
let test_utils = require("../test-utils.js"); const testUtils = require("../test-utils.js");
describe("realtime-callbacks", function() { describe("realtime-callbacks", function() {
let clock = jasmine.Clock; const clock = jasmine.Clock;
let fakeDate; let fakeDate;
function tick(millis) { function tick(millis) {
@@ -14,7 +14,7 @@ describe("realtime-callbacks", function() {
} }
beforeEach(function() { beforeEach(function() {
test_utils.beforeEach(this); // eslint-disable-line no-invalid-this testUtils.beforeEach(this); // eslint-disable-line no-invalid-this
clock.useMock(); clock.useMock();
fakeDate = Date.now(); fakeDate = Date.now();
callbacks.setNow(function() { callbacks.setNow(function() {
@@ -28,7 +28,7 @@ describe("realtime-callbacks", function() {
describe("setTimeout", function() { describe("setTimeout", function() {
it("should call the callback after the timeout", function() { it("should call the callback after the timeout", function() {
let callback = jasmine.createSpy(); const callback = jasmine.createSpy();
callbacks.setTimeout(callback, 100); callbacks.setTimeout(callback, 100);
expect(callback).not.toHaveBeenCalled(); expect(callback).not.toHaveBeenCalled();
@@ -38,7 +38,7 @@ describe("realtime-callbacks", function() {
it("should default to a zero timeout", function() { it("should default to a zero timeout", function() {
let callback = jasmine.createSpy(); const callback = jasmine.createSpy();
callbacks.setTimeout(callback); callbacks.setTimeout(callback);
expect(callback).not.toHaveBeenCalled(); expect(callback).not.toHaveBeenCalled();
@@ -47,14 +47,14 @@ describe("realtime-callbacks", function() {
}); });
it("should pass any parameters to the callback", function() { it("should pass any parameters to the callback", function() {
let callback = jasmine.createSpy(); const callback = jasmine.createSpy();
callbacks.setTimeout(callback, 0, "a", "b", "c"); callbacks.setTimeout(callback, 0, "a", "b", "c");
tick(0); tick(0);
expect(callback).toHaveBeenCalledWith("a", "b", "c"); expect(callback).toHaveBeenCalledWith("a", "b", "c");
}); });
it("should set 'this' to the global object", function() { it("should set 'this' to the global object", function() {
let callback = jasmine.createSpy(); const callback = jasmine.createSpy();
callback.andCallFake(function() { callback.andCallFake(function() {
expect(this).toBe(global); // eslint-disable-line no-invalid-this expect(this).toBe(global); // eslint-disable-line no-invalid-this
expect(this.console).toBeDefined(); // eslint-disable-line no-invalid-this expect(this.console).toBeDefined(); // eslint-disable-line no-invalid-this
@@ -65,7 +65,7 @@ describe("realtime-callbacks", function() {
}); });
it("should handle timeouts of several seconds", function() { it("should handle timeouts of several seconds", function() {
let callback = jasmine.createSpy(); const callback = jasmine.createSpy();
callbacks.setTimeout(callback, 2000); callbacks.setTimeout(callback, 2000);
expect(callback).not.toHaveBeenCalled(); expect(callback).not.toHaveBeenCalled();
@@ -76,9 +76,9 @@ describe("realtime-callbacks", function() {
}); });
it("should call multiple callbacks in the right order", function() { it("should call multiple callbacks in the right order", function() {
let callback1 = jasmine.createSpy("callback1"); const callback1 = jasmine.createSpy("callback1");
let callback2 = jasmine.createSpy("callback2"); const callback2 = jasmine.createSpy("callback2");
let callback3 = jasmine.createSpy("callback3"); const callback3 = jasmine.createSpy("callback3");
callbacks.setTimeout(callback2, 200); callbacks.setTimeout(callback2, 200);
callbacks.setTimeout(callback1, 100); callbacks.setTimeout(callback1, 100);
callbacks.setTimeout(callback3, 300); callbacks.setTimeout(callback3, 300);
@@ -101,8 +101,8 @@ describe("realtime-callbacks", function() {
}); });
it("should treat -ve timeouts the same as a zero timeout", function() { it("should treat -ve timeouts the same as a zero timeout", function() {
let callback1 = jasmine.createSpy("callback1"); const callback1 = jasmine.createSpy("callback1");
let callback2 = jasmine.createSpy("callback2"); const callback2 = jasmine.createSpy("callback2");
// check that cb1 is called before cb2 // check that cb1 is called before cb2
callback1.andCallFake(function() { callback1.andCallFake(function() {
@@ -120,8 +120,8 @@ describe("realtime-callbacks", function() {
}); });
it("should not get confused by chained calls", function() { it("should not get confused by chained calls", function() {
let callback2 = jasmine.createSpy("callback2"); const callback2 = jasmine.createSpy("callback2");
let callback1 = jasmine.createSpy("callback1"); const callback1 = jasmine.createSpy("callback1");
callback1.andCallFake(function() { callback1.andCallFake(function() {
callbacks.setTimeout(callback2, 0); callbacks.setTimeout(callback2, 0);
expect(callback2).not.toHaveBeenCalled(); expect(callback2).not.toHaveBeenCalled();
@@ -136,11 +136,11 @@ describe("realtime-callbacks", function() {
}); });
it("should be immune to exceptions", function() { it("should be immune to exceptions", function() {
let callback1 = jasmine.createSpy("callback1"); const callback1 = jasmine.createSpy("callback1");
callback1.andCallFake(function() { callback1.andCallFake(function() {
throw new Error("prepare to die"); throw new Error("prepare to die");
}); });
let callback2 = jasmine.createSpy("callback2"); const callback2 = jasmine.createSpy("callback2");
callbacks.setTimeout(callback1, 0); callbacks.setTimeout(callback1, 0);
callbacks.setTimeout(callback2, 0); callbacks.setTimeout(callback2, 0);
@@ -154,19 +154,19 @@ describe("realtime-callbacks", function() {
describe("cancelTimeout", function() { describe("cancelTimeout", function() {
it("should cancel a pending timeout", function() { it("should cancel a pending timeout", function() {
let callback = jasmine.createSpy(); const callback = jasmine.createSpy();
let k = callbacks.setTimeout(callback); const k = callbacks.setTimeout(callback);
callbacks.clearTimeout(k); callbacks.clearTimeout(k);
tick(0); tick(0);
expect(callback).not.toHaveBeenCalled(); expect(callback).not.toHaveBeenCalled();
}); });
it("should not affect sooner timeouts", function() { it("should not affect sooner timeouts", function() {
let callback1 = jasmine.createSpy("callback1"); const callback1 = jasmine.createSpy("callback1");
let callback2 = jasmine.createSpy("callback2"); const callback2 = jasmine.createSpy("callback2");
callbacks.setTimeout(callback1, 100); callbacks.setTimeout(callback1, 100);
let k = callbacks.setTimeout(callback2, 200); const k = callbacks.setTimeout(callback2, 200);
callbacks.clearTimeout(k); callbacks.clearTimeout(k);
tick(100); tick(100);

View File

@@ -1,13 +1,13 @@
"use strict"; "use strict";
let sdk = require("../.."); const sdk = require("../..");
let RoomMember = sdk.RoomMember; const RoomMember = sdk.RoomMember;
let utils = require("../test-utils"); const utils = require("../test-utils");
describe("RoomMember", function() { describe("RoomMember", function() {
let roomId = "!foo:bar"; const roomId = "!foo:bar";
let userA = "@alice:bar"; const userA = "@alice:bar";
let userB = "@bertha:bar"; const userB = "@bertha:bar";
let userC = "@clarissa:bar"; const userC = "@clarissa:bar";
let member; let member;
beforeEach(function() { beforeEach(function() {
@@ -16,7 +16,7 @@ describe("RoomMember", function() {
}); });
describe("getAvatarUrl", function() { describe("getAvatarUrl", function() {
let hsUrl = "https://my.home.server"; const hsUrl = "https://my.home.server";
it("should return the URL from m.room.member preferentially", function() { it("should return the URL from m.room.member preferentially", function() {
member.events.member = utils.mkEvent({ member.events.member = utils.mkEvent({
@@ -30,7 +30,7 @@ describe("RoomMember", function() {
avatar_url: "mxc://flibble/wibble", avatar_url: "mxc://flibble/wibble",
}, },
}); });
let url = member.getAvatarUrl(hsUrl); const url = member.getAvatarUrl(hsUrl);
// we don't care about how the mxc->http conversion is done, other // we don't care about how the mxc->http conversion is done, other
// than it contains the mxc body. // than it contains the mxc body.
expect(url.indexOf("flibble/wibble")).not.toEqual(-1); expect(url.indexOf("flibble/wibble")).not.toEqual(-1);
@@ -38,20 +38,20 @@ describe("RoomMember", function() {
it("should return an identicon HTTP URL if allowDefault was set and there " + it("should return an identicon HTTP URL if allowDefault was set and there " +
"was no m.room.member event", function() { "was no m.room.member event", function() {
let url = member.getAvatarUrl(hsUrl, 64, 64, "crop", true); const url = member.getAvatarUrl(hsUrl, 64, 64, "crop", true);
expect(url.indexOf("http")).toEqual(0); // don't care about form expect(url.indexOf("http")).toEqual(0); // don't care about form
}); });
it("should return nothing if there is no m.room.member and allowDefault=false", it("should return nothing if there is no m.room.member and allowDefault=false",
function() { function() {
let url = member.getAvatarUrl(hsUrl, 64, 64, "crop", false); const url = member.getAvatarUrl(hsUrl, 64, 64, "crop", false);
expect(url).toEqual(null); expect(url).toEqual(null);
}); });
}); });
describe("setPowerLevelEvent", function() { describe("setPowerLevelEvent", function() {
it("should set 'powerLevel' and 'powerLevelNorm'.", function() { it("should set 'powerLevel' and 'powerLevelNorm'.", function() {
let event = utils.mkEvent({ const event = utils.mkEvent({
type: "m.room.power_levels", type: "m.room.power_levels",
room: roomId, room: roomId,
user: userA, user: userA,
@@ -68,7 +68,7 @@ describe("RoomMember", function() {
expect(member.powerLevel).toEqual(20); expect(member.powerLevel).toEqual(20);
expect(member.powerLevelNorm).toEqual(10); expect(member.powerLevelNorm).toEqual(10);
let memberB = new RoomMember(roomId, userB); const memberB = new RoomMember(roomId, userB);
memberB.setPowerLevelEvent(event); memberB.setPowerLevelEvent(event);
expect(memberB.powerLevel).toEqual(200); expect(memberB.powerLevel).toEqual(200);
expect(memberB.powerLevelNorm).toEqual(100); expect(memberB.powerLevelNorm).toEqual(100);
@@ -76,7 +76,7 @@ describe("RoomMember", function() {
it("should emit 'RoomMember.powerLevel' if the power level changes.", it("should emit 'RoomMember.powerLevel' if the power level changes.",
function() { function() {
let event = utils.mkEvent({ const event = utils.mkEvent({
type: "m.room.power_levels", type: "m.room.power_levels",
room: roomId, room: roomId,
user: userA, user: userA,
@@ -105,7 +105,7 @@ describe("RoomMember", function() {
it("should honour power levels of zero.", it("should honour power levels of zero.",
function() { function() {
let event = utils.mkEvent({ const event = utils.mkEvent({
type: "m.room.power_levels", type: "m.room.power_levels",
room: roomId, room: roomId,
user: userA, user: userA,
@@ -138,12 +138,12 @@ describe("RoomMember", function() {
describe("setTypingEvent", function() { describe("setTypingEvent", function() {
it("should set 'typing'", function() { it("should set 'typing'", function() {
member.typing = false; member.typing = false;
let memberB = new RoomMember(roomId, userB); const memberB = new RoomMember(roomId, userB);
memberB.typing = true; memberB.typing = true;
let memberC = new RoomMember(roomId, userC); const memberC = new RoomMember(roomId, userC);
memberC.typing = true; memberC.typing = true;
let event = utils.mkEvent({ const event = utils.mkEvent({
type: "m.typing", type: "m.typing",
user: userA, user: userA,
room: roomId, room: roomId,
@@ -165,7 +165,7 @@ describe("RoomMember", function() {
it("should emit 'RoomMember.typing' if the typing state changes", it("should emit 'RoomMember.typing' if the typing state changes",
function() { function() {
let event = utils.mkEvent({ const event = utils.mkEvent({
type: "m.typing", type: "m.typing",
room: roomId, room: roomId,
content: { content: {
@@ -190,7 +190,7 @@ describe("RoomMember", function() {
}); });
describe("setMembershipEvent", function() { describe("setMembershipEvent", function() {
let joinEvent = utils.mkMembership({ const joinEvent = utils.mkMembership({
event: true, event: true,
mship: "join", mship: "join",
user: userA, user: userA,
@@ -198,7 +198,7 @@ describe("RoomMember", function() {
name: "Alice", name: "Alice",
}); });
let inviteEvent = utils.mkMembership({ const inviteEvent = utils.mkMembership({
event: true, event: true,
mship: "invite", mship: "invite",
user: userB, user: userB,
@@ -218,7 +218,7 @@ describe("RoomMember", function() {
it("should set 'name' based on user_id, displayname and room state", it("should set 'name' based on user_id, displayname and room state",
function() { function() {
let roomState = { const roomState = {
getStateEvents: function(type) { getStateEvents: function(type) {
if (type !== "m.room.member") { if (type !== "m.room.member") {
return []; return [];

View File

@@ -1,13 +1,13 @@
"use strict"; "use strict";
let sdk = require("../.."); const sdk = require("../..");
let RoomState = sdk.RoomState; const RoomState = sdk.RoomState;
let RoomMember = sdk.RoomMember; const RoomMember = sdk.RoomMember;
let utils = require("../test-utils"); const utils = require("../test-utils");
describe("RoomState", function() { describe("RoomState", function() {
let roomId = "!foo:bar"; const roomId = "!foo:bar";
let userA = "@alice:bar"; const userA = "@alice:bar";
let userB = "@bob:bar"; const userB = "@bob:bar";
let state; let state;
beforeEach(function() { beforeEach(function() {
@@ -40,7 +40,7 @@ describe("RoomState", function() {
}); });
it("should return a member for each m.room.member event", function() { it("should return a member for each m.room.member event", function() {
let members = state.getMembers(); const members = state.getMembers();
expect(members.length).toEqual(2); expect(members.length).toEqual(2);
// ordering unimportant // ordering unimportant
expect([userA, userB].indexOf(members[0].userId)).not.toEqual(-1); expect([userA, userB].indexOf(members[0].userId)).not.toEqual(-1);
@@ -58,7 +58,7 @@ describe("RoomState", function() {
}); });
it("should return a member which changes as state changes", function() { it("should return a member which changes as state changes", function() {
let member = state.getMember(userB); const member = state.getMember(userB);
expect(member.membership).toEqual("join"); expect(member.membership).toEqual("join");
expect(member.name).toEqual(userB); expect(member.name).toEqual(userB);
@@ -81,14 +81,14 @@ describe("RoomState", function() {
it("should return a member which doesn't change when the state is updated", it("should return a member which doesn't change when the state is updated",
function() { function() {
let preLeaveUser = state.getSentinelMember(userA); const preLeaveUser = state.getSentinelMember(userA);
state.setStateEvents([ state.setStateEvents([
utils.mkMembership({ utils.mkMembership({
room: roomId, user: userA, mship: "leave", event: true, room: roomId, user: userA, mship: "leave", event: true,
name: "AliceIsGone", name: "AliceIsGone",
}), }),
]); ]);
let postLeaveUser = state.getSentinelMember(userA); const postLeaveUser = state.getSentinelMember(userA);
expect(preLeaveUser.membership).toEqual("join"); expect(preLeaveUser.membership).toEqual("join");
expect(preLeaveUser.name).toEqual(userA); expect(preLeaveUser.name).toEqual(userA);
@@ -111,7 +111,7 @@ describe("RoomState", function() {
it("should return a list of matching events if no state_key was specified", it("should return a list of matching events if no state_key was specified",
function() { function() {
let events = state.getStateEvents("m.room.member"); const events = state.getStateEvents("m.room.member");
expect(events.length).toEqual(2); expect(events.length).toEqual(2);
// ordering unimportant // ordering unimportant
expect([userA, userB].indexOf(events[0].getStateKey())).not.toEqual(-1); expect([userA, userB].indexOf(events[0].getStateKey())).not.toEqual(-1);
@@ -120,7 +120,7 @@ describe("RoomState", function() {
it("should return a single MatrixEvent if a state_key was specified", it("should return a single MatrixEvent if a state_key was specified",
function() { function() {
let event = state.getStateEvents("m.room.member", userA); const event = state.getStateEvents("m.room.member", userA);
expect(event.getContent()).toEqual({ expect(event.getContent()).toEqual({
membership: "join", membership: "join",
}); });
@@ -129,7 +129,7 @@ describe("RoomState", function() {
describe("setStateEvents", function() { describe("setStateEvents", function() {
it("should emit 'RoomState.members' for each m.room.member event", function() { it("should emit 'RoomState.members' for each m.room.member event", function() {
let memberEvents = [ const memberEvents = [
utils.mkMembership({ utils.mkMembership({
user: "@cleo:bar", mship: "invite", room: roomId, event: true, user: "@cleo:bar", mship: "invite", room: roomId, event: true,
}), }),
@@ -149,7 +149,7 @@ describe("RoomState", function() {
}); });
it("should emit 'RoomState.newMember' for each new member added", function() { it("should emit 'RoomState.newMember' for each new member added", function() {
let memberEvents = [ const memberEvents = [
utils.mkMembership({ utils.mkMembership({
user: "@cleo:bar", mship: "invite", room: roomId, event: true, user: "@cleo:bar", mship: "invite", room: roomId, event: true,
}), }),
@@ -168,7 +168,7 @@ describe("RoomState", function() {
}); });
it("should emit 'RoomState.events' for each state event", function() { it("should emit 'RoomState.events' for each state event", function() {
let events = [ const events = [
utils.mkMembership({ utils.mkMembership({
user: "@cleo:bar", mship: "invite", room: roomId, event: true, user: "@cleo:bar", mship: "invite", room: roomId, event: true,
}), }),
@@ -198,7 +198,7 @@ describe("RoomState", function() {
state.members[userA] = utils.mock(RoomMember); state.members[userA] = utils.mock(RoomMember);
state.members[userB] = utils.mock(RoomMember); state.members[userB] = utils.mock(RoomMember);
let powerLevelEvent = utils.mkEvent({ const powerLevelEvent = utils.mkEvent({
type: "m.room.power_levels", room: roomId, user: userA, event: true, type: "m.room.power_levels", room: roomId, user: userA, event: true,
content: { content: {
users_default: 10, users_default: 10,
@@ -210,20 +210,20 @@ describe("RoomState", function() {
state.setStateEvents([powerLevelEvent]); state.setStateEvents([powerLevelEvent]);
expect(state.members[userA].setPowerLevelEvent).toHaveBeenCalledWith( expect(state.members[userA].setPowerLevelEvent).toHaveBeenCalledWith(
powerLevelEvent powerLevelEvent,
); );
expect(state.members[userB].setPowerLevelEvent).toHaveBeenCalledWith( expect(state.members[userB].setPowerLevelEvent).toHaveBeenCalledWith(
powerLevelEvent powerLevelEvent,
); );
}); });
it("should call setPowerLevelEvent on a new RoomMember if power levels exist", it("should call setPowerLevelEvent on a new RoomMember if power levels exist",
function() { function() {
let userC = "@cleo:bar"; const userC = "@cleo:bar";
let memberEvent = utils.mkMembership({ const memberEvent = utils.mkMembership({
mship: "join", user: userC, room: roomId, event: true, mship: "join", user: userC, room: roomId, event: true,
}); });
let powerLevelEvent = utils.mkEvent({ const powerLevelEvent = utils.mkEvent({
type: "m.room.power_levels", room: roomId, user: userA, event: true, type: "m.room.power_levels", room: roomId, user: userA, event: true,
content: { content: {
users_default: 10, users_default: 10,
@@ -247,21 +247,21 @@ describe("RoomState", function() {
state.members[userA] = utils.mock(RoomMember); state.members[userA] = utils.mock(RoomMember);
state.members[userB] = utils.mock(RoomMember); state.members[userB] = utils.mock(RoomMember);
let memberEvent = utils.mkMembership({ const memberEvent = utils.mkMembership({
user: userB, mship: "leave", room: roomId, event: true, user: userB, mship: "leave", room: roomId, event: true,
}); });
state.setStateEvents([memberEvent]); state.setStateEvents([memberEvent]);
expect(state.members[userA].setMembershipEvent).not.toHaveBeenCalled(); expect(state.members[userA].setMembershipEvent).not.toHaveBeenCalled();
expect(state.members[userB].setMembershipEvent).toHaveBeenCalledWith( expect(state.members[userB].setMembershipEvent).toHaveBeenCalledWith(
memberEvent, state memberEvent, state,
); );
}); });
}); });
describe("setTypingEvent", function() { describe("setTypingEvent", function() {
it("should call setTypingEvent on each RoomMember", function() { it("should call setTypingEvent on each RoomMember", function() {
let typingEvent = utils.mkEvent({ const typingEvent = utils.mkEvent({
type: "m.typing", room: roomId, event: true, content: { type: "m.typing", room: roomId, event: true, content: {
user_ids: [userA], user_ids: [userA],
}, },
@@ -272,10 +272,10 @@ describe("RoomState", function() {
state.setTypingEvent(typingEvent); state.setTypingEvent(typingEvent);
expect(state.members[userA].setTypingEvent).toHaveBeenCalledWith( expect(state.members[userA].setTypingEvent).toHaveBeenCalledWith(
typingEvent typingEvent,
); );
expect(state.members[userB].setTypingEvent).toHaveBeenCalledWith( expect(state.members[userB].setTypingEvent).toHaveBeenCalledWith(
typingEvent typingEvent,
); );
}); });
}); });
@@ -284,7 +284,7 @@ describe("RoomState", function() {
it("should say non-joined members may not send state", it("should say non-joined members may not send state",
function() { function() {
expect(state.maySendStateEvent( expect(state.maySendStateEvent(
'm.room.name', "@nobody:nowhere" 'm.room.name', "@nobody:nowhere",
)).toEqual(false); )).toEqual(false);
}); });
@@ -296,7 +296,7 @@ describe("RoomState", function() {
it("should say members with power >=50 may send state with power level event " + it("should say members with power >=50 may send state with power level event " +
"but no state default", "but no state default",
function() { function() {
let powerLevelEvent = { const powerLevelEvent = {
type: "m.room.power_levels", room: roomId, user: userA, event: true, type: "m.room.power_levels", room: roomId, user: userA, event: true,
content: { content: {
users_default: 10, users_default: 10,
@@ -316,7 +316,7 @@ describe("RoomState", function() {
it("should obey state_default", it("should obey state_default",
function() { function() {
let powerLevelEvent = { const powerLevelEvent = {
type: "m.room.power_levels", room: roomId, user: userA, event: true, type: "m.room.power_levels", room: roomId, user: userA, event: true,
content: { content: {
users_default: 10, users_default: 10,
@@ -337,7 +337,7 @@ describe("RoomState", function() {
it("should honour explicit event power levels in the power_levels event", it("should honour explicit event power levels in the power_levels event",
function() { function() {
let powerLevelEvent = { const powerLevelEvent = {
type: "m.room.power_levels", room: roomId, user: userA, event: true, type: "m.room.power_levels", room: roomId, user: userA, event: true,
content: { content: {
events: { events: {
@@ -367,7 +367,7 @@ describe("RoomState", function() {
it("should say non-joined members may not send events", it("should say non-joined members may not send events",
function() { function() {
expect(state.maySendEvent( expect(state.maySendEvent(
'm.room.message', "@nobody:nowhere" 'm.room.message', "@nobody:nowhere",
)).toEqual(false); )).toEqual(false);
expect(state.maySendMessage("@nobody:nowhere")).toEqual(false); expect(state.maySendMessage("@nobody:nowhere")).toEqual(false);
}); });
@@ -380,7 +380,7 @@ describe("RoomState", function() {
it("should obey events_default", it("should obey events_default",
function() { function() {
let powerLevelEvent = { const powerLevelEvent = {
type: "m.room.power_levels", room: roomId, user: userA, event: true, type: "m.room.power_levels", room: roomId, user: userA, event: true,
content: { content: {
users_default: 10, users_default: 10,
@@ -404,7 +404,7 @@ describe("RoomState", function() {
it("should honour explicit event power levels in the power_levels event", it("should honour explicit event power levels in the power_levels event",
function() { function() {
let powerLevelEvent = { const powerLevelEvent = {
type: "m.room.power_levels", room: roomId, user: userA, event: true, type: "m.room.power_levels", room: roomId, user: userA, event: true,
content: { content: {
events: { events: {

View File

@@ -1,18 +1,18 @@
"use strict"; "use strict";
let sdk = require("../.."); const sdk = require("../..");
let Room = sdk.Room; const Room = sdk.Room;
let RoomState = sdk.RoomState; const RoomState = sdk.RoomState;
let MatrixEvent = sdk.MatrixEvent; const MatrixEvent = sdk.MatrixEvent;
let EventStatus = sdk.EventStatus; const EventStatus = sdk.EventStatus;
let EventTimeline = sdk.EventTimeline; const EventTimeline = sdk.EventTimeline;
let utils = require("../test-utils"); const utils = require("../test-utils");
describe("Room", function() { describe("Room", function() {
let roomId = "!foo:bar"; const roomId = "!foo:bar";
let userA = "@alice:bar"; const userA = "@alice:bar";
let userB = "@bertha:bar"; const userB = "@bertha:bar";
let userC = "@clarissa:bar"; const userC = "@clarissa:bar";
let userD = "@dorothy:bar"; const userD = "@dorothy:bar";
let room; let room;
beforeEach(function() { beforeEach(function() {
@@ -26,7 +26,7 @@ describe("Room", function() {
}); });
describe("getAvatarUrl", function() { describe("getAvatarUrl", function() {
let hsUrl = "https://my.home.server"; const hsUrl = "https://my.home.server";
it("should return the URL from m.room.avatar preferentially", function() { it("should return the URL from m.room.avatar preferentially", function() {
room.currentState.getStateEvents.andCallFake(function(type, key) { room.currentState.getStateEvents.andCallFake(function(type, key) {
@@ -43,7 +43,7 @@ describe("Room", function() {
}); });
} }
}); });
let url = room.getAvatarUrl(hsUrl); const url = room.getAvatarUrl(hsUrl);
// we don't care about how the mxc->http conversion is done, other // we don't care about how the mxc->http conversion is done, other
// than it contains the mxc body. // than it contains the mxc body.
expect(url.indexOf("flibble/wibble")).not.toEqual(-1); expect(url.indexOf("flibble/wibble")).not.toEqual(-1);
@@ -51,13 +51,13 @@ describe("Room", function() {
it("should return an identicon HTTP URL if allowDefault was set and there " + it("should return an identicon HTTP URL if allowDefault was set and there " +
"was no m.room.avatar event", function() { "was no m.room.avatar event", function() {
let url = room.getAvatarUrl(hsUrl, 64, 64, "crop", true); const url = room.getAvatarUrl(hsUrl, 64, 64, "crop", true);
expect(url.indexOf("http")).toEqual(0); // don't care about form expect(url.indexOf("http")).toEqual(0); // don't care about form
}); });
it("should return nothing if there is no m.room.avatar and allowDefault=false", it("should return nothing if there is no m.room.avatar and allowDefault=false",
function() { function() {
let url = room.getAvatarUrl(hsUrl, 64, 64, "crop", false); const url = room.getAvatarUrl(hsUrl, 64, 64, "crop", false);
expect(url).toEqual(null); expect(url).toEqual(null);
}); });
}); });
@@ -83,7 +83,7 @@ describe("Room", function() {
}); });
describe("addLiveEvents", function() { describe("addLiveEvents", function() {
let events = [ const events = [
utils.mkMessage({ utils.mkMessage({
room: roomId, user: userA, msg: "changing room name", event: true, room: roomId, user: userA, msg: "changing room name", event: true,
}), }),
@@ -95,7 +95,7 @@ describe("Room", function() {
it("should call RoomState.setTypingEvent on m.typing events", function() { it("should call RoomState.setTypingEvent on m.typing events", function() {
room.currentState = utils.mock(RoomState); room.currentState = utils.mock(RoomState);
let typing = utils.mkEvent({ const typing = utils.mkEvent({
room: roomId, type: "m.typing", event: true, content: { room: roomId, type: "m.typing", event: true, content: {
user_ids: [userA], user_ids: [userA],
}, },
@@ -112,7 +112,7 @@ describe("Room", function() {
it("should replace a timeline event if dupe strategy is 'replace'", function() { it("should replace a timeline event if dupe strategy is 'replace'", function() {
// make a duplicate // make a duplicate
let dupe = utils.mkMessage({ const dupe = utils.mkMessage({
room: roomId, user: userA, msg: "dupe", event: true, room: roomId, user: userA, msg: "dupe", event: true,
}); });
dupe.event.event_id = events[0].getId(); dupe.event.event_id = events[0].getId();
@@ -124,7 +124,7 @@ describe("Room", function() {
it("should ignore a given dupe event if dupe strategy is 'ignore'", function() { it("should ignore a given dupe event if dupe strategy is 'ignore'", function() {
// make a duplicate // make a duplicate
let dupe = utils.mkMessage({ const dupe = utils.mkMessage({
room: roomId, user: userA, msg: "dupe", event: true, room: roomId, user: userA, msg: "dupe", event: true,
}); });
dupe.event.event_id = events[0].getId(); dupe.event.event_id = events[0].getId();
@@ -150,7 +150,7 @@ describe("Room", function() {
it("should call setStateEvents on the right RoomState with the right " + it("should call setStateEvents on the right RoomState with the right " +
"forwardLooking value for new events", function() { "forwardLooking value for new events", function() {
let events = [ const events = [
utils.mkMembership({ utils.mkMembership({
room: roomId, mship: "invite", user: userB, skey: userA, event: true, room: roomId, mship: "invite", user: userB, skey: userA, event: true,
}), }),
@@ -163,10 +163,10 @@ describe("Room", function() {
]; ];
room.addLiveEvents(events); room.addLiveEvents(events);
expect(room.currentState.setStateEvents).toHaveBeenCalledWith( expect(room.currentState.setStateEvents).toHaveBeenCalledWith(
[events[0]] [events[0]],
); );
expect(room.currentState.setStateEvents).toHaveBeenCalledWith( expect(room.currentState.setStateEvents).toHaveBeenCalledWith(
[events[1]] [events[1]],
); );
expect(events[0].forwardLooking).toBe(true); expect(events[0].forwardLooking).toBe(true);
expect(events[1].forwardLooking).toBe(true); expect(events[1].forwardLooking).toBe(true);
@@ -174,7 +174,7 @@ describe("Room", function() {
}); });
it("should synthesize read receipts for the senders of events", function() { it("should synthesize read receipts for the senders of events", function() {
let sentinel = { const sentinel = {
userId: userA, userId: userA,
membership: "join", membership: "join",
name: "Alice", name: "Alice",
@@ -190,17 +190,17 @@ describe("Room", function() {
}); });
it("should emit Room.localEchoUpdated when a local echo is updated", function() { it("should emit Room.localEchoUpdated when a local echo is updated", function() {
let localEvent = utils.mkMessage({ const localEvent = utils.mkMessage({
room: roomId, user: userA, event: true, room: roomId, user: userA, event: true,
}); });
localEvent.status = EventStatus.SENDING; localEvent.status = EventStatus.SENDING;
let localEventId = localEvent.getId(); const localEventId = localEvent.getId();
let remoteEvent = utils.mkMessage({ const remoteEvent = utils.mkMessage({
room: roomId, user: userA, event: true, room: roomId, user: userA, event: true,
}); });
remoteEvent.event.unsigned = {transaction_id: "TXN_ID"}; remoteEvent.event.unsigned = {transaction_id: "TXN_ID"};
let remoteEventId = remoteEvent.getId(); const remoteEventId = remoteEvent.getId();
let callCount = 0; let callCount = 0;
room.on("Room.localEchoUpdated", room.on("Room.localEchoUpdated",
@@ -222,7 +222,7 @@ describe("Room", function() {
break; break;
} }
callCount += 1; callCount += 1;
} },
); );
// first add the local echo // first add the local echo
@@ -238,7 +238,7 @@ describe("Room", function() {
}); });
describe("addEventsToTimeline", function() { describe("addEventsToTimeline", function() {
let events = [ const events = [
utils.mkMessage({ utils.mkMessage({
room: roomId, user: userA, msg: "changing room name", event: true, room: roomId, user: userA, msg: "changing room name", event: true,
}), }),
@@ -278,12 +278,12 @@ describe("Room", function() {
describe("event metadata handling", function() { describe("event metadata handling", function() {
it("should set event.sender for new and old events", function() { it("should set event.sender for new and old events", function() {
let sentinel = { const sentinel = {
userId: userA, userId: userA,
membership: "join", membership: "join",
name: "Alice", name: "Alice",
}; };
let oldSentinel = { const oldSentinel = {
userId: userA, userId: userA,
membership: "join", membership: "join",
name: "Old Alice", name: "Old Alice",
@@ -301,11 +301,11 @@ describe("Room", function() {
return null; return null;
}); });
let newEv = utils.mkEvent({ const newEv = utils.mkEvent({
type: "m.room.name", room: roomId, user: userA, event: true, type: "m.room.name", room: roomId, user: userA, event: true,
content: { name: "New Room Name" }, content: { name: "New Room Name" },
}); });
let oldEv = utils.mkEvent({ const oldEv = utils.mkEvent({
type: "m.room.name", room: roomId, user: userA, event: true, type: "m.room.name", room: roomId, user: userA, event: true,
content: { name: "Old Room Name" }, content: { name: "Old Room Name" },
}); });
@@ -317,12 +317,12 @@ describe("Room", function() {
it("should set event.target for new and old m.room.member events", it("should set event.target for new and old m.room.member events",
function() { function() {
let sentinel = { const sentinel = {
userId: userA, userId: userA,
membership: "join", membership: "join",
name: "Alice", name: "Alice",
}; };
let oldSentinel = { const oldSentinel = {
userId: userA, userId: userA,
membership: "join", membership: "join",
name: "Old Alice", name: "Old Alice",
@@ -340,10 +340,10 @@ describe("Room", function() {
return null; return null;
}); });
let newEv = utils.mkMembership({ const newEv = utils.mkMembership({
room: roomId, mship: "invite", user: userB, skey: userA, event: true, room: roomId, mship: "invite", user: userB, skey: userA, event: true,
}); });
let oldEv = utils.mkMembership({ const oldEv = utils.mkMembership({
room: roomId, mship: "ban", user: userB, skey: userA, event: true, room: roomId, mship: "ban", user: userB, skey: userA, event: true,
}); });
room.addLiveEvents([newEv]); room.addLiveEvents([newEv]);
@@ -354,7 +354,7 @@ describe("Room", function() {
it("should call setStateEvents on the right RoomState with the right " + it("should call setStateEvents on the right RoomState with the right " +
"forwardLooking value for old events", function() { "forwardLooking value for old events", function() {
let events = [ const events = [
utils.mkMembership({ utils.mkMembership({
room: roomId, mship: "invite", user: userB, skey: userA, event: true, room: roomId, mship: "invite", user: userB, skey: userA, event: true,
}), }),
@@ -368,10 +368,10 @@ describe("Room", function() {
room.addEventsToTimeline(events, true, room.getLiveTimeline()); room.addEventsToTimeline(events, true, room.getLiveTimeline());
expect(room.oldState.setStateEvents).toHaveBeenCalledWith( expect(room.oldState.setStateEvents).toHaveBeenCalledWith(
[events[0]] [events[0]],
); );
expect(room.oldState.setStateEvents).toHaveBeenCalledWith( expect(room.oldState.setStateEvents).toHaveBeenCalledWith(
[events[1]] [events[1]],
); );
expect(events[0].forwardLooking).toBe(false); expect(events[0].forwardLooking).toBe(false);
expect(events[1].forwardLooking).toBe(false); expect(events[1].forwardLooking).toBe(false);
@@ -379,8 +379,8 @@ describe("Room", function() {
}); });
}); });
let resetTimelineTests = function(timelineSupport) { const resetTimelineTests = function(timelineSupport) {
let events = [ const events = [
utils.mkMessage({ utils.mkMessage({
room: roomId, user: userA, msg: "A message", event: true, room: roomId, user: userA, msg: "A message", event: true,
}), }),
@@ -404,8 +404,8 @@ describe("Room", function() {
room.resetLiveTimeline(); room.resetLiveTimeline();
room.addLiveEvents([events[2]]); room.addLiveEvents([events[2]]);
let oldState = room.getLiveTimeline().getState(EventTimeline.BACKWARDS); const oldState = room.getLiveTimeline().getState(EventTimeline.BACKWARDS);
let newState = room.getLiveTimeline().getState(EventTimeline.FORWARDS); const newState = room.getLiveTimeline().getState(EventTimeline.FORWARDS);
expect(room.getLiveTimeline().getEvents().length).toEqual(1); expect(room.getLiveTimeline().getEvents().length).toEqual(1);
expect(oldState.getStateEvents("m.room.name", "")).toEqual(events[1]); expect(oldState.getStateEvents("m.room.name", "")).toEqual(events[1]);
expect(newState.getStateEvents("m.room.name", "")).toEqual(events[2]); expect(newState.getStateEvents("m.room.name", "")).toEqual(events[2]);
@@ -417,7 +417,7 @@ describe("Room", function() {
room.resetLiveTimeline(); room.resetLiveTimeline();
room.addLiveEvents([events[2]]); room.addLiveEvents([events[2]]);
let newLiveTimeline = room.getLiveTimeline(); const newLiveTimeline = room.getLiveTimeline();
expect(room.timeline).toEqual(newLiveTimeline.getEvents()); expect(room.timeline).toEqual(newLiveTimeline.getEvents());
expect(room.oldState).toEqual( expect(room.oldState).toEqual(
newLiveTimeline.getState(EventTimeline.BACKWARDS)); newLiveTimeline.getState(EventTimeline.BACKWARDS));
@@ -434,7 +434,7 @@ describe("Room", function() {
// make sure that the pagination token has been set before the // make sure that the pagination token has been set before the
// event is emitted. // event is emitted.
let tok = emitRoom.getLiveTimeline() const tok = emitRoom.getLiveTimeline()
.getPaginationToken(EventTimeline.BACKWARDS); .getPaginationToken(EventTimeline.BACKWARDS);
expect(tok).toEqual("pagToken"); expect(tok).toEqual("pagToken");
@@ -447,10 +447,10 @@ describe("Room", function() {
" old timelines", function() { " old timelines", function() {
room.addLiveEvents([events[0]]); room.addLiveEvents([events[0]]);
expect(room.timeline.length).toEqual(1); expect(room.timeline.length).toEqual(1);
let firstLiveTimeline = room.getLiveTimeline(); const firstLiveTimeline = room.getLiveTimeline();
room.resetLiveTimeline(); room.resetLiveTimeline();
let tl = room.getTimelineForEvent(events[0].getId()); const tl = room.getTimelineForEvent(events[0].getId());
expect(tl).toBe(timelineSupport ? firstLiveTimeline : null); expect(tl).toBe(timelineSupport ? firstLiveTimeline : null);
}); });
}; };
@@ -465,7 +465,7 @@ describe("Room", function() {
room = new Room(roomId, {timelineSupport: true}); room = new Room(roomId, {timelineSupport: true});
}); });
let events = [ const events = [
utils.mkMessage({ utils.mkMessage({
room: roomId, user: userA, msg: "1111", event: true, room: roomId, user: userA, msg: "1111", event: true,
}), }),
@@ -492,7 +492,7 @@ describe("Room", function() {
}); });
it("should handle events in adjacent timelines", function() { it("should handle events in adjacent timelines", function() {
let oldTimeline = room.addTimeline(); const oldTimeline = room.addTimeline();
oldTimeline.setNeighbouringTimeline(room.getLiveTimeline(), 'f'); oldTimeline.setNeighbouringTimeline(room.getLiveTimeline(), 'f');
room.getLiveTimeline().setNeighbouringTimeline(oldTimeline, 'b'); room.getLiveTimeline().setNeighbouringTimeline(oldTimeline, 'b');
@@ -508,7 +508,7 @@ describe("Room", function() {
}); });
it("should return null for events in non-adjacent timelines", function() { it("should return null for events in non-adjacent timelines", function() {
let oldTimeline = room.addTimeline(); const oldTimeline = room.addTimeline();
room.addEventsToTimeline([events[0]], false, oldTimeline); room.addEventsToTimeline([events[0]], false, oldTimeline);
room.addLiveEvents([events[1]]); room.addLiveEvents([events[1]]);
@@ -545,7 +545,7 @@ describe("Room", function() {
{ userId: "@cleo:bar", membership: "leave" }, { userId: "@cleo:bar", membership: "leave" },
]; ];
}); });
let res = room.getJoinedMembers(); const res = room.getJoinedMembers();
expect(res.length).toEqual(1); expect(res.length).toEqual(1);
expect(res[0].userId).toEqual("@alice:bar"); expect(res[0].userId).toEqual("@alice:bar");
}); });
@@ -556,7 +556,7 @@ describe("Room", function() {
{ userId: "@bob:bar", membership: "invite" }, { userId: "@bob:bar", membership: "invite" },
]; ];
}); });
let res = room.getJoinedMembers(); const res = room.getJoinedMembers();
expect(res.length).toEqual(0); expect(res.length).toEqual(0);
}); });
}); });
@@ -607,14 +607,14 @@ describe("Room", function() {
// event.type + "$" event.state_key : MatrixEvent // event.type + "$" event.state_key : MatrixEvent
}; };
let setJoinRule = function(rule) { const setJoinRule = function(rule) {
stateLookup["m.room.join_rules$"] = utils.mkEvent({ stateLookup["m.room.join_rules$"] = utils.mkEvent({
type: "m.room.join_rules", room: roomId, user: userA, content: { type: "m.room.join_rules", room: roomId, user: userA, content: {
join_rule: rule, join_rule: rule,
}, event: true, }, event: true,
}); });
}; };
let setAliases = function(aliases, stateKey) { const setAliases = function(aliases, stateKey) {
if (!stateKey) { if (!stateKey) {
stateKey = "flibble"; stateKey = "flibble";
} }
@@ -624,14 +624,14 @@ describe("Room", function() {
}, event: true, }, event: true,
}); });
}; };
let setRoomName = function(name) { const setRoomName = function(name) {
stateLookup["m.room.name$"] = utils.mkEvent({ stateLookup["m.room.name$"] = utils.mkEvent({
type: "m.room.name", room: roomId, user: userA, content: { type: "m.room.name", room: roomId, user: userA, content: {
name: name, name: name,
}, event: true, }, event: true,
}); });
}; };
let addMember = function(userId, state, opts) { const addMember = function(userId, state, opts) {
if (!state) { if (!state) {
state = "join"; state = "join";
} }
@@ -648,9 +648,9 @@ describe("Room", function() {
stateLookup = {}; stateLookup = {};
room.currentState.getStateEvents.andCallFake(function(type, key) { room.currentState.getStateEvents.andCallFake(function(type, key) {
if (key === undefined) { if (key === undefined) {
let prefix = type + "$"; const prefix = type + "$";
let list = []; const list = [];
for (let stateBlob in stateLookup) { for (const stateBlob in stateLookup) {
if (!stateLookup.hasOwnProperty(stateBlob)) { if (!stateLookup.hasOwnProperty(stateBlob)) {
continue; continue;
} }
@@ -664,8 +664,8 @@ describe("Room", function() {
} }
}); });
room.currentState.getMembers.andCallFake(function() { room.currentState.getMembers.andCallFake(function() {
let memberEvents = room.currentState.getStateEvents("m.room.member"); const memberEvents = room.currentState.getStateEvents("m.room.member");
let members = []; const members = [];
for (let i = 0; i < memberEvents.length; i++) { for (let i = 0; i < memberEvents.length; i++) {
members.push({ members.push({
name: memberEvents[i].event.content && name: memberEvents[i].event.content &&
@@ -679,8 +679,8 @@ describe("Room", function() {
return members; return members;
}); });
room.currentState.getMember.andCallFake(function(userId) { room.currentState.getMember.andCallFake(function(userId) {
let memberEvent = room.currentState.getStateEvents( const memberEvent = room.currentState.getStateEvents(
"m.room.member", userId "m.room.member", userId,
); );
return { return {
name: memberEvent.event.content && name: memberEvent.event.content &&
@@ -696,7 +696,7 @@ describe("Room", function() {
describe("Room.recalculate => Stripped State Events", function() { describe("Room.recalculate => Stripped State Events", function() {
it("should set stripped state events as actual state events if the " + it("should set stripped state events as actual state events if the " +
"room is an invite room", function() { "room is an invite room", function() {
let roomName = "flibble"; const roomName = "flibble";
addMember(userA, "invite"); addMember(userA, "invite");
stateLookup["m.room.member$" + userA].event.invite_room_state = [ stateLookup["m.room.member$" + userA].event.invite_room_state = [
@@ -712,7 +712,7 @@ describe("Room", function() {
room.recalculate(userA); room.recalculate(userA);
expect(room.currentState.setStateEvents).toHaveBeenCalled(); expect(room.currentState.setStateEvents).toHaveBeenCalled();
// first call, first arg (which is an array), first element in array // first call, first arg (which is an array), first element in array
let fakeEvent = room.currentState.setStateEvents.calls[0].args[0][0]; const fakeEvent = room.currentState.setStateEvents.calls[0].args[0][0];
expect(fakeEvent.getContent()).toEqual({ expect(fakeEvent.getContent()).toEqual({
name: roomName, name: roomName,
}); });
@@ -745,9 +745,9 @@ describe("Room", function() {
addMember(userC); addMember(userC);
addMember(userD); addMember(userD);
room.recalculate(userA); room.recalculate(userA);
let name = room.name; const name = room.name;
// we expect at least 1 member to be mentioned // we expect at least 1 member to be mentioned
let others = [userB, userC, userD]; const others = [userB, userC, userD];
let found = false; let found = false;
for (let i = 0; i < others.length; i++) { for (let i = 0; i < others.length; i++) {
if (name.indexOf(others[i]) !== -1) { if (name.indexOf(others[i]) !== -1) {
@@ -766,7 +766,7 @@ describe("Room", function() {
addMember(userB); addMember(userB);
addMember(userC); addMember(userC);
room.recalculate(userA); room.recalculate(userA);
let name = room.name; const name = room.name;
expect(name.indexOf(userB)).not.toEqual(-1, name); expect(name.indexOf(userB)).not.toEqual(-1, name);
expect(name.indexOf(userC)).not.toEqual(-1, name); expect(name.indexOf(userC)).not.toEqual(-1, name);
}); });
@@ -779,7 +779,7 @@ describe("Room", function() {
addMember(userB); addMember(userB);
addMember(userC); addMember(userC);
room.recalculate(userA); room.recalculate(userA);
let name = room.name; const name = room.name;
expect(name.indexOf(userB)).not.toEqual(-1, name); expect(name.indexOf(userB)).not.toEqual(-1, name);
expect(name.indexOf(userC)).not.toEqual(-1, name); expect(name.indexOf(userC)).not.toEqual(-1, name);
}); });
@@ -791,7 +791,7 @@ describe("Room", function() {
addMember(userA); addMember(userA);
addMember(userB); addMember(userB);
room.recalculate(userA); room.recalculate(userA);
let name = room.name; const name = room.name;
expect(name.indexOf(userB)).not.toEqual(-1, name); expect(name.indexOf(userB)).not.toEqual(-1, name);
}); });
@@ -802,7 +802,7 @@ describe("Room", function() {
addMember(userA); addMember(userA);
addMember(userB); addMember(userB);
room.recalculate(userA); room.recalculate(userA);
let name = room.name; const name = room.name;
expect(name.indexOf(userB)).not.toEqual(-1, name); expect(name.indexOf(userB)).not.toEqual(-1, name);
}); });
@@ -812,47 +812,47 @@ describe("Room", function() {
addMember(userA, "invite", {user: userB}); addMember(userA, "invite", {user: userB});
addMember(userB); addMember(userB);
room.recalculate(userA); room.recalculate(userA);
let name = room.name; const name = room.name;
expect(name.indexOf(userB)).not.toEqual(-1, name); expect(name.indexOf(userB)).not.toEqual(-1, name);
}); });
it("should show the room alias if one exists for private " + it("should show the room alias if one exists for private " +
"(invite join_rules) rooms if a room name doesn't exist.", function() { "(invite join_rules) rooms if a room name doesn't exist.", function() {
let alias = "#room_alias:here"; const alias = "#room_alias:here";
setJoinRule("invite"); setJoinRule("invite");
setAliases([alias, "#another:one"]); setAliases([alias, "#another:one"]);
room.recalculate(userA); room.recalculate(userA);
let name = room.name; const name = room.name;
expect(name).toEqual(alias); expect(name).toEqual(alias);
}); });
it("should show the room alias if one exists for public " + it("should show the room alias if one exists for public " +
"(public join_rules) rooms if a room name doesn't exist.", function() { "(public join_rules) rooms if a room name doesn't exist.", function() {
let alias = "#room_alias:here"; const alias = "#room_alias:here";
setJoinRule("public"); setJoinRule("public");
setAliases([alias, "#another:one"]); setAliases([alias, "#another:one"]);
room.recalculate(userA); room.recalculate(userA);
let name = room.name; const name = room.name;
expect(name).toEqual(alias); expect(name).toEqual(alias);
}); });
it("should show the room name if one exists for private " + it("should show the room name if one exists for private " +
"(invite join_rules) rooms.", function() { "(invite join_rules) rooms.", function() {
let roomName = "A mighty name indeed"; const roomName = "A mighty name indeed";
setJoinRule("invite"); setJoinRule("invite");
setRoomName(roomName); setRoomName(roomName);
room.recalculate(userA); room.recalculate(userA);
let name = room.name; const name = room.name;
expect(name).toEqual(roomName); expect(name).toEqual(roomName);
}); });
it("should show the room name if one exists for public " + it("should show the room name if one exists for public " +
"(public join_rules) rooms.", function() { "(public join_rules) rooms.", function() {
let roomName = "A mighty name indeed"; const roomName = "A mighty name indeed";
setJoinRule("public"); setJoinRule("public");
setRoomName(roomName); setRoomName(roomName);
room.recalculate(userA); room.recalculate(userA);
let name = room.name; const name = room.name;
expect(name).toEqual(roomName); expect(name).toEqual(roomName);
}); });
@@ -861,7 +861,7 @@ describe("Room", function() {
setJoinRule("invite"); setJoinRule("invite");
addMember(userA); addMember(userA);
room.recalculate(userA); room.recalculate(userA);
let name = room.name; const name = room.name;
expect(name).toEqual("Empty room"); expect(name).toEqual("Empty room");
}); });
@@ -870,7 +870,7 @@ describe("Room", function() {
setJoinRule("public"); setJoinRule("public");
addMember(userA); addMember(userA);
room.recalculate(userA); room.recalculate(userA);
let name = room.name; const name = room.name;
expect(name).toEqual("Empty room"); expect(name).toEqual("Empty room");
}); });
@@ -878,7 +878,7 @@ describe("Room", function() {
"alias or members in the room.", "alias or members in the room.",
function() { function() {
room.recalculate(userA); room.recalculate(userA);
let name = room.name; const name = room.name;
expect(name).toEqual("Empty room"); expect(name).toEqual("Empty room");
}); });
@@ -889,7 +889,7 @@ describe("Room", function() {
addMember(userA, 'join', {name: "Alice"}); addMember(userA, 'join', {name: "Alice"});
addMember(userB, "invite", {user: userA}); addMember(userB, "invite", {user: userA});
room.recalculate(userB); room.recalculate(userB);
let name = room.name; const name = room.name;
expect(name).toEqual("Invite from Alice"); expect(name).toEqual("Invite from Alice");
}); });
@@ -899,20 +899,20 @@ describe("Room", function() {
addMember(userA); addMember(userA);
addMember(userB, "invite", {user: userA}); addMember(userB, "invite", {user: userA});
room.recalculate(userB); room.recalculate(userB);
let name = room.name; const name = room.name;
expect(name).toEqual("Invite from " + userA); expect(name).toEqual("Invite from " + userA);
}); });
}); });
}); });
describe("receipts", function() { describe("receipts", function() {
let eventToAck = utils.mkMessage({ const eventToAck = utils.mkMessage({
room: roomId, user: userA, msg: "PLEASE ACKNOWLEDGE MY EXISTENCE", room: roomId, user: userA, msg: "PLEASE ACKNOWLEDGE MY EXISTENCE",
event: true, event: true,
}); });
function mkReceipt(roomId, records) { function mkReceipt(roomId, records) {
let content = {}; const content = {};
records.forEach(function(r) { records.forEach(function(r) {
if (!content[r.eventId]) { if (!content[r.eventId]) {
content[r.eventId] = {}; content[r.eventId] = {};
@@ -944,7 +944,7 @@ describe("Room", function() {
describe("addReceipt", function() { describe("addReceipt", function() {
it("should store the receipt so it can be obtained via getReceiptsForEvent", it("should store the receipt so it can be obtained via getReceiptsForEvent",
function() { function() {
let ts = 13787898424; const ts = 13787898424;
room.addReceipt(mkReceipt(roomId, [ room.addReceipt(mkReceipt(roomId, [
mkRecord(eventToAck.getId(), "m.read", userB, ts), mkRecord(eventToAck.getId(), "m.read", userB, ts),
])); ]));
@@ -959,12 +959,12 @@ describe("Room", function() {
it("should emit an event when a receipt is added", it("should emit an event when a receipt is added",
function() { function() {
let listener = jasmine.createSpy('spy'); const listener = jasmine.createSpy('spy');
room.on("Room.receipt", listener); room.on("Room.receipt", listener);
let ts = 13787898424; const ts = 13787898424;
let receiptEvent = mkReceipt(roomId, [ const receiptEvent = mkReceipt(roomId, [
mkRecord(eventToAck.getId(), "m.read", userB, ts), mkRecord(eventToAck.getId(), "m.read", userB, ts),
]); ]);
@@ -973,15 +973,15 @@ describe("Room", function() {
}); });
it("should clobber receipts based on type and user ID", function() { it("should clobber receipts based on type and user ID", function() {
let nextEventToAck = utils.mkMessage({ const nextEventToAck = utils.mkMessage({
room: roomId, user: userA, msg: "I AM HERE YOU KNOW", room: roomId, user: userA, msg: "I AM HERE YOU KNOW",
event: true, event: true,
}); });
let ts = 13787898424; const ts = 13787898424;
room.addReceipt(mkReceipt(roomId, [ room.addReceipt(mkReceipt(roomId, [
mkRecord(eventToAck.getId(), "m.read", userB, ts), mkRecord(eventToAck.getId(), "m.read", userB, ts),
])); ]));
let ts2 = 13787899999; const ts2 = 13787899999;
room.addReceipt(mkReceipt(roomId, [ room.addReceipt(mkReceipt(roomId, [
mkRecord(nextEventToAck.getId(), "m.read", userB, ts2), mkRecord(nextEventToAck.getId(), "m.read", userB, ts2),
])); ]));
@@ -996,27 +996,27 @@ describe("Room", function() {
}); });
it("should persist multiple receipts for a single event ID", function() { it("should persist multiple receipts for a single event ID", function() {
let ts = 13787898424; const ts = 13787898424;
room.addReceipt(mkReceipt(roomId, [ room.addReceipt(mkReceipt(roomId, [
mkRecord(eventToAck.getId(), "m.read", userB, ts), mkRecord(eventToAck.getId(), "m.read", userB, ts),
mkRecord(eventToAck.getId(), "m.read", userC, ts), mkRecord(eventToAck.getId(), "m.read", userC, ts),
mkRecord(eventToAck.getId(), "m.read", userD, ts), mkRecord(eventToAck.getId(), "m.read", userD, ts),
])); ]));
expect(room.getUsersReadUpTo(eventToAck)).toEqual( expect(room.getUsersReadUpTo(eventToAck)).toEqual(
[userB, userC, userD] [userB, userC, userD],
); );
}); });
it("should persist multiple receipts for a single receipt type", function() { it("should persist multiple receipts for a single receipt type", function() {
let eventTwo = utils.mkMessage({ const eventTwo = utils.mkMessage({
room: roomId, user: userA, msg: "2222", room: roomId, user: userA, msg: "2222",
event: true, event: true,
}); });
let eventThree = utils.mkMessage({ const eventThree = utils.mkMessage({
room: roomId, user: userA, msg: "3333", room: roomId, user: userA, msg: "3333",
event: true, event: true,
}); });
let ts = 13787898424; const ts = 13787898424;
room.addReceipt(mkReceipt(roomId, [ room.addReceipt(mkReceipt(roomId, [
mkRecord(eventToAck.getId(), "m.read", userB, ts), mkRecord(eventToAck.getId(), "m.read", userB, ts),
mkRecord(eventTwo.getId(), "m.read", userC, ts), mkRecord(eventTwo.getId(), "m.read", userC, ts),
@@ -1059,7 +1059,7 @@ describe("Room", function() {
}); });
it("should prioritise the most recent event", function() { it("should prioritise the most recent event", function() {
let events = [ const events = [
utils.mkMessage({ utils.mkMessage({
room: roomId, user: userA, msg: "1111", room: roomId, user: userA, msg: "1111",
event: true, event: true,
@@ -1075,7 +1075,7 @@ describe("Room", function() {
]; ];
room.addLiveEvents(events); room.addLiveEvents(events);
let ts = 13787898424; const ts = 13787898424;
// check it initialises correctly // check it initialises correctly
room.addReceipt(mkReceipt(roomId, [ room.addReceipt(mkReceipt(roomId, [
@@ -1099,7 +1099,7 @@ describe("Room", function() {
describe("getUsersReadUpTo", function() { describe("getUsersReadUpTo", function() {
it("should return user IDs read up to the given event", function() { it("should return user IDs read up to the given event", function() {
let ts = 13787898424; const ts = 13787898424;
room.addReceipt(mkReceipt(roomId, [ room.addReceipt(mkReceipt(roomId, [
mkRecord(eventToAck.getId(), "m.read", userB, ts), mkRecord(eventToAck.getId(), "m.read", userB, ts),
])); ]));
@@ -1110,7 +1110,7 @@ describe("Room", function() {
describe("tags", function() { describe("tags", function() {
function mkTags(roomId, tags) { function mkTags(roomId, tags) {
let content = { "tags": tags }; const content = { "tags": tags };
return new MatrixEvent({ return new MatrixEvent({
content: content, content: content,
room_id: roomId, room_id: roomId,
@@ -1122,7 +1122,7 @@ describe("Room", function() {
it("should set tags on rooms from event stream so " + it("should set tags on rooms from event stream so " +
"they can be obtained by the tags property", "they can be obtained by the tags property",
function() { function() {
let tags = { "m.foo": { "order": 0.5 } }; const tags = { "m.foo": { "order": 0.5 } };
room.addTags(mkTags(roomId, tags)); room.addTags(mkTags(roomId, tags));
expect(room.tags).toEqual(tags); expect(room.tags).toEqual(tags);
}); });
@@ -1130,11 +1130,11 @@ describe("Room", function() {
it("should emit Room.tags event when new tags are " + it("should emit Room.tags event when new tags are " +
"received on the event stream", "received on the event stream",
function() { function() {
let listener = jasmine.createSpy('spy'); const listener = jasmine.createSpy('spy');
room.on("Room.tags", listener); room.on("Room.tags", listener);
let tags = { "m.foo": { "order": 0.5 } }; const tags = { "m.foo": { "order": 0.5 } };
let event = mkTags(roomId, tags); const event = mkTags(roomId, tags);
room.addTags(event); room.addTags(event);
expect(listener).toHaveBeenCalledWith(event, room); expect(listener).toHaveBeenCalledWith(event, room);
}); });
@@ -1147,27 +1147,27 @@ describe("Room", function() {
describe("addPendingEvent", function() { describe("addPendingEvent", function() {
it("should add pending events to the pendingEventList if " + it("should add pending events to the pendingEventList if " +
"pendingEventOrdering == 'detached'", function() { "pendingEventOrdering == 'detached'", function() {
let room = new Room(roomId, { const room = new Room(roomId, {
pendingEventOrdering: "detached", pendingEventOrdering: "detached",
}); });
let eventA = utils.mkMessage({ const eventA = utils.mkMessage({
room: roomId, user: userA, msg: "remote 1", event: true, room: roomId, user: userA, msg: "remote 1", event: true,
}); });
let eventB = utils.mkMessage({ const eventB = utils.mkMessage({
room: roomId, user: userA, msg: "local 1", event: true, room: roomId, user: userA, msg: "local 1", event: true,
}); });
eventB.status = EventStatus.SENDING; eventB.status = EventStatus.SENDING;
let eventC = utils.mkMessage({ const eventC = utils.mkMessage({
room: roomId, user: userA, msg: "remote 2", event: true, room: roomId, user: userA, msg: "remote 2", event: true,
}); });
room.addLiveEvents([eventA]); room.addLiveEvents([eventA]);
room.addPendingEvent(eventB, "TXN1"); room.addPendingEvent(eventB, "TXN1");
room.addLiveEvents([eventC]); room.addLiveEvents([eventC]);
expect(room.timeline).toEqual( expect(room.timeline).toEqual(
[eventA, eventC] [eventA, eventC],
); );
expect(room.getPendingEvents()).toEqual( expect(room.getPendingEvents()).toEqual(
[eventB] [eventB],
); );
}); });
@@ -1176,39 +1176,39 @@ describe("Room", function() {
room = new Room(roomId, { room = new Room(roomId, {
pendingEventOrdering: "chronological", pendingEventOrdering: "chronological",
}); });
let eventA = utils.mkMessage({ const eventA = utils.mkMessage({
room: roomId, user: userA, msg: "remote 1", event: true, room: roomId, user: userA, msg: "remote 1", event: true,
}); });
let eventB = utils.mkMessage({ const eventB = utils.mkMessage({
room: roomId, user: userA, msg: "local 1", event: true, room: roomId, user: userA, msg: "local 1", event: true,
}); });
eventB.status = EventStatus.SENDING; eventB.status = EventStatus.SENDING;
let eventC = utils.mkMessage({ const eventC = utils.mkMessage({
room: roomId, user: userA, msg: "remote 2", event: true, room: roomId, user: userA, msg: "remote 2", event: true,
}); });
room.addLiveEvents([eventA]); room.addLiveEvents([eventA]);
room.addPendingEvent(eventB, "TXN1"); room.addPendingEvent(eventB, "TXN1");
room.addLiveEvents([eventC]); room.addLiveEvents([eventC]);
expect(room.timeline).toEqual( expect(room.timeline).toEqual(
[eventA, eventB, eventC] [eventA, eventB, eventC],
); );
}); });
}); });
describe("updatePendingEvent", function() { describe("updatePendingEvent", function() {
it("should remove cancelled events from the pending list", function() { it("should remove cancelled events from the pending list", function() {
let room = new Room(roomId, { const room = new Room(roomId, {
pendingEventOrdering: "detached", pendingEventOrdering: "detached",
}); });
let eventA = utils.mkMessage({ const eventA = utils.mkMessage({
room: roomId, user: userA, event: true, room: roomId, user: userA, event: true,
}); });
eventA.status = EventStatus.SENDING; eventA.status = EventStatus.SENDING;
let eventId = eventA.getId(); const eventId = eventA.getId();
room.addPendingEvent(eventA, "TXN1"); room.addPendingEvent(eventA, "TXN1");
expect(room.getPendingEvents()).toEqual( expect(room.getPendingEvents()).toEqual(
[eventA] [eventA],
); );
// the event has to have been failed or queued before it can be // the event has to have been failed or queued before it can be
@@ -1233,16 +1233,16 @@ describe("Room", function() {
it("should remove cancelled events from the timeline", function() { it("should remove cancelled events from the timeline", function() {
let room = new Room(roomId); const room = new Room(roomId);
let eventA = utils.mkMessage({ const eventA = utils.mkMessage({
room: roomId, user: userA, event: true, room: roomId, user: userA, event: true,
}); });
eventA.status = EventStatus.SENDING; eventA.status = EventStatus.SENDING;
let eventId = eventA.getId(); const eventId = eventA.getId();
room.addPendingEvent(eventA, "TXN1"); room.addPendingEvent(eventA, "TXN1");
expect(room.getLiveTimeline().getEvents()).toEqual( expect(room.getLiveTimeline().getEvents()).toEqual(
[eventA] [eventA],
); );
// the event has to have been failed or queued before it can be // the event has to have been failed or queued before it can be

View File

@@ -1,21 +1,22 @@
// This file had a function whose name is all caps, which displeases eslint // This file had a function whose name is all caps, which displeases eslint
/* eslint new-cap: "off" */ /* eslint new-cap: "off" */
let q = require("q"); const q = require("q");
let sdk = require("../.."); const sdk = require("../..");
let MatrixScheduler = sdk.MatrixScheduler; const MatrixScheduler = sdk.MatrixScheduler;
let MatrixError = sdk.MatrixError; const MatrixError = sdk.MatrixError;
let utils = require("../test-utils"); const utils = require("../test-utils");
describe("MatrixScheduler", function() { describe("MatrixScheduler", function() {
let scheduler; let scheduler;
let retryFn, queueFn; let retryFn;
let queueFn;
let defer; let defer;
let roomId = "!foo:bar"; const roomId = "!foo:bar";
let eventA = utils.mkMessage({ const eventA = utils.mkMessage({
user: "@alice:bar", room: roomId, event: true, user: "@alice:bar", room: roomId, event: true,
}); });
let eventB = utils.mkMessage({ const eventB = utils.mkMessage({
user: "@alice:bar", room: roomId, event: true, user: "@alice:bar", room: roomId, event: true,
}); });
@@ -45,8 +46,8 @@ describe("MatrixScheduler", function() {
queueFn = function() { queueFn = function() {
return "one_big_queue"; return "one_big_queue";
}; };
let deferA = q.defer(); const deferA = q.defer();
let deferB = q.defer(); const deferB = q.defer();
let resolvedA = false; let resolvedA = false;
scheduler.setProcessFunction(function(event) { scheduler.setProcessFunction(function(event) {
if (resolvedA) { if (resolvedA) {
@@ -69,8 +70,8 @@ describe("MatrixScheduler", function() {
it("should invoke the retryFn on failure and wait the amount of time specified", it("should invoke the retryFn on failure and wait the amount of time specified",
function(done) { function(done) {
let waitTimeMs = 1500; const waitTimeMs = 1500;
let retryDefer = q.defer(); const retryDefer = q.defer();
retryFn = function() { retryFn = function() {
retryDefer.resolve(); retryDefer.resolve();
return waitTimeMs; return waitTimeMs;
@@ -115,8 +116,8 @@ describe("MatrixScheduler", function() {
return "yep"; return "yep";
}; };
let deferA = q.defer(); const deferA = q.defer();
let deferB = q.defer(); const deferB = q.defer();
let procCount = 0; let procCount = 0;
scheduler.setProcessFunction(function(ev) { scheduler.setProcessFunction(function(ev) {
procCount += 1; procCount += 1;
@@ -130,7 +131,7 @@ describe("MatrixScheduler", function() {
expect(procCount).toBeLessThan(3); expect(procCount).toBeLessThan(3);
}); });
let globalA = scheduler.queueEvent(eventA); const globalA = scheduler.queueEvent(eventA);
scheduler.queueEvent(eventB); scheduler.queueEvent(eventB);
expect(procCount).toEqual(1); expect(procCount).toEqual(1);
@@ -148,10 +149,10 @@ describe("MatrixScheduler", function() {
// Expect to have processFn invoked for A&B. // Expect to have processFn invoked for A&B.
// Resolve A. // Resolve A.
// Expect to have processFn invoked for D. // Expect to have processFn invoked for D.
let eventC = utils.mkMessage({user: "@a:bar", room: roomId, event: true}); const eventC = utils.mkMessage({user: "@a:bar", room: roomId, event: true});
let eventD = utils.mkMessage({user: "@b:bar", room: roomId, event: true}); const eventD = utils.mkMessage({user: "@b:bar", room: roomId, event: true});
let buckets = {}; const buckets = {};
buckets[eventA.getId()] = "queue_A"; buckets[eventA.getId()] = "queue_A";
buckets[eventD.getId()] = "queue_A"; buckets[eventD.getId()] = "queue_A";
buckets[eventB.getId()] = "queue_B"; buckets[eventB.getId()] = "queue_B";
@@ -164,12 +165,12 @@ describe("MatrixScheduler", function() {
return buckets[event.getId()]; return buckets[event.getId()];
}; };
let expectOrder = [ const expectOrder = [
eventA.getId(), eventB.getId(), eventD.getId(), eventA.getId(), eventB.getId(), eventD.getId(),
]; ];
let deferA = q.defer(); const deferA = q.defer();
scheduler.setProcessFunction(function(event) { scheduler.setProcessFunction(function(event) {
let id = expectOrder.shift(); const id = expectOrder.shift();
expect(id).toEqual(event.getId()); expect(id).toEqual(event.getId());
if (expectOrder.length === 0) { if (expectOrder.length === 0) {
done(); done();
@@ -200,7 +201,7 @@ describe("MatrixScheduler", function() {
queueFn = function() { queueFn = function() {
return "yep"; return "yep";
}; };
let prom = scheduler.queueEvent(eventA); const prom = scheduler.queueEvent(eventA);
expect(prom).toBeDefined(); expect(prom).toBeDefined();
expect(prom.then).toBeDefined(); expect(prom.then).toBeDefined();
}); });
@@ -228,15 +229,15 @@ describe("MatrixScheduler", function() {
}; };
scheduler.queueEvent(eventA); scheduler.queueEvent(eventA);
scheduler.queueEvent(eventB); scheduler.queueEvent(eventB);
let queue = scheduler.getQueueForEvent(eventA); const queue = scheduler.getQueueForEvent(eventA);
expect(queue.length).toEqual(2); expect(queue.length).toEqual(2);
expect(queue).toEqual([eventA, eventB]); expect(queue).toEqual([eventA, eventB]);
// modify the queue // modify the queue
let eventC = utils.mkMessage( const eventC = utils.mkMessage(
{user: "@a:bar", room: roomId, event: true} {user: "@a:bar", room: roomId, event: true},
); );
queue.push(eventC); queue.push(eventC);
let queueAgain = scheduler.getQueueForEvent(eventA); const queueAgain = scheduler.getQueueForEvent(eventA);
expect(queueAgain.length).toEqual(2); expect(queueAgain.length).toEqual(2);
}); });
@@ -247,9 +248,9 @@ describe("MatrixScheduler", function() {
}; };
scheduler.queueEvent(eventA); scheduler.queueEvent(eventA);
scheduler.queueEvent(eventB); scheduler.queueEvent(eventB);
let queue = scheduler.getQueueForEvent(eventA); const queue = scheduler.getQueueForEvent(eventA);
queue[1].event.content.body = "foo"; queue[1].event.content.body = "foo";
let queueAgain = scheduler.getQueueForEvent(eventA); const queueAgain = scheduler.getQueueForEvent(eventA);
expect(queueAgain[1].event.content.body).toEqual("foo"); expect(queueAgain[1].event.content.body).toEqual("foo");
}); });
}); });
@@ -312,40 +313,40 @@ describe("MatrixScheduler", function() {
expect(MatrixScheduler.QUEUE_MESSAGES( expect(MatrixScheduler.QUEUE_MESSAGES(
utils.mkMembership({ utils.mkMembership({
user: "@alice:bar", room: roomId, mship: "join", event: true, user: "@alice:bar", room: roomId, mship: "join", event: true,
}) }),
)).toEqual(null); )).toEqual(null);
}); });
}); });
describe("RETRY_BACKOFF_RATELIMIT", function() { describe("RETRY_BACKOFF_RATELIMIT", function() {
it("should wait at least the time given on M_LIMIT_EXCEEDED", function() { it("should wait at least the time given on M_LIMIT_EXCEEDED", function() {
let res = MatrixScheduler.RETRY_BACKOFF_RATELIMIT( const res = MatrixScheduler.RETRY_BACKOFF_RATELIMIT(
eventA, 1, new MatrixError({ eventA, 1, new MatrixError({
errcode: "M_LIMIT_EXCEEDED", retry_after_ms: 5000, errcode: "M_LIMIT_EXCEEDED", retry_after_ms: 5000,
}) }),
); );
expect(res >= 500).toBe(true, "Didn't wait long enough."); expect(res >= 500).toBe(true, "Didn't wait long enough.");
}); });
it("should give up after 5 attempts", function() { it("should give up after 5 attempts", function() {
let res = MatrixScheduler.RETRY_BACKOFF_RATELIMIT( const res = MatrixScheduler.RETRY_BACKOFF_RATELIMIT(
eventA, 5, {} eventA, 5, {},
); );
expect(res).toBe(-1, "Didn't give up."); expect(res).toBe(-1, "Didn't give up.");
}); });
it("should do exponential backoff", function() { it("should do exponential backoff", function() {
expect(MatrixScheduler.RETRY_BACKOFF_RATELIMIT( expect(MatrixScheduler.RETRY_BACKOFF_RATELIMIT(
eventA, 1, {} eventA, 1, {},
)).toEqual(2000); )).toEqual(2000);
expect(MatrixScheduler.RETRY_BACKOFF_RATELIMIT( expect(MatrixScheduler.RETRY_BACKOFF_RATELIMIT(
eventA, 2, {} eventA, 2, {},
)).toEqual(4000); )).toEqual(4000);
expect(MatrixScheduler.RETRY_BACKOFF_RATELIMIT( expect(MatrixScheduler.RETRY_BACKOFF_RATELIMIT(
eventA, 3, {} eventA, 3, {},
)).toEqual(8000); )).toEqual(8000);
expect(MatrixScheduler.RETRY_BACKOFF_RATELIMIT( expect(MatrixScheduler.RETRY_BACKOFF_RATELIMIT(
eventA, 4, {} eventA, 4, {},
)).toEqual(16000); )).toEqual(16000);
}); });
}); });

View File

@@ -1,14 +1,14 @@
"use strict"; "use strict";
let q = require("q"); const q = require("q");
let sdk = require("../.."); const sdk = require("../..");
let EventTimeline = sdk.EventTimeline; const EventTimeline = sdk.EventTimeline;
let TimelineWindow = sdk.TimelineWindow; const TimelineWindow = sdk.TimelineWindow;
let TimelineIndex = require("../../lib/timeline-window").TimelineIndex; const TimelineIndex = require("../../lib/timeline-window").TimelineIndex;
let utils = require("../test-utils"); const utils = require("../test-utils");
let ROOM_ID = "roomId"; const ROOM_ID = "roomId";
let USER_ID = "userId"; const USER_ID = "userId";
/* /*
* create a timeline with a bunch (default 3) events. * create a timeline with a bunch (default 3) events.
@@ -23,12 +23,12 @@ function createTimeline(numEvents, baseIndex) {
} }
// XXX: this is a horrid hack // XXX: this is a horrid hack
let timelineSet = { room: { roomId: ROOM_ID }}; const timelineSet = { room: { roomId: ROOM_ID }};
timelineSet.room.getUnfilteredTimelineSet = function() { timelineSet.room.getUnfilteredTimelineSet = function() {
return timelineSet; return timelineSet;
}; };
let timeline = new EventTimeline(timelineSet); const timeline = new EventTimeline(timelineSet);
// add the events after the baseIndex first // add the events after the baseIndex first
addEventsToTimeline(timeline, numEvents - baseIndex, false); addEventsToTimeline(timeline, numEvents - baseIndex, false);
@@ -46,7 +46,7 @@ function addEventsToTimeline(timeline, numEvents, atStart) {
utils.mkMessage({ utils.mkMessage({
room: ROOM_ID, user: USER_ID, room: ROOM_ID, user: USER_ID,
event: true, event: true,
}), atStart }), atStart,
); );
} }
} }
@@ -56,8 +56,8 @@ function addEventsToTimeline(timeline, numEvents, atStart) {
* create a pair of linked timelines * create a pair of linked timelines
*/ */
function createLinkedTimelines() { function createLinkedTimelines() {
let tl1 = createTimeline(); const tl1 = createTimeline();
let tl2 = createTimeline(); const tl2 = createTimeline();
tl1.setNeighbouringTimeline(tl2, EventTimeline.FORWARDS); tl1.setNeighbouringTimeline(tl2, EventTimeline.FORWARDS);
tl2.setNeighbouringTimeline(tl1, EventTimeline.BACKWARDS); tl2.setNeighbouringTimeline(tl1, EventTimeline.BACKWARDS);
return [tl1, tl2]; return [tl1, tl2];
@@ -71,41 +71,42 @@ describe("TimelineIndex", function() {
describe("minIndex", function() { describe("minIndex", function() {
it("should return the min index relative to BaseIndex", function() { it("should return the min index relative to BaseIndex", function() {
let timelineIndex = new TimelineIndex(createTimeline(), 0); const timelineIndex = new TimelineIndex(createTimeline(), 0);
expect(timelineIndex.minIndex()).toEqual(-1); expect(timelineIndex.minIndex()).toEqual(-1);
}); });
}); });
describe("maxIndex", function() { describe("maxIndex", function() {
it("should return the max index relative to BaseIndex", function() { it("should return the max index relative to BaseIndex", function() {
let timelineIndex = new TimelineIndex(createTimeline(), 0); const timelineIndex = new TimelineIndex(createTimeline(), 0);
expect(timelineIndex.maxIndex()).toEqual(2); expect(timelineIndex.maxIndex()).toEqual(2);
}); });
}); });
describe("advance", function() { describe("advance", function() {
it("should advance up to the end of the timeline", function() { it("should advance up to the end of the timeline", function() {
let timelineIndex = new TimelineIndex(createTimeline(), 0); const timelineIndex = new TimelineIndex(createTimeline(), 0);
let result = timelineIndex.advance(3); const result = timelineIndex.advance(3);
expect(result).toEqual(2); expect(result).toEqual(2);
expect(timelineIndex.index).toEqual(2); expect(timelineIndex.index).toEqual(2);
}); });
it("should retreat back to the start of the timeline", function() { it("should retreat back to the start of the timeline", function() {
let timelineIndex = new TimelineIndex(createTimeline(), 0); const timelineIndex = new TimelineIndex(createTimeline(), 0);
let result = timelineIndex.advance(-2); const result = timelineIndex.advance(-2);
expect(result).toEqual(-1); expect(result).toEqual(-1);
expect(timelineIndex.index).toEqual(-1); expect(timelineIndex.index).toEqual(-1);
}); });
it("should advance into the next timeline", function() { it("should advance into the next timeline", function() {
let timelines = createLinkedTimelines(); const timelines = createLinkedTimelines();
let tl1 = timelines[0], tl2 = timelines[1]; const tl1 = timelines[0];
const tl2 = timelines[1];
// initialise the index pointing at the end of the first timeline // initialise the index pointing at the end of the first timeline
let timelineIndex = new TimelineIndex(tl1, 2); const timelineIndex = new TimelineIndex(tl1, 2);
let result = timelineIndex.advance(1); const result = timelineIndex.advance(1);
expect(result).toEqual(1); expect(result).toEqual(1);
expect(timelineIndex.timeline).toBe(tl2); expect(timelineIndex.timeline).toBe(tl2);
@@ -116,14 +117,15 @@ describe("TimelineIndex", function() {
}); });
it("should retreat into the previous timeline", function() { it("should retreat into the previous timeline", function() {
let timelines = createLinkedTimelines(); const timelines = createLinkedTimelines();
let tl1 = timelines[0], tl2 = timelines[1]; const tl1 = timelines[0];
const tl2 = timelines[1];
// initialise the index pointing at the start of the second // initialise the index pointing at the start of the second
// timeline // timeline
let timelineIndex = new TimelineIndex(tl2, -1); const timelineIndex = new TimelineIndex(tl2, -1);
let result = timelineIndex.advance(-1); const result = timelineIndex.advance(-1);
expect(result).toEqual(-1); expect(result).toEqual(-1);
expect(timelineIndex.timeline).toBe(tl1); expect(timelineIndex.timeline).toBe(tl1);
expect(timelineIndex.index).toEqual(1); expect(timelineIndex.index).toEqual(1);
@@ -132,8 +134,8 @@ describe("TimelineIndex", function() {
describe("retreat", function() { describe("retreat", function() {
it("should retreat up to the start of the timeline", function() { it("should retreat up to the start of the timeline", function() {
let timelineIndex = new TimelineIndex(createTimeline(), 0); const timelineIndex = new TimelineIndex(createTimeline(), 0);
let result = timelineIndex.retreat(2); const result = timelineIndex.retreat(2);
expect(result).toEqual(1); expect(result).toEqual(1);
expect(timelineIndex.index).toEqual(-1); expect(timelineIndex.index).toEqual(-1);
}); });
@@ -146,7 +148,8 @@ describe("TimelineWindow", function() {
* create a dummy eventTimelineSet and client, and a TimelineWindow * create a dummy eventTimelineSet and client, and a TimelineWindow
* attached to them. * attached to them.
*/ */
let timelineSet, client; let timelineSet;
let client;
function createWindow(timeline, opts) { function createWindow(timeline, opts) {
timelineSet = {}; timelineSet = {};
client = {}; client = {};
@@ -164,50 +167,50 @@ describe("TimelineWindow", function() {
describe("load", function() { describe("load", function() {
it("should initialise from the live timeline", function(done) { it("should initialise from the live timeline", function(done) {
let liveTimeline = createTimeline(); const liveTimeline = createTimeline();
let room = {}; const room = {};
room.getLiveTimeline = function() { room.getLiveTimeline = function() {
return liveTimeline; return liveTimeline;
}; };
let timelineWindow = new TimelineWindow(undefined, room); const timelineWindow = new TimelineWindow(undefined, room);
timelineWindow.load(undefined, 2).then(function() { timelineWindow.load(undefined, 2).then(function() {
let expectedEvents = liveTimeline.getEvents().slice(1); const expectedEvents = liveTimeline.getEvents().slice(1);
expect(timelineWindow.getEvents()).toEqual(expectedEvents); expect(timelineWindow.getEvents()).toEqual(expectedEvents);
}).catch(utils.failTest).done(done); }).catch(utils.failTest).done(done);
}); });
it("should initialise from a specific event", function(done) { it("should initialise from a specific event", function(done) {
let timeline = createTimeline(); const timeline = createTimeline();
let eventId = timeline.getEvents()[1].getId(); const eventId = timeline.getEvents()[1].getId();
let timelineSet = {}; const timelineSet = {};
let client = {}; const client = {};
client.getEventTimeline = function(timelineSet0, eventId0) { client.getEventTimeline = function(timelineSet0, eventId0) {
expect(timelineSet0).toBe(timelineSet); expect(timelineSet0).toBe(timelineSet);
expect(eventId0).toEqual(eventId); expect(eventId0).toEqual(eventId);
return q(timeline); return q(timeline);
}; };
let timelineWindow = new TimelineWindow(client, timelineSet); const timelineWindow = new TimelineWindow(client, timelineSet);
timelineWindow.load(eventId, 3).then(function() { timelineWindow.load(eventId, 3).then(function() {
let expectedEvents = timeline.getEvents(); const expectedEvents = timeline.getEvents();
expect(timelineWindow.getEvents()).toEqual(expectedEvents); expect(timelineWindow.getEvents()).toEqual(expectedEvents);
}).catch(utils.failTest).done(done); }).catch(utils.failTest).done(done);
}); });
it("canPaginate should return false until load has returned", it("canPaginate should return false until load has returned",
function(done) { function(done) {
let timeline = createTimeline(); const timeline = createTimeline();
timeline.setPaginationToken("toktok1", EventTimeline.BACKWARDS); timeline.setPaginationToken("toktok1", EventTimeline.BACKWARDS);
timeline.setPaginationToken("toktok2", EventTimeline.FORWARDS); timeline.setPaginationToken("toktok2", EventTimeline.FORWARDS);
let eventId = timeline.getEvents()[1].getId(); const eventId = timeline.getEvents()[1].getId();
let timelineSet = {}; const timelineSet = {};
let client = {}; const client = {};
let timelineWindow = new TimelineWindow(client, timelineSet); const timelineWindow = new TimelineWindow(client, timelineSet);
client.getEventTimeline = function(timelineSet0, eventId0) { client.getEventTimeline = function(timelineSet0, eventId0) {
expect(timelineWindow.canPaginate(EventTimeline.BACKWARDS)) expect(timelineWindow.canPaginate(EventTimeline.BACKWARDS))
@@ -218,7 +221,7 @@ describe("TimelineWindow", function() {
}; };
timelineWindow.load(eventId, 3).then(function() { timelineWindow.load(eventId, 3).then(function() {
let expectedEvents = timeline.getEvents(); const expectedEvents = timeline.getEvents();
expect(timelineWindow.getEvents()).toEqual(expectedEvents); expect(timelineWindow.getEvents()).toEqual(expectedEvents);
expect(timelineWindow.canPaginate(EventTimeline.BACKWARDS)) expect(timelineWindow.canPaginate(EventTimeline.BACKWARDS))
.toBe(true); .toBe(true);
@@ -231,12 +234,12 @@ describe("TimelineWindow", function() {
describe("pagination", function() { describe("pagination", function() {
it("should be able to advance across the initial timeline", it("should be able to advance across the initial timeline",
function(done) { function(done) {
let timeline = createTimeline(); const timeline = createTimeline();
let eventId = timeline.getEvents()[1].getId(); const eventId = timeline.getEvents()[1].getId();
let timelineWindow = createWindow(timeline); const timelineWindow = createWindow(timeline);
timelineWindow.load(eventId, 1).then(function() { timelineWindow.load(eventId, 1).then(function() {
let expectedEvents = [timeline.getEvents()[1]]; const expectedEvents = [timeline.getEvents()[1]];
expect(timelineWindow.getEvents()).toEqual(expectedEvents); expect(timelineWindow.getEvents()).toEqual(expectedEvents);
expect(timelineWindow.canPaginate(EventTimeline.BACKWARDS)) expect(timelineWindow.canPaginate(EventTimeline.BACKWARDS))
@@ -247,7 +250,7 @@ describe("TimelineWindow", function() {
return timelineWindow.paginate(EventTimeline.FORWARDS, 2); return timelineWindow.paginate(EventTimeline.FORWARDS, 2);
}).then(function(success) { }).then(function(success) {
expect(success).toBe(true); expect(success).toBe(true);
let expectedEvents = timeline.getEvents().slice(1); const expectedEvents = timeline.getEvents().slice(1);
expect(timelineWindow.getEvents()).toEqual(expectedEvents); expect(timelineWindow.getEvents()).toEqual(expectedEvents);
expect(timelineWindow.canPaginate(EventTimeline.BACKWARDS)) expect(timelineWindow.canPaginate(EventTimeline.BACKWARDS))
@@ -262,7 +265,7 @@ describe("TimelineWindow", function() {
return timelineWindow.paginate(EventTimeline.BACKWARDS, 2); return timelineWindow.paginate(EventTimeline.BACKWARDS, 2);
}).then(function(success) { }).then(function(success) {
expect(success).toBe(true); expect(success).toBe(true);
let expectedEvents = timeline.getEvents(); const expectedEvents = timeline.getEvents();
expect(timelineWindow.getEvents()).toEqual(expectedEvents); expect(timelineWindow.getEvents()).toEqual(expectedEvents);
expect(timelineWindow.canPaginate(EventTimeline.BACKWARDS)) expect(timelineWindow.canPaginate(EventTimeline.BACKWARDS))
@@ -276,12 +279,12 @@ describe("TimelineWindow", function() {
}); });
it("should advance into next timeline", function(done) { it("should advance into next timeline", function(done) {
let tls = createLinkedTimelines(); const tls = createLinkedTimelines();
let eventId = tls[0].getEvents()[1].getId(); const eventId = tls[0].getEvents()[1].getId();
let timelineWindow = createWindow(tls[0], {windowLimit: 5}); const timelineWindow = createWindow(tls[0], {windowLimit: 5});
timelineWindow.load(eventId, 3).then(function() { timelineWindow.load(eventId, 3).then(function() {
let expectedEvents = tls[0].getEvents(); const expectedEvents = tls[0].getEvents();
expect(timelineWindow.getEvents()).toEqual(expectedEvents); expect(timelineWindow.getEvents()).toEqual(expectedEvents);
expect(timelineWindow.canPaginate(EventTimeline.BACKWARDS)) expect(timelineWindow.canPaginate(EventTimeline.BACKWARDS))
@@ -292,7 +295,7 @@ describe("TimelineWindow", function() {
return timelineWindow.paginate(EventTimeline.FORWARDS, 2); return timelineWindow.paginate(EventTimeline.FORWARDS, 2);
}).then(function(success) { }).then(function(success) {
expect(success).toBe(true); expect(success).toBe(true);
let expectedEvents = tls[0].getEvents() const expectedEvents = tls[0].getEvents()
.concat(tls[1].getEvents().slice(0, 2)); .concat(tls[1].getEvents().slice(0, 2));
expect(timelineWindow.getEvents()).toEqual(expectedEvents); expect(timelineWindow.getEvents()).toEqual(expectedEvents);
@@ -306,7 +309,7 @@ describe("TimelineWindow", function() {
expect(success).toBe(true); expect(success).toBe(true);
// the windowLimit should have made us drop an event from // the windowLimit should have made us drop an event from
// tls[0] // tls[0]
let expectedEvents = tls[0].getEvents().slice(1) const expectedEvents = tls[0].getEvents().slice(1)
.concat(tls[1].getEvents()); .concat(tls[1].getEvents());
expect(timelineWindow.getEvents()).toEqual(expectedEvents); expect(timelineWindow.getEvents()).toEqual(expectedEvents);
@@ -321,12 +324,12 @@ describe("TimelineWindow", function() {
}); });
it("should retreat into previous timeline", function(done) { it("should retreat into previous timeline", function(done) {
let tls = createLinkedTimelines(); const tls = createLinkedTimelines();
let eventId = tls[1].getEvents()[1].getId(); const eventId = tls[1].getEvents()[1].getId();
let timelineWindow = createWindow(tls[1], {windowLimit: 5}); const timelineWindow = createWindow(tls[1], {windowLimit: 5});
timelineWindow.load(eventId, 3).then(function() { timelineWindow.load(eventId, 3).then(function() {
let expectedEvents = tls[1].getEvents(); const expectedEvents = tls[1].getEvents();
expect(timelineWindow.getEvents()).toEqual(expectedEvents); expect(timelineWindow.getEvents()).toEqual(expectedEvents);
expect(timelineWindow.canPaginate(EventTimeline.BACKWARDS)) expect(timelineWindow.canPaginate(EventTimeline.BACKWARDS))
@@ -337,7 +340,7 @@ describe("TimelineWindow", function() {
return timelineWindow.paginate(EventTimeline.BACKWARDS, 2); return timelineWindow.paginate(EventTimeline.BACKWARDS, 2);
}).then(function(success) { }).then(function(success) {
expect(success).toBe(true); expect(success).toBe(true);
let expectedEvents = tls[0].getEvents().slice(1, 3) const expectedEvents = tls[0].getEvents().slice(1, 3)
.concat(tls[1].getEvents()); .concat(tls[1].getEvents());
expect(timelineWindow.getEvents()).toEqual(expectedEvents); expect(timelineWindow.getEvents()).toEqual(expectedEvents);
@@ -351,7 +354,7 @@ describe("TimelineWindow", function() {
expect(success).toBe(true); expect(success).toBe(true);
// the windowLimit should have made us drop an event from // the windowLimit should have made us drop an event from
// tls[1] // tls[1]
let expectedEvents = tls[0].getEvents() const expectedEvents = tls[0].getEvents()
.concat(tls[1].getEvents().slice(0, 2)); .concat(tls[1].getEvents().slice(0, 2));
expect(timelineWindow.getEvents()).toEqual(expectedEvents); expect(timelineWindow.getEvents()).toEqual(expectedEvents);
@@ -366,11 +369,11 @@ describe("TimelineWindow", function() {
}); });
it("should make forward pagination requests", function(done) { it("should make forward pagination requests", function(done) {
let timeline = createTimeline(); const timeline = createTimeline();
timeline.setPaginationToken("toktok", EventTimeline.FORWARDS); timeline.setPaginationToken("toktok", EventTimeline.FORWARDS);
let timelineWindow = createWindow(timeline, {windowLimit: 5}); const timelineWindow = createWindow(timeline, {windowLimit: 5});
let eventId = timeline.getEvents()[1].getId(); const eventId = timeline.getEvents()[1].getId();
client.paginateEventTimeline = function(timeline0, opts) { client.paginateEventTimeline = function(timeline0, opts) {
expect(timeline0).toBe(timeline); expect(timeline0).toBe(timeline);
@@ -382,7 +385,7 @@ describe("TimelineWindow", function() {
}; };
timelineWindow.load(eventId, 3).then(function() { timelineWindow.load(eventId, 3).then(function() {
let expectedEvents = timeline.getEvents(); const expectedEvents = timeline.getEvents();
expect(timelineWindow.getEvents()).toEqual(expectedEvents); expect(timelineWindow.getEvents()).toEqual(expectedEvents);
expect(timelineWindow.canPaginate(EventTimeline.BACKWARDS)) expect(timelineWindow.canPaginate(EventTimeline.BACKWARDS))
@@ -392,18 +395,18 @@ describe("TimelineWindow", function() {
return timelineWindow.paginate(EventTimeline.FORWARDS, 2); return timelineWindow.paginate(EventTimeline.FORWARDS, 2);
}).then(function(success) { }).then(function(success) {
expect(success).toBe(true); expect(success).toBe(true);
let expectedEvents = timeline.getEvents().slice(0, 5); const expectedEvents = timeline.getEvents().slice(0, 5);
expect(timelineWindow.getEvents()).toEqual(expectedEvents); expect(timelineWindow.getEvents()).toEqual(expectedEvents);
}).catch(utils.failTest).done(done); }).catch(utils.failTest).done(done);
}); });
it("should make backward pagination requests", function(done) { it("should make backward pagination requests", function(done) {
let timeline = createTimeline(); const timeline = createTimeline();
timeline.setPaginationToken("toktok", EventTimeline.BACKWARDS); timeline.setPaginationToken("toktok", EventTimeline.BACKWARDS);
let timelineWindow = createWindow(timeline, {windowLimit: 5}); const timelineWindow = createWindow(timeline, {windowLimit: 5});
let eventId = timeline.getEvents()[1].getId(); const eventId = timeline.getEvents()[1].getId();
client.paginateEventTimeline = function(timeline0, opts) { client.paginateEventTimeline = function(timeline0, opts) {
expect(timeline0).toBe(timeline); expect(timeline0).toBe(timeline);
@@ -415,7 +418,7 @@ describe("TimelineWindow", function() {
}; };
timelineWindow.load(eventId, 3).then(function() { timelineWindow.load(eventId, 3).then(function() {
let expectedEvents = timeline.getEvents(); const expectedEvents = timeline.getEvents();
expect(timelineWindow.getEvents()).toEqual(expectedEvents); expect(timelineWindow.getEvents()).toEqual(expectedEvents);
expect(timelineWindow.canPaginate(EventTimeline.BACKWARDS)) expect(timelineWindow.canPaginate(EventTimeline.BACKWARDS))
@@ -425,18 +428,18 @@ describe("TimelineWindow", function() {
return timelineWindow.paginate(EventTimeline.BACKWARDS, 2); return timelineWindow.paginate(EventTimeline.BACKWARDS, 2);
}).then(function(success) { }).then(function(success) {
expect(success).toBe(true); expect(success).toBe(true);
let expectedEvents = timeline.getEvents().slice(1, 6); const expectedEvents = timeline.getEvents().slice(1, 6);
expect(timelineWindow.getEvents()).toEqual(expectedEvents); expect(timelineWindow.getEvents()).toEqual(expectedEvents);
}).catch(utils.failTest).done(done); }).catch(utils.failTest).done(done);
}); });
it("should limit the number of unsuccessful pagination requests", it("should limit the number of unsuccessful pagination requests",
function(done) { function(done) {
let timeline = createTimeline(); const timeline = createTimeline();
timeline.setPaginationToken("toktok", EventTimeline.FORWARDS); timeline.setPaginationToken("toktok", EventTimeline.FORWARDS);
let timelineWindow = createWindow(timeline, {windowLimit: 5}); const timelineWindow = createWindow(timeline, {windowLimit: 5});
let eventId = timeline.getEvents()[1].getId(); const eventId = timeline.getEvents()[1].getId();
let paginateCount = 0; let paginateCount = 0;
client.paginateEventTimeline = function(timeline0, opts) { client.paginateEventTimeline = function(timeline0, opts) {
@@ -448,7 +451,7 @@ describe("TimelineWindow", function() {
}; };
timelineWindow.load(eventId, 3).then(function() { timelineWindow.load(eventId, 3).then(function() {
let expectedEvents = timeline.getEvents(); const expectedEvents = timeline.getEvents();
expect(timelineWindow.getEvents()).toEqual(expectedEvents); expect(timelineWindow.getEvents()).toEqual(expectedEvents);
expect(timelineWindow.canPaginate(EventTimeline.BACKWARDS)) expect(timelineWindow.canPaginate(EventTimeline.BACKWARDS))
@@ -459,7 +462,7 @@ describe("TimelineWindow", function() {
}).then(function(success) { }).then(function(success) {
expect(success).toBe(false); expect(success).toBe(false);
expect(paginateCount).toEqual(3); expect(paginateCount).toEqual(3);
let expectedEvents = timeline.getEvents().slice(0, 3); const expectedEvents = timeline.getEvents().slice(0, 3);
expect(timelineWindow.getEvents()).toEqual(expectedEvents); expect(timelineWindow.getEvents()).toEqual(expectedEvents);
expect(timelineWindow.canPaginate(EventTimeline.BACKWARDS)) expect(timelineWindow.canPaginate(EventTimeline.BACKWARDS))

View File

@@ -1,10 +1,10 @@
"use strict"; "use strict";
let sdk = require("../.."); const sdk = require("../..");
let User = sdk.User; const User = sdk.User;
let utils = require("../test-utils"); const utils = require("../test-utils");
describe("User", function() { describe("User", function() {
let userId = "@alice:bar"; const userId = "@alice:bar";
let user; let user;
beforeEach(function() { beforeEach(function() {
@@ -13,7 +13,7 @@ describe("User", function() {
}); });
describe("setPresenceEvent", function() { describe("setPresenceEvent", function() {
let event = utils.mkEvent({ const event = utils.mkEvent({
type: "m.presence", content: { type: "m.presence", content: {
presence: "online", presence: "online",
user_id: userId, user_id: userId,

View File

@@ -1,6 +1,6 @@
"use strict"; "use strict";
let utils = require("../../lib/utils"); const utils = require("../../lib/utils");
let testUtils = require("../test-utils"); const testUtils = require("../test-utils");
describe("utils", function() { describe("utils", function() {
beforeEach(function() { beforeEach(function() {
@@ -9,32 +9,32 @@ describe("utils", function() {
describe("encodeParams", function() { describe("encodeParams", function() {
it("should url encode and concat with &s", function() { it("should url encode and concat with &s", function() {
let params = { const params = {
foo: "bar", foo: "bar",
baz: "beer@", baz: "beer@",
}; };
expect(utils.encodeParams(params)).toEqual( expect(utils.encodeParams(params)).toEqual(
"foo=bar&baz=beer%40" "foo=bar&baz=beer%40",
); );
}); });
}); });
describe("encodeUri", function() { describe("encodeUri", function() {
it("should replace based on object keys and url encode", function() { it("should replace based on object keys and url encode", function() {
let path = "foo/bar/%something/%here"; const path = "foo/bar/%something/%here";
let vals = { const vals = {
"%something": "baz", "%something": "baz",
"%here": "beer@", "%here": "beer@",
}; };
expect(utils.encodeUri(path, vals)).toEqual( expect(utils.encodeUri(path, vals)).toEqual(
"foo/bar/baz/beer%40" "foo/bar/baz/beer%40",
); );
}); });
}); });
describe("forEach", function() { describe("forEach", function() {
it("should be invoked for each element", function() { it("should be invoked for each element", function() {
let arr = []; const arr = [];
utils.forEach([55, 66, 77], function(element) { utils.forEach([55, 66, 77], function(element) {
arr.push(element); arr.push(element);
}); });
@@ -44,50 +44,50 @@ describe("utils", function() {
describe("findElement", function() { describe("findElement", function() {
it("should find only 1 element if there is a match", function() { it("should find only 1 element if there is a match", function() {
let matchFn = function() { const matchFn = function() {
return true; return true;
}; };
let arr = [55, 66, 77]; const arr = [55, 66, 77];
expect(utils.findElement(arr, matchFn)).toEqual(55); expect(utils.findElement(arr, matchFn)).toEqual(55);
}); });
it("should be able to find in reverse order", function() { it("should be able to find in reverse order", function() {
let matchFn = function() { const matchFn = function() {
return true; return true;
}; };
let arr = [55, 66, 77]; const arr = [55, 66, 77];
expect(utils.findElement(arr, matchFn, true)).toEqual(77); expect(utils.findElement(arr, matchFn, true)).toEqual(77);
}); });
it("should find nothing if the function never returns true", function() { it("should find nothing if the function never returns true", function() {
let matchFn = function() { const matchFn = function() {
return false; return false;
}; };
let arr = [55, 66, 77]; const arr = [55, 66, 77];
expect(utils.findElement(arr, matchFn)).toBeFalsy(); expect(utils.findElement(arr, matchFn)).toBeFalsy();
}); });
}); });
describe("removeElement", function() { describe("removeElement", function() {
it("should remove only 1 element if there is a match", function() { it("should remove only 1 element if there is a match", function() {
let matchFn = function() { const matchFn = function() {
return true; return true;
}; };
let arr = [55, 66, 77]; const arr = [55, 66, 77];
utils.removeElement(arr, matchFn); utils.removeElement(arr, matchFn);
expect(arr).toEqual([66, 77]); expect(arr).toEqual([66, 77]);
}); });
it("should be able to remove in reverse order", function() { it("should be able to remove in reverse order", function() {
let matchFn = function() { const matchFn = function() {
return true; return true;
}; };
let arr = [55, 66, 77]; const arr = [55, 66, 77];
utils.removeElement(arr, matchFn, true); utils.removeElement(arr, matchFn, true);
expect(arr).toEqual([55, 66]); expect(arr).toEqual([55, 66]);
}); });
it("should remove nothing if the function never returns true", function() { it("should remove nothing if the function never returns true", function() {
let matchFn = function() { const matchFn = function() {
return false; return false;
}; };
let arr = [55, 66, 77]; const arr = [55, 66, 77];
utils.removeElement(arr, matchFn); utils.removeElement(arr, matchFn);
expect(arr).toEqual(arr); expect(arr).toEqual(arr);
}); });
@@ -104,7 +104,7 @@ describe("utils", function() {
expect(utils.isFunction(555)).toBe(false); expect(utils.isFunction(555)).toBe(false);
expect(utils.isFunction(function() {})).toBe(true); expect(utils.isFunction(function() {})).toBe(true);
let s = { foo: function() {} }; const s = { foo: function() {} };
expect(utils.isFunction(s.foo)).toBe(true); expect(utils.isFunction(s.foo)).toBe(true);
}); });
}); });
@@ -154,7 +154,7 @@ describe("utils", function() {
}); });
describe("deepCompare", function() { describe("deepCompare", function() {
let assert = { const assert = {
isTrue: function(x) { isTrue: function(x) {
expect(x).toBe(true); expect(x).toBe(true);
}, },
@@ -174,7 +174,7 @@ describe("utils", function() {
it("should handle regexps", function() { it("should handle regexps", function() {
assert.isTrue(utils.deepCompare(/abc/, /abc/)); assert.isTrue(utils.deepCompare(/abc/, /abc/));
assert.isFalse(utils.deepCompare(/abc/, /123/)); assert.isFalse(utils.deepCompare(/abc/, /123/));
let r = /abc/; const r = /abc/;
assert.isTrue(utils.deepCompare(r, r)); assert.isTrue(utils.deepCompare(r, r));
}); });
@@ -216,10 +216,10 @@ describe("utils", function() {
// no two different function is equal really, they capture their // no two different function is equal really, they capture their
// context variables so even if they have same toString(), they // context variables so even if they have same toString(), they
// won't have same functionality // won't have same functionality
let func = function(x) { const func = function(x) {
return true; return true;
}; };
let func2 = function(x) { const func2 = function(x) {
return true; return true;
}; };
assert.isTrue(utils.deepCompare(func, func)); assert.isTrue(utils.deepCompare(func, func));
@@ -231,44 +231,44 @@ describe("utils", function() {
describe("extend", function() { describe("extend", function() {
let SOURCE = { "prop2": 1, "string2": "x", "newprop": "new" }; const SOURCE = { "prop2": 1, "string2": "x", "newprop": "new" };
it("should extend", function() { it("should extend", function() {
let target = { const target = {
"prop1": 5, "prop2": 7, "string1": "baz", "string2": "foo", "prop1": 5, "prop2": 7, "string1": "baz", "string2": "foo",
}; };
let merged = { const merged = {
"prop1": 5, "prop2": 1, "string1": "baz", "string2": "x", "prop1": 5, "prop2": 1, "string1": "baz", "string2": "x",
"newprop": "new", "newprop": "new",
}; };
let source_orig = JSON.stringify(SOURCE); const sourceOrig = JSON.stringify(SOURCE);
utils.extend(target, SOURCE); utils.extend(target, SOURCE);
expect(JSON.stringify(target)).toEqual(JSON.stringify(merged)); expect(JSON.stringify(target)).toEqual(JSON.stringify(merged));
// check the originial wasn't modified // check the originial wasn't modified
expect(JSON.stringify(SOURCE)).toEqual(source_orig); expect(JSON.stringify(SOURCE)).toEqual(sourceOrig);
}); });
it("should ignore null", function() { it("should ignore null", function() {
let target = { const target = {
"prop1": 5, "prop2": 7, "string1": "baz", "string2": "foo", "prop1": 5, "prop2": 7, "string1": "baz", "string2": "foo",
}; };
let merged = { const merged = {
"prop1": 5, "prop2": 1, "string1": "baz", "string2": "x", "prop1": 5, "prop2": 1, "string1": "baz", "string2": "x",
"newprop": "new", "newprop": "new",
}; };
let source_orig = JSON.stringify(SOURCE); const sourceOrig = JSON.stringify(SOURCE);
utils.extend(target, null, SOURCE); utils.extend(target, null, SOURCE);
expect(JSON.stringify(target)).toEqual(JSON.stringify(merged)); expect(JSON.stringify(target)).toEqual(JSON.stringify(merged));
// check the originial wasn't modified // check the originial wasn't modified
expect(JSON.stringify(SOURCE)).toEqual(source_orig); expect(JSON.stringify(SOURCE)).toEqual(sourceOrig);
}); });
it("should handle properties created with defineProperties", function() { it("should handle properties created with defineProperties", function() {
let source = Object.defineProperties({}, { const source = Object.defineProperties({}, {
"enumerableProp": { "enumerableProp": {
get: function() { get: function() {
return true; return true;
@@ -282,7 +282,7 @@ describe("utils", function() {
}, },
}); });
let target = {}; const target = {};
utils.extend(target, source); utils.extend(target, source);
expect(target.enumerableProp).toBe(true); expect(target.enumerableProp).toBe(true);
expect(target.nonenumerableProp).toBe(undefined); expect(target.nonenumerableProp).toBe(undefined);

View File

@@ -22,8 +22,8 @@ limitations under the License.
* @module base-apis * @module base-apis
*/ */
let httpApi = require("./http-api"); const httpApi = require("./http-api");
let utils = require("./utils"); const utils = require("./utils");
/** /**
* Low-level wrappers for the Matrix APIs * Low-level wrappers for the Matrix APIs
@@ -60,7 +60,7 @@ function MatrixBaseApis(opts) {
this.baseUrl = opts.baseUrl; this.baseUrl = opts.baseUrl;
this.idBaseUrl = opts.idBaseUrl; this.idBaseUrl = opts.idBaseUrl;
let httpOpts = { const httpOpts = {
baseUrl: opts.baseUrl, baseUrl: opts.baseUrl,
idBaseUrl: opts.idBaseUrl, idBaseUrl: opts.idBaseUrl,
accessToken: opts.accessToken, accessToken: opts.accessToken,
@@ -133,7 +133,7 @@ MatrixBaseApis.prototype.makeTxnId = function() {
MatrixBaseApis.prototype.register = function( MatrixBaseApis.prototype.register = function(
username, password, username, password,
sessionId, auth, bindEmail, guestAccessToken, sessionId, auth, bindEmail, guestAccessToken,
callback callback,
) { ) {
if (auth === undefined) { if (auth === undefined) {
auth = {}; auth = {};
@@ -142,7 +142,7 @@ MatrixBaseApis.prototype.register = function(
auth.session = sessionId; auth.session = sessionId;
} }
let params = { const params = {
auth: auth, auth: auth,
}; };
if (username !== undefined && username !== null) { if (username !== undefined && username !== null) {
@@ -183,13 +183,13 @@ MatrixBaseApis.prototype.registerGuest = function(opts, callback) {
* @return {module:http-api.MatrixError} Rejects: with an error response. * @return {module:http-api.MatrixError} Rejects: with an error response.
*/ */
MatrixBaseApis.prototype.registerRequest = function(data, kind, callback) { MatrixBaseApis.prototype.registerRequest = function(data, kind, callback) {
let params = {}; const params = {};
if (kind) { if (kind) {
params.kind = kind; params.kind = kind;
} }
return this._http.request( return this._http.request(
callback, "POST", "/register", params, data callback, "POST", "/register", params, data,
); );
}; };
@@ -210,7 +210,7 @@ MatrixBaseApis.prototype.loginFlows = function(callback) {
* @return {module:http-api.MatrixError} Rejects: with an error response. * @return {module:http-api.MatrixError} Rejects: with an error response.
*/ */
MatrixBaseApis.prototype.login = function(loginType, data, callback) { MatrixBaseApis.prototype.login = function(loginType, data, callback) {
let login_data = { const login_data = {
type: loginType, type: loginType,
}; };
@@ -218,7 +218,7 @@ MatrixBaseApis.prototype.login = function(loginType, data, callback) {
utils.extend(login_data, data); utils.extend(login_data, data);
return this._http.authedRequest( return this._http.authedRequest(
callback, "POST", "/login", undefined, login_data callback, "POST", "/login", undefined, login_data,
); );
}; };
@@ -283,7 +283,7 @@ MatrixBaseApis.prototype.loginWithToken = function(token, callback) {
*/ */
MatrixBaseApis.prototype.logout = function(callback) { MatrixBaseApis.prototype.logout = function(callback) {
return this._http.authedRequest( return this._http.authedRequest(
callback, "POST", '/logout' callback, "POST", '/logout',
); );
}; };
@@ -305,7 +305,7 @@ MatrixBaseApis.prototype.deactivateAccount = function(auth, callback) {
}; };
} }
return this._http.authedRequestWithPrefix( return this._http.authedRequestWithPrefix(
callback, "POST", '/account/deactivate', undefined, body, httpApi.PREFIX_UNSTABLE callback, "POST", '/account/deactivate', undefined, body, httpApi.PREFIX_UNSTABLE,
); );
}; };
@@ -318,7 +318,7 @@ MatrixBaseApis.prototype.deactivateAccount = function(auth, callback) {
* @return {string} HS URL to hit to for the fallback interface * @return {string} HS URL to hit to for the fallback interface
*/ */
MatrixBaseApis.prototype.getFallbackAuthUrl = function(loginType, authSessionId) { MatrixBaseApis.prototype.getFallbackAuthUrl = function(loginType, authSessionId) {
let path = utils.encodeUri("/auth/$loginType/fallback/web", { const path = utils.encodeUri("/auth/$loginType/fallback/web", {
$loginType: loginType, $loginType: loginType,
}); });
@@ -347,7 +347,7 @@ MatrixBaseApis.prototype.getFallbackAuthUrl = function(loginType, authSessionId)
MatrixBaseApis.prototype.createRoom = function(options, callback) { MatrixBaseApis.prototype.createRoom = function(options, callback) {
// valid options include: room_alias_name, visibility, invite // valid options include: room_alias_name, visibility, invite
return this._http.authedRequest( return this._http.authedRequest(
callback, "POST", "/createRoom", undefined, options callback, "POST", "/createRoom", undefined, options,
); );
}; };
@@ -358,7 +358,7 @@ MatrixBaseApis.prototype.createRoom = function(options, callback) {
* @return {module:http-api.MatrixError} Rejects: with an error response. * @return {module:http-api.MatrixError} Rejects: with an error response.
*/ */
MatrixBaseApis.prototype.roomState = function(roomId, callback) { MatrixBaseApis.prototype.roomState = function(roomId, callback) {
let path = utils.encodeUri("/rooms/$roomId/state", {$roomId: roomId}); const path = utils.encodeUri("/rooms/$roomId/state", {$roomId: roomId});
return this._http.authedRequest(callback, "GET", path); return this._http.authedRequest(callback, "GET", path);
}; };
@@ -372,7 +372,7 @@ MatrixBaseApis.prototype.roomState = function(roomId, callback) {
* @return {module:http-api.MatrixError} Rejects: with an error response. * @return {module:http-api.MatrixError} Rejects: with an error response.
*/ */
MatrixBaseApis.prototype.getStateEvent = function(roomId, eventType, stateKey, callback) { MatrixBaseApis.prototype.getStateEvent = function(roomId, eventType, stateKey, callback) {
let pathParams = { const pathParams = {
$roomId: roomId, $roomId: roomId,
$eventType: eventType, $eventType: eventType,
$stateKey: stateKey, $stateKey: stateKey,
@@ -382,7 +382,7 @@ MatrixBaseApis.prototype.getStateEvent = function(roomId, eventType, stateKey, c
path = utils.encodeUri(path + "/$stateKey", pathParams); path = utils.encodeUri(path + "/$stateKey", pathParams);
} }
return this._http.authedRequest( return this._http.authedRequest(
callback, "GET", path callback, "GET", path,
); );
}; };
@@ -397,7 +397,7 @@ MatrixBaseApis.prototype.getStateEvent = function(roomId, eventType, stateKey, c
*/ */
MatrixBaseApis.prototype.sendStateEvent = function(roomId, eventType, content, stateKey, MatrixBaseApis.prototype.sendStateEvent = function(roomId, eventType, content, stateKey,
callback) { callback) {
let pathParams = { const pathParams = {
$roomId: roomId, $roomId: roomId,
$eventType: eventType, $eventType: eventType,
$stateKey: stateKey, $stateKey: stateKey,
@@ -407,7 +407,7 @@ MatrixBaseApis.prototype.sendStateEvent = function(roomId, eventType, content, s
path = utils.encodeUri(path + "/$stateKey", pathParams); path = utils.encodeUri(path + "/$stateKey", pathParams);
} }
return this._http.authedRequest( return this._http.authedRequest(
callback, "PUT", path, undefined, content callback, "PUT", path, undefined, content,
); );
}; };
@@ -419,7 +419,7 @@ MatrixBaseApis.prototype.sendStateEvent = function(roomId, eventType, content, s
* @return {module:http-api.MatrixError} Rejects: with an error response. * @return {module:http-api.MatrixError} Rejects: with an error response.
*/ */
MatrixBaseApis.prototype.redactEvent = function(roomId, eventId, callback) { MatrixBaseApis.prototype.redactEvent = function(roomId, eventId, callback) {
let path = utils.encodeUri("/rooms/$roomId/redact/$eventId", { const path = utils.encodeUri("/rooms/$roomId/redact/$eventId", {
$roomId: roomId, $roomId: roomId,
$eventId: eventId, $eventId: eventId,
}); });
@@ -437,14 +437,14 @@ MatrixBaseApis.prototype.roomInitialSync = function(roomId, limit, callback) {
if (utils.isFunction(limit)) { if (utils.isFunction(limit)) {
callback = limit; limit = undefined; callback = limit; limit = undefined;
} }
let path = utils.encodeUri("/rooms/$roomId/initialSync", const path = utils.encodeUri("/rooms/$roomId/initialSync",
{$roomId: roomId} {$roomId: roomId},
); );
if (!limit) { if (!limit) {
limit = 30; limit = 30;
} }
return this._http.authedRequest( return this._http.authedRequest(
callback, "GET", path, { limit: limit } callback, "GET", path, { limit: limit },
); );
}; };
@@ -474,7 +474,7 @@ MatrixBaseApis.prototype.publicRooms = function(options, callback) {
options = {}; options = {};
} }
let query_params = {}; const query_params = {};
if (options.server) { if (options.server) {
query_params.server = options.server; query_params.server = options.server;
delete options.server; delete options.server;
@@ -484,7 +484,7 @@ MatrixBaseApis.prototype.publicRooms = function(options, callback) {
return this._http.authedRequest(callback, "GET", "/publicRooms"); return this._http.authedRequest(callback, "GET", "/publicRooms");
} else { } else {
return this._http.authedRequest( return this._http.authedRequest(
callback, "POST", "/publicRooms", query_params, options callback, "POST", "/publicRooms", query_params, options,
); );
} }
}; };
@@ -498,14 +498,14 @@ MatrixBaseApis.prototype.publicRooms = function(options, callback) {
* @return {module:http-api.MatrixError} Rejects: with an error response. * @return {module:http-api.MatrixError} Rejects: with an error response.
*/ */
MatrixBaseApis.prototype.createAlias = function(alias, roomId, callback) { MatrixBaseApis.prototype.createAlias = function(alias, roomId, callback) {
let path = utils.encodeUri("/directory/room/$alias", { const path = utils.encodeUri("/directory/room/$alias", {
$alias: alias, $alias: alias,
}); });
let data = { const data = {
room_id: roomId, room_id: roomId,
}; };
return this._http.authedRequest( return this._http.authedRequest(
callback, "PUT", path, undefined, data callback, "PUT", path, undefined, data,
); );
}; };
@@ -518,11 +518,11 @@ MatrixBaseApis.prototype.createAlias = function(alias, roomId, callback) {
* @return {module:http-api.MatrixError} Rejects: with an error response. * @return {module:http-api.MatrixError} Rejects: with an error response.
*/ */
MatrixBaseApis.prototype.deleteAlias = function(alias, callback) { MatrixBaseApis.prototype.deleteAlias = function(alias, callback) {
let path = utils.encodeUri("/directory/room/$alias", { const path = utils.encodeUri("/directory/room/$alias", {
$alias: alias, $alias: alias,
}); });
return this._http.authedRequest( return this._http.authedRequest(
callback, "DELETE", path, undefined, undefined callback, "DELETE", path, undefined, undefined,
); );
}; };
@@ -535,11 +535,11 @@ MatrixBaseApis.prototype.deleteAlias = function(alias, callback) {
*/ */
MatrixBaseApis.prototype.getRoomIdForAlias = function(alias, callback) { MatrixBaseApis.prototype.getRoomIdForAlias = function(alias, callback) {
// TODO: deprecate this or resolveRoomAlias // TODO: deprecate this or resolveRoomAlias
let path = utils.encodeUri("/directory/room/$alias", { const path = utils.encodeUri("/directory/room/$alias", {
$alias: alias, $alias: alias,
}); });
return this._http.authedRequest( return this._http.authedRequest(
callback, "GET", path callback, "GET", path,
); );
}; };
@@ -551,7 +551,7 @@ MatrixBaseApis.prototype.getRoomIdForAlias = function(alias, callback) {
*/ */
MatrixBaseApis.prototype.resolveRoomAlias = function(roomAlias, callback) { MatrixBaseApis.prototype.resolveRoomAlias = function(roomAlias, callback) {
// TODO: deprecate this or getRoomIdForAlias // TODO: deprecate this or getRoomIdForAlias
let path = utils.encodeUri("/directory/room/$alias", {$alias: roomAlias}); const path = utils.encodeUri("/directory/room/$alias", {$alias: roomAlias});
return this._http.request(callback, "GET", path); return this._http.request(callback, "GET", path);
}; };
@@ -564,7 +564,7 @@ MatrixBaseApis.prototype.resolveRoomAlias = function(roomAlias, callback) {
*/ */
MatrixBaseApis.prototype.getRoomDirectoryVisibility = MatrixBaseApis.prototype.getRoomDirectoryVisibility =
function(roomId, callback) { function(roomId, callback) {
let path = utils.encodeUri("/directory/list/room/$roomId", { const path = utils.encodeUri("/directory/list/room/$roomId", {
$roomId: roomId, $roomId: roomId,
}); });
return this._http.authedRequest(callback, "GET", path); return this._http.authedRequest(callback, "GET", path);
@@ -582,11 +582,11 @@ MatrixBaseApis.prototype.getRoomDirectoryVisibility =
*/ */
MatrixBaseApis.prototype.setRoomDirectoryVisibility = MatrixBaseApis.prototype.setRoomDirectoryVisibility =
function(roomId, visibility, callback) { function(roomId, visibility, callback) {
let path = utils.encodeUri("/directory/list/room/$roomId", { const path = utils.encodeUri("/directory/list/room/$roomId", {
$roomId: roomId, $roomId: roomId,
}); });
return this._http.authedRequest( return this._http.authedRequest(
callback, "PUT", path, undefined, { "visibility": visibility } callback, "PUT", path, undefined, { "visibility": visibility },
); );
}; };
@@ -605,12 +605,12 @@ MatrixBaseApis.prototype.setRoomDirectoryVisibility =
*/ */
MatrixBaseApis.prototype.setRoomDirectoryVisibilityAppService = MatrixBaseApis.prototype.setRoomDirectoryVisibilityAppService =
function(networkId, roomId, visibility, callback) { function(networkId, roomId, visibility, callback) {
let path = utils.encodeUri("/directory/list/appservice/$networkId/$roomId", { const path = utils.encodeUri("/directory/list/appservice/$networkId/$roomId", {
$networkId: networkId, $networkId: networkId,
$roomId: roomId, $roomId: roomId,
}); });
return this._http.authedRequest( return this._http.authedRequest(
callback, "PUT", path, undefined, { "visibility": visibility } callback, "PUT", path, undefined, { "visibility": visibility },
); );
}; };
@@ -692,7 +692,7 @@ MatrixBaseApis.prototype.getProfileInfo = function(userId, info, callback) {
callback = info; info = undefined; callback = info; info = undefined;
} }
let path = info ? const path = info ?
utils.encodeUri("/profile/$userId/$info", utils.encodeUri("/profile/$userId/$info",
{ $userId: userId, $info: info }) : { $userId: userId, $info: info }) :
utils.encodeUri("/profile/$userId", utils.encodeUri("/profile/$userId",
@@ -710,9 +710,9 @@ MatrixBaseApis.prototype.getProfileInfo = function(userId, info, callback) {
* @return {module:http-api.MatrixError} Rejects: with an error response. * @return {module:http-api.MatrixError} Rejects: with an error response.
*/ */
MatrixBaseApis.prototype.getThreePids = function(callback) { MatrixBaseApis.prototype.getThreePids = function(callback) {
let path = "/account/3pid"; const path = "/account/3pid";
return this._http.authedRequest( return this._http.authedRequest(
callback, "GET", path, undefined, undefined callback, "GET", path, undefined, undefined,
); );
}; };
@@ -724,13 +724,13 @@ MatrixBaseApis.prototype.getThreePids = function(callback) {
* @return {module:http-api.MatrixError} Rejects: with an error response. * @return {module:http-api.MatrixError} Rejects: with an error response.
*/ */
MatrixBaseApis.prototype.addThreePid = function(creds, bind, callback) { MatrixBaseApis.prototype.addThreePid = function(creds, bind, callback) {
let path = "/account/3pid"; const path = "/account/3pid";
let data = { const data = {
'threePidCreds': creds, 'threePidCreds': creds,
'bind': bind, 'bind': bind,
}; };
return this._http.authedRequest( return this._http.authedRequest(
callback, "POST", path, null, data callback, "POST", path, null, data,
); );
}; };
@@ -743,13 +743,13 @@ MatrixBaseApis.prototype.addThreePid = function(creds, bind, callback) {
* @return {module:http-api.MatrixError} Rejects: with an error response. * @return {module:http-api.MatrixError} Rejects: with an error response.
*/ */
MatrixBaseApis.prototype.deleteThreePid = function(medium, address) { MatrixBaseApis.prototype.deleteThreePid = function(medium, address) {
let path = "/account/3pid/delete"; const path = "/account/3pid/delete";
let data = { const data = {
'medium': medium, 'medium': medium,
'address': address, 'address': address,
}; };
return this._http.authedRequestWithPrefix( return this._http.authedRequestWithPrefix(
undefined, "POST", path, null, data, httpApi.PREFIX_UNSTABLE undefined, "POST", path, null, data, httpApi.PREFIX_UNSTABLE,
); );
}; };
@@ -762,14 +762,14 @@ MatrixBaseApis.prototype.deleteThreePid = function(medium, address) {
* @return {module:http-api.MatrixError} Rejects: with an error response. * @return {module:http-api.MatrixError} Rejects: with an error response.
*/ */
MatrixBaseApis.prototype.setPassword = function(authDict, newPassword, callback) { MatrixBaseApis.prototype.setPassword = function(authDict, newPassword, callback) {
let path = "/account/password"; const path = "/account/password";
let data = { const data = {
'auth': authDict, 'auth': authDict,
'new_password': newPassword, 'new_password': newPassword,
}; };
return this._http.authedRequest( return this._http.authedRequest(
callback, "POST", path, null, data callback, "POST", path, null, data,
); );
}; };
@@ -783,10 +783,10 @@ MatrixBaseApis.prototype.setPassword = function(authDict, newPassword, callback)
* @return {module:http-api.MatrixError} Rejects: with an error response. * @return {module:http-api.MatrixError} Rejects: with an error response.
*/ */
MatrixBaseApis.prototype.getDevices = function() { MatrixBaseApis.prototype.getDevices = function() {
let path = "/devices"; const path = "/devices";
return this._http.authedRequestWithPrefix( return this._http.authedRequestWithPrefix(
undefined, "GET", path, undefined, undefined, undefined, "GET", path, undefined, undefined,
httpApi.PREFIX_UNSTABLE httpApi.PREFIX_UNSTABLE,
); );
}; };
@@ -799,14 +799,14 @@ MatrixBaseApis.prototype.getDevices = function() {
* @return {module:http-api.MatrixError} Rejects: with an error response. * @return {module:http-api.MatrixError} Rejects: with an error response.
*/ */
MatrixBaseApis.prototype.setDeviceDetails = function(device_id, body) { MatrixBaseApis.prototype.setDeviceDetails = function(device_id, body) {
let path = utils.encodeUri("/devices/$device_id", { const path = utils.encodeUri("/devices/$device_id", {
$device_id: device_id, $device_id: device_id,
}); });
return this._http.authedRequestWithPrefix( return this._http.authedRequestWithPrefix(
undefined, "PUT", path, undefined, body, undefined, "PUT", path, undefined, body,
httpApi.PREFIX_UNSTABLE httpApi.PREFIX_UNSTABLE,
); );
}; };
@@ -819,11 +819,11 @@ MatrixBaseApis.prototype.setDeviceDetails = function(device_id, body) {
* @return {module:http-api.MatrixError} Rejects: with an error response. * @return {module:http-api.MatrixError} Rejects: with an error response.
*/ */
MatrixBaseApis.prototype.deleteDevice = function(device_id, auth) { MatrixBaseApis.prototype.deleteDevice = function(device_id, auth) {
let path = utils.encodeUri("/devices/$device_id", { const path = utils.encodeUri("/devices/$device_id", {
$device_id: device_id, $device_id: device_id,
}); });
let body = {}; const body = {};
if (auth) { if (auth) {
body.auth = auth; body.auth = auth;
@@ -831,7 +831,7 @@ MatrixBaseApis.prototype.deleteDevice = function(device_id, auth) {
return this._http.authedRequestWithPrefix( return this._http.authedRequestWithPrefix(
undefined, "DELETE", path, undefined, body, undefined, "DELETE", path, undefined, body,
httpApi.PREFIX_UNSTABLE httpApi.PREFIX_UNSTABLE,
); );
}; };
@@ -847,9 +847,9 @@ MatrixBaseApis.prototype.deleteDevice = function(device_id, auth) {
* @return {module:http-api.MatrixError} Rejects: with an error response. * @return {module:http-api.MatrixError} Rejects: with an error response.
*/ */
MatrixBaseApis.prototype.getPushers = function(callback) { MatrixBaseApis.prototype.getPushers = function(callback) {
let path = "/pushers"; const path = "/pushers";
return this._http.authedRequest( return this._http.authedRequest(
callback, "GET", path, undefined, undefined callback, "GET", path, undefined, undefined,
); );
}; };
@@ -862,9 +862,9 @@ MatrixBaseApis.prototype.getPushers = function(callback) {
* @return {module:http-api.MatrixError} Rejects: with an error response. * @return {module:http-api.MatrixError} Rejects: with an error response.
*/ */
MatrixBaseApis.prototype.setPusher = function(pusher, callback) { MatrixBaseApis.prototype.setPusher = function(pusher, callback) {
let path = "/pushers/set"; const path = "/pushers/set";
return this._http.authedRequest( return this._http.authedRequest(
callback, "POST", path, null, pusher callback, "POST", path, null, pusher,
); );
}; };
@@ -888,12 +888,12 @@ MatrixBaseApis.prototype.getPushRules = function(callback) {
*/ */
MatrixBaseApis.prototype.addPushRule = function(scope, kind, ruleId, body, callback) { MatrixBaseApis.prototype.addPushRule = function(scope, kind, ruleId, body, callback) {
// NB. Scope not uri encoded because devices need the '/' // NB. Scope not uri encoded because devices need the '/'
let path = utils.encodeUri("/pushrules/" + scope + "/$kind/$ruleId", { const path = utils.encodeUri("/pushrules/" + scope + "/$kind/$ruleId", {
$kind: kind, $kind: kind,
$ruleId: ruleId, $ruleId: ruleId,
}); });
return this._http.authedRequest( return this._http.authedRequest(
callback, "PUT", path, undefined, body callback, "PUT", path, undefined, body,
); );
}; };
@@ -907,7 +907,7 @@ MatrixBaseApis.prototype.addPushRule = function(scope, kind, ruleId, body, callb
*/ */
MatrixBaseApis.prototype.deletePushRule = function(scope, kind, ruleId, callback) { MatrixBaseApis.prototype.deletePushRule = function(scope, kind, ruleId, callback) {
// NB. Scope not uri encoded because devices need the '/' // NB. Scope not uri encoded because devices need the '/'
let path = utils.encodeUri("/pushrules/" + scope + "/$kind/$ruleId", { const path = utils.encodeUri("/pushrules/" + scope + "/$kind/$ruleId", {
$kind: kind, $kind: kind,
$ruleId: ruleId, $ruleId: ruleId,
}); });
@@ -926,12 +926,12 @@ MatrixBaseApis.prototype.deletePushRule = function(scope, kind, ruleId, callback
*/ */
MatrixBaseApis.prototype.setPushRuleEnabled = function(scope, kind, MatrixBaseApis.prototype.setPushRuleEnabled = function(scope, kind,
ruleId, enabled, callback) { ruleId, enabled, callback) {
let path = utils.encodeUri("/pushrules/" + scope + "/$kind/$ruleId/enabled", { const path = utils.encodeUri("/pushrules/" + scope + "/$kind/$ruleId/enabled", {
$kind: kind, $kind: kind,
$ruleId: ruleId, $ruleId: ruleId,
}); });
return this._http.authedRequest( return this._http.authedRequest(
callback, "PUT", path, undefined, {"enabled": enabled} callback, "PUT", path, undefined, {"enabled": enabled},
); );
}; };
@@ -947,12 +947,12 @@ MatrixBaseApis.prototype.setPushRuleEnabled = function(scope, kind,
*/ */
MatrixBaseApis.prototype.setPushRuleActions = function(scope, kind, MatrixBaseApis.prototype.setPushRuleActions = function(scope, kind,
ruleId, actions, callback) { ruleId, actions, callback) {
let path = utils.encodeUri("/pushrules/" + scope + "/$kind/$ruleId/actions", { const path = utils.encodeUri("/pushrules/" + scope + "/$kind/$ruleId/actions", {
$kind: kind, $kind: kind,
$ruleId: ruleId, $ruleId: ruleId,
}); });
return this._http.authedRequest( return this._http.authedRequest(
callback, "PUT", path, undefined, {"actions": actions} callback, "PUT", path, undefined, {"actions": actions},
); );
}; };
@@ -970,12 +970,12 @@ MatrixBaseApis.prototype.setPushRuleActions = function(scope, kind,
* @return {module:http-api.MatrixError} Rejects: with an error response. * @return {module:http-api.MatrixError} Rejects: with an error response.
*/ */
MatrixBaseApis.prototype.search = function(opts, callback) { MatrixBaseApis.prototype.search = function(opts, callback) {
let queryparams = {}; const queryparams = {};
if (opts.next_batch) { if (opts.next_batch) {
queryparams.next_batch = opts.next_batch; queryparams.next_batch = opts.next_batch;
} }
return this._http.authedRequest( return this._http.authedRequest(
callback, "POST", "/search", queryparams, opts.body callback, "POST", "/search", queryparams, opts.body,
); );
}; };
@@ -999,7 +999,7 @@ MatrixBaseApis.prototype.search = function(opts, callback) {
*/ */
MatrixBaseApis.prototype.uploadKeysRequest = function(content, opts, callback) { MatrixBaseApis.prototype.uploadKeysRequest = function(content, opts, callback) {
opts = opts || {}; opts = opts || {};
let deviceId = opts.device_id; const deviceId = opts.device_id;
let path; let path;
if (deviceId) { if (deviceId) {
path = utils.encodeUri("/keys/upload/$deviceId", { path = utils.encodeUri("/keys/upload/$deviceId", {
@@ -1009,7 +1009,7 @@ MatrixBaseApis.prototype.uploadKeysRequest = function(content, opts, callback) {
path = "/keys/upload"; path = "/keys/upload";
} }
return this._http.authedRequestWithPrefix( return this._http.authedRequestWithPrefix(
callback, "POST", path, undefined, content, httpApi.PREFIX_UNSTABLE callback, "POST", path, undefined, content, httpApi.PREFIX_UNSTABLE,
); );
}; };
@@ -1024,15 +1024,15 @@ MatrixBaseApis.prototype.uploadKeysRequest = function(content, opts, callback) {
* an error response ({@link module:http-api.MatrixError}). * an error response ({@link module:http-api.MatrixError}).
*/ */
MatrixBaseApis.prototype.downloadKeysForUsers = function(userIds, callback) { MatrixBaseApis.prototype.downloadKeysForUsers = function(userIds, callback) {
let downloadQuery = {}; const downloadQuery = {};
for (let i = 0; i < userIds.length; ++i) { for (let i = 0; i < userIds.length; ++i) {
downloadQuery[userIds[i]] = {}; downloadQuery[userIds[i]] = {};
} }
let content = {device_keys: downloadQuery}; const content = {device_keys: downloadQuery};
return this._http.authedRequestWithPrefix( return this._http.authedRequestWithPrefix(
callback, "POST", "/keys/query", undefined, content, callback, "POST", "/keys/query", undefined, content,
httpApi.PREFIX_UNSTABLE httpApi.PREFIX_UNSTABLE,
); );
}; };
@@ -1047,23 +1047,23 @@ MatrixBaseApis.prototype.downloadKeysForUsers = function(userIds, callback) {
* an error response ({@link module:http-api.MatrixError}). * an error response ({@link module:http-api.MatrixError}).
*/ */
MatrixBaseApis.prototype.claimOneTimeKeys = function(devices, key_algorithm) { MatrixBaseApis.prototype.claimOneTimeKeys = function(devices, key_algorithm) {
let queries = {}; const queries = {};
if (key_algorithm === undefined) { if (key_algorithm === undefined) {
key_algorithm = "signed_curve25519"; key_algorithm = "signed_curve25519";
} }
for (let i = 0; i < devices.length; ++i) { for (let i = 0; i < devices.length; ++i) {
let userId = devices[i][0]; const userId = devices[i][0];
let deviceId = devices[i][1]; const deviceId = devices[i][1];
let query = queries[userId] || {}; const query = queries[userId] || {};
queries[userId] = query; queries[userId] = query;
query[deviceId] = key_algorithm; query[deviceId] = key_algorithm;
} }
let content = {one_time_keys: queries}; const content = {one_time_keys: queries};
return this._http.authedRequestWithPrefix( return this._http.authedRequestWithPrefix(
undefined, "POST", "/keys/claim", undefined, content, undefined, "POST", "/keys/claim", undefined, content,
httpApi.PREFIX_UNSTABLE httpApi.PREFIX_UNSTABLE,
); );
}; };
@@ -1093,7 +1093,7 @@ MatrixBaseApis.prototype.claimOneTimeKeys = function(devices, key_algorithm) {
*/ */
MatrixBaseApis.prototype.requestEmailToken = function(email, clientSecret, MatrixBaseApis.prototype.requestEmailToken = function(email, clientSecret,
sendAttempt, nextLink, callback) { sendAttempt, nextLink, callback) {
let params = { const params = {
client_secret: clientSecret, client_secret: clientSecret,
email: email, email: email,
send_attempt: sendAttempt, send_attempt: sendAttempt,
@@ -1101,7 +1101,7 @@ MatrixBaseApis.prototype.requestEmailToken = function(email, clientSecret,
}; };
return this._http.idServerRequest( return this._http.idServerRequest(
callback, "POST", "/validate/email/requestToken", callback, "POST", "/validate/email/requestToken",
params, httpApi.PREFIX_IDENTITY_V1 params, httpApi.PREFIX_IDENTITY_V1,
); );
}; };
@@ -1117,13 +1117,13 @@ MatrixBaseApis.prototype.requestEmailToken = function(email, clientSecret,
* @return {module:http-api.MatrixError} Rejects: with an error response. * @return {module:http-api.MatrixError} Rejects: with an error response.
*/ */
MatrixBaseApis.prototype.lookupThreePid = function(medium, address, callback) { MatrixBaseApis.prototype.lookupThreePid = function(medium, address, callback) {
let params = { const params = {
medium: medium, medium: medium,
address: address, address: address,
}; };
return this._http.idServerRequest( return this._http.idServerRequest(
callback, "GET", "/lookup", callback, "GET", "/lookup",
params, httpApi.PREFIX_IDENTITY_V1 params, httpApi.PREFIX_IDENTITY_V1,
); );
}; };
@@ -1142,20 +1142,20 @@ MatrixBaseApis.prototype.lookupThreePid = function(medium, address, callback) {
* @return {module:client.Promise} Resolves to the result object * @return {module:client.Promise} Resolves to the result object
*/ */
MatrixBaseApis.prototype.sendToDevice = function( MatrixBaseApis.prototype.sendToDevice = function(
eventType, contentMap, txnId eventType, contentMap, txnId,
) { ) {
let path = utils.encodeUri("/sendToDevice/$eventType/$txnId", { const path = utils.encodeUri("/sendToDevice/$eventType/$txnId", {
$eventType: eventType, $eventType: eventType,
$txnId: txnId ? txnId : this.makeTxnId(), $txnId: txnId ? txnId : this.makeTxnId(),
}); });
let body = { const body = {
messages: contentMap, messages: contentMap,
}; };
return this._http.authedRequestWithPrefix( return this._http.authedRequestWithPrefix(
undefined, "PUT", path, undefined, body, undefined, "PUT", path, undefined, body,
httpApi.PREFIX_UNSTABLE httpApi.PREFIX_UNSTABLE,
); );
}; };
@@ -1170,7 +1170,7 @@ MatrixBaseApis.prototype.sendToDevice = function(
MatrixBaseApis.prototype.getThirdpartyProtocols = function() { MatrixBaseApis.prototype.getThirdpartyProtocols = function() {
return this._http.authedRequestWithPrefix( return this._http.authedRequestWithPrefix(
undefined, "GET", "/thirdparty/protocols", undefined, undefined, undefined, "GET", "/thirdparty/protocols", undefined, undefined,
httpApi.PREFIX_UNSTABLE httpApi.PREFIX_UNSTABLE,
); );
}; };
@@ -1183,13 +1183,13 @@ MatrixBaseApis.prototype.getThirdpartyProtocols = function() {
* @return {module:client.Promise} Resolves to the result object * @return {module:client.Promise} Resolves to the result object
*/ */
MatrixBaseApis.prototype.getThirdpartyLocation = function(protocol, params) { MatrixBaseApis.prototype.getThirdpartyLocation = function(protocol, params) {
let path = utils.encodeUri("/thirdparty/location/$protocol", { const path = utils.encodeUri("/thirdparty/location/$protocol", {
$protocol: protocol, $protocol: protocol,
}); });
return this._http.authedRequestWithPrefix( return this._http.authedRequestWithPrefix(
undefined, "GET", path, params, undefined, undefined, "GET", path, params, undefined,
httpApi.PREFIX_UNSTABLE httpApi.PREFIX_UNSTABLE,
); );
}; };

File diff suppressed because it is too large Load Diff

View File

@@ -16,7 +16,7 @@ limitations under the License.
/** /**
* @module content-repo * @module content-repo
*/ */
let utils = require("./utils"); const utils = require("./utils");
/** Content Repo utility functions */ /** Content Repo utility functions */
module.exports = { module.exports = {
@@ -48,7 +48,7 @@ module.exports = {
} }
let serverAndMediaId = mxc.slice(6); // strips mxc:// let serverAndMediaId = mxc.slice(6); // strips mxc://
let prefix = "/_matrix/media/v1/download/"; let prefix = "/_matrix/media/v1/download/";
let params = {}; const params = {};
if (width) { if (width) {
params.width = width; params.width = width;
@@ -65,8 +65,8 @@ module.exports = {
prefix = "/_matrix/media/v1/thumbnail/"; prefix = "/_matrix/media/v1/thumbnail/";
} }
let fragmentOffset = serverAndMediaId.indexOf("#"), const fragmentOffset = serverAndMediaId.indexOf("#");
fragment = ""; let fragment = "";
if (fragmentOffset >= 0) { if (fragmentOffset >= 0) {
fragment = serverAndMediaId.substr(fragmentOffset); fragment = serverAndMediaId.substr(fragmentOffset);
serverAndMediaId = serverAndMediaId.substr(0, fragmentOffset); serverAndMediaId = serverAndMediaId.substr(0, fragmentOffset);
@@ -94,12 +94,12 @@ module.exports = {
if (!height) { if (!height) {
height = 96; height = 96;
} }
let params = { const params = {
width: width, width: width,
height: height, height: height,
}; };
let path = utils.encodeUri("/_matrix/media/v1/identicon/$ident", { const path = utils.encodeUri("/_matrix/media/v1/identicon/$ident", {
$ident: identiconString, $ident: identiconString,
}); });
return baseUrl + path + return baseUrl + path +

View File

@@ -20,13 +20,13 @@ limitations under the License.
* *
* @module crypto/OlmDevice * @module crypto/OlmDevice
*/ */
let Olm = require("olm"); const Olm = require("olm");
let utils = require("../utils"); const utils = require("../utils");
// The maximum size of an event is 65K, and we base64 the content, so this is a // The maximum size of an event is 65K, and we base64 the content, so this is a
// reasonable approximation to the biggest plaintext we can encrypt. // reasonable approximation to the biggest plaintext we can encrypt.
let MAX_PLAINTEXT_LENGTH = 65536 * 3 / 4; const MAX_PLAINTEXT_LENGTH = 65536 * 3 / 4;
function checkPayloadLength(payloadString) { function checkPayloadLength(payloadString) {
if (payloadString === undefined) { if (payloadString === undefined) {
@@ -47,6 +47,18 @@ function checkPayloadLength(payloadString) {
} }
/**
* The type of object we use for importing and exporting megolm session data.
*
* @typedef {Object} module:crypto/OlmDevice.MegolmSessionData
* @property {String} sender_key Sender's Curve25519 device key
* @property {Object<string, string>} sender_claimed_keys Other keys the sender claims.
* @property {String} room_id Room this session is used in
* @property {String} session_id Unique id for the session
* @property {String} session_key Base64'ed key data
*/
/** /**
* Manages the olm cryptography functions. Each OlmDevice has a single * Manages the olm cryptography functions. Each OlmDevice has a single
* OlmAccount and a number of OlmSessions. * OlmAccount and a number of OlmSessions.
@@ -67,7 +79,7 @@ function OlmDevice(sessionStore) {
this._pickleKey = "DEFAULT_KEY"; this._pickleKey = "DEFAULT_KEY";
let e2eKeys; let e2eKeys;
let account = new Olm.Account(); const account = new Olm.Account();
try { try {
_initialise_account(this._sessionStore, this._pickleKey, account); _initialise_account(this._sessionStore, this._pickleKey, account);
e2eKeys = JSON.parse(account.identity_keys()); e2eKeys = JSON.parse(account.identity_keys());
@@ -96,14 +108,14 @@ function OlmDevice(sessionStore) {
} }
function _initialise_account(sessionStore, pickleKey, account) { function _initialise_account(sessionStore, pickleKey, account) {
let e2eAccount = sessionStore.getEndToEndAccount(); const e2eAccount = sessionStore.getEndToEndAccount();
if (e2eAccount !== null) { if (e2eAccount !== null) {
account.unpickle(pickleKey, e2eAccount); account.unpickle(pickleKey, e2eAccount);
return; return;
} }
account.create(); account.create();
let pickled = account.pickle(pickleKey); const pickled = account.pickle(pickleKey);
sessionStore.storeEndToEndAccount(pickled); sessionStore.storeEndToEndAccount(pickled);
} }
@@ -123,9 +135,9 @@ OlmDevice.getOlmVersion = function() {
* @private * @private
*/ */
OlmDevice.prototype._getAccount = function(func) { OlmDevice.prototype._getAccount = function(func) {
let account = new Olm.Account(); const account = new Olm.Account();
try { try {
let pickledAccount = this._sessionStore.getEndToEndAccount(); const pickledAccount = this._sessionStore.getEndToEndAccount();
account.unpickle(this._pickleKey, pickledAccount); account.unpickle(this._pickleKey, pickledAccount);
return func(account); return func(account);
} finally { } finally {
@@ -141,7 +153,7 @@ OlmDevice.prototype._getAccount = function(func) {
* @private * @private
*/ */
OlmDevice.prototype._saveAccount = function(account) { OlmDevice.prototype._saveAccount = function(account) {
let pickledAccount = account.pickle(this._pickleKey); const pickledAccount = account.pickle(this._pickleKey);
this._sessionStore.storeEndToEndAccount(pickledAccount); this._sessionStore.storeEndToEndAccount(pickledAccount);
}; };
@@ -156,10 +168,10 @@ OlmDevice.prototype._saveAccount = function(account) {
* @private * @private
*/ */
OlmDevice.prototype._getSession = function(deviceKey, sessionId, func) { OlmDevice.prototype._getSession = function(deviceKey, sessionId, func) {
let sessions = this._sessionStore.getEndToEndSessions(deviceKey); const sessions = this._sessionStore.getEndToEndSessions(deviceKey);
let pickledSession = sessions[sessionId]; const pickledSession = sessions[sessionId];
let session = new Olm.Session(); const session = new Olm.Session();
try { try {
session.unpickle(this._pickleKey, pickledSession); session.unpickle(this._pickleKey, pickledSession);
return func(session); return func(session);
@@ -177,9 +189,9 @@ OlmDevice.prototype._getSession = function(deviceKey, sessionId, func) {
* @private * @private
*/ */
OlmDevice.prototype._saveSession = function(deviceKey, session) { OlmDevice.prototype._saveSession = function(deviceKey, session) {
let pickledSession = session.pickle(this._pickleKey); const pickledSession = session.pickle(this._pickleKey);
this._sessionStore.storeEndToEndSession( this._sessionStore.storeEndToEndSession(
deviceKey, session.session_id(), pickledSession deviceKey, session.session_id(), pickledSession,
); );
}; };
@@ -192,7 +204,7 @@ OlmDevice.prototype._saveSession = function(deviceKey, session) {
* @private * @private
*/ */
OlmDevice.prototype._getUtility = function(func) { OlmDevice.prototype._getUtility = function(func) {
let utility = new Olm.Utility(); const utility = new Olm.Utility();
try { try {
return func(utility); return func(utility);
} finally { } finally {
@@ -242,7 +254,7 @@ OlmDevice.prototype.maxNumberOfOneTimeKeys = function() {
* Marks all of the one-time keys as published. * Marks all of the one-time keys as published.
*/ */
OlmDevice.prototype.markKeysAsPublished = function() { OlmDevice.prototype.markKeysAsPublished = function() {
let self = this; const self = this;
this._getAccount(function(account) { this._getAccount(function(account) {
account.mark_keys_as_published(); account.mark_keys_as_published();
self._saveAccount(account); self._saveAccount(account);
@@ -255,7 +267,7 @@ OlmDevice.prototype.markKeysAsPublished = function() {
* @param {number} numKeys number of keys to generate * @param {number} numKeys number of keys to generate
*/ */
OlmDevice.prototype.generateOneTimeKeys = function(numKeys) { OlmDevice.prototype.generateOneTimeKeys = function(numKeys) {
let self = this; const self = this;
this._getAccount(function(account) { this._getAccount(function(account) {
account.generate_one_time_keys(numKeys); account.generate_one_time_keys(numKeys);
self._saveAccount(account); self._saveAccount(account);
@@ -272,11 +284,11 @@ OlmDevice.prototype.generateOneTimeKeys = function(numKeys) {
* @return {string} sessionId for the outbound session. * @return {string} sessionId for the outbound session.
*/ */
OlmDevice.prototype.createOutboundSession = function( OlmDevice.prototype.createOutboundSession = function(
theirIdentityKey, theirOneTimeKey theirIdentityKey, theirOneTimeKey,
) { ) {
let self = this; const self = this;
return this._getAccount(function(account) { return this._getAccount(function(account) {
let session = new Olm.Session(); const session = new Olm.Session();
try { try {
session.create_outbound(account, theirIdentityKey, theirOneTimeKey); session.create_outbound(account, theirIdentityKey, theirOneTimeKey);
self._saveSession(theirIdentityKey, session); self._saveSession(theirIdentityKey, session);
@@ -302,21 +314,21 @@ OlmDevice.prototype.createOutboundSession = function(
* didn't use a valid one-time key). * didn't use a valid one-time key).
*/ */
OlmDevice.prototype.createInboundSession = function( OlmDevice.prototype.createInboundSession = function(
theirDeviceIdentityKey, message_type, ciphertext theirDeviceIdentityKey, message_type, ciphertext,
) { ) {
if (message_type !== 0) { if (message_type !== 0) {
throw new Error("Need message_type == 0 to create inbound session"); throw new Error("Need message_type == 0 to create inbound session");
} }
let self = this; const self = this;
return this._getAccount(function(account) { return this._getAccount(function(account) {
let session = new Olm.Session(); const session = new Olm.Session();
try { try {
session.create_inbound_from(account, theirDeviceIdentityKey, ciphertext); session.create_inbound_from(account, theirDeviceIdentityKey, ciphertext);
account.remove_one_time_keys(session); account.remove_one_time_keys(session);
self._saveAccount(account); self._saveAccount(account);
let payloadString = session.decrypt(message_type, ciphertext); const payloadString = session.decrypt(message_type, ciphertext);
self._saveSession(theirDeviceIdentityKey, session); self._saveSession(theirDeviceIdentityKey, session);
@@ -339,8 +351,8 @@ OlmDevice.prototype.createInboundSession = function(
* @return {string[]} a list of known session ids for the device * @return {string[]} a list of known session ids for the device
*/ */
OlmDevice.prototype.getSessionIdsForDevice = function(theirDeviceIdentityKey) { OlmDevice.prototype.getSessionIdsForDevice = function(theirDeviceIdentityKey) {
let sessions = this._sessionStore.getEndToEndSessions( const sessions = this._sessionStore.getEndToEndSessions(
theirDeviceIdentityKey theirDeviceIdentityKey,
); );
return utils.keys(sessions); return utils.keys(sessions);
}; };
@@ -353,7 +365,7 @@ OlmDevice.prototype.getSessionIdsForDevice = function(theirDeviceIdentityKey) {
* @return {string?} session id, or null if no established session * @return {string?} session id, or null if no established session
*/ */
OlmDevice.prototype.getSessionIdForDevice = function(theirDeviceIdentityKey) { OlmDevice.prototype.getSessionIdForDevice = function(theirDeviceIdentityKey) {
let sessionIds = this.getSessionIdsForDevice(theirDeviceIdentityKey); const sessionIds = this.getSessionIdsForDevice(theirDeviceIdentityKey);
if (sessionIds.length === 0) { if (sessionIds.length === 0) {
return null; return null;
} }
@@ -374,10 +386,10 @@ OlmDevice.prototype.getSessionIdForDevice = function(theirDeviceIdentityKey) {
* @return {Array.<{sessionId: string, hasReceivedMessage: Boolean}>} * @return {Array.<{sessionId: string, hasReceivedMessage: Boolean}>}
*/ */
OlmDevice.prototype.getSessionInfoForDevice = function(deviceIdentityKey) { OlmDevice.prototype.getSessionInfoForDevice = function(deviceIdentityKey) {
let sessionIds = this.getSessionIdsForDevice(deviceIdentityKey); const sessionIds = this.getSessionIdsForDevice(deviceIdentityKey);
sessionIds.sort(); sessionIds.sort();
let info = []; const info = [];
function getSessionInfo(session) { function getSessionInfo(session) {
return { return {
@@ -386,8 +398,8 @@ OlmDevice.prototype.getSessionInfoForDevice = function(deviceIdentityKey) {
} }
for (let i = 0; i < sessionIds.length; i++) { for (let i = 0; i < sessionIds.length; i++) {
let sessionId = sessionIds[i]; const sessionId = sessionIds[i];
let res = this._getSession(deviceIdentityKey, sessionId, getSessionInfo); const res = this._getSession(deviceIdentityKey, sessionId, getSessionInfo);
res.sessionId = sessionId; res.sessionId = sessionId;
info.push(res); info.push(res);
} }
@@ -405,14 +417,14 @@ OlmDevice.prototype.getSessionInfoForDevice = function(deviceIdentityKey) {
* @return {string} ciphertext * @return {string} ciphertext
*/ */
OlmDevice.prototype.encryptMessage = function( OlmDevice.prototype.encryptMessage = function(
theirDeviceIdentityKey, sessionId, payloadString theirDeviceIdentityKey, sessionId, payloadString,
) { ) {
let self = this; const self = this;
checkPayloadLength(payloadString); checkPayloadLength(payloadString);
return this._getSession(theirDeviceIdentityKey, sessionId, function(session) { return this._getSession(theirDeviceIdentityKey, sessionId, function(session) {
let res = session.encrypt(payloadString); const res = session.encrypt(payloadString);
self._saveSession(theirDeviceIdentityKey, session); self._saveSession(theirDeviceIdentityKey, session);
return res; return res;
}); });
@@ -430,12 +442,12 @@ OlmDevice.prototype.encryptMessage = function(
* @return {string} decrypted payload. * @return {string} decrypted payload.
*/ */
OlmDevice.prototype.decryptMessage = function( OlmDevice.prototype.decryptMessage = function(
theirDeviceIdentityKey, sessionId, message_type, ciphertext theirDeviceIdentityKey, sessionId, message_type, ciphertext,
) { ) {
let self = this; const self = this;
return this._getSession(theirDeviceIdentityKey, sessionId, function(session) { return this._getSession(theirDeviceIdentityKey, sessionId, function(session) {
let payloadString = session.decrypt(message_type, ciphertext); const payloadString = session.decrypt(message_type, ciphertext);
self._saveSession(theirDeviceIdentityKey, session); self._saveSession(theirDeviceIdentityKey, session);
return payloadString; return payloadString;
@@ -455,7 +467,7 @@ OlmDevice.prototype.decryptMessage = function(
* the given session. * the given session.
*/ */
OlmDevice.prototype.matchesSession = function( OlmDevice.prototype.matchesSession = function(
theirDeviceIdentityKey, sessionId, message_type, ciphertext theirDeviceIdentityKey, sessionId, message_type, ciphertext,
) { ) {
if (message_type !== 0) { if (message_type !== 0) {
return false; return false;
@@ -477,7 +489,7 @@ OlmDevice.prototype.matchesSession = function(
* @private * @private
*/ */
OlmDevice.prototype._saveOutboundGroupSession = function(session) { OlmDevice.prototype._saveOutboundGroupSession = function(session) {
let pickledSession = session.pickle(this._pickleKey); const pickledSession = session.pickle(this._pickleKey);
this._outboundGroupSessionStore[session.session_id()] = pickledSession; this._outboundGroupSessionStore[session.session_id()] = pickledSession;
}; };
@@ -492,12 +504,12 @@ OlmDevice.prototype._saveOutboundGroupSession = function(session) {
* @private * @private
*/ */
OlmDevice.prototype._getOutboundGroupSession = function(sessionId, func) { OlmDevice.prototype._getOutboundGroupSession = function(sessionId, func) {
let pickled = this._outboundGroupSessionStore[sessionId]; const pickled = this._outboundGroupSessionStore[sessionId];
if (pickled === null) { if (pickled === null) {
throw new Error("Unknown outbound group session " + sessionId); throw new Error("Unknown outbound group session " + sessionId);
} }
let session = new Olm.OutboundGroupSession(); const session = new Olm.OutboundGroupSession();
try { try {
session.unpickle(this._pickleKey, pickled); session.unpickle(this._pickleKey, pickled);
return func(session); return func(session);
@@ -513,7 +525,7 @@ OlmDevice.prototype._getOutboundGroupSession = function(sessionId, func) {
* @return {string} sessionId for the outbound session. * @return {string} sessionId for the outbound session.
*/ */
OlmDevice.prototype.createOutboundGroupSession = function() { OlmDevice.prototype.createOutboundGroupSession = function() {
let session = new Olm.OutboundGroupSession(); const session = new Olm.OutboundGroupSession();
try { try {
session.create(); session.create();
this._saveOutboundGroupSession(session); this._saveOutboundGroupSession(session);
@@ -533,12 +545,12 @@ OlmDevice.prototype.createOutboundGroupSession = function() {
* @return {string} ciphertext * @return {string} ciphertext
*/ */
OlmDevice.prototype.encryptGroupMessage = function(sessionId, payloadString) { OlmDevice.prototype.encryptGroupMessage = function(sessionId, payloadString) {
let self = this; const self = this;
checkPayloadLength(payloadString); checkPayloadLength(payloadString);
return this._getOutboundGroupSession(sessionId, function(session) { return this._getOutboundGroupSession(sessionId, function(session) {
let res = session.encrypt(payloadString); const res = session.encrypt(payloadString);
self._saveOutboundGroupSession(session); self._saveOutboundGroupSession(session);
return res; return res;
}); });
@@ -576,16 +588,16 @@ OlmDevice.prototype.getOutboundGroupSessionKey = function(sessionId) {
* @private * @private
*/ */
OlmDevice.prototype._saveInboundGroupSession = function( OlmDevice.prototype._saveInboundGroupSession = function(
roomId, senderCurve25519Key, sessionId, session, keysClaimed roomId, senderCurve25519Key, sessionId, session, keysClaimed,
) { ) {
let r = { const r = {
room_id: roomId, room_id: roomId,
session: session.pickle(this._pickleKey), session: session.pickle(this._pickleKey),
keysClaimed: keysClaimed, keysClaimed: keysClaimed,
}; };
this._sessionStore.storeEndToEndInboundGroupSession( this._sessionStore.storeEndToEndInboundGroupSession(
senderCurve25519Key, sessionId, JSON.stringify(r) senderCurve25519Key, sessionId, JSON.stringify(r),
); );
}; };
@@ -606,10 +618,10 @@ OlmDevice.prototype._saveInboundGroupSession = function(
* @template {T} * @template {T}
*/ */
OlmDevice.prototype._getInboundGroupSession = function( OlmDevice.prototype._getInboundGroupSession = function(
roomId, senderKey, sessionId, func roomId, senderKey, sessionId, func,
) { ) {
let r = this._sessionStore.getEndToEndInboundGroupSession( let r = this._sessionStore.getEndToEndInboundGroupSession(
senderKey, sessionId senderKey, sessionId,
); );
if (r === null) { if (r === null) {
@@ -623,11 +635,11 @@ OlmDevice.prototype._getInboundGroupSession = function(
if (roomId !== r.room_id) { if (roomId !== r.room_id) {
throw new Error( throw new Error(
"Mismatched room_id for inbound group session (expected " + r.room_id + "Mismatched room_id for inbound group session (expected " + r.room_id +
", was " + roomId + ")" ", was " + roomId + ")",
); );
} }
let session = new Olm.InboundGroupSession(); const session = new Olm.InboundGroupSession();
try { try {
session.unpickle(this._pickleKey, r.session); session.unpickle(this._pickleKey, r.session);
return func(session, r.keysClaimed || {}); return func(session, r.keysClaimed || {});
@@ -646,9 +658,9 @@ OlmDevice.prototype._getInboundGroupSession = function(
* @param {Object<string, string>} keysClaimed Other keys the sender claims. * @param {Object<string, string>} keysClaimed Other keys the sender claims.
*/ */
OlmDevice.prototype.addInboundGroupSession = function( OlmDevice.prototype.addInboundGroupSession = function(
roomId, senderKey, sessionId, sessionKey, keysClaimed roomId, senderKey, sessionId, sessionKey, keysClaimed,
) { ) {
let self = this; const self = this;
/* if we already have this session, consider updating it */ /* if we already have this session, consider updating it */
function updateSession(session) { function updateSession(session) {
@@ -658,8 +670,8 @@ OlmDevice.prototype.addInboundGroupSession = function(
return true; return true;
} }
let r = this._getInboundGroupSession( const r = this._getInboundGroupSession(
roomId, senderKey, sessionId, updateSession roomId, senderKey, sessionId, updateSession,
); );
if (r !== null) { if (r !== null) {
@@ -667,16 +679,58 @@ OlmDevice.prototype.addInboundGroupSession = function(
} }
// new session. // new session.
let session = new Olm.InboundGroupSession(); const session = new Olm.InboundGroupSession();
try { try {
session.create(sessionKey); session.create(sessionKey);
if (sessionId != session.session_id()) { if (sessionId != session.session_id()) {
throw new Error( throw new Error(
"Mismatched group session ID from senderKey: " + senderKey "Mismatched group session ID from senderKey: " + senderKey,
); );
} }
self._saveInboundGroupSession( self._saveInboundGroupSession(
roomId, senderKey, sessionId, session, keysClaimed roomId, senderKey, sessionId, session, keysClaimed,
);
} finally {
session.free();
}
};
/**
* Add a previously-exported inbound group session to the session store
*
* @param {module:crypto/OlmDevice.MegolmSessionData} data session data
*/
OlmDevice.prototype.importInboundGroupSession = function(data) {
/* if we already have this session, consider updating it */
function updateSession(session) {
console.log("Update for megolm session " + data.sender_key + "|" +
data.session_id);
// for now we just ignore updates. TODO: implement something here
return true;
}
const r = this._getInboundGroupSession(
data.room_id, data.sender_key, data.session_id, updateSession,
);
if (r !== null) {
return;
}
// new session.
const session = new Olm.InboundGroupSession();
try {
session.import_session(data.session_key);
if (data.session_id != session.session_id()) {
throw new Error(
"Mismatched group session ID from senderKey: " + data.sender_key,
);
}
this._saveInboundGroupSession(
data.room_id, data.sender_key, data.session_id, session,
data.sender_claimed_keys,
); );
} finally { } finally {
session.free(); session.free();
@@ -697,12 +751,12 @@ OlmDevice.prototype.addInboundGroupSession = function(
* Object<string, string>}} result * Object<string, string>}} result
*/ */
OlmDevice.prototype.decryptGroupMessage = function( OlmDevice.prototype.decryptGroupMessage = function(
roomId, senderKey, sessionId, body roomId, senderKey, sessionId, body,
) { ) {
let self = this; const self = this;
function decrypt(session, keysClaimed) { function decrypt(session, keysClaimed) {
let res = session.decrypt(body); const res = session.decrypt(body);
let plaintext = res.plaintext; let plaintext = res.plaintext;
if (plaintext === undefined) { if (plaintext === undefined) {
@@ -710,11 +764,11 @@ OlmDevice.prototype.decryptGroupMessage = function(
plaintext = res; plaintext = res;
} else { } else {
// Check if we have seen this message index before to detect replay attacks. // Check if we have seen this message index before to detect replay attacks.
let messageIndexKey = senderKey + "|" + sessionId + "|" + res.message_index; const messageIndexKey = senderKey + "|" + sessionId + "|" + res.message_index;
if (messageIndexKey in self._inboundGroupSessionMessageIndexes) { if (messageIndexKey in self._inboundGroupSessionMessageIndexes) {
throw new Error( throw new Error(
"Duplicate message index, possible replay attack: " + "Duplicate message index, possible replay attack: " +
messageIndexKey messageIndexKey,
); );
} }
self._inboundGroupSessionMessageIndexes[messageIndexKey] = true; self._inboundGroupSessionMessageIndexes[messageIndexKey] = true;
@@ -722,10 +776,10 @@ OlmDevice.prototype.decryptGroupMessage = function(
// the sender must have had the senderKey to persuade us to save the // the sender must have had the senderKey to persuade us to save the
// session. // session.
let keysProved = {curve25519: senderKey}; const keysProved = {curve25519: senderKey};
self._saveInboundGroupSession( self._saveInboundGroupSession(
roomId, senderKey, sessionId, session, keysClaimed roomId, senderKey, sessionId, session, keysClaimed,
); );
return { return {
result: plaintext, result: plaintext,
@@ -735,10 +789,45 @@ OlmDevice.prototype.decryptGroupMessage = function(
} }
return this._getInboundGroupSession( return this._getInboundGroupSession(
roomId, senderKey, sessionId, decrypt roomId, senderKey, sessionId, decrypt,
); );
}; };
/**
* Export an inbound group session
*
* @param {string} senderKey base64-encoded curve25519 key of the sender
* @param {string} sessionId session identifier
* @return {module:crypto/OlmDevice.MegolmSessionData} exported session data
*/
OlmDevice.prototype.exportInboundGroupSession = function(senderKey, sessionId) {
const s = this._sessionStore.getEndToEndInboundGroupSession(
senderKey, sessionId,
);
if (s === null) {
throw new Error("Unknown inbound group session [" + senderKey + "," +
sessionId + "]");
}
const r = JSON.parse(s);
const session = new Olm.InboundGroupSession();
try {
session.unpickle(this._pickleKey, r.session);
const messageIndex = session.first_known_index();
return {
"sender_key": senderKey,
"sender_claimed_keys": r.keysClaimed,
"room_id": r.room_id,
"session_id": sessionId,
"session_key": session.export_session(messageIndex),
};
} finally {
session.free();
}
};
// Utilities // Utilities
// ========= // =========
@@ -755,7 +844,7 @@ OlmDevice.prototype.decryptGroupMessage = function(
* was invalid then the message will be "OLM.BAD_MESSAGE_MAC". * was invalid then the message will be "OLM.BAD_MESSAGE_MAC".
*/ */
OlmDevice.prototype.verifySignature = function( OlmDevice.prototype.verifySignature = function(
key, message, signature key, message, signature,
) { ) {
this._getUtility(function(util) { this._getUtility(function(util) {
util.ed25519_verify(key, message, signature); util.ed25519_verify(key, message, signature);

View File

@@ -20,7 +20,7 @@ limitations under the License.
* *
* @module crypto/algorithms/base * @module crypto/algorithms/base
*/ */
let utils = require("../../utils"); const utils = require("../../utils");
/** /**
* map of registered encryption algorithm classes. A map from string to {@link * map of registered encryption algorithm classes. A map from string to {@link
@@ -53,7 +53,7 @@ module.exports.DECRYPTION_CLASSES = {};
* @param {string} params.roomId The ID of the room we will be sending to * @param {string} params.roomId The ID of the room we will be sending to
* @param {object} params.config The body of the m.room.encryption event * @param {object} params.config The body of the m.room.encryption event
*/ */
let EncryptionAlgorithm = function(params) { const EncryptionAlgorithm = function(params) {
this._userId = params.userId; this._userId = params.userId;
this._deviceId = params.deviceId; this._deviceId = params.deviceId;
this._crypto = params.crypto; this._crypto = params.crypto;
@@ -85,7 +85,7 @@ module.exports.EncryptionAlgorithm = EncryptionAlgorithm;
* @param {string=} oldMembership previous membership * @param {string=} oldMembership previous membership
*/ */
EncryptionAlgorithm.prototype.onRoomMembership = function( EncryptionAlgorithm.prototype.onRoomMembership = function(
event, member, oldMembership event, member, oldMembership,
) {}; ) {};
/** /**
@@ -101,7 +101,7 @@ EncryptionAlgorithm.prototype.onRoomMembership = function(
* @param {string=} params.roomId The ID of the room we will be receiving * @param {string=} params.roomId The ID of the room we will be receiving
* from. Null for to-device events. * from. Null for to-device events.
*/ */
let DecryptionAlgorithm = function(params) { const DecryptionAlgorithm = function(params) {
this._userId = params.userId; this._userId = params.userId;
this._crypto = params.crypto; this._crypto = params.crypto;
this._olmDevice = params.olmDevice; this._olmDevice = params.olmDevice;
@@ -136,6 +136,15 @@ DecryptionAlgorithm.prototype.onRoomKeyEvent = function(params) {
// ignore by default // ignore by default
}; };
/**
* Import a room key
*
* @param {module:crypto/OlmDevice.MegolmSessionData} session
*/
DecryptionAlgorithm.prototype.importRoomKey = function(session) {
// ignore by default
};
/** /**
* Exception thrown when decryption fails * Exception thrown when decryption fails
* *

View File

@@ -19,7 +19,7 @@ limitations under the License.
* @module crypto/algorithms * @module crypto/algorithms
*/ */
let base = require("./base"); const base = require("./base");
require("./olm"); require("./olm");
require("./megolm"); require("./megolm");

View File

@@ -21,11 +21,11 @@ limitations under the License.
* @module crypto/algorithms/megolm * @module crypto/algorithms/megolm
*/ */
let q = require("q"); const q = require("q");
let utils = require("../../utils"); const utils = require("../../utils");
let olmlib = require("../olmlib"); const olmlib = require("../olmlib");
let base = require("./base"); const base = require("./base");
/** /**
* @private * @private
@@ -57,16 +57,16 @@ function OutboundSessionInfo(sessionId) {
* @return {Boolean} * @return {Boolean}
*/ */
OutboundSessionInfo.prototype.needsRotation = function( OutboundSessionInfo.prototype.needsRotation = function(
rotationPeriodMsgs, rotationPeriodMs rotationPeriodMsgs, rotationPeriodMs,
) { ) {
let sessionLifetime = new Date().getTime() - this.creationTime; const sessionLifetime = new Date().getTime() - this.creationTime;
if (this.useCount >= rotationPeriodMsgs || if (this.useCount >= rotationPeriodMsgs ||
sessionLifetime >= rotationPeriodMs sessionLifetime >= rotationPeriodMs
) { ) {
console.log( console.log(
"Rotating megolm session after " + this.useCount + "Rotating megolm session after " + this.useCount +
" messages, " + sessionLifetime + "ms" " messages, " + sessionLifetime + "ms",
); );
return true; return true;
} }
@@ -86,9 +86,9 @@ OutboundSessionInfo.prototype.needsRotation = function(
* in devicesInRoom. * in devicesInRoom.
*/ */
OutboundSessionInfo.prototype.sharedWithTooManyDevices = function( OutboundSessionInfo.prototype.sharedWithTooManyDevices = function(
devicesInRoom devicesInRoom,
) { ) {
for (let userId in this.sharedWithDevices) { for (const userId in this.sharedWithDevices) {
if (!this.sharedWithDevices.hasOwnProperty(userId)) { if (!this.sharedWithDevices.hasOwnProperty(userId)) {
continue; continue;
} }
@@ -98,7 +98,7 @@ OutboundSessionInfo.prototype.sharedWithTooManyDevices = function(
return true; return true;
} }
for (let deviceId in this.sharedWithDevices[userId]) { for (const deviceId in this.sharedWithDevices[userId]) {
if (!this.sharedWithDevices[userId].hasOwnProperty(deviceId)) { if (!this.sharedWithDevices[userId].hasOwnProperty(deviceId)) {
continue; continue;
} }
@@ -106,7 +106,7 @@ OutboundSessionInfo.prototype.sharedWithTooManyDevices = function(
if (!devicesInRoom[userId].hasOwnProperty(deviceId)) { if (!devicesInRoom[userId].hasOwnProperty(deviceId)) {
console.log( console.log(
"Starting new session because we shared with " + "Starting new session because we shared with " +
userId + ":" + deviceId userId + ":" + deviceId,
); );
return true; return true;
} }
@@ -157,7 +157,7 @@ utils.inherits(MegolmEncryption, base.EncryptionAlgorithm);
* OutboundSessionInfo when setup is complete. * OutboundSessionInfo when setup is complete.
*/ */
MegolmEncryption.prototype._ensureOutboundSession = function(devicesInRoom) { MegolmEncryption.prototype._ensureOutboundSession = function(devicesInRoom) {
let self = this; const self = this;
let session; let session;
@@ -187,23 +187,23 @@ MegolmEncryption.prototype._ensureOutboundSession = function(devicesInRoom) {
} }
// now check if we need to share with any devices // now check if we need to share with any devices
let shareMap = {}; const shareMap = {};
for (let userId in devicesInRoom) { for (const userId in devicesInRoom) {
if (!devicesInRoom.hasOwnProperty(userId)) { if (!devicesInRoom.hasOwnProperty(userId)) {
continue; continue;
} }
let userDevices = devicesInRoom[userId]; const userDevices = devicesInRoom[userId];
for (let deviceId in userDevices) { for (const deviceId in userDevices) {
if (!userDevices.hasOwnProperty(deviceId)) { if (!userDevices.hasOwnProperty(deviceId)) {
continue; continue;
} }
let deviceInfo = userDevices[deviceId]; const deviceInfo = userDevices[deviceId];
let key = deviceInfo.getIdentityKey(); const key = deviceInfo.getIdentityKey();
if (key == self._olmDevice.deviceCurve25519Key) { if (key == self._olmDevice.deviceCurve25519Key) {
// don't bother sending to ourself // don't bother sending to ourself
continue; continue;
@@ -220,7 +220,7 @@ MegolmEncryption.prototype._ensureOutboundSession = function(devicesInRoom) {
} }
return self._shareKeyWithDevices( return self._shareKeyWithDevices(
session, shareMap session, shareMap,
); );
} }
@@ -230,7 +230,7 @@ MegolmEncryption.prototype._ensureOutboundSession = function(devicesInRoom) {
} }
// first wait for the previous share to complete // first wait for the previous share to complete
let prom = this._setupPromise.then(prepareSession); const prom = this._setupPromise.then(prepareSession);
// _setupPromise resolves to `session` whether or not the share succeeds // _setupPromise resolves to `session` whether or not the share succeeds
this._setupPromise = prom.then(returnSession, returnSession); this._setupPromise = prom.then(returnSession, returnSession);
@@ -245,12 +245,12 @@ MegolmEncryption.prototype._ensureOutboundSession = function(devicesInRoom) {
* @return {module:crypto/algorithms/megolm.OutboundSessionInfo} session * @return {module:crypto/algorithms/megolm.OutboundSessionInfo} session
*/ */
MegolmEncryption.prototype._prepareNewSession = function() { MegolmEncryption.prototype._prepareNewSession = function() {
let session_id = this._olmDevice.createOutboundGroupSession(); const session_id = this._olmDevice.createOutboundGroupSession();
let key = this._olmDevice.getOutboundGroupSessionKey(session_id); const key = this._olmDevice.getOutboundGroupSessionKey(session_id);
this._olmDevice.addInboundGroupSession( this._olmDevice.addInboundGroupSession(
this._roomId, this._olmDevice.deviceCurve25519Key, session_id, this._roomId, this._olmDevice.deviceCurve25519Key, session_id,
key.key, {ed25519: this._olmDevice.deviceEd25519Key} key.key, {ed25519: this._olmDevice.deviceEd25519Key},
); );
return new OutboundSessionInfo(session_id); return new OutboundSessionInfo(session_id);
@@ -268,10 +268,10 @@ MegolmEncryption.prototype._prepareNewSession = function() {
* message has been sent. * message has been sent.
*/ */
MegolmEncryption.prototype._shareKeyWithDevices = function(session, devicesByUser) { MegolmEncryption.prototype._shareKeyWithDevices = function(session, devicesByUser) {
let self = this; const self = this;
let key = this._olmDevice.getOutboundGroupSessionKey(session.sessionId); const key = this._olmDevice.getOutboundGroupSessionKey(session.sessionId);
let payload = { const payload = {
type: "m.room_key", type: "m.room_key",
content: { content: {
algorithm: olmlib.MEGOLM_ALGORITHM, algorithm: olmlib.MEGOLM_ALGORITHM,
@@ -282,26 +282,26 @@ MegolmEncryption.prototype._shareKeyWithDevices = function(session, devicesByUse
}, },
}; };
let contentMap = {}; const contentMap = {};
return olmlib.ensureOlmSessionsForDevices( return olmlib.ensureOlmSessionsForDevices(
this._olmDevice, this._baseApis, devicesByUser this._olmDevice, this._baseApis, devicesByUser,
).then(function(devicemap) { ).then(function(devicemap) {
let haveTargets = false; let haveTargets = false;
for (let userId in devicesByUser) { for (const userId in devicesByUser) {
if (!devicesByUser.hasOwnProperty(userId)) { if (!devicesByUser.hasOwnProperty(userId)) {
continue; continue;
} }
let devicesToShareWith = devicesByUser[userId]; const devicesToShareWith = devicesByUser[userId];
let sessionResults = devicemap[userId]; const sessionResults = devicemap[userId];
for (let i = 0; i < devicesToShareWith.length; i++) { for (let i = 0; i < devicesToShareWith.length; i++) {
let deviceInfo = devicesToShareWith[i]; const deviceInfo = devicesToShareWith[i];
let deviceId = deviceInfo.deviceId; const deviceId = deviceInfo.deviceId;
let sessionResult = sessionResults[deviceId]; const sessionResult = sessionResults[deviceId];
if (!sessionResult.sessionId) { if (!sessionResult.sessionId) {
// no session with this device, probably because there // no session with this device, probably because there
// were no one-time keys. // were no one-time keys.
@@ -318,10 +318,10 @@ MegolmEncryption.prototype._shareKeyWithDevices = function(session, devicesByUse
} }
console.log( console.log(
"sharing keys with device " + userId + ":" + deviceId "sharing keys with device " + userId + ":" + deviceId,
); );
let encryptedContent = { const encryptedContent = {
algorithm: olmlib.OLM_ALGORITHM, algorithm: olmlib.OLM_ALGORITHM,
sender_key: self._olmDevice.deviceCurve25519Key, sender_key: self._olmDevice.deviceCurve25519Key,
ciphertext: {}, ciphertext: {},
@@ -334,7 +334,7 @@ MegolmEncryption.prototype._shareKeyWithDevices = function(session, devicesByUse
self._olmDevice, self._olmDevice,
userId, userId,
deviceInfo, deviceInfo,
payload payload,
); );
if (!contentMap[userId]) { if (!contentMap[userId]) {
@@ -359,16 +359,16 @@ MegolmEncryption.prototype._shareKeyWithDevices = function(session, devicesByUse
// attempted to share with) rather than the contentMap (those we did // attempted to share with) rather than the contentMap (those we did
// share with), because we don't want to try to claim a one-time-key // share with), because we don't want to try to claim a one-time-key
// for dead devices on every message. // for dead devices on every message.
for (let userId in devicesByUser) { for (const userId in devicesByUser) {
if (!devicesByUser.hasOwnProperty(userId)) { if (!devicesByUser.hasOwnProperty(userId)) {
continue; continue;
} }
if (!session.sharedWithDevices[userId]) { if (!session.sharedWithDevices[userId]) {
session.sharedWithDevices[userId] = {}; session.sharedWithDevices[userId] = {};
} }
let devicesToShareWith = devicesByUser[userId]; const devicesToShareWith = devicesByUser[userId];
for (let i = 0; i < devicesToShareWith.length; i++) { for (let i = 0; i < devicesToShareWith.length; i++) {
let deviceInfo = devicesToShareWith[i]; const deviceInfo = devicesToShareWith[i];
session.sharedWithDevices[userId][deviceInfo.deviceId] = session.sharedWithDevices[userId][deviceInfo.deviceId] =
key.chain_index; key.chain_index;
} }
@@ -386,21 +386,21 @@ MegolmEncryption.prototype._shareKeyWithDevices = function(session, devicesByUse
* @return {module:client.Promise} Promise which resolves to the new event body * @return {module:client.Promise} Promise which resolves to the new event body
*/ */
MegolmEncryption.prototype.encryptMessage = function(room, eventType, content) { MegolmEncryption.prototype.encryptMessage = function(room, eventType, content) {
let self = this; const self = this;
return this._getDevicesInRoom(room).then(function(devicesInRoom) { return this._getDevicesInRoom(room).then(function(devicesInRoom) {
return self._ensureOutboundSession(devicesInRoom); return self._ensureOutboundSession(devicesInRoom);
}).then(function(session) { }).then(function(session) {
let payloadJson = { const payloadJson = {
room_id: self._roomId, room_id: self._roomId,
type: eventType, type: eventType,
content: content, content: content,
}; };
let ciphertext = self._olmDevice.encryptGroupMessage( const ciphertext = self._olmDevice.encryptGroupMessage(
session.sessionId, JSON.stringify(payloadJson) session.sessionId, JSON.stringify(payloadJson),
); );
let encryptedContent = { const encryptedContent = {
algorithm: olmlib.MEGOLM_ALGORITHM, algorithm: olmlib.MEGOLM_ALGORITHM,
sender_key: self._olmDevice.deviceCurve25519Key, sender_key: self._olmDevice.deviceCurve25519Key,
ciphertext: ciphertext, ciphertext: ciphertext,
@@ -425,7 +425,7 @@ MegolmEncryption.prototype.encryptMessage = function(room, eventType, content) {
*/ */
MegolmEncryption.prototype._getDevicesInRoom = function(room) { MegolmEncryption.prototype._getDevicesInRoom = function(room) {
// XXX what about rooms where invitees can see the content? // XXX what about rooms where invitees can see the content?
let roomMembers = utils.map(room.getJoinedMembers(), function(u) { const roomMembers = utils.map(room.getJoinedMembers(), function(u) {
return u.userId; return u.userId;
}); });
@@ -435,13 +435,13 @@ MegolmEncryption.prototype._getDevicesInRoom = function(room) {
// an m.new_device. // an m.new_device.
return this._crypto.downloadKeys(roomMembers, false).then(function(devices) { return this._crypto.downloadKeys(roomMembers, false).then(function(devices) {
// remove any blocked devices // remove any blocked devices
for (let userId in devices) { for (const userId in devices) {
if (!devices.hasOwnProperty(userId)) { if (!devices.hasOwnProperty(userId)) {
continue; continue;
} }
let userDevices = devices[userId]; const userDevices = devices[userId];
for (let deviceId in userDevices) { for (const deviceId in userDevices) {
if (!userDevices.hasOwnProperty(deviceId)) { if (!userDevices.hasOwnProperty(deviceId)) {
continue; continue;
} }
@@ -482,7 +482,7 @@ utils.inherits(MegolmDecryption, base.DecryptionAlgorithm);
* problem decrypting the event * problem decrypting the event
*/ */
MegolmDecryption.prototype.decryptEvent = function(event) { MegolmDecryption.prototype.decryptEvent = function(event) {
let content = event.getWireContent(); const content = event.getWireContent();
if (!content.sender_key || !content.session_id || if (!content.sender_key || !content.session_id ||
!content.ciphertext !content.ciphertext
@@ -493,7 +493,7 @@ MegolmDecryption.prototype.decryptEvent = function(event) {
let res; let res;
try { try {
res = this._olmDevice.decryptGroupMessage( res = this._olmDevice.decryptGroupMessage(
event.getRoomId(), content.sender_key, content.session_id, content.ciphertext event.getRoomId(), content.sender_key, content.session_id, content.ciphertext,
); );
} catch (e) { } catch (e) {
if (e.message === 'OLM.UNKNOWN_MESSAGE_INDEX') { if (e.message === 'OLM.UNKNOWN_MESSAGE_INDEX') {
@@ -506,18 +506,18 @@ MegolmDecryption.prototype.decryptEvent = function(event) {
// We've got a message for a session we don't have. // We've got a message for a session we don't have.
this._addEventToPendingList(event); this._addEventToPendingList(event);
throw new base.DecryptionError( throw new base.DecryptionError(
"The sender's device has not sent us the keys for this message." "The sender's device has not sent us the keys for this message.",
); );
} }
let payload = JSON.parse(res.result); const payload = JSON.parse(res.result);
// belt-and-braces check that the room id matches that indicated by the HS // belt-and-braces check that the room id matches that indicated by the HS
// (this is somewhat redundant, since the megolm session is scoped to the // (this is somewhat redundant, since the megolm session is scoped to the
// room, so neither the sender nor a MITM can lie about the room_id). // room, so neither the sender nor a MITM can lie about the room_id).
if (payload.room_id !== event.getRoomId()) { if (payload.room_id !== event.getRoomId()) {
throw new base.DecryptionError( throw new base.DecryptionError(
"Message intended for room " + payload.room_id "Message intended for room " + payload.room_id,
); );
} }
@@ -534,8 +534,8 @@ MegolmDecryption.prototype.decryptEvent = function(event) {
* @param {module:models/event.MatrixEvent} event * @param {module:models/event.MatrixEvent} event
*/ */
MegolmDecryption.prototype._addEventToPendingList = function(event) { MegolmDecryption.prototype._addEventToPendingList = function(event) {
let content = event.getWireContent(); const content = event.getWireContent();
let k = content.sender_key + "|" + content.session_id; const k = content.sender_key + "|" + content.session_id;
if (!this._pendingEvents[k]) { if (!this._pendingEvents[k]) {
this._pendingEvents[k] = []; this._pendingEvents[k] = [];
} }
@@ -549,7 +549,7 @@ MegolmDecryption.prototype._addEventToPendingList = function(event) {
*/ */
MegolmDecryption.prototype.onRoomKeyEvent = function(event) { MegolmDecryption.prototype.onRoomKeyEvent = function(event) {
console.log("Adding key from ", event); console.log("Adding key from ", event);
let content = event.getContent(); const content = event.getContent();
if (!content.room_id || if (!content.room_id ||
!content.session_id || !content.session_id ||
@@ -561,13 +561,40 @@ MegolmDecryption.prototype.onRoomKeyEvent = function(event) {
this._olmDevice.addInboundGroupSession( this._olmDevice.addInboundGroupSession(
content.room_id, event.getSenderKey(), content.session_id, content.room_id, event.getSenderKey(), content.session_id,
content.session_key, event.getKeysClaimed() content.session_key, event.getKeysClaimed(),
); );
let k = event.getSenderKey() + "|" + content.session_id;
let pending = this._pendingEvents[k];
if (pending) {
// have another go at decrypting events sent with this session. // have another go at decrypting events sent with this session.
this._retryDecryption(event.getSenderKey, content.session_id);
};
/**
* @inheritdoc
*
* @param {module:crypto/OlmDevice.MegolmSessionData} session
*/
MegolmDecryption.prototype.importRoomKey = function(session) {
this._olmDevice.importInboundGroupSession(session);
// have another go at decrypting events sent with this session.
this._retryDecryption(session.sender_key, session.session_id);
};
/**
* Have another go at decrypting events after we receive a key
*
* @private
* @param {String} senderKey
* @param {String} sessionId
*/
MegolmDecryption.prototype._retryDecryption = function(senderKey, sessionId) {
const k = senderKey + "|" + sessionId;
const pending = this._pendingEvents[k];
if (!pending) {
return;
}
delete this._pendingEvents[k]; delete this._pendingEvents[k];
for (let i = 0; i < pending.length; i++) { for (let i = 0; i < pending.length; i++) {
@@ -578,9 +605,8 @@ MegolmDecryption.prototype.onRoomKeyEvent = function(event) {
console.log("Still can't decrypt", pending[i], e.stack || e); console.log("Still can't decrypt", pending[i], e.stack || e);
} }
} }
}
}; };
base.registerAlgorithm( base.registerAlgorithm(
olmlib.MEGOLM_ALGORITHM, MegolmEncryption, MegolmDecryption olmlib.MEGOLM_ALGORITHM, MegolmEncryption, MegolmDecryption,
); );

View File

@@ -20,15 +20,15 @@ limitations under the License.
* *
* @module crypto/algorithms/olm * @module crypto/algorithms/olm
*/ */
let q = require('q'); const q = require('q');
let utils = require("../../utils"); const utils = require("../../utils");
let olmlib = require("../olmlib"); const olmlib = require("../olmlib");
let DeviceInfo = require("../deviceinfo"); const DeviceInfo = require("../deviceinfo");
let DeviceVerification = DeviceInfo.DeviceVerification; const DeviceVerification = DeviceInfo.DeviceVerification;
let base = require("./base"); const base = require("./base");
/** /**
* Olm encryption implementation * Olm encryption implementation
@@ -63,7 +63,7 @@ OlmEncryption.prototype._ensureSession = function(roomMembers) {
return q(); return q();
} }
let self = this; const self = this;
this._prepPromise = self._crypto.downloadKeys(roomMembers, true).then(function(res) { this._prepPromise = self._crypto.downloadKeys(roomMembers, true).then(function(res) {
return self._crypto.ensureOlmSessionsForUsers(roomMembers); return self._crypto.ensureOlmSessionsForUsers(roomMembers);
}).then(function() { }).then(function() {
@@ -89,31 +89,31 @@ OlmEncryption.prototype.encryptMessage = function(room, eventType, content) {
// TODO: there is a race condition here! What if a new user turns up // TODO: there is a race condition here! What if a new user turns up
// just as you are sending a secret message? // just as you are sending a secret message?
let users = utils.map(room.getJoinedMembers(), function(u) { const users = utils.map(room.getJoinedMembers(), function(u) {
return u.userId; return u.userId;
}); });
let self = this; const self = this;
return this._ensureSession(users).then(function() { return this._ensureSession(users).then(function() {
let payloadFields = { const payloadFields = {
room_id: room.roomId, room_id: room.roomId,
type: eventType, type: eventType,
content: content, content: content,
}; };
let encryptedContent = { const encryptedContent = {
algorithm: olmlib.OLM_ALGORITHM, algorithm: olmlib.OLM_ALGORITHM,
sender_key: self._olmDevice.deviceCurve25519Key, sender_key: self._olmDevice.deviceCurve25519Key,
ciphertext: {}, ciphertext: {},
}; };
for (let i = 0; i < users.length; ++i) { for (let i = 0; i < users.length; ++i) {
let userId = users[i]; const userId = users[i];
let devices = self._crypto.getStoredDevicesForUser(userId); const devices = self._crypto.getStoredDevicesForUser(userId);
for (let j = 0; j < devices.length; ++j) { for (let j = 0; j < devices.length; ++j) {
let deviceInfo = devices[j]; const deviceInfo = devices[j];
let key = deviceInfo.getIdentityKey(); const key = deviceInfo.getIdentityKey();
if (key == self._olmDevice.deviceCurve25519Key) { if (key == self._olmDevice.deviceCurve25519Key) {
// don't bother sending to ourself // don't bother sending to ourself
continue; continue;
@@ -126,7 +126,7 @@ OlmEncryption.prototype.encryptMessage = function(room, eventType, content) {
olmlib.encryptMessageForDevice( olmlib.encryptMessageForDevice(
encryptedContent.ciphertext, encryptedContent.ciphertext,
self._userId, self._deviceId, self._olmDevice, self._userId, self._deviceId, self._olmDevice,
userId, deviceInfo, payloadFields userId, deviceInfo, payloadFields,
); );
} }
} }
@@ -157,9 +157,9 @@ utils.inherits(OlmDecryption, base.DecryptionAlgorithm);
* problem decrypting the event * problem decrypting the event
*/ */
OlmDecryption.prototype.decryptEvent = function(event) { OlmDecryption.prototype.decryptEvent = function(event) {
let content = event.getWireContent(); const content = event.getWireContent();
let deviceKey = content.sender_key; const deviceKey = content.sender_key;
let ciphertext = content.ciphertext; const ciphertext = content.ciphertext;
if (!ciphertext) { if (!ciphertext) {
throw new base.DecryptionError("Missing ciphertext"); throw new base.DecryptionError("Missing ciphertext");
@@ -168,7 +168,7 @@ OlmDecryption.prototype.decryptEvent = function(event) {
if (!(this._olmDevice.deviceCurve25519Key in ciphertext)) { if (!(this._olmDevice.deviceCurve25519Key in ciphertext)) {
throw new base.DecryptionError("Not included in recipients"); throw new base.DecryptionError("Not included in recipients");
} }
let message = ciphertext[this._olmDevice.deviceCurve25519Key]; const message = ciphertext[this._olmDevice.deviceCurve25519Key];
let payloadString; let payloadString;
try { try {
@@ -177,22 +177,22 @@ OlmDecryption.prototype.decryptEvent = function(event) {
console.warn( console.warn(
"Failed to decrypt Olm event (id=" + "Failed to decrypt Olm event (id=" +
event.getId() + ") from " + deviceKey + event.getId() + ") from " + deviceKey +
": " + e.message ": " + e.message,
); );
throw new base.DecryptionError("Bad Encrypted Message"); throw new base.DecryptionError("Bad Encrypted Message");
} }
let payload = JSON.parse(payloadString); const payload = JSON.parse(payloadString);
// check that we were the intended recipient, to avoid unknown-key attack // check that we were the intended recipient, to avoid unknown-key attack
// https://github.com/vector-im/vector-web/issues/2483 // https://github.com/vector-im/vector-web/issues/2483
if (payload.recipient != this._userId) { if (payload.recipient != this._userId) {
console.warn( console.warn(
"Event " + event.getId() + ": Intended recipient " + "Event " + event.getId() + ": Intended recipient " +
payload.recipient + " does not match our id " + this._userId payload.recipient + " does not match our id " + this._userId,
); );
throw new base.DecryptionError( throw new base.DecryptionError(
"Message was intented for " + payload.recipient "Message was intented for " + payload.recipient,
); );
} }
@@ -200,7 +200,7 @@ OlmDecryption.prototype.decryptEvent = function(event) {
this._olmDevice.deviceEd25519Key) { this._olmDevice.deviceEd25519Key) {
console.warn( console.warn(
"Event " + event.getId() + ": Intended recipient ed25519 key " + "Event " + event.getId() + ": Intended recipient ed25519 key " +
payload.recipient_keys.ed25519 + " did not match ours" payload.recipient_keys.ed25519 + " did not match ours",
); );
throw new base.DecryptionError("Message not intended for this device"); throw new base.DecryptionError("Message not intended for this device");
} }
@@ -212,10 +212,10 @@ OlmDecryption.prototype.decryptEvent = function(event) {
if (payload.sender != event.getSender()) { if (payload.sender != event.getSender()) {
console.warn( console.warn(
"Event " + event.getId() + ": original sender " + payload.sender + "Event " + event.getId() + ": original sender " + payload.sender +
" does not match reported sender " + event.getSender() " does not match reported sender " + event.getSender(),
); );
throw new base.DecryptionError( throw new base.DecryptionError(
"Message forwarded from " + payload.sender "Message forwarded from " + payload.sender,
); );
} }
@@ -223,10 +223,10 @@ OlmDecryption.prototype.decryptEvent = function(event) {
if (payload.room_id !== event.getRoomId()) { if (payload.room_id !== event.getRoomId()) {
console.warn( console.warn(
"Event " + event.getId() + ": original room " + payload.room_id + "Event " + event.getId() + ": original room " + payload.room_id +
" does not match reported room " + event.room_id " does not match reported room " + event.room_id,
); );
throw new base.DecryptionError( throw new base.DecryptionError(
"Message intended for room " + payload.room_id "Message intended for room " + payload.room_id,
); );
} }
@@ -243,24 +243,24 @@ OlmDecryption.prototype.decryptEvent = function(event) {
* @return {string} payload, if decrypted successfully. * @return {string} payload, if decrypted successfully.
*/ */
OlmDecryption.prototype._decryptMessage = function(theirDeviceIdentityKey, message) { OlmDecryption.prototype._decryptMessage = function(theirDeviceIdentityKey, message) {
let sessionIds = this._olmDevice.getSessionIdsForDevice(theirDeviceIdentityKey); const sessionIds = this._olmDevice.getSessionIdsForDevice(theirDeviceIdentityKey);
// try each session in turn. // try each session in turn.
let decryptionErrors = {}; const decryptionErrors = {};
for (let i = 0; i < sessionIds.length; i++) { for (let i = 0; i < sessionIds.length; i++) {
let sessionId = sessionIds[i]; const sessionId = sessionIds[i];
try { try {
let payload = this._olmDevice.decryptMessage( const payload = this._olmDevice.decryptMessage(
theirDeviceIdentityKey, sessionId, message.type, message.body theirDeviceIdentityKey, sessionId, message.type, message.body,
); );
console.log( console.log(
"Decrypted Olm message from " + theirDeviceIdentityKey + "Decrypted Olm message from " + theirDeviceIdentityKey +
" with session " + sessionId " with session " + sessionId,
); );
return payload; return payload;
} catch (e) { } catch (e) {
let foundSession = this._olmDevice.matchesSession( const foundSession = this._olmDevice.matchesSession(
theirDeviceIdentityKey, sessionId, message.type, message.body theirDeviceIdentityKey, sessionId, message.type, message.body,
); );
if (foundSession) { if (foundSession) {
@@ -268,7 +268,7 @@ OlmDecryption.prototype._decryptMessage = function(theirDeviceIdentityKey, messa
// session, so it should have worked. // session, so it should have worked.
throw new Error( throw new Error(
"Error decrypting prekey message with existing session id " + "Error decrypting prekey message with existing session id " +
sessionId + ": " + e.message sessionId + ": " + e.message,
); );
} }
@@ -288,7 +288,7 @@ OlmDecryption.prototype._decryptMessage = function(theirDeviceIdentityKey, messa
throw new Error( throw new Error(
"Error decrypting non-prekey message with existing sessions: " + "Error decrypting non-prekey message with existing sessions: " +
JSON.stringify(decryptionErrors) JSON.stringify(decryptionErrors),
); );
} }
@@ -298,19 +298,19 @@ OlmDecryption.prototype._decryptMessage = function(theirDeviceIdentityKey, messa
let res; let res;
try { try {
res = this._olmDevice.createInboundSession( res = this._olmDevice.createInboundSession(
theirDeviceIdentityKey, message.type, message.body theirDeviceIdentityKey, message.type, message.body,
); );
} catch (e) { } catch (e) {
decryptionErrors["(new)"] = e.message; decryptionErrors["(new)"] = e.message;
throw new Error( throw new Error(
"Error decrypting prekey message: " + "Error decrypting prekey message: " +
JSON.stringify(decryptionErrors) JSON.stringify(decryptionErrors),
); );
} }
console.log( console.log(
"created new inbound Olm session ID " + "created new inbound Olm session ID " +
res.session_id + " with " + theirDeviceIdentityKey res.session_id + " with " + theirDeviceIdentityKey,
); );
return res.payload; return res.payload;
}; };

View File

@@ -62,8 +62,8 @@ function DeviceInfo(deviceId) {
* @return {module:crypto~DeviceInfo} new DeviceInfo * @return {module:crypto~DeviceInfo} new DeviceInfo
*/ */
DeviceInfo.fromStorage = function(obj, deviceId) { DeviceInfo.fromStorage = function(obj, deviceId) {
let res = new DeviceInfo(deviceId); const res = new DeviceInfo(deviceId);
for (let prop in obj) { for (const prop in obj) {
if (obj.hasOwnProperty(prop)) { if (obj.hasOwnProperty(prop)) {
res[prop] = obj[prop]; res[prop] = obj[prop];
} }
@@ -139,7 +139,7 @@ DeviceInfo.DeviceVerification = {
BLOCKED: -1, BLOCKED: -1,
}; };
let DeviceVerification = DeviceInfo.DeviceVerification; const DeviceVerification = DeviceInfo.DeviceVerification;
/** */ /** */
module.exports = DeviceInfo; module.exports = DeviceInfo;

View File

@@ -20,15 +20,15 @@ limitations under the License.
* @module crypto * @module crypto
*/ */
let anotherjson = require('another-json'); const anotherjson = require('another-json');
let q = require("q"); const q = require("q");
let utils = require("../utils"); const utils = require("../utils");
let OlmDevice = require("./OlmDevice"); const OlmDevice = require("./OlmDevice");
let olmlib = require("./olmlib"); const olmlib = require("./olmlib");
let algorithms = require("./algorithms"); const algorithms = require("./algorithms");
let DeviceInfo = require("./deviceinfo"); const DeviceInfo = require("./deviceinfo");
let DeviceVerification = DeviceInfo.DeviceVerification; const DeviceVerification = DeviceInfo.DeviceVerification;
/** /**
* Cryptography bits * Cryptography bits
@@ -69,7 +69,7 @@ function Crypto(baseApis, eventEmitter, sessionStore, userId, deviceId) {
this._roomDecryptors = {}; this._roomDecryptors = {};
this._supportedAlgorithms = utils.keys( this._supportedAlgorithms = utils.keys(
algorithms.DECRYPTION_CLASSES algorithms.DECRYPTION_CLASSES,
); );
// build our device keys: these will later be uploaded // build our device keys: these will later be uploaded
@@ -80,7 +80,7 @@ function Crypto(baseApis, eventEmitter, sessionStore, userId, deviceId) {
this._olmDevice.deviceCurve25519Key; this._olmDevice.deviceCurve25519Key;
let myDevices = this._sessionStore.getEndToEndDevicesForUser( let myDevices = this._sessionStore.getEndToEndDevicesForUser(
this._userId this._userId,
); );
if (!myDevices) { if (!myDevices) {
@@ -92,7 +92,7 @@ function Crypto(baseApis, eventEmitter, sessionStore, userId, deviceId) {
if (!myDevices[this._deviceId]) { if (!myDevices[this._deviceId]) {
// add our own deviceinfo to the sessionstore // add our own deviceinfo to the sessionstore
let deviceInfo = { const deviceInfo = {
keys: this._deviceKeys, keys: this._deviceKeys,
algorithms: this._supportedAlgorithms, algorithms: this._supportedAlgorithms,
verified: DeviceVerification.VERIFIED, verified: DeviceVerification.VERIFIED,
@@ -100,7 +100,7 @@ function Crypto(baseApis, eventEmitter, sessionStore, userId, deviceId) {
myDevices[this._deviceId] = deviceInfo; myDevices[this._deviceId] = deviceInfo;
this._sessionStore.storeEndToEndDevicesForUser( this._sessionStore.storeEndToEndDevicesForUser(
this._userId, myDevices this._userId, myDevices,
); );
} }
@@ -113,7 +113,7 @@ function _registerEventHandlers(crypto, eventEmitter) {
if (syncState == "PREPARED") { if (syncState == "PREPARED") {
// XXX ugh. we're assuming the eventEmitter is a MatrixClient. // XXX ugh. we're assuming the eventEmitter is a MatrixClient.
// how can we avoid doing so? // how can we avoid doing so?
let rooms = eventEmitter.getRooms(); const rooms = eventEmitter.getRooms();
crypto._onInitialSyncCompleted(rooms); crypto._onInitialSyncCompleted(rooms);
} }
} catch (e) { } catch (e) {
@@ -176,7 +176,7 @@ Crypto.prototype.getDeviceEd25519Key = function() {
* @return {object} A promise that will resolve when the keys are uploaded. * @return {object} A promise that will resolve when the keys are uploaded.
*/ */
Crypto.prototype.uploadKeys = function(maxKeys) { Crypto.prototype.uploadKeys = function(maxKeys) {
let self = this; const self = this;
return _uploadDeviceKeys(this).then(function(res) { return _uploadDeviceKeys(this).then(function(res) {
// We need to keep a pool of one time public keys on the server so that // We need to keep a pool of one time public keys on the server so that
// other devices can start conversations with us. But we can only store // other devices can start conversations with us. But we can only store
@@ -191,16 +191,16 @@ Crypto.prototype.uploadKeys = function(maxKeys) {
// these factors. // these factors.
// We first find how many keys the server has for us. // We first find how many keys the server has for us.
let keyCount = res.one_time_key_counts.signed_curve25519 || 0; const keyCount = res.one_time_key_counts.signed_curve25519 || 0;
// We then check how many keys we can store in the Account object. // We then check how many keys we can store in the Account object.
let maxOneTimeKeys = self._olmDevice.maxNumberOfOneTimeKeys(); const maxOneTimeKeys = self._olmDevice.maxNumberOfOneTimeKeys();
// Try to keep at most half that number on the server. This leaves the // Try to keep at most half that number on the server. This leaves the
// rest of the slots free to hold keys that have been claimed from the // rest of the slots free to hold keys that have been claimed from the
// server but we haven't recevied a message for. // server but we haven't recevied a message for.
// If we run out of slots when generating new keys then olm will // If we run out of slots when generating new keys then olm will
// discard the oldest private keys first. This will eventually clean // discard the oldest private keys first. This will eventually clean
// out stale private keys that won't receive a message. // out stale private keys that won't receive a message.
let keyLimit = Math.floor(maxOneTimeKeys / 2); const keyLimit = Math.floor(maxOneTimeKeys / 2);
// We work out how many new keys we need to create to top up the server // We work out how many new keys we need to create to top up the server
// If there are too many keys on the server then we don't need to // If there are too many keys on the server then we don't need to
// create any more keys. // create any more keys.
@@ -225,10 +225,10 @@ Crypto.prototype.uploadKeys = function(maxKeys) {
// returns a promise which resolves to the response // returns a promise which resolves to the response
function _uploadDeviceKeys(crypto) { function _uploadDeviceKeys(crypto) {
let userId = crypto._userId; const userId = crypto._userId;
let deviceId = crypto._deviceId; const deviceId = crypto._deviceId;
let deviceKeys = { const deviceKeys = {
algorithms: crypto._supportedAlgorithms, algorithms: crypto._supportedAlgorithms,
device_id: deviceId, device_id: deviceId,
keys: crypto._deviceKeys, keys: crypto._deviceKeys,
@@ -247,12 +247,12 @@ function _uploadDeviceKeys(crypto) {
// returns a promise which resolves to the response // returns a promise which resolves to the response
function _uploadOneTimeKeys(crypto) { function _uploadOneTimeKeys(crypto) {
let oneTimeKeys = crypto._olmDevice.getOneTimeKeys(); const oneTimeKeys = crypto._olmDevice.getOneTimeKeys();
let oneTimeJson = {}; const oneTimeJson = {};
for (let keyId in oneTimeKeys.curve25519) { for (const keyId in oneTimeKeys.curve25519) {
if (oneTimeKeys.curve25519.hasOwnProperty(keyId)) { if (oneTimeKeys.curve25519.hasOwnProperty(keyId)) {
let k = { const k = {
key: oneTimeKeys.curve25519[keyId], key: oneTimeKeys.curve25519[keyId],
}; };
crypto._signObject(k); crypto._signObject(k);
@@ -282,10 +282,10 @@ function _uploadOneTimeKeys(crypto) {
* module:crypto/deviceinfo|DeviceInfo}. * module:crypto/deviceinfo|DeviceInfo}.
*/ */
Crypto.prototype.downloadKeys = function(userIds, forceDownload) { Crypto.prototype.downloadKeys = function(userIds, forceDownload) {
let self = this; const self = this;
// promises we need to wait for while the download happens // promises we need to wait for while the download happens
let promises = []; const promises = [];
// list of userids we need to download keys for // list of userids we need to download keys for
let downloadUsers = []; let downloadUsers = [];
@@ -300,9 +300,9 @@ Crypto.prototype.downloadKeys = function(userIds, forceDownload) {
downloadUsers = userIds; downloadUsers = userIds;
} else { } else {
for (let i = 0; i < userIds.length; ++i) { for (let i = 0; i < userIds.length; ++i) {
let u = userIds[i]; const u = userIds[i];
let inprogress = this._keyDownloadsInProgressByUser[u]; const inprogress = this._keyDownloadsInProgressByUser[u];
if (inprogress) { if (inprogress) {
// wait for the download to complete // wait for the download to complete
promises.push(q.any(inprogress).catch(perUserCatch(u))); promises.push(q.any(inprogress).catch(perUserCatch(u)));
@@ -313,7 +313,7 @@ Crypto.prototype.downloadKeys = function(userIds, forceDownload) {
} }
if (downloadUsers.length > 0) { if (downloadUsers.length > 0) {
let r = this._doKeyDownloadForUsers(downloadUsers); const r = this._doKeyDownloadForUsers(downloadUsers);
downloadUsers.map(function(u) { downloadUsers.map(function(u) {
promises.push(r[u].catch(perUserCatch(u))); promises.push(r[u].catch(perUserCatch(u)));
}); });
@@ -333,11 +333,11 @@ Crypto.prototype.downloadKeys = function(userIds, forceDownload) {
* @return {Object} userId->deviceId->{@link module:crypto/deviceinfo|DeviceInfo}. * @return {Object} userId->deviceId->{@link module:crypto/deviceinfo|DeviceInfo}.
*/ */
Crypto.prototype._getDevicesFromStore = function(userIds) { Crypto.prototype._getDevicesFromStore = function(userIds) {
let stored = {}; const stored = {};
let self = this; const self = this;
userIds.map(function(u) { userIds.map(function(u) {
stored[u] = {}; stored[u] = {};
let devices = self.getStoredDevicesForUser(u) || []; const devices = self.getStoredDevicesForUser(u) || [];
devices.map(function(dev) { devices.map(function(dev) {
stored[u][dev.deviceId] = dev; stored[u][dev.deviceId] = dev;
}); });
@@ -351,17 +351,17 @@ Crypto.prototype._getDevicesFromStore = function(userIds) {
* @return {Object} a map from userId to a promise for a result for that user * @return {Object} a map from userId to a promise for a result for that user
*/ */
Crypto.prototype._doKeyDownloadForUsers = function(downloadUsers) { Crypto.prototype._doKeyDownloadForUsers = function(downloadUsers) {
let self = this; const self = this;
console.log('Starting key download for ' + downloadUsers); console.log('Starting key download for ' + downloadUsers);
let deferMap = {}; const deferMap = {};
let promiseMap = {}; const promiseMap = {};
downloadUsers.map(function(u) { downloadUsers.map(function(u) {
let deferred = q.defer(); const deferred = q.defer();
let promise = deferred.promise.finally(function() { const promise = deferred.promise.finally(function() {
let inProgress = self._keyDownloadsInProgressByUser[u]; const inProgress = self._keyDownloadsInProgressByUser[u];
utils.removeElement(inProgress, function(e) { utils.removeElement(inProgress, function(e) {
return e === promise; return e === promise;
}); });
@@ -381,42 +381,42 @@ Crypto.prototype._doKeyDownloadForUsers = function(downloadUsers) {
}); });
this._baseApis.downloadKeysForUsers( this._baseApis.downloadKeysForUsers(
downloadUsers downloadUsers,
).done(function(res) { ).done(function(res) {
let dk = res.device_keys || {}; const dk = res.device_keys || {};
for (let i = 0; i < downloadUsers.length; ++i) { for (let i = 0; i < downloadUsers.length; ++i) {
let userId = downloadUsers[i]; const userId = downloadUsers[i];
var deviceId; var deviceId;
console.log('got keys for ' + userId + ':', dk[userId]); console.log('got keys for ' + userId + ':', dk[userId]);
if (!dk[userId]) { if (!dk[userId]) {
// no result for this user // no result for this user
let err = 'Unknown'; const err = 'Unknown';
// TODO: do something with res.failures // TODO: do something with res.failures
deferMap[userId].reject(err); deferMap[userId].reject(err);
continue; continue;
} }
// map from deviceid -> deviceinfo for this user // map from deviceid -> deviceinfo for this user
let userStore = {}; const userStore = {};
let devs = self._sessionStore.getEndToEndDevicesForUser(userId); const devs = self._sessionStore.getEndToEndDevicesForUser(userId);
if (devs) { if (devs) {
for (deviceId in devs) { for (deviceId in devs) {
if (devs.hasOwnProperty(deviceId)) { if (devs.hasOwnProperty(deviceId)) {
let d = DeviceInfo.fromStorage(devs[deviceId], deviceId); const d = DeviceInfo.fromStorage(devs[deviceId], deviceId);
userStore[deviceId] = d; userStore[deviceId] = d;
} }
} }
} }
_updateStoredDeviceKeysForUser( _updateStoredDeviceKeysForUser(
self._olmDevice, userId, userStore, dk[userId] self._olmDevice, userId, userStore, dk[userId],
); );
// update the session store // update the session store
let storage = {}; const storage = {};
for (deviceId in userStore) { for (deviceId in userStore) {
if (!userStore.hasOwnProperty(deviceId)) { if (!userStore.hasOwnProperty(deviceId)) {
continue; continue;
@@ -425,7 +425,7 @@ Crypto.prototype._doKeyDownloadForUsers = function(downloadUsers) {
storage[deviceId] = userStore[deviceId].toStorage(); storage[deviceId] = userStore[deviceId].toStorage();
} }
self._sessionStore.storeEndToEndDevicesForUser( self._sessionStore.storeEndToEndDevicesForUser(
userId, storage userId, storage,
); );
deferMap[userId].resolve(); deferMap[userId].resolve();
@@ -462,7 +462,7 @@ function _updateStoredDeviceKeysForUser(_olmDevice, userId, userStore,
continue; continue;
} }
let deviceResult = userResult[deviceId]; const deviceResult = userResult[deviceId];
// check that the user_id and device_id in the response object are // check that the user_id and device_id in the response object are
// correct // correct
@@ -496,18 +496,18 @@ function _storeDeviceKeys(_olmDevice, userStore, deviceResult) {
return false; return false;
} }
let deviceId = deviceResult.device_id; const deviceId = deviceResult.device_id;
let userId = deviceResult.user_id; const userId = deviceResult.user_id;
let signKeyId = "ed25519:" + deviceId; const signKeyId = "ed25519:" + deviceId;
let signKey = deviceResult.keys[signKeyId]; const signKey = deviceResult.keys[signKeyId];
if (!signKey) { if (!signKey) {
console.log("Device " + userId + ":" + deviceId + console.log("Device " + userId + ":" + deviceId +
" has no ed25519 key"); " has no ed25519 key");
return false; return false;
} }
let unsigned = deviceResult.unsigned || {}; const unsigned = deviceResult.unsigned || {};
try { try {
olmlib.verifySignature(_olmDevice, deviceResult, userId, deviceId, signKey); olmlib.verifySignature(_olmDevice, deviceResult, userId, deviceId, signKey);
@@ -552,12 +552,12 @@ function _storeDeviceKeys(_olmDevice, userStore, deviceResult) {
* managed to get a list of devices for this user yet. * managed to get a list of devices for this user yet.
*/ */
Crypto.prototype.getStoredDevicesForUser = function(userId) { Crypto.prototype.getStoredDevicesForUser = function(userId) {
let devs = this._sessionStore.getEndToEndDevicesForUser(userId); const devs = this._sessionStore.getEndToEndDevicesForUser(userId);
if (!devs) { if (!devs) {
return null; return null;
} }
let res = []; const res = [];
for (let deviceId in devs) { for (const deviceId in devs) {
if (devs.hasOwnProperty(deviceId)) { if (devs.hasOwnProperty(deviceId)) {
res.push(DeviceInfo.fromStorage(devs[deviceId], deviceId)); res.push(DeviceInfo.fromStorage(devs[deviceId], deviceId));
} }
@@ -575,7 +575,7 @@ Crypto.prototype.getStoredDevicesForUser = function(userId) {
* if we don't know about this device * if we don't know about this device
*/ */
Crypto.prototype.getStoredDevice = function(userId, deviceId) { Crypto.prototype.getStoredDevice = function(userId, deviceId) {
let devs = this._sessionStore.getEndToEndDevicesForUser(userId); const devs = this._sessionStore.getEndToEndDevicesForUser(userId);
if (!devs || !devs[deviceId]) { if (!devs || !devs[deviceId]) {
return undefined; return undefined;
} }
@@ -593,13 +593,13 @@ Crypto.prototype.getStoredDevice = function(userId, deviceId) {
* "key", and "display_name" parameters. * "key", and "display_name" parameters.
*/ */
Crypto.prototype.listDeviceKeys = function(userId) { Crypto.prototype.listDeviceKeys = function(userId) {
let devices = this.getStoredDevicesForUser(userId) || []; const devices = this.getStoredDevicesForUser(userId) || [];
let result = []; const result = [];
for (let i = 0; i < devices.length; ++i) { for (let i = 0; i < devices.length; ++i) {
let device = devices[i]; const device = devices[i];
let ed25519Key = device.getFingerprint(); const ed25519Key = device.getFingerprint();
if (ed25519Key) { if (ed25519Key) {
result.push({ result.push({
id: device.deviceId, id: device.deviceId,
@@ -643,25 +643,25 @@ Crypto.prototype.getDeviceByIdentityKey = function(userId, algorithm, sender_key
return null; return null;
} }
let devices = this._sessionStore.getEndToEndDevicesForUser(userId); const devices = this._sessionStore.getEndToEndDevicesForUser(userId);
if (!devices) { if (!devices) {
return null; return null;
} }
for (let deviceId in devices) { for (const deviceId in devices) {
if (!devices.hasOwnProperty(deviceId)) { if (!devices.hasOwnProperty(deviceId)) {
continue; continue;
} }
let device = devices[deviceId]; const device = devices[deviceId];
for (let keyId in device.keys) { for (const keyId in device.keys) {
if (!device.keys.hasOwnProperty(keyId)) { if (!device.keys.hasOwnProperty(keyId)) {
continue; continue;
} }
if (keyId.indexOf("curve25519:") !== 0) { if (keyId.indexOf("curve25519:") !== 0) {
continue; continue;
} }
let deviceKey = device.keys[keyId]; const deviceKey = device.keys[keyId];
if (deviceKey == sender_key) { if (deviceKey == sender_key) {
return DeviceInfo.fromStorage(device, deviceId); return DeviceInfo.fromStorage(device, deviceId);
} }
@@ -686,12 +686,12 @@ Crypto.prototype.getDeviceByIdentityKey = function(userId, algorithm, sender_key
* leave unchanged. * leave unchanged.
*/ */
Crypto.prototype.setDeviceVerification = function(userId, deviceId, verified, blocked) { Crypto.prototype.setDeviceVerification = function(userId, deviceId, verified, blocked) {
let devices = this._sessionStore.getEndToEndDevicesForUser(userId); const devices = this._sessionStore.getEndToEndDevicesForUser(userId);
if (!devices || !devices[deviceId]) { if (!devices || !devices[deviceId]) {
throw new Error("Unknown device " + userId + ":" + deviceId); throw new Error("Unknown device " + userId + ":" + deviceId);
} }
let dev = devices[deviceId]; const dev = devices[deviceId];
let verificationStatus = dev.verified; let verificationStatus = dev.verified;
if (verified) { if (verified) {
@@ -729,12 +729,12 @@ Crypto.prototype.setDeviceVerification = function(userId, deviceId, verified, bl
* @return {Object.<string, {deviceIdKey: string, sessions: object[]}>} * @return {Object.<string, {deviceIdKey: string, sessions: object[]}>}
*/ */
Crypto.prototype.getOlmSessionsForUser = function(userId) { Crypto.prototype.getOlmSessionsForUser = function(userId) {
let devices = this.getStoredDevicesForUser(userId) || []; const devices = this.getStoredDevicesForUser(userId) || [];
let result = {}; const result = {};
for (let j = 0; j < devices.length; ++j) { for (let j = 0; j < devices.length; ++j) {
let device = devices[j]; const device = devices[j];
let deviceKey = device.getIdentityKey(); const deviceKey = device.getIdentityKey();
let sessions = this._olmDevice.getSessionInfoForDevice(deviceKey); const sessions = this._olmDevice.getSessionInfoForDevice(deviceKey);
result[device.deviceId] = { result[device.deviceId] = {
deviceIdKey: deviceKey, deviceIdKey: deviceKey,
@@ -753,8 +753,8 @@ Crypto.prototype.getOlmSessionsForUser = function(userId) {
* @return {module:crypto/deviceinfo?} * @return {module:crypto/deviceinfo?}
*/ */
Crypto.prototype.getEventSenderDeviceInfo = function(event) { Crypto.prototype.getEventSenderDeviceInfo = function(event) {
let sender_key = event.getSenderKey(); const sender_key = event.getSenderKey();
let algorithm = event.getWireContent().algorithm; const algorithm = event.getWireContent().algorithm;
if (!sender_key || !algorithm) { if (!sender_key || !algorithm) {
return null; return null;
@@ -764,8 +764,8 @@ Crypto.prototype.getEventSenderDeviceInfo = function(event) {
// was sent from. In the case of Megolm, it's actually the Curve25519 // was sent from. In the case of Megolm, it's actually the Curve25519
// identity key of the device which set up the Megolm session. // identity key of the device which set up the Megolm session.
let device = this.getDeviceByIdentityKey( const device = this.getDeviceByIdentityKey(
event.getSender(), algorithm, sender_key event.getSender(), algorithm, sender_key,
); );
if (device === null) { if (device === null) {
@@ -781,7 +781,7 @@ Crypto.prototype.getEventSenderDeviceInfo = function(event) {
// //
// (see https://github.com/vector-im/vector-web/issues/2215) // (see https://github.com/vector-im/vector-web/issues/2215)
let claimedKey = event.getKeysClaimed().ed25519; const claimedKey = event.getKeysClaimed().ed25519;
if (!claimedKey) { if (!claimedKey) {
console.warn("Event " + event.getId() + " claims no ed25519 key: " + console.warn("Event " + event.getId() + " claims no ed25519 key: " +
"cannot verify sending device"); "cannot verify sending device");
@@ -808,7 +808,7 @@ Crypto.prototype.getEventSenderDeviceInfo = function(event) {
Crypto.prototype.setRoomEncryption = function(roomId, config) { Crypto.prototype.setRoomEncryption = function(roomId, config) {
// if we already have encryption in this room, we should ignore this event // if we already have encryption in this room, we should ignore this event
// (for now at least. maybe we should alert the user somehow?) // (for now at least. maybe we should alert the user somehow?)
let existingConfig = this._sessionStore.getEndToEndRoom(roomId); const existingConfig = this._sessionStore.getEndToEndRoom(roomId);
if (existingConfig) { if (existingConfig) {
if (JSON.stringify(existingConfig) != JSON.stringify(config)) { if (JSON.stringify(existingConfig) != JSON.stringify(config)) {
console.error("Ignoring m.room.encryption event which requests " + console.error("Ignoring m.room.encryption event which requests " +
@@ -817,7 +817,7 @@ Crypto.prototype.setRoomEncryption = function(roomId, config) {
} }
} }
let AlgClass = algorithms.ENCRYPTION_CLASSES[config.algorithm]; const AlgClass = algorithms.ENCRYPTION_CLASSES[config.algorithm];
if (!AlgClass) { if (!AlgClass) {
throw new Error("Unable to encrypt with " + config.algorithm); throw new Error("Unable to encrypt with " + config.algorithm);
} }
@@ -828,7 +828,7 @@ Crypto.prototype.setRoomEncryption = function(roomId, config) {
}; };
this._sessionStore.storeEndToEndRoom(roomId, config); this._sessionStore.storeEndToEndRoom(roomId, config);
let alg = new AlgClass({ const alg = new AlgClass({
userId: this._userId, userId: this._userId,
deviceId: this._deviceId, deviceId: this._deviceId,
crypto: this, crypto: this,
@@ -859,17 +859,17 @@ Crypto.prototype.setRoomEncryption = function(roomId, config) {
* {@link module:crypto~OlmSessionResult} * {@link module:crypto~OlmSessionResult}
*/ */
Crypto.prototype.ensureOlmSessionsForUsers = function(users) { Crypto.prototype.ensureOlmSessionsForUsers = function(users) {
let devicesByUser = {}; const devicesByUser = {};
for (let i = 0; i < users.length; ++i) { for (let i = 0; i < users.length; ++i) {
let userId = users[i]; const userId = users[i];
devicesByUser[userId] = []; devicesByUser[userId] = [];
let devices = this.getStoredDevicesForUser(userId) || []; const devices = this.getStoredDevicesForUser(userId) || [];
for (let j = 0; j < devices.length; ++j) { for (let j = 0; j < devices.length; ++j) {
let deviceInfo = devices[j]; const deviceInfo = devices[j];
let key = deviceInfo.getIdentityKey(); const key = deviceInfo.getIdentityKey();
if (key == this._olmDevice.deviceCurve25519Key) { if (key == this._olmDevice.deviceCurve25519Key) {
// don't bother setting up session to ourself // don't bother setting up session to ourself
continue; continue;
@@ -884,7 +884,7 @@ Crypto.prototype.ensureOlmSessionsForUsers = function(users) {
} }
return olmlib.ensureOlmSessionsForDevices( return olmlib.ensureOlmSessionsForDevices(
this._olmDevice, this._baseApis, devicesByUser this._olmDevice, this._baseApis, devicesByUser,
); );
}; };
@@ -897,6 +897,45 @@ Crypto.prototype.isRoomEncrypted = function(roomId) {
return Boolean(this._roomEncryptors[roomId]); return Boolean(this._roomEncryptors[roomId]);
}; };
/**
* Get a list containing all of the room keys
*
* @return {module:client.Promise} a promise which resolves to a list of
* session export objects
*/
Crypto.prototype.exportRoomKeys = function() {
return q(
this._sessionStore.getAllEndToEndInboundGroupSessionKeys().map(
(s) => {
const sess = this._olmDevice.exportInboundGroupSession(
s.senderKey, s.sessionId,
);
sess.algorithm = olmlib.MEGOLM_ALGORITHM;
return sess;
},
),
);
};
/**
* Import a list of room keys previously exported by exportRoomKeys
*
* @param {Object[]} keys a list of session export objects
*/
Crypto.prototype.importRoomKeys = function(keys) {
keys.map((session) => {
if (!session.room_id || !session.algorithm) {
console.warn("ignoring session entry with missing fields", session);
return;
}
const alg = this._getRoomDecryptor(session.room_id, session.algorithm);
alg.importRoomKey(session);
});
};
/** /**
* Encrypt an event according to the configuration of the room, if necessary. * Encrypt an event according to the configuration of the room, if necessary.
* *
@@ -920,9 +959,9 @@ Crypto.prototype.encryptEventIfNeeded = function(event, room) {
throw new Error("Cannot send encrypted messages in unknown rooms"); throw new Error("Cannot send encrypted messages in unknown rooms");
} }
let roomId = event.getRoomId(); const roomId = event.getRoomId();
let alg = this._roomEncryptors[roomId]; const alg = this._roomEncryptors[roomId];
if (!alg) { if (!alg) {
// not encrypting messages in this room // not encrypting messages in this room
@@ -931,7 +970,7 @@ Crypto.prototype.encryptEventIfNeeded = function(event, room) {
throw new Error( throw new Error(
"Room was previously configured to use encryption, but is " + "Room was previously configured to use encryption, but is " +
"no longer. Perhaps the homeserver is hiding the " + "no longer. Perhaps the homeserver is hiding the " +
"configuration event." "configuration event.",
); );
} }
return null; return null;
@@ -940,13 +979,13 @@ Crypto.prototype.encryptEventIfNeeded = function(event, room) {
// We can claim and prove ownership of all our device keys in the local // We can claim and prove ownership of all our device keys in the local
// echo of the event since we know that all the local echos come from // echo of the event since we know that all the local echos come from
// this device. // this device.
let myKeys = { const myKeys = {
curve25519: this._olmDevice.deviceCurve25519Key, curve25519: this._olmDevice.deviceCurve25519Key,
ed25519: this._olmDevice.deviceEd25519Key, ed25519: this._olmDevice.deviceEd25519Key,
}; };
return alg.encryptMessage( return alg.encryptMessage(
room, event.getType(), event.getContent() room, event.getType(), event.getContent(),
).then(function(encryptedContent) { ).then(function(encryptedContent) {
event.makeEncrypted("m.room.encrypted", encryptedContent, myKeys); event.makeEncrypted("m.room.encrypted", encryptedContent, myKeys);
}); });
@@ -960,8 +999,8 @@ Crypto.prototype.encryptEventIfNeeded = function(event, room) {
* @raises {algorithms.DecryptionError} if there is a problem decrypting the event * @raises {algorithms.DecryptionError} if there is a problem decrypting the event
*/ */
Crypto.prototype.decryptEvent = function(event) { Crypto.prototype.decryptEvent = function(event) {
let content = event.getWireContent(); const content = event.getWireContent();
let alg = this._getRoomDecryptor(event.getRoomId(), content.algorithm); const alg = this._getRoomDecryptor(event.getRoomId(), content.algorithm);
alg.decryptEvent(event); alg.decryptEvent(event);
}; };
@@ -972,8 +1011,8 @@ Crypto.prototype.decryptEvent = function(event) {
* @param {module:models/event.MatrixEvent} event encryption event * @param {module:models/event.MatrixEvent} event encryption event
*/ */
Crypto.prototype._onCryptoEvent = function(event) { Crypto.prototype._onCryptoEvent = function(event) {
let roomId = event.getRoomId(); const roomId = event.getRoomId();
let content = event.getContent(); const content = event.getContent();
try { try {
this.setRoomEncryption(roomId, content); this.setRoomEncryption(roomId, content);
@@ -1004,27 +1043,27 @@ Crypto.prototype._onInitialSyncCompleted = function(rooms) {
// we need to tell all the devices in all the rooms we are members of that // we need to tell all the devices in all the rooms we are members of that
// we have arrived. // we have arrived.
// build a list of rooms for each user. // build a list of rooms for each user.
let roomsByUser = {}; const roomsByUser = {};
for (let i = 0; i < rooms.length; i++) { for (let i = 0; i < rooms.length; i++) {
let room = rooms[i]; const room = rooms[i];
// check for rooms with encryption enabled // check for rooms with encryption enabled
let alg = this._roomEncryptors[room.roomId]; const alg = this._roomEncryptors[room.roomId];
if (!alg) { if (!alg) {
continue; continue;
} }
// ignore any rooms which we have left // ignore any rooms which we have left
let me = room.getMember(this._userId); const me = room.getMember(this._userId);
if (!me || ( if (!me || (
me.membership !== "join" && me.membership !== "invite" me.membership !== "join" && me.membership !== "invite"
)) { )) {
continue; continue;
} }
let members = room.getJoinedMembers(); const members = room.getJoinedMembers();
for (let j = 0; j < members.length; j++) { for (let j = 0; j < members.length; j++) {
let m = members[j]; const m = members[j];
if (!roomsByUser[m.userId]) { if (!roomsByUser[m.userId]) {
roomsByUser[m.userId] = []; roomsByUser[m.userId] = [];
} }
@@ -1033,8 +1072,8 @@ Crypto.prototype._onInitialSyncCompleted = function(rooms) {
} }
// build a per-device message for each user // build a per-device message for each user
let content = {}; const content = {};
for (let userId in roomsByUser) { for (const userId in roomsByUser) {
if (!roomsByUser.hasOwnProperty(userId)) { if (!roomsByUser.hasOwnProperty(userId)) {
continue; continue;
} }
@@ -1046,10 +1085,10 @@ Crypto.prototype._onInitialSyncCompleted = function(rooms) {
}; };
} }
let self = this; const self = this;
this._baseApis.sendToDevice( this._baseApis.sendToDevice(
"m.new_device", // OH HAI! "m.new_device", // OH HAI!
content content,
).done(function() { ).done(function() {
self._sessionStore.setDeviceAnnounced(); self._sessionStore.setDeviceAnnounced();
}); });
@@ -1062,14 +1101,14 @@ Crypto.prototype._onInitialSyncCompleted = function(rooms) {
* @param {module:models/event.MatrixEvent} event key event * @param {module:models/event.MatrixEvent} event key event
*/ */
Crypto.prototype._onRoomKeyEvent = function(event) { Crypto.prototype._onRoomKeyEvent = function(event) {
let content = event.getContent(); const content = event.getContent();
if (!content.room_id || !content.algorithm) { if (!content.room_id || !content.algorithm) {
console.error("key event is missing fields"); console.error("key event is missing fields");
return; return;
} }
let alg = this._getRoomDecryptor(content.room_id, content.algorithm); const alg = this._getRoomDecryptor(content.room_id, content.algorithm);
alg.onRoomKeyEvent(event); alg.onRoomKeyEvent(event);
}; };
@@ -1090,9 +1129,9 @@ Crypto.prototype._onRoomMembership = function(event, member, oldMembership) {
// Further, it is automatically registered and called when new members // Further, it is automatically registered and called when new members
// arrive in the room. // arrive in the room.
let roomId = member.roomId; const roomId = member.roomId;
let alg = this._roomEncryptors[roomId]; const alg = this._roomEncryptors[roomId];
if (!alg) { if (!alg) {
// not encrypting in this room // not encrypting in this room
return; return;
@@ -1109,10 +1148,10 @@ Crypto.prototype._onRoomMembership = function(event, member, oldMembership) {
* @param {module:models/event.MatrixEvent} event announcement event * @param {module:models/event.MatrixEvent} event announcement event
*/ */
Crypto.prototype._onNewDeviceEvent = function(event) { Crypto.prototype._onNewDeviceEvent = function(event) {
let content = event.getContent(); const content = event.getContent();
let userId = event.getSender(); const userId = event.getSender();
let deviceId = content.device_id; const deviceId = content.device_id;
let rooms = content.rooms; const rooms = content.rooms;
if (!rooms || !deviceId) { if (!rooms || !deviceId) {
console.warn("new_device event missing keys"); console.warn("new_device event missing keys");
@@ -1140,15 +1179,15 @@ Crypto.prototype._onNewDeviceEvent = function(event) {
* Start device queries for any users who sent us an m.new_device recently * Start device queries for any users who sent us an m.new_device recently
*/ */
Crypto.prototype._flushNewDeviceRequests = function() { Crypto.prototype._flushNewDeviceRequests = function() {
let self = this; const self = this;
let users = utils.keys(this._pendingUsersWithNewDevices); const users = utils.keys(this._pendingUsersWithNewDevices);
if (users.length === 0) { if (users.length === 0) {
return; return;
} }
let r = this._doKeyDownloadForUsers(users); const r = this._doKeyDownloadForUsers(users);
// we've kicked off requests to these users: remove their // we've kicked off requests to these users: remove their
// pending flag for now. // pending flag for now.
@@ -1157,7 +1196,7 @@ Crypto.prototype._flushNewDeviceRequests = function() {
users.map(function(u) { users.map(function(u) {
r[u] = r[u].catch(function(e) { r[u] = r[u].catch(function(e) {
console.error( console.error(
'Error updating device keys for user ' + u + ':', e 'Error updating device keys for user ' + u + ':', e,
); );
// reinstate the pending flags on any users which failed; this will // reinstate the pending flags on any users which failed; this will
@@ -1206,10 +1245,10 @@ Crypto.prototype._getRoomDecryptor = function(roomId, algorithm) {
} }
} }
let AlgClass = algorithms.DECRYPTION_CLASSES[algorithm]; const AlgClass = algorithms.DECRYPTION_CLASSES[algorithm];
if (!AlgClass) { if (!AlgClass) {
throw new algorithms.DecryptionError( throw new algorithms.DecryptionError(
'Unknown encryption algorithm "' + algorithm + '".' 'Unknown encryption algorithm "' + algorithm + '".',
); );
} }
alg = new AlgClass({ alg = new AlgClass({
@@ -1232,7 +1271,7 @@ Crypto.prototype._getRoomDecryptor = function(roomId, algorithm) {
* @param {Object} obj Object to which we will add a 'signatures' property * @param {Object} obj Object to which we will add a 'signatures' property
*/ */
Crypto.prototype._signObject = function(obj) { Crypto.prototype._signObject = function(obj) {
let sigs = {}; const sigs = {};
sigs[this._userId] = {}; sigs[this._userId] = {};
sigs[this._userId]["ed25519:" + this._deviceId] = sigs[this._userId]["ed25519:" + this._deviceId] =
this._olmDevice.sign(anotherjson.stringify(obj)); this._olmDevice.sign(anotherjson.stringify(obj));

View File

@@ -20,10 +20,10 @@ limitations under the License.
* Utilities common to olm encryption algorithms * Utilities common to olm encryption algorithms
*/ */
let q = require('q'); const q = require('q');
let anotherjson = require('another-json'); const anotherjson = require('another-json');
let utils = require("../utils"); const utils = require("../utils");
/** /**
* matrix algorithm tag for olm * matrix algorithm tag for olm
@@ -52,10 +52,10 @@ module.exports.MEGOLM_ALGORITHM = "m.megolm.v1.aes-sha2";
module.exports.encryptMessageForDevice = function( module.exports.encryptMessageForDevice = function(
resultsObject, resultsObject,
ourUserId, ourDeviceId, olmDevice, recipientUserId, recipientDevice, ourUserId, ourDeviceId, olmDevice, recipientUserId, recipientDevice,
payloadFields payloadFields,
) { ) {
let deviceKey = recipientDevice.getIdentityKey(); const deviceKey = recipientDevice.getIdentityKey();
let sessionId = olmDevice.getSessionIdForDevice(deviceKey); const sessionId = olmDevice.getSessionIdForDevice(deviceKey);
if (sessionId === null) { if (sessionId === null) {
// If we don't have a session for a device then // If we don't have a session for a device then
// we can't encrypt a message for it. // we can't encrypt a message for it.
@@ -64,10 +64,10 @@ module.exports.encryptMessageForDevice = function(
console.log( console.log(
"Using sessionid " + sessionId + " for device " + "Using sessionid " + sessionId + " for device " +
recipientUserId + ":" + recipientDevice.deviceId recipientUserId + ":" + recipientDevice.deviceId,
); );
let payload = { const payload = {
sender: ourUserId, sender: ourUserId,
sender_device: ourDeviceId, sender_device: ourDeviceId,
@@ -100,7 +100,7 @@ module.exports.encryptMessageForDevice = function(
utils.extend(payload, payloadFields); utils.extend(payload, payloadFields);
resultsObject[deviceKey] = olmDevice.encryptMessage( resultsObject[deviceKey] = olmDevice.encryptMessage(
deviceKey, sessionId, JSON.stringify(payload) deviceKey, sessionId, JSON.stringify(payload),
); );
}; };
@@ -119,24 +119,24 @@ module.exports.encryptMessageForDevice = function(
* {@link module:crypto~OlmSessionResult} * {@link module:crypto~OlmSessionResult}
*/ */
module.exports.ensureOlmSessionsForDevices = function( module.exports.ensureOlmSessionsForDevices = function(
olmDevice, baseApis, devicesByUser olmDevice, baseApis, devicesByUser,
) { ) {
let devicesWithoutSession = [ const devicesWithoutSession = [
// [userId, deviceId], ... // [userId, deviceId], ...
]; ];
let result = {}; const result = {};
for (let userId in devicesByUser) { for (const userId in devicesByUser) {
if (!devicesByUser.hasOwnProperty(userId)) { if (!devicesByUser.hasOwnProperty(userId)) {
continue; continue;
} }
result[userId] = {}; result[userId] = {};
let devices = devicesByUser[userId]; const devices = devicesByUser[userId];
for (let j = 0; j < devices.length; j++) { for (let j = 0; j < devices.length; j++) {
let deviceInfo = devices[j]; const deviceInfo = devices[j];
let deviceId = deviceInfo.deviceId; const deviceId = deviceInfo.deviceId;
let key = deviceInfo.getIdentityKey(); const key = deviceInfo.getIdentityKey();
let sessionId = olmDevice.getSessionIdForDevice(key); const sessionId = olmDevice.getSessionIdForDevice(key);
if (sessionId === null) { if (sessionId === null) {
devicesWithoutSession.push([userId, deviceId]); devicesWithoutSession.push([userId, deviceId]);
} }
@@ -157,28 +157,28 @@ module.exports.ensureOlmSessionsForDevices = function(
// //
// That should eventually resolve itself, but it's poor form. // That should eventually resolve itself, but it's poor form.
let oneTimeKeyAlgorithm = "signed_curve25519"; const oneTimeKeyAlgorithm = "signed_curve25519";
return baseApis.claimOneTimeKeys( return baseApis.claimOneTimeKeys(
devicesWithoutSession, oneTimeKeyAlgorithm devicesWithoutSession, oneTimeKeyAlgorithm,
).then(function(res) { ).then(function(res) {
let otk_res = res.one_time_keys || {}; const otk_res = res.one_time_keys || {};
for (let userId in devicesByUser) { for (const userId in devicesByUser) {
if (!devicesByUser.hasOwnProperty(userId)) { if (!devicesByUser.hasOwnProperty(userId)) {
continue; continue;
} }
let userRes = otk_res[userId] || {}; const userRes = otk_res[userId] || {};
let devices = devicesByUser[userId]; const devices = devicesByUser[userId];
for (let j = 0; j < devices.length; j++) { for (let j = 0; j < devices.length; j++) {
let deviceInfo = devices[j]; const deviceInfo = devices[j];
let deviceId = deviceInfo.deviceId; const deviceId = deviceInfo.deviceId;
if (result[userId][deviceId].sessionId) { if (result[userId][deviceId].sessionId) {
// we already have a result for this device // we already have a result for this device
continue; continue;
} }
let deviceRes = userRes[deviceId] || {}; const deviceRes = userRes[deviceId] || {};
let oneTimeKey = null; let oneTimeKey = null;
for (let keyId in deviceRes) { for (const keyId in deviceRes) {
if (keyId.indexOf(oneTimeKeyAlgorithm + ":") === 0) { if (keyId.indexOf(oneTimeKeyAlgorithm + ":") === 0) {
oneTimeKey = deviceRes[keyId]; oneTimeKey = deviceRes[keyId];
} }
@@ -187,13 +187,13 @@ module.exports.ensureOlmSessionsForDevices = function(
if (!oneTimeKey) { if (!oneTimeKey) {
console.warn( console.warn(
"No one-time keys (alg=" + oneTimeKeyAlgorithm + "No one-time keys (alg=" + oneTimeKeyAlgorithm +
") for device " + userId + ":" + deviceId ") for device " + userId + ":" + deviceId,
); );
continue; continue;
} }
let sid = _verifyKeyAndStartSession( const sid = _verifyKeyAndStartSession(
olmDevice, oneTimeKey, userId, deviceInfo olmDevice, oneTimeKey, userId, deviceInfo,
); );
result[userId][deviceId].sessionId = sid; result[userId][deviceId].sessionId = sid;
} }
@@ -204,16 +204,16 @@ module.exports.ensureOlmSessionsForDevices = function(
function _verifyKeyAndStartSession(olmDevice, oneTimeKey, userId, deviceInfo) { function _verifyKeyAndStartSession(olmDevice, oneTimeKey, userId, deviceInfo) {
let deviceId = deviceInfo.deviceId; const deviceId = deviceInfo.deviceId;
try { try {
_verifySignature( _verifySignature(
olmDevice, oneTimeKey, userId, deviceId, olmDevice, oneTimeKey, userId, deviceId,
deviceInfo.getFingerprint() deviceInfo.getFingerprint(),
); );
} catch (e) { } catch (e) {
console.error( console.error(
"Unable to verify signature on one-time key for device " + "Unable to verify signature on one-time key for device " +
userId + ":" + deviceId + ":", e userId + ":" + deviceId + ":", e,
); );
return null; return null;
} }
@@ -221,7 +221,7 @@ function _verifyKeyAndStartSession(olmDevice, oneTimeKey, userId, deviceInfo) {
let sid; let sid;
try { try {
sid = olmDevice.createOutboundSession( sid = olmDevice.createOutboundSession(
deviceInfo.getIdentityKey(), oneTimeKey.key deviceInfo.getIdentityKey(), oneTimeKey.key,
); );
} catch (e) { } catch (e) {
// possibly a bad key // possibly a bad key
@@ -250,13 +250,13 @@ function _verifyKeyAndStartSession(olmDevice, oneTimeKey, userId, deviceInfo) {
* *
* @param {string} signingKey base64-ed ed25519 public key * @param {string} signingKey base64-ed ed25519 public key
*/ */
let _verifySignature = module.exports.verifySignature = function( const _verifySignature = module.exports.verifySignature = function(
olmDevice, obj, signingUserId, signingDeviceId, signingKey olmDevice, obj, signingUserId, signingDeviceId, signingKey,
) { ) {
let signKeyId = "ed25519:" + signingDeviceId; const signKeyId = "ed25519:" + signingDeviceId;
let signatures = obj.signatures || {}; const signatures = obj.signatures || {};
let userSigs = signatures[signingUserId] || {}; const userSigs = signatures[signingUserId] || {};
let signature = userSigs[signKeyId]; const signature = userSigs[signKeyId];
if (!signature) { if (!signature) {
throw Error("No signature"); throw Error("No signature");
} }
@@ -265,9 +265,9 @@ let _verifySignature = module.exports.verifySignature = function(
// anotherjson // anotherjson
delete obj.unsigned; delete obj.unsigned;
delete obj.signatures; delete obj.signatures;
let json = anotherjson.stringify(obj); const json = anotherjson.stringify(obj);
olmDevice.verifySignature( olmDevice.verifySignature(
signingKey, json, signature signingKey, json, signature,
); );
}; };

View File

@@ -27,7 +27,7 @@ limitations under the License.
*/ */
function _matches_wildcard(actual_value, filter_value) { function _matches_wildcard(actual_value, filter_value) {
if (filter_value.endsWith("*")) { if (filter_value.endsWith("*")) {
let type_prefix = filter_value.slice(0, -1); const type_prefix = filter_value.slice(0, -1);
return actual_value.substr(0, type_prefix.length) === type_prefix; return actual_value.substr(0, type_prefix.length) === type_prefix;
} else { } else {
return actual_value === filter_value; return actual_value === filter_value;
@@ -70,7 +70,7 @@ FilterComponent.prototype.check = function(event) {
event.getRoomId(), event.getRoomId(),
event.getSender(), event.getSender(),
event.getType(), event.getType(),
event.getContent() ? event.getContent().url !== undefined : false event.getContent() ? event.getContent().url !== undefined : false,
); );
}; };
@@ -84,7 +84,7 @@ FilterComponent.prototype.check = function(event) {
*/ */
FilterComponent.prototype._checkFields = FilterComponent.prototype._checkFields =
function(room_id, sender, event_type, contains_url) { function(room_id, sender, event_type, contains_url) {
let literal_keys = { const literal_keys = {
"rooms": function(v) { "rooms": function(v) {
return room_id === v; return room_id === v;
}, },
@@ -96,16 +96,16 @@ FilterComponent.prototype._checkFields =
}, },
}; };
let self = this; const self = this;
Object.keys(literal_keys).forEach(function(name) { Object.keys(literal_keys).forEach(function(name) {
let match_func = literal_keys[name]; const match_func = literal_keys[name];
let not_name = "not_" + name; const not_name = "not_" + name;
let disallowed_values = self[not_name]; const disallowed_values = self[not_name];
if (disallowed_values.map(match_func)) { if (disallowed_values.map(match_func)) {
return false; return false;
} }
let allowed_values = self[name]; const allowed_values = self[name];
if (allowed_values) { if (allowed_values) {
if (!allowed_values.map(match_func)) { if (!allowed_values.map(match_func)) {
return false; return false;
@@ -113,7 +113,7 @@ FilterComponent.prototype._checkFields =
} }
}); });
let contains_url_filter = this.filter_json.contains_url; const contains_url_filter = this.filter_json.contains_url;
if (contains_url_filter !== undefined) { if (contains_url_filter !== undefined) {
if (contains_url_filter !== contains_url) { if (contains_url_filter !== contains_url) {
return false; return false;

View File

@@ -18,7 +18,7 @@ limitations under the License.
* @module filter * @module filter
*/ */
let FilterComponent = require("./filter-component"); const FilterComponent = require("./filter-component");
/** /**
* @param {Object} obj * @param {Object} obj
@@ -26,7 +26,7 @@ let FilterComponent = require("./filter-component");
* @param {*} val * @param {*} val
*/ */
function setProp(obj, keyNesting, val) { function setProp(obj, keyNesting, val) {
let nestedKeys = keyNesting.split("."); const nestedKeys = keyNesting.split(".");
let currentObj = obj; let currentObj = obj;
for (let i = 0; i < (nestedKeys.length - 1); i++) { for (let i = 0; i < (nestedKeys.length - 1); i++) {
if (!currentObj[nestedKeys[i]]) { if (!currentObj[nestedKeys[i]]) {
@@ -106,10 +106,10 @@ Filter.prototype.setDefinition = function(definition) {
// "event_fields": ["type", "content", "sender"] // "event_fields": ["type", "content", "sender"]
// } // }
let room_filter_json = definition.room; const room_filter_json = definition.room;
// consider the top level rooms/not_rooms filter // consider the top level rooms/not_rooms filter
let room_filter_fields = {}; const room_filter_fields = {};
if (room_filter_json) { if (room_filter_json) {
if (room_filter_json.rooms) { if (room_filter_json.rooms) {
room_filter_fields.rooms = room_filter_json.rooms; room_filter_fields.rooms = room_filter_json.rooms;
@@ -123,7 +123,7 @@ Filter.prototype.setDefinition = function(definition) {
this._room_filter = new FilterComponent(room_filter_fields); this._room_filter = new FilterComponent(room_filter_fields);
this._room_timeline_filter = new FilterComponent( this._room_timeline_filter = new FilterComponent(
room_filter_json ? (room_filter_json.timeline || {}) : {} room_filter_json ? (room_filter_json.timeline || {}) : {},
); );
// don't bother porting this from synapse yet: // don't bother porting this from synapse yet:
@@ -183,7 +183,7 @@ Filter.prototype.setIncludeLeaveRooms = function(includeLeave) {
* @return {Filter} * @return {Filter}
*/ */
Filter.fromJson = function(userId, filterId, jsonObj) { Filter.fromJson = function(userId, filterId, jsonObj) {
let filter = new Filter(userId, filterId); const filter = new Filter(userId, filterId);
filter.setDefinition(jsonObj); filter.setDefinition(jsonObj);
return filter; return filter;
}; };

View File

@@ -18,13 +18,13 @@ limitations under the License.
* This is an internal module. See {@link MatrixHttpApi} for the public class. * This is an internal module. See {@link MatrixHttpApi} for the public class.
* @module http-api * @module http-api
*/ */
let q = require("q"); const q = require("q");
let utils = require("./utils"); const utils = require("./utils");
// we use our own implementation of setTimeout, so that if we get suspended in // we use our own implementation of setTimeout, so that if we get suspended in
// the middle of a /sync, we cancel the sync as soon as we awake, rather than // the middle of a /sync, we cancel the sync as soon as we awake, rather than
// waiting for the delay to elapse. // waiting for the delay to elapse.
let callbacks = require("./realtime-callbacks"); const callbacks = require("./realtime-callbacks");
/* /*
TODO: TODO:
@@ -91,7 +91,7 @@ module.exports.MatrixHttpApi.prototype = {
* path and query parameters respectively. * path and query parameters respectively.
*/ */
getContentUri: function() { getContentUri: function() {
let params = { const params = {
access_token: this.opts.accessToken, access_token: this.opts.accessToken,
}; };
return { return {
@@ -145,12 +145,12 @@ module.exports.MatrixHttpApi.prototype = {
// if the file doesn't have a mime type, use a default since // if the file doesn't have a mime type, use a default since
// the HS errors if we don't supply one. // the HS errors if we don't supply one.
let contentType = opts.type || file.type || 'application/octet-stream'; const contentType = opts.type || file.type || 'application/octet-stream';
let fileName = opts.name || file.name; const fileName = opts.name || file.name;
// we used to recommend setting file.stream to the thing to upload on // we used to recommend setting file.stream to the thing to upload on
// nodejs. // nodejs.
let body = file.stream ? file.stream : file; const body = file.stream ? file.stream : file;
// backwards-compatibility hacks where we used to do different things // backwards-compatibility hacks where we used to do different things
// between browser and node. // between browser and node.
@@ -163,7 +163,7 @@ module.exports.MatrixHttpApi.prototype = {
"Returning the raw JSON from uploadContent(). Future " + "Returning the raw JSON from uploadContent(). Future " +
"versions of the js-sdk will change this default, to " + "versions of the js-sdk will change this default, to " +
"return the parsed object. Set opts.rawResponse=false " + "return the parsed object. Set opts.rawResponse=false " +
"to change this behaviour now." "to change this behaviour now.",
); );
rawResponse = true; rawResponse = true;
} }
@@ -176,7 +176,7 @@ module.exports.MatrixHttpApi.prototype = {
"Returning only the content-uri from uploadContent(). " + "Returning only the content-uri from uploadContent(). " +
"Future versions of the js-sdk will change this " + "Future versions of the js-sdk will change this " +
"default, to return the whole response object. Set " + "default, to return the whole response object. Set " +
"opts.onlyContentUri=false to change this behaviour now." "opts.onlyContentUri=false to change this behaviour now.",
); );
onlyContentUri = true; onlyContentUri = true;
} else { } else {
@@ -192,7 +192,7 @@ module.exports.MatrixHttpApi.prototype = {
// (browser-request doesn't support progress either, which is also kind // (browser-request doesn't support progress either, which is also kind
// of important here) // of important here)
let upload = { loaded: 0, total: 0 }; const upload = { loaded: 0, total: 0 };
let promise; let promise;
// XMLHttpRequest doesn't parse JSON for us. request normally does, but // XMLHttpRequest doesn't parse JSON for us. request normally does, but
@@ -214,12 +214,12 @@ module.exports.MatrixHttpApi.prototype = {
} }
if (global.XMLHttpRequest) { if (global.XMLHttpRequest) {
let defer = q.defer(); const defer = q.defer();
let xhr = new global.XMLHttpRequest(); const xhr = new global.XMLHttpRequest();
upload.xhr = xhr; upload.xhr = xhr;
let cb = requestCallback(defer, opts.callback, this.opts.onlyData); const cb = requestCallback(defer, opts.callback, this.opts.onlyData);
let timeout_fn = function() { const timeout_fn = function() {
xhr.abort(); xhr.abort();
cb(new Error('Timeout')); cb(new Error('Timeout'));
}; };
@@ -269,7 +269,7 @@ module.exports.MatrixHttpApi.prototype = {
// dirty hack (as per _request) to allow the upload to be cancelled. // dirty hack (as per _request) to allow the upload to be cancelled.
promise.abort = xhr.abort.bind(xhr); promise.abort = xhr.abort.bind(xhr);
} else { } else {
let queryParams = { const queryParams = {
filename: fileName, filename: fileName,
}; };
@@ -279,14 +279,14 @@ module.exports.MatrixHttpApi.prototype = {
headers: {"Content-Type": contentType}, headers: {"Content-Type": contentType},
json: false, json: false,
bodyParser: bodyParser, bodyParser: bodyParser,
} },
); );
} }
let self = this; const self = this;
// remove the upload from the list on completion // remove the upload from the list on completion
let promise0 = promise.finally(function() { const promise0 = promise.finally(function() {
for (let i = 0; i < self.uploads.length; ++i) { for (let i = 0; i < self.uploads.length; ++i) {
if (self.uploads[i] === upload) { if (self.uploads[i] === upload) {
self.uploads.splice(i, 1); self.uploads.splice(i, 1);
@@ -317,15 +317,15 @@ module.exports.MatrixHttpApi.prototype = {
}, },
idServerRequest: function(callback, method, path, params, prefix) { idServerRequest: function(callback, method, path, params, prefix) {
let fullUri = this.opts.idBaseUrl + prefix + path; const fullUri = this.opts.idBaseUrl + prefix + path;
if (callback !== undefined && !utils.isFunction(callback)) { if (callback !== undefined && !utils.isFunction(callback)) {
throw Error( throw Error(
"Expected callback to be a function but got " + typeof callback "Expected callback to be a function but got " + typeof callback,
); );
} }
let opts = { const opts = {
uri: fullUri, uri: fullUri,
method: method, method: method,
withCredentials: false, withCredentials: false,
@@ -338,10 +338,10 @@ module.exports.MatrixHttpApi.prototype = {
opts.form = params; opts.form = params;
} }
let defer = q.defer(); const defer = q.defer();
this.opts.request( this.opts.request(
opts, opts,
requestCallback(defer, callback, this.opts.onlyData) requestCallback(defer, callback, this.opts.onlyData),
); );
// ID server does not always take JSON, so we can't use requests' 'json' // ID server does not always take JSON, so we can't use requests' 'json'
// option as we do with the home server, but it does return JSON, so // option as we do with the home server, but it does return JSON, so
@@ -389,11 +389,11 @@ module.exports.MatrixHttpApi.prototype = {
queryParams.access_token = this.opts.accessToken; queryParams.access_token = this.opts.accessToken;
} }
let request_promise = this.request( const request_promise = this.request(
callback, method, path, queryParams, data, opts callback, method, path, queryParams, data, opts,
); );
let self = this; const self = this;
request_promise.catch(function(err) { request_promise.catch(function(err) {
if (err.errcode == 'M_UNKNOWN_TOKEN') { if (err.errcode == 'M_UNKNOWN_TOKEN') {
self.event_emitter.emit("Session.logged_out"); self.event_emitter.emit("Session.logged_out");
@@ -437,11 +437,11 @@ module.exports.MatrixHttpApi.prototype = {
*/ */
request: function(callback, method, path, queryParams, data, opts) { request: function(callback, method, path, queryParams, data, opts) {
opts = opts || {}; opts = opts || {};
let prefix = opts.prefix !== undefined ? opts.prefix : this.opts.prefix; const prefix = opts.prefix !== undefined ? opts.prefix : this.opts.prefix;
let fullUri = this.opts.baseUrl + prefix + path; const fullUri = this.opts.baseUrl + prefix + path;
return this.requestOtherUrl( return this.requestOtherUrl(
callback, method, fullUri, queryParams, data, opts callback, method, fullUri, queryParams, data, opts,
); );
}, },
@@ -476,7 +476,7 @@ module.exports.MatrixHttpApi.prototype = {
callback, method, path, queryParams, data, { callback, method, path, queryParams, data, {
localTimeoutMs: localTimeoutMs, localTimeoutMs: localTimeoutMs,
prefix: prefix, prefix: prefix,
} },
); );
}, },
@@ -511,7 +511,7 @@ module.exports.MatrixHttpApi.prototype = {
callback, method, path, queryParams, data, { callback, method, path, queryParams, data, {
localTimeoutMs: localTimeoutMs, localTimeoutMs: localTimeoutMs,
prefix: prefix, prefix: prefix,
} },
); );
}, },
@@ -556,7 +556,7 @@ module.exports.MatrixHttpApi.prototype = {
} }
return this._request( return this._request(
callback, method, uri, queryParams, data, opts callback, method, uri, queryParams, data, opts,
); );
}, },
@@ -608,14 +608,14 @@ module.exports.MatrixHttpApi.prototype = {
_request: function(callback, method, uri, queryParams, data, opts) { _request: function(callback, method, uri, queryParams, data, opts) {
if (callback !== undefined && !utils.isFunction(callback)) { if (callback !== undefined && !utils.isFunction(callback)) {
throw Error( throw Error(
"Expected callback to be a function but got " + typeof callback "Expected callback to be a function but got " + typeof callback,
); );
} }
opts = opts || {}; opts = opts || {};
let self = this; const self = this;
if (this.opts.extraParams) { if (this.opts.extraParams) {
for (let key in this.opts.extraParams) { for (const key in this.opts.extraParams) {
if (!this.opts.extraParams.hasOwnProperty(key)) { if (!this.opts.extraParams.hasOwnProperty(key)) {
continue; continue;
} }
@@ -623,14 +623,14 @@ module.exports.MatrixHttpApi.prototype = {
} }
} }
let json = opts.json === undefined ? true : opts.json; const json = opts.json === undefined ? true : opts.json;
let defer = q.defer(); const defer = q.defer();
let timeoutId; let timeoutId;
let timedOut = false; let timedOut = false;
let req; let req;
let localTimeoutMs = opts.localTimeoutMs || this.opts.localTimeoutMs; const localTimeoutMs = opts.localTimeoutMs || this.opts.localTimeoutMs;
if (localTimeoutMs) { if (localTimeoutMs) {
timeoutId = callbacks.setTimeout(function() { timeoutId = callbacks.setTimeout(function() {
timedOut = true; timedOut = true;
@@ -645,7 +645,7 @@ module.exports.MatrixHttpApi.prototype = {
}, localTimeoutMs); }, localTimeoutMs);
} }
let reqPromise = defer.promise; const reqPromise = defer.promise;
try { try {
req = this.opts.request( req = this.opts.request(
@@ -670,14 +670,14 @@ module.exports.MatrixHttpApi.prototype = {
// if json is falsy, we won't parse any error response, so need // if json is falsy, we won't parse any error response, so need
// to do so before turning it into a MatrixError // to do so before turning it into a MatrixError
let parseErrorJson = !json; const parseErrorJson = !json;
let handlerFn = requestCallback( const handlerFn = requestCallback(
defer, callback, self.opts.onlyData, defer, callback, self.opts.onlyData,
parseErrorJson, parseErrorJson,
opts.bodyParser opts.bodyParser,
); );
handlerFn(err, response, body); handlerFn(err, response, body);
} },
); );
if (req && req.abort) { if (req && req.abort) {
// FIXME: This is EVIL, but I can't think of a better way to expose // FIXME: This is EVIL, but I can't think of a better way to expose
@@ -705,9 +705,9 @@ module.exports.MatrixHttpApi.prototype = {
* If parseErrorJson is true, we will JSON.parse the body if we get a 4xx error. * If parseErrorJson is true, we will JSON.parse the body if we get a 4xx error.
* *
*/ */
let requestCallback = function( const requestCallback = function(
defer, userDefinedCallback, onlyData, defer, userDefinedCallback, onlyData,
parseErrorJson, bodyParser parseErrorJson, bodyParser,
) { ) {
userDefinedCallback = userDefinedCallback || function() {}; userDefinedCallback = userDefinedCallback || function() {};
@@ -735,7 +735,7 @@ let requestCallback = function(
defer.reject(err); defer.reject(err);
userDefinedCallback(err); userDefinedCallback(err);
} else { } else {
let res = { const res = {
code: response.statusCode, code: response.statusCode,
headers: response.headers, headers: response.headers,
data: body, data: body,

View File

@@ -16,9 +16,9 @@ limitations under the License.
"use strict"; "use strict";
/** @module interactive-auth */ /** @module interactive-auth */
let q = require("q"); const q = require("q");
let utils = require("./utils"); const utils = require("./utils");
/** /**
* Abstracts the logic used to drive the interactive auth process. * Abstracts the logic used to drive the interactive auth process.
@@ -115,7 +115,7 @@ InteractiveAuth.prototype = {
} }
// use the sessionid from the last request. // use the sessionid from the last request.
let auth = { const auth = {
session: this._data.session, session: this._data.session,
}; };
utils.extend(auth, authData); utils.extend(auth, authData);
@@ -131,7 +131,7 @@ InteractiveAuth.prototype = {
* @param {object?} auth new auth dict, including session id * @param {object?} auth new auth dict, including session id
*/ */
_doRequest: function(auth) { _doRequest: function(auth) {
let self = this; const self = this;
// hackery to make sure that synchronous exceptions end up in the catch // hackery to make sure that synchronous exceptions end up in the catch
// handler (without the additional event loop entailed by q.fcall or an // handler (without the additional event loop entailed by q.fcall or an
@@ -154,7 +154,7 @@ InteractiveAuth.prototype = {
} }
self._data = error.data; self._data = error.data;
self._startNextAuthStage(); self._startNextAuthStage();
} },
).catch(this._completionDeferred.reject).done(); ).catch(this._completionDeferred.reject).done();
}, },
@@ -164,7 +164,7 @@ InteractiveAuth.prototype = {
* @private * @private
*/ */
_startNextAuthStage: function() { _startNextAuthStage: function() {
let nextStage = this._chooseStage(); const nextStage = this._chooseStage();
if (!nextStage) { if (!nextStage) {
throw new Error("No incomplete flows from the server"); throw new Error("No incomplete flows from the server");
} }
@@ -186,9 +186,9 @@ InteractiveAuth.prototype = {
* @return {string?} login type * @return {string?} login type
*/ */
_chooseStage: function() { _chooseStage: function() {
let flow = this._chooseFlow(); const flow = this._chooseFlow();
console.log("Active flow => %s", JSON.stringify(flow)); console.log("Active flow => %s", JSON.stringify(flow));
let nextStage = this._firstUncompletedStage(flow); const nextStage = this._firstUncompletedStage(flow);
console.log("Next stage: %s", nextStage); console.log("Next stage: %s", nextStage);
return nextStage; return nextStage;
}, },
@@ -200,7 +200,7 @@ InteractiveAuth.prototype = {
* @return {object} flow * @return {object} flow
*/ */
_chooseFlow: function() { _chooseFlow: function() {
let flows = this._data.flows || []; const flows = this._data.flows || [];
// always use the first flow for now // always use the first flow for now
return flows[0]; return flows[0];
}, },
@@ -213,9 +213,9 @@ InteractiveAuth.prototype = {
* @return {string} login type * @return {string} login type
*/ */
_firstUncompletedStage: function(flow) { _firstUncompletedStage: function(flow) {
let completed = (this._data || {}).completed || []; const completed = (this._data || {}).completed || [];
for (let i = 0; i < flow.stages.length; ++i) { for (let i = 0; i < flow.stages.length; ++i) {
let stageType = flow.stages[i]; const stageType = flow.stages[i];
if (completed.indexOf(stageType) === -1) { if (completed.indexOf(stageType) === -1) {
return stageType; return stageType;
} }

View File

@@ -96,7 +96,7 @@ module.exports.getRequest = function() {
* @param {requestWrapperFunction} wrapper The wrapping function. * @param {requestWrapperFunction} wrapper The wrapping function.
*/ */
module.exports.wrapRequest = function(wrapper) { module.exports.wrapRequest = function(wrapper) {
let origRequest = request; const origRequest = request;
request = function(options, callback) { request = function(options, callback) {
return wrapper(origRequest, options, callback); return wrapper(origRequest, options, callback);
}; };

View File

@@ -17,12 +17,12 @@ limitations under the License.
/** /**
* @module models/event-timeline-set * @module models/event-timeline-set
*/ */
let EventEmitter = require("events").EventEmitter; const EventEmitter = require("events").EventEmitter;
let utils = require("../utils"); const utils = require("../utils");
let EventTimeline = require("./event-timeline"); const EventTimeline = require("./event-timeline");
// var DEBUG = false; // var DEBUG = false;
let DEBUG = true; const DEBUG = true;
let debuglog; let debuglog;
if (DEBUG) { if (DEBUG) {
@@ -136,7 +136,7 @@ EventTimelineSet.prototype.eventIdToTimeline = function(eventId) {
* @param {String} newEventId event ID of the replacement event * @param {String} newEventId event ID of the replacement event
*/ */
EventTimelineSet.prototype.replaceEventId = function(oldEventId, newEventId) { EventTimelineSet.prototype.replaceEventId = function(oldEventId, newEventId) {
let existingTimeline = this._eventIdToTimeline[oldEventId]; const existingTimeline = this._eventIdToTimeline[oldEventId];
if (existingTimeline) { if (existingTimeline) {
delete this._eventIdToTimeline[oldEventId]; delete this._eventIdToTimeline[oldEventId];
this._eventIdToTimeline[newEventId] = existingTimeline; this._eventIdToTimeline[newEventId] = existingTimeline;
@@ -166,13 +166,13 @@ EventTimelineSet.prototype.resetLiveTimeline = function(backPaginationToken, flu
} }
// initialise the state in the new timeline from our last known state // initialise the state in the new timeline from our last known state
let evMap = this._liveTimeline.getState(EventTimeline.FORWARDS).events; const evMap = this._liveTimeline.getState(EventTimeline.FORWARDS).events;
let events = []; const events = [];
for (let evtype in evMap) { for (const evtype in evMap) {
if (!evMap.hasOwnProperty(evtype)) { if (!evMap.hasOwnProperty(evtype)) {
continue; continue;
} }
for (let stateKey in evMap[evtype]) { for (const stateKey in evMap[evtype]) {
if (!evMap[evtype].hasOwnProperty(stateKey)) { if (!evMap[evtype].hasOwnProperty(stateKey)) {
continue; continue;
} }
@@ -198,7 +198,7 @@ EventTimelineSet.prototype.resetLiveTimeline = function(backPaginationToken, flu
* the given event, or null if unknown * the given event, or null if unknown
*/ */
EventTimelineSet.prototype.getTimelineForEvent = function(eventId) { EventTimelineSet.prototype.getTimelineForEvent = function(eventId) {
let res = this._eventIdToTimeline[eventId]; const res = this._eventIdToTimeline[eventId];
return (res === undefined) ? null : res; return (res === undefined) ? null : res;
}; };
@@ -209,7 +209,7 @@ EventTimelineSet.prototype.getTimelineForEvent = function(eventId) {
* @return {?module:models/event~MatrixEvent} the given event, or undefined if unknown * @return {?module:models/event~MatrixEvent} the given event, or undefined if unknown
*/ */
EventTimelineSet.prototype.findEventById = function(eventId) { EventTimelineSet.prototype.findEventById = function(eventId) {
let tl = this.getTimelineForEvent(eventId); const tl = this.getTimelineForEvent(eventId);
if (!tl) { if (!tl) {
return undefined; return undefined;
} }
@@ -230,7 +230,7 @@ EventTimelineSet.prototype.addTimeline = function() {
" it."); " it.");
} }
let timeline = new EventTimeline(this); const timeline = new EventTimeline(this);
this._timelines.push(timeline); this._timelines.push(timeline);
return timeline; return timeline;
}; };
@@ -259,14 +259,14 @@ EventTimelineSet.prototype.addEventsToTimeline = function(events, toStartOfTimel
timeline, paginationToken) { timeline, paginationToken) {
if (!timeline) { if (!timeline) {
throw new Error( throw new Error(
"'timeline' not specified for EventTimelineSet.addEventsToTimeline" "'timeline' not specified for EventTimelineSet.addEventsToTimeline",
); );
} }
if (!toStartOfTimeline && timeline == this._liveTimeline) { if (!toStartOfTimeline && timeline == this._liveTimeline) {
throw new Error( throw new Error(
"EventTimelineSet.addEventsToTimeline cannot be used for adding events to " + "EventTimelineSet.addEventsToTimeline cannot be used for adding events to " +
"the live timeline - use Room.addLiveEvents instead" "the live timeline - use Room.addLiveEvents instead",
); );
} }
@@ -277,9 +277,9 @@ EventTimelineSet.prototype.addEventsToTimeline = function(events, toStartOfTimel
} }
} }
let direction = toStartOfTimeline ? EventTimeline.BACKWARDS : const direction = toStartOfTimeline ? EventTimeline.BACKWARDS :
EventTimeline.FORWARDS; EventTimeline.FORWARDS;
let inverseDirection = toStartOfTimeline ? EventTimeline.FORWARDS : const inverseDirection = toStartOfTimeline ? EventTimeline.FORWARDS :
EventTimeline.BACKWARDS; EventTimeline.BACKWARDS;
// Adding events to timelines can be quite complicated. The following // Adding events to timelines can be quite complicated. The following
@@ -354,10 +354,10 @@ EventTimelineSet.prototype.addEventsToTimeline = function(events, toStartOfTimel
let didUpdate = false; let didUpdate = false;
let lastEventWasNew = false; let lastEventWasNew = false;
for (let i = 0; i < events.length; i++) { for (let i = 0; i < events.length; i++) {
let event = events[i]; const event = events[i];
let eventId = event.getId(); const eventId = event.getId();
let existingTimeline = this._eventIdToTimeline[eventId]; const existingTimeline = this._eventIdToTimeline[eventId];
if (!existingTimeline) { if (!existingTimeline) {
// we don't know about this event yet. Just add it to the timeline. // we don't know about this event yet. Just add it to the timeline.
@@ -374,7 +374,7 @@ EventTimelineSet.prototype.addEventsToTimeline = function(events, toStartOfTimel
continue; continue;
} }
let neighbour = timeline.getNeighbouringTimeline(direction); const neighbour = timeline.getNeighbouringTimeline(direction);
if (neighbour) { if (neighbour) {
// this timeline already has a neighbour in the relevant direction; // this timeline already has a neighbour in the relevant direction;
// let's assume the timelines are already correctly linked up, and // let's assume the timelines are already correctly linked up, and
@@ -422,25 +422,25 @@ EventTimelineSet.prototype.addEventsToTimeline = function(events, toStartOfTimel
*/ */
EventTimelineSet.prototype.addLiveEvent = function(event, duplicateStrategy) { EventTimelineSet.prototype.addLiveEvent = function(event, duplicateStrategy) {
if (this._filter) { if (this._filter) {
let events = this._filter.filterRoomTimeline([event]); const events = this._filter.filterRoomTimeline([event]);
if (!events.length) { if (!events.length) {
return; return;
} }
} }
let timeline = this._eventIdToTimeline[event.getId()]; const timeline = this._eventIdToTimeline[event.getId()];
if (timeline) { if (timeline) {
if (duplicateStrategy === "replace") { if (duplicateStrategy === "replace") {
debuglog("EventTimelineSet.addLiveEvent: replacing duplicate event " + debuglog("EventTimelineSet.addLiveEvent: replacing duplicate event " +
event.getId()); event.getId());
let tlEvents = timeline.getEvents(); const tlEvents = timeline.getEvents();
for (let j = 0; j < tlEvents.length; j++) { for (let j = 0; j < tlEvents.length; j++) {
if (tlEvents[j].getId() === event.getId()) { if (tlEvents[j].getId() === event.getId()) {
// still need to set the right metadata on this event // still need to set the right metadata on this event
EventTimeline.setEventMetadata( EventTimeline.setEventMetadata(
event, event,
timeline.getState(EventTimeline.FORWARDS), timeline.getState(EventTimeline.FORWARDS),
false false,
); );
if (!tlEvents[j].encryptedType) { if (!tlEvents[j].encryptedType) {
@@ -475,11 +475,11 @@ EventTimelineSet.prototype.addLiveEvent = function(event, duplicateStrategy) {
*/ */
EventTimelineSet.prototype.addEventToTimeline = function(event, timeline, EventTimelineSet.prototype.addEventToTimeline = function(event, timeline,
toStartOfTimeline) { toStartOfTimeline) {
let eventId = event.getId(); const eventId = event.getId();
timeline.addEvent(event, toStartOfTimeline); timeline.addEvent(event, toStartOfTimeline);
this._eventIdToTimeline[eventId] = timeline; this._eventIdToTimeline[eventId] = timeline;
let data = { const data = {
timeline: timeline, timeline: timeline,
liveEvent: !toStartOfTimeline && timeline == this._liveTimeline, liveEvent: !toStartOfTimeline && timeline == this._liveTimeline,
}; };
@@ -500,7 +500,7 @@ EventTimelineSet.prototype.addEventToTimeline = function(event, timeline,
EventTimelineSet.prototype.handleRemoteEcho = function(localEvent, oldEventId, EventTimelineSet.prototype.handleRemoteEcho = function(localEvent, oldEventId,
newEventId) { newEventId) {
// XXX: why don't we infer newEventId from localEvent? // XXX: why don't we infer newEventId from localEvent?
let existingTimeline = this._eventIdToTimeline[oldEventId]; const existingTimeline = this._eventIdToTimeline[oldEventId];
if (existingTimeline) { if (existingTimeline) {
delete this._eventIdToTimeline[oldEventId]; delete this._eventIdToTimeline[oldEventId];
this._eventIdToTimeline[newEventId] = existingTimeline; this._eventIdToTimeline[newEventId] = existingTimeline;
@@ -524,15 +524,15 @@ EventTimelineSet.prototype.handleRemoteEcho = function(localEvent, oldEventId,
* in this room. * in this room.
*/ */
EventTimelineSet.prototype.removeEvent = function(eventId) { EventTimelineSet.prototype.removeEvent = function(eventId) {
let timeline = this._eventIdToTimeline[eventId]; const timeline = this._eventIdToTimeline[eventId];
if (!timeline) { if (!timeline) {
return null; return null;
} }
let removed = timeline.removeEvent(eventId); const removed = timeline.removeEvent(eventId);
if (removed) { if (removed) {
delete this._eventIdToTimeline[eventId]; delete this._eventIdToTimeline[eventId];
let data = { const data = {
timeline: timeline, timeline: timeline,
}; };
this.emit("Room.timeline", removed, this.room, undefined, true, data); this.emit("Room.timeline", removed, this.room, undefined, true, data);
@@ -558,8 +558,8 @@ EventTimelineSet.prototype.compareEventOrdering = function(eventId1, eventId2) {
return 0; return 0;
} }
let timeline1 = this._eventIdToTimeline[eventId1]; const timeline1 = this._eventIdToTimeline[eventId1];
let timeline2 = this._eventIdToTimeline[eventId2]; const timeline2 = this._eventIdToTimeline[eventId2];
if (timeline1 === undefined) { if (timeline1 === undefined) {
return null; return null;
@@ -572,10 +572,10 @@ EventTimelineSet.prototype.compareEventOrdering = function(eventId1, eventId2) {
// both events are in the same timeline - figure out their // both events are in the same timeline - figure out their
// relative indices // relative indices
let idx1, idx2; let idx1, idx2;
let events = timeline1.getEvents(); const events = timeline1.getEvents();
for (let idx = 0; idx < events.length && for (let idx = 0; idx < events.length &&
(idx1 === undefined || idx2 === undefined); idx++) { (idx1 === undefined || idx2 === undefined); idx++) {
let evId = events[idx].getId(); const evId = events[idx].getId();
if (evId == eventId1) { if (evId == eventId1) {
idx1 = idx; idx1 = idx;
} }

View File

@@ -4,9 +4,9 @@
* @module models/event-timeline * @module models/event-timeline
*/ */
let RoomState = require("./room-state"); const RoomState = require("./room-state");
let utils = require("../utils"); const utils = require("../utils");
let MatrixEvent = require("./event").MatrixEvent; const MatrixEvent = require("./event").MatrixEvent;
/** /**
* Construct a new EventTimeline * Construct a new EventTimeline
@@ -75,11 +75,11 @@ EventTimeline.prototype.initialiseState = function(stateEvents) {
// we deep-copy the events here, in case they get changed later - we don't // we deep-copy the events here, in case they get changed later - we don't
// want changes to the start state leaking through to the end state. // want changes to the start state leaking through to the end state.
let oldStateEvents = utils.map( const oldStateEvents = utils.map(
utils.deepCopy( utils.deepCopy(
stateEvents.map(function(mxEvent) { stateEvents.map(function(mxEvent) {
return mxEvent.event; return mxEvent.event;
}) }),
), ),
function(ev) { function(ev) {
return new MatrixEvent(ev); return new MatrixEvent(ev);
@@ -237,10 +237,10 @@ EventTimeline.prototype.setNeighbouringTimeline = function(neighbour, direction)
* @param {boolean} atStart true to insert new event at the start * @param {boolean} atStart true to insert new event at the start
*/ */
EventTimeline.prototype.addEvent = function(event, atStart) { EventTimeline.prototype.addEvent = function(event, atStart) {
let stateContext = atStart ? this._startState : this._endState; const stateContext = atStart ? this._startState : this._endState;
// only call setEventMetadata on the unfiltered timelineSets // only call setEventMetadata on the unfiltered timelineSets
let timelineSet = this.getTimelineSet(); const timelineSet = this.getTimelineSet();
if (timelineSet.room && if (timelineSet.room &&
timelineSet.room.getUnfilteredTimelineSet() === timelineSet) { timelineSet.room.getUnfilteredTimelineSet() === timelineSet) {
EventTimeline.setEventMetadata(event, stateContext, atStart); EventTimeline.setEventMetadata(event, stateContext, atStart);
@@ -288,11 +288,11 @@ EventTimeline.prototype.addEvent = function(event, atStart) {
EventTimeline.setEventMetadata = function(event, stateContext, toStartOfTimeline) { EventTimeline.setEventMetadata = function(event, stateContext, toStartOfTimeline) {
// set sender and target properties // set sender and target properties
event.sender = stateContext.getSentinelMember( event.sender = stateContext.getSentinelMember(
event.getSender() event.getSender(),
); );
if (event.getType() === "m.room.member") { if (event.getType() === "m.room.member") {
event.target = stateContext.getSentinelMember( event.target = stateContext.getSentinelMember(
event.getStateKey() event.getStateKey(),
); );
} }
if (event.isState()) { if (event.isState()) {
@@ -314,7 +314,7 @@ EventTimeline.setEventMetadata = function(event, stateContext, toStartOfTimeline
*/ */
EventTimeline.prototype.removeEvent = function(eventId) { EventTimeline.prototype.removeEvent = function(eventId) {
for (let i = this._events.length - 1; i >= 0; i--) { for (let i = this._events.length - 1; i >= 0; i--) {
let ev = this._events[i]; const ev = this._events[i];
if (ev.getId() == eventId) { if (ev.getId() == eventId) {
this._events.splice(i, 1); this._events.splice(i, 1);
if (i < this._baseIndex) { if (i < this._baseIndex) {

View File

@@ -21,9 +21,9 @@ limitations under the License.
* @module models/event * @module models/event
*/ */
let EventEmitter = require("events").EventEmitter; const EventEmitter = require("events").EventEmitter;
let utils = require('../utils.js'); const utils = require('../utils.js');
/** /**
* Enum for event statuses. * Enum for event statuses.
@@ -70,7 +70,7 @@ module.exports.EventStatus = {
* Default: true. <strong>This property is experimental and may change.</strong> * Default: true. <strong>This property is experimental and may change.</strong>
*/ */
module.exports.MatrixEvent = function MatrixEvent( module.exports.MatrixEvent = function MatrixEvent(
event event,
) { ) {
this.event = event || {}; this.event = event || {};
this.sender = null; this.sender = null;
@@ -350,8 +350,8 @@ utils.extend(module.exports.MatrixEvent.prototype, {
} }
} }
let keeps = _REDACT_KEEP_CONTENT_MAP[this.getType()] || {}; const keeps = _REDACT_KEEP_CONTENT_MAP[this.getType()] || {};
let content = this.getContent(); const content = this.getContent();
for (key in content) { for (key in content) {
if (!content.hasOwnProperty(key)) { if (!content.hasOwnProperty(key)) {
continue; continue;
@@ -424,7 +424,7 @@ utils.extend(module.exports.MatrixEvent.prototype, {
* m.room.aliases allows key aliases * m.room.aliases allows key aliases
*/ */
// a map giving the keys we keep when an event is redacted // a map giving the keys we keep when an event is redacted
let _REDACT_KEEP_KEY_MAP = [ const _REDACT_KEEP_KEY_MAP = [
'event_id', 'type', 'room_id', 'user_id', 'state_key', 'prev_state', 'event_id', 'type', 'room_id', 'user_id', 'state_key', 'prev_state',
'content', 'unsigned', 'content', 'unsigned',
].reduce(function(ret, val) { ].reduce(function(ret, val) {
@@ -432,7 +432,7 @@ let _REDACT_KEEP_KEY_MAP = [
}, {}); }, {});
// a map from event type to the .content keys we keep when an event is redacted // a map from event type to the .content keys we keep when an event is redacted
let _REDACT_KEEP_CONTENT_MAP = { const _REDACT_KEEP_CONTENT_MAP = {
'm.room.member': {'membership': 1}, 'm.room.member': {'membership': 1},
'm.room.create': {'creator': 1}, 'm.room.create': {'creator': 1},
'm.room.join_rules': {'join_rule': 1}, 'm.room.join_rules': {'join_rule': 1},

View File

@@ -17,10 +17,10 @@ limitations under the License.
/** /**
* @module models/room-member * @module models/room-member
*/ */
let EventEmitter = require("events").EventEmitter; const EventEmitter = require("events").EventEmitter;
let ContentRepo = require("../content-repo"); const ContentRepo = require("../content-repo");
let utils = require("../utils"); const utils = require("../utils");
/** /**
* Construct a new room member. * Construct a new room member.
@@ -73,10 +73,10 @@ RoomMember.prototype.setMembershipEvent = function(event, roomState) {
} }
this.events.member = event; this.events.member = event;
let oldMembership = this.membership; const oldMembership = this.membership;
this.membership = event.getDirectionalContent().membership; this.membership = event.getDirectionalContent().membership;
let oldName = this.name; const oldName = this.name;
this.name = calculateDisplayName(this, event, roomState); this.name = calculateDisplayName(this, event, roomState);
if (oldMembership !== this.membership) { if (oldMembership !== this.membership) {
this._updateModifiedTime(); this._updateModifiedTime();
@@ -103,8 +103,8 @@ RoomMember.prototype.setPowerLevelEvent = function(powerLevelEvent) {
utils.forEach(utils.values(powerLevelEvent.getContent().users), function(lvl) { utils.forEach(utils.values(powerLevelEvent.getContent().users), function(lvl) {
maxLevel = Math.max(maxLevel, lvl); maxLevel = Math.max(maxLevel, lvl);
}); });
let oldPowerLevel = this.powerLevel; const oldPowerLevel = this.powerLevel;
let oldPowerLevelNorm = this.powerLevelNorm; const oldPowerLevelNorm = this.powerLevelNorm;
if (powerLevelEvent.getContent().users[this.userId] !== undefined) { if (powerLevelEvent.getContent().users[this.userId] !== undefined) {
this.powerLevel = powerLevelEvent.getContent().users[this.userId]; this.powerLevel = powerLevelEvent.getContent().users[this.userId];
@@ -136,9 +136,9 @@ RoomMember.prototype.setTypingEvent = function(event) {
if (event.getType() !== "m.typing") { if (event.getType() !== "m.typing") {
return; return;
} }
let oldTyping = this.typing; const oldTyping = this.typing;
this.typing = false; this.typing = false;
let typingList = event.getContent().user_ids; const typingList = event.getContent().user_ids;
if (!utils.isArray(typingList)) { if (!utils.isArray(typingList)) {
// malformed event :/ bail early. TODO: whine? // malformed event :/ bail early. TODO: whine?
return; return;
@@ -195,23 +195,23 @@ RoomMember.prototype.getAvatarUrl =
if (!this.events.member && !allowDefault) { if (!this.events.member && !allowDefault) {
return null; return null;
} }
let rawUrl = this.events.member ? this.events.member.getContent().avatar_url : null; const rawUrl = this.events.member ? this.events.member.getContent().avatar_url : null;
let httpUrl = ContentRepo.getHttpUriForMxc( const httpUrl = ContentRepo.getHttpUriForMxc(
baseUrl, rawUrl, width, height, resizeMethod, allowDirectLinks baseUrl, rawUrl, width, height, resizeMethod, allowDirectLinks,
); );
if (httpUrl) { if (httpUrl) {
return httpUrl; return httpUrl;
} else if (allowDefault) { } else if (allowDefault) {
return ContentRepo.getIdenticonUri( return ContentRepo.getIdenticonUri(
baseUrl, this.userId, width, height baseUrl, this.userId, width, height,
); );
} }
return null; return null;
}; };
function calculateDisplayName(member, event, roomState) { function calculateDisplayName(member, event, roomState) {
let displayName = event.getDirectionalContent().displayname; const displayName = event.getDirectionalContent().displayname;
let selfUserId = member.userId; const selfUserId = member.userId;
if (!displayName) { if (!displayName) {
return selfUserId; return selfUserId;
@@ -221,8 +221,8 @@ function calculateDisplayName(member, event, roomState) {
return displayName; return displayName;
} }
let userIds = roomState.getUserIdsWithDisplayName(displayName); const userIds = roomState.getUserIdsWithDisplayName(displayName);
let otherUsers = userIds.filter(function(u) { const otherUsers = userIds.filter(function(u) {
return u !== selfUserId; return u !== selfUserId;
}); });
if (otherUsers.length > 0) { if (otherUsers.length > 0) {

View File

@@ -17,10 +17,10 @@ limitations under the License.
/** /**
* @module models/room-state * @module models/room-state
*/ */
let EventEmitter = require("events").EventEmitter; const EventEmitter = require("events").EventEmitter;
let utils = require("../utils"); const utils = require("../utils");
let RoomMember = require("./room-member"); const RoomMember = require("./room-member");
/** /**
* Construct room state. * Construct room state.
@@ -100,7 +100,7 @@ RoomState.prototype.getStateEvents = function(eventType, stateKey) {
if (stateKey === undefined) { // return all values if (stateKey === undefined) { // return all values
return utils.values(this.events[eventType]); return utils.values(this.events[eventType]);
} }
let event = this.events[eventType][stateKey]; const event = this.events[eventType][stateKey];
return event ? event : null; return event ? event : null;
}; };
@@ -115,7 +115,7 @@ RoomState.prototype.getStateEvents = function(eventType, stateKey) {
* @fires module:client~MatrixClient#event:"RoomState.events" * @fires module:client~MatrixClient#event:"RoomState.events"
*/ */
RoomState.prototype.setStateEvents = function(stateEvents) { RoomState.prototype.setStateEvents = function(stateEvents) {
let self = this; const self = this;
this._updateModifiedTime(); this._updateModifiedTime();
// update the core event dict // update the core event dict
@@ -133,7 +133,7 @@ RoomState.prototype.setStateEvents = function(stateEvents) {
self.events[event.getType()][event.getStateKey()] = event; self.events[event.getType()][event.getStateKey()] = event;
if (event.getType() === "m.room.member") { if (event.getType() === "m.room.member") {
_updateDisplayNameCache( _updateDisplayNameCache(
self, event.getStateKey(), event.getContent().displayname self, event.getStateKey(), event.getContent().displayname,
); );
_updateThirdPartyTokenCache(self, event); _updateThirdPartyTokenCache(self, event);
} }
@@ -153,7 +153,7 @@ RoomState.prototype.setStateEvents = function(stateEvents) {
} }
if (event.getType() === "m.room.member") { if (event.getType() === "m.room.member") {
let userId = event.getStateKey(); const userId = event.getStateKey();
// leave events apparently elide the displayname or avatar_url, // leave events apparently elide the displayname or avatar_url,
// so let's fake one up so that we don't leak user ids // so let's fake one up so that we don't leak user ids
@@ -178,11 +178,11 @@ RoomState.prototype.setStateEvents = function(stateEvents) {
// so we don't make assumptions about the properties of RoomMember // so we don't make assumptions about the properties of RoomMember
// (e.g. and manage to break it because deep copying doesn't do // (e.g. and manage to break it because deep copying doesn't do
// everything). // everything).
let sentinel = new RoomMember(event.getRoomId(), userId); const sentinel = new RoomMember(event.getRoomId(), userId);
utils.forEach([member, sentinel], function(roomMember) { utils.forEach([member, sentinel], function(roomMember) {
roomMember.setMembershipEvent(event, self); roomMember.setMembershipEvent(event, self);
// this member may have a power level already, so set it. // this member may have a power level already, so set it.
let pwrLvlEvent = self.getStateEvents("m.room.power_levels", ""); const pwrLvlEvent = self.getStateEvents("m.room.power_levels", "");
if (pwrLvlEvent) { if (pwrLvlEvent) {
roomMember.setPowerLevelEvent(pwrLvlEvent); roomMember.setPowerLevelEvent(pwrLvlEvent);
} }
@@ -192,7 +192,7 @@ RoomState.prototype.setStateEvents = function(stateEvents) {
self.members[userId] = member; self.members[userId] = member;
self.emit("RoomState.members", event, self, member); self.emit("RoomState.members", event, self, member);
} else if (event.getType() === "m.room.power_levels") { } else if (event.getType() === "m.room.power_levels") {
let members = utils.values(self.members); const members = utils.values(self.members);
utils.forEach(members, function(member) { utils.forEach(members, function(member) {
member.setPowerLevelEvent(event); member.setPowerLevelEvent(event);
self.emit("RoomState.members", event, self, member); self.emit("RoomState.members", event, self, member);
@@ -312,12 +312,12 @@ RoomState.prototype.maySendStateEvent = function(stateEventType, userId) {
* according to the room's state. * according to the room's state.
*/ */
RoomState.prototype._maySendEventOfType = function(eventType, userId, state) { RoomState.prototype._maySendEventOfType = function(eventType, userId, state) {
let member = this.getMember(userId); const member = this.getMember(userId);
if (!member || member.membership == 'leave') { if (!member || member.membership == 'leave') {
return false; return false;
} }
let power_levels_event = this.getStateEvents('m.room.power_levels', ''); const power_levels_event = this.getStateEvents('m.room.power_levels', '');
let power_levels; let power_levels;
let events_levels = {}; let events_levels = {};
@@ -355,12 +355,12 @@ function _updateThirdPartyTokenCache(roomState, memberEvent) {
if (!memberEvent.getContent().third_party_invite) { if (!memberEvent.getContent().third_party_invite) {
return; return;
} }
let token = (memberEvent.getContent().third_party_invite.signed || {}).token; const token = (memberEvent.getContent().third_party_invite.signed || {}).token;
if (!token) { if (!token) {
return; return;
} }
let threePidInvite = roomState.getStateEvents( const threePidInvite = roomState.getStateEvents(
"m.room.third_party_invite", token "m.room.third_party_invite", token,
); );
if (!threePidInvite) { if (!threePidInvite) {
return; return;
@@ -369,14 +369,14 @@ function _updateThirdPartyTokenCache(roomState, memberEvent) {
} }
function _updateDisplayNameCache(roomState, userId, displayName) { function _updateDisplayNameCache(roomState, userId, displayName) {
let oldName = roomState._userIdsToDisplayNames[userId]; const oldName = roomState._userIdsToDisplayNames[userId];
delete roomState._userIdsToDisplayNames[userId]; delete roomState._userIdsToDisplayNames[userId];
if (oldName) { if (oldName) {
// Remove the old name from the cache. // Remove the old name from the cache.
// We clobber the user_id > name lookup but the name -> [user_id] lookup // We clobber the user_id > name lookup but the name -> [user_id] lookup
// means we need to remove that user ID from that array rather than nuking // means we need to remove that user ID from that array rather than nuking
// the lot. // the lot.
let existingUserIds = roomState._displayNameToUserIds[oldName] || []; const existingUserIds = roomState._displayNameToUserIds[oldName] || [];
for (let i = 0; i < existingUserIds.length; i++) { for (let i = 0; i < existingUserIds.length; i++) {
if (existingUserIds[i] === userId) { if (existingUserIds[i] === userId) {
// remove this user ID from this array // remove this user ID from this array

View File

@@ -17,22 +17,22 @@ limitations under the License.
/** /**
* @module models/room * @module models/room
*/ */
let EventEmitter = require("events").EventEmitter; const EventEmitter = require("events").EventEmitter;
let EventStatus = require("./event").EventStatus; const EventStatus = require("./event").EventStatus;
let RoomSummary = require("./room-summary"); const RoomSummary = require("./room-summary");
let MatrixEvent = require("./event").MatrixEvent; const MatrixEvent = require("./event").MatrixEvent;
let utils = require("../utils"); const utils = require("../utils");
let ContentRepo = require("../content-repo"); const ContentRepo = require("../content-repo");
let EventTimeline = require("./event-timeline"); const EventTimeline = require("./event-timeline");
let EventTimelineSet = require("./event-timeline-set"); const EventTimelineSet = require("./event-timeline-set");
function synthesizeReceipt(userId, event, receiptType) { function synthesizeReceipt(userId, event, receiptType) {
// console.log("synthesizing receipt for "+event.getId()); // console.log("synthesizing receipt for "+event.getId());
// This is really ugly because JS has no way to express an object literal // This is really ugly because JS has no way to express an object literal
// where the name of a key comes from an expression // where the name of a key comes from an expression
let fakeReceipt = { const fakeReceipt = {
content: {}, content: {},
type: "m.receipt", type: "m.receipt",
room_id: event.getRoomId(), room_id: event.getRoomId(),
@@ -108,7 +108,7 @@ function Room(roomId, opts) {
if (["chronological", "detached"].indexOf(opts.pendingEventOrdering) === -1) { if (["chronological", "detached"].indexOf(opts.pendingEventOrdering) === -1) {
throw new Error( throw new Error(
"opts.pendingEventOrdering MUST be either 'chronological' or " + "opts.pendingEventOrdering MUST be either 'chronological' or " +
"'detached'. Got: '" + opts.pendingEventOrdering + "'" "'detached'. Got: '" + opts.pendingEventOrdering + "'",
); );
} }
@@ -308,7 +308,7 @@ Room.prototype.setUnreadNotificationCount = function(type, count) {
*/ */
Room.prototype.getAvatarUrl = function(baseUrl, width, height, resizeMethod, Room.prototype.getAvatarUrl = function(baseUrl, width, height, resizeMethod,
allowDefault) { allowDefault) {
let roomAvatarEvent = this.currentState.getStateEvents("m.room.avatar", ""); const roomAvatarEvent = this.currentState.getStateEvents("m.room.avatar", "");
if (allowDefault === undefined) { if (allowDefault === undefined) {
allowDefault = true; allowDefault = true;
} }
@@ -316,14 +316,14 @@ Room.prototype.getAvatarUrl = function(baseUrl, width, height, resizeMethod,
return null; return null;
} }
let mainUrl = roomAvatarEvent ? roomAvatarEvent.getContent().url : null; const mainUrl = roomAvatarEvent ? roomAvatarEvent.getContent().url : null;
if (mainUrl) { if (mainUrl) {
return ContentRepo.getHttpUriForMxc( return ContentRepo.getHttpUriForMxc(
baseUrl, mainUrl, width, height, resizeMethod baseUrl, mainUrl, width, height, resizeMethod,
); );
} else if (allowDefault) { } else if (allowDefault) {
return ContentRepo.getIdenticonUri( return ContentRepo.getIdenticonUri(
baseUrl, this.roomId, width, height baseUrl, this.roomId, width, height,
); );
} }
@@ -337,15 +337,15 @@ Room.prototype.getAvatarUrl = function(baseUrl, width, height, resizeMethod,
* @return {array} The room's alias as an array of strings * @return {array} The room's alias as an array of strings
*/ */
Room.prototype.getAliases = function() { Room.prototype.getAliases = function() {
let alias_strings = []; const alias_strings = [];
let alias_events = this.currentState.getStateEvents("m.room.aliases"); const alias_events = this.currentState.getStateEvents("m.room.aliases");
if (alias_events) { if (alias_events) {
for (let i = 0; i < alias_events.length; ++i) { for (let i = 0; i < alias_events.length; ++i) {
let alias_event = alias_events[i]; const alias_event = alias_events[i];
if (utils.isArray(alias_event.getContent().aliases)) { if (utils.isArray(alias_event.getContent().aliases)) {
Array.prototype.push.apply( Array.prototype.push.apply(
alias_strings, alias_event.getContent().aliases alias_strings, alias_event.getContent().aliases,
); );
} }
} }
@@ -360,7 +360,7 @@ Room.prototype.getAliases = function() {
* @return {?string} The room's canonical alias, or null if there is none * @return {?string} The room's canonical alias, or null if there is none
*/ */
Room.prototype.getCanonicalAlias = function() { Room.prototype.getCanonicalAlias = function() {
let canonicalAlias = this.currentState.getStateEvents("m.room.canonical_alias", ""); const canonicalAlias = this.currentState.getStateEvents("m.room.canonical_alias", "");
if (canonicalAlias) { if (canonicalAlias) {
return canonicalAlias.getContent().alias; return canonicalAlias.getContent().alias;
} }
@@ -390,7 +390,7 @@ Room.prototype.addEventsToTimeline = function(events, toStartOfTimeline,
timeline, paginationToken) { timeline, paginationToken) {
timeline.getTimelineSet().addEventsToTimeline( timeline.getTimelineSet().addEventsToTimeline(
events, toStartOfTimeline, events, toStartOfTimeline,
timeline, paginationToken timeline, paginationToken,
); );
}; };
@@ -400,7 +400,7 @@ Room.prototype.addEventsToTimeline = function(events, toStartOfTimeline,
* @return {RoomMember} The member or <code>null</code>. * @return {RoomMember} The member or <code>null</code>.
*/ */
Room.prototype.getMember = function(userId) { Room.prototype.getMember = function(userId) {
let member = this.currentState.members[userId]; const member = this.currentState.members[userId];
if (!member) { if (!member) {
return null; return null;
} }
@@ -445,7 +445,7 @@ Room.prototype.addEventsToTimeline = function(events, toStartOfTimeline,
* @return {boolean} True if this user_id has the given membership state. * @return {boolean} True if this user_id has the given membership state.
*/ */
Room.prototype.hasMembershipState = function(userId, membership) { Room.prototype.hasMembershipState = function(userId, membership) {
let member = this.getMember(userId); const member = this.getMember(userId);
if (!member) { if (!member) {
return false; return false;
} }
@@ -461,8 +461,8 @@ Room.prototype.getOrCreateFilteredTimelineSet = function(filter) {
if (this._filteredTimelineSets[filter.filterId]) { if (this._filteredTimelineSets[filter.filterId]) {
return this._filteredTimelineSets[filter.filterId]; return this._filteredTimelineSets[filter.filterId];
} }
let opts = Object.assign({ filter: filter }, this._opts); const opts = Object.assign({ filter: filter }, this._opts);
let timelineSet = new EventTimelineSet(this, opts); const timelineSet = new EventTimelineSet(this, opts);
reEmit(this, timelineSet, ["Room.timeline", "Room.timelineReset"]); reEmit(this, timelineSet, ["Room.timeline", "Room.timelineReset"]);
this._filteredTimelineSets[filter.filterId] = timelineSet; this._filteredTimelineSets[filter.filterId] = timelineSet;
this._timelineSets.push(timelineSet); this._timelineSets.push(timelineSet);
@@ -474,7 +474,7 @@ Room.prototype.getOrCreateFilteredTimelineSet = function(filter) {
// may have grown huge and so take a long time to filter. // may have grown huge and so take a long time to filter.
// see https://github.com/vector-im/vector-web/issues/2109 // see https://github.com/vector-im/vector-web/issues/2109
let unfilteredLiveTimeline = this.getLiveTimeline(); const unfilteredLiveTimeline = this.getLiveTimeline();
unfilteredLiveTimeline.getEvents().forEach(function(event) { unfilteredLiveTimeline.getEvents().forEach(function(event) {
timelineSet.addLiveEvent(event); timelineSet.addLiveEvent(event);
@@ -488,7 +488,7 @@ Room.prototype.getOrCreateFilteredTimelineSet = function(filter) {
timelineSet.getLiveTimeline().setPaginationToken( timelineSet.getLiveTimeline().setPaginationToken(
timeline.getPaginationToken(EventTimeline.BACKWARDS), timeline.getPaginationToken(EventTimeline.BACKWARDS),
EventTimeline.BACKWARDS EventTimeline.BACKWARDS,
); );
// alternatively, we could try to do something like this to try and re-paginate // alternatively, we could try to do something like this to try and re-paginate
@@ -508,9 +508,9 @@ Room.prototype.getOrCreateFilteredTimelineSet = function(filter) {
* @param {Filter} filter the filter whose timelineSet is to be forgotten * @param {Filter} filter the filter whose timelineSet is to be forgotten
*/ */
Room.prototype.removeFilteredTimelineSet = function(filter) { Room.prototype.removeFilteredTimelineSet = function(filter) {
let timelineSet = this._filteredTimelineSets[filter.filterId]; const timelineSet = this._filteredTimelineSets[filter.filterId];
delete this._filteredTimelineSets[filter.filterId]; delete this._filteredTimelineSets[filter.filterId];
let i = this._timelineSets.indexOf(timelineSet); const i = this._timelineSets.indexOf(timelineSet);
if (i > -1) { if (i > -1) {
this._timelineSets.splice(i, 1); this._timelineSets.splice(i, 1);
} }
@@ -528,10 +528,10 @@ Room.prototype.removeFilteredTimelineSet = function(filter) {
Room.prototype._addLiveEvent = function(event, duplicateStrategy) { Room.prototype._addLiveEvent = function(event, duplicateStrategy) {
let i; let i;
if (event.getType() === "m.room.redaction") { if (event.getType() === "m.room.redaction") {
let redactId = event.event.redacts; const redactId = event.event.redacts;
// if we know about this event, redact its contents now. // if we know about this event, redact its contents now.
let redactedEvent = this.getUnfilteredTimelineSet().findEventById(redactId); const redactedEvent = this.getUnfilteredTimelineSet().findEventById(redactId);
if (redactedEvent) { if (redactedEvent) {
redactedEvent.makeRedacted(event); redactedEvent.makeRedacted(event);
this.emit("Room.redaction", event, this); this.emit("Room.redaction", event, this);
@@ -551,7 +551,7 @@ Room.prototype._addLiveEvent = function(event, duplicateStrategy) {
} }
if (event.getUnsigned().transaction_id) { if (event.getUnsigned().transaction_id) {
let existingEvent = this._txnToEvent[event.getUnsigned().transaction_id]; const existingEvent = this._txnToEvent[event.getUnsigned().transaction_id];
if (existingEvent) { if (existingEvent) {
// remote echo of an event we sent earlier // remote echo of an event we sent earlier
this._handleRemoteEcho(event, existingEvent); this._handleRemoteEcho(event, existingEvent);
@@ -569,7 +569,7 @@ Room.prototype._addLiveEvent = function(event, duplicateStrategy) {
// pointing to an event that wasn't yet in the timeline // pointing to an event that wasn't yet in the timeline
if (event.sender) { if (event.sender) {
this.addReceipt(synthesizeReceipt( this.addReceipt(synthesizeReceipt(
event.sender.userId, event, "m.read" event.sender.userId, event, "m.read",
), true); ), true);
// Any live events from a user could be taken as implicit // Any live events from a user could be taken as implicit
@@ -616,7 +616,7 @@ Room.prototype.addPendingEvent = function(event, txnId) {
EventTimeline.setEventMetadata( EventTimeline.setEventMetadata(
event, event,
this.getLiveTimeline().getState(EventTimeline.FORWARDS), this.getLiveTimeline().getState(EventTimeline.FORWARDS),
false false,
); );
this._txnToEvent[txnId] = event; this._txnToEvent[txnId] = event;
@@ -625,7 +625,7 @@ Room.prototype.addPendingEvent = function(event, txnId) {
this._pendingEventList.push(event); this._pendingEventList.push(event);
} else { } else {
for (let i = 0; i < this._timelineSets.length; i++) { for (let i = 0; i < this._timelineSets.length; i++) {
let timelineSet = this._timelineSets[i]; const timelineSet = this._timelineSets[i];
if (timelineSet.getFilter()) { if (timelineSet.getFilter()) {
if (this._filter.filterRoomTimeline([event]).length) { if (this._filter.filterRoomTimeline([event]).length) {
timelineSet.addEventToTimeline(event, timelineSet.addEventToTimeline(event,
@@ -656,9 +656,9 @@ Room.prototype.addPendingEvent = function(event, txnId) {
* @private * @private
*/ */
Room.prototype._handleRemoteEcho = function(remoteEvent, localEvent) { Room.prototype._handleRemoteEcho = function(remoteEvent, localEvent) {
let oldEventId = localEvent.getId(); const oldEventId = localEvent.getId();
let newEventId = remoteEvent.getId(); const newEventId = remoteEvent.getId();
let oldStatus = localEvent.status; const oldStatus = localEvent.status;
// no longer pending // no longer pending
delete this._txnToEvent[remoteEvent.transaction_id]; delete this._txnToEvent[remoteEvent.transaction_id];
@@ -669,7 +669,7 @@ Room.prototype._handleRemoteEcho = function(remoteEvent, localEvent) {
this._pendingEventList, this._pendingEventList,
function(ev) { function(ev) {
return ev.getId() == oldEventId; return ev.getId() == oldEventId;
}, false }, false,
); );
} }
@@ -678,7 +678,7 @@ Room.prototype._handleRemoteEcho = function(remoteEvent, localEvent) {
localEvent.handleRemoteEcho(remoteEvent.event); localEvent.handleRemoteEcho(remoteEvent.event);
for (let i = 0; i < this._timelineSets.length; i++) { for (let i = 0; i < this._timelineSets.length; i++) {
let timelineSet = this._timelineSets[i]; const timelineSet = this._timelineSets[i];
// if it's already in the timeline, update the timeline map. If it's not, add it. // if it's already in the timeline, update the timeline map. If it's not, add it.
timelineSet.handleRemoteEcho(localEvent, oldEventId, newEventId); timelineSet.handleRemoteEcho(localEvent, oldEventId, newEventId);
@@ -690,7 +690,7 @@ Room.prototype._handleRemoteEcho = function(remoteEvent, localEvent) {
/* a map from current event status to a list of allowed next statuses /* a map from current event status to a list of allowed next statuses
*/ */
let ALLOWED_TRANSITIONS = {}; const ALLOWED_TRANSITIONS = {};
ALLOWED_TRANSITIONS[EventStatus.ENCRYPTING] = [ ALLOWED_TRANSITIONS[EventStatus.ENCRYPTING] = [
EventStatus.SENDING, EventStatus.SENDING,
@@ -737,7 +737,7 @@ Room.prototype.updatePendingEvent = function(event, newStatus, newEventId) {
// SENT races against /sync, so we have to special-case it. // SENT races against /sync, so we have to special-case it.
if (newStatus == EventStatus.SENT) { if (newStatus == EventStatus.SENT) {
let timeline = this.getUnfilteredTimelineSet().eventIdToTimeline(newEventId); const timeline = this.getUnfilteredTimelineSet().eventIdToTimeline(newEventId);
if (timeline) { if (timeline) {
// we've already received the event via the event stream. // we've already received the event via the event stream.
// nothing more to do here. // nothing more to do here.
@@ -745,15 +745,15 @@ Room.prototype.updatePendingEvent = function(event, newStatus, newEventId) {
} }
} }
let oldStatus = event.status; const oldStatus = event.status;
let oldEventId = event.getId(); const oldEventId = event.getId();
if (!oldStatus) { if (!oldStatus) {
throw new Error("updatePendingEventStatus called on an event which is " + throw new Error("updatePendingEventStatus called on an event which is " +
"not a local echo."); "not a local echo.");
} }
let allowed = ALLOWED_TRANSITIONS[oldStatus]; const allowed = ALLOWED_TRANSITIONS[oldStatus];
if (!allowed || allowed.indexOf(newStatus) < 0) { if (!allowed || allowed.indexOf(newStatus) < 0) {
throw new Error("Invalid EventStatus transition " + oldStatus + "->" + throw new Error("Invalid EventStatus transition " + oldStatus + "->" +
newStatus); newStatus);
@@ -778,7 +778,7 @@ Room.prototype.updatePendingEvent = function(event, newStatus, newEventId) {
this._pendingEventList, this._pendingEventList,
function(ev) { function(ev) {
return ev.getId() == oldEventId; return ev.getId() == oldEventId;
}, false }, false,
); );
} }
this.removeEvent(oldEventId); this.removeEvent(oldEventId);
@@ -812,17 +812,17 @@ Room.prototype.addLiveEvents = function(events, duplicateStrategy) {
// sanity check that the live timeline is still live // sanity check that the live timeline is still live
for (i = 0; i < this._timelineSets.length; i++) { for (i = 0; i < this._timelineSets.length; i++) {
let liveTimeline = this._timelineSets[i].getLiveTimeline(); const liveTimeline = this._timelineSets[i].getLiveTimeline();
if (liveTimeline.getPaginationToken(EventTimeline.FORWARDS)) { if (liveTimeline.getPaginationToken(EventTimeline.FORWARDS)) {
throw new Error( throw new Error(
"live timeline " + i + " is no longer live - it has a pagination token " + "live timeline " + i + " is no longer live - it has a pagination token " +
"(" + liveTimeline.getPaginationToken(EventTimeline.FORWARDS) + ")" "(" + liveTimeline.getPaginationToken(EventTimeline.FORWARDS) + ")",
); );
} }
if (liveTimeline.getNeighbouringTimeline(EventTimeline.FORWARDS)) { if (liveTimeline.getNeighbouringTimeline(EventTimeline.FORWARDS)) {
throw new Error( throw new Error(
"live timeline " + i + " is no longer live - " + "live timeline " + i + " is no longer live - " +
"it has a neighbouring timeline" "it has a neighbouring timeline",
); );
} }
} }
@@ -863,7 +863,7 @@ Room.prototype.removeEvents = function(event_ids) {
Room.prototype.removeEvent = function(eventId) { Room.prototype.removeEvent = function(eventId) {
let removedAny = false; let removedAny = false;
for (let i = 0; i < this._timelineSets.length; i++) { for (let i = 0; i < this._timelineSets.length; i++) {
let removed = this._timelineSets[i].removeEvent(eventId); const removed = this._timelineSets[i].removeEvent(eventId);
if (removed) { if (removed) {
removedAny = true; removedAny = true;
} }
@@ -882,15 +882,15 @@ Room.prototype.removeEvent = function(eventId) {
Room.prototype.recalculate = function(userId) { Room.prototype.recalculate = function(userId) {
// set fake stripped state events if this is an invite room so logic remains // set fake stripped state events if this is an invite room so logic remains
// consistent elsewhere. // consistent elsewhere.
let self = this; const self = this;
let membershipEvent = this.currentState.getStateEvents( const membershipEvent = this.currentState.getStateEvents(
"m.room.member", userId "m.room.member", userId,
); );
if (membershipEvent && membershipEvent.getContent().membership === "invite") { if (membershipEvent && membershipEvent.getContent().membership === "invite") {
let strippedStateEvents = membershipEvent.event.invite_room_state || []; const strippedStateEvents = membershipEvent.event.invite_room_state || [];
utils.forEach(strippedStateEvents, function(strippedEvent) { utils.forEach(strippedStateEvents, function(strippedEvent) {
let existingEvent = self.currentState.getStateEvents( const existingEvent = self.currentState.getStateEvents(
strippedEvent.type, strippedEvent.state_key strippedEvent.type, strippedEvent.state_key,
); );
if (!existingEvent) { if (!existingEvent) {
// set the fake stripped event instead // set the fake stripped event instead
@@ -906,7 +906,7 @@ Room.prototype.recalculate = function(userId) {
}); });
} }
let oldName = this.name; const oldName = this.name;
this.name = calculateRoomName(this, userId); this.name = calculateRoomName(this, userId);
this.summary = new RoomSummary(this.roomId, { this.summary = new RoomSummary(this.roomId, {
title: this.name, title: this.name,
@@ -1004,18 +1004,18 @@ Room.prototype.addReceipt = function(event, fake) {
* @param {Object} receipts The object to add receipts to * @param {Object} receipts The object to add receipts to
*/ */
Room.prototype._addReceiptsToStructure = function(event, receipts) { Room.prototype._addReceiptsToStructure = function(event, receipts) {
let self = this; const self = this;
utils.keys(event.getContent()).forEach(function(eventId) { utils.keys(event.getContent()).forEach(function(eventId) {
utils.keys(event.getContent()[eventId]).forEach(function(receiptType) { utils.keys(event.getContent()[eventId]).forEach(function(receiptType) {
utils.keys(event.getContent()[eventId][receiptType]).forEach( utils.keys(event.getContent()[eventId][receiptType]).forEach(
function(userId) { function(userId) {
let receipt = event.getContent()[eventId][receiptType][userId]; const receipt = event.getContent()[eventId][receiptType][userId];
if (!receipts[receiptType]) { if (!receipts[receiptType]) {
receipts[receiptType] = {}; receipts[receiptType] = {};
} }
let existingReceipt = receipts[receiptType][userId]; const existingReceipt = receipts[receiptType][userId];
if (!existingReceipt) { if (!existingReceipt) {
receipts[receiptType][userId] = {}; receipts[receiptType][userId] = {};
@@ -1024,7 +1024,7 @@ Room.prototype._addReceiptsToStructure = function(event, receipts) {
// than the one we already have. (This is managed // than the one we already have. (This is managed
// server-side, but because we synthesize RRs locally we // server-side, but because we synthesize RRs locally we
// have to do it here too.) // have to do it here too.)
let ordering = self.getUnfilteredTimelineSet().compareEventOrdering( const ordering = self.getUnfilteredTimelineSet().compareEventOrdering(
existingReceipt.eventId, eventId); existingReceipt.eventId, eventId);
if (ordering !== null && ordering >= 0) { if (ordering !== null && ordering >= 0) {
return; return;
@@ -1046,10 +1046,10 @@ Room.prototype._addReceiptsToStructure = function(event, receipts) {
* @return {Object} Map of receipts by event ID * @return {Object} Map of receipts by event ID
*/ */
Room.prototype._buildReceiptCache = function(receipts) { Room.prototype._buildReceiptCache = function(receipts) {
let receiptCacheByEventId = {}; const receiptCacheByEventId = {};
utils.keys(receipts).forEach(function(receiptType) { utils.keys(receipts).forEach(function(receiptType) {
utils.keys(receipts[receiptType]).forEach(function(userId) { utils.keys(receipts[receiptType]).forEach(function(userId) {
let receipt = receipts[receiptType][userId]; const receipt = receipts[receiptType][userId];
if (!receiptCacheByEventId[receipt.eventId]) { if (!receiptCacheByEventId[receipt.eventId]) {
receiptCacheByEventId[receipt.eventId] = []; receiptCacheByEventId[receipt.eventId] = [];
} }
@@ -1102,7 +1102,7 @@ Room.prototype.addTags = function(event) {
*/ */
Room.prototype.addAccountData = function(events) { Room.prototype.addAccountData = function(events) {
for (let i = 0; i < events.length; i++) { for (let i = 0; i < events.length; i++) {
let event = events[i]; const event = events[i];
if (event.getType() === "m.tag") { if (event.getType() === "m.tag") {
this.addTags(event); this.addTags(event);
} }
@@ -1134,7 +1134,7 @@ function calculateRoomName(room, userId, ignoreRoomNameEvent) {
if (!ignoreRoomNameEvent) { if (!ignoreRoomNameEvent) {
// check for an alias, if any. for now, assume first alias is the // check for an alias, if any. for now, assume first alias is the
// official one. // official one.
let mRoomName = room.currentState.getStateEvents("m.room.name", ""); const mRoomName = room.currentState.getStateEvents("m.room.name", "");
if (mRoomName && mRoomName.getContent() && mRoomName.getContent().name) { if (mRoomName && mRoomName.getContent() && mRoomName.getContent().name) {
return mRoomName.getContent().name; return mRoomName.getContent().name;
} }
@@ -1143,7 +1143,7 @@ function calculateRoomName(room, userId, ignoreRoomNameEvent) {
let alias = room.getCanonicalAlias(); let alias = room.getCanonicalAlias();
if (!alias) { if (!alias) {
let aliases = room.getAliases(); const aliases = room.getAliases();
if (aliases.length) { if (aliases.length) {
alias = aliases[0]; alias = aliases[0];
@@ -1154,16 +1154,16 @@ function calculateRoomName(room, userId, ignoreRoomNameEvent) {
} }
// get members that are NOT ourselves and are actually in the room. // get members that are NOT ourselves and are actually in the room.
let otherMembers = utils.filter(room.currentState.getMembers(), function(m) { const otherMembers = utils.filter(room.currentState.getMembers(), function(m) {
return (m.userId !== userId && m.membership !== "leave"); return (m.userId !== userId && m.membership !== "leave");
}); });
let allMembers = utils.filter(room.currentState.getMembers(), function(m) { const allMembers = utils.filter(room.currentState.getMembers(), function(m) {
return (m.membership !== "leave"); return (m.membership !== "leave");
}); });
let myMemberEventArray = utils.filter(room.currentState.getMembers(), function(m) { const myMemberEventArray = utils.filter(room.currentState.getMembers(), function(m) {
return (m.userId == userId); return (m.userId == userId);
}); });
let myMemberEvent = ( const myMemberEvent = (
(myMemberEventArray.length && myMemberEventArray[0].events) ? (myMemberEventArray.length && myMemberEventArray[0].events) ?
myMemberEventArray[0].events.member.event : undefined myMemberEventArray[0].events.member.event : undefined
); );
@@ -1173,7 +1173,7 @@ function calculateRoomName(room, userId, ignoreRoomNameEvent) {
if (room.currentState.getMember(myMemberEvent.sender)) { if (room.currentState.getMember(myMemberEvent.sender)) {
// extract who invited us to the room // extract who invited us to the room
return "Invite from " + room.currentState.getMember( return "Invite from " + room.currentState.getMember(
myMemberEvent.sender myMemberEvent.sender,
).name; ).name;
} else if (allMembers[0].events.member) { } else if (allMembers[0].events.member) {
// use the sender field from the invite event, although this only // use the sender field from the invite event, although this only
@@ -1190,7 +1190,7 @@ function calculateRoomName(room, userId, ignoreRoomNameEvent) {
// self-chat, peeked room with 1 participant, // self-chat, peeked room with 1 participant,
// or inbound invite, or outbound 3PID invite. // or inbound invite, or outbound 3PID invite.
if (allMembers[0].userId === userId) { if (allMembers[0].userId === userId) {
let thirdPartyInvites = const thirdPartyInvites =
room.currentState.getStateEvents("m.room.third_party_invite"); room.currentState.getStateEvents("m.room.third_party_invite");
if (thirdPartyInvites && thirdPartyInvites.length > 0) { if (thirdPartyInvites && thirdPartyInvites.length > 0) {
let name = "Inviting " + let name = "Inviting " +
@@ -1238,7 +1238,7 @@ function reEmit(reEmitEntity, emittableEntity, eventNames) {
// Transformation Example: // Transformation Example:
// listener on "foo" => function(a,b) { ... } // listener on "foo" => function(a,b) { ... }
// Re-emit on "thing" => thing.emit("foo", a, b) // Re-emit on "thing" => thing.emit("foo", a, b)
let newArgs = [eventName]; const newArgs = [eventName];
for (let i = 0; i < arguments.length; i++) { for (let i = 0; i < arguments.length; i++) {
newArgs.push(arguments[i]); newArgs.push(arguments[i]);
} }

View File

@@ -19,8 +19,8 @@ limitations under the License.
* @module models/search-result * @module models/search-result
*/ */
let EventContext = require("./event-context"); const EventContext = require("./event-context");
let utils = require("../utils"); const utils = require("../utils");
/** /**
* Construct a new SearchResult * Construct a new SearchResult
@@ -45,11 +45,11 @@ function SearchResult(rank, eventContext) {
*/ */
SearchResult.fromJson = function(jsonObj, eventMapper) { SearchResult.fromJson = function(jsonObj, eventMapper) {
let jsonContext = jsonObj.context || {}; const jsonContext = jsonObj.context || {};
let events_before = jsonContext.events_before || []; const events_before = jsonContext.events_before || [];
let events_after = jsonContext.events_after || []; const events_after = jsonContext.events_after || [];
let context = new EventContext(eventMapper(jsonObj.result)); const context = new EventContext(eventMapper(jsonObj.result));
context.setPaginateToken(jsonContext.start, true); context.setPaginateToken(jsonContext.start, true);
context.addEvents(utils.map(events_before, eventMapper), true); context.addEvents(utils.map(events_before, eventMapper), true);

View File

@@ -17,8 +17,8 @@ limitations under the License.
/** /**
* @module models/user * @module models/user
*/ */
let EventEmitter = require("events").EventEmitter; const EventEmitter = require("events").EventEmitter;
let utils = require("../utils"); const utils = require("../utils");
/** /**
* Construct a new User. A User must have an ID and can optionally have extra * Construct a new User. A User must have an ID and can optionally have extra
@@ -73,10 +73,10 @@ User.prototype.setPresenceEvent = function(event) {
if (event.getType() !== "m.presence") { if (event.getType() !== "m.presence") {
return; return;
} }
let firstFire = this.events.presence === null; const firstFire = this.events.presence === null;
this.events.presence = event; this.events.presence = event;
let eventsToFire = []; const eventsToFire = [];
if (event.getContent().presence !== this.presence || firstFire) { if (event.getContent().presence !== this.presence || firstFire) {
eventsToFire.push("User.presence"); eventsToFire.push("User.presence");
} }
@@ -122,7 +122,7 @@ User.prototype.setPresenceEvent = function(event) {
* @param {string} name The new display name. * @param {string} name The new display name.
*/ */
User.prototype.setDisplayName = function(name) { User.prototype.setDisplayName = function(name) {
let oldName = this.displayName; const oldName = this.displayName;
this.displayName = name; this.displayName = name;
if (name !== oldName) { if (name !== oldName) {
this._updateModifiedTime(); this._updateModifiedTime();
@@ -146,7 +146,7 @@ User.prototype.setRawDisplayName = function(name) {
* @param {string} url The new avatar URL. * @param {string} url The new avatar URL.
*/ */
User.prototype.setAvatarUrl = function(url) { User.prototype.setAvatarUrl = function(url) {
let oldUrl = this.avatarUrl; const oldUrl = this.avatarUrl;
this.avatarUrl = url; this.avatarUrl = url;
if (url !== oldUrl) { if (url !== oldUrl) {
this._updateModifiedTime(); this._updateModifiedTime();

View File

@@ -23,25 +23,25 @@ limitations under the License.
* @param {Object} client The Matrix client object to use * @param {Object} client The Matrix client object to use
*/ */
function PushProcessor(client) { function PushProcessor(client) {
let escapeRegExp = function(string) { const escapeRegExp = function(string) {
return string.replace(/[.*+?^${}()|[\]\\]/g, "\\$&"); return string.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
}; };
let matchingRuleFromKindSet = function(ev, kindset, device) { const matchingRuleFromKindSet = function(ev, kindset, device) {
let rulekinds_in_order = ['override', 'content', 'room', 'sender', 'underride']; const rulekinds_in_order = ['override', 'content', 'room', 'sender', 'underride'];
for (let ruleKindIndex = 0; for (let ruleKindIndex = 0;
ruleKindIndex < rulekinds_in_order.length; ruleKindIndex < rulekinds_in_order.length;
++ruleKindIndex) { ++ruleKindIndex) {
let kind = rulekinds_in_order[ruleKindIndex]; const kind = rulekinds_in_order[ruleKindIndex];
let ruleset = kindset[kind]; const ruleset = kindset[kind];
for (let ruleIndex = 0; ruleIndex < ruleset.length; ++ruleIndex) { for (let ruleIndex = 0; ruleIndex < ruleset.length; ++ruleIndex) {
let rule = ruleset[ruleIndex]; const rule = ruleset[ruleIndex];
if (!rule.enabled) { if (!rule.enabled) {
continue; continue;
} }
let rawrule = templateRuleToRaw(kind, rule, device); const rawrule = templateRuleToRaw(kind, rule, device);
if (!rawrule) { if (!rawrule) {
continue; continue;
} }
@@ -55,8 +55,8 @@ function PushProcessor(client) {
return null; return null;
}; };
let templateRuleToRaw = function(kind, tprule, device) { const templateRuleToRaw = function(kind, tprule, device) {
let rawrule = { const rawrule = {
'rule_id': tprule.rule_id, 'rule_id': tprule.rule_id,
'actions': tprule.actions, 'actions': tprule.actions,
'conditions': [], 'conditions': [],
@@ -106,18 +106,18 @@ function PushProcessor(client) {
return rawrule; return rawrule;
}; };
let ruleMatchesEvent = function(rule, ev) { const ruleMatchesEvent = function(rule, ev) {
let ret = true; let ret = true;
for (let i = 0; i < rule.conditions.length; ++i) { for (let i = 0; i < rule.conditions.length; ++i) {
let cond = rule.conditions[i]; const cond = rule.conditions[i];
ret &= eventFulfillsCondition(cond, ev); ret &= eventFulfillsCondition(cond, ev);
} }
//console.log("Rule "+rule.rule_id+(ret ? " matches" : " doesn't match")); //console.log("Rule "+rule.rule_id+(ret ? " matches" : " doesn't match"));
return ret; return ret;
}; };
let eventFulfillsCondition = function(cond, ev) { const eventFulfillsCondition = function(cond, ev) {
let condition_functions = { const condition_functions = {
"event_match": eventFulfillsEventMatchCondition, "event_match": eventFulfillsEventMatchCondition,
"device": eventFulfillsDeviceCondition, "device": eventFulfillsDeviceCondition,
"contains_display_name": eventFulfillsDisplayNameCondition, "contains_display_name": eventFulfillsDisplayNameCondition,
@@ -129,26 +129,26 @@ function PushProcessor(client) {
return true; return true;
}; };
let eventFulfillsRoomMemberCountCondition = function(cond, ev) { const eventFulfillsRoomMemberCountCondition = function(cond, ev) {
if (!cond.is) { if (!cond.is) {
return false; return false;
} }
let room = client.getRoom(ev.getRoomId()); const room = client.getRoom(ev.getRoomId());
if (!room || !room.currentState || !room.currentState.members) { if (!room || !room.currentState || !room.currentState.members) {
return false; return false;
} }
let memberCount = Object.keys(room.currentState.members).filter(function(m) { const memberCount = Object.keys(room.currentState.members).filter(function(m) {
return room.currentState.members[m].membership == 'join'; return room.currentState.members[m].membership == 'join';
}).length; }).length;
let m = cond.is.match(/^([=<>]*)([0-9]*)$/); const m = cond.is.match(/^([=<>]*)([0-9]*)$/);
if (!m) { if (!m) {
return false; return false;
} }
let ineq = m[1]; const ineq = m[1];
let rhs = parseInt(m[2]); const rhs = parseInt(m[2]);
if (isNaN(rhs)) { if (isNaN(rhs)) {
return false; return false;
} }
@@ -169,32 +169,32 @@ function PushProcessor(client) {
} }
}; };
let eventFulfillsDisplayNameCondition = function(cond, ev) { const eventFulfillsDisplayNameCondition = function(cond, ev) {
let content = ev.getContent(); const content = ev.getContent();
if (!content || !content.body || typeof content.body != 'string') { if (!content || !content.body || typeof content.body != 'string') {
return false; return false;
} }
let room = client.getRoom(ev.getRoomId()); const room = client.getRoom(ev.getRoomId());
if (!room || !room.currentState || !room.currentState.members || if (!room || !room.currentState || !room.currentState.members ||
!room.currentState.getMember(client.credentials.userId)) { !room.currentState.getMember(client.credentials.userId)) {
return false; return false;
} }
let displayName = room.currentState.getMember(client.credentials.userId).name; const displayName = room.currentState.getMember(client.credentials.userId).name;
// N.B. we can't use \b as it chokes on unicode. however \W seems to be okay // N.B. we can't use \b as it chokes on unicode. however \W seems to be okay
// as shorthand for [^0-9A-Za-z_]. // as shorthand for [^0-9A-Za-z_].
let pat = new RegExp("(^|\\W)" + escapeRegExp(displayName) + "(\\W|$)", 'i'); const pat = new RegExp("(^|\\W)" + escapeRegExp(displayName) + "(\\W|$)", 'i');
return content.body.search(pat) > -1; return content.body.search(pat) > -1;
}; };
let eventFulfillsDeviceCondition = function(cond, ev) { const eventFulfillsDeviceCondition = function(cond, ev) {
return false; // XXX: Allow a profile tag to be set for the web client instance return false; // XXX: Allow a profile tag to be set for the web client instance
}; };
let eventFulfillsEventMatchCondition = function(cond, ev) { const eventFulfillsEventMatchCondition = function(cond, ev) {
let val = valueForDottedKey(cond.key, ev); const val = valueForDottedKey(cond.key, ev);
if (!val || typeof val != 'string') { if (!val || typeof val != 'string') {
return false; return false;
} }
@@ -205,11 +205,11 @@ function PushProcessor(client) {
} else { } else {
pat = '^' + globToRegexp(cond.pattern) + '$'; pat = '^' + globToRegexp(cond.pattern) + '$';
} }
let regex = new RegExp(pat, 'i'); const regex = new RegExp(pat, 'i');
return !!val.match(regex); return !!val.match(regex);
}; };
let globToRegexp = function(glob) { const globToRegexp = function(glob) {
// From // From
// https://github.com/matrix-org/synapse/blob/abbee6b29be80a77e05730707602f3bbfc3f38cb/synapse/push/__init__.py#L132 // https://github.com/matrix-org/synapse/blob/abbee6b29be80a77e05730707602f3bbfc3f38cb/synapse/push/__init__.py#L132
// Because micromatch is about 130KB with dependencies, // Because micromatch is about 130KB with dependencies,
@@ -218,19 +218,19 @@ function PushProcessor(client) {
pat = pat.replace(/\\\*/, '.*'); pat = pat.replace(/\\\*/, '.*');
pat = pat.replace(/\?/, '.'); pat = pat.replace(/\?/, '.');
pat = pat.replace(/\\\[(!|)(.*)\\]/, function(match, p1, p2, offset, string) { pat = pat.replace(/\\\[(!|)(.*)\\]/, function(match, p1, p2, offset, string) {
let first = p1 && '^' || ''; const first = p1 && '^' || '';
let second = p2.replace(/\\\-/, '-'); const second = p2.replace(/\\\-/, '-');
return '[' + first + second + ']'; return '[' + first + second + ']';
}); });
return pat; return pat;
}; };
let valueForDottedKey = function(key, ev) { const valueForDottedKey = function(key, ev) {
let parts = key.split('.'); const parts = key.split('.');
let val; let val;
// special-case the first component to deal with encrypted messages // special-case the first component to deal with encrypted messages
let firstPart = parts[0]; const firstPart = parts[0];
if (firstPart == 'content') { if (firstPart == 'content') {
val = ev.getContent(); val = ev.getContent();
parts.shift(); parts.shift();
@@ -243,7 +243,7 @@ function PushProcessor(client) {
} }
while (parts.length > 0) { while (parts.length > 0) {
let thispart = parts.shift(); const thispart = parts.shift();
if (!val[thispart]) { if (!val[thispart]) {
return null; return null;
} }
@@ -252,7 +252,7 @@ function PushProcessor(client) {
return val; return val;
}; };
let matchingRuleForEventWithRulesets = function(ev, rulesets) { const matchingRuleForEventWithRulesets = function(ev, rulesets) {
if (!rulesets || !rulesets.device) { if (!rulesets || !rulesets.device) {
return null; return null;
} }
@@ -260,12 +260,12 @@ function PushProcessor(client) {
return null; return null;
} }
let allDevNames = Object.keys(rulesets.device); const allDevNames = Object.keys(rulesets.device);
for (let i = 0; i < allDevNames.length; ++i) { for (let i = 0; i < allDevNames.length; ++i) {
let devname = allDevNames[i]; const devname = allDevNames[i];
let devrules = rulesets.device[devname]; const devrules = rulesets.device[devname];
let matchingRule = matchingRuleFromKindSet(devrules, devname); const matchingRule = matchingRuleFromKindSet(devrules, devname);
if (matchingRule) { if (matchingRule) {
return matchingRule; return matchingRule;
} }
@@ -273,13 +273,13 @@ function PushProcessor(client) {
return matchingRuleFromKindSet(ev, rulesets.global); return matchingRuleFromKindSet(ev, rulesets.global);
}; };
let pushActionsForEventAndRulesets = function(ev, rulesets) { const pushActionsForEventAndRulesets = function(ev, rulesets) {
let rule = matchingRuleForEventWithRulesets(ev, rulesets); const rule = matchingRuleForEventWithRulesets(ev, rulesets);
if (!rule) { if (!rule) {
return {}; return {};
} }
let actionObj = PushProcessor.actionListToActionsObject(rule.actions); const actionObj = PushProcessor.actionListToActionsObject(rule.actions);
// Some actions are implicit in some situations: we add those here // Some actions are implicit in some situations: we add those here
if (actionObj.tweaks.highlight === undefined) { if (actionObj.tweaks.highlight === undefined) {
@@ -312,9 +312,9 @@ function PushProcessor(client) {
* @return {object} A object with key 'notify' (true or false) and an object of actions * @return {object} A object with key 'notify' (true or false) and an object of actions
*/ */
PushProcessor.actionListToActionsObject = function(actionlist) { PushProcessor.actionListToActionsObject = function(actionlist) {
let actionobj = { 'notify': false, 'tweaks': {} }; const actionobj = { 'notify': false, 'tweaks': {} };
for (let i = 0; i < actionlist.length; ++i) { for (let i = 0; i < actionlist.length; ++i) {
let action = actionlist[i]; const action = actionlist[i];
if (action === 'notify') { if (action === 'notify') {
actionobj.notify = true; actionobj.notify = true;
} else if (typeof action === 'object') { } else if (typeof action === 'object') {

View File

@@ -27,7 +27,7 @@ limitations under the License.
// we schedule a callback at least this often, to check if we've missed out on // we schedule a callback at least this often, to check if we've missed out on
// some wall-clock time due to being suspended. // some wall-clock time due to being suspended.
let TIMER_CHECK_PERIOD_MS = 1000; const TIMER_CHECK_PERIOD_MS = 1000;
// counter, for making up ids to return from setTimeout // counter, for making up ids to return from setTimeout
let _count = 0; let _count = 0;
@@ -37,10 +37,10 @@ let _realCallbackKey;
// a sorted list of the callbacks to be run. // a sorted list of the callbacks to be run.
// each is an object with keys [runAt, func, params, key]. // each is an object with keys [runAt, func, params, key].
let _callbackList = []; const _callbackList = [];
// var debuglog = console.log.bind(console); // var debuglog = console.log.bind(console);
let debuglog = function() {}; const debuglog = function() {};
/** /**
* Replace the function used by this module to get the current time. * Replace the function used by this module to get the current time.
@@ -72,12 +72,12 @@ module.exports.setTimeout = function(func, delayMs) {
delayMs = 0; delayMs = 0;
} }
let params = Array.prototype.slice.call(arguments, 2); const params = Array.prototype.slice.call(arguments, 2);
let runAt = _now() + delayMs; const runAt = _now() + delayMs;
let key = _count++; const key = _count++;
debuglog("setTimeout: scheduling cb", key, "at", runAt, debuglog("setTimeout: scheduling cb", key, "at", runAt,
"(delay", delayMs, ")"); "(delay", delayMs, ")");
let data = { const data = {
runAt: runAt, runAt: runAt,
func: func, func: func,
params: params, params: params,
@@ -85,10 +85,10 @@ module.exports.setTimeout = function(func, delayMs) {
}; };
// figure out where it goes in the list // figure out where it goes in the list
let idx = binarySearch( const idx = binarySearch(
_callbackList, function(el) { _callbackList, function(el) {
return el.runAt - runAt; return el.runAt - runAt;
} },
); );
_callbackList.splice(idx, 0, data); _callbackList.splice(idx, 0, data);
@@ -110,7 +110,7 @@ module.exports.clearTimeout = function(key) {
// remove the element from the list // remove the element from the list
let i; let i;
for (i = 0; i < _callbackList.length; i++) { for (i = 0; i < _callbackList.length; i++) {
let cb = _callbackList[i]; const cb = _callbackList[i];
if (cb.key == key) { if (cb.key == key) {
_callbackList.splice(i, 1); _callbackList.splice(i, 1);
break; break;
@@ -129,15 +129,15 @@ function _scheduleRealCallback() {
global.clearTimeout(_realCallbackKey); global.clearTimeout(_realCallbackKey);
} }
let first = _callbackList[0]; const first = _callbackList[0];
if (!first) { if (!first) {
debuglog("_scheduleRealCallback: no more callbacks, not rescheduling"); debuglog("_scheduleRealCallback: no more callbacks, not rescheduling");
return; return;
} }
let now = _now(); const now = _now();
let delayMs = Math.min(first.runAt - now, TIMER_CHECK_PERIOD_MS); const delayMs = Math.min(first.runAt - now, TIMER_CHECK_PERIOD_MS);
debuglog("_scheduleRealCallback: now:", now, "delay:", delayMs); debuglog("_scheduleRealCallback: now:", now, "delay:", delayMs);
_realCallbackKey = global.setTimeout(_runCallbacks, delayMs); _realCallbackKey = global.setTimeout(_runCallbacks, delayMs);
@@ -145,13 +145,13 @@ function _scheduleRealCallback() {
function _runCallbacks() { function _runCallbacks() {
let cb; let cb;
let now = _now(); const now = _now();
debuglog("_runCallbacks: now:", now); debuglog("_runCallbacks: now:", now);
// get the list of things to call // get the list of things to call
let callbacksToRun = []; const callbacksToRun = [];
while (true) { while (true) {
let first = _callbackList[0]; const first = _callbackList[0];
if (!first || first.runAt > now) { if (!first || first.runAt > now) {
break; break;
} }
@@ -188,8 +188,8 @@ function binarySearch(array, func) {
max = array.length; max = array.length;
while (min < max) { while (min < max) {
let mid = (min + max) >> 1; const mid = (min + max) >> 1;
let res = func(array[mid]); const res = func(array[mid]);
if (res > 0) { if (res > 0) {
// the element at 'mid' is too big; set it as the new max. // the element at 'mid' is too big; set it as the new max.
max = mid; max = mid;

View File

@@ -19,10 +19,10 @@ limitations under the License.
* of requests. * of requests.
* @module scheduler * @module scheduler
*/ */
let utils = require("./utils"); const utils = require("./utils");
let q = require("q"); const q = require("q");
let DEBUG = false; // set true to enable console logging. const DEBUG = false; // set true to enable console logging.
/** /**
* Construct a scheduler for Matrix. Requires * Construct a scheduler for Matrix. Requires
@@ -60,7 +60,7 @@ function MatrixScheduler(retryAlgorithm, queueAlgorithm) {
* @see MatrixScheduler.removeEventFromQueue To remove an event from the queue. * @see MatrixScheduler.removeEventFromQueue To remove an event from the queue.
*/ */
MatrixScheduler.prototype.getQueueForEvent = function(event) { MatrixScheduler.prototype.getQueueForEvent = function(event) {
let name = this.queueAlgorithm(event); const name = this.queueAlgorithm(event);
if (!name || !this._queues[name]) { if (!name || !this._queues[name]) {
return null; return null;
} }
@@ -76,7 +76,7 @@ MatrixScheduler.prototype.getQueueForEvent = function(event) {
* @return {boolean} True if this event was removed. * @return {boolean} True if this event was removed.
*/ */
MatrixScheduler.prototype.removeEventFromQueue = function(event) { MatrixScheduler.prototype.removeEventFromQueue = function(event) {
let name = this.queueAlgorithm(event); const name = this.queueAlgorithm(event);
if (!name || !this._queues[name]) { if (!name || !this._queues[name]) {
return false; return false;
} }
@@ -110,7 +110,7 @@ MatrixScheduler.prototype.setProcessFunction = function(fn) {
* resolved or rejected in due time, else null. * resolved or rejected in due time, else null.
*/ */
MatrixScheduler.prototype.queueEvent = function(event) { MatrixScheduler.prototype.queueEvent = function(event) {
let queueName = this.queueAlgorithm(event); const queueName = this.queueAlgorithm(event);
if (!queueName) { if (!queueName) {
return null; return null;
} }
@@ -118,7 +118,7 @@ MatrixScheduler.prototype.queueEvent = function(event) {
if (!this._queues[queueName]) { if (!this._queues[queueName]) {
this._queues[queueName] = []; this._queues[queueName] = [];
} }
let defer = q.defer(); const defer = q.defer();
this._queues[queueName].push({ this._queues[queueName].push({
event: event, event: event,
defer: defer, defer: defer,
@@ -126,7 +126,7 @@ MatrixScheduler.prototype.queueEvent = function(event) {
}); });
debuglog( debuglog(
"Queue algorithm dumped event %s into queue '%s'", "Queue algorithm dumped event %s into queue '%s'",
event.getId(), queueName event.getId(), queueName,
); );
_startProcessingQueues(this); _startProcessingQueues(this);
return defer.promise; return defer.promise;
@@ -155,7 +155,7 @@ MatrixScheduler.RETRY_BACKOFF_RATELIMIT = function(event, attempts, err) {
} }
if (err.name === "M_LIMIT_EXCEEDED") { if (err.name === "M_LIMIT_EXCEEDED") {
let waitTime = err.data.retry_after_ms; const waitTime = err.data.retry_after_ms;
if (waitTime) { if (waitTime) {
return waitTime; return waitTime;
} }
@@ -201,10 +201,10 @@ function _startProcessingQueues(scheduler) {
function _processQueue(scheduler, queueName) { function _processQueue(scheduler, queueName) {
// get head of queue // get head of queue
let obj = _peekNextEvent(scheduler, queueName); const obj = _peekNextEvent(scheduler, queueName);
if (!obj) { if (!obj) {
// queue is empty. Mark as inactive and stop recursing. // queue is empty. Mark as inactive and stop recursing.
let index = scheduler._activeQueues.indexOf(queueName); const index = scheduler._activeQueues.indexOf(queueName);
if (index >= 0) { if (index >= 0) {
scheduler._activeQueues.splice(index, 1); scheduler._activeQueues.splice(index, 1);
} }
@@ -213,7 +213,7 @@ function _processQueue(scheduler, queueName) {
} }
debuglog( debuglog(
"Queue '%s' has %s pending events", "Queue '%s' has %s pending events",
queueName, scheduler._queues[queueName].length queueName, scheduler._queues[queueName].length,
); );
// fire the process function and if it resolves, resolve the deferred. Else // fire the process function and if it resolves, resolve the deferred. Else
// invoke the retry algorithm. // invoke the retry algorithm.
@@ -227,14 +227,14 @@ function _processQueue(scheduler, queueName) {
}, function(err) { }, function(err) {
obj.attempts += 1; obj.attempts += 1;
// ask the retry algorithm when/if we should try again // ask the retry algorithm when/if we should try again
let waitTimeMs = scheduler.retryAlgorithm(obj.event, obj.attempts, err); const waitTimeMs = scheduler.retryAlgorithm(obj.event, obj.attempts, err);
debuglog( debuglog(
"retry(%s) err=%s event_id=%s waitTime=%s", "retry(%s) err=%s event_id=%s waitTime=%s",
obj.attempts, err, obj.event.getId(), waitTimeMs obj.attempts, err, obj.event.getId(), waitTimeMs,
); );
if (waitTimeMs === -1) { // give up (you quitter!) if (waitTimeMs === -1) { // give up (you quitter!)
debuglog( debuglog(
"Queue '%s' giving up on event %s", queueName, obj.event.getId() "Queue '%s' giving up on event %s", queueName, obj.event.getId(),
); );
// remove this from the queue // remove this from the queue
_removeNextEvent(scheduler, queueName); _removeNextEvent(scheduler, queueName);
@@ -250,7 +250,7 @@ function _processQueue(scheduler, queueName) {
} }
function _peekNextEvent(scheduler, queueName) { function _peekNextEvent(scheduler, queueName) {
let queue = scheduler._queues[queueName]; const queue = scheduler._queues[queueName];
if (!utils.isArray(queue)) { if (!utils.isArray(queue)) {
return null; return null;
} }
@@ -258,7 +258,7 @@ function _peekNextEvent(scheduler, queueName) {
} }
function _removeNextEvent(scheduler, queueName) { function _removeNextEvent(scheduler, queueName) {
let queue = scheduler._queues[queueName]; const queue = scheduler._queues[queueName];
if (!utils.isArray(queue)) { if (!utils.isArray(queue)) {
return null; return null;
} }

View File

@@ -18,8 +18,8 @@ limitations under the License.
* This is an internal module. See {@link MatrixInMemoryStore} for the public class. * This is an internal module. See {@link MatrixInMemoryStore} for the public class.
* @module store/memory * @module store/memory
*/ */
let utils = require("../utils"); const utils = require("../utils");
let User = require("../models/user"); const User = require("../models/user");
/** /**
* Construct a new in-memory data store for the Matrix Client. * Construct a new in-memory data store for the Matrix Client.
@@ -77,7 +77,7 @@ module.exports.MatrixInMemoryStore.prototype = {
// map up-to-date. // map up-to-date.
room.currentState.on("RoomState.members", this._onRoomMember.bind(this)); room.currentState.on("RoomState.members", this._onRoomMember.bind(this));
// add existing members // add existing members
let self = this; const self = this;
room.currentState.getMembers().forEach(function(m) { room.currentState.getMembers().forEach(function(m) {
self._onRoomMember(null, room.currentState, m); self._onRoomMember(null, room.currentState, m);
}); });
@@ -97,12 +97,12 @@ module.exports.MatrixInMemoryStore.prototype = {
return; return;
} }
let user = this.users[member.userId] || new User(member.userId); const user = this.users[member.userId] || new User(member.userId);
if (member.name) { if (member.name) {
user.setDisplayName(member.name); user.setDisplayName(member.name);
if (member.events.member) { if (member.events.member) {
user.setRawDisplayName( user.setRawDisplayName(
member.events.member.getDirectionalContent().displayname member.events.member.getDirectionalContent().displayname,
); );
} }
} }
@@ -260,7 +260,7 @@ module.exports.MatrixInMemoryStore.prototype = {
* @param {Array<MatrixEvent>} events The events to store. * @param {Array<MatrixEvent>} events The events to store.
*/ */
storeAccountDataEvents: function(events) { storeAccountDataEvents: function(events) {
let self = this; const self = this;
events.forEach(function(event) { events.forEach(function(event) {
self.accountData[event.getType()] = event; self.accountData[event.getType()] = event;
}); });

View File

@@ -19,10 +19,10 @@ limitations under the License.
* @module store/session/webstorage * @module store/session/webstorage
*/ */
let utils = require("../../utils"); const utils = require("../../utils");
let DEBUG = false; // set true to enable console logging. const DEBUG = false; // set true to enable console logging.
let E2E_PREFIX = "session.e2e."; const E2E_PREFIX = "session.e2e.";
/** /**
* Construct a web storage session store, capable of storing account keys, * Construct a web storage session store, capable of storing account keys,
@@ -37,9 +37,12 @@ function WebStorageSessionStore(webStore) {
this.store = webStore; this.store = webStore;
if (!utils.isFunction(webStore.getItem) || if (!utils.isFunction(webStore.getItem) ||
!utils.isFunction(webStore.setItem) || !utils.isFunction(webStore.setItem) ||
!utils.isFunction(webStore.removeItem)) { !utils.isFunction(webStore.removeItem) ||
!utils.isFunction(webStore.key) ||
typeof(webStore.length) !== 'number'
) {
throw new Error( throw new Error(
"Supplied webStore does not meet the WebStorage API interface" "Supplied webStore does not meet the WebStorage API interface",
); );
} }
} }
@@ -103,10 +106,10 @@ WebStorageSessionStore.prototype = {
* @param {string} session Base64 encoded end-to-end session. * @param {string} session Base64 encoded end-to-end session.
*/ */
storeEndToEndSession: function(deviceKey, sessionId, session) { storeEndToEndSession: function(deviceKey, sessionId, session) {
let sessions = this.getEndToEndSessions(deviceKey) || {}; const sessions = this.getEndToEndSessions(deviceKey) || {};
sessions[sessionId] = session; sessions[sessionId] = session;
setJsonItem( setJsonItem(
this.store, keyEndToEndSessions(deviceKey), sessions this.store, keyEndToEndSessions(deviceKey), sessions,
); );
}, },
@@ -120,13 +123,39 @@ WebStorageSessionStore.prototype = {
return getJsonItem(this.store, keyEndToEndSessions(deviceKey)); return getJsonItem(this.store, keyEndToEndSessions(deviceKey));
}, },
/**
* Retrieve a list of all known inbound group sessions
*
* @return {{senderKey: string, sessionId: string}}
*/
getAllEndToEndInboundGroupSessionKeys: function() {
const prefix = E2E_PREFIX + 'inboundgroupsessions/';
const result = [];
for (let i = 0; i < this.store.length; i++) {
const key = this.store.key(i);
if (!key.startsWith(prefix)) {
continue;
}
// we can't use split, as the components we are trying to split out
// might themselves contain '/' characters. We rely on the
// senderKey being a (32-byte) curve25519 key, base64-encoded
// (hence 43 characters long).
result.push({
senderKey: key.substr(prefix.length, 43),
sessionId: key.substr(prefix.length + 44),
});
}
return result;
},
getEndToEndInboundGroupSession: function(senderKey, sessionId) { getEndToEndInboundGroupSession: function(senderKey, sessionId) {
let key = keyEndToEndInboundGroupSession(senderKey, sessionId); const key = keyEndToEndInboundGroupSession(senderKey, sessionId);
return this.store.getItem(key); return this.store.getItem(key);
}, },
storeEndToEndInboundGroupSession: function(senderKey, sessionId, pickledSession) { storeEndToEndInboundGroupSession: function(senderKey, sessionId, pickledSession) {
let key = keyEndToEndInboundGroupSession(senderKey, sessionId); const key = keyEndToEndInboundGroupSession(senderKey, sessionId);
return this.store.setItem(key, pickledSession); return this.store.setItem(key, pickledSession);
}, },
@@ -149,8 +178,8 @@ WebStorageSessionStore.prototype = {
}, },
}; };
let KEY_END_TO_END_ACCOUNT = E2E_PREFIX + "account"; const KEY_END_TO_END_ACCOUNT = E2E_PREFIX + "account";
let KEY_END_TO_END_ANNOUNCED = E2E_PREFIX + "announced"; const KEY_END_TO_END_ANNOUNCED = E2E_PREFIX + "announced";
function keyEndToEndDevicesForUser(userId) { function keyEndToEndDevicesForUser(userId) {
return E2E_PREFIX + "devices/" + userId; return E2E_PREFIX + "devices/" + userId;

View File

@@ -23,20 +23,20 @@ limitations under the License.
* an alternative syncing API, we may want to have a proper syncing interface * an alternative syncing API, we may want to have a proper syncing interface
* for HTTP and WS at some point. * for HTTP and WS at some point.
*/ */
let q = require("q"); const q = require("q");
let User = require("./models/user"); const User = require("./models/user");
let Room = require("./models/room"); const Room = require("./models/room");
let utils = require("./utils"); const utils = require("./utils");
let Filter = require("./filter"); const Filter = require("./filter");
let EventTimeline = require("./models/event-timeline"); const EventTimeline = require("./models/event-timeline");
let DEBUG = true; const DEBUG = true;
// /sync requests allow you to set a timeout= but the request may continue // /sync requests allow you to set a timeout= but the request may continue
// beyond that and wedge forever, so we need to track how long we are willing // beyond that and wedge forever, so we need to track how long we are willing
// to keep open the connection. This constant is *ADDED* to the timeout= value // to keep open the connection. This constant is *ADDED* to the timeout= value
// to determine the max time we're willing to wait. // to determine the max time we're willing to wait.
let BUFFER_PERIOD_MS = 80 * 1000; const BUFFER_PERIOD_MS = 80 * 1000;
function getFilterName(userId, suffix) { function getFilterName(userId, suffix) {
// scope this on the user ID because people may login on many accounts // scope this on the user ID because people may login on many accounts
@@ -88,8 +88,8 @@ function SyncApi(client, opts) {
* @return {Room} * @return {Room}
*/ */
SyncApi.prototype.createRoom = function(roomId) { SyncApi.prototype.createRoom = function(roomId) {
let client = this.client; const client = this.client;
let room = new Room(roomId, { const room = new Room(roomId, {
pendingEventOrdering: this.opts.pendingEventOrdering, pendingEventOrdering: this.opts.pendingEventOrdering,
timelineSupport: client.timelineSupport, timelineSupport: client.timelineSupport,
}); });
@@ -108,7 +108,7 @@ SyncApi.prototype.createRoom = function(roomId) {
* @private * @private
*/ */
SyncApi.prototype._registerStateListeners = function(room) { SyncApi.prototype._registerStateListeners = function(room) {
let client = this.client; const client = this.client;
// we need to also re-emit room state and room member events, so hook it up // we need to also re-emit room state and room member events, so hook it up
// to the client now. We need to add a listener for RoomState.members in // to the client now. We need to add a listener for RoomState.members in
// order to hook them correctly. (TODO: find a better way?) // order to hook them correctly. (TODO: find a better way?)
@@ -122,7 +122,7 @@ SyncApi.prototype._registerStateListeners = function(room) {
[ [
"RoomMember.name", "RoomMember.typing", "RoomMember.powerLevel", "RoomMember.name", "RoomMember.typing", "RoomMember.powerLevel",
"RoomMember.membership", "RoomMember.membership",
] ],
); );
}); });
}; };
@@ -144,34 +144,34 @@ SyncApi.prototype._deregisterStateListeners = function(room) {
* @return {Promise} Resolved when they've been added to the store. * @return {Promise} Resolved when they've been added to the store.
*/ */
SyncApi.prototype.syncLeftRooms = function() { SyncApi.prototype.syncLeftRooms = function() {
let client = this.client; const client = this.client;
let self = this; const self = this;
// grab a filter with limit=1 and include_leave=true // grab a filter with limit=1 and include_leave=true
let filter = new Filter(this.client.credentials.userId); const filter = new Filter(this.client.credentials.userId);
filter.setTimelineLimit(1); filter.setTimelineLimit(1);
filter.setIncludeLeaveRooms(true); filter.setIncludeLeaveRooms(true);
let localTimeoutMs = this.opts.pollTimeout + BUFFER_PERIOD_MS; const localTimeoutMs = this.opts.pollTimeout + BUFFER_PERIOD_MS;
let qps = { const qps = {
timeout: 0, // don't want to block since this is a single isolated req timeout: 0, // don't want to block since this is a single isolated req
}; };
return client.getOrCreateFilter( return client.getOrCreateFilter(
getFilterName(client.credentials.userId, "LEFT_ROOMS"), filter getFilterName(client.credentials.userId, "LEFT_ROOMS"), filter,
).then(function(filterId) { ).then(function(filterId) {
qps.filter = filterId; qps.filter = filterId;
return client._http.authedRequest( return client._http.authedRequest(
undefined, "GET", "/sync", qps, undefined, localTimeoutMs undefined, "GET", "/sync", qps, undefined, localTimeoutMs,
); );
}).then(function(data) { }).then(function(data) {
let leaveRooms = []; let leaveRooms = [];
if (data.rooms && data.rooms.leave) { if (data.rooms && data.rooms.leave) {
leaveRooms = self._mapSyncResponseToRoomArray(data.rooms.leave); leaveRooms = self._mapSyncResponseToRoomArray(data.rooms.leave);
} }
let rooms = []; const rooms = [];
leaveRooms.forEach(function(leaveObj) { leaveRooms.forEach(function(leaveObj) {
let room = leaveObj.room; const room = leaveObj.room;
rooms.push(room); rooms.push(room);
if (!leaveObj.isBrandNewRoom) { if (!leaveObj.isBrandNewRoom) {
// the intention behind syncLeftRooms is to add in rooms which were // the intention behind syncLeftRooms is to add in rooms which were
@@ -185,9 +185,9 @@ SyncApi.prototype.syncLeftRooms = function() {
return; return;
} }
leaveObj.timeline = leaveObj.timeline || {}; leaveObj.timeline = leaveObj.timeline || {};
let timelineEvents = const timelineEvents =
self._mapSyncEventsFormat(leaveObj.timeline, room); self._mapSyncEventsFormat(leaveObj.timeline, room);
let stateEvents = self._mapSyncEventsFormat(leaveObj.state, room); const stateEvents = self._mapSyncEventsFormat(leaveObj.state, room);
// set the back-pagination token. Do this *before* adding any // set the back-pagination token. Do this *before* adding any
// events so that clients can start back-paginating. // events so that clients can start back-paginating.
@@ -212,8 +212,8 @@ SyncApi.prototype.syncLeftRooms = function() {
* store. * store.
*/ */
SyncApi.prototype.peek = function(roomId) { SyncApi.prototype.peek = function(roomId) {
let self = this; const self = this;
let client = this.client; const client = this.client;
this._peekRoomId = roomId; this._peekRoomId = roomId;
return this.client.roomInitialSync(roomId, 20).then(function(response) { return this.client.roomInitialSync(roomId, 20).then(function(response) {
// make sure things are init'd // make sure things are init'd
@@ -221,18 +221,18 @@ SyncApi.prototype.peek = function(roomId) {
response.messages.chunk = response.messages.chunk || []; response.messages.chunk = response.messages.chunk || [];
response.state = response.state || []; response.state = response.state || [];
let peekRoom = self.createRoom(roomId); const peekRoom = self.createRoom(roomId);
// FIXME: Mostly duplicated from _processRoomEvents but not entirely // FIXME: Mostly duplicated from _processRoomEvents but not entirely
// because "state" in this API is at the BEGINNING of the chunk // because "state" in this API is at the BEGINNING of the chunk
let oldStateEvents = utils.map( const oldStateEvents = utils.map(
utils.deepCopy(response.state), client.getEventMapper() utils.deepCopy(response.state), client.getEventMapper(),
); );
let stateEvents = utils.map( const stateEvents = utils.map(
response.state, client.getEventMapper() response.state, client.getEventMapper(),
); );
let messages = utils.map( const messages = utils.map(
response.messages.chunk, client.getEventMapper() response.messages.chunk, client.getEventMapper(),
); );
// XXX: copypasted from /sync until we kill off this // XXX: copypasted from /sync until we kill off this
@@ -301,7 +301,7 @@ SyncApi.prototype._peekPoll = function(roomId, token) {
return; return;
} }
let self = this; const self = this;
// FIXME: gut wrenching; hard-coded timeout values // FIXME: gut wrenching; hard-coded timeout values
this.client._http.authedRequest(undefined, "GET", "/events", { this.client._http.authedRequest(undefined, "GET", "/events", {
room_id: roomId, room_id: roomId,
@@ -332,10 +332,10 @@ SyncApi.prototype._peekPoll = function(roomId, token) {
}); });
// strip out events which aren't for the given room_id (e.g presence) // strip out events which aren't for the given room_id (e.g presence)
let events = res.chunk.filter(function(e) { const events = res.chunk.filter(function(e) {
return e.room_id === roomId; return e.room_id === roomId;
}).map(self.client.getEventMapper()); }).map(self.client.getEventMapper());
let room = self.client.getRoom(roomId); const room = self.client.getRoom(roomId);
room.addLiveEvents(events); room.addLiveEvents(events);
self._peekPoll(roomId, res.end); self._peekPoll(roomId, res.end);
}, function(err) { }, function(err) {
@@ -362,8 +362,8 @@ SyncApi.prototype.sync = function() {
debuglog("SyncApi.sync: starting with sync token " + debuglog("SyncApi.sync: starting with sync token " +
this.client.store.getSyncToken()); this.client.store.getSyncToken());
let client = this.client; const client = this.client;
let self = this; const self = this;
this._running = true; this._running = true;
@@ -401,7 +401,7 @@ SyncApi.prototype.sync = function() {
} }
client.getOrCreateFilter( client.getOrCreateFilter(
getFilterName(client.credentials.userId), filter getFilterName(client.credentials.userId), filter,
).done(function(filterId) { ).done(function(filterId) {
// reset the notifications timeline to prepare it to paginate from // reset the notifications timeline to prepare it to paginate from
// the current point in time. // the current point in time.
@@ -465,8 +465,8 @@ SyncApi.prototype.retryImmediately = function() {
* @param {boolean} syncOptions.hasSyncedBefore * @param {boolean} syncOptions.hasSyncedBefore
*/ */
SyncApi.prototype._sync = function(syncOptions) { SyncApi.prototype._sync = function(syncOptions) {
let client = this.client; const client = this.client;
let self = this; const self = this;
if (!this._running) { if (!this._running) {
debuglog("Sync no longer running: exiting."); debuglog("Sync no longer running: exiting.");
@@ -483,9 +483,9 @@ SyncApi.prototype._sync = function(syncOptions) {
filterId = this._getGuestFilter(); filterId = this._getGuestFilter();
} }
let syncToken = client.store.getSyncToken(); const syncToken = client.store.getSyncToken();
let qps = { const qps = {
filter: filterId, filter: filterId,
timeout: this.opts.pollTimeout, timeout: this.opts.pollTimeout,
}; };
@@ -508,10 +508,10 @@ SyncApi.prototype._sync = function(syncOptions) {
} }
// normal timeout= plus buffer time // normal timeout= plus buffer time
let clientSideTimeoutMs = this.opts.pollTimeout + BUFFER_PERIOD_MS; const clientSideTimeoutMs = this.opts.pollTimeout + BUFFER_PERIOD_MS;
this._currentSyncRequest = client._http.authedRequest( this._currentSyncRequest = client._http.authedRequest(
undefined, "GET", "/sync", qps, undefined, clientSideTimeoutMs undefined, "GET", "/sync", qps, undefined, clientSideTimeoutMs,
); );
this._currentSyncRequest.done(function(data) { this._currentSyncRequest.done(function(data) {
@@ -576,8 +576,8 @@ SyncApi.prototype._sync = function(syncOptions) {
* @param {Object} data The response from /sync * @param {Object} data The response from /sync
*/ */
SyncApi.prototype._processSyncResponse = function(syncToken, data) { SyncApi.prototype._processSyncResponse = function(syncToken, data) {
let client = this.client; const client = this.client;
let self = this; const self = this;
// data looks like: // data looks like:
// { // {
@@ -635,7 +635,7 @@ SyncApi.prototype._processSyncResponse = function(syncToken, data) {
// handle non-room account_data // handle non-room account_data
if (data.account_data && utils.isArray(data.account_data.events)) { if (data.account_data && utils.isArray(data.account_data.events)) {
let events = data.account_data.events.map(client.getEventMapper()); const events = data.account_data.events.map(client.getEventMapper());
client.store.storeAccountDataEvents(events); client.store.storeAccountDataEvents(events);
events.forEach( events.forEach(
function(accountDataEvent) { function(accountDataEvent) {
@@ -644,7 +644,7 @@ SyncApi.prototype._processSyncResponse = function(syncToken, data) {
} }
client.emit("accountData", accountDataEvent); client.emit("accountData", accountDataEvent);
return accountDataEvent; return accountDataEvent;
} },
); );
} }
@@ -654,19 +654,19 @@ SyncApi.prototype._processSyncResponse = function(syncToken, data) {
.map(client.getEventMapper()) .map(client.getEventMapper())
.forEach( .forEach(
function(toDeviceEvent) { function(toDeviceEvent) {
let content = toDeviceEvent.getContent(); const content = toDeviceEvent.getContent();
if ( if (
toDeviceEvent.getType() == "m.room.message" && toDeviceEvent.getType() == "m.room.message" &&
content.msgtype == "m.bad.encrypted" content.msgtype == "m.bad.encrypted"
) { ) {
console.warn( console.warn(
"Unable to decrypt to-device event: " + content.body "Unable to decrypt to-device event: " + content.body,
); );
return; return;
} }
client.emit("toDeviceEvent", toDeviceEvent); client.emit("toDeviceEvent", toDeviceEvent);
} },
); );
} }
@@ -693,8 +693,8 @@ SyncApi.prototype._processSyncResponse = function(syncToken, data) {
// Handle invites // Handle invites
inviteRooms.forEach(function(inviteObj) { inviteRooms.forEach(function(inviteObj) {
let room = inviteObj.room; const room = inviteObj.room;
let stateEvents = const stateEvents =
self._mapSyncEventsFormat(inviteObj.invite_state, room); self._mapSyncEventsFormat(inviteObj.invite_state, room);
self._processRoomEvents(room, stateEvents); self._processRoomEvents(room, stateEvents);
if (inviteObj.isBrandNewRoom) { if (inviteObj.isBrandNewRoom) {
@@ -709,19 +709,19 @@ SyncApi.prototype._processSyncResponse = function(syncToken, data) {
// Handle joins // Handle joins
joinRooms.forEach(function(joinObj) { joinRooms.forEach(function(joinObj) {
let room = joinObj.room; const room = joinObj.room;
let stateEvents = self._mapSyncEventsFormat(joinObj.state, room); const stateEvents = self._mapSyncEventsFormat(joinObj.state, room);
let timelineEvents = self._mapSyncEventsFormat(joinObj.timeline, room); const timelineEvents = self._mapSyncEventsFormat(joinObj.timeline, room);
let ephemeralEvents = self._mapSyncEventsFormat(joinObj.ephemeral); const ephemeralEvents = self._mapSyncEventsFormat(joinObj.ephemeral);
let accountDataEvents = self._mapSyncEventsFormat(joinObj.account_data); const accountDataEvents = self._mapSyncEventsFormat(joinObj.account_data);
// we do this first so it's correct when any of the events fire // we do this first so it's correct when any of the events fire
if (joinObj.unread_notifications) { if (joinObj.unread_notifications) {
room.setUnreadNotificationCount( room.setUnreadNotificationCount(
'total', joinObj.unread_notifications.notification_count 'total', joinObj.unread_notifications.notification_count,
); );
room.setUnreadNotificationCount( room.setUnreadNotificationCount(
'highlight', joinObj.unread_notifications.highlight_count 'highlight', joinObj.unread_notifications.highlight_count,
); );
} }
@@ -748,7 +748,7 @@ SyncApi.prototype._processSyncResponse = function(syncToken, data) {
// will stop us linking the empty timeline into the chain). // will stop us linking the empty timeline into the chain).
// //
for (let i = timelineEvents.length - 1; i >= 0; i--) { for (let i = timelineEvents.length - 1; i >= 0; i--) {
let eventId = timelineEvents[i].getId(); const eventId = timelineEvents[i].getId();
if (room.getTimelineForEvent(eventId)) { if (room.getTimelineForEvent(eventId)) {
debuglog("Already have event " + eventId + " in limited " + debuglog("Already have event " + eventId + " in limited " +
"sync - not resetting"); "sync - not resetting");
@@ -818,12 +818,12 @@ SyncApi.prototype._processSyncResponse = function(syncToken, data) {
// Handle leaves (e.g. kicked rooms) // Handle leaves (e.g. kicked rooms)
leaveRooms.forEach(function(leaveObj) { leaveRooms.forEach(function(leaveObj) {
let room = leaveObj.room; const room = leaveObj.room;
let stateEvents = const stateEvents =
self._mapSyncEventsFormat(leaveObj.state, room); self._mapSyncEventsFormat(leaveObj.state, room);
let timelineEvents = const timelineEvents =
self._mapSyncEventsFormat(leaveObj.timeline, room); self._mapSyncEventsFormat(leaveObj.timeline, room);
let accountDataEvents = const accountDataEvents =
self._mapSyncEventsFormat(leaveObj.account_data); self._mapSyncEventsFormat(leaveObj.account_data);
self._processRoomEvents(room, stateEvents, timelineEvents); self._processRoomEvents(room, stateEvents, timelineEvents);
@@ -876,11 +876,11 @@ SyncApi.prototype._startKeepAlives = function(delay) {
if (this._keepAliveTimer !== null) { if (this._keepAliveTimer !== null) {
clearTimeout(this._keepAliveTimer); clearTimeout(this._keepAliveTimer);
} }
let self = this; const self = this;
if (delay > 0) { if (delay > 0) {
self._keepAliveTimer = setTimeout( self._keepAliveTimer = setTimeout(
self._pokeKeepAlive.bind(self), self._pokeKeepAlive.bind(self),
delay delay,
); );
} else { } else {
self._pokeKeepAlive(); self._pokeKeepAlive();
@@ -895,7 +895,7 @@ SyncApi.prototype._startKeepAlives = function(delay) {
* *
*/ */
SyncApi.prototype._pokeKeepAlive = function() { SyncApi.prototype._pokeKeepAlive = function() {
let self = this; const self = this;
function success() { function success() {
clearTimeout(self._keepAliveTimer); clearTimeout(self._keepAliveTimer);
if (self._connectionReturnedDefer) { if (self._connectionReturnedDefer) {
@@ -912,7 +912,7 @@ SyncApi.prototype._pokeKeepAlive = function() {
{ {
prefix: '', prefix: '',
localTimeoutMs: 15 * 1000, localTimeoutMs: 15 * 1000,
} },
).done(function() { ).done(function() {
success(); success();
}, function(err) { }, function(err) {
@@ -926,7 +926,7 @@ SyncApi.prototype._pokeKeepAlive = function() {
} else { } else {
self._keepAliveTimer = setTimeout( self._keepAliveTimer = setTimeout(
self._pokeKeepAlive.bind(self), self._pokeKeepAlive.bind(self),
5000 + Math.floor(Math.random() * 5000) 5000 + Math.floor(Math.random() * 5000),
); );
// A keepalive has failed, so we emit the // A keepalive has failed, so we emit the
// error state (whether or not this is the // error state (whether or not this is the
@@ -947,10 +947,10 @@ SyncApi.prototype._mapSyncResponseToRoomArray = function(obj) {
// Maps { roomid: {stuff}, roomid: {stuff} } // Maps { roomid: {stuff}, roomid: {stuff} }
// to // to
// [{stuff+Room+isBrandNewRoom}, {stuff+Room+isBrandNewRoom}] // [{stuff+Room+isBrandNewRoom}, {stuff+Room+isBrandNewRoom}]
let client = this.client; const client = this.client;
let self = this; const self = this;
return utils.keys(obj).map(function(roomId) { return utils.keys(obj).map(function(roomId) {
let arrObj = obj[roomId]; const arrObj = obj[roomId];
let room = client.store.getRoom(roomId); let room = client.store.getRoom(roomId);
let isBrandNewRoom = false; let isBrandNewRoom = false;
if (!room) { if (!room) {
@@ -972,7 +972,7 @@ SyncApi.prototype._mapSyncEventsFormat = function(obj, room) {
if (!obj || !utils.isArray(obj.events)) { if (!obj || !utils.isArray(obj.events)) {
return []; return [];
} }
let mapper = this.client.getEventMapper(); const mapper = this.client.getEventMapper();
return obj.events.map(function(e) { return obj.events.map(function(e) {
if (room) { if (room) {
e.room_id = room.roomId; e.room_id = room.roomId;
@@ -988,7 +988,7 @@ SyncApi.prototype._resolveInvites = function(room) {
if (!room || !this.opts.resolveInvitesToProfiles) { if (!room || !this.opts.resolveInvitesToProfiles) {
return; return;
} }
let client = this.client; const client = this.client;
// For each invited room member we want to give them a displayname/avatar url // For each invited room member we want to give them a displayname/avatar url
// if they have one (the m.room.member invites don't contain this). // if they have one (the m.room.member invites don't contain this).
room.getMembersWithMembership("invite").forEach(function(member) { room.getMembersWithMembership("invite").forEach(function(member) {
@@ -997,7 +997,7 @@ SyncApi.prototype._resolveInvites = function(room) {
} }
member._requestedProfileInfo = true; member._requestedProfileInfo = true;
// try to get a cached copy first. // try to get a cached copy first.
let user = client.getUser(member.userId); const user = client.getUser(member.userId);
let promise; let promise;
if (user) { if (user) {
promise = q({ promise = q({
@@ -1011,7 +1011,7 @@ SyncApi.prototype._resolveInvites = function(room) {
// slightly naughty by doctoring the invite event but this means all // slightly naughty by doctoring the invite event but this means all
// the code paths remain the same between invite/join display name stuff // the code paths remain the same between invite/join display name stuff
// which is a worthy trade-off for some minor pollution. // which is a worthy trade-off for some minor pollution.
let inviteEvent = member.events.member; const inviteEvent = member.events.member;
if (inviteEvent.getContent().membership !== "invite") { if (inviteEvent.getContent().membership !== "invite") {
// between resolving and now they have since joined, so don't clobber // between resolving and now they have since joined, so don't clobber
return; return;
@@ -1036,19 +1036,19 @@ SyncApi.prototype._resolveInvites = function(room) {
SyncApi.prototype._processRoomEvents = function(room, stateEventList, SyncApi.prototype._processRoomEvents = function(room, stateEventList,
timelineEventList) { timelineEventList) {
timelineEventList = timelineEventList || []; timelineEventList = timelineEventList || [];
let client = this.client; const client = this.client;
// "old" and "current" state are the same initially; they // "old" and "current" state are the same initially; they
// start diverging if the user paginates. // start diverging if the user paginates.
// We must deep copy otherwise membership changes in old state // We must deep copy otherwise membership changes in old state
// will leak through to current state! // will leak through to current state!
let oldStateEvents = utils.map( const oldStateEvents = utils.map(
utils.deepCopy( utils.deepCopy(
stateEventList.map(function(mxEvent) { stateEventList.map(function(mxEvent) {
return mxEvent.event; return mxEvent.event;
}) }),
), client.getEventMapper() ), client.getEventMapper(),
); );
let stateEvents = stateEventList; const stateEvents = stateEventList;
// set the state of the room to as it was before the timeline executes // set the state of the room to as it was before the timeline executes
// //
@@ -1068,7 +1068,7 @@ SyncApi.prototype._processRoomEvents = function(room, stateEventList,
// gather our notifications into this._notifEvents // gather our notifications into this._notifEvents
if (client.getNotifTimelineSet()) { if (client.getNotifTimelineSet()) {
for (let i = 0; i < timelineEventList.length; i++) { for (let i = 0; i < timelineEventList.length; i++) {
let pushActions = client.getPushActionsForEvent(timelineEventList[i]); const pushActions = client.getPushActionsForEvent(timelineEventList[i]);
if (pushActions && pushActions.notify && if (pushActions && pushActions.notify &&
pushActions.tweaks && pushActions.tweaks.highlight) { pushActions.tweaks && pushActions.tweaks.highlight) {
this._notifEvents.push(timelineEventList[i]); this._notifEvents.push(timelineEventList[i]);
@@ -1085,7 +1085,7 @@ SyncApi.prototype._processRoomEvents = function(room, stateEventList,
* @return {string} * @return {string}
*/ */
SyncApi.prototype._getGuestFilter = function() { SyncApi.prototype._getGuestFilter = function() {
let guestRooms = this.client._guestRooms; // FIXME: horrible gut-wrenching const guestRooms = this.client._guestRooms; // FIXME: horrible gut-wrenching
if (!guestRooms) { if (!guestRooms) {
return "{}"; return "{}";
} }
@@ -1106,7 +1106,7 @@ SyncApi.prototype._getGuestFilter = function() {
* @param {Object} data Object of additional data to emit in the event * @param {Object} data Object of additional data to emit in the event
*/ */
SyncApi.prototype._updateSyncState = function(newState, data) { SyncApi.prototype._updateSyncState = function(newState, data) {
let old = this._syncState; const old = this._syncState;
this._syncState = newState; this._syncState = newState;
this.client.emit("sync", this._syncState, old, data); this.client.emit("sync", this._syncState, old, data);
}; };
@@ -1123,7 +1123,7 @@ SyncApi.prototype._onOnline = function() {
}; };
function createNewUser(client, userId) { function createNewUser(client, userId) {
let user = new User(userId); const user = new User(userId);
reEmit(client, user, [ reEmit(client, user, [
"User.avatarUrl", "User.displayName", "User.presence", "User.avatarUrl", "User.displayName", "User.presence",
"User.currentlyActive", "User.lastPresenceTs", "User.currentlyActive", "User.lastPresenceTs",
@@ -1140,7 +1140,7 @@ function reEmit(reEmitEntity, emittableEntity, eventNames) {
// Transformation Example: // Transformation Example:
// listener on "foo" => function(a,b) { ... } // listener on "foo" => function(a,b) { ... }
// Re-emit on "thing" => thing.emit("foo", a, b) // Re-emit on "thing" => thing.emit("foo", a, b)
let newArgs = [eventName]; const newArgs = [eventName];
for (let i = 0; i < arguments.length; i++) { for (let i = 0; i < arguments.length; i++) {
newArgs.push(arguments[i]); newArgs.push(arguments[i]);
} }

View File

@@ -17,25 +17,25 @@ limitations under the License.
/** @module timeline-window */ /** @module timeline-window */
let q = require("q"); const q = require("q");
let EventTimeline = require("./models/event-timeline"); const EventTimeline = require("./models/event-timeline");
/** /**
* @private * @private
*/ */
let DEBUG = false; const DEBUG = false;
/** /**
* @private * @private
*/ */
let debuglog = DEBUG ? console.log.bind(console) : function() {}; const debuglog = DEBUG ? console.log.bind(console) : function() {};
/** /**
* the number of times we ask the server for more events before giving up * the number of times we ask the server for more events before giving up
* *
* @private * @private
*/ */
let DEFAULT_PAGINATE_LOOP_LIMIT = 5; const DEFAULT_PAGINATE_LOOP_LIMIT = 5;
/** /**
* Construct a TimelineWindow. * Construct a TimelineWindow.
@@ -92,15 +92,15 @@ function TimelineWindow(client, timelineSet, opts) {
* @return {module:client.Promise} * @return {module:client.Promise}
*/ */
TimelineWindow.prototype.load = function(initialEventId, initialWindowSize) { TimelineWindow.prototype.load = function(initialEventId, initialWindowSize) {
let self = this; const self = this;
initialWindowSize = initialWindowSize || 20; initialWindowSize = initialWindowSize || 20;
// given an EventTimeline, and an event index within it, initialise our // given an EventTimeline, and an event index within it, initialise our
// fields so that the event in question is in the middle of the window. // fields so that the event in question is in the middle of the window.
let initFields = function(timeline, eventIndex) { const initFields = function(timeline, eventIndex) {
let endIndex = Math.min(timeline.getEvents().length, const endIndex = Math.min(timeline.getEvents().length,
eventIndex + Math.ceil(initialWindowSize / 2)); eventIndex + Math.ceil(initialWindowSize / 2));
let startIndex = Math.max(0, endIndex - initialWindowSize); const startIndex = Math.max(0, endIndex - initialWindowSize);
self._start = new TimelineIndex(timeline, startIndex - timeline.getBaseIndex()); self._start = new TimelineIndex(timeline, startIndex - timeline.getBaseIndex());
self._end = new TimelineIndex(timeline, endIndex - timeline.getBaseIndex()); self._end = new TimelineIndex(timeline, endIndex - timeline.getBaseIndex());
self._eventCount = endIndex - startIndex; self._eventCount = endIndex - startIndex;
@@ -126,7 +126,7 @@ TimelineWindow.prototype.load = function(initialEventId, initialWindowSize) {
}); });
} else { } else {
// start with the most recent events // start with the most recent events
let tl = this._timelineSet.getLiveTimeline(); const tl = this._timelineSet.getLiveTimeline();
initFields(tl, tl.getEvents().length); initFields(tl, tl.getEvents().length);
return q(); return q();
} }
@@ -228,7 +228,7 @@ TimelineWindow.prototype.paginate = function(direction, size, makeRequest,
} }
// try moving the cap // try moving the cap
let count = (direction == EventTimeline.BACKWARDS) ? const count = (direction == EventTimeline.BACKWARDS) ?
tl.retreat(size) : tl.advance(size); tl.retreat(size) : tl.advance(size);
if (count) { if (count) {
@@ -236,7 +236,7 @@ TimelineWindow.prototype.paginate = function(direction, size, makeRequest,
debuglog("TimelineWindow: increased cap by " + count + debuglog("TimelineWindow: increased cap by " + count +
" (now " + this._eventCount + ")"); " (now " + this._eventCount + ")");
// remove some events from the other end, if necessary // remove some events from the other end, if necessary
let excess = this._eventCount - this._windowLimit; const excess = this._eventCount - this._windowLimit;
if (excess > 0) { if (excess > 0) {
this.unpaginate(excess, direction != EventTimeline.BACKWARDS); this.unpaginate(excess, direction != EventTimeline.BACKWARDS);
} }
@@ -250,16 +250,16 @@ TimelineWindow.prototype.paginate = function(direction, size, makeRequest,
} }
// try making a pagination request // try making a pagination request
let token = tl.timeline.getPaginationToken(direction); const token = tl.timeline.getPaginationToken(direction);
if (!token) { if (!token) {
debuglog("TimelineWindow: no token"); debuglog("TimelineWindow: no token");
return q(false); return q(false);
} }
debuglog("TimelineWindow: starting request"); debuglog("TimelineWindow: starting request");
let self = this; const self = this;
let prom = this._client.paginateEventTimeline(tl.timeline, { const prom = this._client.paginateEventTimeline(tl.timeline, {
backwards: direction == EventTimeline.BACKWARDS, backwards: direction == EventTimeline.BACKWARDS,
limit: size, limit: size,
}).finally(function() { }).finally(function() {
@@ -298,7 +298,7 @@ TimelineWindow.prototype.paginate = function(direction, size, makeRequest,
* of the timeline. * of the timeline.
*/ */
TimelineWindow.prototype.unpaginate = function(delta, startOfTimeline) { TimelineWindow.prototype.unpaginate = function(delta, startOfTimeline) {
let tl = startOfTimeline ? this._start : this._end; const tl = startOfTimeline ? this._start : this._end;
// sanity-check the delta // sanity-check the delta
if (delta > this._eventCount || delta < 0) { if (delta > this._eventCount || delta < 0) {
@@ -307,7 +307,7 @@ TimelineWindow.prototype.unpaginate = function(delta, startOfTimeline) {
} }
while (delta > 0) { while (delta > 0) {
let count = startOfTimeline ? tl.advance(delta) : tl.retreat(delta); const count = startOfTimeline ? tl.advance(delta) : tl.retreat(delta);
if (count <= 0) { if (count <= 0) {
// sadness. This shouldn't be possible. // sadness. This shouldn't be possible.
throw new Error( throw new Error(
@@ -334,13 +334,13 @@ TimelineWindow.prototype.getEvents = function() {
return []; return [];
} }
let result = []; const result = [];
// iterate through each timeline between this._start and this._end // iterate through each timeline between this._start and this._end
// (inclusive). // (inclusive).
let timeline = this._start.timeline; let timeline = this._start.timeline;
while (true) { while (true) {
let events = timeline.getEvents(); const events = timeline.getEvents();
// For the first timeline in the chain, we want to start at // For the first timeline in the chain, we want to start at
// this._start.index. For the last timeline in the chain, we want to // this._start.index. For the last timeline in the chain, we want to
@@ -447,7 +447,7 @@ TimelineIndex.prototype.advance = function(delta) {
// the index is already at the start/end of the current timeline. // the index is already at the start/end of the current timeline.
// //
// next see if there is a neighbouring timeline to switch to. // next see if there is a neighbouring timeline to switch to.
let neighbour = this.timeline.getNeighbouringTimeline( const neighbour = this.timeline.getNeighbouringTimeline(
delta < 0 ? EventTimeline.BACKWARDS : EventTimeline.FORWARDS); delta < 0 ? EventTimeline.BACKWARDS : EventTimeline.FORWARDS);
if (neighbour) { if (neighbour) {
this.timeline = neighbour; this.timeline = neighbour;

View File

@@ -27,7 +27,7 @@ limitations under the License.
*/ */
module.exports.encodeParams = function(params) { module.exports.encodeParams = function(params) {
let qs = ""; let qs = "";
for (let key in params) { for (const key in params) {
if (!params.hasOwnProperty(key)) { if (!params.hasOwnProperty(key)) {
continue; continue;
} }
@@ -46,12 +46,12 @@ module.exports.encodeParams = function(params) {
* @return {string} The result of replacing all template variables e.g. '/foo/baz'. * @return {string} The result of replacing all template variables e.g. '/foo/baz'.
*/ */
module.exports.encodeUri = function(pathTemplate, variables) { module.exports.encodeUri = function(pathTemplate, variables) {
for (let key in variables) { for (const key in variables) {
if (!variables.hasOwnProperty(key)) { if (!variables.hasOwnProperty(key)) {
continue; continue;
} }
pathTemplate = pathTemplate.replace( pathTemplate = pathTemplate.replace(
key, encodeURIComponent(variables[key]) key, encodeURIComponent(variables[key]),
); );
} }
return pathTemplate; return pathTemplate;
@@ -65,7 +65,7 @@ module.exports.encodeUri = function(pathTemplate, variables) {
* @return {Array} A new array with the results of the function. * @return {Array} A new array with the results of the function.
*/ */
module.exports.map = function(array, fn) { module.exports.map = function(array, fn) {
let results = new Array(array.length); const results = new Array(array.length);
for (let i = 0; i < array.length; i++) { for (let i = 0; i < array.length; i++) {
results[i] = fn(array[i]); results[i] = fn(array[i]);
} }
@@ -81,7 +81,7 @@ module.exports.map = function(array, fn) {
* @return {Array} A new array with the results of the function. * @return {Array} A new array with the results of the function.
*/ */
module.exports.filter = function(array, fn) { module.exports.filter = function(array, fn) {
let results = []; const results = [];
for (let i = 0; i < array.length; i++) { for (let i = 0; i < array.length; i++) {
if (fn(array[i], i, array)) { if (fn(array[i], i, array)) {
results.push(array[i]); results.push(array[i]);
@@ -96,8 +96,8 @@ module.exports.filter = function(array, fn) {
* @return {string[]} The keys of the object. * @return {string[]} The keys of the object.
*/ */
module.exports.keys = function(obj) { module.exports.keys = function(obj) {
let keys = []; const keys = [];
for (let key in obj) { for (const key in obj) {
if (!obj.hasOwnProperty(key)) { if (!obj.hasOwnProperty(key)) {
continue; continue;
} }
@@ -112,8 +112,8 @@ module.exports.keys = function(obj) {
* @return {Array<*>} The values of the object. * @return {Array<*>} The values of the object.
*/ */
module.exports.values = function(obj) { module.exports.values = function(obj) {
let values = []; const values = [];
for (let key in obj) { for (const key in obj) {
if (!obj.hasOwnProperty(key)) { if (!obj.hasOwnProperty(key)) {
continue; continue;
} }
@@ -235,7 +235,7 @@ module.exports.checkObjectHasKeys = function(obj, keys) {
* @throws If there are extra keys. * @throws If there are extra keys.
*/ */
module.exports.checkObjectHasNoAdditionalKeys = function(obj, allowedKeys) { module.exports.checkObjectHasNoAdditionalKeys = function(obj, allowedKeys) {
for (let key in obj) { for (const key in obj) {
if (!obj.hasOwnProperty(key)) { if (!obj.hasOwnProperty(key)) {
continue; continue;
} }
@@ -263,7 +263,7 @@ module.exports.deepCopy = function(obj) {
* *
* @return {boolean} true if the two objects are equal * @return {boolean} true if the two objects are equal
*/ */
let deepCompare = module.exports.deepCompare = function(x, y) { const deepCompare = module.exports.deepCompare = function(x, y) {
// Inspired by // Inspired by
// http://stackoverflow.com/questions/1068834/object-comparison-in-javascript#1144249 // http://stackoverflow.com/questions/1068834/object-comparison-in-javascript#1144249
@@ -355,10 +355,10 @@ let deepCompare = module.exports.deepCompare = function(x, y) {
* @return {Object} target * @return {Object} target
*/ */
module.exports.extend = function() { module.exports.extend = function() {
let target = arguments[0] || {}; const target = arguments[0] || {};
for (let i = 1; i < arguments.length; i++) { for (let i = 1; i < arguments.length; i++) {
let source = arguments[i]; const source = arguments[i];
for (let propName in source) { // eslint-disable-line guard-for-in for (const propName in source) { // eslint-disable-line guard-for-in
target[propName] = source[propName]; target[propName] = source[propName];
} }
} }
@@ -379,17 +379,17 @@ module.exports.runPolyfills = function() {
throw new TypeError(); throw new TypeError();
} }
let t = Object(this); const t = Object(this);
let len = t.length >>> 0; const len = t.length >>> 0;
if (typeof fun !== 'function') { if (typeof fun !== 'function') {
throw new TypeError(); throw new TypeError();
} }
let res = []; const res = [];
let thisArg = arguments.length >= 2 ? arguments[1] : void 0; const thisArg = arguments.length >= 2 ? arguments[1] : void 0;
for (let i = 0; i < len; i++) { for (let i = 0; i < len; i++) {
if (i in t) { if (i in t) {
let val = t[i]; const val = t[i];
// NOTE: Technically this should Object.defineProperty at // NOTE: Technically this should Object.defineProperty at
// the next index, as push can be affected by // the next index, as push can be affected by
@@ -414,7 +414,7 @@ module.exports.runPolyfills = function() {
// Reference: http://es5.github.io/#x15.4.4.19 // Reference: http://es5.github.io/#x15.4.4.19
if (!Array.prototype.map) { if (!Array.prototype.map) {
Array.prototype.map = function(callback, thisArg) { Array.prototype.map = function(callback, thisArg) {
let T, A, k; let T, k;
if (this === null || this === undefined) { if (this === null || this === undefined) {
throw new TypeError(' this is null or not defined'); throw new TypeError(' this is null or not defined');
@@ -422,12 +422,12 @@ module.exports.runPolyfills = function() {
// 1. Let O be the result of calling ToObject passing the |this| // 1. Let O be the result of calling ToObject passing the |this|
// value as the argument. // value as the argument.
let O = Object(this); const O = Object(this);
// 2. Let lenValue be the result of calling the Get internal // 2. Let lenValue be the result of calling the Get internal
// method of O with the argument "length". // method of O with the argument "length".
// 3. Let len be ToUint32(lenValue). // 3. Let len be ToUint32(lenValue).
let len = O.length >>> 0; const len = O.length >>> 0;
// 4. If IsCallable(callback) is false, throw a TypeError exception. // 4. If IsCallable(callback) is false, throw a TypeError exception.
// See: http://es5.github.com/#x9.11 // See: http://es5.github.com/#x9.11
@@ -443,7 +443,7 @@ module.exports.runPolyfills = function() {
// 6. Let A be a new array created as if by the expression new Array(len) // 6. Let A be a new array created as if by the expression new Array(len)
// where Array is the standard built-in constructor with that name and // where Array is the standard built-in constructor with that name and
// len is the value of len. // len is the value of len.
A = new Array(len); const A = new Array(len);
// 7. Let k be 0 // 7. Let k be 0
k = 0; k = 0;
@@ -512,12 +512,12 @@ module.exports.runPolyfills = function() {
// 1. Let O be the result of calling ToObject passing the |this| value as the // 1. Let O be the result of calling ToObject passing the |this| value as the
// argument. // argument.
let O = Object(this); const O = Object(this);
// 2. Let lenValue be the result of calling the Get internal method of O with the // 2. Let lenValue be the result of calling the Get internal method of O with the
// argument "length". // argument "length".
// 3. Let len be ToUint32(lenValue). // 3. Let len be ToUint32(lenValue).
let len = O.length >>> 0; const len = O.length >>> 0;
// 4. If IsCallable(callback) is false, throw a TypeError exception. // 4. If IsCallable(callback) is false, throw a TypeError exception.
// See: http://es5.github.com/#x9.11 // See: http://es5.github.com/#x9.11
@@ -582,7 +582,7 @@ module.exports.inherits = function(ctor, superCtor) {
function Temp() {} function Temp() {}
// make a safe reference to Object.prototype.hasOwnProperty // make a safe reference to Object.prototype.hasOwnProperty
let hasOwn = Object.prototype.hasOwnProperty; const hasOwn = Object.prototype.hasOwnProperty;
return function(O) { return function(O) {
// 1. If Type(O) is not Object or Null throw a TypeError exception. // 1. If Type(O) is not Object or Null throw a TypeError exception.
@@ -595,7 +595,7 @@ module.exports.inherits = function(ctor, superCtor) {
// constructor with that name // constructor with that name
// 3. Set the [[Prototype]] internal property of obj to O. // 3. Set the [[Prototype]] internal property of obj to O.
Temp.prototype = O; Temp.prototype = O;
let obj = new Temp(); const obj = new Temp();
Temp.prototype = null; // Let's not keep a stray reference to O... Temp.prototype = null; // Let's not keep a stray reference to O...
// 4. If the argument Properties is present and not undefined, add // 4. If the argument Properties is present and not undefined, add
@@ -604,8 +604,8 @@ module.exports.inherits = function(ctor, superCtor) {
// Properties. // Properties.
if (arguments.length > 1) { if (arguments.length > 1) {
// Object.defineProperties does ToObject on its first argument. // Object.defineProperties does ToObject on its first argument.
let Properties = Object(arguments[1]); const Properties = Object(arguments[1]);
for (let prop in Properties) { for (const prop in Properties) {
if (hasOwn.call(Properties, prop)) { if (hasOwn.call(Properties, prop)) {
obj[prop] = Properties[prop]; obj[prop] = Properties[prop];
} }

View File

@@ -18,9 +18,9 @@ limitations under the License.
* This is an internal module. See {@link createNewMatrixCall} for the public API. * This is an internal module. See {@link createNewMatrixCall} for the public API.
* @module webrtc/call * @module webrtc/call
*/ */
let utils = require("../utils"); const utils = require("../utils");
let EventEmitter = require("events").EventEmitter; const EventEmitter = require("events").EventEmitter;
let DEBUG = true; // set true to enable console logging. const DEBUG = true; // set true to enable console logging.
// events: hangup, error(err), replaced(call), state(state, oldState) // events: hangup, error(err), replaced(call), state(state, oldState)
@@ -125,24 +125,24 @@ MatrixCall.prototype.placeScreenSharingCall =
function(remoteVideoElement, localVideoElement) { function(remoteVideoElement, localVideoElement) {
debuglog("placeScreenSharingCall"); debuglog("placeScreenSharingCall");
checkForErrorListener(this); checkForErrorListener(this);
let screenConstraints = _getChromeScreenSharingConstraints(this); const screenConstraints = _getChromeScreenSharingConstraints(this);
if (!screenConstraints) { if (!screenConstraints) {
return; return;
} }
this.localVideoElement = localVideoElement; this.localVideoElement = localVideoElement;
this.remoteVideoElement = remoteVideoElement; this.remoteVideoElement = remoteVideoElement;
let self = this; const self = this;
this.webRtc.getUserMedia(screenConstraints, function(stream) { this.webRtc.getUserMedia(screenConstraints, function(stream) {
self.screenSharingStream = stream; self.screenSharingStream = stream;
debuglog("Got screen stream, requesting audio stream..."); debuglog("Got screen stream, requesting audio stream...");
let audioConstraints = _getUserMediaVideoContraints('voice'); const audioConstraints = _getUserMediaVideoContraints('voice');
_placeCallWithConstraints(self, audioConstraints); _placeCallWithConstraints(self, audioConstraints);
}, function(err) { }, function(err) {
self.emit("error", self.emit("error",
callError( callError(
MatrixCall.ERR_NO_USER_MEDIA, MatrixCall.ERR_NO_USER_MEDIA,
"Failed to get screen-sharing stream: " + err "Failed to get screen-sharing stream: " + err,
) ),
); );
}); });
this.type = 'video'; this.type = 'video';
@@ -266,9 +266,9 @@ MatrixCall.prototype.setLocalVideoElement = function(element) {
this.URL.createObjectURL(this.localAVStream), this.URL.createObjectURL(this.localAVStream),
"localVideo"); "localVideo");
element.muted = true; element.muted = true;
let self = this; const self = this;
setTimeout(function() { setTimeout(function() {
let vel = self.getLocalVideoElement(); const vel = self.getLocalVideoElement();
if (vel.play) { if (vel.play) {
self.playElement(vel, "localVideo"); self.playElement(vel, "localVideo");
} }
@@ -306,12 +306,12 @@ MatrixCall.prototype.setRemoteAudioElement = function(element) {
MatrixCall.prototype._initWithInvite = function(event) { MatrixCall.prototype._initWithInvite = function(event) {
this.msg = event.getContent(); this.msg = event.getContent();
this.peerConn = _createPeerConnection(this); this.peerConn = _createPeerConnection(this);
let self = this; const self = this;
if (this.peerConn) { if (this.peerConn) {
this.peerConn.setRemoteDescription( this.peerConn.setRemoteDescription(
new this.webRtc.RtcSessionDescription(this.msg.offer), new this.webRtc.RtcSessionDescription(this.msg.offer),
hookCallback(self, self._onSetRemoteDescriptionSuccess), hookCallback(self, self._onSetRemoteDescriptionSuccess),
hookCallback(self, self._onSetRemoteDescriptionError) hookCallback(self, self._onSetRemoteDescriptionError),
); );
} }
setState(this, 'ringing'); setState(this, 'ringing');
@@ -364,13 +364,13 @@ MatrixCall.prototype._initWithHangup = function(event) {
*/ */
MatrixCall.prototype.answer = function() { MatrixCall.prototype.answer = function() {
debuglog("Answering call %s of type %s", this.callId, this.type); debuglog("Answering call %s of type %s", this.callId, this.type);
let self = this; const self = this;
if (!this.localAVStream && !this.waitForLocalAVStream) { if (!this.localAVStream && !this.waitForLocalAVStream) {
this.webRtc.getUserMedia( this.webRtc.getUserMedia(
_getUserMediaVideoContraints(this.type), _getUserMediaVideoContraints(this.type),
hookCallback(self, self._gotUserMediaForAnswer), hookCallback(self, self._gotUserMediaForAnswer),
hookCallback(self, self._getUserMediaFailed) hookCallback(self, self._getUserMediaFailed),
); );
setState(this, 'wait_local_media'); setState(this, 'wait_local_media');
} else if (this.localAVStream) { } else if (this.localAVStream) {
@@ -416,7 +416,7 @@ MatrixCall.prototype._replacedBy = function(newCall) {
MatrixCall.prototype.hangup = function(reason, suppressEvent) { MatrixCall.prototype.hangup = function(reason, suppressEvent) {
debuglog("Ending call " + this.callId); debuglog("Ending call " + this.callId);
terminate(this, "local", reason, !suppressEvent); terminate(this, "local", reason, !suppressEvent);
let content = { const content = {
version: 0, version: 0,
call_id: this.callId, call_id: this.callId,
reason: reason, reason: reason,
@@ -492,8 +492,8 @@ MatrixCall.prototype._gotUserMediaForInvite = function(stream) {
return; return;
} }
debuglog("_gotUserMediaForInvite -> " + this.type); debuglog("_gotUserMediaForInvite -> " + this.type);
let self = this; const self = this;
let videoEl = this.getLocalVideoElement(); const videoEl = this.getLocalVideoElement();
if (videoEl && this.type == 'video') { if (videoEl && this.type == 'video') {
videoEl.autoplay = true; videoEl.autoplay = true;
@@ -509,15 +509,17 @@ MatrixCall.prototype._gotUserMediaForInvite = function(stream) {
} }
videoEl.muted = true; videoEl.muted = true;
setTimeout(function() { setTimeout(function() {
let vel = self.getLocalVideoElement(); const vel = self.getLocalVideoElement();
if (vel.play) { if (vel.play) {
self.playElement(vel, "localVideo"); self.playElement(vel, "localVideo");
} }
}, 0); }, 0);
} }
if (this.screenSharingStream) {
this.screenSharingStream.addTrack(stream.getAudioTracks()[0]); this.screenSharingStream.addTrack(stream.getAudioTracks()[0]);
stream = this.screenSharingStream; stream = this.screenSharingStream;
}
this.localAVStream = stream; this.localAVStream = stream;
// why do we enable audio (and only audio) tracks here? -- matthew // why do we enable audio (and only audio) tracks here? -- matthew
@@ -526,7 +528,7 @@ MatrixCall.prototype._gotUserMediaForInvite = function(stream) {
this.peerConn.addStream(stream); this.peerConn.addStream(stream);
this.peerConn.createOffer( this.peerConn.createOffer(
hookCallback(self, self._gotLocalOffer), hookCallback(self, self._gotLocalOffer),
hookCallback(self, self._getLocalOfferFailed) hookCallback(self, self._getLocalOfferFailed),
); );
setState(self, 'create_offer'); setState(self, 'create_offer');
}; };
@@ -537,11 +539,11 @@ MatrixCall.prototype._gotUserMediaForInvite = function(stream) {
* @param {Object} stream * @param {Object} stream
*/ */
MatrixCall.prototype._gotUserMediaForAnswer = function(stream) { MatrixCall.prototype._gotUserMediaForAnswer = function(stream) {
let self = this; const self = this;
if (self.state == 'ended') { if (self.state == 'ended') {
return; return;
} }
let localVidEl = self.getLocalVideoElement(); const localVidEl = self.getLocalVideoElement();
if (localVidEl && self.type == 'video') { if (localVidEl && self.type == 'video') {
localVidEl.autoplay = true; localVidEl.autoplay = true;
@@ -550,7 +552,7 @@ MatrixCall.prototype._gotUserMediaForAnswer = function(stream) {
"localVideo"); "localVideo");
localVidEl.muted = true; localVidEl.muted = true;
setTimeout(function() { setTimeout(function() {
let vel = self.getLocalVideoElement(); const vel = self.getLocalVideoElement();
if (vel.play) { if (vel.play) {
self.playElement(vel, "localVideo"); self.playElement(vel, "localVideo");
} }
@@ -561,7 +563,7 @@ MatrixCall.prototype._gotUserMediaForAnswer = function(stream) {
setTracksEnabled(stream.getAudioTracks(), true); setTracksEnabled(stream.getAudioTracks(), true);
self.peerConn.addStream(stream); self.peerConn.addStream(stream);
let constraints = { const constraints = {
'mandatory': { 'mandatory': {
'OfferToReceiveAudio': true, 'OfferToReceiveAudio': true,
'OfferToReceiveVideo': self.type == 'video', 'OfferToReceiveVideo': self.type == 'video',
@@ -570,7 +572,7 @@ MatrixCall.prototype._gotUserMediaForAnswer = function(stream) {
self.peerConn.createAnswer(function(description) { self.peerConn.createAnswer(function(description) {
debuglog("Created answer: " + description); debuglog("Created answer: " + description);
self.peerConn.setLocalDescription(description, function() { self.peerConn.setLocalDescription(description, function() {
let content = { const content = {
version: 0, version: 0,
call_id: self.callId, call_id: self.callId,
answer: { answer: {
@@ -598,11 +600,11 @@ MatrixCall.prototype._gotLocalIceCandidate = function(event) {
if (event.candidate) { if (event.candidate) {
debuglog( debuglog(
"Got local ICE " + event.candidate.sdpMid + " candidate: " + "Got local ICE " + event.candidate.sdpMid + " candidate: " +
event.candidate.candidate event.candidate.candidate,
); );
// As with the offer, note we need to make a copy of this object, not // As with the offer, note we need to make a copy of this object, not
// pass the original: that broke in Chrome ~m43. // pass the original: that broke in Chrome ~m43.
let c = { const c = {
candidate: event.candidate.candidate, candidate: event.candidate.candidate,
sdpMid: event.candidate.sdpMid, sdpMid: event.candidate.sdpMid,
sdpMLineIndex: event.candidate.sdpMLineIndex, sdpMLineIndex: event.candidate.sdpMLineIndex,
@@ -625,7 +627,7 @@ MatrixCall.prototype._gotRemoteIceCandidate = function(cand) {
this.peerConn.addIceCandidate( this.peerConn.addIceCandidate(
new this.webRtc.RtcIceCandidate(cand), new this.webRtc.RtcIceCandidate(cand),
function() {}, function() {},
function(e) {} function(e) {},
); );
}; };
@@ -639,11 +641,11 @@ MatrixCall.prototype._receivedAnswer = function(msg) {
return; return;
} }
let self = this; const self = this;
this.peerConn.setRemoteDescription( this.peerConn.setRemoteDescription(
new this.webRtc.RtcSessionDescription(msg.answer), new this.webRtc.RtcSessionDescription(msg.answer),
hookCallback(self, self._onSetRemoteDescriptionSuccess), hookCallback(self, self._onSetRemoteDescriptionSuccess),
hookCallback(self, self._onSetRemoteDescriptionError) hookCallback(self, self._onSetRemoteDescriptionError),
); );
setState(self, 'connecting'); setState(self, 'connecting');
}; };
@@ -654,7 +656,7 @@ MatrixCall.prototype._receivedAnswer = function(msg) {
* @param {Object} description * @param {Object} description
*/ */
MatrixCall.prototype._gotLocalOffer = function(description) { MatrixCall.prototype._gotLocalOffer = function(description) {
let self = this; const self = this;
debuglog("Created offer: " + description); debuglog("Created offer: " + description);
if (self.state == 'ended') { if (self.state == 'ended') {
@@ -664,7 +666,7 @@ MatrixCall.prototype._gotLocalOffer = function(description) {
} }
self.peerConn.setLocalDescription(description, function() { self.peerConn.setLocalDescription(description, function() {
let content = { const content = {
version: 0, version: 0,
call_id: self.callId, call_id: self.callId,
// OpenWebRTC appears to add extra stuff (like the DTLS fingerprint) // OpenWebRTC appears to add extra stuff (like the DTLS fingerprint)
@@ -703,7 +705,7 @@ MatrixCall.prototype._gotLocalOffer = function(description) {
MatrixCall.prototype._getLocalOfferFailed = function(error) { MatrixCall.prototype._getLocalOfferFailed = function(error) {
this.emit( this.emit(
"error", "error",
callError(MatrixCall.ERR_LOCAL_OFFER_FAILED, "Failed to start audio for call!") callError(MatrixCall.ERR_LOCAL_OFFER_FAILED, "Failed to start audio for call!"),
); );
}; };
@@ -718,8 +720,8 @@ MatrixCall.prototype._getUserMediaFailed = function(error) {
callError( callError(
MatrixCall.ERR_NO_USER_MEDIA, MatrixCall.ERR_NO_USER_MEDIA,
"Couldn't start capturing media! Is your microphone set up and " + "Couldn't start capturing media! Is your microphone set up and " +
"does this app have permission?" "does this app have permission?",
) ),
); );
this.hangup("user_media_failed"); this.hangup("user_media_failed");
}; };
@@ -733,7 +735,7 @@ MatrixCall.prototype._onIceConnectionStateChanged = function() {
return; // because ICE can still complete as we're ending the call return; // because ICE can still complete as we're ending the call
} }
debuglog( debuglog(
"Ice connection state changed to: " + this.peerConn.iceConnectionState "Ice connection state changed to: " + this.peerConn.iceConnectionState,
); );
// ideally we'd consider the call to be connected when we get media but // ideally we'd consider the call to be connected when we get media but
// chrome doesn't implement any of the 'onstarted' events yet // chrome doesn't implement any of the 'onstarted' events yet
@@ -753,7 +755,7 @@ MatrixCall.prototype._onIceConnectionStateChanged = function() {
MatrixCall.prototype._onSignallingStateChanged = function() { MatrixCall.prototype._onSignallingStateChanged = function() {
debuglog( debuglog(
"call " + this.callId + ": Signalling state changed to: " + "call " + this.callId + ": Signalling state changed to: " +
this.peerConn.signalingState this.peerConn.signalingState,
); );
}; };
@@ -782,7 +784,7 @@ MatrixCall.prototype._onSetRemoteDescriptionError = function(e) {
MatrixCall.prototype._onAddStream = function(event) { MatrixCall.prototype._onAddStream = function(event) {
debuglog("Stream id " + event.stream.id + " added"); debuglog("Stream id " + event.stream.id + " added");
let s = event.stream; const s = event.stream;
if (s.getVideoTracks().length > 0) { if (s.getVideoTracks().length > 0) {
this.type = 'video'; this.type = 'video';
@@ -793,7 +795,7 @@ MatrixCall.prototype._onAddStream = function(event) {
this.remoteAStream = s; this.remoteAStream = s;
} }
let self = this; const self = this;
forAllTracksOnStream(s, function(t) { forAllTracksOnStream(s, function(t) {
debuglog("Track id " + t.id + " added"); debuglog("Track id " + t.id + " added");
// not currently implemented in chrome // not currently implemented in chrome
@@ -872,13 +874,13 @@ MatrixCall.prototype._onAnsweredElsewhere = function(msg) {
terminate(this, "remote", "answered_elsewhere", true); terminate(this, "remote", "answered_elsewhere", true);
}; };
let setTracksEnabled = function(tracks, enabled) { const setTracksEnabled = function(tracks, enabled) {
for (let i = 0; i < tracks.length; i++) { for (let i = 0; i < tracks.length; i++) {
tracks[i].enabled = enabled; tracks[i].enabled = enabled;
} }
}; };
let isTracksEnabled = function(tracks) { const isTracksEnabled = function(tracks) {
for (let i = 0; i < tracks.length; i++) { for (let i = 0; i < tracks.length; i++) {
if (tracks[i].enabled) { if (tracks[i].enabled) {
return true; // at least one track is enabled return true; // at least one track is enabled
@@ -887,8 +889,8 @@ let isTracksEnabled = function(tracks) {
return false; return false;
}; };
let setState = function(self, state) { const setState = function(self, state) {
let oldState = self.state; const oldState = self.state;
self.state = state; self.state = state;
self.emit("state", state, oldState); self.emit("state", state, oldState);
}; };
@@ -900,11 +902,11 @@ let setState = function(self, state) {
* @param {Object} content * @param {Object} content
* @return {Promise} * @return {Promise}
*/ */
let sendEvent = function(self, eventType, content) { const sendEvent = function(self, eventType, content) {
return self.client.sendEvent(self.roomId, eventType, content); return self.client.sendEvent(self.roomId, eventType, content);
}; };
let sendCandidate = function(self, content) { const sendCandidate = function(self, content) {
// Sends candidates with are sent in a special way because we try to amalgamate // Sends candidates with are sent in a special way because we try to amalgamate
// them into one message // them into one message
self.candidateSendQueue.push(content); self.candidateSendQueue.push(content);
@@ -915,7 +917,7 @@ let sendCandidate = function(self, content) {
} }
}; };
let terminate = function(self, hangupParty, hangupReason, shouldEmit) { const terminate = function(self, hangupParty, hangupReason, shouldEmit) {
if (self.getRemoteVideoElement()) { if (self.getRemoteVideoElement()) {
if (self.getRemoteVideoElement().pause) { if (self.getRemoteVideoElement().pause) {
self.pauseElement(self.getRemoteVideoElement(), "remoteVideo"); self.pauseElement(self.getRemoteVideoElement(), "remoteVideo");
@@ -946,7 +948,7 @@ let terminate = function(self, hangupParty, hangupReason, shouldEmit) {
} }
}; };
let stopAllMedia = function(self) { const stopAllMedia = function(self) {
debuglog("stopAllMedia (stream=%s)", self.localAVStream); debuglog("stopAllMedia (stream=%s)", self.localAVStream);
if (self.localAVStream) { if (self.localAVStream) {
forAllTracksOnStream(self.localAVStream, function(t) { forAllTracksOnStream(self.localAVStream, function(t) {
@@ -986,15 +988,15 @@ let stopAllMedia = function(self) {
} }
}; };
let _tryPlayRemoteStream = function(self) { const _tryPlayRemoteStream = function(self) {
if (self.getRemoteVideoElement() && self.remoteAVStream) { if (self.getRemoteVideoElement() && self.remoteAVStream) {
let player = self.getRemoteVideoElement(); const player = self.getRemoteVideoElement();
player.autoplay = true; player.autoplay = true;
self.assignElement(player, self.assignElement(player,
self.URL.createObjectURL(self.remoteAVStream), self.URL.createObjectURL(self.remoteAVStream),
"remoteVideo"); "remoteVideo");
setTimeout(function() { setTimeout(function() {
let vel = self.getRemoteVideoElement(); const vel = self.getRemoteVideoElement();
if (vel.play) { if (vel.play) {
self.playElement(vel, "remoteVideo"); self.playElement(vel, "remoteVideo");
} }
@@ -1006,15 +1008,15 @@ let _tryPlayRemoteStream = function(self) {
} }
}; };
let _tryPlayRemoteAudioStream = function(self) { const _tryPlayRemoteAudioStream = function(self) {
if (self.getRemoteAudioElement() && self.remoteAStream) { if (self.getRemoteAudioElement() && self.remoteAStream) {
let player = self.getRemoteAudioElement(); const player = self.getRemoteAudioElement();
player.autoplay = true; player.autoplay = true;
self.assignElement(player, self.assignElement(player,
self.URL.createObjectURL(self.remoteAStream), self.URL.createObjectURL(self.remoteAStream),
"remoteAudio"); "remoteAudio");
setTimeout(function() { setTimeout(function() {
let ael = self.getRemoteAudioElement(); const ael = self.getRemoteAudioElement();
if (ael.play) { if (ael.play) {
self.playElement(ael, "remoteAudio"); self.playElement(ael, "remoteAudio");
} }
@@ -1026,35 +1028,35 @@ let _tryPlayRemoteAudioStream = function(self) {
} }
}; };
let checkForErrorListener = function(self) { const checkForErrorListener = function(self) {
if (self.listeners("error").length === 0) { if (self.listeners("error").length === 0) {
throw new Error( throw new Error(
"You MUST attach an error listener using call.on('error', function() {})" "You MUST attach an error listener using call.on('error', function() {})",
); );
} }
}; };
let callError = function(code, msg) { const callError = function(code, msg) {
let e = new Error(msg); const e = new Error(msg);
e.code = code; e.code = code;
return e; return e;
}; };
let debuglog = function() { const debuglog = function() {
if (DEBUG) { if (DEBUG) {
console.log(...arguments); console.log(...arguments);
} }
}; };
let _sendCandidateQueue = function(self) { const _sendCandidateQueue = function(self) {
if (self.candidateSendQueue.length === 0) { if (self.candidateSendQueue.length === 0) {
return; return;
} }
let cands = self.candidateSendQueue; const cands = self.candidateSendQueue;
self.candidateSendQueue = []; self.candidateSendQueue = [];
++self.candidateSendTries; ++self.candidateSendTries;
let content = { const content = {
version: 0, version: 0,
call_id: self.callId, call_id: self.callId,
candidates: cands, candidates: cands,
@@ -1071,13 +1073,13 @@ let _sendCandidateQueue = function(self) {
if (self.candidateSendTries > 5) { if (self.candidateSendTries > 5) {
debuglog( debuglog(
"Failed to send candidates on attempt %s. Giving up for now.", "Failed to send candidates on attempt %s. Giving up for now.",
self.candidateSendTries self.candidateSendTries,
); );
self.candidateSendTries = 0; self.candidateSendTries = 0;
return; return;
} }
let delayMs = 500 * Math.pow(2, self.candidateSendTries); const delayMs = 500 * Math.pow(2, self.candidateSendTries);
++self.candidateSendTries; ++self.candidateSendTries;
debuglog("Failed to send candidates. Retrying in " + delayMs + "ms"); debuglog("Failed to send candidates. Retrying in " + delayMs + "ms");
setTimeout(function() { setTimeout(function() {
@@ -1086,19 +1088,19 @@ let _sendCandidateQueue = function(self) {
}); });
}; };
let _placeCallWithConstraints = function(self, constraints) { const _placeCallWithConstraints = function(self, constraints) {
self.client.callList[self.callId] = self; self.client.callList[self.callId] = self;
self.webRtc.getUserMedia( self.webRtc.getUserMedia(
constraints, constraints,
hookCallback(self, self._gotUserMediaForInvite), hookCallback(self, self._gotUserMediaForInvite),
hookCallback(self, self._getUserMediaFailed) hookCallback(self, self._getUserMediaFailed),
); );
setState(self, 'wait_local_media'); setState(self, 'wait_local_media');
self.direction = 'outbound'; self.direction = 'outbound';
self.config = constraints; self.config = constraints;
}; };
let _createPeerConnection = function(self) { const _createPeerConnection = function(self) {
let servers = self.turnServers; let servers = self.turnServers;
if (self.webRtc.vendor === "mozilla") { if (self.webRtc.vendor === "mozilla") {
// modify turnServers struct to match what mozilla expects. // modify turnServers struct to match what mozilla expects.
@@ -1114,7 +1116,7 @@ let _createPeerConnection = function(self) {
} }
} }
let pc = new self.webRtc.RtcPeerConnection({ const pc = new self.webRtc.RtcPeerConnection({
iceServers: servers, iceServers: servers,
}); });
pc.oniceconnectionstatechange = hookCallback(self, self._onIceConnectionStateChanged); pc.oniceconnectionstatechange = hookCallback(self, self._onIceConnectionStateChanged);
@@ -1124,12 +1126,12 @@ let _createPeerConnection = function(self) {
return pc; return pc;
}; };
let _getChromeScreenSharingConstraints = function(call) { const _getChromeScreenSharingConstraints = function(call) {
let screen = global.screen; const screen = global.screen;
if (!screen) { if (!screen) {
call.emit("error", callError( call.emit("error", callError(
MatrixCall.ERR_NO_USER_MEDIA, MatrixCall.ERR_NO_USER_MEDIA,
"Couldn't determine screen sharing constaints." "Couldn't determine screen sharing constaints.",
)); ));
return; return;
} }
@@ -1148,7 +1150,7 @@ let _getChromeScreenSharingConstraints = function(call) {
}; };
}; };
let _getUserMediaVideoContraints = function(callType) { const _getUserMediaVideoContraints = function(callType) {
switch (callType) { switch (callType) {
case 'voice': case 'voice':
return ({audio: true, video: false}); return ({audio: true, video: false});
@@ -1164,27 +1166,27 @@ let _getUserMediaVideoContraints = function(callType) {
} }
}; };
let hookCallback = function(call, fn) { const hookCallback = function(call, fn) {
return function() { return function() {
return fn.apply(call, arguments); return fn.apply(call, arguments);
}; };
}; };
let forAllVideoTracksOnStream = function(s, f) { const forAllVideoTracksOnStream = function(s, f) {
let tracks = s.getVideoTracks(); const tracks = s.getVideoTracks();
for (let i = 0; i < tracks.length; i++) { for (let i = 0; i < tracks.length; i++) {
f(tracks[i]); f(tracks[i]);
} }
}; };
let forAllAudioTracksOnStream = function(s, f) { const forAllAudioTracksOnStream = function(s, f) {
let tracks = s.getAudioTracks(); const tracks = s.getAudioTracks();
for (let i = 0; i < tracks.length; i++) { for (let i = 0; i < tracks.length; i++) {
f(tracks[i]); f(tracks[i]);
} }
}; };
let forAllTracksOnStream = function(s, f) { const forAllTracksOnStream = function(s, f) {
forAllVideoTracksOnStream(s, f); forAllVideoTracksOnStream(s, f);
forAllAudioTracksOnStream(s, f); forAllAudioTracksOnStream(s, f);
}; };
@@ -1200,14 +1202,14 @@ module.exports.MatrixCall = MatrixCall;
* @return {MatrixCall} the call or null if the browser doesn't support calling. * @return {MatrixCall} the call or null if the browser doesn't support calling.
*/ */
module.exports.createNewMatrixCall = function(client, roomId) { module.exports.createNewMatrixCall = function(client, roomId) {
let w = global.window; const w = global.window;
let doc = global.document; const doc = global.document;
if (!w || !doc) { if (!w || !doc) {
return null; return null;
} }
let webRtc = {}; const webRtc = {};
webRtc.isOpenWebRTC = function() { webRtc.isOpenWebRTC = function() {
let scripts = doc.getElementById("script"); const scripts = doc.getElementById("script");
if (!scripts || !scripts.length) { if (!scripts || !scripts.length) {
return false; return false;
} }
@@ -1218,7 +1220,7 @@ module.exports.createNewMatrixCall = function(client, roomId) {
} }
return false; return false;
}; };
let getUserMedia = ( const getUserMedia = (
w.navigator.getUserMedia || w.navigator.webkitGetUserMedia || w.navigator.getUserMedia || w.navigator.webkitGetUserMedia ||
w.navigator.mozGetUserMedia w.navigator.mozGetUserMedia
); );
@@ -1249,7 +1251,7 @@ module.exports.createNewMatrixCall = function(client, roomId) {
!webRtc.RtcPeerConnection || !webRtc.getUserMedia) { !webRtc.RtcPeerConnection || !webRtc.getUserMedia) {
return null; // WebRTC is not supported. return null; // WebRTC is not supported.
} }
let opts = { const opts = {
webRtc: webRtc, webRtc: webRtc,
client: client, client: client,
URL: w.URL, URL: w.URL,