This is not supported by Ruma. The join_rule field, despite being
defined as a pure string, can have associated data to it based on the
join rule variant.
This means that custom and unknown enum variants might lose data when
reserializing.
Let's just skip the serialization of custom join rules in the RoomInfo,
the concrete value is still available in the state store, it's just not
kept at hand in the RoomInfo.
Signed-off-by: Damir Jelić <poljar@termina.org.uk>
Co-authored-by: Ivan Enderlin <ivan@mnt.io>
This method will retrieve the database sizes if available and expose it in the client.
Note: the actual database size measuring is only implemented for the SQLite based stores
The event has been sent to the server and the server has received it.
Yepee! Now, we usually wait on the server to give us back the event via
the sync.
Problem: sometimes the network lags, can be down, or the server may be
slow; well, anything can happen. It results in a weird situation where
the user sees its event being sent, then disappears before it's received
again from the server.
To avoid this situation, this patch eagerly saves the event in the Event
Cache. It's similar to what would happen if the event was echoed back
from the server via the sync, but we avoid any network issues. The Event
Cache is smart enought to deduplicate events based on the event ID, so
it's safe to do that.
This patch removes some logs around the cross-process lock methods. This
is called pretty often by the cross-process lock task, which pollute the
log files.
Making network requests before actually building a client interferes with offline support, especially so in lie-fi situations.
The method is exposed through FFI though and can be used at the final user's discretion (e.g. when submitting a bug report).
We need to handle 2 possible deadlocks for this:
1. We cannot try to refresh an expired access token if this call happens
while we are currently trying to refresh the token. The easiest way
to handle this is to never try to refresh the token when making this
call inside `get_path_builder_input()` so we implement a "failsafe"
mode that disables refreshing the access token in case it expired.
However it attempts the GET /versions again without the token.
2. We cannot access the cached supported versions if we are in the
process of refreshing that cache because the RwLock has a write lock.
So if the access token has expired and we try to refresh it, the
possible calls to `get_path_builder_input()` must not wait for a read
lock to be available. So the solution is to never wait for a read
lock, and skip the cache if a read lock is not available.
This also gets rid of workarounds in other functions.
Signed-off-by: Kévin Commaille <zecakeh@tedomum.fr>
This will allow to handle automatically whether to send an access token
or not on endpoints that don't require it in contexts were can't refresh
it.
We also don't cache calls to GET /versions that were not authenticated,
because they might lack some features compared to an authenticated
request.
Signed-off-by: Kévin Commaille <zecakeh@tedomum.fr>
In theory clients shouldn't make requests to the server-server API. A
way to work around it for this specific case would be to implement
MSC4383.
In the meantime, clients that don't want to use
`Client::server_vendor_info()` won't have to build the extra
dependencies added by ruma-federation-api.
The feature is enabled for the bindings, so it isn't a breaking change
for matrix-sdk-ffi.
Signed-off-by: Kévin Commaille <zecakeh@tedomum.fr>
Exposes the `is_space` flag to FFI in the `NotificationRoomInfo`, so
that a client can tell through a notification if the room that generated
it, is a space or not.
This patch changes the rule of what is a `LatestEventValue` candidate
in case of an edit. An edit must target/relate to its immediate previous
event to be a candidate. Otherwise it's easy to edit an old message
and create a “broken” `LatestEventValue` because it points to an older
message that the user may not be able to find easily.
The supported versions are necessary for querying almost all endpoints,
but after homeserver auto-discovery the well-known info is only
necessary to get the MatrixRTC foci advertised by the homeserver. So it
shouldn't be necessary to always request both at the same time.
Besides:
- Not all clients support MatrixRTC, so they don't need the well-known
info.
- The well-known info is only supposed to be used for homeserver
auto-discovery before login. In fact, the MatrixRTC MSC was changed to
use a new endpoint for this.
- We don't have access to the server name after restoring the Client, so
the well-known lookup is more likely to fail.
Signed-off-by: Kévin Commaille <zecakeh@tedomum.fr>
This patch fixes a bug where a new local `LatestEventValue`
was always created as `LocalIsSending`. It must be created as
`LocalCannotBeSent` if a previous local `LatestEventValue` exists and is
`LocalCannotBeSent`.
This patch adds the companion test too.
This patch improves the Wasm support of the matrix-sdk-ffi crate.
First a uniffi feature needed to be enabled.
Secondly a bunch of methods which don't work under Wasm have been stubbed out.
Signed-off-by: MTRNord <MTRNord@users.noreply.github.com>
Co-authored-by: MTRNord <MTRNord@users.noreply.github.com>
This patch changes the `Semaphore(permit=1)` for a `Mutex`: the
semantics is strictly equivalent, but it removes the need to guarantee
there is a single permit.
This patch updates the reloading of `RoomEventCacheStateLock`
when the cross-process lock over the store is dirty to broadcast
`RoomEventCacheUpdate` and `RoomEventCacheGenericUpdate`. That way the
`Timeline` and other components can react to this reload.
This patch adds the new `test_reset_when_dirty` test, which ensures
the state is correctly reset when the cross-process lock over the store
becomes dirty.
This patch fixes a problem found in a test (not commited yet) where it
was impossible to do multiple calls to `read` if the first guard was
still alive. See the comments to learn more.
This patch extracts fields from `RoomEventCacheState` and move them
into `RoomEventCacheStateLock`. This lock provides 2 methods: `read`
and `write`, respectively to acquire a read-only lock, and a write-only
lock, represented by the `RoomEventCacheStateLockReadGuard` and the
`RoomEventCacheStateLockWriteGuard` types.
All “public” methods on `RoomEventCacheState` now are facade to the read
and write guards.
This refactoring makes the code to compile with the last change in
`EventCacheStore::lock`, which now returns a `EventCacheStoreLockState`.
The next step is to re-load `RoomEventCacheStateLock` when the lock is
dirty! But before doing that, we need this new mechanism to centralise
the management of the store lock.
This patch changes `EventCacheStoreLockState` to own a clone of
the inner store. It helps to remove the `'a` lifetime, and so it
“disconnects” from the lifetime of the store.
This patch replicates the `is_dirty` and `clear_dirty` methods from
`CrossProcessLock` to `CrossProcessLockGuard`. It allows to get an
access to this API from a guard when one doesn't have the cross-process
lock at hand.
This patch updates `EventCacheStoreLock::lock()` to return an
`EventCacheStoreLockState` instead of an `EventCacheStoreLockGuard`, so
that the caller has to handle dirty locks.
This patch adds the `CrossProcessLockState::map` method along with its
companion `MappedCrossProcessLockState` type. The idea is to facilitate
the creation of custom `CrossProcessLockState`-like type in various
usage of the cross-process lock.
These will use `bridge_trace_id` to map an exising client transaction/span to this one so they'll be displayed as a single one in Sentry.
This is done through the `sentry.trace` field, which will be used by `sentry-tracing` to differentiate these kinds of special spans.
The special fields need to be added on the Span creation, that's why we do it in the constructor instead of just using `span.record(...)` later.
This patch adds a `profile: TimelineDetails<Profile>` field to
`LatestEventValue::Local` in `matrix_sdk_ui::timeline` (and the
corresponding `matrix_sdk_ffi` type).
This patch fixes a race condition where events won't get decrypted
because a room key arrives after the initial decryption attempt but
before the UTD has been persisted in the event cache.
The fix is relatively straightforward, we'd need a synchronization point
for the two different tasks, the event cache which adds events and the
redecryptor which listens to room keys to decrypt events.
A lock could have been used, so the storing and redecrypting of events
becomes synchronized via the storage layer. This approach could have
degraded performance since the event cache needs to handle a lot of
events.
The approach that was chosen here is to let the redecryptor listen to
updates coming from the event cache itself. If the event cache tells us
that it persisted a UTD, we will attempt to decrypt. Upon a successful
decryption we will replace the event in the cache as well.
This patch adds a convenience function for the Update enum. If one only
cares about the items contained in the Update, then they can chose to
use this method to extract them out of the enum.
This patch adds a test confirming that the redecryptor has a race
condition.
Namely, events and room keys are received over two different sync
streams from the homeserver. When events are received over the sync, we
first try to decrypt them, this might fail because the room key hasn't
yet arrived over the other sync stream. The event cache will then
persist the event as a UTD.
At the same time, the redecryptor will listen to room keys that arrive
on the other sync stream. Once the redecryptor gets notified about a
room key, it will attempt to fetch the event from the event cache to
decrypt the event and replace it.
Crucially if the key arrives before the event gets persisted but after
the initial decryption attempt we might never attempt to redecrypt such
an event.
We had an instance where a user joined a room on Element X but did not download
the key bundle, so let's add some logging to help figure out what was going on.
This patch uses the newly introduced
`SlidingSyncListBuilder::requires_timeout` to define when the
`RoomListService` must apply a long-polling depending on its state
machine.
This patch adds a new `SlidingSyncListBuilder::requires_timeout` method
that takes a function deciding whether the list requires a timeout, i.e.
if the list should trigger a `http::Request::timeout`, i.e. if it
deserves a long-polling or not.
The default behaviour is kept for compatibility purposes.
This patch updates `SlidingSyncListInner::state` from a
`RwLock<Observable>` to a `SharedObservable`. It is semantically and
programmatically identical, but the API is simpler.
Previously, this used the latest event in the thread as the event to mark as read, while this is not right if we're in a context that hides thread events
This task is still necessary because the redecryptor in the event cache
might miss some room keys.
In this case the timeline can tell the redecryptor which events it
should retry to decrypt.
We're collecting all the UTDs in the timeline and telling the
redecryptor to do its best.
Add an integration test that checks that, when we receive a copy of a megolm
session directly after having previously received it via history sharing, we
get the best bits of both.
... with `merge_received_group_session`.
`merge_received_group_session` expands the logic of `compare_group_session` to
handle the fact that there is more than one axis of "better" or "worse" and we
may need to take the best bits of two copies of the session.
In order to correctly merge sessions, we need more granular comparisons between
two sessions than just "Better" or "Worse", so factor out a method that *just*
looks at the ratchet states.
Expose the room join rules in the `OtherState::RoomJoinRules` event
for the FFI timeline.
It reuses the existing `JoinRules` type from the client module and
converts the event content accordingly. This allows clients to inspect
the room’s current join rule directly from the event. Like `m.federate`,
this field was previously unavailable in the FFI variant of the SDK.
---------
Signed-off-by: JoFrost <20685007+JoFrost@users.noreply.github.com>
The previous message implied that we had received a session for this
message, but that is only one of the several reasons we might encounter
this situation. If redecryption failed, it is more likely we got here
because we'd been asked to attempt redecryption for all UTDs e.g. when
we build a new timeline.
Additionally, having similar wording for the error case and the unable
to decrypt case could also cause confusion, so I adjusted the wording to
make clear which situation is happening.
This patch replaces the `into_guard()` call by a `match` over
`CrossProcessLockKind` so that the `Dirty` case is explicitly handled.
The mid-term idea is to remove the `into_guard()` method because it
is “dangerous” as it hides the `Dirty` case.
This patch undo an optimisation that was initialising the
`RoomListService` at the `SettingUp` state if a `pos` value was
recovered successfully (see bbf9bf2c0b).
The problem is that it starts with a range of 0..99 instead of 0..19,
which can slow things done in particular cases. Whilst a good idea on
paper, it's not in practise. So let's continue to recover the `pos`, but
let's keep starting at the `Init` state.
This patch removes the `connection::Config` type. It was “inspired”
from `deadpool_sqlite`, but we can clearly remove it by using our own
`SqliteStoreConfig` type. It simplifies the way we open a database.
This patch replaces `deadpool-sqlite` by our own implementation in
`crate::connection`. It still uses `deadpool` but the object manager has
a different implementation.
This avoids the scenario where the mock server gets deallocated before
the rendezvous server and thus the rendezvous specific mock guards.
Dropping those in the wrong order will result in a panic.
Hello, I'm writing on behalf of the Citadel product developed by ERCOM.
This PR expose `m.federate` and `history_visibility` in timeline diffs.
These fields are available in the Matrix SDK but were previously omitted
from the FFI variant.
Signed-off-by: JoFrost <20685007+JoFrost@users.noreply.github.com>
This patch changes the signature of `CrossProcessLock::try_lock_once`.
It was returning a:
```rust
Result<CrossProcessLockResult, CrossProcessLockError>
```
Now it returns a:
```rust
Result<Result<CrossProcessLockKind, CrossProcessLockUnobtained>, L::LockError>
```
We will explain these new types in a moment.
This patch also changes the signature of `CrossProcessLock::spin_lock`.
It was returning a:
```rust
Result<CrossProcessLockGuard, CrossProcessLockError>
```
Now it returns a:
```rust
Result<Result<CrossProcessLockKind, CrossProcessLockUnobtained>, L::LockError>
```
First off, we notice that the returned types are now unified. The
`CrossProcessLockResult` type has been renamed `CrossProcessLockKind`
and lives in a `Result::Ok`. The `CrossProcessLockResult::Unobtained`
variant has been removed, but `CrossProcessLockUnobtainedReason`
has been renamed to `CrossProcessLockUnobtained` and lives in a
`Result::Err`.
Second, the `CrossProcessLockError` now is a union type between
`CrossProcessLockUnobtained` and `TryLock::LockError`. It's not used
by `try_lock_once` or `spin_lock`, but only by the code using the
cross-process lock to provide a unified error type.
The ideas behind these changes are:
- it's easy to forward an error from the `TryLock`,
- it's difficult to ignore the `Clean` vs. `Dirty` state of the lock
guard,
- unified API with clearly separated responsibility (the first `Result`
vs. the second `Result`).
Note: the `CrossProcessLockKind::into_guard` method aims at being
removed. It's useful now to maintain compatibility but it's “dangerous”
as it makes trivial to skip `Clean` vs. `Dirty` states. We ultimately
don't want that.
This is necessary because both the timeline and the event cache attempt
to redecrypt events currently.
This will change once only the event cache handles this task.
This patch detects when the cross-process lock has been dirtied.
A new `CrossProcessLockResult` enum is introduced to simplify the
returned value of `try_lock_once` and `spin_lock`. It flattens the
previous `Result<Option<_>>` by providing 3 variants: `Clean`, `Dirty`
and `Unobtained`.
This patch adds `Lease::generation` support in the crypto, media and
event cache stores.
For the crypto store, we add the new `lease_locks` object store/table.
Previously, `Lease` was stored in `core`, but without any prefix, it's
easy to overwrite another records, it's dangerous. The sad thing is
that it's hard to delete the existing leases in `core` because the keys
aren't known. See the comment in the code explaining the tradeoff.
For media and event cache stores, the already existing `leases` object
store/table is cleared so that we can change the format of `Lease`
easily.
This patch adds `CrossProcessLockGeneration`. A lock generation is an
integer incremented each time the lock is taken by another holder. If
the generation changes, it means the lock is _dirtied_. This _dirtying_
aspect is going to be expanded in the next patches. This patch focuses
on the introduction of this _generation_.
The `CrossProcessLock::try_lock_once` method, and
the `TryLock::try_lock` method, both returns a
`Option<CrossProcessLockGeneration>` instead of a `bool`: `true` is
replaced by `Some(_)`, `false` by `None`.
Creating a `RoomMember` takes a lot of store queries, and previously all of them were done sequentially. I've tried to make this process run as much in parallel as I can.
I find a single match statement easier to reason about than one nested in another.
Also, import `UnableToDecryptReason::*`, to shorten the match lines.
I want to be able to test that the correct `UtdCause` is presented for withheld
historical messages. That means we need to use `/sync` rather than `/event` to
obtain the message (since the MSC4115 `membership` field is missing on `/event`
(https://github.com/element-hq/synapse/issues/17486)). So then the most
realistic way to get hold of the actual UtdCause is to use a Timeline.
Of course, the thing I actually want to test doesn't actually work correctly,
so it's left as a FIXME in this commit.
When constructing a key bundle, if we had received a key bundle ourselves, in
which one or more sessions was marked as "history not shared", pass that on to
the new user.
This patch introduces the `sqlite` and `indexeddb` feature flag,
enabling the use of SQLite or IndexedDB for the stores. This patch also
introduces the ability to use non-persistent, in-memory stores.
The new `ClientBuilder::in_memory_store`, `ClientBuilder::sqlite_store`
and `ClientBuilder::indexeddb_store` methods are introduced to
configure the stores. This patch adds new `SqliteStoreBuilder` and
`IndexedDbStoreBuilder` structure.
It will allow us to fetch the latest event id coming from the SDK instead of deciding which one to use in the clients, which could be altered by filters, post-processing, etc.
This method shouldn't be widely used, but it's useful when we want to mark the room as fully read when leaving it and at the same time we have to destroy the room and timeline instances immediately so their in-memory cache is cleared
Tests that a to-device `m.room_key.withheld` event can be
serialized (using JSON), then deserialized as a RoomKeyWithheldEntry.
Ensures compatibility with exisiting store data.
This is an unstable feature but as per
[MSC3230](https://github.com/matrix-org/matrix-spec-proposals/pull/3230)
each space room might have an optional
`m.space_order`/`org.matrix.msc3230.space_order` string field in its
room account data defining the lexicographical order in which the spaces
should be displayed, with spaces missing this field shown at the bottom
and ordered by their room id.
This is important since we want to move the redecryption logic out of
the timeline into the main crate. This in turn means that we don't have
such low level access to the redecryption logic.
Not all tests were rewritten:
- `test_retry_edit_and_more` Is proving to be difficult to rewrite,
may come in a separate commit.
- `test_retry_fetching_encryption_info` Needs verification state
changes. Will be rewritten on the event cache layer
A new batch of breaking changes, allowing to stop providing dummy
`SupportedVersions` where they are not necessary.
Signed-off-by: Kévin Commaille <zecakeh@tedomum.fr>
This patch moves the `Client::get_dm_room` helper function and its tests
from `src/encryption/mod.rs` to `src/client/mod.rs`, so it may be used
without the `e2e-encryption` crate feature enabled.
- [x] Public API changes documented in changelogs (optional)
Signed-off-by: Ginger <ginger@gingershaped.computer>
This patch adds the complementary login flow for the already existing QR code login support.
Namely, previously it was only possible for the new device to scan a QR code to log in. Now
it's possible for the new device to create the QR code and let the existing device scan it.
- [x] Public API changes documented in changelogs (optional)
Signed-off-by: Johannes Marbach <n0-0ne+github@mailbox.org>
In the previous version of the thread, the following sequence of events
could happen:
- we subscribe to the thread linked chunk changes
- *then*, the events are being added to the thread linked chunk
This is an edge case where, since we've subscribed to the thread linked
chunk, the thread root will be "known" to be part of a thread, and will
be appended to the thread linked chunk.
If the events happen in the other order (first the events are added to
the thread linked chunk, then we subscribe to the changes), then the
thread root will not be part of the thread linked chunk (because when it
arrived, we didn't know it would be a thread root). As such, the thread
linked chunk state would end up being different in this case.
The solution is to make it so that the thread linked chunk is always
subscribed to *before* any events are added to it. This way, we make
sure that we'll always have the thread root in the thread linked chunk.
In this initial version, a redaction will:
- *remove* the event from the thread chunk, as does Element Web,
- update the thread summary to reflect the new number of messages in the
thread, and let us have a thread summary with 0 replies.
A next commit will adapt the code so that a thread summary with 0
replies is removed.
Brings changes to the requests metadata. It was changed from a struct to a trait, and the authentication scheme is now an associated type.
This allows to forbid at compile time requests that use an unsupported authentication scheme.
When receiving an encrypted to-device message, if the sender device is not in
the store, but the event includes `sender_device_keys`, use
`sender_device_keys` to do the verification checks etc.
Fixes: https://github.com/matrix-org/matrix-rust-sdk/issues/5768
It was incorrect to say that the timeline focus can be changed after the
timeline has been created, since it is *not* the case. Also explained
what the default value is.
Most clients will probably work with values between 0 and 1 and need to
convert it just to send it, so we can move that conversion into the SDK.
This is also more forwards-compatible, because MSC3246 now has a
different max value for the amplitude, so when this becomes stable, the
only change needed will be in the SDK.
Signed-off-by: Kévin Commaille <zecakeh@tedomum.fr>
Currently, when we receive a room key bundle to-device event, we don't look up
the sender device at all, meaning that the message is then marked as "from
missing device", which means that if you turn on "exclude insecure devices",
the message is dropped.
This patch changes the logic so that room key bundle to-device events are
treated the same way as most other to-device events (except room keys, which
continue to be special).
Fixes: https://github.com/matrix-org/matrix-rust-sdk/issues/5613, although the
integration test now fails because instead we hit https://github.com/matrix-org/matrix-rust-sdk/issues/5768.
`Account::parse_decrypted_to_device_event` is getting a bit big and unwieldy,
so factor out the bit that attempts to find the sending device.
(Also, remove an outdated TODO.)
The legacy mention push rules were removed, and the
`contains_display_name` condition was deprecated.
Some tests check for backwards-compatibility with legacy mentions, so we
need to add them back for those tests.
A test with an encrypted event was relying on the legacy mentions, so
the encrypted event was replaced with another one with an intentional
mention.
Signed-off-by: Kévin Commaille <zecakeh@tedomum.fr>
StringEnum now also implements Ord, PartialOrd, Eq and PartialEq so it
is not necessary to derive them. Also the ordering used is comparing the
string representation of the variants.
Signed-off-by: Kévin Commaille <zecakeh@tedomum.fr>
Extended profile fields were stabilized so the old endpoints are now
deprecated, and there are a few other changes.
Signed-off-by: Kévin Commaille <zecakeh@tedomum.fr>
Adds `DeviceKeys::has_signed` and `DeviceKeys::check_self_signature`, and
removes `DeviceData::has_signed` and `DeviceData::verify_device_keys`.
I just found this easier to grok, and it means we can avoid needlessly turning
a `DeviceKeys` into a `DeviceData` sometimes.
This should only happen when a room has been forgotten and was a room
DMs before. Ideally, we'd clean up the room DM event data, but since
this is slightly more involved, we don't do that here just quite yet.
With Rust 2024, by default `impl` return types use any generic that is
in scope, so in these cases the lifetime of `self`.
But since the return type is actually owned, the returned impl shouldn't
use any lifetime, which is what `use<>` does.
Signed-off-by: Kévin Commaille <zecakeh@tedomum.fr>
With Rust 2024, by default `impl` return types use any generic that is
in scope, so in these cases the lifetime of `self`.
But since the return type is actually owned, the returned impl shouldn't
use any lifetime, which is what `use<>` does.
Signed-off-by: Kévin Commaille <zecakeh@tedomum.fr>
We don't really need the poll start event entirely, since we're only
interested in the start block and the fallback text. With this, it'll be
simpler to create embedded polls from poll edit events.
Brings a breaking change with event structs being non-exhaustive now,
so they need to be constructed with methods rather than with a struct
declaration.
Signed-off-by: Kévin Commaille <zecakeh@tedomum.fr>
There is a breaking change in Ruma and those types are now
non-exhaustive so they can't be built with the struct declaration
anymore.
Signed-off-by: Kévin Commaille <zecakeh@tedomum.fr>
We actually want other event formats in those cases, and in most cases
just using `.into()` is enough to generate the proper format.
Signed-off-by: Kévin Commaille <zecakeh@tedomum.fr>
And use the proper fields for these formats. We also add more conversion
implementations for the types associated with these formats.
Signed-off-by: Kévin Commaille <zecakeh@tedomum.fr>
This patch moves the creation of the `message` in `TracingTimer` if and
only if the log is enabled. Computing it every time is useless, and can
even slow things down (because of the time calculation).
This patch introduces a write-only connection in `SqliteStateStore`
_à la_ `SqliteEventCacheStore`. The idea is to get many read-only
connections, and a single write-only connections behind a lock, so that
there is a single writer at a time.
This patch renames the `acquire` method to `read`, and it introduces a
new `write` connection.
**NOTE:** _this should not be merged until matrix-org/rust-indexed-db#1
is merged! The `[patch]` in this branch should point to the official
`matrix-org` fork of `rust-indexed_db`, but is currently pointed at my
personal fork._
## Background
This pull request makes updates
[`indexed_db_futures`](https://docs.rs/indexed_db_futures/latest/indexed_db_futures/index.html)
in the `matrix-sdk-indexeddb` crate. The reason we'd like to update this
dependency is because the version currently used does not fully support
the Chrome browser (see #5420).
The latest version of `indexed_db_futures` has significant changes. Many
of these changes can be integrated without issue. There is, however, a
single change which is incompatible with the `matrix-sdk-indexeddb`
crate. Namely, one cannot access the active transaction in the callback
to update the database (for details, see Alorel/rust-indexed-db#66).
### An Updated Proposal
Originally, new migrations were implemented in order to work around this
issue (see #5467). However, the proposal was ultimately rejected (see
@andybalaam's
[comment](https://github.com/matrix-org/matrix-rust-sdk/pull/5467#issuecomment-3149550617)).
For this reason, the dependency has instead been `[patch]`ed in the
top-level `Cargo.toml` with a modified version of `indexed_db_futures`
(see matrix-org/rust-indexed-db#1). Furthermore, these changes have been
proposed to the maintainer and are awaiting feedback (see
Alorel/rust-indexed-db#72).
### Why do we need the active transaction in our migrations?
The `crypto_store` module provides access to the active transaction to
its migrations (see
[here](https://github.com/matrix-org/matrix-rust-sdk/blob/ca89700dfe9f29dcd823bb10861807f9d75e0634/crates/matrix-sdk-indexeddb/src/crypto_store/migrations/mod.rs#L211)).
Furthermore, there is a single migration (`v11_to_v12`) in the
`crypto_store` module which actually makes use of the active transaction
(see
[here](https://github.com/matrix-org/matrix-rust-sdk/blob/ca89700dfe9f29dcd823bb10861807f9d75e0634/crates/matrix-sdk-indexeddb/src/crypto_store/migrations/v11_to_v12.rs#L23)).
For clarity, the reason `v11_to_v12` is problematic in the latest
versions of `indexed_db_futures` is because it is simply adding an index
to an object store which was created in a different migration and this
requires access to the active transaction. All the other migrations
create object stores and indices in the same migration, which does not
suffer from the same issue.
## Changes
- Move `indexed_db_futures` to the workspace `Cargo.toml` and add a
`[patch]` so that it points to a modified version.
- Add `GenericError` type and conversions in order to more easily map
`indexed_db_futures` errors into `matrix-sdk-*` errors.
- Update all IndexedDB interactions so that they use the upgraded
interface provided by `indexed_db_futures`
- Add functionality for running `wasm-pack` tests against Chrome
---
Closes#5420.
---
- [ ] Public API changes documented in changelogs (optional)
Signed-off-by: Michael Goldenberg <m@mgoldenberg.net>
---------
Signed-off-by: Michael Goldenberg <m@mgoldenberg.net>
This patch replaces `user_can_kick` by `user_can_kick`: it performs an
extra check to make sure the acting user has at least the same power
level as the target user.
The former has been merge in the latter, and it errors when generating
the docs in a recent version of nightly, like the one used on docs.rs.
This also requires to bump the version of nightly used in CI, otherwise
it would break the docs generation.
Signed-off-by: Kévin Commaille <zecakeh@tedomum.fr>
This patch splits `power_levels: &Option<(&UserId, RoomPowerLevels)>`
into 2 variables: `own_user_id: Option<&UserId>` and `power_levels:
Option<&RoomPowerLevels>`. The idea is to be able to get the
`own_user_id` even if the power levels are `None`.
This helps make sure the rooms to be left were actually part of the space graph as they are stored inside the `LeaveRoomHandle` and filtered from there. On the FFI layer on the other hand, we still take plain strings as working around the limitations would've significantly complicated things.
When leaving a space the user should be informed of which rooms are DMs (already part of the `SpaceRoom`)
and in which they might be the last admin, where leaving would prevent anybody else for taking control.
It doesn't make sense to send a formatted caption without a plain text
caption so using TextMessageEventContent forces the latter to be present.
This also allows to use the helpful constructors of
TextMessageEventContent.
Signed-off-by: Kévin Commaille <zecakeh@tedomum.fr>
Part of the fix to
https://github.com/element-hq/element-x-android/issues/5099
Allows applications to distinguish between errors that occur when
unlocking Secret Storage, or errors that occur when importing a secret,
so that they can display appropriate feedback (or not) to the user.
- [ ] Public API changes documented in changelogs (optional)
<!-- Sign-off, if not part of the commits -->
<!-- See CONTRIBUTING.md if you don't know what this is -->
Signed-off-by:
---------
Signed-off-by: Hubert Chathi <hubertc@matrix.org>
I was wrong in a previous commit: both receipts are on the same event
anyways, so we can safely override the keys in the read receipts map
(overriding would mean both receipts point to the same event, which is
fine, as we're displaying only one of those).
This is a fix, because some other code elsewhere will use both kinds of
receipts whenever they're received over sync. The code that's modified
in this patch is called for the initial load of receipts, that happens
whenever we see a new event. Since the two code paths were not doing the
same thing, this would affect the displayed receipts, depending on
whether we received them during sync, or after loading the timeline for
the first time.
This case is very specific to the room pagination, and will not apply to
the thread pagination; by removing it from the generic pagination logic,
we'll be able to use the generic pagination logic for threads.
… when known to the client and forward updates through the existing
`subscribe_to_space_updates` mechanisms.
This allows clients to listen to updates without having to resort to a
separate room info subscription on their side.
The raw event was being deserialized in a wrong way and it could have a missing room id in some cases, returning an error even when the event was found
For thread permalinks, we start with a /context query that will load the
focused event, and maybe a few other in-thread events. In fact, it can
also include the thread root event, which was excluded before. Instead,
we would get a previous-token for back-paginations, which would be used
in /relations. When the request to /relations returns an empty previous
token, that means we've reached the start of the thread, and in this
case we would manually load the root with /event.
We can do better, if the root event is part of the initial /context
response: skip the back-paginations altogether, and make sure to include
the root event in `init_focus()`.
It's much faster now as it downloads the latest version of the
precompiled binary from Github, and it will use the latest tagged
version of cargo-machete by default.
This patch revisits a feature we have disabled a couple of days ago:
the `recency` sorter was initially only supporting the recency stamp,
then later the recency stamp _and_ the latest event's timestamp. It was
however buggy and we had to revert it. Now it's time to re-introduce it
but with a different approach.
The previous rules were:
1. if two rooms have a latest event, use their latest event's timestamps
as their _scores,
2. if one of room has a latest event, use the recency stamp as their
_scores_ for both rooms.
Rule 2 was buggy because one room was sometimes using its latest
event's timestamp, and sometimes its recency stamp, based on what it was
compared to. It was an error!
The new rules are the following:
1. unchanged
2. if one room has a latest event, use its latest event's timestamp as
its _score_, and use no _score_ for the other room,
3. if two rooms have NO latest event, use the recency stamp as their
_scores_.
It means that a room with no latest event will always be sorted _after_
a room with a latest event. It can feel cruel, but it should be an edge
case. When a room is synchronised, it should receive events, which
should trigger the computation of a latest event.
Note that this patch also renames _rank_ to _score_, as I consider it's
a better vocabulary. It could be confusing to use _rank_ as one can
expect all rooms to be indexed and get a rank, but it's not the case.
_Score_ sounds better.
This allows custom message-like events (created by the `EventContent` macro from ruma) to be added to the timeline if they are explicitly allowed when building the timeline with a custom `event_filter`.
The custom event content is not available directly to the consumer, but it can still fetch it from the matrix-sdk client with its `event_id`, or display a "this type of event is not supported".
Signed-off-by: Itess <me@aloiseau.com>
Fixes#5598.
This patch tries to solve a problem raised by Complement Crypto. In
`compute_latest_events`, in two places, `RegisteredRooms::rooms` was
locked with an exclusive write access. Then, during the updates of
the latest events (via `RoomLatestEvents::update_with_event_cache` and
`RoomLatestEvents::update_with_send_queue`), the state store lock is
acquired to update the state store. At the same time, in the sync, the
state store lock can **already** be taken to store the new updates, and
the function `subscribe_to_room_latest_events` is called, which waits
on the lock around `RegisteredRooms::rooms` to be available. We have a
dead lock:
- `compute_latest_events` waits on the state store lock while the lock
on `RegisteredRooms::rooms` is taken with an exclusive access,
- the sync has acquired the state store lock while it waits on the lock
on `RegisteredRooms::rooms`
This patch introduces a lock inside `RoomLatestEvents`. A new
`RoomLatestEventsState` type is introduced to be the lockable value. A
new `RoomLatestEvents::read()` and `RoomLatestEvents::write()` methods
are introduced to respectively return a `RoomLatestEventsReadGuard` and
a `RoomLatestEventsWriteGuard` type. The idea is to abstract a bit the
owned lock guard and to distribute the methods that were previously on
`RoomLatestEvents` in the new guard types, so that we keep the `&self`
and `&mut self` semantics, plus we take a lock for multiple operations.
The deadlock is fixed because of all the following reasons combined:
- only `RegisteredRooms::room_latest_event`,
`RegisteredRooms::forget_room` and `RegisteredRooms::forget_thread`
take a write lock over `RegisteredRooms::rooms`,
- `compute_latest_events` no longer takes a write lock over
`RegisteredRoooms::rooms`, but it also has a short-lived lock:
its read lock is dropped as soon as the **owned** write lock over
`RoomLatestEvents` is taken.
Now, `subscribe_to_room_latest_events` can acquire a write lock over
`RegisteredRooms::rooms` while `compute_latest_events` is doing the
updates. If the state store lock is acquired here, it will just wait
its availability: the sync flow can finish and release the lock without
being blocked by `subscribe_to_room_latest_events`.
This patch updates `SlidingSyncResponseProcessor::handle_room_response`
to automatically call `LatestEvents::listen_to_room` based on
`http::Response`'s `rooms`.
Why? Because when a sync is received, we want its `LatestEventValue`
to be computed, so that it can trigger a `RoomInfoNotableUpdate`,
which will update the `RoomList`, which will re-sort the
rooms. So far, `LatestEvents::listen_to_room` was called by
`RoomListService::subscribe_to_rooms`, but it's possible to receive a
room update via the sync for a room that is not subscribed, i.e. out
of the viewport of the room list in Matrix clients (it's recommended
to subscribe to rooms that “enter” the viewport). Without this
patch, rooms are receiving updates but the room list is not entirely
refreshed/recalculated.
This way we can retrieve random events in a room and check their properties - this is needed to decide whether a permalink for an event should open in a thread or not
This way we can have the same focus handling both the focused event pagination in the main timeline with the `Paginator` and the focused event pagination in a thread with `EventThreadsLoader`.
The actual paginator is populated in `TimelineController::init_focus` after we call `/context` and can check if the event is part of a thread.
For some reason, running `cargo xtask ci clippy` locally would now fail,
complaining that the recent emoji functions didn't exist, in the FFI
layer. I suspect it's because some of the uniffi derive macro to export
functions incorrectly propagates the `cfg` guards; so a solution is to
move all this code under a new mod, that's enabled if and only if the
feature's enabled.
This patch fixes an issue where the `recency` sorter is based on either
the latest event's timestamp, or the room recency stamp. This cannot
work with a sort algorithm as the position of a particular room can
be different based on what it is compared to (i.e. if the rooms have a
latest event value or not).
This patch updates the `recency` sorter to only use the recency stamp
for now, as the latest event is not yet computed for all rooms.
Some background knowledge: the room notification modes are functions of
the push rules events, and they will only change when the push rules
event changes. As a result, there are only two cases where we need to
recompute them:
- when the push rules event changed, we need to recompute all the room
notification modes, in case one has changed;
- when we run into a new room, we need to compute an initial value for
its room notification modes.
Based on these observations, this improves the code to avoid recomputing
the room notification mode on every single sync response. Instead,
they're computed if and only if the push rules event has changed, or for
new rooms only.
Also, this avoids reconstructing one `NotificationSettings` object per
room, since this would load from the database each time. Instead, a
single object is created (at most), and its `Rules` object is directly
accessed, to avoid repeatedly taking the lock on its internal `rules`
field.
This makes it so that the time spent under this method from tens of
milliseconds to less than 1 millisecond, in testing. See the pull
request initial post for more numbers.
This patch improves throughput by +710% in `room_list_service` sorters
and filters. It introduces a new `room_list_service::Room` type that
derefs to `matrix_sdk::Room`. However, it **caches** some data from
`matrix_sdk::Room`. Why doing so? Because filters, but more specifically
sorters!, are calling methods on `matrix_sdk::Room`, so likely on
`matrix_sdk::RoomInfo`, quite intensively. `RoomInfo` is behind a
`SharedObservable`, which means it's behind a lock. Each time a sorter
sorts 2 rooms, the lock on `RoomInfo` can be called twice or more.
By caching the data, `RoomInfo` is reached once per refresh data, but
not during the filtering nor the sorting. It greatly reduces contention
on the `RoomInfo` lock, which improves the throughput by +710%, and the
time by -87%.
The cached data are refreshed in `merge_stream_and_receiver` when
(i) the stream of `Room` is updated, or when (ii) the stream of
`RoomInfoNotableUpdate` is updated. It's a central place it happens,
which isolates the behaviour.
This patch adds 2 methods on `RoomInfo`: `new_latest_event_timestamp`
and `new_latest_event_is_local`, which respectively returns
`LatestEventValue::timestamp` and `LatestEventValue::is_local`. The goal
is to avoid cloning a `LatestEventValue` when it's useless. For example,
in the room list sorters!
This patch also updates the room list sorters `recency` and
`latest_event` to use these new methods. It improves the speed and
throughput by 18%.
These are meant to be replaced with specific endpoints for each case.
Added the `global_account_data_mock_builder` helper function to make building these mock endpoints a bit easier.
By making it explicit that the async closures return a unit type, we can
get rid of these two allow lines, and prepare for migrating this code to
the 2024 edition.
This patch updates the `recency` room list sorter to no longer
use the `LatestEventValue::timestamp` method. It keeps using the
`Room::recency_stamp` for the moment, as it was the case before. This
patch is a test to try finding the problem in some Matrix clients where
the room list becomes unusable. We suspect it's because of this patch
sorter.
This patch defines a new log target,
`MatrixSdkCommonDeserializedResponses`. It is enabled by the
`SyncProfiling`, `EventCache` or `Timeline` log packs.
This patch also changes the level of the log in
`TimelineEvent::timestamp` from `trace` to `warn`.
This will pave the way for permalink targets which are for events in a
thread, by making it possible to add a future condition in the
`TimelineFocusKind::Event` case (if the pagination used under the hood
is using /relations, then it's a thread).
This patch adds a log in `TimelineEvent::timestamp` when the `timestamp`
has to be extracted. It can be a performance problem depending on when
it's called.
After the merge of
https://github.com/matrix-org/matrix-rust-sdk/pull/5648, we want
all events to get a `TimelineEvent::timestamp` value (extracted from
`origin_server_ts`).
To accomplish that, we are emptying the event cache. New synced events
will be built correctly, with a valid `TimelineEvent::timestamp`,
allowing a clear, stable situation.
It turns out that creating a cross-signing identity *without* the upload
requests is a very common thing to do, especially in tests. We can simplify
some code by factoring it out as a new helper.
This patch adds the `timestamp` field to `TimelineEvent`.
It's a copy of the `origin_server_ts` value, parsed as an
`Option<MilliSecondsSinceUnixEpoch>`. It's `None` if the parsing failed,
or if the `TimelineEvent` was deserialised from a version before this
new field was added.
A new `extract_timestamp` function is added for this purpose. It
protects against malicious `origin_server_ts` where the value can be
set to year 2100 for example. The only protection we are adding here is
to take the `min(origin_server_ts, now())`, so that the event can never
been “in the future”.
It doesn't protect against a malicious value like 0. It's non-trivial to
define a minimum timestamp for an event.
When a `TimelineEvent` is mapped from one kind to another kind, the
`timestamp` is carried over. To achieve that, new `to_decrypted` and
`to_utd` methods are added.
The rest of the code is updated accordingly.
This patch renames the `LockStoreError` enum to `CrossProcessLockError`
to be consistent with the other types in the same module.
The `BackingStoreError` variant is also renamed to `TryLockError`.
This patch renames the `BackingStore` trait to `TryLock`. It also
renames the `CrossProcessLock::store` field to `locker`. It's not
necessarily a store, it can be anything.
This PR is a start to the process of splitting the media store from the
event cache store. #5410
It contains:
* Split `MediaStore` trait from `EventCacheStore`.
* Rename `EventCacheStoreMedia` to `MediaStoreInner`.
* Move relevant tests into `MediaStoreIntegrationTests`.
This will be done over 3 PR's (reviewing 1, 2, 3 then merging 3 into 2
into 1).
A reminder comment for my own sanity:
This PR will not pass tests until after merging.
Current state of this PR:
- [x] Step 1 reviewed #5568
- [x] Step 2 reviewed #5569
- [x] Step 3 reviewed #5571
- [x] Step 3 merged into Step 2
- [x] Step 2 merged into Step 1
- [ ] Add changes to changelog.
- [ ] Ready to merge 🎉
Note, may also want to:
* Re-organize file structure
* Split/refactor benchmarks namely `benchmarks/benches/event_cache.rs`
<!-- description of the changes in this PR -->
- [ ] Public API changes documented in changelogs (optional)
<!-- Sign-off, if not part of the commits -->
<!-- See CONTRIBUTING.md if you don't know what this is -->
Signed-off-by: Shrey Patel shreyp@element.io
---------
Co-authored-by: Shrey Patel <shreyp@element.io>
This PR is part of an onging effort to move responsiblity to the EC app
and out of the EX apps.
4 intends (f.ex `join_existing` `start_new_dm`... ) (as url paramters)
are introduced in recent element call versions. Those intends behave
like defaults. If an intend is set a set of url parameters are
predefined.
Not all params can be covered by the intend (for insteance the
`widget_id` or the `host_url`).
This PR splits the url parameters into configuration (things that can be
configured by the intent) and properties (things that still need to be
passed one by one)
The goal with this change is that EX only needs to configre the intent
once and the EC codebase can update the behavior in those 4 specific
scenarios in case new features come along (auto hangup when other
participants leave, send call ring notification...)
Signed-off-by: Timo K <toger5@hotmail.de>
<!-- description of the changes in this PR -->
- [ ] Public API changes documented in changelogs (optional)
<!-- Sign-off, if not part of the commits -->
<!-- See CONTRIBUTING.md if you don't know what this is -->
Signed-off-by:
---------
Signed-off-by: Timo K <toger5@hotmail.de>
This patch adds the notion of _rank_ in the `recency` sorter to avoid
confusion around `u64`: is it a timestamp or a recency stamp? It's
purely semantics, but I hope it clarify the code.
This patch renames all the structure `*Matcher` to `*Sorter`.
And their `matches` method become `cmp`. It was copy-pasted from
`room_list_service::filters` probably, but the semantics here are not
_matcher_ but _sorter_. It's more consistent that `cmp` returns an
`Ordering`.
This patch updates the `recency` sorter of the room list to rely on the
`LatestEventValue`'s timestamp, or on the `bump_stamp` returned by the
sync. Using the `LatestEventValue`'s timestamp is more reliable as we
don't rely on the server. However, we must be careful to compare values
of the same nature because the timetamp from the `LatestEventValue` and
the `bump_stamp` doesn't represent the same thing! The `bump_stamp` is
only used when the value for the `LatestEventValue` is `None`.
It's a compromise to get a more accurate listing. Though,
`LatestEventValue::timestamp` returns the `origin_server_ts` value,
which can be forged by a malicious user (then a room could be _sticked_
at the top or at the bottom of the room list). Note that this problem
already existed in the past before the server computed a `bump_stamp`.
Also note that some homeservers use the `origin_server_ts` as the
`bump_stamp` value. Anyway, it's not a security risk as far as I know.
This patch implements the new `latest_event` sorter for the room list
which puts the local latest events before the other kinds (like `Remote`
or `None`).
This patch updates the signature of `TerminationReport`'s
constructors so that it's impossible to create invalid states, like
an `origin` of `TerminationOrigin::RoomList` with an error of type
`encryption_sync_service::Error`. The constructors force the error to
match the origin.
This patch moves `SyncTaskSupervisor::check_if_expired` to
`TerminationReport::has_expired`. Because `TerminationReport` now holds
the error, we can remove the `has_expired` field and get a `has_expired`
method!
This patch changes the `TerminationReport::is_error` field to become
`error: Option<Error>`. This patch also creates new constructor on
`TerminationReport` to simplify the code.
By slightly changing the shape of the function used to process read
receipts, we can make it so that it's trivial to run concurrently, which
gives some nice speedups locally.
Distribution of 6 worst case processing time, initial response:
Before:
0.172524963s
0.216173016s
0.252289760s
0.257619156s
0.275838632s
0.280295891s
After:
0.083094692s
0.117074046s
0.130246646s
0.132577343s
0.138685246s
0.170287945s
This ensures that we're using the same color despite what your color
scheme of your terminal is. Some color schemes might produce unreadable
combinations of foreground color and background color.
Specially important, the one from `ClientBuilder::build` as it avoids a situation where the builder would infinitely try to get a response for this request and never create the `Client` or fail.
This patch zips the `unable_to_decrypt_info` and the `meta` arguments
into a single one. They are strictly related, `meta` has no sense if
`unable_to_decrypt_info` has no sense neither.
The necessary patch was merged[1] now, thanks to Jonas. We still need
the patch section since we don't have a release with the patch.
[1]: https://github.com/tokio-rs/tracing/pull/3000
Our paranoid-android for was configured to use our fork of the tracing
crates.
But paranoid-android will already use our tracing fork since it's
defined in the patch section. The patch section will override the
dependencies for all of our dependencies as well.
This can be seen in the dependency tree using:
$ cargo tree -p matrix-sdk-ffi --target=aarch64-linux-android
This will be used inside the WASM SDK to introduce a similar field to
its EncryptionSettings struct.
Signed-off-by: Skye Elliot <actuallyori@gmail.com>
This patch updates `LatestEvent::update` to call the new
`LatestEvent::store` method, which will store the new `LatestEventValue`
in the `RoomInfo` struct, and will persist it in the `StateStore`.
This patch also adds the test for this new feature.
This patch adds the new `new_latest_event: LatestEventValue` field in
`RoomInfo`. The `latest_event` is kept for the moment, but it will be
removed once the new API has landed entirely.
This patch moves `LatestEventValue` into the
`matrix_sdk_base::latest_event` module. If we want to store this value
in `RoomInfo`, it must be in this crate.
Because it's not allowed to `impl T` where `T` lives in a different
crate, this patch changes the `impl LatestEventValue` to `struct
LatestEventValueBuilder` + `impl LatestEventValueBuilder`. Luckily, all
methods on `LatestEventValue` are only constructors, so the change is
super straightforward.
This patch replaces `OwnedRoomId` by `WeakRoom` in `LatestEvent`. Apart
from simplifying a couple of method' signatures, it also opens the road
for storing the `LatestEventValue` in `RoomInfo`.
Now that (since https://github.com/matrix-org/matrix-js-sdk/pull/4918) Element
Web uses separate subscribers for each OlmMachine, rather than a single global
one with a separate LevelFilter, EW's logs are very verbose because they
receive all the TRACE logs.
Dropping the TRACE logs on the floor isn't my favourite solution, but
everything else seems to be a bit harder than I have time for right
now:
* Sending TRACE logs up to the JS side in case it wants to print them would (a)
increase overhead and (b) be an annoying breaking change in JsLogger
* Ideally we'd let the application configure its logging more precisely via an
`EnvFilter` or something, but I'm not really sure what the API would look like
for that.
So for now, we take the easy path.
Since the server will reject any duplicate one-time keys forever,
clients which encounter such an error will spam sentry with such
reports.
This patch ensures that we only send the sentry report once.
This patch revisits the `assert_latest_event_content` macro to not take
a `true` or `false` value. It feels a bit weird to read. Instead, `with
|factory| { … }, true` becomes `event |factory| { … } is a candidate`.
Same for the `false`case which becomes `is not a candidate`. No more
comma, it feels a bit more like a sentence.
This patch replaces `LocalLatestEventValue::content` and `…::event_type`
fields by using the existing `SerializableEventContent`. It does exactly
the same thing.
The problem is: `LatestEventContent` cannot be serialized. It's annoying
because it means we can't store a `LatestEventValue` (that wraps a
`LatestEventContent`) in the database.
This patch revisits `LatestEventValue`. Before we got:
```rust
pub enum LatestEventValue {
None,
Remote(LatestEventContent),
LocalIsSending(LatestEventContent),
LocalCannotBeSent(LatestEventContent),
}
pub enum LatestEventContent {
RoomMessage(RoomMessageEventContent),
Sticker(StickerEventContent),
Poll(UnstablePollStartEventContent),
CallInvite(CallInviteEventContent),
CallNotify(CallNotifyEventContent),
KnockedStateEvent(RoomMemberEventContent),
Redacted(AnySyncMessageLikeEvent),
}
```
`LatestEventContent::Redacted` contains an `AnySyncMessageLikeEvent`.
That's the part that is not serializable.
It appears that `LatestEventContent` isn't necessary! The only thing we
need is to _filter_ the events by their type, no need to _find and
map_. The `LatestEventValue` can contain the entry event directly (e.g.
a `TimelineEvent` for the event cache). Okay, let's do that.
```rust
pub enum LatestEventValue {
None,
Remote(RemoteLatestEventValue),
LocalIsSending(???),
LocalCannotBeSent(???),
}
type RemoteLatestEventValue = TimelineEvent;
```
What about the `Local*` variants? We can't use a `TimelineEvent`. We
need a new type for that:
```rust
pub enum LatestEventValue {
None,
Remote(RemoteLatestEventValue),
LocalIsSending(LocalLatestEventValue),
LocalCannotBeSent(LocalLatestEventValue),
}
pub struct LocalLatestEventValue {
pub timestamp: MilliSecondsSinceUnixEpoch,
pub content: Raw<AnyMessageLikeEventContent>,
pub event_type: String,
}
```
We don't need the event ID nor the transaction ID in
`LocalLatestEventValue`.
That's the only change. All the other changes are about the tests.
This will resolve a number of transitive dependency issues when testing
crates that do not enable the `experimental-encrypted-state-events` feature
flag by default.
Signed-off-by: Skye Elliot <actuallyori@gmail.com>
Implements support for decryption of state events
- [ ] Introduce a case for `AnySyncStateEvent::RoomEncrypted` to the
`state_events` sync response processor.
- [ ] Introduce modified `Room::decrypt_event` and
`::try_decrypt_room_event`.
- [ ] Introduce testing macro
`assert_let_decrypted_state_event_content`.
- [ ] Add casts and explicit type hints where necessary.
---------
Signed-off-by: Skye Elliot <actuallyori@gmail.com>
Deduplicates common code that would be shared between
SendRawMessageLikeEvent and SendRawStateEvent to a helper method,
`ensure_room_encryption_ready`.
Signed-off-by: Skye Elliot <actuallyori@gmail.com>
This fixes a small issue encountered while developing the integration test for encrypted state events. If the first sync response received from the server after enabling encryption does not contain the m.room.encryption event, the client will report the encryption state as unknown, even if the next sync response does contain the event.
- [x] Modify Room::enable_encryption_inner to spin on the room encryption state, rather than bailing after the first sync response is received.
Signed-off-by: Skye Elliot
Remove previous code that got updates in `RoomEventCacheState::post_process_new_events`.
Add new task in `EventCache` that subscribes to `linked_chunk_update_sender` and forwards new events to `client::search::SearchIndex` same as before.
Signed-off-by: Shrey Patel shreyp@element.io
The `ruma-common` crate is reexported by `ruma`, which is in our
dependency tree anyways. This change makes it so that qrcode, the only
crate that was making use of `ruma-common`, now depends on `ruma`. It
may move it further down the line in the compilation pipeline, but this
is unlikely to affect compile times in a crazy way. The benefit is that
this avoids the burden of having to specify the ruma commit hash twice
in the top-level Cargo.toml, as well as replacing it twice when
overriding it.
Instead of creating a fresh client every single time, this creates a
single client with a single event cache store, that's cleared between
runs of the benchmark.
So the tradeoff is:
- we don't have to create a new client anymore, which means no more
async setup code, which means we can avoid using `iter_custom`; a
benefit of this is that this can be benchmarked on CI now.
- but we're also measuring the time it takes to clear the database,
which isn't trivial in itself.
The task would stop when the receiver is closed; for the receiver to be
closed, the sender ought to be closed too.
Because the sender lives in `EventCacheInner`, and the task would hold
onto an `EventCacheInner` struct, the sender would never be dropped, so
the full `EventCacheInner` would leak, as a result.
Changes `Room::enable_encryption_with_state` to
`Room::enable_encryption_with_encrypted_state_events`, and updates the
respective unit test and testing utilities.
Signed-off-by: Skye Elliot <actuallyori@gmail.com>
This patch moves the `test_update_ignores_none_value`
test in a new (correct) test module, and creates the new
`test_local_has_priority_over_remote` test.
This patch changes the order in which the `LatestEventValue` is removed
from the buffer and re-created in case of a `SentEvent`. Previously,
the value from the buffer was removed before re-creating one, now it's
the opposite.
Why this order? Because once the local event is sent, it's not yet
received by the sync and consequently not stored in the event cache. So
once the local event is sent, it won't show up as a `LatestEventValue`
as it will immediately be replaced by an event from the event cache. By
computing the new value before removing it from the buffer, we ensure
the `LatestEventValue` represents the just sent local event.
See the comment in the code to learn more.
This patch renames `LocalIsWedged` to `LocalCannotBeSent` to avoid
confusion with the wedged/unwedged state of the `send_queue`. The
semantics is different in `latest_events`.
This patch handles the case where a local event is replaced by another
local event which isn't suitable for being a latest event value. In this
case, the previous existing latest event value should be removed from
the buffer.
This patch reduces the level of logs when channels have been closed in
`LatestEvents`' tasks from `error` to `warn`. Indeed, when the `Client`
shutdowns, the channels will be closed, but it's not an error at all.
This patch implements `LatestEvent::update_with_send_queue`.
It introduces an intermediate type, for the sake of clarity,
`LatestEventValuesForLocalEvents`.
The difficulty here is to keep a buffer of `LatestEventValue`s requested
by the `SendQueue`. Why? Because we want the latest event value, but we
only receive `RoomSendQueueUpdate`s, we can't iterate over local events
in the `SendQueue` like we do for the `EventCache` to re-compute the
latest event if a local event has been cancelled or updated.
A particular care must also be applied when a local event is wedged:
this local event and all its followings must be marked as wedged too,
so that the `LatestEventValue` is `LocalIsWedged`. Same when the local
event is unwedged.
This patch splits the `LatestEventValue` type into `LatestEventValue`
+ `LatestEventKind`. Basically, all variants in `LatestEventValue` are
moved inside the new `LatestEventKind` enum. `LatestEventValue` keeps
`None`, and see the new `Remote`, `LocalIsSending` and `LocalIsWedged`
variants.
This patch also extracts the message-like handling of `find_and_map`
(now renamed `find_and_map_timeline_event`) into its own function:
`find_and_map_any_message_like_event_content`. This is going to be
handful for the send queue part.
This patch updates `compute_latest_events` to broadcast a
`RoomSendQueueUpdate` onto `LatestEvent`. It introduces the new
`update_with_send_queue` method.
This patch renames the `update` methods to `update_with_event_cache`
in the `latest_events` module. It frees the road to introduce
`update_with_send_queue`.
This patch updates `LatestEvents` to listen to the updates from the
`SendQueue`. The `listen_to_event_cache_and_send_queue_updates` function
contains the important change. A new `LatestEventQueueUpdate` enum is
added to represent either an update from the event cache, or from the
send queue.
So far, `compute_latest_events` does nothing in particular, apart from
panicking with a `todo!()` when a send queue update is met.
Allows `Backups::maybe_download_room_key` to accept any T:
JsonCastable<EncryptedEvent>, which will be required for state events to
trigger fetching the room key.
Implements JsonCastable<EncryptedEvent> for
OriginalSyncStateRoomEncryptedEventContent.
Implements JsonCastable<AnyStateEvent> for RoomEncryptedEventContent.
Modifies `OlmMachine::decrypt_room_event_inner` to call a new method
`OlmMachine::verify_packed_state_key` which, if the event is a state
event, verifies that the original event's state key, when unpacked,
matches the state key and event type in the decrypted event content.
Introduces MegolmError::StateKeyVerificationFailed and
UnableToDecryptReason::StateKeyVerificationFailed which are thrown when
the verification fails.
Signed-off-by: Skye Elliot <actuallyori@gmail.com>
This commit also refactors out what would be common code between
::encrypt and ::encrypt_state to a helper ::encrypt_inner.
Signed-off-by: Skye Elliot <actuallyori@gmail.com>
Integrate matrix-sdk-search into matrix-sdk.
When a room is joined, a corresponding index is created.
When a message is received via sync or via a back-pagination, it is
added to the corresponding room's index.
Signed-off-by: Shrey Patel shreyp@element.io
This PR makes some non-domain-specific changes across multiple crates
that are required for proper testing of features implemented for #5397.
* Adds a `experimental-encrypted-state-events` feature flag across the
SDK.
* Introduces a feature set into xtask to ensure feature-gated tests are
run during CI.
* Minor fix to a test that would otherwise fail with the newly
introduced CI.
The semantics of this variant are unclear: sometimes a timeline could be
cleared, which would result in a `UpdateTimeline` (and if we looked at
the vector diffs, it would include a `Clear`), but in this case the
`Clear` variant would not be emitted.
It was only emitted in a few adhoc spots, but it was missing the whole
picture. Also, the current observer was only interested in getting *a*
room update with the room id, and didn't react particularly to clears.
So, there's apparently little reason in having this variant, and as a
result we should get rid of it.
Introduces a new `SyncToken` enum for the `SyncSettings::token` field.
The enum has 3 variants: ReusePrevious (default), NoToken, Specific(String).
Some tests were changed to use the old default (NoToken).
Handle the changes to the Response of the get_profile endpoint. The
content of the response is private and fields must be accessed with
methods.
Signed-off-by: Kévin Commaille <zecakeh@tedomum.fr>
Handle the previous breaking change that was reverted: `StrippedState`
was removed and `AnyStrippedStateEvent` is used again.
Signed-off-by: Kévin Commaille <zecakeh@tedomum.fr>
- [x] Change `DecryptedRoomEvent::event` to `Raw<AnyTimelineEvent>`
- [x] Update usages to pattern match on `AnyTimelineEvent::MessageLike`
where necessary
---------
Signed-off-by: kaylendog <actuallyori@gmail.com>
This patch updates the Timeline Controller's `handle_explicit_read_receipts` method to also consider unthreaded read receipts on **threaded** **main** timelines when calculating timeline items states and adds a test for it.
This picks up from #5442 and fixes https://github.com/matrix-org/matrix-rust-sdk/issues/5440
Add a new `server_vendor_info` method on the `matrix-sdk` `Client` that calls the `/_matrix/federation/v1/version` endpoint to retrieve the server's software name and version information.
Also add it to the bindings + log it when initializing the logs.
This can happen because of an OS-level error, so let's try to handle it
in a slightly cleaner way. At the moment, it will bubble up and only be
logged, but we might try to find a better way to handle this at the
top-level.
The `timeout` setting on the `/sync` endpoint is the maximum allowed
time for the server to send its response, because this is a poll-based
API. It means that if there is no new data to show, the server will wait
until the end of `timeout` before returning a response.
It can be an undesirable behavior when starting a client and informing
the user that we are "catching up" while waiting for the first response.
By not setting a `timeout` on the first request to `/sync`, the
homeserver should reply immediately, whether the response is empty or
not.
---------
Signed-off-by: Kévin Commaille <zecakeh@tedomum.fr>
Signed-off-by: Ivan Enderlin <ivan@mnt.io>
Co-authored-by: Ivan Enderlin <ivan@mnt.io>
It is supposed to be an improvement over `state`, since it allows the
server to send updates to the state that might not be reflected in the
timeline.
This is also the same behavior as in Simplified Sliding Sync.
This is MSC4222 that was accepted and is about to get merged in the
spec.
---------
Signed-off-by: Kévin Commaille <zecakeh@tedomum.fr>
This brings 2 important bug fixes:
- Make deprecated fields of `m.room.encrypted` optional: it seems that there are events without these fields in the wild.
- Fix deserialization of `RedactedRoomJoinRulesEventContent`. This was found by a bug report in Fractal that caused the same error as #3557 when restoring the client. So maybe we could consider that this bug is fixed? It is still possible that there is another deserialization error.
There is also a breaking change in the format of the `state` field in response to `GET /v3/sync`.
This is a breaking change as spaces are now requested through sliding sync and they need to manually be excluded from the room list by using the newly introduced non-space filter.
We use `cargo ndk -p {package_name}`, where `-p` is short for
`--package`. However, `cargo ndk` has introduced the `-p` option (see
https://github.com/bbqsrc/cargo-ndk/commit/c6b93a89a2723ff0fac99b5ac86ae6636a6cf54a),
short for `--platform`. It creates a confusion and the command line
doesn't execute properly. Let's use the long option `--package` to
clarify everything.
The `m.room.create` event contains at lot of important information for a
room, like its type (i.e. whether it is a space), its version and its
creator(s) (which are important in room version 12). So ignoring the
event completely might break a room.
Instead what we do here is simply ignore the `predecessor` field if it
is considered invalid, allowing us to access the other fields.
Signed-off-by: Kévin Commaille <zecakeh@tedomum.fr>
Fixes the encrypting part of
https://github.com/matrix-org/matrix-rust-sdk/issues/4147
Probably easiest to review commit-by-commit
<!-- description of the changes in this PR -->
- [x] Public API changes documented in changelogs (optional)
<!-- Sign-off, if not part of the commits -->
<!-- See CONTRIBUTING.md if you don't know what this is -->
Signed-off-by:
This brings in a new breaking change from Ruma, because not all events
are stripped in a room's stripped state. For simplicity, this still
considers the events as stripped during deserialization for now, since
this format is compatible with the other possible formats.
Signed-off-by: Kévin Commaille <zecakeh@tedomum.fr>
These tests now fully mock all the end-to-end encryption server
endpoints to test the redecryption and UTD item replacement logic of the
timeline without any manual room key insertions.
We test that the item replacement correctly handles supported event
types as well as unsupported ones.
Instead of having one static method duplicating an underlying
`ClientBuilder` method, we can pass the builder directly to a closure,
that will replace it. Call sites are a bit more verbose, but that would
avoid having to add duplicate `MockClientBuilder` methods for each
`ClientBuilder` method.
As noted in the changelog entry, the event type they send is outdated, and Client is not actually supposed to be able to join MatrixRTC sessions at this time. A MatrixRTC client implementation which actually participates in sessions should be able to send these notifications without the SDK's help.
For clients which integrate Element Call: Currently matrix-rust-sdk is responsible for sending the call notification event when joining MatrixRTC sessions, but this is planned to be changed soon. As of the upcoming Element Call 0.14.0 release, it will request the capability to send call notifications itself, and we should auto-approve this capability.
Client::get_url is there for SDK consumers to be able to use the
existing HTTP stack (configuration and all) however in practice it was a
bit weird:
- Responses came back as strings limiting the types of resource that
could be fetched (as well as requiring the string to be converted back
to data before handed to a JSON decoder).
- HTTP errors weren't being raised and instead you would find the (e.g.
404) error response in the Ok case.
This patch fixes both of these issues.
This patch updates our `Raw` API usage since the newly added `JsonCastable` that disallows Raw casts that are known to fail deserialization.
Signed-off-by: Kévin Commaille <zecakeh@tedomum.fr>
This patch changes the query used by
`SqliteEventCacheStore::load_all_chunks_metadata`. It was the cause of
severe slowness. The new query improves the throughput by +1140% and the
time by -91.916%. The benchmark will follow in the next patch.
Metrics for 10'000 events (with 1 gap every 80 events).
- Before:
- throughput: 20.686 Kelem/s,
- time: 483.43 ms.
- After:
- throughput: 253.52 Kelem/s,
- time: 39.478 ms.
This query will visit all chunks of a linked chunk with ID
`hashed_linked_chunk_id`. For each chunk, it collects its ID
(`ChunkIdentifier`), previous chunk, next chunk, and number of
events (`num_events`). If it's a gap, `num_events` is equal to 0,
otherwise it counts the number of events in `event_chunks` where
`event_chunks.chunk_id = linked_chunks.id`.
Why not using a `(LEFT) JOIN` + `COUNT`? Because for gaps, the entire
`event_chunks` will be traversed every time. It's extremely inefficient.
To speed that up, we could use an `INDEX` but it will consume more
storage space. Finally, traversing an `INDEX` boils down to traverse a
B-tree, which is O(log n), whilst this `CASE` approach is O(1). This
solution is nice trade-off and offers great performance.
It uses the statically-known type from the `StaticEventContent`
implementation to call `fetch_account_data()`.
This is the equivalent of `Account::account_data()` but for fetching
from the server. It avoids the need to cast to the proper type after.
Signed-off-by: Kévin Commaille <zecakeh@tedomum.fr>
Currently Element X can't distinguish the cases where a homeserver only
supports legacy SSO without OIDC (and password login isn't avaliable),
and other server unreachable scenarios.
This patch exposes legacy SSO support infomation so that Element X side
can give a dedicated error message when it encounters a homeserver that
can only support legacy SSO.
Signed-off-by: Yorusaka Miyabi <23130178+ShadowRZ@users.noreply.github.com>
Historic room key bundles are uploaded as an encrypted file to the media
repo and the key to decrypt the file is sent as a to-device message to
the recipient device.
In the nominal case, the invite and this to-device message should arrive
at the same time and accepting the invite would download and import the
bundle.
If the to-device message arrives after the invite has already been
accepted we would never download and import the bundle.
To mitigate this problem, this patch introduces a task that listens for
bundles that arrive. If the bundle is for a room that we have joined we
will consider importing the bundle.
It is going away in MSC4291, which should be accepted next week.
Removing it now makes sure that no one uses it.
Signed-off-by: Kévin Commaille <zecakeh@tedomum.fr>
For custom integrations it might be necessary to allow the SDK to
request additional scopes for the OAuth2 authorization code flow.
Currently, only the MSC2967 client API and client device scopes are
requested statically.
Signed-off-by: fl0lli <github@fl0lli.de>
This patch removes the use of `OrderTracker` because the
implementation of `EventCacheStore::load_all_chunks_metadata` for
`SqliteEventCacheStore` is the cause of severe slownesses (up to 100s
for some account).
We are going to undo this patch once the problem has been solved.
Avoids to carry around the event content only to convert it when we
want to use it. Avoids also to carry around the room creator when we
might not need it.
Signed-off-by: Kévin Commaille <zecakeh@tedomum.fr>
This patch adds `timer!` logs in each method from `EventCacheStore` for
`SqliteEventCacheStore`. It will help to know the execution duration of
each of these methods.
This patch renames `TracingTiming::new_debug` to `new`. The
documentation claims it sets the log level to `debug` while the `level`
is actually an argument of the constructor. It's then wrong, and the
constructor must be renamed.
This changes the `TracingTimer` message to use the `Debug` impl of
`Duration` instead of displaying it as milliseconds. It can help spotting
seconds without counting all the digits.
Until now, `SqliteEventCacheStore` manages a pool of connections. A
connection is fetched from this pool and operations are executed on it,
regardless whether these are read operations or write operations.
We are seeing more and more _database is busy_ errors. We believe this
is because too many write operations are executed concurrently.
The solution to solve this is to use multiple connections for read
operations, and a single connection for write operations. That way,
concurrent writings are no longer a thing, and we hope it will reduce
the number of _database is busy_ errors to zero. That's our guess.
This patch does that. When the pool of connections is created, a
connection is elected as the `write_connection`. To get a connection for
read operations, one has to use the new `SqliteEventCacheStore::read`
method (it replaces the `acquire` method). To get a connection for
write operations, one has to use the new `SQliteEventCacheStore::write`
method. It returns a `OwnedMutexGuard` from an async `Mutex`. All
callers that want to do write operations on this store have to wait
their turn, this `Mutex` is fair, and the first to wait on the lock is
the first that will take the lock (FIFO). It guarantees the execution
ordering the code expects.
The rest of the patch updates all spots where `acquire` was used and
replaces them by `read()` or `write()`. A particular care was made to
see if other places are using `SqliteEventCacheStore::pool` directly. No
place remains except in `read()` and `write()`.
This patch updates `SqliteStoreConfig::pool_size` to be at least 2. We
need 2 connections: one for write operations, one for read operations.
This behaviour is coming in the next patches.
This patch adds more logs inside `EventCache` around the
`multiple_room_updates_lock` and around the `listen_task`, just to be
sure if everything is listened and works as expected.
The SQLite implementation for the
EventCache::find_event_with_relations() the relation type list isn't
inserted using SQL placeholders.
The relation types are inserted manually using a format!() call. The
usage of the format!() call can lead to SQL injection if a
RelationType::Custom variant is used which contains SQL expressions.
This patch modifies the, query logic which retrieves the related events,
to use two separate queries which use SQL placeholders to insert all
the dynamic variables.
Security-Impact: Moderate
CVE: CVE-2025-53549
GitHub-Advisory: GHSA-275g-g844-73jh
This patch adds the new `RoomListService::new_with_share_pos`
constructor. It decides whether the `share_pos` feature of sliding sync
should be enabled or not.
`SyncServiceBuilder` gains a new `with_share_pos` method to configure
the way the `RoomListService` is built.
The FFI bindings are updated accordingly.
This patch updates the `assert_update` macro in the send queue test
suites to test that `SendQueue::subscribe` provides the same data that
`RoomSendQueue::subscribe`. It ensures `SendQueueUpdate` won't miss
an update.
To get updates from the `SendQueue`, one needs to use
`RoomSendQueue::subscribe`, it emits `RoomSendQueueUpdate`s. However, if
one wants to receive updates for all rooms managed by the `SendQueue`,
instead of subscribing to all `RoomSendQueue` individually, this
patch introduces a new `SendQueue::subscribe` method, which emits
`SendQueueUpdate`s. It's basically a wrapper around
`RoomSendQueueUpdate` by adding an `OwnedRoomId`.
This patch renames variants of `RoomEventCacheGenericUpdate`:
- `TimelineUpdated` becomes `UpdateTimeline`,
- `Cleared` becomes `Clear`.
It matches the rest of the codebase where we use _verb_ + _subject_.
This reorders methods so that they're grouped in "dual" pairs
(encode/decode, serialize/deserialize). Also adds a doc comment to
`encode_key`, as I've wondered in the past what it did.
This patch updates `RoomListService::subscribe_to_rooms` to call
`LatestEvents::listen_to_room` automatically. This method becomes async,
which propagates to a couple of callers.
The idea is that when one is interested by a specific room, a
subscription will be applied. This is an opportunity to also “activate”
the computation of the `LatestEvent` for this specific room, so that the
user doesn't have to do that manually (except if room subscription is
never used).
This patch adds a new log field, named `request_duration` in
`HttpClient::send_request`. It helps to know how much time the request
took to be executed.
This is a bugfix for the `compat-lax-room-create-deser` and
`compat-lax-room-topic-deser` features, which didn't work with events
in the wild.
Signed-off-by: Kévin Commaille <zecakeh@tedomum.fr>
This patch removes an optimisation that was considering
`LatestEventValue::None` as a value that should no overwrite the
previous value if any. This is a mistake: if the event cache is cleared,
it won't be possible to calculate a new value, and the previous value
must be overwritten.
This patch adds new variants to `LatestEventValue` that represent
all the possible suitable latest events. It's heavily inspired by
`matrix_sdk_base::latest_event::PossibleLatestEvent`. It uses the
new `find_and_map` method to find a suitable `TimelineEvent` and to
map it into a `LatestEventValue`. This method is heavily inspired by
`matrix_sdk_base::latest_value::is_suitable_for_latest_event`.
To be able to provide the `power_levels` to `find_and_map`, a
`WeakClient` is required by `LatestEvents::new`. It flows up to a
`WeakRoom` in `RoomLatestEvents`, used to create or to update the
`LatestEventValue`.
A particular care is applied to re-compute the `power_levels` only when
necessary and once **per room** (and not per latest event value).
Fetching the `power_levels` requires an access to the storage, it's
not anodyne.
This is more precise than using the event timeline item kind: indeed,
when the event for which we want to add a reaction is a local echo that
has been sent, it is still marked as a local echo, but the send queue
will not know about it, and thus will not be able to add the reaction
immediately, leading to a silent failure.
The `TimelineItemHandle` was made to help with this kind of situation:
in this case, it will return `TimelineItemHandle::Remote`, even though
the item is a local echo that has been sent; that way we can use the
event id, and correctly send a (remote) reaciton event immediately.
The following commit includes a regression test.
Using this type will be mandatory in the next breaking release of Ruma,
that will gain support for recognizing unstable features. Besides, it
allows to cache the supported versions and features in a single
CachedValue, which makes more sense than separately because we always
get both at the same time in production.
Signed-off-by: Kévin Commaille <zecakeh@tedomum.fr>
This patch fixes the markup in the `README.md` file. Links were broken because of the mix of HTML and Markdown. Plus, the HTML markup was kind of incorrect. Plus, too much `<br />`, most of them were “collapsed” automatically.
Signed-off-by: Ivan Enderlin <ivan@mnt.io>
Usually tests that don't construct it via MockMatrixServer don't care
about the homeserver URL, so this allows to provide a default URL for
them.
Also we don't force to allocate a string when the inner API actually
uses a borrowed string.
Signed-off-by: Kévin Commaille <zecakeh@tedomum.fr>
It seems that some `m.room.topic` events in the wild have the wrong
format for the `m.topic` field. Since this field was stabilized recently
in Ruma, deserializing these events now fails. We added a feature to
ignore this field if its deserialization fails.
Signed-off-by: Kévin Commaille <zecakeh@tedomum.fr>
The `EventContent` trait is gone in Ruma so this will ease the upgrade
to the next breaking release.
Signed-off-by: Kévin Commaille <zecakeh@tedomum.fr>
With the UI crate now sending threaded read receipts we need to start considering them when computing unread counts. As a first step before the participation model, threaded messages will be ignored when computing room unread counts.
This patch moves away from always sending unthreaded read receipts to checking the timeline's focus and `hide_threaded_events` associated values to see whether `ReceiptThread::Main` or `ReceiptThread::Thread` should be used.
It doesn't make sense to name a thing "Matrix" when it comes from the
core SDK crate.
Also adjust a now slightly-incorrect doc comment for `get_notification`.
These are not included in Element's main privacy policy, and may
constitute PII (because the homeserver may include the name of some
user). We keep the information as separate log lines, so that
rageshakes/manual reports still include those.
The metadata loading shouldn't cause an error to be displayed, when the
linked chunk is empty; this can happen for new rooms we've never
visited.
Spotted while investigating some failures in a rageshake.
This patch introduces a new method named
`RoomEventCache::rfind_event_in_memory_by` to look for an in-memory
event, starting from the most recent event, by applying a predicate
closure on each event.
This patch renames the `RoomEventCache::event_with_relations` method to
`find_event_with_relations` for the sake of clarity, also to match the
other method names, and to match the Rust standard library namings.
The swift bindings aren't getting tested (they don't run) in CI anymore,
so building with the reldbg profile (that's a workaround to make it run
and not crash in production) doesn't provide more value than building in
debug mode, while taking much longer to build.
Let's use the default dev profile for this; we have to specify it
manually, because the default for the xtask command is to use the
`reldbg` profile otherwise.
This requires a fix for the dev profile, that consists in being able to
set the iOS deployment target, and set it to a high value in CI
settings. Production builds *don't* have to set it, though.
These two methods could be only made private now, since they're only
used in `finish_back_pagination` (and in tests). But they only call
inside other methods of the underlying linked chunk without any extra
value, so they can be inlined instead. This reduces the public API and
removes tests for other APIs that were tested some place else.
This patch fixes `EventCache::for_room` to return an error when the room
isn't found. Additionally, it also returns an error when the `Client`
(actually the `WeakClient`) is dropped.
These errors were “hidden” behind the room version logic because of
the fallback. The code has been rewritten in a way it makes it harder to
do it again.
This patch is the first part of the new `LatestEvents` API. It contains
the “framework”, i.e. the structure, tasks, logic to make it work, but
no latest events are computed for the moment.
The Latest Events API provides a lazy, reactive and efficient way to
compute the latest event for a room or a thread.
The latest event represents the last displayable and relevant event
a room or a thread has been received. It is usually displayed in a
_summary_, e.g. below the room title in a room list.
The entry point is `LatestEvents`. It is preferable to get a reference
to it from `Client::latest_events`, which already plugs everything to
build it. `LatestEvents` is using the `EventCache` and the `SendQueue`
to respectively get known remote events (i.e. synced from the server),
or local events (i.e. ones being sent).
\## Laziness
`LatestEvents` is lazy, it means that, despites `LatestEvents`
is listening to all `EventCache` or `SendQueue` updates, it will
only do something if one is expected to get the latest event for a
particular room or a particular thread. Concretely, it means that until
`LatestEvents::listen_to_room` is called for a particular room, no
latest event will ever be computed for that room (and similarly with
`LatestEvents::listen_to_thread`).
If one is no longer interested to get the latest event for a
particular room or thread, the `LatestEvents::forget_room` and
`LatestEvents::forget_thread` methods must be used.
\## Reactive
`LatestEvents` is designed to be reactive. Use
`LatestEvents::listen_and_subscribe_to_room` (same for thread) to get
a `Subscriber`.
This patch moves the `JoinHandleExt` trait and the
`AbortOnDrop` type from `matrix_sdk::sliding_sync::utils` into
`matrix_sdk_common::executor`. This is going to be useful for other
modules.
This patch updates `test_sync_indicator` since the `SyncIndicator`
is shown for the `SettingUp` state. Also, this patch makes this
test non-flaky entirely by changing the `sync::mpsc::channel` to a
`sync::Barrier`.
Since `RoomListService` uses a persistent `pos` for sliding sync, the
`SyncIndicator` no longer shows its face except if the sliding sync
session doesn't exist or has expired.
This patch changes that by extending the `Show` from `Init` to
`SettingUp`.
When we upgrade Ruma, the `EventContent` bound on `EventBuilder` will be
changed to `StaticEventContent`, which is not implemented by the
`Any*EventContent` enums.
Signed-off-by: Kévin Commaille <zecakeh@tedomum.fr>
One must now specify the target linked chunk; both callers would filter
out items based on this after the fact, which is a bit overkill since
most items would thus be filtered out on the sinking end.
The one hardship is that lazy-loading updates must NOT affect the order
tracker, otherwise its internal state will be incorrect (disynchronized
from the store) and thus return incorrect values upon shrink/lazy-load.
In this specific case, some updates must be ignored, the same way we do
it for the store using `let _ = store_updates().take()` in a few places.
The author considered that a right place where to flush the pending
updates was at the same time we flushed the updates-as-vector-diffs,
since they would be observable at the same time.
This is a new data structure that will help figuring out a local,
absolute ordering for events in the current linked chunk. It's designed
to work even if the linked chunk is being lazily loaded, and it provides
a few high-level primitives that make it possible to work nicely with
the event cache.
In the next patch, we're going to introduce another user of
`UpdatesToVectorDiff` which doesn't require accumulating the
`VectorDiff` updates; so as to make it optional, let's generalize the
algorithm with a trait, that carries the same semantics.
No changes in functionality.
It doesn't belong there anymore, because it's not used within the event
cache itself. It's used in the timeline, and I think it's nice to keep
it available for external users as well, so it now lives in its own
`matrix-sdk/src/paginators` module. Next step is to move the thread
loader in there as well.
It avoids using different versions in several places for consistency. It
also allows to be able to change it in a single place when needed.
This also bumps the fallback to v11 everywhere, since it is the default
version for new rooms since Matrix 1.14 and it has the sanest redaction
rules.
Signed-off-by: Kévin Commaille <zecakeh@tedomum.fr>
Process:
- set style_edition to 2024 in .rustfmt.toml
- run `cargo fmt`
- undo .rustfmt.toml change
- run `cargo fmt` again
- manually rewrap some strings
The `/auth_metadata` endpoint has been supported by Synapse for 6 months
now so there shouldn't be any homeserver that still depend exclusively
on it. This endpoint is also part of Matrix 1.15.
Support for this endpoint has been removed from Ruma so this is
necessary before an upgrade of the dependency.
Signed-off-by: Kévin Commaille <zecakeh@tedomum.fr>
It turns out that downstream clients can and do call
`Client::join_room_by_id()` rather than `Room::join`, so we need to do
the room key history import in the lower-level method.
---------
Signed-off-by: Richard van der Hoff <1389908+richvdh@users.noreply.github.com>
Co-authored-by: Benjamin Bouvier <benjamin@bouvier.cc>
The previous code would parse the entire bundled event, only to look at
its type indirectly. We can do better than this, and only look at the
type instead. This brings a few benefits:
- it is faster, as we don't have to deserialize the entire event
- while the spec seems to indicate that the latest thread event has a
`room_id`, it seems that, under some circumstances, it does not, as
indicated by some rageshakes. As such, not parsing as `AnyMessageLike`
(which mandates a room id) makes it more robust to the absence of a
room id in there, marking more events as latest events.
The latest mobile designs for Element Call have it displaying the room name in an "app bar". So the Element Call widget will soon start requesting the capability to learn the room name, and the SDK should auto-approve this capability.
This prevents us from having to add type constraints on the dynamic type
and instead only having to specify the type constraint at the call site.
Signed-off-by: Michael Goldenberg <m@mgoldenberg.net>
This can be used to invalidate the persisted state on disk related to
the sliding sync positions. It's useful to do so when clearing up all
the caches, since the sliding sync `pos`itions are stored in the crypto
store (to benefit from the cross-process lock).
The join rule state event can be missing from a room state. In this
case, it's an API footgun to return a default value; instead, we should
return none and let the caller decide what to do with missing
information.
`RoomEventCache::subscribe` is nice to subscribe to every update
happening inside a room in the event cache. However, the returned
`RoomEventCacheSubscriber` has side-effects when dropped (see
auto-shrink to save memory space). In some situation, this is pretty
annoying. for example, if one wants to listen to multiple room updates,
all the room event cache subscribers must be kept in memory, thus
breaking the side-effects. This isn't always the desired output. In
addition, listening to multiple channels/subscribers at the same is
quite complex, as it implies non-trivial async runtime efforts or
complex future types.
To solve this problem, this patch introduces a new
`EventCache::subscribe_to_room_generic_updates` method, which returns a
single `Receiver<RoomEventCacheGenericUpdate>`.
First off, it hides the details of `RoomEventCacheUpdate` (returned by
`RoomEventCacheSubscriber`), which might be desired, but particularly
lighter because events aren't part of the payload.
Second, one no longer needs to subscribe to all rooms. Only one channel
can be listened to get updates for all rooms. It reduces the complexity
on the caller side, plus `Receiver<RoomEventCacheGenericUpdate>` doesn't
have any side-effect.
This patch tests this feature in 4 situations:
1. when a room is created/loaded empty,
2. when a room is loaded and is not empty because data exists in the storage,
3. when a room receives data from the sync,
4. when a room receives data from the pagination.
<!-- description of the changes in this PR -->
Features to configure UserAgent, Proxy, Disabling SSL, and additional
certificates are not available on Wasm platforms. We remove these
configuration options from the FFI layer, while preserving them on
non-Wasm platforms.
- [ ] Public API changes documented in changelogs (optional)
<!-- Sign-off, if not part of the commits -->
<!-- See CONTRIBUTING.md if you don't know what this is -->
Signed-off-by: Daniel Salinas
---------
Co-authored-by: Daniel Salinas <danielsalinas@Daniels-MacBook-Pro-2.local>
Previously, we held a TrustRequirement inside Client, and had to wrap it
in a DecryptionSettings manually a couple of times.
It feels more right to hold on to a DecryptionSettings directly. If
there were ever some additional settings, most likely we would need them
all here.
If I haven't screwed it up, this should not affect behaviour in any way.
The pagination status was only mapped onto the "global" state, that is, the state of the event cache pagination.
Now, consider the following case, where two timeline instances are live:
- the first one could have backpaginated all the items back to the start of the room
- the second one is created later. Because of the initial value for the skip count, it will only return a subset of event items (~20).
However, listening to the pagination status for the second timeline would incorrectly state that the timeline was entirely paginated (because it returned the "global" pagination status). As such, an observer might think that there are no more items in the timeline, while a subsequent pagination would adjust the skip count and return more items.
This fixes it by combining the global pagination state with the local timeline state (aka the skip count value). If the skip count is positive (meaning, we could set it to 0 later and thus returning more events), we pretend we haven't reached the start of the timeline. This way, an observer can call pagination later, which may adjust the skip count and "return" more items.
`RoomPowerLevels` already holds an inner version of the power levels and has access to everything needed to compute the user to level map.
This way the async fetching only happens once and the mapping only on request.
Currently, clients have to make async requests to `Room::get_power_levels` from multiple places throughout the app in order to correctly configure the various UI components and again, on randomly decided events, to keep them up to date.
This patch starts publishing the power levels directly on the `RoomInfo` and allows them to be handled (and updated!) through the normal `subscribe_to_room_info_updates` mechanism.
This patch removes a name ambiguity around _listener_ vs. _subscriber_.
Both terms are used to talk about `RoomEventCacheListener`. We usually
use the term _subscriber_ for the type being returned by a `subscribe`
method. The code refers to this sometimes as listener, sometimes
as subscriber, sometimes both in the same sentence, which can be very
confusing! This patch solves this by using the _subscriber_ term only.
They are only semantically different if a macro of the same name exists,
in which case the foo::{self} import only imports foo-the-module, not
foo-the-macro.
We have a working implementation of the additional forms of QR Code login
of MSC4108. This commit moves the existing code into its own file
to make future updates easier to follow.
Remove the MediaFileHandle concept from the matrix-sdk-ffi crate on Wasm
platforms. File handles are not supported in the browser.
Signed-off-by: Daniel Salinas
The uniffi tool for generating JS/Wasm bindings utilizes rust as its
intermediate language.
As a result, the 'target' uniffi annotated library needs to be marked as
a 'lib' so that the generated rust code can utilize it to generate the
Wasm create + typescript bindings.
Signed-off-by: Daniel Salinas
This patch expands on the already existent `RoomPowerLevels` record (which it renames to `RoomPowerLevelsValues` to work around uniffi not exposing public fields) and nests them inside a new exported object that also provides methods for retrieving the actions that an user can take, methods moved from the room object.
This reduces the amount of async calls the clients need to make, simplifies the API and groups the code better together.
The system of platform targets was already quite messy, and becoming
even worse as we start preparing for Wasm support. Switch to features
instead to make this easier to work with.
UInt::MAX.try_into().unwrap() was causing errors on Wasm platforms, due
to the result being unrepresentable.
This `unwrap_or` was also always being calculated regardless, so I think
using `usize::MAX` is preferable on all platforms.
Signed-off-by: Daniel Salinas <zzorba@users.noreply.github.com>
Some of these Box<dyn Error + Send + Sync> are okay, but a few are
problematic.
Confirmed this still compiles fine on the fully working wasm tree.
Signed-off-by: Daniel Salinas
The main thing left now are the store traits, unsure how to deal with
those. `dynosaur` + `trait_variant` are kind of the modern replacement
for `async_trait`, but (a) `trait_variant` seemed to generate invalid
code here when I tried it and (b) even with that fixed I think the error
type erasure is going to present some extra problems. Maybe it's fine to
just keep the current solution for the store traits for now.
Signed-off-by: Jonas Platte <jplatte+matrix@posteo.de>
This patch switches from tarpaulin to llvm-cov for our coverage reports.
llvm-cov can use cargo-nextest to run the tests which means that we can
tolerate flaky tests for coverage just like do for the rest of our CI
run.
We can also start using JUnit reports to track flaky tests.
Proper support for receiving to-device messages for widgets.
If the widget is in an e2ee room, clear to-device traffic will be excluded. Also filter out internal to-device messages that widgets should not be aware off.
On this date (heh), the date divider reports include the following
information:
- initial timeline items in a shortened format,
- operations to apply,
- final timeline items in the same shortened format,
- errors
The shortened format includes:
- either, for events: "[event id]: server timestamp"
- or for date divider: "--- date divider timestamp"
As such, they don't include any personal information.
The initial timeline items state and set of operations to apply
constitutes a fully enclosed test case, so it's nice to report it to
Sentry, so we can reuse it almost as is (we'd only need to randomize the
event IDs) and fix it in a subsequent commit.
This patch simplifies the selected read receipt rendering by the fact
that we can simply fetch the selected timeline item instead of the event
ID and then do a search for the selected item.
Co-authored-by: Benjamin Bouvier <benjamin@bouvier.cc>
Signed-off-by: Damir Jelić <poljar@termina.org.uk>
This patch changes the strategy of `check_room_upgrades`.
Instead of checking all state events in `StateChanges` and
throwing an error in case of an invalid state, this patch updates
`state_events::sync::dispatch` to filter out invalid state events
(specifically `m.room.create` and `m.room.tombstone`), and log the
error. That way, the sync doesn't stop and the app can continue working
smoothly.
So `check_room_upgrades` is splited into two functions:
`is_create_event_valid` and `is_tombstone_event_valid`. It's no longer
necessary to detect mergers or splitters because those are _soft
errors_, however loops are still critical errors (hence the fact
the state events aren't stored nor saved nor applied, and that a log
is emitted).
Note: `check_room_upgrades` has been reverted in a previous commit,
that's why it doesn't appear in this diff.
This patch adds optional thread root event id parameters to the drafting functions exposed on the room level
allowing unfinished messages to be managed for the main room as well as any inner thread.
Internally it uses the room id or a tuple of the room id and the thread as keys for the various backing stores.
It doesn't make sense to do it after a back-pagination, since a
back-pagination does require a previous-batch token in the first place,
meaning that if we did paginate, then we did wait for a previous-batch
token beforehand.
Having decrypted an event with a given megolm session, we need to check that
the owner of that session actually matches the sender of an event, otherwise
there is a danger of the sender being spoofed to make it look like it was sent
by another user.
Security-Impact: High
CVE: CVE-2025-48937
GitHub-Advisory: GHSA-x958-rvg6-956w
Internal Sentry reports tell us that enabling the busy_timeout seems to
have *increased* the number of "database is busy" errors, instead of
lowering those. As a result, we're going to disable the pragmas in all
the places where we enabled it before, and observe how the number of
"database is busy" errors evolves.
This correctly handles the reply fallback behavior:
- the behavior isn't changed for a live timeline,
- when a timeline is thread-focused, we will extract the `replied_to`
field if and only if the thread relation is *not* marked as behaving in
a fallback manner.
This makes it possible to distinguish actual in-thread replies.
In a "soon" future, threads have their own linked chunk. All our code
has been written with the fact that a linked chunk belong to *a room* in
mind, so it needs some biggish update. Fortunately, most of the changes
are mechanical, so they should be rather easy to review.
Part of #4869, namely #5122.
This patch renames `check_tombstone` to `check_room_upgrades`.
Then it rewrites it **entirely** to remove all false-positives and
false-negatives. More importantly, the room versions are no longer
involved: they can't be compared or ordered, they must be treated as
opaque values.
This new version of `check_room_upgrades` does a first path to check
predecessor-successor consistency. Then it does a second version to
detect loops. This new algorithm is robust to absent `m.room.create`
events. Making them mandatory is left to another patch.
More tests are added, especially to ensure that `m.room.create` cannot
be overwritten, and to ensure loops or inconsistent predecessors and
successors are correctly detected.
And add getters and setters. It makes it clear who are the external
readers/writers of the push actions, and it makes it impossible to
create a `TimelineEvent` out of thin air (since it now has a private
field).
There's been many segfaults happening in tests, while running the test
coverage for this specific crate. An issue has been opened on
cargo-tarpaulin's repository:
https://github.com/xd009642/tarpaulin/issues/1749
Until this is fixed or worked around, we'll disable coverage testing for
this specific crate.
This module only builds on non-wasm with the patched async-compat from
the workspace Cargo.toml's patch section, and it is only used by the ffi
crate. It is currently breaking the use of the SDK as a git dependency,
and would prevent the publishing of matrix-sdk-common (unless using
--no-verify, but then that would just break all users of the newly
published crates.io version).
This bug was introduced in
https://github.com/matrix-org/matrix-rust-sdk/pull/5089.
Signed-off-by: Jonas Platte <jplatte+matrix@posteo.de>
This helps in the case we want to observe the membership state changes - or some other info - for a room that's still not known so we can't just use `Client::get_room` to fetch it.
Addendum to https://github.com/matrix-org/matrix-rust-sdk/pull/5125 to
allow sending galleries from the FFI crate. This is the final PR for
galleries (apart from possible enhancements to report the upload status
in https://github.com/matrix-org/matrix-rust-sdk/pull/5008).
This is somewhat lengthy again, apologies. Most of the changes are just
wrappers and type mapping, however. So I was hoping that it's relatively
straightforward to review in bulk. Happy to try and elaborate on the
changes or break them up into smaller commits if that helps, however.
---------
Signed-off-by: Johannes Marbach <n0-0ne+github@mailbox.org>
This commit systematically replaces Send+Sync trait bounds throughout
the matrix-rust-sdk codebase to enable Wasm compatibility while
maintaining thread safety on native targets.
Key changes:
- Use SendOutsideWasm/SyncOutsideWasm traits instead of Send/Sync for
trait bounds
- Apply conditional compilation for error types and trait objects
- Update FFI trait definitions to use Wasm-compatible bounds
- Fix event handler and type alias definitions for cross-platform
compatibility
- Maintain existing functionality while enabling WebAssembly target
support
The SendOutsideWasm/SyncOutsideWasm traits are empty on Wasm (allowing
all types) and alias to Send/Sync on native targets, ensuring zero-cost
abstraction.
Files updated:
- All FFI bindings (30+ trait definitions)
- Core SDK error types and type aliases
- Event handler infrastructure
- Store and crypto abstractions
- UI service filters and sorters
- Timeline and authentication modules
<!-- description of the changes in this PR -->
- [ ] Public API changes documented in changelogs (optional)
<!-- Sign-off, if not part of the commits -->
<!-- See CONTRIBUTING.md if you don't know what this is -->
Signed-off-by: Daniel Salinas
---------
Signed-off-by: Daniel Salinas <zzorba@users.noreply.github.com>
Co-authored-by: Daniel Salinas <danielsalinas@Daniels-MacBook-Pro-2.local>
Co-authored-by: Daniel Salinas <danielsalinas@daniels-mbp-2.myfiosgateway.com>
The `ProcessedToDeviceEvent::Decrypted` variant now also have an
`EncryptionInfo` field.
The enum variant changed from `Decrypted(Raw<AnyToDeviceEvent>)` to `Decrypted {
raw: Raw<AnyToDeviceEvent>, encryption_info: EncryptionInfo) }`
Mechanical move from tokio::spawn to matrix_sdk_common::executor::spawn
that has support for Wasm platforms. On non-Wasm, this shim defaults to
tokio::spawn.
The actual code useful in `with_events_mut` and used in that function
was to propagate the changes to the store and propagating diffs to
observers. It often striked me as hacky to use this method to do that,
so instead I'm proposing here to inline the useful bits. That way,
`with_events_mut` is now clearly called only in two cases: after a sync,
or after a successful network back-pagination.
This patch adds the `check_tombstone` response processor to
detect invalid state with room upgrades. One can check the new
`InconsistentTombstonedRooms` error to learn more about the detected
patterns.
If the vec of actions is defined (Some) but empty, then it means we
could determine there are no push actions. It is a slight optimization
to not serialize them, in this case; otherwise, this can result in many
serialized empty action vector, in the event cache's persistent storage.
When the user does an `/invite`, if the target user doesn't start with
an `@`, try expanding it as a user on the local server.
This makes it much easier when repeatedly testing inviting!
Rather than always writing the logs to `/tmp`, write them to the session
directory. The session directory defaults to `/tmp` so by default this
will do the same as before, but if you override the session path on the
commandline, the logs will get stored alongside the stores and caches.
This is particularly useful when running two instances of multiverse,
and you want them to put their logs in different places.
The .boxed() method requires a Send trait that makes it
unusable on Wasm platforms. This re-exports the existing StreamExt,
while providing a new extension for the wasm family of targets.
This is an implementation of an update to MSC2762 (https://github.com/matrix-org/matrix-spec-proposals/pull/4237). It changes the widget driver to split state updates out into an `update_state` action and use the `send_event` action exclusively for forwarding timeline events. Accordingly, `read_events` now always reads from /messages, never the state store.
It's >100 bytes large and often optional, so it makes sense to put it
on the heap to reduce the size of structs with such optional fields,
and the stack size of functions with such optional parameters.
It's also cloned in a couple places in the UI crate, so it probably
makes sense to just always refcount it.
This started as a clippy suggestion to box PendingEdit inside
AggregationKind::Edit.
Part of #3716
I did notice that the `sender` and `member` methods have some overlap in
what values get set for the "sender" and "state key", and I tried to
make sure that in my changes to use `EventFactory` the original event
configuration is being replicated, so please do double-check me on that
note in particular.
Signed-off-by: Yousef Moazzam <yousefmoazzam@hotmail.co.uk>
The test was ignored since the functionality was only implemented for
the memory and SQLite store. This caused a bug in the SQLite
implementation to go unnoticed.
Let's just disable it for WASM since this is the only place where we
didn't yet implement the necessary methods.
The status code is usually returned by Cloudflare to indicate an unknown server error, so we should cancel the upload and let the user retry if they want to.
This patch removes `RoomTombstoneInfo` and replaces it by
`SuccessorRoom`. This patch renames `RoomInfo::tombstone` to
`RoomInfo::success_room`.
This patch also implements `Room::successor_room()` and
`Room::predecessor_room()`, and adds documentation.
This allows applications to decide what they'd like to do if there isn't a value present. It allows the application to decide what the default should be.
This patch adds the new `deduplicate_versions`. This new filter will
filter out room versions that are outdated. Only the “active” versions
are kept.
A room version is considered active if and only if:
* the room is joined and has no successor,
* the room is joined and has a successor room that is invited or knocked,
* the room is left, invited, banned or knocked.
All other rooms are filtered out.
This patch extracts a bit of code from `dispatch` in a new response
processor: `dispatch_room_member`. The idea is to clarify the content of
`dispatch` itself.
This patch moves the insertion of `new_user_ids` in
`updated_members_in_room` after the use of `new_user_ids` by
`update_or_set_if_room_is_newly_encrypted`. By moving it after, it saves
the need to clone it entirely, thus saving memory allocations.
This patch renames `dispatch_and_get_new_users` to `dispatch`. This
response processor no longer returns the new user IDs, but they are
written in a mutable reference argument. This argument is
typed by a new private trait: `NewUsers`. This trait is implemented on
`BTreeSet<OwnedUserId>` and on `()`. It helps to avoid allocations when
the new users are not needed.
This reproduces the issue originally described, where it wasn't possible
to run a /members query in an event handler, because the sync lock was
taken at this point.
This is a dangerous operation, and requires that the sync service must
be stopped while we're touching this. Since this is an internal method,
that shouldn't be used in most clients anyways (as it usually papers
over actual issues happening elsewhere, on the server for instance), I
kept it simple with a scary doc comment explaining the preconditions,
but we could assert them at runtime, with a little bit more effort.
It's just a room, now! Since there were some users of the
`latest_event()` that returned an `EventTimelineItem`, I kept this
method as a method in the Room trait extension that's in the UI crate,
so it's still convenient to use.
This patch updates `Room::leave` to not early return when the server
returns a 403 error code on `/leave`. Indeed, if the user doesn't have
the permissions to leave a room, it's impossible for they to leave it.
Let's consider it's fine to ignore this particular error and continue
the process of leaving the room.
This patch adds the `predecessor` and `no_predecessor` methods on
`EventBuilder<RoomCreateEventContent>`. This is helpful to configure the
`predecessor` field.
This patch fixes `EventFactory::create` where the `m.room.create` wasn't
created as a state-event (the `state_key` field was missing).
Also, it uses the `creator_user_id` in the `sender` field if no sender
was given.
First off, this patch renames `Room::tombstone` to
`Room::tombstone_content` (to be consistent with other methods, such as
`Room::create_content`).
Second, this patch adds the `Room::successor_room` and
`Room::predecessor_room` methods, along with the `SuccessorRoom` and
`PredecessorRoom` types. This naming more or less comes from the Matrix
specification:
- the term _predecessor_ is part of the specification,
- the term _successor_ isn't present _per se_, the words _replacement
room_ are used instead, but I prefer _successor_ as it brings a nice
symmetry with _predecessor_.
The widget Driver should be able to send and receive to-device events.
This is useful for element call encryption keys.
This PR focusses on the widget driver and machine logic. To
send/communicate the events from the widget to the driver.
It skips any encryption logic. Some of the encryption logic will be part
of crypto crate and the code in the widget driver crate should be kept
minimal once the crypto crate is ready.
---------
Co-authored-by: Valere <bill.carson@valrsoft.com>
This behaviour was added only at the `RoomPreview::leave` method, but since we're slowly moving away from it we should move the forget action to the `Room::leave` method instead
On Android, we should use rustls instead of native-tls; this requires
unsetting the default features of the `sentry` crate, and specifying
them by hand instead.
For consistency, I've done the same for the non-android sentry
dependency.
This patch moves the `Room::get_member_hints` method inside the newly
created `display_name` module. That way it is isolated from the rest of
the codebase.
This patch moves the `Room::has_active_room_call` and
`Room::active_room_call_participants` methods into the new `call`
module. This patch also moves the associated tests in this new module.
This patch moves the `Room::*knock*` methods into the new `knock`
module.
The idea is to group API by “theme” to get smaller modules and more
organised code.
This patch moves the `Room::state` method, along with the ``RoomState`
and `RoomStateFilter` types into the new `state` module. This patch also
moves the tests in this new module.
The idea is to group API by “theme” to get smaller modules and more
organised code.
This patch merges the `rooms/normal.rs` file into `rooms/mod.rs`.
The name `normal` is present for historical reasons that no longer stand
today. This is no needed anymore. Let's simplify the modules.
This patch moves everything related to the `Room` latest event API
inside the new `latest_event` module. This patch also moves the tests.
The idea is to get a smaller `rooms::normal` module, and to clarify the
code by grouping `Room` APIs by “theme”.
This patch moves the Room::is_favourite` and `::is_low_priority`, along
with the `RoomNotableTags` into the new `tags` module. This patch also
moves the tests in this new module.
The idea is to group API by “theme” to get smaller modules and more
organised code.
This patch moves the `Room::encryption_state()` and
`Room::encryption_settings()` methods, and the sibling types, into a new
`encryption` module. This patch also moves the tests in this new module.
The idea is to group `Room` API by “theme” in modules, to clarify the
code.
This patch moves the `Room::display_name()` method, and all the
siblings, into a new `display_name` module. It includes types like
`RoomDisplayName`, `UpdatedRoomDisplayName`, `RoomSummary` etc. This
patch also moves the tests in this new module. The idea is to group
`Room` API by “theme” in modules, to clarify the code and to make the
big `rooms::normal` module smaller.
This patch moves the `Room::subscribe_info`, `::clone_info` and
`::set_room_info` methods from the `rooms::normal` module to the
`rooms::room_info` module. This patch also moves the tests related to
room info inside `room_info`.
This patch explains why having `m.room.create` is necessary. It's not
only about the room previews, but also about the room versions, and thus
the tombstoned rooms.
This patch renames the `RoomInfo::version` field to
`data_format_version` to avoid all possible confusion with the
`room_version` (from `m.room.create`).
If the replied-to event is an aggregation, the
`RepliedToEvent::try_from_timeline_event` will now return `Ok(None)`,
and the caller may handle this as they please.
In the FFI layer, this will be filled with an error message indicating
that the event is unsupported.
As per the plan defined in #4718:
```
the room_list_service::room::RoomInner shouldn't make use of its inner timeline;
it's only used in a direct getter, or to compute the latest room event, but it's not working
as intended, since local echoes aren't properly displayed in the room list.
This non-working feature can be removed, in favor of #4112
```
Updates the unread flag or the room in `Timeline::send_single_receipt()`
and `Timeline::send_multiple_receipts()` if the room is marked as unread
and the receipts are unthreaded.
Updates it also in `Timeline::mark_as_read()`, even if there is no
latest event ID.
Signed-off-by: Kévin Commaille <zecakeh@tedomum.fr>
Updates the unread flag or the room in `Room::send_single_receipt()` and
`Room::send_multiple_receipts()` if the room is marked as unread and the
receipts are unthreaded.
Signed-off-by: Kévin Commaille <zecakeh@tedomum.fr>
This makes it possible to handle reactions/redactions/edits/etc. on
non-live timelines. As a result, the pinned and focused timelines will
now get live reactions/redactions and so on. This makes it possible to
also have the thread timelines handle those live events, although it's
unclear how it will pane out in the end, when the event cache is also
involved.
This can be done by splitting the handling of the msgtype/mentions from
the handling of the `relates_to` field, requiring a few API changes here
and there.
We only need the edit_json if we're about to save the edit aggregation.
Likewise, if there's no current event id (i.e. the event being handled
is a local echo), then we don't need to even try to extract anything
from the bundle information.
The poll events's `related_to` field is a `RelationWithoutReplacement`,
while the two others are `Relation<C>`, where `C` is the event content
type (in case it was replacement). As a matter of fact, we try
converting the `Relation<C>` into a `RelationWithoutReplacement` (which
unfortunately requires cloning, which is wasteful if the relation was a
replacement indeed), and then we can use a single function to extract
the reply information and thread root info, for all three.
There are two reasons for this.
Firstly. we've already done a bunch of work to map `SenderData` into a
`VerificationState`, and the decision tree from `VerificationState` to
allow/reject is simpler than going from `SenderData`, even if we have to
fudge it a bit to get the "legacy" flag. (Note that it allows us to get
rid of an `unreachable!` panic.)
Secondly, `VerficationState` represents the state of an *event*, whereas
`SenderData` is about the session as a whole. A session can be fine,
whilst events (claiming to be) encrypted with it can be suspect. What we
want here is to check a specific message. Currently, this doesn't make
any functional difference, but conceptually it's cleaner to check the
`VerificationState`.
Note that there are a bunch of tests for this method in
`matrix-sdk-crypto/src/machine/tests/decryption_verification_state.rs`,
called `test_decryption_trust_requirement`.
This patch removes the `SlidingSync::rooms` field. A cascade of removal
happens, and many part of the code is simplified. The most notable is
`FrozenSlidingSync`.
This patch
- Updates Ruma to use the improved MediaPreviewConfig event type that
also supports a `Default` for the content type
- Implemented a way to observe the stable and unstable values of the
event and return the used one accordingly, if no one is present the
default will be used
- Set the value (will only use unstable type for now)
This patch removes the `RoomInfo::prev_room_state` field, along with the
`RoomInfo::prev_state` method.
This data was introduced during the knocking project but was never used,
and is not used nowadays. Let's remove it.
This is used to configure EC on devices that need to control media outputs on their own (android, ios).
If set, EC will display a list of devices provided by the app.
This patch adds the `m.room.tombstone` state event to the list of
events in `required_state` used by the `RoomListService`. The goal is to
offer the possibility for the consumers to know whether a room has been
tombstoned or not.
The `read_receipts::compute_unread_counts` function needs the _previous
events_ to compute the read receipt correctly. These previous events
were store in `SlidingSyncRoom::timeline_queue`. Since the removal of
`timeline_queue` in the previous patches, this patch uses the Event
Cache to fetch them. It only uses events that are loaded in memory.
This is as correct as the prior behaviour, even this is still incorrect
since it doesn't back-paginate to get a better view. This is for
later. The goal of this patch is to restore the same behaviour, without
`timeline_queue`.
The main problem is that read receipts are computed in
`matrix-sdk-base`, and that the Event Cache lives in `matrix-sdk`. Thus,
we change the `SlidingSyncResponseProcessor` to handle read receipt
in particular.
The
`matrix_sdk_base::response_processors::rooms::msc4186::extensions::dispa
tch_ephemeral_events` function has been split in
two methods `dispatch_typing_ephemeral_events`, and
`dispatch_receipt_ephemeral_event_for_room`. The workflow has been a
little bit redesigned to fit in the new `SlidingSyncResponseProcessor`
constraints.
This patch moves one test from `matrix-sdk-base` into `matrix-sdk`,
because to compute the read receipt, the Event Cache must be
enabled/listening to sync updates.
`RoomEventCache::subscribe` returns the set of events + the
`RoomEventCacheListener`. However, creating this listener isn't
cheap, especially dropping it. That's why this patch creates
`RoomEventCache::events` to replace `subscribe` when the listener is
not necessary.
This patch reduces the sizes of `Verification` from 376 bytes to
16 bytes, and `VerificationRequestState` from 424 bytes to 96 bytes.
It also reduces the size of a couple of other types in the same vain.
They have never been set and there was no way of telling if stickers and polls belong on a thread or come in reply of any other message.
This patch also exposes methods for setting these relations on the event factory level.
This moves the logic from `Room::join()` to these two methods. This is
isofunctional, because `Room::join()` does call into
`Client::join_room_by_id()` internally.
The then() function can be used with booleans and futures to execute a
piece of code if the boolean is true or once the future is completed.
In contrast, the then() function in the widget driver is not executed
immediately. Instead it only adds a callback that is later on executed
by the widget driver.
… that allows building a timeline instance specific to a particular
thread root.
Creating a timeline in this mode will start by backpaginating root event
relations with `num_events` and automatically insert the thread root
event when reaching the end. It will include
`RelationsOfType(RelationType::Thread)` but also recurse over the
retrieved events to fetch reactions.
It will not however react to new events received over sync or that the
user sends (for now).
This patch will also help incrementally deliver the upstream client
support for creating such a timeline.
Part of #4833 (meta #4869).
Under some very particular circumstances, the "database is locked" error
can still happen, even in WAL mode, even if the database connection is
not being upgraded from a read transaction to a write transaction.
We *think* this might be the reason behind errors like
github.com/element-hq/element-x-ios/issues/3582, so we're enabling the
sqlite busy_timeout, which will retry the operation after a short sleep,
until the busy timeout is being hit.
This variant will be used to cause side-effects to existing timeline
items, because the event they relate to is for an aggregation
(edit/reaction/etc.).
This is used here for reactions.
This patch updates `EventHandler` to use the correct regions where
appropriate, thus reducing the complexity of the code, and removing
classes of bugs.
In the case of `Flow::Remote { position: TimelineItemPosition::At { …
}}`, we no longer need to skip the local timeline items, and to handle
the presence of the `TimelineStart` timeline item. The code is less
complex.
In the case of `Flow::Remote { position: TimelineItemPosition::End { …
}}`, that's exactly the same at the previous case.
In the case of `recycle_local_or_create_item`, the `try_fold` approach
is replaced entirely with a simple `iter_locals_region`, reducing the
size of the comments explaining the code, reducing the complexity of the
code, and reducing the surface of bugs.
This patch updates `TimelineMetadata` to work on the _remotes_ region
only, excluding the _start_ and the _locals_ regions. It helps to reduce
the risk of inserting items in an incorrect regions.
This patch also removes on more `rfind_event_by_id` usage, which is
nice.
This patch updates `ReadReceiptTimelineUpdate` to work on the _remotes_
region only, excluding the _start_ and the _lcoals_ regions. It helps
to reduce the risk of inserting a `ReadMarker` inside the _start_ or the
_locals_ regions.
This patch updates `DateDividerAdjuster` to work on _remotes_ and
_locals_ regions only, excluding the _start_ region. It helps to reduce
the risk of inserting a `DateDivider` inside the _start_ region.
This patch also uses the new `push_date_divider` method, which provides
a couple of invariants.
This patch defines a new concept in the `Timeline`: Regions.
The `ObservableItems` holds all the invariants about the _position_ of the
items. It defines three regions where items can live:
1. the _start_ region, which can only contain a single `TimelineStart`,
2. the _remotes_ region, which can only contain many `Remote` timeline
items with their decorations (only `DateDivider`s and `ReadMarker`s),
3. the _locals_ region, which can only contain many `Local` timeline items
with their decorations (only `DateDivider`s).
The `iter_all_regions` method allows to iterate over all regions.
`iter_remotes_region` will restrict the iterator over the _remotes_
region, and so on. These iterators provide the absolute indices of the
items, so that it's harder to make mistakes when manipulating the indices of
items with operations like `insert`, `remove`, `replace` etc.
Other methods like `push_local` or `push_date_divider` insert the items
in the correct region, and check a couple of invariants.
This patch implements the `has_local` method on
`ObservableItemsTransaction`, which is way faster than the previous the
previous solution which was to iterate over all items to find at least
one local timeline item.
This patch adds the `push_local` method on `ObservableItemsTransaction`
to add semantics and hardcode the invariant in a single place for the
different timeline items.
This patch adds the `push_timeline_start_if_missing` method on
`ObservableItemsTransaction` to add semantics and hardcode the
invariant in a single place for the different timeline items.
This patch adds the `--generate-link-to-definition`
argument to `rustdoc` for `docs.rs`. This is using
https://github.com/rust-lang/rust/pull/84176 to add links in the source
code page.
If we already have cross-signing details for the owner of the device at the
point we receive the to-device message, we should store that rather than just
the device info.
create a new method `SenderData::from_device` which does the last few steps of
`SenderDataFinder`: turns out we want it elsewhere. Add some tests to test that
functionality in isolation.
- Doc comment for the SQLite-based state store incorrectly referred to
it as a "cryptostore".
- Consistent capitalisation of SQLite.
- Consistent use of indefinite article "an" before SQLite.
- Fix line length.
Imagine we have the following events:
| event_id | room_id | chunk_id | position |
|----------|---------|----------|----------|
| $ev0 | !r0 | 42 | 0 |
| $ev1 | !r0 | 42 | 1 |
| $ev2 | !r0 | 42 | 2 |
| $ev3 | !r0 | 42 | 3 |
| $ev4 | !r0 | 42 | 4 |
`$ev2` has been removed, then we end up in this state:
| event_id | room_id | chunk_id | position |
|----------|---------|----------|----------|
| $ev0 | !r0 | 42 | 0 |
| $ev1 | !r0 | 42 | 1 |
| | | | | <- no more `$ev2`
| $ev3 | !r0 | 42 | 3 |
| $ev4 | !r0 | 42 | 4 |
We need to shift the `position` of `$ev3` and `$ev4` to `position - 1`,
like so:
| event_id | room_id | chunk_id | position |
|----------|---------|----------|----------|
| $ev0 | !r0 | 42 | 0 |
| $ev1 | !r0 | 42 | 1 |
| $ev3 | !r0 | 42 | 2 |
| $ev4 | !r0 | 42 | 3 |
Usually, it boils down to run the following query:
```sql
UPDATE event_chunks
SET position = position - 1
WHERE position > 2 AND …
```
Okay. But `UPDATE` runs on rows in no particular order. It means that
it can update `$ev4` before `$ev3` for example. What happens in this
particular case? The `position` of `$ev4` becomes `3`, however `$ev3`
already has `position = 3`. Because there is a `UNIQUE` constraint
on `(room_id, chunk_id, position)`, it will result in a constraint
violation.
There is **no way** to control the execution order of `UPDATE` in
SQLite. To persuade yourself, try:
```sql
UPDATE event_chunks
SET position = position - 1
FROM (
SELECT event_id
FROM event_chunks
WHERE position > 2 AND …
ORDER BY position ASC
) as ordered
WHERE event_chunks.event_id = ordered.event_id
```
It will fail the same way.
Thus, we have 2 solutions:
1. Remove the `UNIQUE` constraint,
2. Be creative.
The `UNIQUE` constraint is a safe belt. Normally, we have
`event_cache::Deduplicator` that is responsible to ensure there is no
duplicated event. However, relying on this is “fragile” in the sense it
can contain bugs. Relying on the `UNIQUE` constraint from SQLite is more
robust. It's “braces and belt” as we say here.
So. We need to be creative.
Many solutions exist. Amongst the most popular, we see _dropping and
re-creating the index_, which is no-go for us, it's too expensive. I
(@hywan) have adopted the following one:
- Do `position = position - 1` but in the negative space, so
`position = -(position - 1)`. A position cannot be negative; we are
sure it is unique!
- Once all candidate rows are updated, do `position = -position` to move
back to the positive space.
'told you it's gonna be creative.
This solution is a hack, **but** it is a small number of operations, and
we can keep the `UNIQUE` constraint in place.
This patch updates the `test_linked_chunk_remove_item` to handle
6 events. On _my_ system, with _my_ SQLite version, it triggers the
`UNIQUE` constraint violation without the bug fix.
This is necessary because the `NotificationClient` runs a sliding sync loop and the retrieved data isn't pushed back into the parent client stores (because of cross process locking shenanigans).
This will be used with the previously introduced `org.matrix.msc3401.call.member` required state to check whether a room still has an ongoing call before showing the ringing screen.
This is apparently the right way to do it, both because some HS expect only this mimetype and also so we don't leak the mime type of the encrypted media.
This commit simplifies the filter public api.
Rethinking the public api we only need:
- to know if events can be sent based on the capabilities
- to know if events can be sent to the widget (read) based on the capabilities
- if it even makes sense to sent a cs api read request or if all possibly returned events
would not match the type.
To simplify the code in the machine it also made sense to add `From` implementation
to the FilterInputs instead of gathering the relevant data from all kinds of Raw events.
The new api is simpler:
All possible events we need to check can be converted into filter inputs (using `into()`).
`capabilites` has two allow_read/allow_send that consume filter inputs.
`capabilites` can be asked if there is any filter for specific event types
to allow not send unnecassary requests.
This is (sadly) required since we cannot do `as_str()` for `TimlineEventType` and other `ruma` event types.
So we need to use `String`. We also never used them more specifically than strings.
Previously, the `share_strategy` was breaking the abstraction provided
by `OutboundGroupSession` by accessing its internal fields in an
inconsistent and adhoc way. Now all fields are private and a proper
abstraction was added to access the required state in a consistent API.
This patch moves the `session_id` field from EncryptionInfo to
AlgorithmInfo::MegolmV1AesSha2 as it is specific to Megolm. We provide
transparent migration of the serialized data from one format to the other.
In the future we plan to reuse `EncryptionInfo` for to_device decryption
(using olm not megolm). So megolm session_id should move to algorithm
specific data.
This method had a confusing name: it didn't receive a key bundle, but
rather the data *about* a key bundle.
Remove the unused `sender_key` parameter while we are at it: we use the
embedded (and already-checked) `event.sender_device_keys` here.
This avoids conditions where a key may be shared with a device only
after we decided that it is fine to reuse (and not rotate) the session
based on the wrong assumption that that particular device does not have
the keys.
Signed-off-by: Niklas Baumstark
[niklas.baumstark@gmail.com](mailto:niklas.baumstark@gmail.com)
Previously, `is_session_overshared_for_user` did not take into account
that `shared_with_set` also contains withheld device IDs who explicitly
have never received the session keys. This would lead to it mistakenly
determining oversharing for those devices for every event being sent in
the presence of blacklisted/withheld devices in the room, and rotating
the group session accordingly.
The fix is to correctly exclude devices with `ShareInfo::Withheld` from
the enumeration.
Signed-off-by: Niklas Baumstark niklas.baumstark@gmail.com
This patch updates the sending side of the `sender_device_keys` field
introduced in MSC4147.
Since the MSC got merged, we're switching from the unstable identifier
to the stable one.
A couple of snapshot tests were added modified to make this happen.
This PR is a revived version of:
https://github.com/matrix-org/matrix-rust-sdk/pull/4707 since it is now
possible to easily add wasm support thanks to:
https://github.com/matrix-org/matrix-rust-sdk/pull/4572
Using the `executer::spawn` will select `tokio::spawn` or
`wasm_bindgen_futures::spawn_local` based on what platform we are on.
~~They behave differently in that `tokio` actually starts the async
block inside the spawn but the wasm `spawn` wrapper will only start the
part that is not inside the `async` block and the join handle needs to
be awaited for it to work.~~
This has now changed with:
https://github.com/matrix-org/matrix-rust-sdk/pull/4572.
Now they behave the same and this PR becomes a very simple change.
Rather than attempting to trigger Alice's encryption sync loop with an incoming
message from Bob, instead have Alice send a message once Bob has joined the
room.
Simplifies the `ProcessedToDeviceEvent` enum by converting its variants to tuple variants.
This change improves code readability and conciseness by removing the need for named fields within the variants.
This patch introduces a temporary hack.
So here is the thing. Ideally, we DO NOT want to emit this reason.
It does not makes sense. However, all notable update reasons
are not clearly identified so far. Why is it a problem? The
`matrix_sdk_ui::room_list_service::RoomList` is listening this stream
of [`RoomInfoNotableUpdate`], and emits an update on a room item if
it receives a notable reason. Because all reasons are not identified,
we are likely to miss particular updates, and it can feel broken.
Ultimately, we want to clearly identify all the notable update reasons,
and remove this one.
This patch creates the `room::display_name::update_for_rooms` response
processor. It also creates the `changes::save_only` response processor.
Finally, this patch uses both to compute the new display name for all
rooms and save them, for sliding sync only.
This patch extracts the “save” part of the `save_and_apply` response
processor into its own function. Thus we have `save_changes` (new) and
`apply_changes` that are used by `save_and_apply`.
This patch introduces a new enum: `UpdatedRoomDisplayName`, which
will be used to know if a room display name is different or not when
computing the room display name.
…that holds information on the thread the given item is the root of
- it holds the latest event content and sender at the moment but will
hold more information in the future e.g. number of replies, if it's
unread etc.
- the field is not currently being populate but is delivered earlier so
it can power shipping the UI side on the embedders
See #4891 that shows a case where we should have saved the
previous-batch token, and instead ditched it, in the previous version.
Changes include:
- moving the code deciding to keep or ditch the `previous-batch` token
into `append_events_locked`.
- tweak the condition to ditch, so that the `previous-batch` token is
ditched only if we didn't have events in the event cache in the first
place, in addition to having storage + the timeline not being marked as
limited explicitly.
Credits to @zecakeh for the test case.
This patch is twofold:
1. it transforms the `&mut` to a `&` for the room account data in the
sliding sync flow, which allows to remove one big clone!
2. it adds the `room_account_data` response processor.
This patch creates the new `room::msc4186::extensions::ephemeral_events`
response processor.
Ideally we would like to merge this with `ephemeral_events`, but they
are a bit different. Let's see how it evolves in the future.
This patch uses the `room::Room` structure in `room::sync_v2` to
reduce the number of arguments of the `update_joined_room` and the
`update_left_room` processors.
This patch uses the `room::Room` structure in
`room::msc4186::update_any_room` to reduce its number of arguments. It
results in the removal of te `allow(clippy::too_many_arguments)`.
This patch removes the `SessionMeta` argument of
`room::msc4186::update_any_room`. Tracking its usage, it reveals that
providing a `UserId` is sufficient. Happily, we already provide a
`UserId`, hence making `SessionMeta` useless here.
This patch renames the fields in `RoomUpdate`: `join` becomes `joined`,
`leave` becomes `left`, `invite` becomes `invited`, to match their
associate type.
This patch simplifies the flow of `membership` when the room is an
invited room.
Previously, we were creating the room as `Invited`. Then, later
overriding it to `Knocked` if we found it was such a room. Otherwise, we
were overriding it again to `Invited`. Well. Now the flow is simpler.
This patch extracts the `BaseClient::process_sliding_sync_room` method
into the new `msc4186::update_any_room` response processor. So far, this
is purely a code move, without any changes (modulo method-to-function
transformation).
With `BaseClient:process_sliding_sync_room` comes
`BaseClient::process_sliding_sync_room_membership`,
`BaseClient::handle_own_room_membership`, `process_room_properties` and
`cache_latest_events`.
This patch removes the re-exports of `Notification` and `E2EE` in
`timeline::builder`. Let's make things simple now that they are used
outside the `timeline` processors.
This patch groups arguments behind the `Notification` struct
if it makes sense. This patch also uses the new method
`Notification::push_notification_from_event_if` method to replace
duplicated code.
This patch moves the `timeline::builder::Notification` into
its own module, `notification`. This patch adds two methods:
`push_notification` and `push_notification_from_event_if`.
This patch adds two `From` implementations on
`RawAnySyncOrStrippedTimelineEvent` to create the correct variant of
this enum. This is useful when we get generic types and want to build
this type.
This patch creates the `update_left_room` processor, extracted from the
sync v2 flow.
I've noticed that `new_user_ids` is not used, so it has been put behind
a `_` variable for the moment, but some computations have been removed.
We need to clean this user ID flow.
This patch moves the `timeline::builder::E2EE` type into the `e2ee`
module. Gathering these 3 E2EE values in the same type was a good idea,
and is now applied to more places in the response processors.
This patch makes `Context` to derive `Default`. The `new` constructor
also no longer takes a `RoomInfoNotableUpdates`, since it was always
used with a default value, it generates this value by itself.
This patch removes all mentions of `include_heroes`. This field isn't
part of the MSC4186. We have the `test_compute_heroes_from_sliding_sync`
which continues to pass, everything fine on that side. There is no
mention of `include_heroes` in Synapse at the time of writing. It seems
to be an artifact from the sliding sync proxy experiment.
This patch moves the `state_events::dispatch_and_get_new_users`
processor inside the `state_events::sync` module. Why? Because a similar
processor for `state_events::stripped` is about to be created.
MSC4147 added a `sender_device_keys` property to olm-encrypted to-device
messages, with recommendations about checking the values in that propety. We do
(most of?) those checks for `m.room_key` messages today, but not other types of
to-device message.
MSC4147 added a `sender_device_keys` property to the plaintext of *all*
olm-encrypted events. 03d4a30eb added the field to `DecryptedOlmV1Event`, but
due to Reasons, there is an almost-parallel struct `ToDeviceCustomEvent` which
is used for event types other than the 4 we have content types for.
To complete the set, let's add the field to `ToDeviceCustomEvent`.
2025-04-11 11:01:22 +01:00
750 changed files with 114328 additions and 37010 deletions
Development of the SDK is proudly sponsored and maintained by [Element](https://element.io). Element uses the SDK in their next-generation mobile apps Element X on [iOS](https://github.com/element-hq/element-x-ios) and [Android](https://github.com/element-hq/element-x-android) and has plans to introduce it to the web and desktop clients as well.
The SDK is also the basis for multiple Matrix projects and we welcome contributions from all.
</div>
## Purpose
The SDK takes care of the low-level details like encryption,
syncing, and room state, so you can focus on your app's logic and UI. Whether
you're writing a small bot, a desktop client, or something in between, the SDK
is designed to be flexible, async-friendly, and ready to use out of the box.
[Matrix]: https://matrix.org/
[Rust]: https://www.rust-lang.org/
## Project structure
The Matrix Rust SDK is made up of several crates that build on top of each other. Here are the key ones:
The Matrix Rust SDK is made up of several crates that build on top of each
other. The following crates are expected to be usable as direct dependencies:
- [matrix-sdk-ui](https://docs.rs/matrix-sdk-ui/latest/matrix_sdk_ui/) – A high-level client library that makes it easy to build
full-featured UI clients with minimal setup. Check out our reference client,
@@ -45,6 +62,9 @@ The Matrix Rust SDK is made up of several crates that build on top of each other
See the [crypto tutorial](https://docs.rs/matrix-sdk-crypto/latest/matrix_sdk_crypto/tutorial/index.html)
for a step-by-step introduction.
All other crates are effectively internal-only and only structured as crates
for organizational purposes and to improve compilation times. Direct usage of them is discouraged.
## Status
The library is considered production ready and backs multiple client
@@ -54,9 +74,6 @@ implementations such as Element X
[Fractal](https://gitlab.gnome.org/World/fractal) and [iamb](https://github.com/ulyssa/iamb). Client developers should feel
confident to build upon it.
Development of the SDK has been primarily sponsored by Element though accepts
contributions from all.
## Bindings
The higher-level crates of the Matrix Rust SDK can be embedded in other
- Add `Client::get_store_sizes()` so to query the size of the existing stores, if available. ([#5911](https://github.com/matrix-org/matrix-rust-sdk/pull/5911))
- Expose `is_space` in `NotificationRoomInfo`, allowing clients to determine if the room that triggered the notification is a space.
- Add push actions to `NotificationItem` and replace `SyncNotification` with `NotificationItem`.
- Add `Room::mark_as_fully_read_unchecked` so clients can mark a room as read without needing a `Timeline` instance. Note this method is not recommended as it can potentially cause incorrect read receipts, but it can needed in certain cases.
- Add `Timeline::latest_event_id` to be able to fetch the event id of the latest event of the timeline.
- Add `Room::load_or_fetch_event` so we can get a `TimelineEvent` given its event id ([#5678](https://github.com/matrix-org/matrix-rust-sdk/pull/5678)).
- Add `TimelineEvent::thread_root_event_id` to expose the thread root event id for this type too ([#5678](https://github.com/matrix-org/matrix-rust-sdk/pull/5678)).
- Add `NotificationSettings::get_raw_push_rules` so clients can fetch the raw JSON content of the push rules of the current user and include it in bug reports ([#5706](https://github.com/matrix-org/matrix-rust-sdk/pull/5706)).
- Add new API to decline calls ([MSC4310](https://github.com/matrix-org/matrix-spec-proposals/pull/4310)): `Room::decline_call` and `Room::subscribe_to_call_decline_events`
- Expose `m.federate` in `OtherState::RoomCreate` and `history_visibility` in `OtherState::RoomHistoryVisibility`, allowing clients to know whether a room federates and how its history is shared in the appropriate timeline events.
- Expose `join_rule` in `OtherState::RoomJoinRules`, allowing clients to know the join rules of a room from the appropriate timeline events.
### Changes
- `Timeline::latest_event_id` now uses its `ui::Timeline::latest_event_id` counterpart, instead of getting the latest event from the timeline and then its id.([#5864](https://github.com/matrix-org/matrix-rust-sdk/pull/5864))
- Build Android ARM64 bindings using better default RUSTFLAGS (the same used for iOS ARM64). This should improve performance. [(#5854)](https://github.com/matrix-org/matrix-rust-sdk/pull/5854)
## [0.14.0] - 2025-09-04
### Features:
- Add `LowPriority` and `NonLowPriority` variants to `RoomListEntriesDynamicFilterKind` for filtering
rooms based on their low priority status. These filters allow clients to show only low priority rooms
- `Room::send_call_notification` and `Room::send_call_notification_if_needed` have been removed, since the event type they send is outdated, and `Client` is not actually supposed to be able to join MatrixRTC sessions (yet). In practice, users of these methods probably already rely on another MatrixRTC implementation to participate in sessions, and such an implementation should be capable of sending notifications itself.
- The `GalleryItemInfo` variants now take an `UploadSource` rather than a `String` path to enable uploading
- `contacts` has been removed from `OidcConfiguration` (it was unused since the switch to OAuth).
## [0.11.0] - 2025-04-11
Breaking changes:
@@ -20,7 +289,7 @@ Breaking changes:
programs can set it to `true`.
- Matrix client API errors coming from API responses will now be mapped to `ClientError::MatrixApi`, containing both the
original message and the associated error code and kind.
original message and the associated error code and kind.
- `EventSendState` now has two additional variants: `CrossSigningNotSetup` and
`SendingFromUnverifiedDevice`. These indicate that your own device is not
@@ -81,7 +350,8 @@ Breaking changes:
- The `dynamic_registrations_file` field of `OidcConfiguration` was removed.
Clients are supposed to re-register with the homeserver for every login.
- `RoomPreview::own_membership_details` is now `RoomPreview::member_with_sender_info`, takes any user id and returns an `Option<RoomMemberWithSenderInfo>`.
- `RoomPreview::own_membership_details` is now `RoomPreview::member_with_sender_info`, takes any user id and returns an
`Option<RoomMemberWithSenderInfo>`.
Additions:
@@ -96,9 +366,11 @@ Additions:
- Add `Timeline::send_thread_reply` for clients that need to start threads
- Add `ClientBuilder::session_pool_max_size`, `::session_cache_size` and `::session_journal_size_limit` to control the stores configuration, especially their memory consumption
- Add `ClientBuilder::session_pool_max_size`, `::session_cache_size` and `::session_journal_size_limit` to control the
stores configuration, especially their memory consumption
- Add `Room::member_with_sender_info` to get both a room member's info and for the user who sent the `m.room.member` event the `RoomMember` is based on.
- Add `Room::member_with_sender_info` to get both a room member's info and for the user who sent the `m.room.member`
This uses [`uniffi`](https://mozilla.github.io/uniffi-rs/Overview.html) to build the matrix bindings for native support and wasm-bindgen for web-browser assembly support. Please refer to the specific section to figure out how to build and use the bindings for your platform.
## Features
Given the number of platforms targeted, we have broken out a number of features
### Platform specific
-`rustls-tls`: Use Rustls as the TLS implementation, necessary on Android platforms.
-`native-tls`: Use the TLS implementation provided by the host system, necessary on iOS and Wasm platforms.
### Functionality
-`sentry`: Enable error monitoring using Sentry, not supports on Wasm platforms.
-`sqlite`: Use SQLite for the session storage.
-`bundled-sqlite`: Use an embedded version of SQLite instead of the system provided one.
-`indexeddb`: Use IndexedDB for the session storage.
### Unstable specs
-`unstable-msc4274`: Adds support for gallery message types, which contain multiple media elements.
## Platforms
Each supported target should use features to select the relevant TLS system. Here are some suggested feature flags for the major platforms:
Some files were not shown because too many files have changed in this diff
Show More
Reference in New Issue
Block a user
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.