diff --git a/src/matrix/Session.js b/src/matrix/Session.js index 2bd93136..c2c2e20a 100644 --- a/src/matrix/Session.js +++ b/src/matrix/Session.js @@ -42,10 +42,11 @@ const PICKLE_KEY = "DEFAULT_KEY"; export class Session { // sessionInfo contains deviceId, userId and homeServer - constructor({clock, storage, hsApi, sessionInfo, olm, olmWorker, cryptoDriver}) { + constructor({clock, storage, hsApi, sessionInfo, olm, olmWorker, cryptoDriver, mediaRepository}) { this._clock = clock; this._storage = storage; this._hsApi = hsApi; + this._mediaRepository = mediaRepository; this._syncInfo = null; this._sessionInfo = sessionInfo; this._rooms = new ObservableMap(); @@ -332,7 +333,8 @@ export class Session { emitCollectionChange: this._roomUpdateCallback, hsApi: this._hsApi, sendScheduler: this._sendScheduler, - pendingEvents, +._hsApi, + mediaRepository: this._mediaRep pendingEvents, user: this._user, createRoomEncryption: this._createRoomEncryption, clock: this._clock diff --git a/src/matrix/SessionContainer.js b/src/matrix/SessionContainer.js index 0de70400..be2c0c72 100644 --- a/src/matrix/SessionContainer.js +++ b/src/matrix/SessionContainer.js @@ -19,6 +19,7 @@ import {ObservableValue} from "../observable/ObservableValue.js"; import {HomeServerApi} from "./net/HomeServerApi.js"; import {Reconnector, ConnectionStatus} from "./net/Reconnector.js"; import {ExponentialRetryDelay} from "./net/ExponentialRetryDelay.js"; +import {MediaRepository} from "./net/MediaRepository.js"; import {HomeServerError, ConnectionError, AbortError} from "./error.js"; import {Sync, SyncStatus} from "./Sync.js"; import {Session} from "./Session.js"; @@ -158,9 +159,16 @@ export class SessionContainer { if (this._workerPromise) { olmWorker = await this._workerPromise; } - this._session = new Session({storage: this._storage, - sessionInfo: filteredSessionInfo, hsApi, olm, - clock: this._clock, olmWorker, cryptoDriver: this._cryptoDriver}); + this._session = new Session({ + storage: this._storage, + sessionInfo: filteredSessionInfo, + hsApi, + olm, + clock: this._clock, + olmWorker, + cryptoDriver: this._cryptoDriver, + mediaRepository: new MediaRepository(sessionInfo.homeServer) + }); await this._session.load(); this._status.set(LoadStatus.SessionSetup); await this._session.beforeFirstSync(isNewLogin); diff --git a/src/matrix/net/HomeServerApi.js b/src/matrix/net/HomeServerApi.js index 955e9548..63d5c830 100644 --- a/src/matrix/net/HomeServerApi.js +++ b/src/matrix/net/HomeServerApi.js @@ -1,5 +1,6 @@ /* Copyright 2020 Bruno Windels +Copyright 2020 The Matrix.org Foundation C.I.C. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. @@ -14,11 +15,8 @@ See the License for the specific language governing permissions and limitations under the License. */ -import { - HomeServerError, - ConnectionError, - AbortError -} from "../error.js"; +import {HomeServerError} from "../error.js"; +import {encodeQueryParams} from "./common.js"; class RequestWrapper { constructor(method, url, requestResult) { @@ -45,18 +43,6 @@ class RequestWrapper { } } -function encodeQueryParams(queryParams) { - return Object.entries(queryParams || {}) - .filter(([, value]) => value !== undefined) - .map(([name, value]) => { - if (typeof value === "object") { - value = JSON.stringify(value); - } - return `${encodeURIComponent(name)}=${encodeURIComponent(value)}`; - }) - .join("&"); -} - export class HomeServerApi { constructor({homeServer, accessToken, request, createTimeout, reconnector}) { // store these both in a closure somehow so it's harder to get at in case of XSS? @@ -66,7 +52,6 @@ export class HomeServerApi { this._requestFn = request; this._createTimeout = createTimeout; this._reconnector = reconnector; - this._mediaRepository = new MediaRepository(homeServer); } _url(csPath) { @@ -196,45 +181,6 @@ export class HomeServerApi { roomKeyForRoomAndSession(version, roomId, sessionId, options = null) { return this._get(`/room_keys/keys/${encodeURIComponent(roomId)}/${encodeURIComponent(sessionId)}`, {version}, null, options); } - - get mediaRepository() { - return this._mediaRepository; - } -} - -class MediaRepository { - constructor(homeserver) { - this._homeserver = homeserver; - } - - mxcUrlThumbnail(url, width, height, method) { - const parts = this._parseMxcUrl(url); - if (parts) { - const [serverName, mediaId] = parts; - const httpUrl = `${this._homeserver}/_matrix/media/r0/thumbnail/${encodeURIComponent(serverName)}/${encodeURIComponent(mediaId)}`; - return httpUrl + "?" + encodeQueryParams({width, height, method}); - } - return null; - } - - mxcUrl(url) { - const parts = this._parseMxcUrl(url); - if (parts) { - const [serverName, mediaId] = parts; - return `${this._homeserver}/_matrix/media/r0/download/${encodeURIComponent(serverName)}/${encodeURIComponent(mediaId)}`; - } else { - return null; - } - } - - _parseMxcUrl(url) { - const prefix = "mxc://"; - if (url.startsWith(prefix)) { - return url.substr(prefix.length).split("/", 2); - } else { - return null; - } - } } export function tests() { diff --git a/src/matrix/net/MediaRepository.js b/src/matrix/net/MediaRepository.js new file mode 100644 index 00000000..63fde496 --- /dev/null +++ b/src/matrix/net/MediaRepository.js @@ -0,0 +1,52 @@ +/* +Copyright 2020 The Matrix.org Foundation C.I.C. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +import {encodeQueryParams} from "./common.js"; + +export class MediaRepository { + constructor(homeserver) { + this._homeserver = homeserver; + } + + mxcUrlThumbnail(url, width, height, method) { + const parts = this._parseMxcUrl(url); + if (parts) { + const [serverName, mediaId] = parts; + const httpUrl = `${this._homeserver}/_matrix/media/r0/thumbnail/${encodeURIComponent(serverName)}/${encodeURIComponent(mediaId)}`; + return httpUrl + "?" + encodeQueryParams({width, height, method}); + } + return null; + } + + mxcUrl(url) { + const parts = this._parseMxcUrl(url); + if (parts) { + const [serverName, mediaId] = parts; + return `${this._homeserver}/_matrix/media/r0/download/${encodeURIComponent(serverName)}/${encodeURIComponent(mediaId)}`; + } else { + return null; + } + } + + _parseMxcUrl(url) { + const prefix = "mxc://"; + if (url.startsWith(prefix)) { + return url.substr(prefix.length).split("/", 2); + } else { + return null; + } + } +} diff --git a/src/matrix/net/common.js b/src/matrix/net/common.js new file mode 100644 index 00000000..c7a06351 --- /dev/null +++ b/src/matrix/net/common.js @@ -0,0 +1,28 @@ +/* +Copyright 2020 Bruno Windels +Copyright 2020 The Matrix.org Foundation C.I.C. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +export function encodeQueryParams(queryParams) { + return Object.entries(queryParams || {}) + .filter(([, value]) => value !== undefined) + .map(([name, value]) => { + if (typeof value === "object") { + value = JSON.stringify(value); + } + return `${encodeURIComponent(name)}=${encodeURIComponent(value)}`; + }) + .join("&"); +} diff --git a/src/matrix/room/Room.js b/src/matrix/room/Room.js index db61aa14..18b5d18c 100644 --- a/src/matrix/room/Room.js +++ b/src/matrix/room/Room.js @@ -31,11 +31,12 @@ import {DecryptionSource} from "../e2ee/common.js"; const EVENT_ENCRYPTED_TYPE = "m.room.encrypted"; export class Room extends EventEmitter { - constructor({roomId, storage, hsApi, emitCollectionChange, sendScheduler, pendingEvents, user, createRoomEncryption, getSyncToken, clock}) { + constructor({roomId, storage, hsApi, mediaRepository, emitCollectionChange, sendScheduler, pendingEvents, user, createRoomEncryption, getSyncToken, clock}) { super(); this._roomId = roomId; this._storage = storage; this._hsApi = hsApi; + this._mediaRepository = mediaRepository; this._summary = new RoomSummary(roomId, user.id); this._fragmentIdComparer = new FragmentIdComparer([]); this._syncWriter = new SyncWriter({roomId, fragmentIdComparer: this._fragmentIdComparer}); @@ -517,7 +518,7 @@ export class Room extends EventEmitter { } get mediaRepository() { - return this._hsApi.mediaRepository; + return this._mediaRepository; } /** @package */