From d2213e7eba2ec8b478c879397dc0de64d293f367 Mon Sep 17 00:00:00 2001 From: Kristóf Marussy Date: Mon, 14 Mar 2022 17:59:22 +0100 Subject: feat: Temporary certificate acceptance backend MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We use the 'certificate-error' event of webContents to detect certificate verification errors and display a message to manually trust the certificate. Certificates are trusted per profile and only until Sophie is restarted. We still need to build the associated UI, the current one is just a rough prototype for debugging. Signed-off-by: Kristóf Marussy --- packages/renderer/src/components/App.tsx | 64 +++++++++++------ .../src/components/BrowserViewPlaceholder.tsx | 26 ++++--- packages/renderer/src/stores/Service.ts | 84 ++++++++++++---------- 3 files changed, 107 insertions(+), 67 deletions(-) (limited to 'packages/renderer/src') diff --git a/packages/renderer/src/components/App.tsx b/packages/renderer/src/components/App.tsx index af2e4ec..b647a80 100644 --- a/packages/renderer/src/components/App.tsx +++ b/packages/renderer/src/components/App.tsx @@ -19,38 +19,46 @@ */ import Box from '@mui/material/Box'; -import React from 'react'; +import Button from '@mui/material/Button'; +import { observer } from 'mobx-react-lite'; +import React, { useCallback } from 'react'; import BrowserViewPlaceholder from './BrowserViewPlaceholder'; import { useStore } from './StoreProvider'; import LocationBar from './locationBar/LocationBar'; import Sidebar from './sidebar/Sidebar'; -export default function App(): JSX.Element { - const store = useStore(); +function App(): JSX.Element { + const { + settings: { selectedService }, + } = useStore(); - function onClick(event: React.MouseEvent): void { - switch (event.button) { - case 3: - store.settings.selectedService?.goBack(); - break; - case 4: - store.settings.selectedService?.goForward(); - break; - default: - // Allow the event to propagate. - return; - } - event.preventDefault(); - event.stopPropagation(); - } + const handleBackForwardMouseButtons = useCallback( + (event: React.MouseEvent) => { + switch (event.button) { + case 3: + selectedService?.goBack(); + break; + case 4: + selectedService?.goForward(); + break; + default: + // Allow the event to propagate. + return; + } + event.preventDefault(); + event.stopPropagation(); + }, + [selectedService], + ); return ( onClick(event)} - onAuxClick={(event) => onClick(event)} + onClick={handleBackForwardMouseButtons} + onAuxClick={handleBackForwardMouseButtons} sx={{ display: 'flex', + overflow: 'hidden', flexDirection: 'row', alignItems: 'stretch', height: '100vh', @@ -69,8 +77,22 @@ export default function App(): JSX.Element { }} > - + +

{JSON.stringify(selectedService?.state)}

+ {selectedService?.state.type === 'certificateError' && ( + + )} +
); } + +export default observer(App); diff --git a/packages/renderer/src/components/BrowserViewPlaceholder.tsx b/packages/renderer/src/components/BrowserViewPlaceholder.tsx index c07ed15..1f5f9f4 100644 --- a/packages/renderer/src/components/BrowserViewPlaceholder.tsx +++ b/packages/renderer/src/components/BrowserViewPlaceholder.tsx @@ -20,12 +20,15 @@ import Box from '@mui/material/Box'; import throttle from 'lodash-es/throttle'; -import { observer } from 'mobx-react-lite'; -import React, { useCallback, useRef } from 'react'; +import React, { ReactNode, useCallback, useRef } from 'react'; import { useStore } from './StoreProvider'; -export default observer(() => { +function BrowserViewPlaceholder({ + children, +}: { + children?: ReactNode; +}): JSX.Element { const store = useStore(); // eslint-disable-next-line react-hooks/exhaustive-deps -- react-hooks doesn't support `throttle`. @@ -62,11 +65,14 @@ export default observer(() => { ); return ( - + + {children} + ); -}); +} + +BrowserViewPlaceholder.defaultProps = { + children: undefined, +}; + +export default BrowserViewPlaceholder; diff --git a/packages/renderer/src/stores/Service.ts b/packages/renderer/src/stores/Service.ts index 7878ea0..695cff4 100644 --- a/packages/renderer/src/stores/Service.ts +++ b/packages/renderer/src/stores/Service.ts @@ -25,47 +25,59 @@ import getEnv from '../env/getEnv'; import ServiceSettings from './ServiceSettings'; -const Service = defineServiceModel(ServiceSettings).actions((self) => ({ - dispatch(serviceAction: ServiceAction): void { +const Service = defineServiceModel(ServiceSettings).actions((self) => { + function dispatch(serviceAction: ServiceAction): void { getEnv(self).dispatchMainAction({ action: 'dispatch-service-action', serviceId: self.id, serviceAction, }); - }, - goBack(): void { - this.dispatch({ - action: 'back', - }); - }, - goForward(): void { - this.dispatch({ - action: 'forward', - }); - }, - reload(ignoreCache = false): void { - this.dispatch({ - action: 'reload', - ignoreCache, - }); - }, - stop(): void { - this.dispatch({ - action: 'stop', - }); - }, - go(url: string): void { - this.dispatch({ - action: 'go', - url, - }); - }, - goHome(): void { - this.dispatch({ - action: 'go-home', - }); - }, -})); + } + + return { + 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, + }); + }, + }; +}); /* eslint-disable-next-line @typescript-eslint/no-redeclare -- -- cgit v1.2.3-54-g00ecf