mirror of
https://github.com/vector-im/hydrogen-web.git
synced 2024-11-20 03:25:52 +01:00
Add access-token to request
This commit is contained in:
parent
841ed2527c
commit
53b8a2f4d0
@ -146,8 +146,13 @@ export class Platform {
|
||||
this.onlineStatus = new OnlineStatus();
|
||||
this.timeFormatter = new TimeFormatter();
|
||||
this._serviceWorkerHandler = null;
|
||||
this.sessionInfoStorage = new SessionInfoStorage(
|
||||
"hydrogen_sessions_v1"
|
||||
);
|
||||
if (assetPaths.serviceWorker && "serviceWorker" in navigator) {
|
||||
this._serviceWorkerHandler = new ServiceWorkerHandler();
|
||||
this._serviceWorkerHandler = new ServiceWorkerHandler(
|
||||
this.sessionInfoStorage
|
||||
);
|
||||
this._serviceWorkerHandler.registerAndStart(assetPaths.serviceWorker);
|
||||
}
|
||||
this.notificationService = undefined;
|
||||
@ -156,7 +161,6 @@ export class Platform {
|
||||
this.crypto = new Crypto(cryptoExtras);
|
||||
}
|
||||
this.storageFactory = new StorageFactory(this._serviceWorkerHandler);
|
||||
this.sessionInfoStorage = new SessionInfoStorage("hydrogen_sessions_v1");
|
||||
this.estimateStorageUsage = estimateStorageUsage;
|
||||
if (typeof fetch === "function") {
|
||||
this.request = createFetchRequest(this.clock.createTimeout, this._serviceWorkerHandler);
|
||||
|
@ -19,13 +19,14 @@ limitations under the License.
|
||||
// - UpdateService (see checkForUpdate method, and should also emit events rather than showing confirm dialog here)
|
||||
// - ConcurrentAccessBlocker (see preventConcurrentSessionAccess method)
|
||||
export class ServiceWorkerHandler {
|
||||
constructor() {
|
||||
constructor(sessionInfoStorage) {
|
||||
this._waitingForReply = new Map();
|
||||
this._messageIdCounter = 0;
|
||||
this._navigation = null;
|
||||
this._registration = null;
|
||||
this._registrationPromise = null;
|
||||
this._currentController = null;
|
||||
this._sessionInfoStorage = sessionInfoStorage;
|
||||
this.haltRequests = false;
|
||||
}
|
||||
|
||||
@ -50,8 +51,8 @@ export class ServiceWorkerHandler {
|
||||
})();
|
||||
}
|
||||
|
||||
_onMessage(event) {
|
||||
const {data} = event;
|
||||
async _onMessage(event) {
|
||||
const { data } = event;
|
||||
const replyTo = data.replyTo;
|
||||
if (replyTo) {
|
||||
const resolve = this._waitingForReply.get(replyTo);
|
||||
@ -61,37 +62,63 @@ export class ServiceWorkerHandler {
|
||||
}
|
||||
}
|
||||
if (data.type === "hasSessionOpen") {
|
||||
const hasOpen = this._navigation.observe("session").get() === data.payload.sessionId;
|
||||
event.source.postMessage({replyTo: data.id, payload: hasOpen});
|
||||
const hasOpen =
|
||||
this._navigation.observe("session").get() ===
|
||||
data.payload.sessionId;
|
||||
event.source.postMessage({ replyTo: data.id, payload: hasOpen });
|
||||
} else if (data.type === "hasRoomOpen") {
|
||||
const hasSessionOpen = this._navigation.observe("session").get() === data.payload.sessionId;
|
||||
const hasRoomOpen = this._navigation.observe("room").get() === data.payload.roomId;
|
||||
event.source.postMessage({replyTo: data.id, payload: hasSessionOpen && hasRoomOpen});
|
||||
const hasSessionOpen =
|
||||
this._navigation.observe("session").get() ===
|
||||
data.payload.sessionId;
|
||||
const hasRoomOpen =
|
||||
this._navigation.observe("room").get() === data.payload.roomId;
|
||||
event.source.postMessage({
|
||||
replyTo: data.id,
|
||||
payload: hasSessionOpen && hasRoomOpen,
|
||||
});
|
||||
} else if (data.type === "closeSession") {
|
||||
const {sessionId} = data.payload;
|
||||
const { sessionId } = data.payload;
|
||||
this._closeSessionIfNeeded(sessionId).finally(() => {
|
||||
event.source.postMessage({replyTo: data.id});
|
||||
event.source.postMessage({ replyTo: data.id });
|
||||
});
|
||||
} else if (data.type === "haltRequests") {
|
||||
// this flag is read in fetch.js
|
||||
this.haltRequests = true;
|
||||
event.source.postMessage({replyTo: data.id});
|
||||
event.source.postMessage({ replyTo: data.id });
|
||||
} else if (data.type === "openRoom") {
|
||||
this._navigation.push("room", data.payload.roomId);
|
||||
} else if (data.type === "getAccessToken") {
|
||||
const token = await this._getLatestAccessToken();
|
||||
event.source.postMessage({ replyTo: data.id, payload: token });
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetch access-token from the storage
|
||||
* @returns access token as string
|
||||
*/
|
||||
async _getLatestAccessToken() {
|
||||
const currentSessionId = this._navigation?.path.get("session")?.value;
|
||||
if (!currentSessionId) return null;
|
||||
const { accessToken } = await this._sessionInfoStorage.get(
|
||||
currentSessionId
|
||||
);
|
||||
return accessToken;
|
||||
}
|
||||
|
||||
_closeSessionIfNeeded(sessionId) {
|
||||
const currentSession = this._navigation?.path.get("session");
|
||||
if (sessionId && currentSession?.value === sessionId) {
|
||||
return new Promise(resolve => {
|
||||
const unsubscribe = this._navigation.pathObservable.subscribe(path => {
|
||||
const session = path.get("session");
|
||||
if (!session || session.value !== sessionId) {
|
||||
unsubscribe();
|
||||
resolve();
|
||||
return new Promise((resolve) => {
|
||||
const unsubscribe = this._navigation.pathObservable.subscribe(
|
||||
(path) => {
|
||||
const session = path.get("session");
|
||||
if (!session || session.value !== sessionId) {
|
||||
unsubscribe();
|
||||
resolve();
|
||||
}
|
||||
}
|
||||
});
|
||||
);
|
||||
this._navigation.push("session");
|
||||
});
|
||||
} else {
|
||||
@ -135,7 +162,10 @@ export class ServiceWorkerHandler {
|
||||
this._onMessage(event);
|
||||
break;
|
||||
case "updatefound":
|
||||
this._registration.installing.addEventListener("statechange", this);
|
||||
this._registration.installing.addEventListener(
|
||||
"statechange",
|
||||
this
|
||||
);
|
||||
break;
|
||||
case "statechange": {
|
||||
if (event.target.state === "installed") {
|
||||
@ -149,10 +179,11 @@ export class ServiceWorkerHandler {
|
||||
// Clients.claim() in the SW can trigger a controllerchange event
|
||||
// if we had no SW before. This is fine,
|
||||
// and now our requests will be served from the SW.
|
||||
this._currentController = navigator.serviceWorker.controller;
|
||||
this._currentController =
|
||||
navigator.serviceWorker.controller;
|
||||
} else {
|
||||
// active service worker changed,
|
||||
// refresh, so we can get all assets
|
||||
// refresh, so we can get all assets
|
||||
// (and not only some if we would not refresh)
|
||||
// up to date from it
|
||||
document.location.reload();
|
||||
@ -168,7 +199,7 @@ export class ServiceWorkerHandler {
|
||||
if (!worker) {
|
||||
worker = this._registration.active;
|
||||
}
|
||||
worker.postMessage({type, payload});
|
||||
worker.postMessage({ type, payload });
|
||||
}
|
||||
|
||||
async _sendAndWaitForReply(type, payload, worker = undefined) {
|
||||
@ -180,10 +211,10 @@ export class ServiceWorkerHandler {
|
||||
}
|
||||
this._messageIdCounter += 1;
|
||||
const id = this._messageIdCounter;
|
||||
const promise = new Promise(resolve => {
|
||||
const promise = new Promise((resolve) => {
|
||||
this._waitingForReply.set(id, resolve);
|
||||
});
|
||||
worker.postMessage({type, id, payload});
|
||||
worker.postMessage({ type, id, payload });
|
||||
return await promise;
|
||||
}
|
||||
|
||||
@ -203,7 +234,7 @@ export class ServiceWorkerHandler {
|
||||
}
|
||||
|
||||
async preventConcurrentSessionAccess(sessionId) {
|
||||
return this._sendAndWaitForReply("closeSession", {sessionId});
|
||||
return this._sendAndWaitForReply("closeSession", { sessionId });
|
||||
}
|
||||
|
||||
async getRegistration() {
|
||||
|
@ -83,12 +83,15 @@ self.addEventListener("fetch", (event) => {
|
||||
This has to do with xhr not being supported in service workers.
|
||||
*/
|
||||
if (event.request.method === "GET") {
|
||||
event.respondWith(handleRequest(event.request));
|
||||
event.respondWith(handleRequest(event));
|
||||
}
|
||||
});
|
||||
|
||||
function isCacheableThumbnail(url) {
|
||||
if (url.pathname.startsWith("/_matrix/media/r0/thumbnail/")) {
|
||||
if (
|
||||
url.pathname.startsWith("/_matrix/media/r0/thumbnail/") ||
|
||||
url.pathname.startsWith("/_matrix/client/v1/media/thumbnail/")
|
||||
) {
|
||||
const width = parseInt(url.searchParams.get("width"), 10);
|
||||
const height = parseInt(url.searchParams.get("height"), 10);
|
||||
if (width <= 50 && height <= 50) {
|
||||
@ -101,22 +104,42 @@ function isCacheableThumbnail(url) {
|
||||
const baseURL = new URL(self.registration.scope);
|
||||
let pendingFetchAbortController = new AbortController();
|
||||
|
||||
async function handleRequest(request) {
|
||||
async function handleRequest({ request, clientId }) {
|
||||
try {
|
||||
// Special caching strategy for config.json and theme json files
|
||||
if (
|
||||
request.url.includes("config.json") ||
|
||||
/theme-.+\.json/.test(request.url)
|
||||
) {
|
||||
return handleStaleWhileRevalidateRequest(request);
|
||||
}
|
||||
const url = new URL(request.url);
|
||||
|
||||
// rewrite / to /index.html so it hits the cache
|
||||
const url = new URL(request.url);
|
||||
if (
|
||||
url.origin === baseURL.origin &&
|
||||
url.pathname === baseURL.pathname
|
||||
) {
|
||||
request = new Request(new URL("index.html", baseURL.href));
|
||||
}
|
||||
|
||||
// Add access token for authenticated media endpoints
|
||||
if (request.url.includes("_matrix/client/v1/media")) {
|
||||
const headers = new Headers(request.headers);
|
||||
const client = await self.clients.get(clientId);
|
||||
const accessToken = await sendAndWaitForReply(
|
||||
client,
|
||||
"getAccessToken",
|
||||
{}
|
||||
);
|
||||
headers.set("authorization", `Bearer ${accessToken}`);
|
||||
request = new Request(request, {
|
||||
mode: "cors",
|
||||
credentials: "omit",
|
||||
headers,
|
||||
});
|
||||
}
|
||||
|
||||
let response = await readCache(request);
|
||||
if (!response) {
|
||||
// use cors so the resource in the cache isn't opaque and uses up to 7mb
|
||||
|
Loading…
Reference in New Issue
Block a user