/* * Copyright (C) 2021-2022 Kristóf Marussy * * This file is part of Sophie. * * Sophie is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as * published by the Free Software Foundation, version 3. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Affero General Public License for more details. * * You should have received a copy of the GNU Affero General Public License * along with this program. If not, see . * * SPDX-License-Identifier: AGPL-3.0-only */ import { defineProtoProperty, deleteProtoProperty, simulateNativeClass, simulateNativeFunction, } from '../utils'; export function shimUserAgentData(chromeVersion: string | null, platform: string): void { const brands = [ { brand: ' Not A; Brand', version: '99', }, ]; if (chromeVersion !== null) { brands.push({ brand: 'Chromium', version: '96', }); } const mobile = false; const simulatedNavigatorUa = simulateNativeClass('NavigatorUAData', function NavigatorUAData() { // Nothing to initiailize. }, { brands: { configurable: true, enumerable: true, get: simulateNativeFunction('brands', () => brands), }, mobile: { configurable: true, enumerable: true, get: simulateNativeFunction('mobile', () => mobile), }, platform: { configurable: true, enumerable: true, get: simulateNativeFunction('platform', () => platform), }, getHighEntropyValues: { configurable: true, enumerable: false, value: simulateNativeFunction('getHighEntropyValues', (...args: unknown[]) => { if (args.length == 0) { throw new TypeError("Failed to execute 'getHighEntropyValues' on 'NavigatorUAData': 1 argument required, but only 0 present."); } const hints = Array.from(args[0] as Iterable); if (hints.length === 0) { return {}; } const data: Record = { brands, mobile, } if (hints.includes('platform')) { data['platform'] = platform; } return Promise.resolve(data); }) }, toJSON: { configurable: true, enumerable: false, value: simulateNativeFunction('toJSON', () => ({ brands, mobile, })), writable: false, }, }); const simulatedUserAgentData = Reflect.construct(simulatedNavigatorUa, []); defineProtoProperty(globalThis.navigator, 'userAgentData', { configurable: true, enumerable: true, get: simulateNativeFunction('userAgentData', () => simulatedUserAgentData), }); } export function deleteUserAgentData(): void { deleteProtoProperty(globalThis.navigator, 'userAgentData'); }