lsa-planer

LSA-Planer Professional – Planungssoftware für Lichtsignalanlagen nach RiLSA 2015 und § 45 StVO. EUPL-1.2.

/ electron navigation.ts

3,2 KB Rohdatei
electron/navigation.ts — 75 Zeilen
1 /**
2 * Was mit einer Navigation geschehen soll, die das Fenster verlassen will.
3 *
4 * WARUM DAS HIER STEHT UND NICHT IN `createWindow`. Bis hierher entschieden das
5 * zwei Ereignisbehandlungen mitten in `electron/main.ts`, und zwar in einer
6 * Weise, die von aussen niemand nachlesen konnte:
7 *
8 * - Beschrieben war nur die Haelfte: `will-navigate` breche "jede
9 * Navigation ab", `setWindowOpenHandler` lehne "jedes neue Fenster ab".
10 * Beides stimmt - und beide reichen die Adresse anschliessend an den
11 * Standardbrowser weiter, wenn sie mit `https:` beginnt. Das stand
12 * nirgends.
13 * - Der Kartenabruf galt als "Einzige Ausnahme" vom Grundsatz, dass das
14 * Programm nicht ins Netz geht. Der Weg ueber den Browser ist eine zweite.
15 * - `vitest.config.ts` begruendete die Abdeckungsluecke in `electron/main.ts`
16 * damit, genau diese Behandlungen pruefe der Rauchtest am gebauten Stand.
17 * GEMESSEN: `e2e/rauchtest.spec.ts` hat sechs Faelle und nennt weder
18 * `will-navigate` noch `setWindowOpenHandler`; das Wort "navigate" kommt
19 * dort ueberhaupt nicht vor. Eine Abdeckungsausnahme, gedeckt von einem
20 * Test, den es nicht gab.
21 *
22 * Als reine Funktion laesst sich die Entscheidung erschoepfend pruefen, ohne
23 * ein Fenster zu oeffnen und ohne einen Browser zu starten. Die beiden
24 * Behandlungen in `main.ts` tun danach nur noch, was die Entscheidung sagt.
25 */
26
27 /** Was mit einer Adresse geschehen soll. */
28 export type Navigationsentscheidung =
29 /** Im eigenen Fenster laden - allein die geladene `index.html`. */
30 | 'laden'
31 /** Abbrechen und sonst nichts. */
32 | 'abbrechen'
33 /** Abbrechen und dem Betriebssystem uebergeben. */
34 | 'extern';
35
36 /**
37 * Darf diese Adresse geladen, muss sie abgebrochen oder nach draussen gegeben
38 * werden?
39 *
40 * `erlaubt` ist die Adresse der geladenen `index.html` als Zeichenkette - der
41 * einzige Ort, den das Fenster selbst anzeigen darf.
42 *
43 * DIE REIHENFOLGE DER PRUEFUNGEN IST DIE SICHERHEITSRICHTUNG: Erst der
44 * Vergleich auf Gleichheit, dann alles Uebrige. Wer zuerst nach `https:`
45 * fragte, gaebe eine Adresse nach draussen, die vielleicht die eigene ist.
46 */
47 export function entscheideNavigation(adresse: string, erlaubt: string): Navigationsentscheidung {
48 let ziel: URL;
49 try {
50 ziel = new URL(adresse);
51 } catch {
52 /*
53 * Was sich nicht als Adresse lesen laesst, wird abgebrochen und NICHT
54 * weitergereicht. `shell.openExternal` gibt die Zeichenkette an das
55 * Betriebssystem; was Windows aus etwas Unlesbarem macht, entscheidet dann
56 * nicht mehr dieses Programm.
57 */
58 return 'abbrechen';
59 }
60
61 if (ziel.toString() === erlaubt) return 'laden';
62
63 /*
64 * NUR `https:` GEHT NACH DRAUSSEN. Nicht `http:` - eine unverschluesselte
65 * Adresse aus einer fremden Datei ist ein Weg, Daten unbemerkt abfliessen zu
66 * lassen. Nicht `file:` - das oeffnete ein beliebiges Programm mit einer
67 * beliebigen Datei. Nicht `javascript:`, nicht `data:`. Die Pruefung fragt
68 * das Protokoll der ausgewerteten Adresse und nicht den Anfang der
69 * Zeichenkette: `startsWith('https://')` traefe auch
70 * "https://example.com\\@boeses.example" anders als der Auswerter.
71 */
72 if (ziel.protocol === 'https:') return 'extern';
73
74 return 'abbrechen';
75 }