From 7461cdbf3f8056ff9c07f43d31077beb689ed775 Mon Sep 17 00:00:00 2001 From: Will Hunt <2072976+Half-Shot@users.noreply.github.com> Date: Fri, 27 Feb 2026 10:55:22 +0000 Subject: [PATCH] Prevent logging lots of "Browser unsupported" lines (#32647) * Store the result of getBrowserSupport * Add supported_environment data * Refactor * Ensure have a cache opt-out * docstring * Use memoizeOne --- apps/web/src/SupportedBrowser.ts | 54 ++++++++++--------- apps/web/src/rageshake/submit-rageshake.ts | 2 + .../test/unit-tests/SupportedBrowser-test.ts | 4 +- 3 files changed, 34 insertions(+), 26 deletions(-) diff --git a/apps/web/src/SupportedBrowser.ts b/apps/web/src/SupportedBrowser.ts index 0527ed829f..43b7017ff3 100644 --- a/apps/web/src/SupportedBrowser.ts +++ b/apps/web/src/SupportedBrowser.ts @@ -9,6 +9,7 @@ Please see LICENSE files in the repository root for full details. import { logger } from "matrix-js-sdk/src/logger"; import browserlist from "browserslist"; import PopOutIcon from "@vector-im/compound-design-tokens/assets/web/icons/pop-out"; +import memoizeOne from "memoize-one"; import { DeviceType, parseUserAgent } from "./utils/device/parseUserAgent"; import ToastStore from "./stores/ToastStore"; @@ -40,11 +41,7 @@ function getBrowserNameVersion(browser: string): [name: string, version: number] return [browserNameLc, parseInt(browserVersion, 10)]; } -/** - * Function to check if the current browser is considered supported by our support policy. - * Based on user agent parsing so may be inaccurate if the user has fingerprint prevention turned up to 11. - */ -export function getBrowserSupport(): boolean { +function calculateBrowserSupport(): boolean { const browsers = browserlist(SUPPORTED_BROWSER_QUERY).sort(); const minimumBrowserVersions = new Map(); for (const browser of browsers) { @@ -56,34 +53,41 @@ export function getBrowserSupport(): boolean { const details = parseUserAgent(navigator.userAgent); - let supported = true; + if (!details.client) { + logger.warn("Browser unsupported, unknown client", navigator.userAgent); + return false; + } + if (!SUPPORTED_DEVICE_TYPES.includes(details.deviceType)) { logger.warn("Browser unsupported, unsupported device type", details.deviceType); - supported = false; + return false; } - if (details.client) { - // We don't care about the browser version for desktop devices - // We ship our own browser (electron) for desktop devices - if (details.deviceType === DeviceType.Desktop) { - return supported; - } - - const [browserName, browserVersion] = getBrowserNameVersion(details.client); - const minimumVersion = minimumBrowserVersions.get(browserName); - // Check both with the sub-version cut off and without as some browsers have less granular versioning e.g. Safari - if (!minimumVersion || browserVersion < minimumVersion) { - logger.warn("Browser unsupported, unsupported user agent", details.client); - supported = false; - } - } else { - logger.warn("Browser unsupported, unknown client", navigator.userAgent); - supported = false; + // We don't care about the browser version for desktop devices + // We ship our own browser (electron) for desktop devices + if (details.deviceType === DeviceType.Desktop) { + return true; } - return supported; + const [browserName, browserVersion] = getBrowserNameVersion(details.client); + const minimumVersion = minimumBrowserVersions.get(browserName); + // Check both with the sub-version cut off and without as some browsers have less granular versioning e.g. Safari + if (!minimumVersion || browserVersion < minimumVersion) { + logger.warn("Browser unsupported, unsupported user agent", details.client); + return false; + } + return true; } +/** + * Function to check if the current browser is considered supported by our support policy. + * Based on user agent parsing so may be inaccurate if the user has fingerprint prevention turned up to 11. + * This is calculated once and stored for the lifetime of the session to prevent logspam. + * + * @returns `true` if the browser is supported by us, or `false` if *any* of the checks fail. + */ +export const getBrowserSupport = memoizeOne(calculateBrowserSupport); + /** * Shows a user warning toast if the user's browser is not supported. */ diff --git a/apps/web/src/rageshake/submit-rageshake.ts b/apps/web/src/rageshake/submit-rageshake.ts index 0101686548..f341664f05 100644 --- a/apps/web/src/rageshake/submit-rageshake.ts +++ b/apps/web/src/rageshake/submit-rageshake.ts @@ -22,6 +22,7 @@ import SdkConfig from "../SdkConfig"; import { getServerVersionFromFederationApi } from "../components/views/dialogs/devtools/ServerInfo"; import type * as Tar from "tar-js"; import { BugReportEndpointURLLocal } from "../IConfigOptions"; +import { getBrowserSupport } from "../SupportedBrowser"; interface IOpts { labels?: string[]; @@ -118,6 +119,7 @@ async function collectBaseInformation(body: FormData, opts: IOpts): Promise { beforeEach(() => { jest.resetAllMocks(); localStorage.clear(); + getBrowserSupport.clear(); }); const testUserAgentFactory = @@ -109,6 +110,7 @@ describe("SupportedBrowser", () => { toastSpy.mockClear(); warnLogSpy.mockClear(); + getBrowserSupport.clear(); checkBrowserSupport(); expect(warnLogSpy).toHaveBeenCalledWith("Browser unsupported, but user has previously accepted"); expect(toastSpy).not.toHaveBeenCalled();