/* * Copyright (C) 2022 Kristóf Marussy * * This file is part of Sophie. * * Sophie is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as * published by the Free Software Foundation, version 3. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Affero General Public License for more details. * * You should have received a copy of the GNU Affero General Public License * along with this program. If not, see . * * SPDX-License-Identifier: AGPL-3.0-only */ import { BrowserViewBounds, defineServiceModel, ServiceAction, } from '@sophie/shared'; import { Instance } from 'mobx-state-tree'; import { getEnv } from './RendererEnv'; import ServiceSettings from './ServiceSettings'; const Service = defineServiceModel(ServiceSettings) .views((self) => ({ get canReconnectSecurely(): boolean { const { currentUrl } = self; if (currentUrl === undefined) { return false; } try { const { protocol } = new URL(currentUrl); return protocol === 'http:'; } catch { return false; } }, })) .actions((self) => { function dispatch(serviceAction: ServiceAction): void { getEnv(self).dispatchMainAction({ action: 'dispatch-service-action', serviceId: self.id, serviceAction, }); } return { setBrowserViewBounds(browserViewBounds: BrowserViewBounds): void { dispatch({ action: 'set-browser-view-bounds', browserViewBounds, }); }, goBack(): void { dispatch({ action: 'back', }); }, goForward(): void { dispatch({ action: 'forward', }); }, reload(ignoreCache = false): void { dispatch({ action: 'reload', ignoreCache, }); }, stop(): void { dispatch({ action: 'stop', }); }, go(url: string): void { dispatch({ action: 'go', url, }); }, goHome(): void { dispatch({ action: 'go-home', }); }, temporarilyTrustCurrentCertificate(): void { if (self.state.type !== 'certificateError') { throw new Error('No certificate to accept'); } dispatch({ action: 'temporarily-trust-current-certificate', fingerprint: self.state.certificate.fingerprint, }); }, openCurrentURLInExternalBrowser(): void { dispatch({ action: 'open-current-url-in-external-browser', }); }, followPopup(url: string): void { dispatch({ action: 'follow-popup', url, }); }, openPopupInExternalBrowser(url: string): void { dispatch({ action: 'open-popup-in-external-browser', url, }); }, openAllPopupsInExternalBrowser(): void { dispatch({ action: 'open-all-popups-in-external-browser', }); }, dismissPopup(url: string): void { dispatch({ action: 'dismiss-popup', url, }); }, dismissAllPopups(): void { dispatch({ action: 'dismiss-all-popups', }); }, downloadCertificate(fingerprint: string): void { dispatch({ action: 'download-certificate', fingerprint, }); }, }; }) .actions((self) => ({ reconnectSecurely(): void { const { currentUrl, canReconnectSecurely } = self; if (currentUrl === undefined || !canReconnectSecurely) { return; } const url = new URL(currentUrl); url.protocol = 'https:'; self.go(url.toString()); }, })); /* eslint-disable-next-line @typescript-eslint/no-redeclare -- Intentionally naming the type the same as the store definition. */ interface Service extends Instance {} export default Service;