diff --git a/background.html b/background.html index 92379761fc..84bfedd203 100644 --- a/background.html +++ b/background.html @@ -24,6 +24,7 @@ + diff --git a/index.html b/index.html index 265ef1c11e..46201c21ba 100644 --- a/index.html +++ b/index.html @@ -135,6 +135,7 @@ + diff --git a/js/errors.js b/js/errors.js new file mode 100644 index 0000000000..9cd5149be7 --- /dev/null +++ b/js/errors.js @@ -0,0 +1,76 @@ +/* vim: ts=4:sw=4:expandtab + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program. If not, see . + */ + +;(function() { + 'use strict'; + + var registeredFunctions = {}; + var Type = { + SEND_MESSAGE: 1, + INIT_SESSION: 2, + }; + window.textsecure = window.textsecure || {}; + window.textsecure.replay = { + Type: Type, + registerFunction: function(func, functionCode) { + registeredFunctions[functionCode] = func; + } + }; + + function ReplayableError(options) { + options = options || {}; + this.name = options.name || 'ReplayableError'; + this.functionCode = options.functionCode; + this.args = options.args; + } + ReplayableError.prototype = new Error(); + ReplayableError.prototype.constructor = ReplayableError; + + ReplayableError.prototype.replay = function() { + var args = Array.prototype.slice.call(arguments); + args.shift(); + args = this.args.concat(args); + + registeredFunctions[this.functionCode].apply(window, args); + }; + + function IncomingIdentityKeyError(number, message) { + ReplayableError.call(this, { + functionCode : Type.INIT_SESSION, + args : [number, message] + }); + this.name = 'IncomingIdentityKeyError'; + this.message = "The identity of the sender has changed. This may be malicious, or the sender may have simply reinstalled TextSecure."; + } + IncomingIdentityKeyError.prototype = new ReplayableError(); + IncomingIdentityKeyError.prototype.constructor = IncomingIdentityKeyError; + + function OutgoingIdentityKeyError(number, message) { + ReplayableError.call(this, { + functionCode : Type.SEND_MESSAGE, + args : [number, message] + }); + this.name = 'OutgoingIdentityKeyError'; + this.message = "The identity of the destination has changed. This may be malicious, or the destination may have simply reinstalled TextSecure."; + } + OutgoingIdentityKeyError.prototype = new ReplayableError(); + OutgoingIdentityKeyError.prototype.constructor = OutgoingIdentityKeyError; + + window.textsecure.IncomingIdentityKeyError = IncomingIdentityKeyError; + window.textsecure.OutgoingIdentityKeyError = OutgoingIdentityKeyError; + window.textsecure.ReplayableError = ReplayableError; + +})(); diff --git a/js/helpers.js b/js/helpers.js index ca68abe695..dc1c6a39c3 100644 --- a/js/helpers.js +++ b/js/helpers.js @@ -126,41 +126,6 @@ window.textsecure.throwHumanError = function(error, type, humanError) { throw e; } -window.textsecure.replay = function() { - var self = {}; - - self.REPLAY_FUNCS = { - SEND_MESSAGE: 1, - INIT_SESSION: 2, - } - - var functions = {}; - - self.registerReplayFunction = function(func, functionCode) { - functions[functionCode] = func; - } - - self.replayError = function(replayData) { - var args = Array.prototype.slice.call(arguments); - args.shift(); - args = replayData.args.concat(args); - functions[replayData.replayFunction].apply(window, args); - } - - self.createReplayableError = function(shortMsg, longMsg, replayFunction, args) { - var e = new Error(shortMsg); - e.name = "ReplayableError"; - e.humanError = e.longMessage = longMsg; - e.replayData = { replayFunction: replayFunction, args: args }; - e.replay = function() { - self.replayError(e.replayData); - } - return e; - } - - return self; -}(); - // message_callback({message: decryptedMessage, pushMessage: server-providedPushMessage}) window.textsecure.subscribeToPush = function(message_callback) { var socket = textsecure.api.getMessageWebsocket(); diff --git a/js/protocol.js b/js/protocol.js index 53bae4479b..8d5d9813f9 100644 --- a/js/protocol.js +++ b/js/protocol.js @@ -366,7 +366,7 @@ window.textsecure.protocol = function() { //TODO: Wipe identity key! return handlePreKeyWhisperMessage(from, encodedMessage); } - textsecure.replay.registerReplayFunction(wipeIdentityAndTryMessageAgain, textsecure.replay.REPLAY_FUNCS.INIT_SESSION); + textsecure.replay.registerFunction(wipeIdentityAndTryMessageAgain, textsecure.replay.Type.INIT_SESSION); initSessionFromPreKeyWhisperMessage = function(encodedNumber, message) { var preKeyPair = crypto_storage.getStoredKeyPair("preKey" + message.preKeyId); @@ -394,7 +394,7 @@ window.textsecure.protocol = function() { closeSession(open_session); // To be returned and saved later } else { // ...otherwise create an error that the UI will pick up and ask the user if they want to re-negotiate - throw new Error("Received message with unknown identity key", "The identity of the sender has changed. This may be malicious, or the sender may have simply reinstalled TextSecure.", textsecure.replay.REPLAY_FUNCS.INIT_SESSION, [encodedNumber, getString(message.encode())]); + throw new textsecure.IncomingIdentityKeyError(encodedNumber, getString(message.encode())); } } return initSession(false, preKeyPair, signedPreKeyPair, encodedNumber, toArrayBuffer(message.identityKey), toArrayBuffer(message.baseKey), undefined) diff --git a/js/sendmessage.js b/js/sendmessage.js index abb7db0a3b..9db62f6d26 100644 --- a/js/sendmessage.js +++ b/js/sendmessage.js @@ -117,11 +117,11 @@ window.textsecure.messaging = function() { var tryMessageAgain = function(number, encodedMessage, callback) { //TODO: Wipe identity key! refreshGroups(number).then(function() { - var message = textsecure.protobuf.PushMessageContent.decode(encodedMessage, 'binary'); - textsecure.sendMessage([number], message, callback); + var message = textsecure.protobuf.PushMessageContent.decode(encodedMessage); + textsecure.sendMessageProto([number], message, callback); }); }; - textsecure.replay.registerReplayFunction(tryMessageAgain, textsecure.replay.SEND_MESSAGE); + textsecure.replay.registerFunction(tryMessageAgain, textsecure.replay.Type.SEND_MESSAGE); var sendMessageProto = function(numbers, message, callback) { var numbersCompleted = 0; @@ -175,8 +175,7 @@ window.textsecure.messaging = function() { if (error.message !== "Identity key changed") registerError(number, "Failed to reload device keys", error); else { - error = textsecure.replay.createReplayableError("The destination's identity key has changed", "The identity of the destination has changed. This may be malicious, or the destination may have simply reinstalled TextSecure.", - textsecure.replay.SEND_MESSAGE, [number, getString(message.encode())]); + error = new textsecure.OutgoingIdentityKeyError(encodedNumber, message.encode()); registerError(number, "Identity key changed", error); } }); diff --git a/options.html b/options.html index fb53fb46db..a31e7c0259 100644 --- a/options.html +++ b/options.html @@ -103,6 +103,7 @@ + diff --git a/test/index.html b/test/index.html index d30d2faad2..630e012a8f 100644 --- a/test/index.html +++ b/test/index.html @@ -129,6 +129,7 @@ +