/* * vim: ts=4:sw=4:expandtab */ (function () { 'use strict'; window.Whisper = window.Whisper || {}; Whisper.KeyVerificationPanelView = Whisper.View.extend({ className: 'key-verification panel', templateName: 'key-verification', events: { 'click button.verify': 'toggleVerified', }, initialize: function(options) { this.ourNumber = textsecure.storage.user.getNumber(); if (options.newKey) { this.theirKey = options.newKey; } this.loadKeys().then(function() { this.listenTo(this.model, 'change', this.render); }.bind(this)); }, loadKeys: function() { return Promise.all([ this.loadTheirKey(), this.loadOurKey(), ]).then(this.generateSecurityNumber.bind(this)) .then(this.render.bind(this)); //.then(this.makeQRCode.bind(this)); }, makeQRCode: function() { // Per Lilia: We can't turn this on until it generates a Latin1 string, as is // required by the mobile clients. new QRCode(this.$('.qr')[0]).makeCode( dcodeIO.ByteBuffer.wrap(this.ourKey).toString('base64') ); }, loadTheirKey: function() { return textsecure.storage.protocol.loadIdentityKey( this.model.id ).then(function(theirKey) { this.theirKey = theirKey; }.bind(this)); }, loadOurKey: function() { return textsecure.storage.protocol.loadIdentityKey( this.ourNumber ).then(function(ourKey) { this.ourKey = ourKey; }.bind(this)); }, generateSecurityNumber: function() { return new libsignal.FingerprintGenerator(5200).createFor( this.ourNumber, this.ourKey, this.model.id, this.theirKey ).then(function(securityNumber) { this.securityNumber = securityNumber; }.bind(this)); }, onSafetyNumberChanged: function() { this.model.getProfiles().then(this.loadKeys.bind(this)); var dialog = new Whisper.ConfirmationDialogView({ message: i18n('changedRightAfterVerify', [this.model.getTitle(), this.model.getTitle()]), hideCancel: true }); dialog.$el.insertBefore(this.el); dialog.focusCancel(); }, toggleVerified: function() { this.$('button.verify').attr('disabled', true); this.model.toggleVerified().catch(function(result) { if (result instanceof Error) { if (result.name === 'OutgoingIdentityKeyError') { this.onSafetyNumberChanged(); } else { console.log('failed to toggle verified:', result.stack); } } else { var keyError = _.some(result.errors, function(error) { return error.name === 'OutgoingIdentityKeyError'; }); if (keyError) { this.onSafetyNumberChanged(); } else { _.forEach(result.errors, function(error) { console.log('failed to toggle verified:', error.stack); }); } } }.bind(this)).then(function() { this.$('button.verify').removeAttr('disabled'); }.bind(this)); }, render_attributes: function() { var s = this.securityNumber; var chunks = []; for (var i = 0; i < s.length; i += 5) { chunks.push(s.substring(i, i+5)); } var name = this.model.getTitle(); var yourSafetyNumberWith = i18n('yourSafetyNumberWith', name); var isVerified = this.model.isVerified(); var verifyButton = isVerified ? i18n('unverify') : i18n('verify'); var verifiedStatus = isVerified ? i18n('isVerified', name) : i18n('isNotVerified', name); return { learnMore : i18n('learnMore'), theirKeyUnknown : i18n('theirIdentityUnknown'), yourSafetyNumberWith : i18n('yourSafetyNumberWith', this.model.getTitle()), verifyHelp : i18n('verifyHelp', this.model.getTitle()), verifyButton : verifyButton, hasTheirKey : this.theirKey !== undefined, chunks : chunks, isVerified : isVerified, verifiedStatus : verifiedStatus }; } }); })();