aboutsummaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
Diffstat (limited to 'lib')
-rw-r--r--lib/accountregistry.h25
-rw-r--r--lib/avatar.cpp8
-rw-r--r--lib/connection.cpp78
-rw-r--r--lib/connection.h5
-rw-r--r--lib/room.cpp4
5 files changed, 55 insertions, 65 deletions
diff --git a/lib/accountregistry.h b/lib/accountregistry.h
index 38cfe6c6..9560688e 100644
--- a/lib/accountregistry.h
+++ b/lib/accountregistry.h
@@ -31,8 +31,9 @@ class QUOTIENT_API AccountRegistry : public QAbstractListModel,
/// Can be used to inform the user or to show a login screen if size() == 0 and no accounts are loaded
Q_PROPERTY(QStringList accountsLoading READ accountsLoading NOTIFY accountsLoadingChanged)
public:
- using const_iterator = QVector::const_iterator;
- using const_reference = QVector::const_reference;
+ using vector_t = QVector<Connection*>;
+ using const_iterator = vector_t::const_iterator;
+ using const_reference = vector_t::const_reference;
enum EventRoles {
AccountRole = Qt::UserRole + 1,
@@ -42,24 +43,24 @@ public:
[[deprecated("Use Accounts variable instead")]] //
static AccountRegistry& instance();
- // Expose most of QVector's const-API but only provide add() and drop()
+ // Expose most of vector_t's const-API but only provide add() and drop()
// for changing it. In theory other changing operations could be supported
// too; but then boilerplate begin/end*() calls has to be tucked into each
// and this class gives no guarantees on the order of entries, so why care.
- const QVector<Connection*>& accounts() const { return *this; }
+ const vector_t& accounts() const { return *this; }
void add(Connection* a);
void drop(Connection* a);
- const_iterator begin() const { return QVector::begin(); }
- const_iterator end() const { return QVector::end(); }
- const_reference front() const { return QVector::front(); }
- const_reference back() const { return QVector::back(); }
+ const_iterator begin() const { return vector_t::begin(); }
+ const_iterator end() const { return vector_t::end(); }
+ const_reference front() const { return vector_t::front(); }
+ const_reference back() const { return vector_t::back(); }
bool isLoggedIn(const QString& userId) const;
Connection* get(const QString& userId);
- using QVector::isEmpty, QVector::empty;
- using QVector::size, QVector::count, QVector::capacity;
- using QVector::cbegin, QVector::cend, QVector::contains;
+ using vector_t::isEmpty, vector_t::empty;
+ using vector_t::size, vector_t::count, vector_t::capacity;
+ using vector_t::cbegin, vector_t::cend, vector_t::contains;
// QAbstractItemModel interface implementation
@@ -88,4 +89,4 @@ private:
inline QUOTIENT_API AccountRegistry Accounts {};
inline AccountRegistry& AccountRegistry::instance() { return Accounts; }
-}
+} // namespace Quotient
diff --git a/lib/avatar.cpp b/lib/avatar.cpp
index 9304a3de..13de99bf 100644
--- a/lib/avatar.cpp
+++ b/lib/avatar.cpp
@@ -39,7 +39,7 @@ public:
// The below are related to image caching, hence mutable
mutable QImage _originalImage;
- mutable std::vector<QPair<QSize, QImage>> _scaledImages;
+ mutable std::vector<std::pair<QSize, QImage>> _scaledImages;
mutable QSize _requestedSize;
mutable enum { Unknown, Cache, Network, Banned } _imageSource = Unknown;
mutable QPointer<MediaThumbnailJob> _thumbnailRequest = nullptr;
@@ -124,9 +124,9 @@ QImage Avatar::Private::get(Connection* connection, QSize size,
});
}
- for (const auto& p : _scaledImages)
- if (p.first == size)
- return p.second;
+ for (const auto& [scaledSize, scaledImage] : _scaledImages)
+ if (scaledSize == size)
+ return scaledImage;
auto result = _originalImage.isNull()
? QImage()
: _originalImage.scaled(size, Qt::KeepAspectRatio,
diff --git a/lib/connection.cpp b/lib/connection.cpp
index 101bef89..c390cc05 100644
--- a/lib/connection.cpp
+++ b/lib/connection.cpp
@@ -92,7 +92,7 @@ public:
// state is Invited. The spec mandates to keep Invited room state
// separately; specifically, we should keep objects for Invite and
// Leave state of the same room if the two happen to co-exist.
- QHash<QPair<QString, bool>, Room*> roomMap;
+ QHash<std::pair<QString, bool>, Room*> roomMap;
/// Mapping from serverparts to alias/room id mappings,
/// as of the last sync
QHash<QString, QString> roomAliasMap;
@@ -381,10 +381,9 @@ public:
const QString& device) const;
QString edKeyForUserDevice(const QString& userId,
const QString& device) const;
- std::unique_ptr<EncryptedEvent> makeEventForSessionKey(
- const QString& roomId, const QString& targetUserId,
- const QString& targetDeviceId, const QByteArray& sessionId,
- const QByteArray& sessionKey) const;
+ QJsonObject encryptSessionKeyEvent(QJsonObject payloadJson,
+ const QString& targetUserId,
+ const QString& targetDeviceId) const;
#endif
void saveAccessTokenToKeychain() const
@@ -1365,17 +1364,10 @@ ForgetRoomJob* Connection::forgetRoom(const QString& id)
}
SendToDeviceJob* Connection::sendToDevices(
- const QString& eventType, const UsersToDevicesToEvents& eventsMap)
+ const QString& eventType, const UsersToDevicesToContent& contents)
{
- QHash<QString, QHash<QString, QJsonObject>> json;
- json.reserve(int(eventsMap.size()));
- for (const auto& [userId, devicesToEvents] : eventsMap) {
- auto& jsonUser = json[userId];
- for (const auto& [deviceId, event] : devicesToEvents)
- jsonUser.insert(deviceId, event->contentJson());
- }
return callApi<SendToDeviceJob>(BackgroundRequest, eventType,
- generateTxnId(), json);
+ generateTxnId(), contents);
}
SendMessageJob* Connection::sendMessage(const QString& roomId,
@@ -1715,7 +1707,7 @@ Room* Connection::provideRoom(const QString& id, Omittable<JoinState> joinState)
Q_ASSERT_X(!id.isEmpty(), __FUNCTION__, "Empty room id");
// If joinState is empty, all joinState == comparisons below are false.
- const auto roomKey = qMakePair(id, joinState == JoinState::Invite);
+ const std::pair roomKey { id, joinState == JoinState::Invite };
auto* room = d->roomMap.value(roomKey, nullptr);
if (room) {
// Leave is a special case because in transition (5a) (see the .h file)
@@ -2354,30 +2346,15 @@ bool Connection::Private::createOlmSession(const QString& targetUserId,
return true;
}
-std::unique_ptr<EncryptedEvent> Connection::Private::makeEventForSessionKey(
- const QString& roomId, const QString& targetUserId,
- const QString& targetDeviceId, const QByteArray& sessionId,
- const QByteArray& sessionKey) const
+QJsonObject Connection::Private::encryptSessionKeyEvent(
+ QJsonObject payloadJson, const QString& targetUserId,
+ const QString& targetDeviceId) const
{
- // Noisy but nice for debugging
- // qDebug(E2EE) << "Creating the payload for" << data->userId() << device <<
- // sessionId << sessionKey.toHex();
- const auto event = makeEvent<RoomKeyEvent>("m.megolm.v1.aes-sha2", roomId,
- sessionId, sessionKey,
- data->userId());
- auto payloadJson = event->fullJson();
payloadJson.insert("recipient"_ls, targetUserId);
- payloadJson.insert(SenderKeyL, data->userId());
payloadJson.insert("recipient_keys"_ls,
QJsonObject { { Ed25519Key,
edKeyForUserDevice(targetUserId,
targetDeviceId) } });
- payloadJson.insert("keys"_ls,
- QJsonObject {
- { Ed25519Key,
- QString(olmAccount->identityKeys().ed25519) } });
- payloadJson.insert("sender_device"_ls, data->deviceId());
-
const auto [type, cipherText] = olmEncryptMessage(
targetUserId, targetDeviceId,
QJsonDocument(payloadJson).toJson(QJsonDocument::Compact));
@@ -2387,8 +2364,8 @@ std::unique_ptr<EncryptedEvent> Connection::Private::makeEventForSessionKey(
{ "body"_ls, QString(cipherText) } } }
};
- return makeEvent<EncryptedEvent>(encrypted,
- olmAccount->identityKeys().curve25519);
+ return EncryptedEvent(encrypted, olmAccount->identityKeys().curve25519)
+ .contentJson();
}
void Connection::sendSessionKeyToDevices(
@@ -2409,11 +2386,21 @@ void Connection::sendSessionKeyToDevices(
if (hash.isEmpty())
return;
+ auto keyEventJson = RoomKeyEvent(MegolmV1AesSha2AlgoKey, roomId, sessionId,
+ sessionKey, userId())
+ .fullJson();
+ keyEventJson.insert(SenderKeyL, userId());
+ keyEventJson.insert("sender_device"_ls, deviceId());
+ keyEventJson.insert(
+ "keys"_ls,
+ QJsonObject {
+ { Ed25519Key, QString(olmAccount()->identityKeys().ed25519) } });
+
auto job = callApi<ClaimKeysJob>(hash);
- connect(job, &BaseJob::success, this, [job, this, roomId, sessionId, sessionKey, devices, index] {
- UsersToDevicesToEvents usersToDevicesToEvents;
- const auto oneTimeKeys = job->oneTimeKeys();
- for (const auto& [targetUserId, targetDeviceId] :
+ connect(job, &BaseJob::success, this, [job, this, roomId, sessionId, keyEventJson, devices, index] {
+ QHash<QString, QHash<QString, QJsonObject>> usersToDevicesToContent;
+ for (const auto oneTimeKeys = job->oneTimeKeys();
+ const auto& [targetUserId, targetDeviceId] :
asKeyValueRange(devices)) {
if (!hasOlmSession(targetUserId, targetDeviceId)
&& !d->createOlmSession(
@@ -2421,12 +2408,15 @@ void Connection::sendSessionKeyToDevices(
oneTimeKeys[targetUserId][targetDeviceId]))
continue;
- usersToDevicesToEvents[targetUserId][targetDeviceId] =
- d->makeEventForSessionKey(roomId, targetUserId, targetDeviceId,
- sessionId, sessionKey);
+ // Noisy but nice for debugging
+// qDebug(E2EE) << "Creating the payload for" << targetUserId
+// << targetDeviceId << sessionId << sessionKey.toHex();
+ usersToDevicesToContent[targetUserId][targetDeviceId] =
+ d->encryptSessionKeyEvent(keyEventJson, targetUserId,
+ targetDeviceId);
}
- if (!usersToDevicesToEvents.empty()) {
- sendToDevices(EncryptedEvent::TypeId, usersToDevicesToEvents);
+ if (!usersToDevicesToContent.empty()) {
+ sendToDevices(EncryptedEvent::TypeId, usersToDevicesToContent);
QVector<std::tuple<QString, QString, QString>> receivedDevices;
receivedDevices.reserve(devices.size());
for (const auto& [user, device] : asKeyValueRange(devices))
diff --git a/lib/connection.h b/lib/connection.h
index 5b806350..b8246ecb 100644
--- a/lib/connection.h
+++ b/lib/connection.h
@@ -133,8 +133,7 @@ class QUOTIENT_API Connection : public QObject {
Q_PROPERTY(bool canChangePassword READ canChangePassword NOTIFY capabilitiesLoaded)
public:
- using UsersToDevicesToEvents =
- UnorderedMap<QString, UnorderedMap<QString, EventPtr>>;
+ using UsersToDevicesToContent = QHash<QString, QHash<QString, QJsonObject>>;
enum RoomVisibility {
PublishRoom,
@@ -689,7 +688,7 @@ public Q_SLOTS:
ForgetRoomJob* forgetRoom(const QString& id);
SendToDeviceJob* sendToDevices(const QString& eventType,
- const UsersToDevicesToEvents& eventsMap);
+ const UsersToDevicesToContent& contents);
/** \deprecated This method is experimental and may be removed any time */
SendMessageJob* sendMessage(const QString& roomId, const RoomEvent& event);
diff --git a/lib/room.cpp b/lib/room.cpp
index 284d19df..f692c354 100644
--- a/lib/room.cpp
+++ b/lib/room.cpp
@@ -118,7 +118,7 @@ public:
// A map from evtId to a map of relation type to a vector of event
// pointers. Not using QMultiHash, because we want to quickly return
// a number of relations for a given event without enumerating them.
- QHash<QPair<QString, QString>, RelatedEvents> relations;
+ QHash<std::pair<QString, QString>, RelatedEvents> relations;
QString displayname;
Avatar avatar;
QHash<QString, Notification> notifications;
@@ -2687,7 +2687,7 @@ bool Room::Private::processRedaction(const RedactionEvent& redaction)
}
if (const auto* reaction = eventCast<ReactionEvent>(oldEvent)) {
const auto& targetEvtId = reaction->relation().eventId;
- const QPair lookupKey { targetEvtId, EventRelation::AnnotationType };
+ const std::pair lookupKey { targetEvtId, EventRelation::AnnotationType };
if (relations.contains(lookupKey)) {
relations[lookupKey].removeOne(reaction);
emit q->updatedEvent(targetEvtId);