Skip to content
GitLab
Menu
Projects
Groups
Snippets
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
Menu
Open sidebar
GNOME
fractal
Commits
002be907
Commit
002be907
authored
May 13, 2022
by
Julian Sparber
Browse files
room: Retry to decrypt room messages
parent
6345b24d
Pipeline
#398995
failed with stages
in 26 minutes and 43 seconds
Changes
4
Pipelines
1
Hide whitespace changes
Inline
Side-by-side
src/session/content/room_history/message_row/mod.rs
View file @
002be907
...
...
@@ -412,7 +412,7 @@ fn build_content(parent: &adw::Bin, event: &Event, compact: bool) {
parent
.set_child
(
Some
(
&
child
));
child
};
child
.text
(
gettext
(
"Fractal couldn’t decrypt this message."
));
child
.text
(
gettext
(
"Fractal couldn’t decrypt this message
, but will retry once the keys are available
."
));
}
Some
(
AnyMessageLikeEventContent
::
RoomRedaction
(
_
))
=>
{
let
child
=
if
let
Some
(
Ok
(
child
))
=
parent
.child
()
.map
(|
w
|
w
.downcast
::
<
MessageText
>
())
...
...
src/session/mod.rs
View file @
002be907
...
...
@@ -26,6 +26,7 @@ use log::{debug, error, warn};
use
matrix_sdk
::{
config
::{
RequestConfig
,
SyncSettings
},
deserialized_responses
::
SyncResponse
,
room
::
Room
as
MatrixRoom
,
ruma
::{
api
::{
client
::{
...
...
@@ -36,7 +37,10 @@ use matrix_sdk::{
error
::{
FromHttpResponseError
,
ServerError
},
},
assign
,
events
::{
direct
::
DirectEventContent
,
GlobalAccountDataEvent
},
events
::{
direct
::
DirectEventContent
,
room
::
encryption
::
SyncRoomEncryptionEvent
,
GlobalAccountDataEvent
,
},
RoomId
,
},
store
::{
make_store_config
,
OpenStoreError
},
...
...
@@ -476,6 +480,7 @@ impl Session {
self
.room_list
()
.load
();
self
.setup_direct_room_handler
();
self
.setup_room_encrypted_changes
();
self
.sync
();
...
...
@@ -881,6 +886,32 @@ impl Session {
})
);
}
fn
setup_room_encrypted_changes
(
&
self
)
{
let
session_weak
=
glib
::
SendWeakRef
::
from
(
self
.downgrade
());
let
client
=
self
.client
();
spawn_tokio!
(
async
move
{
client
.register_event_handler
(
move
|
_
:
SyncRoomEncryptionEvent
,
matrix_room
:
MatrixRoom
|
{
let
session_weak
=
session_weak
.clone
();
async
move
{
let
ctx
=
glib
::
MainContext
::
default
();
ctx
.spawn
(
async
move
{
if
let
Some
(
session
)
=
session_weak
.upgrade
()
{
if
let
Some
(
room
)
=
session
.room_list
()
.get
(
matrix_room
.room_id
())
{
room
.set_is_encrypted
(
true
);
}
}
});
}
},
)
.await
;
});
}
}
impl
Default
for
Session
{
...
...
src/session/room/event.rs
View file @
002be907
...
...
@@ -11,11 +11,13 @@ use matrix_sdk::{
ruma
::{
events
::{
room
::{
encrypted
::
RoomEncryptedEventContent
,
message
::{
MessageType
,
Relation
},
redaction
::
SyncRoomRedactionEvent
,
},
AnyMessageLikeEventContent
,
AnySyncMessageLikeEvent
,
AnySyncRoomEvent
,
AnySyncStateEvent
,
MessageLikeUnsigned
,
SyncMessageLikeEvent
,
SyncStateEvent
,
AnySyncStateEvent
,
MessageLikeUnsigned
,
OriginalSyncMessageLikeEvent
,
SyncMessageLikeEvent
,
SyncStateEvent
,
},
MilliSecondsSinceUnixEpoch
,
OwnedEventId
,
OwnedTransactionId
,
OwnedUserId
,
},
...
...
@@ -27,7 +29,7 @@ use super::{
Member
,
ReactionList
,
Room
,
};
use
crate
::{
spawn_tokio
,
spawn
,
spawn_tokio
,
utils
::{
filename_for_mime
,
media_type_uid
},
};
...
...
@@ -54,6 +56,7 @@ mod imp {
pub
replacing_events
:
RefCell
<
Vec
<
super
::
Event
>>
,
pub
reactions
:
ReactionList
,
pub
source_changed_handler
:
RefCell
<
Option
<
SignalHandlerId
>>
,
pub
keys_handle
:
RefCell
<
Option
<
SignalHandlerId
>>
,
pub
room
:
OnceCell
<
WeakRef
<
Room
>>
,
}
...
...
@@ -221,6 +224,16 @@ impl Event {
let
priv_
=
self
.imp
();
if
let
Ok
(
deserialized
)
=
event
.event
.deserialize
()
{
if
let
AnySyncRoomEvent
::
MessageLike
(
AnySyncMessageLikeEvent
::
RoomEncrypted
(
SyncMessageLikeEvent
::
Original
(
ref
encrypted
),
))
=
deserialized
{
let
encrypted
=
encrypted
.to_owned
();
spawn!
(
clone!
(
@
weak
self
as
obj
=>
async
move
{
obj
.try_to_decrypt
(
encrypted
)
.await
;
}));
}
priv_
.event
.replace
(
Some
(
deserialized
));
}
else
{
warn!
(
"Failed to deserialize event: {:?}"
,
event
);
...
...
@@ -230,6 +243,35 @@ impl Event {
self
.notify
(
"event"
);
self
.notify
(
"activatable"
);
self
.notify
(
"source"
);
}
async
fn
try_to_decrypt
(
&
self
,
event
:
OriginalSyncMessageLikeEvent
<
RoomEncryptedEventContent
>
)
{
let
priv_
=
self
.imp
();
let
room
=
self
.room
()
.matrix_room
();
let
handle
=
spawn_tokio!
(
async
move
{
room
.decrypt_event
(
&
event
)
.await
});
match
handle
.await
.unwrap
()
{
Ok
(
decrypted
)
=>
{
if
let
Some
(
keys_handle
)
=
priv_
.keys_handle
.take
()
{
self
.room
()
.disconnect
(
keys_handle
);
}
self
.set_matrix_pure_event
(
decrypted
.into
());
}
Err
(
error
)
=>
{
warn!
(
"Failed to decrypt event: {}"
,
error
);
if
priv_
.keys_handle
.borrow
()
.is_none
()
{
let
handle
=
self
.room
()
.connect_new_encryption_keys
(
clone!
(
@
weak
self
as
obj
=>
move
|
_
|
{
// Try to decrypt the event again
obj
.set_matrix_pure_event
(
obj
.matrix_pure_event
());
}),
);
priv_
.keys_handle
.replace
(
Some
(
handle
));
}
}
}
}
pub
fn
matrix_sender
(
&
self
)
->
OwnedUserId
{
...
...
src/session/room/mod.rs
View file @
002be907
...
...
@@ -31,11 +31,12 @@ use matrix_sdk::{
redaction
::{
OriginalSyncRoomRedactionEvent
,
RoomRedactionEventContent
},
topic
::
RoomTopicEventContent
,
},
room_key
::
ToDeviceRoomKeyEventContent
,
tag
::{
TagInfo
,
TagName
},
AnyRoomAccountDataEvent
,
AnyStrippedStateEvent
,
AnySyncMessageLikeEvent
,
AnySyncRoomEvent
,
AnySyncStateEvent
,
EventContent
,
MessageLikeEventType
,
MessageLikeUnsigned
,
OriginalSyncMessageLikeEvent
,
StateEventType
,
SyncMessageLikeEvent
,
SyncStateEvent
,
SyncMessageLikeEvent
,
SyncStateEvent
,
ToDeviceEvent
,
},
receipt
::
ReceiptType
,
serde
::
Raw
,
...
...
@@ -110,6 +111,8 @@ mod imp {
pub
successor
:
OnceCell
<
OwnedRoomId
>
,
/// The most recent verification request event.
pub
verification
:
RefCell
<
Option
<
IdentityVerification
>>
,
/// Whether this room is encrypted
pub
is_encrypted
:
Cell
<
bool
>
,
}
#[glib::object_subclass]
...
...
@@ -241,6 +244,13 @@ mod imp {
IdentityVerification
::
static_type
(),
glib
::
ParamFlags
::
READWRITE
,
),
glib
::
ParamSpecBoolean
::
new
(
"encrypted"
,
"Encrypted"
,
"Whether this room is encrypted"
,
false
,
glib
::
ParamFlags
::
READWRITE
|
glib
::
ParamFlags
::
EXPLICIT_NOTIFY
,
),
]
});
...
...
@@ -276,6 +286,7 @@ mod imp {
obj
.store_topic
(
topic
);
}
"verification"
=>
obj
.set_verification
(
value
.get
()
.unwrap
()),
"encrypted"
=>
obj
.set_is_encrypted
(
value
.get
()
.unwrap
()),
_
=>
unimplemented!
(),
}
}
...
...
@@ -310,6 +321,7 @@ mod imp {
|
id
|
id
.as_ref
()
.to_value
(),
),
"verification"
=>
obj
.verification
()
.to_value
(),
"encrypted"
=>
obj
.is_encrypted
()
.to_value
(),
_
=>
unimplemented!
(),
}
}
...
...
@@ -319,6 +331,7 @@ mod imp {
vec!
[
Signal
::
builder
(
"order-changed"
,
&
[],
<
()
>
::
static_type
()
.into
())
.build
(),
Signal
::
builder
(
"room-forgotten"
,
&
[],
<
()
>
::
static_type
()
.into
())
.build
(),
Signal
::
builder
(
"new-encryption-keys"
,
&
[],
<
()
>
::
static_type
()
.into
())
.build
(),
]
});
SIGNALS
.as_ref
()
...
...
@@ -338,6 +351,7 @@ mod imp {
.unwrap
();
obj
.load_power_levels
();
obj
.setup_is_encrypted
();
obj
.bind_property
(
"display-name"
,
obj
.avatar
(),
"display-name"
)
.flags
(
glib
::
BindingFlags
::
SYNC_CREATE
)
...
...
@@ -1637,6 +1651,75 @@ impl Room {
self
.set_latest_unread
(
latest_unread
);
}
pub
fn
is_encrypted
(
&
self
)
->
bool
{
self
.imp
()
.is_encrypted
.get
()
}
pub
fn
set_is_encrypted
(
&
self
,
is_encrypted
:
bool
)
{
let
was_encrypted
=
self
.is_encrypted
();
if
was_encrypted
==
is_encrypted
{
return
;
}
if
was_encrypted
&&
!
is_encrypted
{
error!
(
"Encryption for a room can't be disabled"
);
return
;
}
if
self
.matrix_room
()
.is_encrypted
()
!=
is_encrypted
{
// TODO: enable encryption if it isn't enabled yet
}
self
.setup_is_encrypted
();
}
fn
setup_is_encrypted
(
&
self
)
{
if
!
self
.matrix_room
()
.is_encrypted
()
{
return
;
}
self
.setup_new_encryption_keys_handler
();
self
.imp
()
.is_encrypted
.set
(
true
);
self
.notify
(
"encrypted"
);
}
fn
setup_new_encryption_keys_handler
(
&
self
)
{
spawn!
(
glib
::
PRIORITY_DEFAULT_IDLE
,
clone!
(
@
weak
self
as
obj
=>
async
move
{
let
obj_weak
=
glib
::
SendWeakRef
::
from
(
obj
.downgrade
());
obj
.session
()
.client
()
.register_event_handler
(
move
|
event
:
ToDeviceEvent
<
ToDeviceRoomKeyEventContent
>
|
{
let
obj_weak
=
obj_weak
.clone
();
async
move
{
let
ctx
=
glib
::
MainContext
::
default
();
ctx
.spawn
(
async
move
{
if
let
Some
(
room
)
=
obj_weak
.upgrade
()
{
if
room
.room_id
()
==
event
.content.room_id
{
room
.emit_by_name
::
<
()
>
(
"new-encryption-keys"
,
&
[]);
}
}
});
}
},
)
.await
;
})
);
}
pub
fn
connect_new_encryption_keys
<
F
:
Fn
(
&
Self
)
+
'static
>
(
&
self
,
f
:
F
,
)
->
glib
::
SignalHandlerId
{
self
.connect_local
(
"new-encryption-keys"
,
true
,
move
|
values
|
{
let
obj
=
values
[
0
]
.get
::
<
Self
>
()
.unwrap
();
f
(
&
obj
);
None
})
}
}
/// Whether the given event can count as an unread message.
...
...
Write
Preview
Supports
Markdown
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment