Retry API, standardize <script> list
This commit is contained in:
parent
8f49d201e6
commit
cf35b7056f
7 changed files with 143 additions and 70 deletions
|
@ -14,8 +14,6 @@
|
||||||
|
|
||||||
<html>
|
<html>
|
||||||
<head>
|
<head>
|
||||||
<script type="text/javascript" src="js/webcrypto.js"></script>
|
|
||||||
<script type="text/javascript" src="js/crypto.js"></script>
|
|
||||||
<script type="text/javascript" src="js-deps/nacl-common.js"></script>
|
<script type="text/javascript" src="js-deps/nacl-common.js"></script>
|
||||||
<script type="text/javascript" src="js-deps/jquery.js"></script>
|
<script type="text/javascript" src="js-deps/jquery.js"></script>
|
||||||
<script type="text/javascript" src="js-deps/core.js"></script>
|
<script type="text/javascript" src="js-deps/core.js"></script>
|
||||||
|
@ -33,9 +31,12 @@
|
||||||
<script type="text/javascript" src="js-deps/underscore.js"></script>
|
<script type="text/javascript" src="js-deps/underscore.js"></script>
|
||||||
<script type="text/javascript" src="js-deps/backbone.js"></script>
|
<script type="text/javascript" src="js-deps/backbone.js"></script>
|
||||||
<script type="text/javascript" src="js-deps/backbone.localStorage.js"></script>
|
<script type="text/javascript" src="js-deps/backbone.localStorage.js"></script>
|
||||||
|
|
||||||
|
<script type="text/javascript" src="js/helpers.js"></script>
|
||||||
|
<script type="text/javascript" src="js/webcrypto.js"></script>
|
||||||
|
<script type="text/javascript" src="js/crypto.js"></script>
|
||||||
<script type="text/javascript" src="js/models/messages.js"></script>
|
<script type="text/javascript" src="js/models/messages.js"></script>
|
||||||
<script type="text/javascript" src="js/models/threads.js"></script>
|
<script type="text/javascript" src="js/models/threads.js"></script>
|
||||||
<script type="text/javascript" src="js/helpers.js"></script>
|
|
||||||
<script type="text/javascript" src="js/api.js"></script>
|
<script type="text/javascript" src="js/api.js"></script>
|
||||||
<script type="text/javascript" src="js/chromium.js"></script>
|
<script type="text/javascript" src="js/chromium.js"></script>
|
||||||
<script type="text/javascript" src="js/background.js"></script>
|
<script type="text/javascript" src="js/background.js"></script>
|
||||||
|
|
|
@ -104,6 +104,8 @@ window.textsecure.api = function() {
|
||||||
textsecure.throwHumanError(code, "HTTPError", "The server rejected our query, please file a bug report.");
|
textsecure.throwHumanError(code, "HTTPError", "The server rejected our query, please file a bug report.");
|
||||||
}
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
|
if (jqXHR.responseJSON)
|
||||||
|
e.response = jqXHR.responseJSON;
|
||||||
reject(e);
|
reject(e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
41
js/crypto.js
41
js/crypto.js
|
@ -238,12 +238,6 @@ window.textsecure.crypto = function() {
|
||||||
throw new Error("Datastore inconsistency: device was stored without identity key");
|
throw new Error("Datastore inconsistency: device was stored without identity key");
|
||||||
}
|
}
|
||||||
|
|
||||||
// Used when device keys change - we assume key compromise so refuse all new messages
|
|
||||||
self.forceRemoveAllSessions = function(encodedNumber) {
|
|
||||||
textsecure.storage.removeEncrypted("session" + encodedNumber);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*****************************
|
/*****************************
|
||||||
*** Internal Crypto stuff ***
|
*** Internal Crypto stuff ***
|
||||||
*****************************/
|
*****************************/
|
||||||
|
@ -407,7 +401,26 @@ window.textsecure.crypto = function() {
|
||||||
session.indexInfo.closed = new Date().getTime();
|
session.indexInfo.closed = new Date().getTime();
|
||||||
}
|
}
|
||||||
|
|
||||||
var initSessionFromPreKeyWhisperMessage = function(encodedNumber, message) {
|
var initSessionFromPreKeyWhisperMessage;
|
||||||
|
var decryptWhisperMessage;
|
||||||
|
var handlePreKeyWhisperMessage = function(from, encodedMessage) {
|
||||||
|
var preKeyProto = textsecure.protos.decodePreKeyWhisperMessageProtobuf(encodedMessage);
|
||||||
|
return initSessionFromPreKeyWhisperMessage(from, preKeyProto).then(function(sessions) {
|
||||||
|
return decryptWhisperMessage(from, getString(preKeyProto.message), sessions[0], preKeyProto.registrationId).then(function(result) {
|
||||||
|
if (sessions[1] !== undefined)
|
||||||
|
crypto_storage.saveSession(from, sessions[1]);
|
||||||
|
return result;
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
var wipeIdentityAndTryMessageAgain = function(from, encodedMessage) {
|
||||||
|
//TODO: Wipe identity key!
|
||||||
|
return handlePreKeyWhisperMessage(from, encodedMessage);
|
||||||
|
}
|
||||||
|
textsecure.replay.registerReplayFunction(wipeIdentityAndTryMessageAgain, textsecure.replay.REPLAY_FUNCS.INIT_SESSION);
|
||||||
|
|
||||||
|
initSessionFromPreKeyWhisperMessage = function(encodedNumber, message) {
|
||||||
var preKeyPair = crypto_storage.getAndRemovePreKeyPair(message.preKeyId);
|
var preKeyPair = crypto_storage.getAndRemovePreKeyPair(message.preKeyId);
|
||||||
|
|
||||||
var session = crypto_storage.getSessionOrIdentityKeyByBaseKey(encodedNumber, toArrayBuffer(message.baseKey));
|
var session = crypto_storage.getSessionOrIdentityKeyByBaseKey(encodedNumber, toArrayBuffer(message.baseKey));
|
||||||
|
@ -428,8 +441,7 @@ window.textsecure.crypto = function() {
|
||||||
closeSession(open_session); // To be returned and saved later
|
closeSession(open_session); // To be returned and saved later
|
||||||
} else {
|
} else {
|
||||||
// ...otherwise create an error that the UI will pick up and ask the user if they want to re-negotiate
|
// ...otherwise create an error that the UI will pick up and ask the user if they want to re-negotiate
|
||||||
// TODO: Save the message for possible later renegotiation
|
throw textsecure.createTryAgainError("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())]);
|
||||||
textsecure.throwHumanError("Received message with unknown identity key", "WarnTryAgainError", "The identity of the sender has changed. This may be malicious, or the sender may have simply reinstalled TextSecure.");
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return initSession(false, preKeyPair, encodedNumber, toArrayBuffer(message.identityKey), toArrayBuffer(message.baseKey))
|
return initSession(false, preKeyPair, encodedNumber, toArrayBuffer(message.identityKey), toArrayBuffer(message.baseKey))
|
||||||
|
@ -525,7 +537,7 @@ window.textsecure.crypto = function() {
|
||||||
}
|
}
|
||||||
|
|
||||||
// returns decrypted protobuf
|
// returns decrypted protobuf
|
||||||
var decryptWhisperMessage = function(encodedNumber, messageBytes, session, registrationId) {
|
decryptWhisperMessage = function(encodedNumber, messageBytes, session, registrationId) {
|
||||||
if (messageBytes[0] != String.fromCharCode((2 << 4) | 2))
|
if (messageBytes[0] != String.fromCharCode((2 << 4) | 2))
|
||||||
throw new Error("Bad version number on WhisperMessage");
|
throw new Error("Bad version number on WhisperMessage");
|
||||||
|
|
||||||
|
@ -618,14 +630,7 @@ window.textsecure.crypto = function() {
|
||||||
if (proto.message.readUint8() != (2 << 4 | 2))
|
if (proto.message.readUint8() != (2 << 4 | 2))
|
||||||
throw new Error("Bad version byte");
|
throw new Error("Bad version byte");
|
||||||
var from = proto.source + "." + (proto.sourceDevice == null ? 0 : proto.sourceDevice);
|
var from = proto.source + "." + (proto.sourceDevice == null ? 0 : proto.sourceDevice);
|
||||||
var preKeyProto = textsecure.protos.decodePreKeyWhisperMessageProtobuf(getString(proto.message));
|
return handlePreKeyWhisperMessage(from, getString(proto.message));
|
||||||
return initSessionFromPreKeyWhisperMessage(from, preKeyProto).then(function(sessions) {
|
|
||||||
return decryptWhisperMessage(from, getString(preKeyProto.message), sessions[0], preKeyProto.registrationId).then(function(result) {
|
|
||||||
if (sessions[1] !== undefined)
|
|
||||||
crypto_storage.saveSession(proto.source, sessions[1]);
|
|
||||||
return result;
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -389,8 +389,8 @@ window.textsecure.storage = function() {
|
||||||
var devicesRemoved = 0;
|
var devicesRemoved = 0;
|
||||||
for (i in map.devices) {
|
for (i in map.devices) {
|
||||||
var keep = true;
|
var keep = true;
|
||||||
for (idToRemove in deviceIdsToRemove)
|
for (j in deviceIdsToRemove)
|
||||||
if (map.devices[i].encodedNumber == number + "." + idToRemove)
|
if (map.devices[i].encodedNumber == number + "." + deviceIdsToRemove[j])
|
||||||
keep = false;
|
keep = false;
|
||||||
|
|
||||||
if (keep)
|
if (keep)
|
||||||
|
@ -459,6 +459,41 @@ window.textsecure.nacl = function() {
|
||||||
//TODO: Some kind of textsecure.init(use_nacl)
|
//TODO: Some kind of textsecure.init(use_nacl)
|
||||||
window.textsecure.registerOnLoadFunction = window.textsecure.nacl.registerOnLoadFunction;
|
window.textsecure.registerOnLoadFunction = window.textsecure.nacl.registerOnLoadFunction;
|
||||||
|
|
||||||
|
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})
|
// message_callback({message: decryptedMessage, pushMessage: server-providedPushMessage})
|
||||||
window.textsecure.subscribeToPush = function() {
|
window.textsecure.subscribeToPush = function() {
|
||||||
var subscribeToPushMessageSemaphore = 0;
|
var subscribeToPushMessageSemaphore = 0;
|
||||||
|
@ -539,13 +574,13 @@ window.textsecure.sendMessage = function() {
|
||||||
var identityKey = getString(response[0].identityKey);
|
var identityKey = getString(response[0].identityKey);
|
||||||
for (i in response)
|
for (i in response)
|
||||||
if (getString(response[i].identityKey) != identityKey)
|
if (getString(response[i].identityKey) != identityKey)
|
||||||
throw new Error("Identity key changed");
|
throw new Error("Identity key not consistent");
|
||||||
|
|
||||||
for (i in response) {
|
for (i in response) {
|
||||||
var updateDevice = (updateDevices === undefined);
|
var updateDevice = (updateDevices === undefined);
|
||||||
if (!updateDevice)
|
if (!updateDevice)
|
||||||
for (deviceId in updateDevices)
|
for (j in updateDevices)
|
||||||
if (deviceId == response[i].deviceId)
|
if (updateDevices[j] == response[i].deviceId)
|
||||||
updateDevice = true;
|
updateDevice = true;
|
||||||
|
|
||||||
if (updateDevice)
|
if (updateDevice)
|
||||||
|
@ -602,6 +637,13 @@ window.textsecure.sendMessage = function() {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var tryMessageAgain = function(number, encodedMessage, callback) {
|
||||||
|
//TODO: Wipe identity key!
|
||||||
|
var message = textsecure.protos.decodePushMessageContentProtobuf(encodedMessage);
|
||||||
|
textsecure.sendMessage([number], message, callback);
|
||||||
|
}
|
||||||
|
textsecure.replay.registerReplayFunction(tryMessageAgain, textsecure.replay.SEND_MESSAGE);
|
||||||
|
|
||||||
return function(numbers, message, callback) {
|
return function(numbers, message, callback) {
|
||||||
var numbersCompleted = 0;
|
var numbersCompleted = 0;
|
||||||
var errors = [];
|
var errors = [];
|
||||||
|
@ -620,28 +662,39 @@ window.textsecure.sendMessage = function() {
|
||||||
numberCompleted();
|
numberCompleted();
|
||||||
}
|
}
|
||||||
|
|
||||||
var doSendMessage = function(number, devicesForNumber, message) {
|
var doSendMessage;
|
||||||
|
var reloadDevicesAndSend = function(number, recurse) {
|
||||||
|
return function() {
|
||||||
|
var devicesForNumber = textsecure.storage.devices.getDeviceObjectsForNumber(number);
|
||||||
|
if (devicesForNumber.length == 0)
|
||||||
|
registerError(number, "Go empty device list when loading device keys", null);
|
||||||
|
else
|
||||||
|
doSendMessage(number, devicesForNumber, recurse);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
doSendMessage = function(number, devicesForNumber, recurse) {
|
||||||
return sendMessageToDevices(number, devicesForNumber, message).then(function(result) {
|
return sendMessageToDevices(number, devicesForNumber, message).then(function(result) {
|
||||||
successfulNumbers[successfulNumbers.length] = number;
|
successfulNumbers[successfulNumbers.length] = number;
|
||||||
numberCompleted();
|
numberCompleted();
|
||||||
}).catch(function(error) {
|
}).catch(function(error) {
|
||||||
if (error instanceof Error && error.name == "HTTPError" && (error.message == 410 || error.message == 409)) {
|
if (error instanceof Error && error.name == "HTTPError" && (error.message == 410 || error.message == 409)) {
|
||||||
var resetDevices = ((error.message == 410) ? error.response.staleDevices : error.response.missingDevices);
|
if (!recurse)
|
||||||
getKeysForNumber(number, resetDevices).then(function() {
|
return registerError(number, "Hit retry limit attempting to reload device list", error);
|
||||||
|
|
||||||
if (error.message == 409)
|
if (error.message == 409)
|
||||||
resetDevices = resetDevices.concat(error.response.extraDevices);
|
textsecure.storage.devices.removeDeviceIdsForNumber(number, error.response.extraDevices);
|
||||||
|
|
||||||
textsecure.storage.devices.removeDeviceIdsForNumber(number, resetDevices);
|
var resetDevices = ((error.message == 410) ? error.response.staleDevices : error.response.missingDevices);
|
||||||
for (i in resetDevices)
|
getKeysForNumber(number, resetDevices)
|
||||||
textsecure.crypto.forceRemoveAllSessions(number + "." + resetDevices[i]);
|
.then(reloadDevicesAndSend(number, false))
|
||||||
|
.catch(function(error) {
|
||||||
//TODO: Try again
|
|
||||||
}).catch(function(error) {
|
|
||||||
if (error.message !== "Identity key changed")
|
if (error.message !== "Identity key changed")
|
||||||
registerError(number, "Failed to reload device keys", error);
|
registerError(number, "Failed to reload device keys", error);
|
||||||
else {
|
else {
|
||||||
// TODO: Identity key changed, check which devices it changed for and get upset
|
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.",
|
||||||
registerError(number, "Identity key changed!!!!", error);
|
textsecure.replay.SEND_MESSAGE, [number, getString(message.encode())]);
|
||||||
|
registerError(number, "Identity key changed", error);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
} else
|
} else
|
||||||
|
@ -654,17 +707,13 @@ window.textsecure.sendMessage = function() {
|
||||||
var devicesForNumber = textsecure.storage.devices.getDeviceObjectsForNumber(number);
|
var devicesForNumber = textsecure.storage.devices.getDeviceObjectsForNumber(number);
|
||||||
|
|
||||||
if (devicesForNumber.length == 0) {
|
if (devicesForNumber.length == 0) {
|
||||||
getKeysForNumber(number).then(function() {
|
getKeysForNumber(number)
|
||||||
devicesForNumber = textsecure.storage.devices.getDeviceObjectsForNumber(number);
|
.then(reloadDevicesAndSend(number, true))
|
||||||
if (devicesForNumber.length == 0)
|
.catch(function(error) {
|
||||||
registerError(number, "Failed to retreive new device keys for number " + number, null);
|
|
||||||
else
|
|
||||||
doSendMessage(number, devicesForNumber, message);
|
|
||||||
}).catch(function(error) {
|
|
||||||
registerError(number, "Failed to retreive new device keys for number " + number, error);
|
registerError(number, "Failed to retreive new device keys for number " + number, error);
|
||||||
});
|
});
|
||||||
} else
|
} else
|
||||||
doSendMessage(number, devicesForNumber, message);
|
doSendMessage(number, devicesForNumber, true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}();
|
}();
|
||||||
|
|
12
options.html
12
options.html
|
@ -38,7 +38,6 @@
|
||||||
<div id="setup-complete" style="display: none;">
|
<div id="setup-complete" style="display: none;">
|
||||||
<h2>You are now registered on TextSecure with number <span id="complete-number"></span></h2>
|
<h2>You are now registered on TextSecure with number <span id="complete-number"></span></h2>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<script type="text/javascript" src="js-deps/nacl-common.js"></script>
|
<script type="text/javascript" src="js-deps/nacl-common.js"></script>
|
||||||
<script type="text/javascript" src="js-deps/jquery.js"></script>
|
<script type="text/javascript" src="js-deps/jquery.js"></script>
|
||||||
<script type="text/javascript" src="js-deps/core.js"></script>
|
<script type="text/javascript" src="js-deps/core.js"></script>
|
||||||
|
@ -53,9 +52,16 @@
|
||||||
<script type="text/javascript" src="js-deps/Long.min.js"></script>
|
<script type="text/javascript" src="js-deps/Long.min.js"></script>
|
||||||
<script type="text/javascript" src="js-deps/ByteBuffer.min.js"></script>
|
<script type="text/javascript" src="js-deps/ByteBuffer.min.js"></script>
|
||||||
<script type="text/javascript" src="js-deps/ProtoBuf.min.js"></script>
|
<script type="text/javascript" src="js-deps/ProtoBuf.min.js"></script>
|
||||||
<script type="text/javascript" src="js/crypto.js"></script>
|
<script type="text/javascript" src="js-deps/underscore.js"></script>
|
||||||
<script type="text/javascript" src="js/api.js"></script>
|
<script type="text/javascript" src="js-deps/backbone.js"></script>
|
||||||
|
<script type="text/javascript" src="js-deps/backbone.localStorage.js"></script>
|
||||||
|
|
||||||
<script type="text/javascript" src="js/helpers.js"></script>
|
<script type="text/javascript" src="js/helpers.js"></script>
|
||||||
|
<script type="text/javascript" src="js/webcrypto.js"></script>
|
||||||
|
<script type="text/javascript" src="js/crypto.js"></script>
|
||||||
|
<script type="text/javascript" src="js/models/messages.js"></script>
|
||||||
|
<script type="text/javascript" src="js/models/threads.js"></script>
|
||||||
|
<script type="text/javascript" src="js/api.js"></script>
|
||||||
<script type="text/javascript" src="js/chromium.js"></script>
|
<script type="text/javascript" src="js/chromium.js"></script>
|
||||||
<script type="text/javascript" src="js/options.js"></script>
|
<script type="text/javascript" src="js/options.js"></script>
|
||||||
</body>
|
</body>
|
||||||
|
|
25
popup.html
25
popup.html
|
@ -44,19 +44,8 @@
|
||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<script type="text/javascript" src="js/webcrypto.js"></script>
|
|
||||||
<script type="text/javascript" src="js/crypto.js"></script>
|
|
||||||
<script type="text/javascript" src="js-deps/nacl-common.js"></script>
|
<script type="text/javascript" src="js-deps/nacl-common.js"></script>
|
||||||
<script type="text/javascript" src="js-deps/jquery.js"></script>
|
<script type="text/javascript" src="js-deps/jquery.js"></script>
|
||||||
<script type="text/javascript" src="js-deps/underscore.js"></script>
|
|
||||||
<script type="text/javascript" src="js-deps/backbone.js"></script>
|
|
||||||
<script type="text/javascript" src="js-deps/backbone.localStorage.js"></script>
|
|
||||||
<script type="text/javascript" src="js/models/messages.js"></script>
|
|
||||||
<script type="text/javascript" src="js/models/threads.js"></script>
|
|
||||||
<script type="text/javascript" src="js/views/notifications.js"></script>
|
|
||||||
<script type="text/javascript" src="js/views/message.js"></script>
|
|
||||||
<script type="text/javascript" src="js/views/conversation.js"></script>
|
|
||||||
<script type="text/javascript" src="js/views/messages.js"></script>
|
|
||||||
<script type="text/javascript" src="js-deps/core.js"></script>
|
<script type="text/javascript" src="js-deps/core.js"></script>
|
||||||
<script type="text/javascript" src="js-deps/enc-base64.js"></script>
|
<script type="text/javascript" src="js-deps/enc-base64.js"></script>
|
||||||
<script type="text/javascript" src="js-deps/cipher-core.js"></script>
|
<script type="text/javascript" src="js-deps/cipher-core.js"></script>
|
||||||
|
@ -69,8 +58,22 @@
|
||||||
<script type="text/javascript" src="js-deps/Long.min.js"></script>
|
<script type="text/javascript" src="js-deps/Long.min.js"></script>
|
||||||
<script type="text/javascript" src="js-deps/ByteBuffer.min.js"></script>
|
<script type="text/javascript" src="js-deps/ByteBuffer.min.js"></script>
|
||||||
<script type="text/javascript" src="js-deps/ProtoBuf.min.js"></script>
|
<script type="text/javascript" src="js-deps/ProtoBuf.min.js"></script>
|
||||||
|
<script type="text/javascript" src="js-deps/underscore.js"></script>
|
||||||
|
<script type="text/javascript" src="js-deps/backbone.js"></script>
|
||||||
|
<script type="text/javascript" src="js-deps/backbone.localStorage.js"></script>
|
||||||
|
|
||||||
<script type="text/javascript" src="js/helpers.js"></script>
|
<script type="text/javascript" src="js/helpers.js"></script>
|
||||||
|
<script type="text/javascript" src="js/webcrypto.js"></script>
|
||||||
|
<script type="text/javascript" src="js/crypto.js"></script>
|
||||||
|
<script type="text/javascript" src="js/models/messages.js"></script>
|
||||||
|
<script type="text/javascript" src="js/models/threads.js"></script>
|
||||||
<script type="text/javascript" src="js/api.js"></script>
|
<script type="text/javascript" src="js/api.js"></script>
|
||||||
|
<script type="text/javascript" src="js/chromium.js"></script>
|
||||||
|
|
||||||
|
<script type="text/javascript" src="js/views/notifications.js"></script>
|
||||||
|
<script type="text/javascript" src="js/views/message.js"></script>
|
||||||
|
<script type="text/javascript" src="js/views/conversation.js"></script>
|
||||||
|
<script type="text/javascript" src="js/views/messages.js"></script>
|
||||||
<script type="text/javascript" src="js/popup.js"></script>
|
<script type="text/javascript" src="js/popup.js"></script>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|
11
test.html
11
test.html
|
@ -29,20 +29,27 @@
|
||||||
<script type="text/javascript" src="js-deps/core.js"></script>
|
<script type="text/javascript" src="js-deps/core.js"></script>
|
||||||
<script type="text/javascript" src="js-deps/enc-base64.js"></script>
|
<script type="text/javascript" src="js-deps/enc-base64.js"></script>
|
||||||
<script type="text/javascript" src="js-deps/cipher-core.js"></script>
|
<script type="text/javascript" src="js-deps/cipher-core.js"></script>
|
||||||
<script type="text/javascript" src="js-deps/lib-typedarrays.js"></script>
|
|
||||||
<script type="text/javascript" src="js-deps/aes.js"></script>
|
<script type="text/javascript" src="js-deps/aes.js"></script>
|
||||||
<script type="text/javascript" src="js-deps/mode-ctr-min.js"></script>
|
<script type="text/javascript" src="js-deps/mode-ctr-min.js"></script>
|
||||||
<script type="text/javascript" src="js-deps/pad-nopadding.js"></script>
|
<script type="text/javascript" src="js-deps/pad-nopadding.js"></script>
|
||||||
<script type="text/javascript" src="js-deps/hmac-sha256.js"></script>
|
<script type="text/javascript" src="js-deps/hmac-sha256.js"></script>
|
||||||
<script type="text/javascript" src="js-deps/curve255.js"></script>
|
<script type="text/javascript" src="js-deps/curve255.js"></script>
|
||||||
|
<script type="text/javascript" src="js-deps/lib-typedarrays.js"></script>
|
||||||
<script type="text/javascript" src="js-deps/Long.min.js"></script>
|
<script type="text/javascript" src="js-deps/Long.min.js"></script>
|
||||||
<script type="text/javascript" src="js-deps/ByteBuffer.min.js"></script>
|
<script type="text/javascript" src="js-deps/ByteBuffer.min.js"></script>
|
||||||
<script type="text/javascript" src="js-deps/ProtoBuf.min.js"></script>
|
<script type="text/javascript" src="js-deps/ProtoBuf.min.js"></script>
|
||||||
|
<script type="text/javascript" src="js-deps/underscore.js"></script>
|
||||||
|
<script type="text/javascript" src="js-deps/backbone.js"></script>
|
||||||
|
<script type="text/javascript" src="js-deps/backbone.localStorage.js"></script>
|
||||||
|
|
||||||
|
<script type="text/javascript" src="js/helpers.js"></script>
|
||||||
<script type="text/javascript" src="js/webcrypto.js"></script>
|
<script type="text/javascript" src="js/webcrypto.js"></script>
|
||||||
<script type="text/javascript" src="js/crypto.js"></script>
|
<script type="text/javascript" src="js/crypto.js"></script>
|
||||||
<script type="text/javascript" src="js/helpers.js"></script>
|
<script type="text/javascript" src="js/models/messages.js"></script>
|
||||||
|
<script type="text/javascript" src="js/models/threads.js"></script>
|
||||||
<script type="text/javascript" src="js/api.js"></script>
|
<script type="text/javascript" src="js/api.js"></script>
|
||||||
|
<script type="text/javascript" src="js/chromium.js"></script>
|
||||||
|
|
||||||
<script type="text/javascript" src="js/fake_api.js"></script>
|
<script type="text/javascript" src="js/fake_api.js"></script>
|
||||||
<script type="text/javascript" src="js/test.js"></script>
|
<script type="text/javascript" src="js/test.js"></script>
|
||||||
</body>
|
</body>
|
||||||
|
|
Loading…
Reference in a new issue