1
0
mirror of https://github.com/bitwarden/browser synced 2025-12-06 00:13:28 +00:00

Failsafe for Chromium browsers' forced rendering of opaque bkgd (#15098)

This commit is contained in:
Miles Blackwood
2025-06-12 17:15:16 -04:00
committed by GitHub
parent 0e1d48179d
commit 64e577e2e6
4 changed files with 37 additions and 4 deletions

View File

@@ -12,7 +12,7 @@ import { NotificationConfirmationContainer } from "../content/components/notific
import { NotificationContainer } from "../content/components/notification/container"; import { NotificationContainer } from "../content/components/notification/container";
import { selectedFolder as selectedFolderSignal } from "../content/components/signals/selected-folder"; import { selectedFolder as selectedFolderSignal } from "../content/components/signals/selected-folder";
import { selectedVault as selectedVaultSignal } from "../content/components/signals/selected-vault"; import { selectedVault as selectedVaultSignal } from "../content/components/signals/selected-vault";
import { buildSvgDomElement } from "../utils"; import { buildSvgDomElement, matchAllowedColorSchemes } from "../utils";
import { circleCheckIcon } from "../utils/svg-icons"; import { circleCheckIcon } from "../utils/svg-icons";
import { import {
@@ -238,6 +238,15 @@ async function initNotificationBar(message: NotificationBarWindowMessage) {
const i18n = getI18n(); const i18n = getI18n();
const resolvedTheme = getResolvedTheme(theme ?? ThemeTypes.Light); const resolvedTheme = getResolvedTheme(theme ?? ThemeTypes.Light);
// https://drafts.csswg.org/css-color-adjust-1/#preferred
// Prevents preferred color scheme from forcing an opaque background in the iframe
const colorScheme = new URLSearchParams(window.location.search).get("colorScheme") || "";
const allowedColorScheme = matchAllowedColorSchemes(colorScheme);
const meta = document.createElement("meta");
meta.setAttribute("name", "color-scheme");
meta.setAttribute("content", allowedColorScheme);
document.getElementsByTagName("head")[0].appendChild(meta);
if (useComponentBar) { if (useComponentBar) {
const resolvedType = resolveNotificationType(notificationBarIframeInitData); const resolvedType = resolveNotificationType(notificationBarIframeInitData);
const headerMessage = getNotificationHeaderMessage(i18n, resolvedType); const headerMessage = getNotificationHeaderMessage(i18n, resolvedType);

View File

@@ -7,7 +7,7 @@ exports[`OverlayNotificationsContentService opening the notification bar creates
> >
<iframe <iframe
id="bit-notification-bar-iframe" id="bit-notification-bar-iframe"
src="chrome-extension://id/notification/bar.html" src="chrome-extension://id/notification/bar.html?colorScheme=normal"
style="width: 100% !important; height: 100% !important; border: 0px !important; display: block !important; position: relative !important; transition: transform 0.15s ease-out, opacity 0.15s ease !important; border-radius: 4px !important; transform: translateX(0) !important; opacity: 0;" style="width: 100% !important; height: 100% !important; border: 0px !important; display: block !important; position: relative !important; transition: transform 0.15s ease-out, opacity 0.15s ease !important; border-radius: 4px !important; transform: translateX(0) !important; opacity: 0;"
/> />
</div> </div>

View File

@@ -7,7 +7,7 @@ import {
NotificationType, NotificationType,
NotificationTypes, NotificationTypes,
} from "../../../notification/abstractions/notification-bar"; } from "../../../notification/abstractions/notification-bar";
import { sendExtensionMessage, setElementStyles } from "../../../utils"; import { matchAllowedColorSchemes, sendExtensionMessage, setElementStyles } from "../../../utils";
import { import {
NotificationsExtensionMessage, NotificationsExtensionMessage,
OverlayNotificationsContentService as OverlayNotificationsContentServiceInterface, OverlayNotificationsContentService as OverlayNotificationsContentServiceInterface,
@@ -175,13 +175,18 @@ export class OverlayNotificationsContentService
* @param initData - The initialization data for the notification bar. * @param initData - The initialization data for the notification bar.
*/ */
private createNotificationBarIframeElement(initData: NotificationBarIframeInitData) { private createNotificationBarIframeElement(initData: NotificationBarIframeInitData) {
const content = (document.querySelector('meta[name="color-scheme"]') as HTMLMetaElement)
?.content;
const allowedColorScheme = matchAllowedColorSchemes(content);
const isNotificationFresh = const isNotificationFresh =
initData.launchTimestamp && Date.now() - initData.launchTimestamp < 250; initData.launchTimestamp && Date.now() - initData.launchTimestamp < 250;
this.currentNotificationBarType = initData.type; this.currentNotificationBarType = initData.type;
this.notificationBarIframeElement = globalThis.document.createElement("iframe"); this.notificationBarIframeElement = globalThis.document.createElement("iframe");
this.notificationBarIframeElement.id = "bit-notification-bar-iframe"; this.notificationBarIframeElement.id = "bit-notification-bar-iframe";
this.notificationBarIframeElement.src = chrome.runtime.getURL("notification/bar.html"); this.notificationBarIframeElement.src = chrome.runtime.getURL(
`notification/bar.html?colorScheme=${encodeURIComponent(allowedColorScheme)}`,
);
setElementStyles( setElementStyles(
this.notificationBarIframeElement, this.notificationBarIframeElement,
{ {

View File

@@ -575,3 +575,22 @@ export function areKeyValuesNull<T extends Record<string, any>>(
return keysToCheck.every((key) => obj[key] == null); return keysToCheck.every((key) => obj[key] == null);
} }
export type AllowedColorScheme = "light dark" | "dark light" | "light" | "dark" | "normal";
/**
* Ensures string matches allowed color scheme, defaulting/overriding to "normal".
* https://drafts.csswg.org/css-color-adjust-1/#color-scheme-meta
*/
export function matchAllowedColorSchemes(content: string): AllowedColorScheme {
switch (content) {
case "light dark":
case "dark light":
case "light":
case "dark":
// content must match one of these types.
return content;
default:
return "normal";
}
}