Skip to content
This repository was archived by the owner on Sep 11, 2024. It is now read-only.

Commit bf5fe29

Browse files
authored
Merge pull request #6695 from matrix-org/travis/keep-old-out
Don't send prehistorical events to widgets during decryption at startup
2 parents 3ed76f5 + 20b6219 commit bf5fe29

File tree

1 file changed

+47
-0
lines changed

1 file changed

+47
-0
lines changed

src/stores/widgets/StopGapWidget.ts

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,7 @@ import { MatrixEvent } from "matrix-js-sdk/src/models/event";
5555
import { ELEMENT_CLIENT_ID } from "../../identifiers";
5656
import { getUserLanguage } from "../../languageHandler";
5757
import { WidgetVariableCustomisations } from "../../customisations/WidgetVariables";
58+
import { arrayFastClone } from "../../utils/arrays";
5859

5960
// TODO: Destroy all of this code
6061

@@ -146,6 +147,7 @@ export class StopGapWidget extends EventEmitter {
146147
private scalarToken: string;
147148
private roomId?: string;
148149
private kind: WidgetKind;
150+
private readUpToMap: {[roomId: string]: string} = {}; // room ID to event ID
149151

150152
constructor(private appTileProps: IAppTileProps) {
151153
super();
@@ -294,6 +296,14 @@ export class StopGapWidget extends EventEmitter {
294296
this.messaging.transport.reply(ev.detail, <IWidgetApiRequestEmptyData>{});
295297
});
296298

299+
// Populate the map of "read up to" events for this widget with the current event in every room.
300+
// This is a bit inefficient, but should be okay. We do this for all rooms in case the widget
301+
// requests timeline capabilities in other rooms down the road. It's just easier to manage here.
302+
for (const room of MatrixClientPeg.get().getRooms()) {
303+
// Timelines are most recent last
304+
this.readUpToMap[room.roomId] = arrayFastClone(room.getLiveTimeline().getEvents()).reverse()[0].getId();
305+
}
306+
297307
// Attach listeners for feeding events - the underlying widget classes handle permissions for us
298308
MatrixClientPeg.get().on('event', this.onEvent);
299309
MatrixClientPeg.get().on('Event.decrypted', this.onEventDecrypted);
@@ -421,6 +431,43 @@ export class StopGapWidget extends EventEmitter {
421431
private feedEvent(ev: MatrixEvent) {
422432
if (!this.messaging) return;
423433

434+
// Check to see if this event would be before or after our "read up to" marker. If it's
435+
// before, or we can't decide, then we assume the widget will have already seen the event.
436+
// If the event is after, or we don't have a marker for the room, then we'll send it through.
437+
//
438+
// This approach of "read up to" prevents widgets receiving decryption spam from startup or
439+
// receiving out-of-order events from backfill and such.
440+
const upToEventId = this.readUpToMap[ev.getRoomId()];
441+
if (upToEventId) {
442+
// Small optimization for exact match (prevent search)
443+
if (upToEventId === ev.getId()) {
444+
return;
445+
}
446+
447+
let isBeforeMark = true;
448+
449+
// Timelines are most recent last, so reverse the order and limit ourselves to 100 events
450+
// to avoid overusing the CPU.
451+
const timeline = MatrixClientPeg.get().getRoom(ev.getRoomId()).getLiveTimeline();
452+
const events = arrayFastClone(timeline.getEvents()).reverse().slice(0, 100);
453+
454+
for (const timelineEvent of events) {
455+
if (timelineEvent.getId() === upToEventId) {
456+
break;
457+
} else if (timelineEvent.getId() === ev.getId()) {
458+
isBeforeMark = false;
459+
break;
460+
}
461+
}
462+
463+
if (isBeforeMark) {
464+
// Ignore the event: it is before our interest.
465+
return;
466+
}
467+
}
468+
469+
this.readUpToMap[ev.getRoomId()] = ev.getId();
470+
424471
const raw = ev.getEffectiveEvent();
425472
this.messaging.feedEvent(raw).catch(e => {
426473
console.error("Error sending event to widget: ", e);

0 commit comments

Comments
 (0)