Die HoneyBar braucht kein 'unsafe-inline' mehr
Ihre Stile hingen als <style> im Shadow DOM, und Markup faellt unter die CSP der Gastgeber-App: Jede fremde App musste deshalb style-src 'unsafe-inline' erlauben, sonst stand die HoneyBar schwarz auf schwarz da. Jetzt kommen sie als konstruiertes Stylesheet ueber die CSSOM herein, die keine CSP kennt. Damit braucht die App gar keine style-src-Erlaubnis mehr -- auch keine fuer die HoneyOS-Domain, was der geplante Weg ueber eine zweite Datei und <link> gekostet haette, samt zweiter Anfrage. Der Strich zum Wiederausklappen hat seinen eigenen Shadow-Root und geht denselben Weg. Der Rueckfall fuer alte Browser laeuft nach innerHTML, sonst raeumt das Markup ihn gleich wieder weg. Gemessen an einer nachgebauten App mit style-src 'self': Leiste bernstein, 32 px, Strich mit Verlauf, keine CSP-Meldung. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
1 parent
8ca16aec84
commit
3b47003492
4 files changed
+97
-33
No files matched your search
+46
-14
@@ -105,10 +105,37 @@
|
||||
*/
|
||||
const WAPPEN = '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 15 12" shape-rendering="crispEdges" aria-hidden="true"><rect x="4" y="0" width="2" height="1" fill="#f5f2e7"/><rect x="9" y="0" width="2" height="1" fill="#f5f2e7"/><rect x="2" y="1" width="5" height="1" fill="#f5f2e7"/><rect x="8" y="1" width="5" height="1" fill="#f5f2e7"/><rect x="2" y="2" width="11" height="1" fill="#f5f2e7"/><rect x="14" y="2" width="1" height="1" fill="#3b2412"/><rect x="3" y="3" width="9" height="1" fill="#f5f2e7"/><rect x="13" y="3" width="2" height="1" fill="#3b2412"/><rect x="3" y="4" width="11" height="1" fill="#ffd060"/><rect x="2" y="5" width="2" height="1" fill="#f2b33d"/><rect x="4" y="5" width="2" height="1" fill="#5c3a1c"/><rect x="6" y="5" width="2" height="1" fill="#f2b33d"/><rect x="8" y="5" width="2" height="1" fill="#5c3a1c"/><rect x="10" y="5" width="5" height="1" fill="#f2b33d"/><rect x="1" y="6" width="3" height="1" fill="#f2b33d"/><rect x="4" y="6" width="2" height="1" fill="#5c3a1c"/><rect x="6" y="6" width="2" height="1" fill="#f2b33d"/><rect x="8" y="6" width="2" height="1" fill="#5c3a1c"/><rect x="10" y="6" width="2" height="1" fill="#f2b33d"/><rect x="12" y="6" width="1" height="1" fill="#181410"/><rect x="13" y="6" width="1" height="1" fill="#63c7c0"/><rect x="14" y="6" width="1" height="1" fill="#f2b33d"/><rect x="0" y="7" width="1" height="1" fill="#5c3a1c"/><rect x="1" y="7" width="3" height="1" fill="#f2b33d"/><rect x="4" y="7" width="2" height="1" fill="#5c3a1c"/><rect x="6" y="7" width="2" height="1" fill="#f2b33d"/><rect x="8" y="7" width="2" height="1" fill="#5c3a1c"/><rect x="10" y="7" width="2" height="1" fill="#f2b33d"/><rect x="12" y="7" width="2" height="1" fill="#181410"/><rect x="14" y="7" width="1" height="1" fill="#f2b33d"/><rect x="1" y="8" width="3" height="1" fill="#f2b33d"/><rect x="4" y="8" width="2" height="1" fill="#5c3a1c"/><rect x="6" y="8" width="2" height="1" fill="#f2b33d"/><rect x="8" y="8" width="2" height="1" fill="#5c3a1c"/><rect x="10" y="8" width="5" height="1" fill="#f2b33d"/><rect x="2" y="9" width="1" height="1" fill="#d2952a"/><rect x="3" y="9" width="2" height="1" fill="#462b14"/><rect x="5" y="9" width="2" height="1" fill="#d2952a"/><rect x="7" y="9" width="2" height="1" fill="#462b14"/><rect x="9" y="9" width="6" height="1" fill="#d2952a"/><rect x="3" y="10" width="2" height="1" fill="#181410"/><rect x="7" y="10" width="2" height="1" fill="#181410"/><rect x="11" y="10" width="2" height="1" fill="#181410"/><rect x="3" y="11" width="2" height="1" fill="#181410"/><rect x="7" y="11" width="2" height="1" fill="#181410"/><rect x="11" y="11" width="2" height="1" fill="#181410"/></svg>';
|
||||
|
||||
/* ── Stile ohne CSP-Ausnahme ──────────────────────────────────────────────
|
||||
* Die Stile kommen als konstruiertes Stylesheet in den Shadow-Root, nicht
|
||||
* als style-Element. Der Unterschied ist nicht Geschmack, sondern der
|
||||
* ganze Punkt: Ein style-Element ist Markup und faellt damit unter die CSP der
|
||||
* fremden App — die musste deshalb bis hierher style-src 'unsafe-inline'
|
||||
* erlauben, sonst stand die HoneyBar schwarz auf schwarz da. Ueber die
|
||||
* CSSOM gesetzte Stile fallen nicht darunter. So braucht die Gastgeber-App
|
||||
* fuer die HoneyBar gar keine style-src-Erlaubnis mehr, und es bleibt
|
||||
* trotzdem bei einer Datei ohne zweite Anfrage.
|
||||
*
|
||||
* Der Rueckfall ist fuer Browser ohne konstruierbare Stylesheets (vor
|
||||
* Safari 16.4, Firefox 101): Dort steht es wie bisher, also nicht
|
||||
* schlechter — nur eben weiter mit 'unsafe-inline'.
|
||||
*/
|
||||
function stileAnlegen(wurzel, css) {
|
||||
try {
|
||||
const blatt = new CSSStyleSheet();
|
||||
blatt.replaceSync(css);
|
||||
wurzel.adoptedStyleSheets = [blatt];
|
||||
return;
|
||||
} catch {
|
||||
/* alter Browser: unten der Weg ueber das Markup */
|
||||
}
|
||||
const el = document.createElement("style");
|
||||
el.textContent = css;
|
||||
wurzel.appendChild(el);
|
||||
}
|
||||
|
||||
const root = host.attachShadow({ mode: "open" });
|
||||
|
||||
root.innerHTML = `
|
||||
<style>
|
||||
const STIL = `
|
||||
:host, * { box-sizing: border-box; }
|
||||
/* Dieselben Röhren wie auf dem Schreibtisch. Welche gilt, sagt der
|
||||
Server; bis seine Antwort da ist, leuchtet Bernstein. */
|
||||
@@ -253,8 +280,9 @@
|
||||
Logo links, das App-Menue am Pfeil rechts. */
|
||||
.menu.sys { left: 6px; right: auto; }
|
||||
@media (max-width: 560px) { .clock { display: none; } }
|
||||
</style>
|
||||
`;
|
||||
|
||||
root.innerHTML = `
|
||||
<div class="bar">
|
||||
<button class="home" id="home" title="HoneyOS-Menü" aria-haspopup="true" aria-expanded="false"><span class="hex">${WAPPEN}</span> HONEY<b>OS</b></button>
|
||||
<nav class="apps" id="apps"></nav>
|
||||
@@ -277,6 +305,8 @@
|
||||
<div class="drawer" id="menuApps"></div>
|
||||
</div>`;
|
||||
|
||||
stileAnlegen(root, STIL);
|
||||
|
||||
/* ── Aussehen ─────────────────────────────────────────────────────────────
|
||||
* Dieselben drei Röhren wie in style.css. Sie hier zu wiederholen ist die
|
||||
* bewusste Entscheidung: die HoneyBar soll ohne zweite Datei auskommen, damit
|
||||
@@ -520,17 +550,19 @@
|
||||
// auch wenn in HoneyOS Grün eingestellt war. Er gehört zur HoneyBar, also
|
||||
// trägt er dieselbe Röhre.
|
||||
const t = ROEHREN[(settings && settings.phosphor) || "amber"] || ROEHREN.amber;
|
||||
r.innerHTML = `
|
||||
<style>
|
||||
.strich {
|
||||
height: 3px;
|
||||
background: linear-gradient(90deg, ${t.dim}, ${t.p} 50%, ${t.dim});
|
||||
opacity: .55;
|
||||
transition: opacity .15s, height .15s;
|
||||
}
|
||||
:host(:hover) .strich { opacity: 1; height: 3px; }
|
||||
</style>
|
||||
<div class="strich"></div>`;
|
||||
// Auch hier ueber die CSSOM statt als style-Element: Der Strich hat seinen
|
||||
// eigenen Shadow-Root und waere sonst das einzige Stueck geblieben, das
|
||||
// unter einer strengen CSP unsichtbar bleibt.
|
||||
r.innerHTML = `<div class="strich"></div>`;
|
||||
stileAnlegen(r, `
|
||||
.strich {
|
||||
height: 3px;
|
||||
background: linear-gradient(90deg, ${t.dim}, ${t.p} 50%, ${t.dim});
|
||||
opacity: .55;
|
||||
transition: opacity .15s, height .15s;
|
||||
}
|
||||
:host(:hover) .strich { opacity: 1; height: 3px; }
|
||||
`);
|
||||
|
||||
nub.addEventListener("click", () => {
|
||||
forget();
|
||||
|
||||
Reference in new issue
Block a user