diff --git a/src/domain/RootViewModel.js b/src/domain/RootViewModel.js index d6fdcfa0..d9949c77 100644 --- a/src/domain/RootViewModel.js +++ b/src/domain/RootViewModel.js @@ -105,7 +105,7 @@ export class RootViewModel extends ViewModel { _showLogin(loginToken) { this._setSection(() => { this._loginViewModel = new LoginViewModel(this.childOptions({ - defaultHomeServer: this.platform.config["defaultHomeServer"], + defaultHomeserver: this.platform.config["defaultHomeServer"], createSessionContainer: this._createSessionContainer, ready: sessionContainer => { // we don't want to load the session container again, diff --git a/src/domain/login/LoginViewModel.js b/src/domain/login/LoginViewModel.js index cd75ca87..d0cf9664 100644 --- a/src/domain/login/LoginViewModel.js +++ b/src/domain/login/LoginViewModel.js @@ -24,7 +24,7 @@ import {SessionLoadViewModel} from "../SessionLoadViewModel.js"; export class LoginViewModel extends ViewModel { constructor(options) { super(options); - const {ready, defaultHomeServer, createSessionContainer, loginToken} = options; + const {ready, defaultHomeserver, createSessionContainer, loginToken} = options; this._createSessionContainer = createSessionContainer; this._ready = ready; this._loginToken = loginToken; @@ -35,7 +35,7 @@ export class LoginViewModel extends ViewModel { this._completeSSOLoginViewModel = null; this._loadViewModel = null; this._loadViewModelSubscription = null; - this._homeserver = defaultHomeServer; + this._homeserver = defaultHomeserver; this._errorMessage = ""; this._hideHomeserver = false; this._isBusy = false; @@ -71,7 +71,7 @@ export class LoginViewModel extends ViewModel { this.emitChange("completeSSOLoginViewModel"); } else { - await this.queryHomeServer(); + await this.queryHomeserver(); } } @@ -156,7 +156,7 @@ export class LoginViewModel extends ViewModel { this.emitChange("disposeViewModels"); } - async setHomeServer(newHomeserver) { + async setHomeserver(newHomeserver) { this._homeserver = newHomeserver; // abort ongoing query, if any this._abortQueryOperation = this.disposeTracked(this._abortQueryOperation); @@ -174,13 +174,13 @@ export class LoginViewModel extends ViewModel { } } this._abortHomeserverQueryTimeout = this.disposeTracked(this._abortHomeserverQueryTimeout); - this.queryHomeServer(); + this.queryHomeserver(); } - async queryHomeServer() { this._errorMessage = ""; this.emitChange("errorMessage"); // if query is called before the typing timeout hits (e.g. field lost focus), cancel the timeout so we don't query again. + async queryHomeserver() { this._abortHomeserverQueryTimeout = this.disposeTracked(this._abortHomeserverQueryTimeout); // cancel ongoing query operation, if any this._abortQueryOperation = this.disposeTracked(this._abortQueryOperation); diff --git a/src/domain/login/PasswordLoginViewModel.js b/src/domain/login/PasswordLoginViewModel.js index f8d354a4..7ea239e6 100644 --- a/src/domain/login/PasswordLoginViewModel.js +++ b/src/domain/login/PasswordLoginViewModel.js @@ -43,15 +43,14 @@ export class PasswordLoginViewModel extends ViewModel { async login(username, password) { this._errorMessage = ""; this.emitChange("errorMessage"); - const loginMethod = this._loginOptions.password(username, password); - const status = await this._attemptLogin(loginMethod); + const status = await this._attemptLogin(this._loginOptions.password(username, password)); let error = ""; switch (status) { case LoginFailure.Credentials: error = this.i18n`Your username and/or password don't seem to be correct.`; break; case LoginFailure.Connection: - error = this.i18n`Can't connect to ${loginMethod.homeServer}.`; + error = this.i18n`Can't connect to ${this._loginOptions.homeserver}.`; break; case LoginFailure.Unknown: error = this.i18n`Something went wrong while checking your login and password.`; diff --git a/src/domain/session/settings/SettingsViewModel.js b/src/domain/session/settings/SettingsViewModel.js index 221e39da..7120f5fb 100644 --- a/src/domain/session/settings/SettingsViewModel.js +++ b/src/domain/session/settings/SettingsViewModel.js @@ -151,7 +151,7 @@ export class SettingsViewModel extends ViewModel { this.pushNotifications.enabledOnServer = null; this.pushNotifications.serverError = null; try { - this.pushNotifications.enabledOnServer = await this._session.checkPusherEnabledOnHomeServer(); + this.pushNotifications.enabledOnServer = await this._session.checkPusherEnabledOnHomeserver(); this.emitChange("pushNotifications.enabledOnServer"); } catch (err) { this.pushNotifications.serverError = err; diff --git a/src/matrix/Session.js b/src/matrix/Session.js index 5a046117..63aece42 100644 --- a/src/matrix/Session.js +++ b/src/matrix/Session.js @@ -46,7 +46,7 @@ const PICKLE_KEY = "DEFAULT_KEY"; const PUSHER_KEY = "pusher"; export class Session { - // sessionInfo contains deviceId, userId and homeServer + // sessionInfo contains deviceId, userId and homeserver constructor({storage, hsApi, sessionInfo, olm, olmWorker, platform, mediaRepository}) { this._platform = platform; this._storage = storage; @@ -636,7 +636,7 @@ export class Session { return !!pusherData; } - async checkPusherEnabledOnHomeServer() { + async checkPusherEnabledOnHomeserver() { const readTxn = await this._storage.readTxn([this._storage.storeNames.session]); const pusherData = await readTxn.session.get(PUSHER_KEY); if (!pusherData) { diff --git a/src/matrix/SessionContainer.js b/src/matrix/SessionContainer.js index 7233eeb0..f375fdd7 100644 --- a/src/matrix/SessionContainer.js +++ b/src/matrix/SessionContainer.js @@ -16,7 +16,7 @@ limitations under the License. */ import {createEnum} from "../utils/enum.js"; -import {lookupHomeServer} from "./well-known.js"; +import {lookupHomeserver} from "./well-known.js"; import {AbortableOperation} from "../utils/AbortableOperation"; import {ObservableValue} from "../observable/ObservableValue.js"; import {HomeServerApi} from "./net/HomeServerApi.js"; @@ -30,24 +30,6 @@ import {PasswordLoginMethod} from "./login/PasswordLoginMethod.js"; import {TokenLoginMethod} from "./login/TokenLoginMethod.js"; import {SSOLoginHelper} from "./login/SSOLoginHelper.js"; -function normalizeHomeserver(homeServer) { - try { - return new URL(homeServer).origin; - } catch (err) { - return new URL(`https://${homeServer}`).origin; - } -} - -function getRetryHomeServer(homeServer) { - const url = new URL(homeServer); - const {host} = url; - const dotCount = host.split(".").length - 1; - if (dotCount === 1) { - url.host = `www.${host}`; - return url.origin; - } -} - export const LoadStatus = createEnum( "NotLoading", "Login", @@ -66,7 +48,6 @@ export const LoginFailure = createEnum( "Unknown", ); - export class SessionContainer { constructor({platform, olmPromise, workerPromise}) { this._platform = platform; @@ -114,35 +95,35 @@ export class SessionContainer { }); } - _parseLoginOptions(options, homeServer) { + _parseLoginOptions(options, homeserver) { /* Take server response and return new object which has two props password and sso which implements LoginMethod */ const flows = options.flows; - const result = {homeServer}; + const result = {homeserver}; for (const flow of flows) { if (flow.type === "m.login.password") { - result.password = (username, password) => new PasswordLoginMethod({homeServer, username, password}); + result.password = (username, password) => new PasswordLoginMethod({homeserver, username, password}); } else if (flow.type === "m.login.sso" && flows.find(flow => flow.type === "m.login.token")) { - result.sso = new SSOLoginHelper(homeServer); + result.sso = new SSOLoginHelper(homeserver); } else if (flow.type === "m.login.token") { - result.token = loginToken => new TokenLoginMethod({homeServer, loginToken}); + result.token = loginToken => new TokenLoginMethod({homeserver, loginToken}); } } return result; } - queryLogin(homeServer) { + queryLogin(homeserver) { return new AbortableOperation(async setAbortable => { - homeServer = await lookupHomeServer(homeServer, (url, options) => { + homeserver = await lookupHomeserver(homeserver, (url, options) => { return setAbortable(this._platform.request(url, options)); }); - const hsApi = new HomeServerApi({homeServer, request: this._platform.request}); + const hsApi = new HomeServerApi({homeserver, request: this._platform.request}); const response = await setAbortable(hsApi.getLoginFlows()).response(); - return this._parseLoginOptions(response, homeServer); + return this._parseLoginOptions(response, homeserver); }); } @@ -160,14 +141,15 @@ export class SessionContainer { let sessionInfo; try { const request = this._platform.request; - const hsApi = new HomeServerApi({homeServer: loginMethod.homeServer, request}); + const hsApi = new HomeServerApi({homeserver: loginMethod.homeserver, request}); const loginData = await loginMethod.login(hsApi, "Hydrogen", log); const sessionId = this.createNewSessionId(); sessionInfo = { id: sessionId, deviceId: loginData.device_id, userId: loginData.user_id, - homeServer: loginMethod.homeServer, + homeServer: loginMethod.homeserver, // deprecate this over time + homeserver: loginMethod.homeserver, accessToken: loginData.access_token, lastUsed: clock.now() }; @@ -216,7 +198,7 @@ export class SessionContainer { createMeasure: clock.createMeasure }); const hsApi = new HomeServerApi({ - homeServer: sessionInfo.homeServer, + homeserver: sessionInfo.homeServer, accessToken: sessionInfo.accessToken, request: this._platform.request, reconnector: this._reconnector, @@ -228,7 +210,7 @@ export class SessionContainer { id: sessionInfo.id, deviceId: sessionInfo.deviceId, userId: sessionInfo.userId, - homeServer: sessionInfo.homeServer, + homeserver: sessionInfo.homeServer, }; const olm = await this._olmPromise; let olmWorker = null; @@ -238,7 +220,7 @@ export class SessionContainer { this._requestScheduler = new RequestScheduler({hsApi, clock}); this._requestScheduler.start(); const mediaRepository = new MediaRepository({ - homeServer: sessionInfo.homeServer, + homeserver: sessionInfo.homeServer, platform: this._platform, }); this._session = new Session({ diff --git a/src/matrix/login/LoginMethod.js b/src/matrix/login/LoginMethod.js index fee8e845..ece18871 100644 --- a/src/matrix/login/LoginMethod.js +++ b/src/matrix/login/LoginMethod.js @@ -15,8 +15,8 @@ limitations under the License. */ export class LoginMethod { - constructor({homeServer}) { - this.homeServer = homeServer; + constructor({homeserver}) { + this.homeserver = homeserver; } // eslint-disable-next-line no-unused-vars diff --git a/src/matrix/net/HomeServerApi.js b/src/matrix/net/HomeServerApi.js index 8641e374..4b53b28b 100644 --- a/src/matrix/net/HomeServerApi.js +++ b/src/matrix/net/HomeServerApi.js @@ -19,10 +19,10 @@ import {encodeQueryParams, encodeBody} from "./common.js"; import {HomeServerRequest} from "./HomeServerRequest.js"; export class HomeServerApi { - constructor({homeServer, accessToken, request, reconnector}) { + constructor({homeserver, accessToken, request, reconnector}) { // store these both in a closure somehow so it's harder to get at in case of XSS? // one could change the homeserver as well so the token gets sent there, so both must be protected from read/write - this._homeserver = homeServer; + this._homeserver = homeserver; this._accessToken = accessToken; this._requestFn = request; this._reconnector = reconnector; @@ -234,7 +234,7 @@ export function tests() { "superficial happy path for GET": async assert => { const hsApi = new HomeServerApi({ request: () => new MockRequest().respond(200, 42), - homeServer: "https://hs.tld" + homeserver: "https://hs.tld" }); const result = await hsApi._get("foo", null, null, null).response(); assert.strictEqual(result, 42); diff --git a/src/matrix/net/MediaRepository.js b/src/matrix/net/MediaRepository.js index f7e47cfd..3f718c85 100644 --- a/src/matrix/net/MediaRepository.js +++ b/src/matrix/net/MediaRepository.js @@ -18,8 +18,8 @@ import {encodeQueryParams} from "./common.js"; import {decryptAttachment} from "../e2ee/attachment.js"; export class MediaRepository { - constructor({homeServer, platform}) { - this._homeServer = homeServer; + constructor({homeserver, platform}) { + this._homeserver = homeserver; this._platform = platform; } @@ -27,7 +27,7 @@ export class MediaRepository { const parts = this._parseMxcUrl(url); if (parts) { const [serverName, mediaId] = parts; - const httpUrl = `${this._homeServer}/_matrix/media/r0/thumbnail/${encodeURIComponent(serverName)}/${encodeURIComponent(mediaId)}`; + const httpUrl = `${this._homeserver}/_matrix/media/r0/thumbnail/${encodeURIComponent(serverName)}/${encodeURIComponent(mediaId)}`; return httpUrl + "?" + encodeQueryParams({width: Math.round(width), height: Math.round(height), method}); } return null; @@ -37,7 +37,7 @@ export class MediaRepository { const parts = this._parseMxcUrl(url); if (parts) { const [serverName, mediaId] = parts; - return `${this._homeServer}/_matrix/media/r0/download/${encodeURIComponent(serverName)}/${encodeURIComponent(mediaId)}`; + return `${this._homeserver}/_matrix/media/r0/download/${encodeURIComponent(serverName)}/${encodeURIComponent(mediaId)}`; } else { return null; } diff --git a/src/matrix/well-known.js b/src/matrix/well-known.js index a33a734a..1217c43e 100644 --- a/src/matrix/well-known.js +++ b/src/matrix/well-known.js @@ -14,16 +14,16 @@ See the License for the specific language governing permissions and limitations under the License. */ -function normalizeHomeserver(homeServer) { +function normalizeHomeserver(homeserver) { try { - return new URL(homeServer).origin; + return new URL(homeserver).origin; } catch (err) { - return new URL(`https://${homeServer}`).origin; + return new URL(`https://${homeserver}`).origin; } } -function getRetryHomeServer(homeServer) { - const url = new URL(homeServer); +function getRetryHomeserver(homeserver) { + const url = new URL(homeserver); const {host} = url; const dotCount = host.split(".").length - 1; if (dotCount === 1) { @@ -32,33 +32,33 @@ function getRetryHomeServer(homeServer) { } } -export async function lookupHomeServer(homeServer, request) { - homeServer = normalizeHomeserver(homeServer); - const requestOptions = {format: "json", timeout: 30000, method: "GET"}; - let wellKnownResponse = null; - while (!wellKnownResponse) { - try { - const wellKnownUrl = `${homeServer}/.well-known/matrix/client`; - wellKnownResponse = await request(wellKnownUrl, requestOptions).response(); - } catch (err) { - if (err.name === "ConnectionError") { - const retryHS = getRetryHomeServer(homeServer); - if (retryHS) { - homeServer = retryHS; - } else { - throw err; - } +export async function lookupHomeserver(homeserver, request) { + homeserver = normalizeHomeserver(homeserver); + const requestOptions = {format: "json", timeout: 30000, method: "GET"}; + let wellKnownResponse = null; + while (!wellKnownResponse) { + try { + const wellKnownUrl = `${homeserver}/.well-known/matrix/client`; + wellKnownResponse = await request(wellKnownUrl, requestOptions).response(); + } catch (err) { + if (err.name === "ConnectionError") { + const retryHS = getRetryHomeserver(homeserver); + if (retryHS) { + homeserver = retryHS; } else { throw err; } + } else { + throw err; } } - if (wellKnownResponse.status === 200) { - const {body} = wellKnownResponse; - const wellKnownHomeServer = body["m.homeserver"]?.["base_url"]; - if (typeof wellKnownHomeServer === "string") { - homeServer = normalizeHomeserver(wellKnownHomeServer); - } + } + if (wellKnownResponse.status === 200) { + const {body} = wellKnownResponse; + const wellKnownHomeserver = body["m.homeserver"]?.["base_url"]; + if (typeof wellKnownHomeserver === "string") { + homeserver = normalizeHomeserver(wellKnownHomeserver); } - return homeServer + } + return homeserver; } diff --git a/src/platform/web/ui/login/LoginView.js b/src/platform/web/ui/login/LoginView.js index 498cb574..4e4f1061 100644 --- a/src/platform/web/ui/login/LoginView.js +++ b/src/platform/web/ui/login/LoginView.js @@ -43,8 +43,8 @@ export class LoginView extends TemplateView { placeholder: vm.i18n`Your matrix homeserver`, value: vm.homeserver, disabled, - onInput: () => vm.setHomeServer(event.target.value), - onChange: event => vm.queryHomeServer(), + onInput: event => vm.setHomeserver(event.target.value), + onChange: () => vm.queryHomeserver(), }), t.if(vm => vm.errorMessage, (t, vm) => t.p({className: "error"}, vm.i18n(vm.errorMessage))), ] diff --git a/src/platform/web/ui/view-gallery.html b/src/platform/web/ui/view-gallery.html index 7887d44f..675b2b5b 100644 --- a/src/platform/web/ui/view-gallery.html +++ b/src/platform/web/ui/view-gallery.html @@ -43,7 +43,7 @@