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 @@
+