Path: blob/main/plugins/default-browser-emulator/lib/BrowserData.ts
1029 views
import * as Fs from 'fs';1import IUserAgentOption from '@secret-agent/interfaces/IUserAgentOption';2import IBrowserData, {3IDataBrowserConfig,4IDataClienthello,5IDataCodecs,6IDataDomPolyfill,7IDataHeaders,8IDataHttp2Settings,9IDataWindowChrome,10IDataWindowFraming,11IDataWindowNavigator,12} from '../interfaces/IBrowserData';13import DataLoader, { loadData } from './DataLoader';14import getLocalOperatingSystemMeta from './utils/getLocalOperatingSystemMeta';15import { convertMacOsVersionString, findClosestVersionMatch } from './VersionUtils';1617const localOsMeta = getLocalOperatingSystemMeta();1819export default class BrowserData implements IBrowserData {20private readonly dataLoader: DataLoader;21private readonly baseDataDir: string;22private readonly osDataDir: string;23private domPolyfillFilename: string;2425constructor(dataLoader: DataLoader, userAgentOption: IUserAgentOption) {26const browserId = createBrowserId(userAgentOption);27const os = getOperatingSystemParts(userAgentOption);28this.dataLoader = dataLoader;29this.baseDataDir = `${dataLoader.dataDir}/as-${browserId}`;30this.osDataDir = `${this.baseDataDir}/as-${os.name}-${os.version}`;31if (!this.dataLoader.isSupportedEmulator(this.osDataDir)) {32const otherVersions = this.dataLoader.getBrowserOperatingSystemVersions(browserId, os.name);33if (!otherVersions.length) {34throw new Error(`${browserId} has no emulation data for ${os.name}`);35}3637const closestVersionMatch = findClosestVersionMatch(os.version, otherVersions);38this.osDataDir = `${this.baseDataDir}/as-${os.name}-${closestVersionMatch}`;39}40}4142public get pkg(): any {43return this.dataLoader.pkg;44}4546public get headers(): IDataHeaders {47return loadData(`${this.baseDataDir}/headers.json`);48}4950public get windowBaseFraming(): IDataWindowFraming {51return loadData(`${this.baseDataDir}/window-base-framing.json`);52}5354public get browserConfig(): IDataBrowserConfig {55return loadData(`${this.baseDataDir}/config.json`);56}5758public get clienthello(): IDataClienthello {59return loadData(`${this.osDataDir}/clienthello.json`);60}6162public get codecs(): IDataCodecs {63return loadData(`${this.osDataDir}/codecs.json`);64}6566public get http2Settings(): IDataHttp2Settings {67return loadData(`${this.osDataDir}/http2-session.json`);68}6970public get windowChrome(): IDataWindowChrome {71try {72return loadData(`${this.osDataDir}/window-chrome.json`);73} catch (e) {74return undefined;75}76}7778public get windowFraming(): IDataWindowFraming {79return loadData(`${this.osDataDir}/window-framing.json`);80}8182public get windowNavigator(): IDataWindowNavigator {83return loadData(`${this.osDataDir}/window-navigator.json`);84}8586public get domPolyfill(): IDataDomPolyfill {87try {88this.domPolyfillFilename ??= extractPolyfillFilename(this.osDataDir);89return loadData(`${this.osDataDir}/${this.domPolyfillFilename}`);90} catch (e) {91return undefined;92}93}94}9596const polyfillFilesByDatadir: {97[dataDir: string]: { [osName: string]: { [osVersion: string]: string } };98} = {};99100function extractPolyfillFilename(dataDir: string) {101let filenameMap = polyfillFilesByDatadir[dataDir];102if (!filenameMap) {103filenameMap = {};104polyfillFilesByDatadir[dataDir] = filenameMap;105for (const filename of Fs.readdirSync(dataDir)) {106const matches = filename.match(/^dom-polyfill-when-runtime-([a-z-]+)(-([0-9-]+))?.json$/);107if (!matches) continue;108109const [osName, _, osVersion] = matches.slice(1); // eslint-disable-line @typescript-eslint/naming-convention,@typescript-eslint/no-unused-vars110filenameMap[osName] = filenameMap[osName] || {};111filenameMap[osName][osVersion || 'ALL'] = filename;112}113}114115if (!filenameMap[localOsMeta.name]) {116throw new Error(`Your OS (${localOsMeta.name}) is not supported by this emulator.`);117}118119const versionMatch = findClosestVersionMatch(120localOsMeta.version,121Object.keys(filenameMap[localOsMeta.name]),122);123124if (!versionMatch) {125throw new Error(126`Emulator could not find a version match for ${localOsMeta.name} ${localOsMeta.version}`,127);128}129130return filenameMap[localOsMeta.name][versionMatch];131}132133function createBrowserId(userAgentOption: IUserAgentOption) {134const { browserName, browserVersion } = userAgentOption;135return [browserName, browserVersion.major, browserVersion.minor].filter(x => x).join('-');136}137138function getOperatingSystemParts(userAgentOption: IUserAgentOption) {139const { operatingSystemName: name, operatingSystemVersion: version } = userAgentOption;140let { major, minor } = version;141142if (name.startsWith('mac')) {143[major, minor] = convertMacOsVersionString([major, minor].filter(x => x).join('.')).split('.');144} else if (name.startsWith('win') && version.minor === '0') {145minor = null;146}147const finalVersion = [major, minor].filter(x => x).join('-');148return { name, version: finalVersion };149}150151152