Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion src/matrix/Session.js
Original file line number Diff line number Diff line change
Expand Up @@ -946,7 +946,7 @@ export class Session {
async _enablePush() {
return this._platform.logger.run("enablePush", async log => {
const defaultPayload = Pusher.createDefaultPayload(this._sessionInfo.id);
const pusher = await this._platform.notificationService.enablePush(Pusher, defaultPayload);
const pusher = await this._platform.notificationService.enablePush(Pusher, defaultPayload, this._hsApi);
if (!pusher) {
log.set("no_pusher", true);
return false;
Expand Down
4 changes: 4 additions & 0 deletions src/matrix/net/HomeServerApi.ts
Original file line number Diff line number Diff line change
Expand Up @@ -223,6 +223,10 @@ export class HomeServerApi {
return this._unauthedRequest("GET", `${this._homeserver}/_matrix/client/versions`, undefined, undefined, options);
}

capabilities(options?: BaseRequestOptions): IHomeServerRequest {
return this._get("/capabilities", undefined, undefined, options);
}

uploadKeys(dehydratedDeviceId: string, payload: Record<string, any>, options?: BaseRequestOptions): IHomeServerRequest {
let path = "/keys/upload";
if (dehydratedDeviceId) {
Expand Down
13 changes: 13 additions & 0 deletions src/matrix/push/Pusher.ts
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,19 @@ export class Pusher {
});
}

static webpushPusher(appId: string, pushkey: string, data: IPusherData): Pusher {
return new Pusher({
kind: "webpush",
append: true, // as pushkeys are shared between multiple users on one origin
data,
pushkey,
app_id: appId,
app_display_name: "Hydrogen",
device_display_name: "Hydrogen",
lang: "en"
});
}

static createDefaultPayload(sessionId: string): {session_id: string} {
return {session_id: sessionId};
}
Expand Down
36 changes: 28 additions & 8 deletions src/platform/web/dom/NotificationService.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,12 +20,24 @@ export class NotificationService {
this._pushConfig = pushConfig;
}

async enablePush(pusherFactory, defaultPayload) {
async enablePush(pusherFactory, defaultPayload, hsApi) {
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does this code handle the 201 response code that the MSC asks for?

If the request creates a new pusher or modifies values under pushkey , PusherData.url, or PusherData.auth, then the server MUST respond with 201, ...

as well as handling the subsequent validation push containing app_id and ack_token?

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We seem to also be missing the bit where the client calls POST /_matrix/client/v3/pushers/ack after receiving the validation push.

The client needs to handle the new M_EXPIRED_ACTIVATION_TOKEN and M_UNKNOWN_ACTIVATION_TOKEN error types.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

To be done on the SW 👍

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

SW?

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

service worker

const registration = await this._serviceWorkerHandler?.getRegistration();
if (registration?.pushManager) {
const response = await hsApi.capabilities().response();
var webPushCapability = response?.capabilities?.["m.webpush"]
if (!webPushCapability)
webPushCapability = response?.capabilities?.["org.matrix.msc4174.webpush"]

var supportDirectWebPush = false;
var applicationServerKey = this._pushConfig.applicationServerKey
if (webPushCapability && webPushCapability?.enabled == true) {
supportDirectWebPush = true;
applicationServerKey = webPushCapability?.vapid
}

const subscription = await registration.pushManager.subscribe({
userVisibleOnly: true,
applicationServerKey: this._pushConfig.applicationServerKey,
applicationServerKey: applicationServerKey,
});
const subscriptionData = subscription.toJSON();
const pushkey = subscriptionData.keys.p256dh;
Expand All @@ -37,12 +49,20 @@ export class NotificationService {
events_only: true,
default_payload: defaultPayload
};
return pusherFactory.httpPusher(
this._pushConfig.gatewayUrl,
this._pushConfig.appId,
pushkey,
data
);
if (supportDirectWebPush) {
return pusherFactory.webpushPusher(
this._pushConfig.appId,
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
this._pushConfig.appId,
subscriptionData.endpoint,
this._pushConfig.appId,

pushkey,
data
);
} else {
return pusherFactory.httpPusher(
this._pushConfig.gatewayUrl,
this._pushConfig.appId,
pushkey,
data
);
}
}
}

Expand Down