diff --git a/src/MatrixClientPeg.js b/src/MatrixClientPeg.js
index b31cf7511e..4264828c7b 100644
--- a/src/MatrixClientPeg.js
+++ b/src/MatrixClientPeg.js
@@ -78,6 +78,18 @@ class MatrixClientPeg {
}
async start() {
+ // try to initialise e2e on the new client
+ try {
+ // check that we have a version of the js-sdk which includes initCrypto
+ if (this.matrixClient.initCrypto) {
+ await this.matrixClient.initCrypto();
+ }
+ } catch(e) {
+ // this can happen for a number of reasons, the most likely being
+ // that the olm library was missing. It's not fatal.
+ console.warn("Unable to initialise e2e: " + e);
+ }
+
const opts = utils.deepCopy(this.opts);
// the react sdk doesn't work without this, so don't allow
opts.pendingEventOrdering = "detached";
diff --git a/src/SlashCommands.js b/src/SlashCommands.js
index b1cd59f3a9..dea3d27751 100644
--- a/src/SlashCommands.js
+++ b/src/SlashCommands.js
@@ -301,51 +301,54 @@ const commands = {
const deviceId = matches[2];
const fingerprint = matches[3];
- const device = MatrixClientPeg.get().getStoredDevice(userId, deviceId);
- if (!device) {
- return reject(_t(`Unknown (user, device) pair:`) + ` (${userId}, ${deviceId})`);
- }
+ return success(
+ // Promise.resolve to handle transition from static result to promise; can be removed
+ // in future
+ Promise.resolve(MatrixClientPeg.get().getStoredDevice(userId, deviceId)).then((device) => {
+ if (!device) {
+ throw new Error(_t(`Unknown (user, device) pair:`) + ` (${userId}, ${deviceId})`);
+ }
- if (device.isVerified()) {
- if (device.getFingerprint() === fingerprint) {
- return reject(_t(`Device already verified!`));
- } else {
- return reject(_t(`WARNING: Device already verified, but keys do NOT MATCH!`));
- }
- }
+ if (device.isVerified()) {
+ if (device.getFingerprint() === fingerprint) {
+ throw new Error(_t(`Device already verified!`));
+ } else {
+ throw new Error(_t(`WARNING: Device already verified, but keys do NOT MATCH!`));
+ }
+ }
- if (device.getFingerprint() === fingerprint) {
- MatrixClientPeg.get().setDeviceVerified(
- userId, deviceId, true,
- );
+ if (device.getFingerprint() !== fingerprint) {
+ const fprint = device.getFingerprint();
+ throw new Error(
+ _t('WARNING: KEY VERIFICATION FAILED! The signing key for %(userId)s and device' +
+ ' %(deviceId)s is "%(fprint)s" which does not match the provided key' +
+ ' "%(fingerprint)s". This could mean your communications are being intercepted!',
+ {deviceId: deviceId, fprint: fprint, userId: userId, fingerprint: fingerprint}));
+ }
- // Tell the user we verified everything!
- const QuestionDialog = sdk.getComponent("dialogs.QuestionDialog");
- Modal.createDialog(QuestionDialog, {
- title: _t("Verified key"),
- description: (
-
-
- {
- _t("The signing key you provided matches the signing key you received " +
- "from %(userId)s's device %(deviceId)s. Device marked as verified.",
- {userId: userId, deviceId: deviceId})
- }
-
-
- ),
- hasCancelButton: false,
- });
-
- return success();
- } else {
- const fprint = device.getFingerprint();
- return reject(
- _t('WARNING: KEY VERIFICATION FAILED! The signing key for %(userId)s and device' +
- ' %(deviceId)s is "%(fprint)s" which does not match the provided key' +
- ' "%(fingerprint)s". This could mean your communications are being intercepted!',
- {deviceId: deviceId, fprint: fprint, userId: userId, fingerprint: fingerprint}));
- }
+ return MatrixClientPeg.get().setDeviceVerified(
+ userId, deviceId, true,
+ );
+ }).then(() => {
+ // Tell the user we verified everything
+ const QuestionDialog = sdk.getComponent("dialogs.QuestionDialog");
+ Modal.createDialog(QuestionDialog, {
+ title: _t("Verified key"),
+ description: (
+
+
+ {
+ _t("The signing key you provided matches the signing key you received " +
+ "from %(userId)s's device %(deviceId)s. Device marked as verified.",
+ {userId: userId, deviceId: deviceId})
+ }
+
+
+ ),
+ hasCancelButton: false,
+ });
+ }),
+ );
}
}
return reject(this.getUsage());
diff --git a/src/async-components/views/dialogs/EncryptedEventDialog.js b/src/async-components/views/dialogs/EncryptedEventDialog.js
index 3a6ca4e6b7..cec2f05de2 100644
--- a/src/async-components/views/dialogs/EncryptedEventDialog.js
+++ b/src/async-components/views/dialogs/EncryptedEventDialog.js
@@ -28,23 +28,31 @@ module.exports = React.createClass({
},
getInitialState: function() {
- return { device: this.refreshDevice() };
+ return { device: null };
},
componentWillMount: function() {
this._unmounted = false;
var client = MatrixClientPeg.get();
- client.on("deviceVerificationChanged", this.onDeviceVerificationChanged);
- // no need to redownload keys if we already have the device
- if (this.state.device) {
- return;
- }
- client.downloadKeys([this.props.event.getSender()], true).done(()=>{
+ // first try to load the device from our store.
+ //
+ this.refreshDevice().then((dev) => {
+ if (dev) {
+ return dev;
+ }
+
+ // tell the client to try to refresh the device list for this user
+ return client.downloadKeys([this.props.event.getSender()], true).then(() => {
+ return this.refreshDevice();
+ });
+ }).then((dev) => {
if (this._unmounted) {
return;
}
- this.setState({ device: this.refreshDevice() });
+
+ this.setState({ device: dev });
+ client.on("deviceVerificationChanged", this.onDeviceVerificationChanged);
}, (err)=>{
console.log("Error downloading devices", err);
});
@@ -59,12 +67,16 @@ module.exports = React.createClass({
},
refreshDevice: function() {
- return MatrixClientPeg.get().getEventSenderDeviceInfo(this.props.event);
+ // Promise.resolve to handle transition from static result to promise; can be removed
+ // in future
+ return Promise.resolve(MatrixClientPeg.get().getEventSenderDeviceInfo(this.props.event));
},
onDeviceVerificationChanged: function(userId, device) {
if (userId == this.props.event.getSender()) {
- this.setState({ device: this.refreshDevice() });
+ this.refreshDevice().then((dev) => {
+ this.setState({ device: dev });
+ });
}
},
diff --git a/src/components/views/rooms/EventTile.js b/src/components/views/rooms/EventTile.js
index bb085279e8..68ef3a1f44 100644
--- a/src/components/views/rooms/EventTile.js
+++ b/src/components/views/rooms/EventTile.js
@@ -193,13 +193,12 @@ module.exports = withMatrixClient(React.createClass({
}
},
- _verifyEvent: function(mxEvent) {
- var verified = null;
-
- if (mxEvent.isEncrypted()) {
- verified = this.props.matrixClient.isEventSenderVerified(mxEvent);
+ _verifyEvent: async function(mxEvent) {
+ if (!mxEvent.isEncrypted()) {
+ return;
}
+ const verified = await this.props.matrixClient.isEventSenderVerified(mxEvent);
this.setState({
verified: verified
});
diff --git a/src/components/views/rooms/MemberInfo.js b/src/components/views/rooms/MemberInfo.js
index c034f0e704..290bd35483 100644
--- a/src/components/views/rooms/MemberInfo.js
+++ b/src/components/views/rooms/MemberInfo.js
@@ -136,8 +136,12 @@ module.exports = withMatrixClient(React.createClass({
if (userId == this.props.member.userId) {
// no need to re-download the whole thing; just update our copy of
// the list.
- var devices = this.props.matrixClient.getStoredDevicesForUser(userId);
- this.setState({devices: devices});
+
+ // Promise.resolve to handle transition from static result to promise; can be removed
+ // in future
+ Promise.resolve(this.props.matrixClient.getStoredDevicesForUser(userId)).then((devices) => {
+ this.setState({devices: devices});
+ });
}
},
@@ -204,14 +208,15 @@ module.exports = withMatrixClient(React.createClass({
var client = this.props.matrixClient;
var self = this;
- client.downloadKeys([member.userId], true).finally(function() {
+ client.downloadKeys([member.userId], true).then(() => {
+ return client.getStoredDevicesForUser(member.userId);
+ }).finally(function() {
self._cancelDeviceList = null;
- }).done(function() {
+ }).done(function(devices) {
if (cancelled) {
// we got cancelled - presumably a different user now
return;
}
- var devices = client.getStoredDevicesForUser(member.userId);
self._disambiguateDevices(devices);
self.setState({devicesLoading: false, devices: devices});
}, function(err) {