Skip to content

Commit abf44ad

Browse files
authored
MSC4076: Add disable_badge_count to pusher configuration (#17975)
This PR implements [MSC4076: Let E2EE clients calculate app badge counts themselves (disable_badge_count)](matrix-org/matrix-spec-proposals#4076).
1 parent 657dd51 commit abf44ad

File tree

4 files changed

+98
-6
lines changed

4 files changed

+98
-6
lines changed

Diff for: changelog.d/17975.feature

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
[MSC4076](https://github.com/matrix-org/matrix-spec-proposals/pull/4076): Add `disable_badge_count` to pusher configuration.

Diff for: synapse/config/experimental.py

+3
Original file line numberDiff line numberDiff line change
@@ -448,3 +448,6 @@ def read_config(self, config: JsonDict, **kwargs: Any) -> None:
448448

449449
# MSC4222: Adding `state_after` to sync v2
450450
self.msc4222_enabled: bool = experimental.get("msc4222_enabled", False)
451+
452+
# MSC4076: Add `disable_badge_count`` to pusher configuration
453+
self.msc4076_enabled: bool = experimental.get("msc4076_enabled", False)

Diff for: synapse/push/httppusher.py

+11-5
Original file line numberDiff line numberDiff line change
@@ -127,6 +127,11 @@ def __init__(self, hs: "HomeServer", pusher_config: PusherConfig):
127127
if self.data is None:
128128
raise PusherConfigException("'data' key can not be null for HTTP pusher")
129129

130+
# Check if badge counts should be disabled for this push gateway
131+
self.disable_badge_count = self.hs.config.experimental.msc4076_enabled and bool(
132+
self.data.get("org.matrix.msc4076.disable_badge_count", False)
133+
)
134+
130135
self.name = "%s/%s/%s" % (
131136
pusher_config.user_name,
132137
pusher_config.app_id,
@@ -461,9 +466,10 @@ async def dispatch_push_event(
461466
content: JsonDict = {
462467
"event_id": event.event_id,
463468
"room_id": event.room_id,
464-
"counts": {"unread": badge},
465469
"prio": priority,
466470
}
471+
if not self.disable_badge_count:
472+
content["counts"] = {"unread": badge}
467473
# event_id_only doesn't include the tweaks, so override them.
468474
tweaks = {}
469475
else:
@@ -478,11 +484,11 @@ async def dispatch_push_event(
478484
"type": event.type,
479485
"sender": event.user_id,
480486
"prio": priority,
481-
"counts": {
482-
"unread": badge,
483-
# 'missed_calls': 2
484-
},
485487
}
488+
if not self.disable_badge_count:
489+
content["counts"] = {
490+
"unread": badge,
491+
}
486492
if event.type == "m.room.member" and event.is_state():
487493
content["membership"] = event.content["membership"]
488494
content["user_is_target"] = event.state_key == self.user_id

Diff for: tests/push/test_http.py

+83-1
Original file line numberDiff line numberDiff line change
@@ -17,9 +17,11 @@
1717
# [This file includes modifications made by New Vector Limited]
1818
#
1919
#
20-
from typing import Any, List, Tuple
20+
from typing import Any, Dict, List, Tuple
2121
from unittest.mock import Mock
2222

23+
from parameterized import parameterized
24+
2325
from twisted.internet.defer import Deferred
2426
from twisted.test.proto_helpers import MemoryReactor
2527

@@ -1085,3 +1087,83 @@ def test_jitter(self) -> None:
10851087
self.pump()
10861088

10871089
self.assertEqual(len(self.push_attempts), 11)
1090+
1091+
@parameterized.expand(
1092+
[
1093+
# Badge count disabled
1094+
(True, True),
1095+
(True, False),
1096+
# Badge count enabled
1097+
(False, True),
1098+
(False, False),
1099+
]
1100+
)
1101+
@override_config({"experimental_features": {"msc4076_enabled": True}})
1102+
def test_msc4076_badge_count(
1103+
self, disable_badge_count: bool, event_id_only: bool
1104+
) -> None:
1105+
# Register the user who gets notified
1106+
user_id = self.register_user("user", "pass")
1107+
access_token = self.login("user", "pass")
1108+
1109+
# Register the user who sends the message
1110+
other_user_id = self.register_user("otheruser", "pass")
1111+
other_access_token = self.login("otheruser", "pass")
1112+
1113+
# Register the pusher with disable_badge_count set to True
1114+
user_tuple = self.get_success(
1115+
self.hs.get_datastores().main.get_user_by_access_token(access_token)
1116+
)
1117+
assert user_tuple is not None
1118+
device_id = user_tuple.device_id
1119+
1120+
# Set the push data dict based on test input parameters
1121+
push_data: Dict[str, Any] = {
1122+
"url": "http://example.com/_matrix/push/v1/notify",
1123+
}
1124+
if disable_badge_count:
1125+
push_data["org.matrix.msc4076.disable_badge_count"] = True
1126+
if event_id_only:
1127+
push_data["format"] = "event_id_only"
1128+
1129+
self.get_success(
1130+
self.hs.get_pusherpool().add_or_update_pusher(
1131+
user_id=user_id,
1132+
device_id=device_id,
1133+
kind="http",
1134+
app_id="m.http",
1135+
app_display_name="HTTP Push Notifications",
1136+
device_display_name="pushy push",
1137+
pushkey="[email protected]",
1138+
lang=None,
1139+
data=push_data,
1140+
)
1141+
)
1142+
1143+
# Create a room
1144+
room = self.helper.create_room_as(user_id, tok=access_token)
1145+
1146+
# The other user joins
1147+
self.helper.join(room=room, user=other_user_id, tok=other_access_token)
1148+
1149+
# The other user sends a message
1150+
self.helper.send(room, body="Hi!", tok=other_access_token)
1151+
1152+
# Advance time a bit, so the pusher will register something has happened
1153+
self.pump()
1154+
1155+
# One push was attempted to be sent
1156+
self.assertEqual(len(self.push_attempts), 1)
1157+
self.assertEqual(
1158+
self.push_attempts[0][1], "http://example.com/_matrix/push/v1/notify"
1159+
)
1160+
1161+
if disable_badge_count:
1162+
# Verify that the notification DOESN'T contain a counts field
1163+
self.assertNotIn("counts", self.push_attempts[0][2]["notification"])
1164+
else:
1165+
# Ensure that the notification DOES contain a counts field
1166+
self.assertIn("counts", self.push_attempts[0][2]["notification"])
1167+
self.assertEqual(
1168+
self.push_attempts[0][2]["notification"]["counts"]["unread"], 1
1169+
)

0 commit comments

Comments
 (0)