Don't save device objects to disk
Generate them from session and identity data. Save/delete pending prekey data in an in-memory store and attach it to outgoing device objects.
This commit is contained in:
parent
f18795a253
commit
43d6efcd9e
3 changed files with 85 additions and 213 deletions
|
@ -198,19 +198,7 @@
|
||||||
contact.fetch().always(function() {
|
contact.fetch().always(function() {
|
||||||
var sessions = contact.get('sessions') || {};
|
var sessions = contact.get('sessions') || {};
|
||||||
sessions[deviceId] = record;
|
sessions[deviceId] = record;
|
||||||
contact.save({sessions: sessions}).always(function() {
|
contact.save({sessions: sessions}).always(resolve);
|
||||||
resolve(textsecure.storage.devices.getDeviceObject(encodedNumber).then(function(device) {
|
|
||||||
if (device === undefined) {
|
|
||||||
return textsecure.storage.axolotl.getIdentityKey(number).then(function(identityKey) {
|
|
||||||
device = { encodedNumber: encodedNumber,
|
|
||||||
//TODO: Remove this duplication
|
|
||||||
identityKey: identityKey
|
|
||||||
};
|
|
||||||
return textsecure.storage.devices.saveDeviceObject(device);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}));
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
|
@ -38094,122 +38094,64 @@ axolotlInternal.RecipientRecord = function() {
|
||||||
window.textsecure = window.textsecure || {};
|
window.textsecure = window.textsecure || {};
|
||||||
window.textsecure.storage = window.textsecure.storage || {};
|
window.textsecure.storage = window.textsecure.storage || {};
|
||||||
|
|
||||||
window.textsecure.storage.devices = {
|
var tempKeys = {};
|
||||||
saveDeviceObject: function(deviceObject) {
|
|
||||||
return internalSaveDeviceObject(deviceObject, false);
|
|
||||||
},
|
|
||||||
|
|
||||||
|
window.textsecure.storage.devices = {
|
||||||
saveKeysToDeviceObject: function(deviceObject) {
|
saveKeysToDeviceObject: function(deviceObject) {
|
||||||
return internalSaveDeviceObject(deviceObject, true);
|
var number = textsecure.utils.unencodeNumber(deviceObject.encodedNumber)[0];
|
||||||
|
return textsecure.storage.axolotl.putIdentityKey(number, deviceObject.identityKey).then(function() {
|
||||||
|
tempKeys[deviceObject.encodedNumber] = {
|
||||||
|
preKey: deviceObject.preKey,
|
||||||
|
preKeyId: deviceObject.preKeyId,
|
||||||
|
signedKey: deviceObject.signedKey,
|
||||||
|
signedKeyId: deviceObject.signedKeyId,
|
||||||
|
signedKeySignature: deviceObject.signedKeySignature,
|
||||||
|
registrationId: deviceObject.registrationId
|
||||||
|
};
|
||||||
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
removeTempKeysFromDevice: function(encodedNumber) {
|
removeTempKeysFromDevice: function(encodedNumber) {
|
||||||
return textsecure.storage.devices.getDeviceObject(encodedNumber).then(function(deviceObject) {
|
delete tempKeys[encodedNumber];
|
||||||
try {
|
return Promise.resolve();
|
||||||
delete deviceObject['signedKey'];
|
|
||||||
delete deviceObject['signedKeyId'];
|
|
||||||
delete deviceObject['signedKeySignature'];
|
|
||||||
delete deviceObject['preKey'];
|
|
||||||
delete deviceObject['preKeyId'];
|
|
||||||
delete deviceObject['registrationId'];
|
|
||||||
} catch(_) {}
|
|
||||||
return internalSaveDeviceObject(deviceObject, false);
|
|
||||||
});
|
|
||||||
},
|
},
|
||||||
|
|
||||||
getDeviceObjectsForNumber: function(number) {
|
getDeviceObjectsForNumber: function(number) {
|
||||||
return textsecure.storage.axolotl.getIdentityKey(number).then(function(identityKey) {
|
return textsecure.storage.axolotl.getIdentityKey(number).then(function(identityKey) {
|
||||||
var map = textsecure.storage.get("devices" + number);
|
if (identityKey === undefined) {
|
||||||
if (map === undefined)
|
|
||||||
return [];
|
return [];
|
||||||
return map.devices.map(function(device) {
|
}
|
||||||
device.identityKey = identityKey;
|
return textsecure.storage.axolotl.getDeviceIds(number).then(function(deviceIds) {
|
||||||
return device;
|
// Add pending devices from tempKeys
|
||||||
|
for (var encodedNumber in tempKeys) {
|
||||||
|
var deviceNumber = textsecure.utils.unencodeNumber(encodedNumber)[0];
|
||||||
|
var deviceId = textsecure.utils.unencodeNumber(encodedNumber)[1];
|
||||||
|
if (deviceNumber === number && deviceIds.indexOf(deviceId) < 0) {
|
||||||
|
deviceIds.push(deviceId);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return deviceIds.map(function(deviceId) {
|
||||||
|
var encodedNumber = number + '.' + deviceId;
|
||||||
|
var deviceObject = tempKeys[encodedNumber] || {};
|
||||||
|
deviceObject.encodedNumber = encodedNumber;
|
||||||
|
deviceObject.identityKey = identityKey;
|
||||||
|
return deviceObject;
|
||||||
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
getDeviceObject: function(encodedNumber) {
|
|
||||||
var number = textsecure.utils.unencodeNumber(encodedNumber)[0];
|
|
||||||
return textsecure.storage.devices.getDeviceObjectsForNumber(number).then(function(devices) {
|
|
||||||
for (var i in devices)
|
|
||||||
if (devices[i].encodedNumber == encodedNumber)
|
|
||||||
return devices[i];
|
|
||||||
|
|
||||||
return undefined;
|
|
||||||
});
|
|
||||||
},
|
|
||||||
|
|
||||||
removeDeviceIdsForNumber: function(number, deviceIdsToRemove) {
|
removeDeviceIdsForNumber: function(number, deviceIdsToRemove) {
|
||||||
return Promise.resolve((function() {
|
var promise = Promise.resolve();
|
||||||
var map = textsecure.storage.get("devices" + number);
|
for (var j in deviceIdsToRemove) {
|
||||||
if (map === undefined)
|
promise = promise.then(function() {
|
||||||
throw new Error("Tried to remove device for unknown number");
|
var encodedNumber = number + "." + deviceIdsToRemove[j];
|
||||||
|
delete tempKeys[encodedNumber];
|
||||||
var newDevices = [];
|
return textsecure.storage.axolotl.removeSession(encodedNumber);
|
||||||
var devicesRemoved = 0;
|
});
|
||||||
for (var i in map.devices) {
|
|
||||||
var keep = true;
|
|
||||||
for (var j in deviceIdsToRemove)
|
|
||||||
if (map.devices[i].encodedNumber == number + "." + deviceIdsToRemove[j])
|
|
||||||
keep = false;
|
|
||||||
|
|
||||||
if (keep)
|
|
||||||
newDevices.push(map.devices[i]);
|
|
||||||
else
|
|
||||||
devicesRemoved++;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (devicesRemoved != deviceIdsToRemove.length)
|
|
||||||
throw new Error("Tried to remove unknown device");
|
|
||||||
|
|
||||||
if (newDevices.length === 0)
|
|
||||||
textsecure.storage.remove("devices" + number);
|
|
||||||
else {
|
|
||||||
map.devices = newDevices;
|
|
||||||
textsecure.storage.put("devices" + number, map);
|
|
||||||
}
|
|
||||||
})());
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
var internalSaveDeviceObject = function(deviceObject, onlyKeys) {
|
|
||||||
if (deviceObject.encodedNumber === undefined)
|
|
||||||
throw new Error("Tried to store invalid deviceObject");
|
|
||||||
|
|
||||||
var number = textsecure.utils.unencodeNumber(deviceObject.encodedNumber)[0];
|
|
||||||
var map = textsecure.storage.get("devices" + number);
|
|
||||||
|
|
||||||
return textsecure.storage.axolotl.getIdentityKey(number).then(function(identityKey) {
|
|
||||||
if (identityKey !== undefined && deviceObject.identityKey !== undefined && getString(identityKey) != getString(deviceObject.identityKey))
|
|
||||||
throw new Error("Identity key changed");
|
|
||||||
|
|
||||||
if (map === undefined)
|
|
||||||
map = { devices: [deviceObject] };
|
|
||||||
else {
|
|
||||||
var updated = false;
|
|
||||||
for (var i in map.devices) {
|
|
||||||
if (map.devices[i].encodedNumber == deviceObject.encodedNumber) {
|
|
||||||
if (!onlyKeys)
|
|
||||||
map.devices[i] = deviceObject;
|
|
||||||
else {
|
|
||||||
map.devices[i].preKey = deviceObject.preKey;
|
|
||||||
map.devices[i].preKeyId = deviceObject.preKeyId;
|
|
||||||
map.devices[i].signedKey = deviceObject.signedKey;
|
|
||||||
map.devices[i].signedKeyId = deviceObject.signedKeyId;
|
|
||||||
map.devices[i].signedKeySignature = deviceObject.signedKeySignature;
|
|
||||||
map.devices[i].registrationId = deviceObject.registrationId;
|
|
||||||
}
|
|
||||||
updated = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!updated)
|
|
||||||
map.devices.push(deviceObject);
|
|
||||||
}
|
}
|
||||||
|
return promise;
|
||||||
textsecure.storage.put("devices" + number, map);
|
}
|
||||||
});
|
|
||||||
};
|
};
|
||||||
})();
|
})();
|
||||||
|
|
||||||
|
|
|
@ -23,121 +23,63 @@
|
||||||
window.textsecure = window.textsecure || {};
|
window.textsecure = window.textsecure || {};
|
||||||
window.textsecure.storage = window.textsecure.storage || {};
|
window.textsecure.storage = window.textsecure.storage || {};
|
||||||
|
|
||||||
window.textsecure.storage.devices = {
|
var tempKeys = {};
|
||||||
saveDeviceObject: function(deviceObject) {
|
|
||||||
return internalSaveDeviceObject(deviceObject, false);
|
|
||||||
},
|
|
||||||
|
|
||||||
|
window.textsecure.storage.devices = {
|
||||||
saveKeysToDeviceObject: function(deviceObject) {
|
saveKeysToDeviceObject: function(deviceObject) {
|
||||||
return internalSaveDeviceObject(deviceObject, true);
|
var number = textsecure.utils.unencodeNumber(deviceObject.encodedNumber)[0];
|
||||||
|
return textsecure.storage.axolotl.putIdentityKey(number, deviceObject.identityKey).then(function() {
|
||||||
|
tempKeys[deviceObject.encodedNumber] = {
|
||||||
|
preKey: deviceObject.preKey,
|
||||||
|
preKeyId: deviceObject.preKeyId,
|
||||||
|
signedKey: deviceObject.signedKey,
|
||||||
|
signedKeyId: deviceObject.signedKeyId,
|
||||||
|
signedKeySignature: deviceObject.signedKeySignature,
|
||||||
|
registrationId: deviceObject.registrationId
|
||||||
|
};
|
||||||
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
removeTempKeysFromDevice: function(encodedNumber) {
|
removeTempKeysFromDevice: function(encodedNumber) {
|
||||||
return textsecure.storage.devices.getDeviceObject(encodedNumber).then(function(deviceObject) {
|
delete tempKeys[encodedNumber];
|
||||||
try {
|
return Promise.resolve();
|
||||||
delete deviceObject['signedKey'];
|
|
||||||
delete deviceObject['signedKeyId'];
|
|
||||||
delete deviceObject['signedKeySignature'];
|
|
||||||
delete deviceObject['preKey'];
|
|
||||||
delete deviceObject['preKeyId'];
|
|
||||||
delete deviceObject['registrationId'];
|
|
||||||
} catch(_) {}
|
|
||||||
return internalSaveDeviceObject(deviceObject, false);
|
|
||||||
});
|
|
||||||
},
|
},
|
||||||
|
|
||||||
getDeviceObjectsForNumber: function(number) {
|
getDeviceObjectsForNumber: function(number) {
|
||||||
return textsecure.storage.axolotl.getIdentityKey(number).then(function(identityKey) {
|
return textsecure.storage.axolotl.getIdentityKey(number).then(function(identityKey) {
|
||||||
var map = textsecure.storage.get("devices" + number);
|
if (identityKey === undefined) {
|
||||||
if (map === undefined)
|
|
||||||
return [];
|
return [];
|
||||||
return map.devices.map(function(device) {
|
}
|
||||||
device.identityKey = identityKey;
|
return textsecure.storage.axolotl.getDeviceIds(number).then(function(deviceIds) {
|
||||||
return device;
|
// Add pending devices from tempKeys
|
||||||
|
for (var encodedNumber in tempKeys) {
|
||||||
|
var deviceNumber = textsecure.utils.unencodeNumber(encodedNumber)[0];
|
||||||
|
var deviceId = textsecure.utils.unencodeNumber(encodedNumber)[1];
|
||||||
|
if (deviceNumber === number && deviceIds.indexOf(deviceId) < 0) {
|
||||||
|
deviceIds.push(deviceId);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return deviceIds.map(function(deviceId) {
|
||||||
|
var encodedNumber = number + '.' + deviceId;
|
||||||
|
var deviceObject = tempKeys[encodedNumber] || {};
|
||||||
|
deviceObject.encodedNumber = encodedNumber;
|
||||||
|
deviceObject.identityKey = identityKey;
|
||||||
|
return deviceObject;
|
||||||
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
getDeviceObject: function(encodedNumber) {
|
|
||||||
var number = textsecure.utils.unencodeNumber(encodedNumber)[0];
|
|
||||||
return textsecure.storage.devices.getDeviceObjectsForNumber(number).then(function(devices) {
|
|
||||||
for (var i in devices)
|
|
||||||
if (devices[i].encodedNumber == encodedNumber)
|
|
||||||
return devices[i];
|
|
||||||
|
|
||||||
return undefined;
|
|
||||||
});
|
|
||||||
},
|
|
||||||
|
|
||||||
removeDeviceIdsForNumber: function(number, deviceIdsToRemove) {
|
removeDeviceIdsForNumber: function(number, deviceIdsToRemove) {
|
||||||
return Promise.resolve((function() {
|
var promise = Promise.resolve();
|
||||||
var map = textsecure.storage.get("devices" + number);
|
for (var j in deviceIdsToRemove) {
|
||||||
if (map === undefined)
|
promise = promise.then(function() {
|
||||||
throw new Error("Tried to remove device for unknown number");
|
var encodedNumber = number + "." + deviceIdsToRemove[j];
|
||||||
|
delete tempKeys[encodedNumber];
|
||||||
var newDevices = [];
|
return textsecure.storage.axolotl.removeSession(encodedNumber);
|
||||||
var devicesRemoved = 0;
|
});
|
||||||
for (var i in map.devices) {
|
}
|
||||||
var keep = true;
|
return promise;
|
||||||
for (var j in deviceIdsToRemove)
|
|
||||||
if (map.devices[i].encodedNumber == number + "." + deviceIdsToRemove[j])
|
|
||||||
keep = false;
|
|
||||||
|
|
||||||
if (keep)
|
|
||||||
newDevices.push(map.devices[i]);
|
|
||||||
else
|
|
||||||
devicesRemoved++;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (devicesRemoved != deviceIdsToRemove.length)
|
|
||||||
throw new Error("Tried to remove unknown device");
|
|
||||||
|
|
||||||
if (newDevices.length === 0)
|
|
||||||
textsecure.storage.remove("devices" + number);
|
|
||||||
else {
|
|
||||||
map.devices = newDevices;
|
|
||||||
textsecure.storage.put("devices" + number, map);
|
|
||||||
}
|
|
||||||
})());
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
var internalSaveDeviceObject = function(deviceObject, onlyKeys) {
|
|
||||||
if (deviceObject.encodedNumber === undefined)
|
|
||||||
throw new Error("Tried to store invalid deviceObject");
|
|
||||||
|
|
||||||
var number = textsecure.utils.unencodeNumber(deviceObject.encodedNumber)[0];
|
|
||||||
var map = textsecure.storage.get("devices" + number);
|
|
||||||
|
|
||||||
return textsecure.storage.axolotl.getIdentityKey(number).then(function(identityKey) {
|
|
||||||
if (identityKey !== undefined && deviceObject.identityKey !== undefined && getString(identityKey) != getString(deviceObject.identityKey))
|
|
||||||
throw new Error("Identity key changed");
|
|
||||||
|
|
||||||
if (map === undefined)
|
|
||||||
map = { devices: [deviceObject] };
|
|
||||||
else {
|
|
||||||
var updated = false;
|
|
||||||
for (var i in map.devices) {
|
|
||||||
if (map.devices[i].encodedNumber == deviceObject.encodedNumber) {
|
|
||||||
if (!onlyKeys)
|
|
||||||
map.devices[i] = deviceObject;
|
|
||||||
else {
|
|
||||||
map.devices[i].preKey = deviceObject.preKey;
|
|
||||||
map.devices[i].preKeyId = deviceObject.preKeyId;
|
|
||||||
map.devices[i].signedKey = deviceObject.signedKey;
|
|
||||||
map.devices[i].signedKeyId = deviceObject.signedKeyId;
|
|
||||||
map.devices[i].signedKeySignature = deviceObject.signedKeySignature;
|
|
||||||
map.devices[i].registrationId = deviceObject.registrationId;
|
|
||||||
}
|
|
||||||
updated = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!updated)
|
|
||||||
map.devices.push(deviceObject);
|
|
||||||
}
|
|
||||||
|
|
||||||
textsecure.storage.put("devices" + number, map);
|
|
||||||
});
|
|
||||||
};
|
|
||||||
})();
|
})();
|
||||||
|
|
Loading…
Add table
Reference in a new issue