backgroundTasks method
Future<void>
backgroundTasks(
)
Implementation
Future<void> backgroundTasks() async {
final database = client.database;
final userID = client.userID;
if (_isUploadingKeys || database == null || userID == null) {
return;
}
_isUploadingKeys = true;
try {
if (!_haveKeysToUpload || !(await isCached())) {
return; // we can't backup anyways
}
final dbSessions = await database.getInboundGroupSessionsToUpload();
if (dbSessions.isEmpty) {
_haveKeysToUpload = false;
return; // nothing to do
}
final privateKey =
base64decodeUnpadded((await encryption.ssss.getCached(megolmKey))!);
// decryption is needed to calculate the public key and thus see if the claimed information is in fact valid
final decryption = olm.PkDecryption();
final info = await getRoomKeysBackupInfo(false);
String backupPubKey;
try {
backupPubKey = decryption.init_with_private_key(privateKey);
if (info.algorithm !=
BackupAlgorithm.mMegolmBackupV1Curve25519AesSha2 ||
info.authData['public_key'] != backupPubKey) {
return;
}
final args = GenerateUploadKeysArgs(
pubkey: backupPubKey,
dbSessions: <DbInboundGroupSessionBundle>[],
userId: userID,
);
// we need to calculate verified beforehand, as else we pass a closure to an isolate
// with 500 keys they do, however, noticably block the UI, which is why we give brief async suspentions in here
// so that the event loop can progress
var i = 0;
for (final dbSession in dbSessions) {
final device =
client.getUserDeviceKeysByCurve25519Key(dbSession.senderKey);
args.dbSessions.add(DbInboundGroupSessionBundle(
dbSession: dbSession,
verified: device?.verified ?? false,
));
i++;
if (i > 10) {
await Future.delayed(Duration(milliseconds: 1));
i = 0;
}
}
final roomKeys =
await client.nativeImplementations.generateUploadKeys(args);
Logs().i('[Key Manager] Uploading ${dbSessions.length} room keys...');
// upload the payload...
await client.putRoomKeys(info.version, roomKeys);
// and now finally mark all the keys as uploaded
// no need to optimze this, as we only run it so seldomly and almost never with many keys at once
for (final dbSession in dbSessions) {
await database.markInboundGroupSessionAsUploaded(
dbSession.roomId, dbSession.sessionId);
}
} finally {
decryption.free();
}
} catch (e, s) {
Logs().e('[Key Manager] Error uploading room keys', e, s);
} finally {
_isUploadingKeys = false;
}
}