├── .editorconfig ├── .gitignore ├── README.md ├── builder ├── cmd │ ├── build.js │ ├── dist.js │ ├── gen.js │ ├── launch.js │ ├── restore.js │ ├── setup.js │ └── watch.js ├── tools │ ├── build.js │ ├── depot-tools.js │ ├── dist.js │ ├── launch.js │ ├── merge.js │ ├── restore.js │ └── watch.js └── utils │ ├── copy.js │ ├── dir.js │ ├── morror.js │ └── steps.js ├── bypass └── webgl │ ├── readme.md │ └── script.js ├── configs ├── devices │ ├── device-1647096314873.json │ └── device.json ├── dist.js └── path.js ├── docs ├── development │ └── macos.md └── setup │ └── macos.md ├── package-lock.json ├── package.json └── updates └── src ├── base ├── BUILD.gn ├── base_switches.cc ├── base_switches.h ├── custom_device.cc └── custom_device.h ├── content └── browser │ └── renderer_host │ └── render_process_host_impl.cc └── third_party └── blink └── renderer └── core ├── css ├── local_font_face_source.cc └── media_values.cc └── frame ├── navigator.cc ├── navigator_concurrent_hardware.cc ├── navigator_device_memory.cc ├── navigator_id.cc ├── navigator_ua_data.cc └── screen.cc /.editorconfig: -------------------------------------------------------------------------------- 1 | # editorconfig.org 2 | root = true 3 | 4 | [*] 5 | indent_style = space 6 | indent_size = 2 7 | end_of_line = lf 8 | charset = utf-8 9 | trim_trailing_whitespace = true 10 | insert_final_newline = true 11 | 12 | [*.md] 13 | trim_trailing_whitespace = false 14 | 15 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | depot_tools 2 | node_modules 3 | chromium 4 | build 5 | _build 6 | temp 7 | .idea 8 | .DS_Store 9 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | This is an open source custom chrome project. 2 | The goal of the project is to completely fake the fingerprint of any device without leaving any traces. 3 | 4 | ## Setup 5 | [MacOS](https://github.com/serzz1990/custom-chromium/blob/main/docs/setup/macos.md) 6 | 7 | ## Development 8 | [MacOS](https://github.com/serzz1990/custom-chromium/blob/main/docs/development/macos.md) 9 | 10 | ## Project tree 11 | 📦custom-chromium 12 | ┣ 📂build (files for build) 13 | ┣ 📂builder (scripts for build) 14 | ┣ 📂chromium (original chromium) 15 | ┣ 📂configs (configs for build) 16 | ┃ ┗ 📂devices (device descriptors) 17 | ┣ 📂depot_tools (utils for build chromium) 18 | ┣ 📂docs (documentation) 19 | ┣ 📂dist (distribution kit) 20 | ┗ 📂updates (changes made to chromium assembly) 21 | 22 | ## How does it work? 23 | 24 | soon 25 | 26 | ## Links 27 | 28 | * [Telegram chat](https://t.me/cchromium) 29 | * [pixelscan](https://pixelscan.net/) 30 | * [creepjs](https://abrahamjuliot.github.io/creepjs/) 31 | * [best practice for patching chrome](https://github.com/Eloston/ungoogled-chromium/tree/master/patches/extra) 32 | * [best practice for patching chrome 2](https://github.com/brave/brave-browser/wiki/Patching-Chromium) 33 | 34 | 35 | ## TODO LIST ✓ 36 | - [x] create one json with all params 37 | - [x] matchMedia here: "third_party/blink/renderer/core/css/media_values.cc" 38 | - [x] fonts 39 | - [x] [navigator.vendor](https://github.com/berstend/puppeteer-extra/tree/master/packages/puppeteer-extra-plugin-stealth/evasions/navigator.vendor) 40 | - [ ] [media.codecs](https://github.com/berstend/puppeteer-extra/tree/master/packages/puppeteer-extra-plugin-stealth/evasions/media.codecs) 41 | - [ ] [navigator.languages](https://github.com/berstend/puppeteer-extra/tree/master/packages/puppeteer-extra-plugin-stealth/evasions/navigator.languages) 42 | - [ ] [navigator.permissions](https://github.com/berstend/puppeteer-extra/tree/master/packages/puppeteer-extra-plugin-stealth/evasions/navigator.permissions) 43 | - [ ] [navigator.plugins](https://github.com/berstend/puppeteer-extra/tree/master/packages/puppeteer-extra-plugin-stealth/evasions/navigator.plugins) 44 | - [ ] [webgl.vendor](https://github.com/berstend/puppeteer-extra/tree/master/packages/puppeteer-extra-plugin-stealth/evasions/webgl.vendor) 45 | - [ ] [window.outerdimensions](https://github.com/berstend/puppeteer-extra/blob/master/packages/puppeteer-extra-plugin-stealth/evasions/window.outerdimensions) 46 | - [ ] WebRTC 47 | - [ ] css computed style colors / fonts 48 | - [ ] keyboard 49 | - [ ] mimeTypes 50 | - [ ] audio 51 | - [ ] emoji 52 | - [ ] [fingerprintjs fonts](https://github.com/fingerprintjs/fingerprintjs/blob/master/src/sources/fonts.ts) 53 | - [ ] [chrome.app](https://github.com/berstend/puppeteer-extra/tree/master/packages/puppeteer-extra-plugin-stealth/evasions/chrome.app) 54 | - [ ] [chrome.csi](https://github.com/berstend/puppeteer-extra/tree/master/packages/puppeteer-extra-plugin-stealth/evasions/chrome.csi) 55 | - [ ] [chrome.runtime](https://github.com/berstend/puppeteer-extra/tree/master/packages/puppeteer-extra-plugin-stealth/evasions/chrome.runtime) 56 | - [ ] [iframe.contentWindow](https://github.com/berstend/puppeteer-extra/tree/master/packages/puppeteer-extra-plugin-stealth/evasions/iframe.contentWindow) 57 | - [ ] [navigator.webdriver](https://github.com/berstend/puppeteer-extra/tree/master/packages/puppeteer-extra-plugin-stealth/evasions/navigator.webdriver) 58 | - [ ] collect device descriptor 59 | - [ ] change patching chrome 60 | 61 | 62 | getFontFaceLoadFonts(getFontList 63 | -------------------------------------------------------------------------------- /builder/cmd/build.js: -------------------------------------------------------------------------------- 1 | const build = require('../tools/build'); 2 | 3 | (async () => { 4 | await build(); 5 | })() -------------------------------------------------------------------------------- /builder/cmd/dist.js: -------------------------------------------------------------------------------- 1 | const dist = require('../tools/dist'); 2 | 3 | (async () => { 4 | await dist(); 5 | })() 6 | -------------------------------------------------------------------------------- /builder/cmd/gen.js: -------------------------------------------------------------------------------- 1 | const shell = require('shelljs'); 2 | const fs = require('fs'); 3 | const configPath = require('../../configs/path'); 4 | 5 | const depotTools = require('../tools/depot-tools'); 6 | 7 | if (!fs.existsSync(configPath.outPath)){ 8 | fs.mkdirSync(configPath.outPath, { recursive: true }); 9 | } 10 | shell.cd(configPath.outPath); 11 | depotTools.cmd('gn gen ./') 12 | -------------------------------------------------------------------------------- /builder/cmd/launch.js: -------------------------------------------------------------------------------- 1 | const launch = require('../tools/launch'); 2 | 3 | (async () => { 4 | await launch(); 5 | })() 6 | -------------------------------------------------------------------------------- /builder/cmd/restore.js: -------------------------------------------------------------------------------- 1 | const restore = require('../tools/restore'); 2 | 3 | (async () => { 4 | await restore(); 5 | })() 6 | -------------------------------------------------------------------------------- /builder/cmd/setup.js: -------------------------------------------------------------------------------- 1 | const shell = require('shelljs'); 2 | const fs = require('fs'); 3 | const path = require('path'); 4 | const configPath = require('../../configs/path'); 5 | 6 | const steps = require('../utils/steps'); 7 | const build = require('../tools/build'); 8 | const depotTools = require('../tools/depot-tools'); 9 | const copy = require("../utils/copy"); 10 | 11 | (async () => { 12 | await steps([ 13 | { 14 | name: 'Get depot tools', 15 | fn: depotTools.cloneRepo 16 | }, 17 | { 18 | name: 'Get chromium', 19 | fn: () => { 20 | if (!fs.existsSync(configPath.chromiumPath)) { 21 | fs.mkdirSync(configPath.chromiumPath, { recursive: true }); 22 | shell.cd(configPath.chromiumPath); 23 | // https://chromium.googlesource.com/chromium/src.git#:~:text=Chromium%20is%20an%20open%2Dsource,how%20to%20get%20the%20code. 24 | // shell.exec('git fetch https://chromium.googlesource.com/chromium/src.git +refs/tags/59.0.3071.115:chromium_59.0.3071.115 --depth 1'); 25 | // depotTools.cmd('caffeinate fetch --no-history chromium'); 26 | depotTools.cmd('caffeinate fetch chromium'); 27 | } 28 | } 29 | }, 30 | { 31 | name: 'Copy chromium', 32 | fn: async () => { 33 | await copy(configPath.chromiumPath + '/src', configPath.buildPath + '/src'); 34 | } 35 | }, 36 | { 37 | name: 'Generate ninja files', 38 | fn: async () => { 39 | if (!fs.existsSync(configPath.outPath)){ 40 | fs.mkdirSync(configPath.outPath, { recursive: true }); 41 | } 42 | shell.cd(configPath.outPath); 43 | depotTools.cmd('gn gen ./') 44 | } 45 | }, 46 | { 47 | name: 'Setup Faster builds', 48 | fn: async () => { 49 | const argsFilePath = path.join(configPath.outPath, 'args.gn'); 50 | fs.writeFileSync(argsFilePath, `is_debug = false 51 | is_component_build = true 52 | symbol_level = 0 53 | `); 54 | } 55 | }, 56 | { 57 | name: 'Build cache', 58 | fn: build 59 | }, 60 | ]); 61 | })(); 62 | -------------------------------------------------------------------------------- /builder/cmd/watch.js: -------------------------------------------------------------------------------- 1 | const watch = require('../tools/watch'); 2 | 3 | (async () => { 4 | await watch(); 5 | })() 6 | -------------------------------------------------------------------------------- /builder/tools/build.js: -------------------------------------------------------------------------------- 1 | const shell = require('shelljs'); 2 | const configPath = require('../../configs/path'); 3 | const depthTools = require('./depot-tools'); 4 | const merge = require('./merge'); 5 | 6 | module.exports = async function () { 7 | await merge(); 8 | shell.cd(configPath.outPath); 9 | depthTools.cmd('autoninja -C ./ chrome'); 10 | } 11 | -------------------------------------------------------------------------------- /builder/tools/depot-tools.js: -------------------------------------------------------------------------------- 1 | const shell = require('shelljs'); 2 | const colors = require("colors/safe"); 3 | const fs = require("fs"); 4 | const configPath = require("../../configs/path"); 5 | const depotToolsRepo = 'https://chromium.googlesource.com/chromium/tools/depot_tools.git'; 6 | 7 | module.exports = { 8 | cloneRepo: () => { 9 | if (!shell.which('git')) { 10 | console.log(colors.red.underline('Sorry, this script requires git')); 11 | shell.exit(1); 12 | } 13 | if (!fs.existsSync(configPath.depotToolsPath)){ 14 | fs.mkdirSync(configPath.depotToolsPath, { recursive: true }); 15 | shell.exec('git clone ' + depotToolsRepo); 16 | } 17 | }, 18 | cmd: (cmd) => { 19 | return shell.exec(`export PATH="$PATH:${configPath.depotToolsPath}" && ${cmd}`); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /builder/tools/dist.js: -------------------------------------------------------------------------------- 1 | const fs = require('fs'); 2 | const path = require('path'); 3 | const configDist = require('../../configs/dist'); 4 | const configPath = require('../../configs/path'); 5 | 6 | module.exports = async function () { 7 | if (fs.existsSync(configPath.distPath)) { 8 | await fs.promises.rm(configPath.distPath, { recursive: true }); 9 | } 10 | await fs.mkdirSync(configPath.distPath); 11 | await Promise.all(configDist.copy.map(async (filename) => { 12 | const srcPath = path.join(configPath.outPath, filename); 13 | const distPath = path.join(configPath.distPath, filename); 14 | const exists = fs.existsSync(srcPath); 15 | if (exists) { 16 | await fs.promises.cp(srcPath, distPath, { recursive: true }); 17 | } 18 | })); 19 | } 20 | 21 | 22 | -------------------------------------------------------------------------------- /builder/tools/launch.js: -------------------------------------------------------------------------------- 1 | const puppeteer = require('puppeteer'); 2 | const path = require('path'); 3 | const device = require('../../configs/devices/device.json'); 4 | const configPath = require('../../configs/path'); 5 | const configDist = require('../../configs/dist'); 6 | 7 | module.exports = async function () { 8 | const browser = await puppeteer.launch({ 9 | executablePath: path.join(configPath.outPath, configDist.platforms[process.platform].executablePath), 10 | devtools: false, 11 | dumpio: true, 12 | headless: false, 13 | defaultViewport: null, 14 | args: [ 15 | `--user-agent=${device.navigator.userAgent}`, 16 | `--custom-device-data=${JSON.stringify(device)}` 17 | ] 18 | }); 19 | 20 | const page = await browser.newPage(); 21 | await page.goto('https://abrahamjuliot.github.io/creepjs/'); 22 | } 23 | -------------------------------------------------------------------------------- /builder/tools/merge.js: -------------------------------------------------------------------------------- 1 | const path = require('path'); 2 | const fs = require('fs'); 3 | const configPath = require('../../configs/path'); 4 | const colors = require('colors/safe'); 5 | const dir = require('../utils/dir'); 6 | const ignoreFiles = [ 7 | '.DS_Store' 8 | ]; 9 | 10 | // module.exports = async function () { 11 | // await dir.copy(configPath.updatesPath, configPath.buildPath, { 12 | // // onPath: (filepath) => { 13 | // // console.log(filepath) 14 | // // } 15 | // }); 16 | // } 17 | 18 | module.exports = async function () { 19 | const originalFilesDir = path.join(configPath.chromiumPath, 'src') 20 | const modifyFilesDir = path.join(configPath.updatesPath, 'src') 21 | const buildFilesDir = path.join(configPath.buildPath, 'src') 22 | 23 | await dir.forEachFiles(modifyFilesDir, { 24 | onPath: async (modifyPath) => { 25 | const targetPath = modifyPath.replace(modifyFilesDir, buildFilesDir) 26 | const originalFilePath = modifyPath.replace(modifyFilesDir, originalFilesDir) 27 | const modifyPathStat = await fs.promises.stat(modifyPath) 28 | const isExistTargetPath = fs.existsSync(targetPath) 29 | const isExistOriginalPath = fs.existsSync(originalFilePath) 30 | const filename = path.basename(modifyPath) 31 | 32 | if (ignoreFiles.includes(filename)) { 33 | return; 34 | } 35 | 36 | if (modifyPathStat.isDirectory()) { 37 | return await fs.promises.mkdir(targetPath, { recursive: true }) 38 | } 39 | 40 | if (!isExistOriginalPath) { 41 | await modifyFile(modifyPath, targetPath) 42 | // await fs.promises.cp(modifyPath, targetPath, { recursive: true }) 43 | return; 44 | } 45 | 46 | if (!isExistTargetPath) { 47 | return; 48 | } 49 | 50 | const diffs = await findFilesDiff(originalFilePath, modifyPath) 51 | 52 | if (diffs) { 53 | console.log(colors.red(`Conflict in: ${modifyPath}`)) 54 | console.log(colors.green(`> ${diffs.line}: ${diffs.lines[0]}`)) 55 | console.log(colors.yellow(`> ${diffs.line}: ${diffs.lines[1]}`)) 56 | throw Error 57 | } else { 58 | await modifyFile(modifyPath, targetPath) 59 | // await fs.promises.cp(modifyPath, targetPath, { recursive: true }) 60 | } 61 | } 62 | }) 63 | } 64 | 65 | async function findFilesDiff (originalFilePath, modifyFilePath) { 66 | const modifyFileContent = await fs.promises.readFile(modifyFilePath, 'utf8') 67 | const originalFileContent = await fs.promises.readFile(originalFilePath, 'utf8') 68 | const contentWithoutModify = modifyFileContent.replace(/\n?\/\/START-UPDATES(.+?)\n?\/\/END-UPDATES/gmis, '') 69 | if (contentWithoutModify !== originalFileContent) { 70 | return findStringDiff(originalFileContent, contentWithoutModify) 71 | } else { 72 | return null 73 | } 74 | } 75 | 76 | async function modifyFile (modifyFilePath, filePathTo) { 77 | const modifyFileContent = await fs.promises.readFile(modifyFilePath, 'utf8') 78 | const newFileContent = modifyFileContent 79 | .replace(/\n?\/\/START-UPDATES(.+)?/gmi, '') 80 | .replace(/\n?\/\/END-UPDATES(.+)?/gmi, '') 81 | await fs.promises.writeFile(filePathTo, newFileContent) 82 | } 83 | 84 | function findStringDiff(str1, str2) { 85 | const lines1 = str1.split(/\r?\n/) 86 | const lines2 = str2.split(/\r?\n/) 87 | const maxLinesCount = Math.max(lines1.length, lines2.length) 88 | for (let i = 0; i < maxLinesCount; i++) { 89 | if (lines1[i] !== lines2[i]) { 90 | return { 91 | line: i + 1, 92 | lines: [ 93 | lines1[i], 94 | lines2[i] 95 | ] 96 | } 97 | } 98 | } 99 | return null 100 | } 101 | 102 | -------------------------------------------------------------------------------- /builder/tools/restore.js: -------------------------------------------------------------------------------- 1 | const shell = require('shelljs'); 2 | const path = require('path'); 3 | const fs = require('fs'); 4 | const configPath = require('../../configs/path'); 5 | const dir = require('../utils/dir'); 6 | 7 | module.exports = async function () { 8 | const srcPath = path.join(configPath.updatesPath, 'src'); 9 | const chromiumPath = path.join(configPath.chromiumPath, 'src'); 10 | const tempPath = path.join(configPath.rootPath, 'temp/src'); 11 | const buildPath = path.join(configPath.buildPath, 'src'); 12 | if (fs.existsSync(tempPath)) { 13 | await fs.promises.rm(tempPath, { recursive: true }); 14 | } 15 | await fs.promises.mkdir(tempPath, { recursive: true }); 16 | await dir.forEachFiles(srcPath, { 17 | onPath: async (itemSrc, itemStat) => { 18 | const chromiumItemPath = itemSrc.replace(srcPath, chromiumPath); 19 | const targetItemPath = itemSrc.replace(srcPath, tempPath); 20 | if (fs.existsSync(chromiumItemPath)) { 21 | const chromiumItemPathStat = await fs.promises.stat(chromiumItemPath); 22 | if (chromiumItemPathStat.isDirectory()) { 23 | if (!fs.existsSync(tempPath)) { 24 | await fs.promises.mkdir(targetItemPath, { recursive: true }); 25 | } 26 | } else { 27 | // console.log(chromiumItemPath, ' => ' ,targetItemPath); 28 | await fs.promises.cp(chromiumItemPath, targetItemPath); 29 | } 30 | } 31 | } 32 | }); 33 | await dir.copy(tempPath, buildPath); 34 | await fs.promises.rm(tempPath, { recursive: true }); 35 | } 36 | -------------------------------------------------------------------------------- /builder/tools/watch.js: -------------------------------------------------------------------------------- 1 | const merge = require('../tools/merge'); 2 | const configPath = require('../../configs/path'); 3 | const fs = require('fs'); 4 | const path = require('path'); 5 | const shell = require('shelljs'); 6 | const depotTools = require('./depot-tools'); 7 | const build = require('./build'); 8 | const mirror = require('../utils/morror'); 9 | 10 | let building = false; 11 | let nextBuild = false; 12 | let timeoutId; 13 | 14 | module.exports = async function () { 15 | await merge(); 16 | 17 | // fs.watch(configPath.updatesPath, { recursive: true }, async (eventType, filename) => { 18 | // clearTimeout(timeoutId); 19 | // const isTemp = filename ? filename.search(/~$/) > -1 : true; 20 | // if (!isTemp) { 21 | // const srcPath = path.join(configPath.updatesPath, filename); 22 | // const destPath = path.join(configPath.buildPath, filename); 23 | // await mirror(srcPath, destPath, filename); 24 | // } 25 | // timeoutId = setTimeout(runbuild, 600); 26 | // }); 27 | } 28 | 29 | async function runbuild () { 30 | if (building) { 31 | nextBuild = true; 32 | } else { 33 | building = true; 34 | try { 35 | await build(); 36 | } finally { 37 | building = false; 38 | if (nextBuild) { 39 | nextBuild = false; 40 | clearTimeout(timeoutId); 41 | runbuild(); 42 | } 43 | } 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /builder/utils/copy.js: -------------------------------------------------------------------------------- 1 | const fs = require('fs'); 2 | const getSizeCallback = require('get-folder-size'); 3 | const cliProgress = require('cli-progress'); 4 | const path = require("path"); 5 | 6 | module.exports = async function copyWithProgress(src, dest, options) { 7 | const _options = Object.assign({ progress: true, onCopy: () => {} }, options); 8 | let totalCopedSize = 0; 9 | 10 | if (!fs.existsSync(dest)) { 11 | fs.mkdirSync(dest, { recursive: true }); 12 | } 13 | const bar = _options.progress ? new cliProgress.SingleBar({}, cliProgress.Presets.shades_classic) : null; 14 | const sizeSrc = await getSize(src); 15 | 16 | bar && bar.start(sizeSrc, 0); 17 | 18 | await copyFolderRecursiveSync(src, dest, { 19 | onCopy: (filepath, stat) => { 20 | totalCopedSize += stat.size; 21 | bar && bar.update(totalCopedSize); 22 | _options.onCopy(filepath, stat); 23 | } 24 | }); 25 | 26 | bar && bar.update(sizeSrc); 27 | bar && bar.stop(); 28 | }; 29 | 30 | 31 | 32 | function copyFileSync(source, target, options) { 33 | const _options = Object.assign({ skipErrors: true }, options) 34 | try { 35 | let targetFile = target; 36 | if ( fs.existsSync( target ) ) { 37 | if ( fs.lstatSync( target ).isDirectory() ) { 38 | targetFile = path.join( target, path.basename( source ) ); 39 | } 40 | } 41 | fs.cpSync(source, targetFile, { recursive: true }); 42 | } catch (e) { 43 | if (!_options.skipErrors) { 44 | throw Error(e); 45 | } else { 46 | console.log('Fail copy', e.code, e.info); 47 | } 48 | } 49 | } 50 | 51 | function copyFolderRecursiveSync(source, target, options) { 52 | const _options = Object.assign({ insert: false, skipErrors: true, onCopy: () => {} }, options) 53 | let targetFolder = target; 54 | 55 | if (_options.insert) { 56 | targetFolder = path.join(target, path.basename(source)); 57 | } 58 | 59 | if (!fs.existsSync(targetFolder)) { 60 | fs.mkdirSync(targetFolder, { recursive: true }); 61 | } 62 | 63 | // Copy 64 | if ( fs.lstatSync( source ).isDirectory() ) { 65 | const files = fs.readdirSync( source ); 66 | files.forEach( function ( file ) { 67 | let curSource = path.join( source, file ); 68 | if ( fs.lstatSync( curSource ).isDirectory() ) { 69 | copyFolderRecursiveSync(curSource, targetFolder, { insert: true, onCopy: _options.onCopy }); 70 | _options.onCopy(curSource, fs.lstatSync(curSource)); 71 | } else { 72 | copyFileSync(curSource, targetFolder, { skipErrors: _options.skipErrors }); 73 | _options.onCopy(curSource, fs.lstatSync(curSource)); 74 | } 75 | }); 76 | } 77 | } 78 | 79 | async function getSize(dir) { 80 | return new Promise((resolve, reject) => { 81 | getSizeCallback(dir, (err, size) => { 82 | if (err) { 83 | reject(err); 84 | } 85 | resolve(size); 86 | }); 87 | }); 88 | } 89 | -------------------------------------------------------------------------------- /builder/utils/dir.js: -------------------------------------------------------------------------------- 1 | const fs = require('fs'); 2 | const cliProgress = require('cli-progress'); 3 | const path = require('path'); 4 | 5 | module.exports = { 6 | forEachFiles, 7 | copy 8 | }; 9 | 10 | async function forEachFiles (src, options) { 11 | const _options = Object.assign({ 12 | onPath: async () => {} 13 | }, options); 14 | const stat = await fs.promises.stat(src); 15 | const isDirectory = stat.isDirectory(); 16 | const paths = []; 17 | await _options.onPath(src, stat); 18 | 19 | if (isDirectory) { 20 | const files = await fs.promises.readdir(src); 21 | await Promise.all( 22 | files.map(async (file) => { 23 | const curSource = path.join(src, file); 24 | const curStat = await fs.promises.stat(curSource); 25 | paths.push({ path: curSource, stat: curStat }); 26 | }) 27 | ); 28 | paths.sort((a, b) => (a.stat.isDirectory() ? 1 : -1)); 29 | await Promise.all( 30 | paths.map(async (item) => { 31 | if (item.stat.isDirectory()) { 32 | await forEachFiles(item.path, _options); 33 | } else { 34 | await _options.onPath(item.path, stat); 35 | } 36 | }) 37 | ); 38 | } 39 | } 40 | 41 | async function copy(src, dest, options) { 42 | const _options = Object.assign({ 43 | progress: true, 44 | insert: false, 45 | skipErrors: true, 46 | onPath: () => {} 47 | }, options); 48 | const bar = _options.progress ? new cliProgress.SingleBar({}, cliProgress.Presets.shades_classic) : null; 49 | let sizeSrc = 0; 50 | let totalCopedSize = 0; 51 | 52 | await forEachFiles(src, { onPath: async (itemSrc, stat) => { 53 | sizeSrc += stat.size 54 | }}); 55 | 56 | if (!fs.existsSync(dest)) { 57 | fs.mkdirSync(dest, { recursive: true }); 58 | } 59 | 60 | bar && bar.start(sizeSrc, 0); 61 | 62 | await forEachFiles(src, { onPath: async (itemSrc, stat) => { 63 | totalCopedSize += stat.size; 64 | bar && bar.update(totalCopedSize); 65 | try { 66 | const target = itemSrc.replace(src, dest); 67 | await _options.onPath(itemSrc, stat); 68 | await fs.promises.cp(itemSrc, target, { recursive: true }); 69 | } catch (e) { 70 | if (!_options.skipErrors) { 71 | throw Error(e); 72 | } else { 73 | console.log('Fail copy', e.code, e.info); 74 | } 75 | } 76 | }}); 77 | 78 | bar && bar.stop(); 79 | } 80 | 81 | -------------------------------------------------------------------------------- /builder/utils/morror.js: -------------------------------------------------------------------------------- 1 | const fs = require('fs'); 2 | 3 | module.exports = async function (srcPath, destPath) { 4 | const srcPathExists = fs.existsSync(srcPath); 5 | if (!srcPathExists) { 6 | await rm(destPath); 7 | } else { 8 | await fs.promises.cp(srcPath, destPath, { recursive: true }); 9 | } 10 | } 11 | 12 | async function rm (_path) { 13 | const exists = fs.existsSync(_path); 14 | if (exists) { 15 | const stat = await fs.promises.stat(_path); 16 | const isDir = stat.isDirectory(); 17 | if (isDir) { 18 | await fs.promises.rmdir(_path, { recursive: true }); 19 | } else { 20 | await fs.promises.unlink(_path); 21 | } 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /builder/utils/steps.js: -------------------------------------------------------------------------------- 1 | const colors = require('colors/safe'); 2 | 3 | module.exports = async function (steps) { 4 | for (let i = 0; i < steps.length; i++) { 5 | const step = steps[i]; 6 | const index = i + 1; 7 | console.log(colors.green(`Step ${index}/${steps.length}: ${step.name}`)); 8 | await step.fn(); 9 | } 10 | console.log(colors.green(`All steps Done.`)); 11 | } 12 | -------------------------------------------------------------------------------- /bypass/webgl/readme.md: -------------------------------------------------------------------------------- 1 | # How to use 2 | Replace %VENDOR% and %RENDERER% in script.txt 3 | Then read it and load it to puppeteer page 4 | 5 | If target.type() === "page" 6 | ```javascript 7 | await page.evaluateOnNewDocument(fs.readFileSync("script.txt", "UTF-8")) 8 | ``` 9 | If target.type() === "service_worker" 10 | ```javascript 11 | await page.evaluate(fs.readFileSync("script.txt", "UTF-8")) 12 | ``` 13 | -------------------------------------------------------------------------------- /bypass/webgl/script.js: -------------------------------------------------------------------------------- 1 | const config = { 2 | random: { 3 | value() { 4 | return Math.random(); 5 | }, 6 | item(e) { 7 | const rand = e.length * config.random.value(); 8 | return e[Math.floor(rand)]; 9 | }, 10 | array(e) { 11 | const rand = config.random.item(e); 12 | return new Int32Array([rand, rand]); 13 | }, 14 | items(e, n) { 15 | let { length } = e; 16 | const result = new Array(n); 17 | const taken = new Array(length); 18 | if (n > length) n = length; 19 | while (n--) { 20 | const i = Math.floor(config.random.value() * length); 21 | result[n] = e[i in taken ? taken[i] : i]; 22 | taken[i] = --length in taken ? taken[length] : length; 23 | } 24 | return result; 25 | }, 26 | }, 27 | 28 | spoof: { 29 | webgl: { 30 | parameter(target) { 31 | const { getParameter } = target.prototype; 32 | 33 | Object.defineProperty(target.prototype, "getParameter", { 34 | value() { 35 | const float32array = new Float32Array([1, 8192]); 36 | // 37 | if (arguments[0] === 37445) { 38 | return "%VENDOR%"; 39 | } 40 | // UNMASKED_RENDERER_WEBGL 41 | if (arguments[0] === 37446) { 42 | return "%RENDERER%"; 43 | } 44 | if (arguments[0] === 3415) return 0; 45 | if (arguments[0] === 3414) return 24; 46 | if (arguments[0] === 35661) { 47 | return config.random.items([128, 192, 256]); 48 | } 49 | if (arguments[0] === 3386) { 50 | return config.random.array([8192, 16384, 32768]); 51 | } 52 | if (arguments[0] === 36349 || arguments[0] === 36347) { 53 | return config.random.item([4096, 8192]); 54 | } 55 | if (arguments[0] === 34047 || arguments[0] === 34921) { 56 | return config.random.items([2, 4, 8, 16]); 57 | } 58 | if ( 59 | arguments[0] === 7937 || 60 | arguments[0] === 33901 || 61 | arguments[0] === 33902 62 | ) { 63 | return float32array; 64 | } 65 | if ( 66 | arguments[0] === 34930 || 67 | arguments[0] === 36348 || 68 | arguments[0] === 35660 69 | ) { 70 | return config.random.item([16, 32, 64]); 71 | } 72 | if ( 73 | arguments[0] === 34076 || 74 | arguments[0] === 34024 || 75 | arguments[0] === 3379 76 | ) { 77 | return config.random.item([16384, 32768]); 78 | } 79 | if ( 80 | arguments[0] === 3413 || 81 | arguments[0] === 3412 || 82 | arguments[0] === 3411 || 83 | arguments[0] === 3410 || 84 | arguments[0] === 34852 85 | ) { 86 | return config.random.item([2, 4, 8, 16]); 87 | } 88 | 89 | return getParameter.apply(this, arguments); 90 | }, 91 | }); 92 | }, 93 | }, 94 | }, 95 | }; 96 | // 97 | config.spoof.webgl.parameter(WebGLRenderingContext); 98 | config.spoof.webgl.parameter(WebGL2RenderingContext); 99 | -------------------------------------------------------------------------------- /configs/devices/device.json: -------------------------------------------------------------------------------- 1 | { 2 | "screen": { 3 | "availWidth": 1920, 4 | "availHeight": 1040, 5 | "availLeft": 0, 6 | "availTop": 0, 7 | "width": 1920, 8 | "height": 1080, 9 | "colorDepth": 24, 10 | "pixelDepth": 24 11 | }, 12 | "navigator": { 13 | "userAgent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/97.0.4692.99 Safari/537.36", 14 | "platform": "Win32", 15 | "deviceMemory": 2, 16 | "hardwareConcurrency": 2, 17 | "vendor": "Google Inc.", 18 | "vendorSub": "", 19 | "product": "Gecko", 20 | "productSub": "20030107" 21 | }, 22 | "fonts": { 23 | "MS Gothic": { 24 | "offsetWidth": 7, 25 | "offsetHeight": 2, 26 | "style": "oblique", 27 | "weight": "normal", 28 | "size": 11 29 | }, 30 | "Gabriola": { 31 | "offsetWidth": 5, 32 | "offsetHeight": 2, 33 | "style": "oblique", 34 | "weight": "bold", 35 | "size": 2 36 | }, 37 | "Times": { 38 | "offsetWidth": 6, 39 | "offsetHeight": 1, 40 | "style": "italic", 41 | "weight": "normal", 42 | "size": 3 43 | } 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /configs/dist.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | platforms: { 3 | darwin: { 4 | executablePath: 'Chromium.app/Contents/MacOS/Chromium', 5 | files: ['Chromium.app'] 6 | } 7 | }, 8 | copy: [ 9 | // 'Chromium Framework.framework', 10 | // 'Chromium Helper.app', 11 | // 'Chromium Helper (Plugin).app', 12 | // 'Chromium Helper (Renderer).app', 13 | ] 14 | }; 15 | -------------------------------------------------------------------------------- /configs/path.js: -------------------------------------------------------------------------------- 1 | const path = require('path'); 2 | 3 | const rootPath = path.join(__dirname, '../'); 4 | const buildPath = path.join(rootPath, '/build'); 5 | const chromiumPath = path.join(rootPath, '/chromium'); 6 | const updatesPath = path.join(rootPath, '/updates'); 7 | const outPath = path.join(buildPath, 'src/out/Default'); 8 | const depotToolsPath = path.join(rootPath, '/depot_tools'); 9 | const distPath = path.join(rootPath, '/dist'); 10 | 11 | module.exports = { 12 | rootPath, 13 | buildPath, 14 | chromiumPath, 15 | depotToolsPath, 16 | outPath, 17 | updatesPath, 18 | distPath 19 | } 20 | -------------------------------------------------------------------------------- /docs/development/macos.md: -------------------------------------------------------------------------------- 1 | ## Build Custom chromium 2 | 3 | npm run build 4 | 5 | ## Watch and build 6 | 7 | npm run watch 8 | 9 | ## Run Custom chromium 10 | 11 | cd /custom-chromium 12 | chromium/src/out/Default/Chromium.app/Contents/MacOS/Chromium --custom-screen-width=1500 --custom-screen-height=800 13 | 14 | ## Run Custom chromium from puppeteer 15 | 16 | npm run launch 17 | -------------------------------------------------------------------------------- /docs/setup/macos.md: -------------------------------------------------------------------------------- 1 | 2 | Original doc file [here](https://chromium.googlesource.com/chromium/src/+/main/docs/mac_build_instructions.md) 3 | 4 | ##System requirements: 5 | 1) A Mac, Intel or Arm. 6 | 2) [git](https://git-scm.com/book/en/v2/Getting-Started-Installing-Git), git comes with... 7 | ``` 8 | $ git --version 9 | ``` 10 | 3) [Xcode](https://developer.apple.com/xcode/), Xcode comes with... 11 | ``` 12 | $ ls `xcode-select -p`/Platforms/MacOSX.platform/Developer/SDKs 13 | ``` 14 | 4) [nodejs](https://nodejs.org/en/), nodejs comes with... 15 | ``` 16 | $ node -v 17 | ``` 18 | 19 | 20 | ## Setup 21 | Install node modules 22 | ``` 23 | $ npm install 24 | ``` 25 | 26 | Project setup (it's a very long process, be patient) 27 | ``` 28 | $ npm run setup 29 | ``` 30 | -------------------------------------------------------------------------------- /package-lock.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "custom-chromium", 3 | "version": "1.0.0", 4 | "lockfileVersion": 2, 5 | "requires": true, 6 | "packages": { 7 | "": { 8 | "name": "custom-chromium", 9 | "version": "1.0.0", 10 | "license": "ISC", 11 | "dependencies": { 12 | "cli-progress": "^3.10.0", 13 | "colors": "^1.4.0", 14 | "diff": "^5.0.0", 15 | "fs-extra": "^10.0.0", 16 | "get-folder-size": "2.0.1", 17 | "puppeteer": "^13.3.2", 18 | "safe-merge-files": "^0.2.3", 19 | "shelljs": "^0.8.5" 20 | } 21 | }, 22 | "node_modules/@types/node": { 23 | "version": "17.0.18", 24 | "resolved": "https://registry.npmjs.org/@types/node/-/node-17.0.18.tgz", 25 | "integrity": "sha512-eKj4f/BsN/qcculZiRSujogjvp5O/k4lOW5m35NopjZM/QwLOR075a8pJW5hD+Rtdm2DaCVPENS6KtSQnUD6BA==", 26 | "optional": true 27 | }, 28 | "node_modules/@types/yauzl": { 29 | "version": "2.9.2", 30 | "resolved": "https://registry.npmjs.org/@types/yauzl/-/yauzl-2.9.2.tgz", 31 | "integrity": "sha512-8uALY5LTvSuHgloDVUvWP3pIauILm+8/0pDMokuDYIoNsOkSwd5AiHBTSEJjKTDcZr5z8UpgOWZkxBF4iJftoA==", 32 | "optional": true, 33 | "dependencies": { 34 | "@types/node": "*" 35 | } 36 | }, 37 | "node_modules/agent-base": { 38 | "version": "6.0.2", 39 | "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", 40 | "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", 41 | "dependencies": { 42 | "debug": "4" 43 | }, 44 | "engines": { 45 | "node": ">= 6.0.0" 46 | } 47 | }, 48 | "node_modules/ansi-regex": { 49 | "version": "5.0.1", 50 | "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", 51 | "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", 52 | "engines": { 53 | "node": ">=8" 54 | } 55 | }, 56 | "node_modules/balanced-match": { 57 | "version": "1.0.2", 58 | "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", 59 | "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==" 60 | }, 61 | "node_modules/base64-js": { 62 | "version": "1.5.1", 63 | "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", 64 | "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==", 65 | "funding": [ 66 | { 67 | "type": "github", 68 | "url": "https://github.com/sponsors/feross" 69 | }, 70 | { 71 | "type": "patreon", 72 | "url": "https://www.patreon.com/feross" 73 | }, 74 | { 75 | "type": "consulting", 76 | "url": "https://feross.org/support" 77 | } 78 | ] 79 | }, 80 | "node_modules/bindings": { 81 | "version": "1.5.0", 82 | "resolved": "https://registry.npmjs.org/bindings/-/bindings-1.5.0.tgz", 83 | "integrity": "sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ==", 84 | "dependencies": { 85 | "file-uri-to-path": "1.0.0" 86 | } 87 | }, 88 | "node_modules/bl": { 89 | "version": "4.1.0", 90 | "resolved": "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz", 91 | "integrity": "sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==", 92 | "dependencies": { 93 | "buffer": "^5.5.0", 94 | "inherits": "^2.0.4", 95 | "readable-stream": "^3.4.0" 96 | } 97 | }, 98 | "node_modules/brace-expansion": { 99 | "version": "1.1.11", 100 | "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", 101 | "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", 102 | "dependencies": { 103 | "balanced-match": "^1.0.0", 104 | "concat-map": "0.0.1" 105 | } 106 | }, 107 | "node_modules/buffer": { 108 | "version": "5.7.1", 109 | "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz", 110 | "integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==", 111 | "funding": [ 112 | { 113 | "type": "github", 114 | "url": "https://github.com/sponsors/feross" 115 | }, 116 | { 117 | "type": "patreon", 118 | "url": "https://www.patreon.com/feross" 119 | }, 120 | { 121 | "type": "consulting", 122 | "url": "https://feross.org/support" 123 | } 124 | ], 125 | "dependencies": { 126 | "base64-js": "^1.3.1", 127 | "ieee754": "^1.1.13" 128 | } 129 | }, 130 | "node_modules/buffer-crc32": { 131 | "version": "0.2.13", 132 | "resolved": "https://registry.npmjs.org/buffer-crc32/-/buffer-crc32-0.2.13.tgz", 133 | "integrity": "sha1-DTM+PwDqxQqhRUq9MO+MKl2ackI=", 134 | "engines": { 135 | "node": "*" 136 | } 137 | }, 138 | "node_modules/chownr": { 139 | "version": "1.1.4", 140 | "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.4.tgz", 141 | "integrity": "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==" 142 | }, 143 | "node_modules/cli-progress": { 144 | "version": "3.10.0", 145 | "resolved": "https://registry.npmjs.org/cli-progress/-/cli-progress-3.10.0.tgz", 146 | "integrity": "sha512-kLORQrhYCAtUPLZxqsAt2YJGOvRdt34+O6jl5cQGb7iF3dM55FQZlTR+rQyIK9JUcO9bBMwZsTlND+3dmFU2Cw==", 147 | "dependencies": { 148 | "string-width": "^4.2.0" 149 | }, 150 | "engines": { 151 | "node": ">=4" 152 | } 153 | }, 154 | "node_modules/colors": { 155 | "version": "1.4.0", 156 | "resolved": "https://registry.npmjs.org/colors/-/colors-1.4.0.tgz", 157 | "integrity": "sha512-a+UqTh4kgZg/SlGvfbzDHpgRu7AAQOmmqRHJnxhRZICKFUT91brVhNNt58CMWU9PsBbv3PDCZUHbVxuDiH2mtA==", 158 | "engines": { 159 | "node": ">=0.1.90" 160 | } 161 | }, 162 | "node_modules/concat-map": { 163 | "version": "0.0.1", 164 | "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", 165 | "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=" 166 | }, 167 | "node_modules/cross-fetch": { 168 | "version": "3.1.5", 169 | "resolved": "https://registry.npmjs.org/cross-fetch/-/cross-fetch-3.1.5.tgz", 170 | "integrity": "sha512-lvb1SBsI0Z7GDwmuid+mU3kWVBwTVUbe7S0H52yaaAdQOXq2YktTCZdlAcNKFzE6QtRz0snpw9bNiPeOIkkQvw==", 171 | "dependencies": { 172 | "node-fetch": "2.6.7" 173 | } 174 | }, 175 | "node_modules/deasync": { 176 | "version": "0.1.24", 177 | "resolved": "https://registry.npmjs.org/deasync/-/deasync-0.1.24.tgz", 178 | "integrity": "sha512-i98vg42xNfRZCymummMAN0rIcQ1gZFinSe3btvPIvy6JFTaeHcumeKybRo2HTv86nasfmT0nEgAn2ggLZhOCVA==", 179 | "hasInstallScript": true, 180 | "dependencies": { 181 | "bindings": "^1.5.0", 182 | "node-addon-api": "^1.7.1" 183 | }, 184 | "engines": { 185 | "node": ">=0.11.0" 186 | } 187 | }, 188 | "node_modules/debug": { 189 | "version": "4.3.3", 190 | "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.3.tgz", 191 | "integrity": "sha512-/zxw5+vh1Tfv+4Qn7a5nsbcJKPaSvCDhojn6FEl9vupwK2VCSDtEiEtqr8DFtzYFOdz63LBkxec7DYuc2jon6Q==", 192 | "dependencies": { 193 | "ms": "2.1.2" 194 | }, 195 | "engines": { 196 | "node": ">=6.0" 197 | }, 198 | "peerDependenciesMeta": { 199 | "supports-color": { 200 | "optional": true 201 | } 202 | } 203 | }, 204 | "node_modules/devtools-protocol": { 205 | "version": "0.0.960912", 206 | "resolved": "https://registry.npmjs.org/devtools-protocol/-/devtools-protocol-0.0.960912.tgz", 207 | "integrity": "sha512-I3hWmV9rWHbdnUdmMKHF2NuYutIM2kXz2mdXW8ha7TbRlGTVs+PF+PsB5QWvpCek4Fy9B+msiispCfwlhG5Sqg==" 208 | }, 209 | "node_modules/diff": { 210 | "version": "5.0.0", 211 | "resolved": "https://registry.npmjs.org/diff/-/diff-5.0.0.tgz", 212 | "integrity": "sha512-/VTCrvm5Z0JGty/BWHljh+BAiw3IK+2j87NGMu8Nwc/f48WoDAC395uomO9ZD117ZOBaHmkX1oyLvkVM/aIT3w==", 213 | "engines": { 214 | "node": ">=0.3.1" 215 | } 216 | }, 217 | "node_modules/emoji-regex": { 218 | "version": "8.0.0", 219 | "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", 220 | "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" 221 | }, 222 | "node_modules/end-of-stream": { 223 | "version": "1.4.4", 224 | "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", 225 | "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==", 226 | "dependencies": { 227 | "once": "^1.4.0" 228 | } 229 | }, 230 | "node_modules/extract-zip": { 231 | "version": "2.0.1", 232 | "resolved": "https://registry.npmjs.org/extract-zip/-/extract-zip-2.0.1.tgz", 233 | "integrity": "sha512-GDhU9ntwuKyGXdZBUgTIe+vXnWj0fppUEtMDL0+idd5Sta8TGpHssn/eusA9mrPr9qNDym6SxAYZjNvCn/9RBg==", 234 | "dependencies": { 235 | "debug": "^4.1.1", 236 | "get-stream": "^5.1.0", 237 | "yauzl": "^2.10.0" 238 | }, 239 | "bin": { 240 | "extract-zip": "cli.js" 241 | }, 242 | "engines": { 243 | "node": ">= 10.17.0" 244 | }, 245 | "optionalDependencies": { 246 | "@types/yauzl": "^2.9.1" 247 | } 248 | }, 249 | "node_modules/fd-slicer": { 250 | "version": "1.1.0", 251 | "resolved": "https://registry.npmjs.org/fd-slicer/-/fd-slicer-1.1.0.tgz", 252 | "integrity": "sha1-JcfInLH5B3+IkbvmHY85Dq4lbx4=", 253 | "dependencies": { 254 | "pend": "~1.2.0" 255 | } 256 | }, 257 | "node_modules/file-uri-to-path": { 258 | "version": "1.0.0", 259 | "resolved": "https://registry.npmjs.org/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz", 260 | "integrity": "sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==" 261 | }, 262 | "node_modules/find-up": { 263 | "version": "4.1.0", 264 | "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", 265 | "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", 266 | "dependencies": { 267 | "locate-path": "^5.0.0", 268 | "path-exists": "^4.0.0" 269 | }, 270 | "engines": { 271 | "node": ">=8" 272 | } 273 | }, 274 | "node_modules/fs-constants": { 275 | "version": "1.0.0", 276 | "resolved": "https://registry.npmjs.org/fs-constants/-/fs-constants-1.0.0.tgz", 277 | "integrity": "sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==" 278 | }, 279 | "node_modules/fs-extra": { 280 | "version": "10.0.0", 281 | "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.0.0.tgz", 282 | "integrity": "sha512-C5owb14u9eJwizKGdchcDUQeFtlSHHthBk8pbX9Vc1PFZrLombudjDnNns88aYslCyF6IY5SUw3Roz6xShcEIQ==", 283 | "dependencies": { 284 | "graceful-fs": "^4.2.0", 285 | "jsonfile": "^6.0.1", 286 | "universalify": "^2.0.0" 287 | }, 288 | "engines": { 289 | "node": ">=12" 290 | } 291 | }, 292 | "node_modules/fs.realpath": { 293 | "version": "1.0.0", 294 | "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", 295 | "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=" 296 | }, 297 | "node_modules/function-bind": { 298 | "version": "1.1.1", 299 | "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", 300 | "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==" 301 | }, 302 | "node_modules/gar": { 303 | "version": "1.0.4", 304 | "resolved": "https://registry.npmjs.org/gar/-/gar-1.0.4.tgz", 305 | "integrity": "sha512-w4n9cPWyP7aHxKxYHFQMegj7WIAsL/YX/C4Bs5Rr8s1H9M1rNtRWRsw+ovYMkXDQ5S4ZbYHsHAPmevPjPgw44w==" 306 | }, 307 | "node_modules/get-folder-size": { 308 | "version": "2.0.1", 309 | "resolved": "https://registry.npmjs.org/get-folder-size/-/get-folder-size-2.0.1.tgz", 310 | "integrity": "sha512-+CEb+GDCM7tkOS2wdMKTn9vU7DgnKUTuDlehkNJKNSovdCOVxs14OfKCk4cvSaR3za4gj+OBdl9opPN9xrJ0zA==", 311 | "dependencies": { 312 | "gar": "^1.0.4", 313 | "tiny-each-async": "2.0.3" 314 | }, 315 | "bin": { 316 | "get-folder-size": "bin/get-folder-size" 317 | } 318 | }, 319 | "node_modules/get-stream": { 320 | "version": "5.2.0", 321 | "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.2.0.tgz", 322 | "integrity": "sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==", 323 | "dependencies": { 324 | "pump": "^3.0.0" 325 | }, 326 | "engines": { 327 | "node": ">=8" 328 | }, 329 | "funding": { 330 | "url": "https://github.com/sponsors/sindresorhus" 331 | } 332 | }, 333 | "node_modules/glob": { 334 | "version": "7.2.0", 335 | "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.0.tgz", 336 | "integrity": "sha512-lmLf6gtyrPq8tTjSmrO94wBeQbFR3HbLHbuyD69wuyQkImp2hWqMGB47OX65FBkPffO641IP9jWa1z4ivqG26Q==", 337 | "dependencies": { 338 | "fs.realpath": "^1.0.0", 339 | "inflight": "^1.0.4", 340 | "inherits": "2", 341 | "minimatch": "^3.0.4", 342 | "once": "^1.3.0", 343 | "path-is-absolute": "^1.0.0" 344 | }, 345 | "engines": { 346 | "node": "*" 347 | }, 348 | "funding": { 349 | "url": "https://github.com/sponsors/isaacs" 350 | } 351 | }, 352 | "node_modules/graceful-fs": { 353 | "version": "4.2.9", 354 | "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.9.tgz", 355 | "integrity": "sha512-NtNxqUcXgpW2iMrfqSfR73Glt39K+BLwWsPs94yR63v45T0Wbej7eRmL5cWfwEgqXnmjQp3zaJTshdRW/qC2ZQ==" 356 | }, 357 | "node_modules/has": { 358 | "version": "1.0.3", 359 | "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", 360 | "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", 361 | "dependencies": { 362 | "function-bind": "^1.1.1" 363 | }, 364 | "engines": { 365 | "node": ">= 0.4.0" 366 | } 367 | }, 368 | "node_modules/https-proxy-agent": { 369 | "version": "5.0.0", 370 | "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.0.tgz", 371 | "integrity": "sha512-EkYm5BcKUGiduxzSt3Eppko+PiNWNEpa4ySk9vTC6wDsQJW9rHSa+UhGNJoRYp7bz6Ht1eaRIa6QaJqO5rCFbA==", 372 | "dependencies": { 373 | "agent-base": "6", 374 | "debug": "4" 375 | }, 376 | "engines": { 377 | "node": ">= 6" 378 | } 379 | }, 380 | "node_modules/ieee754": { 381 | "version": "1.2.1", 382 | "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", 383 | "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==", 384 | "funding": [ 385 | { 386 | "type": "github", 387 | "url": "https://github.com/sponsors/feross" 388 | }, 389 | { 390 | "type": "patreon", 391 | "url": "https://www.patreon.com/feross" 392 | }, 393 | { 394 | "type": "consulting", 395 | "url": "https://feross.org/support" 396 | } 397 | ] 398 | }, 399 | "node_modules/inflight": { 400 | "version": "1.0.6", 401 | "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", 402 | "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", 403 | "dependencies": { 404 | "once": "^1.3.0", 405 | "wrappy": "1" 406 | } 407 | }, 408 | "node_modules/inherits": { 409 | "version": "2.0.4", 410 | "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", 411 | "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" 412 | }, 413 | "node_modules/interpret": { 414 | "version": "1.4.0", 415 | "resolved": "https://registry.npmjs.org/interpret/-/interpret-1.4.0.tgz", 416 | "integrity": "sha512-agE4QfB2Lkp9uICn7BAqoscw4SZP9kTE2hxiFI3jBPmXJfdqiahTbUuKGsMoN2GtqL9AxhYioAcVvgsb1HvRbA==", 417 | "engines": { 418 | "node": ">= 0.10" 419 | } 420 | }, 421 | "node_modules/is-core-module": { 422 | "version": "2.8.1", 423 | "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.8.1.tgz", 424 | "integrity": "sha512-SdNCUs284hr40hFTFP6l0IfZ/RSrMXF3qgoRHd3/79unUTvrFO/JoXwkGm+5J/Oe3E/b5GsnG330uUNgRpu1PA==", 425 | "dependencies": { 426 | "has": "^1.0.3" 427 | }, 428 | "funding": { 429 | "url": "https://github.com/sponsors/ljharb" 430 | } 431 | }, 432 | "node_modules/is-fullwidth-code-point": { 433 | "version": "3.0.0", 434 | "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", 435 | "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", 436 | "engines": { 437 | "node": ">=8" 438 | } 439 | }, 440 | "node_modules/jsonfile": { 441 | "version": "6.1.0", 442 | "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", 443 | "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", 444 | "dependencies": { 445 | "universalify": "^2.0.0" 446 | }, 447 | "optionalDependencies": { 448 | "graceful-fs": "^4.1.6" 449 | } 450 | }, 451 | "node_modules/locate-path": { 452 | "version": "5.0.0", 453 | "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", 454 | "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", 455 | "dependencies": { 456 | "p-locate": "^4.1.0" 457 | }, 458 | "engines": { 459 | "node": ">=8" 460 | } 461 | }, 462 | "node_modules/minimatch": { 463 | "version": "3.1.2", 464 | "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", 465 | "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", 466 | "dependencies": { 467 | "brace-expansion": "^1.1.7" 468 | }, 469 | "engines": { 470 | "node": "*" 471 | } 472 | }, 473 | "node_modules/mkdirp-classic": { 474 | "version": "0.5.3", 475 | "resolved": "https://registry.npmjs.org/mkdirp-classic/-/mkdirp-classic-0.5.3.tgz", 476 | "integrity": "sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A==" 477 | }, 478 | "node_modules/ms": { 479 | "version": "2.1.2", 480 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", 481 | "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" 482 | }, 483 | "node_modules/node-addon-api": { 484 | "version": "1.7.2", 485 | "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-1.7.2.tgz", 486 | "integrity": "sha512-ibPK3iA+vaY1eEjESkQkM0BbCqFOaZMiXRTtdB0u7b4djtY6JnsjvPdUHVMg6xQt3B8fpTTWHI9A+ADjM9frzg==" 487 | }, 488 | "node_modules/node-fetch": { 489 | "version": "2.6.7", 490 | "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.7.tgz", 491 | "integrity": "sha512-ZjMPFEfVx5j+y2yF35Kzx5sF7kDzxuDj6ziH4FFbOp87zKDZNx8yExJIb05OGF4Nlt9IHFIMBkRl41VdvcNdbQ==", 492 | "dependencies": { 493 | "whatwg-url": "^5.0.0" 494 | }, 495 | "engines": { 496 | "node": "4.x || >=6.0.0" 497 | }, 498 | "peerDependencies": { 499 | "encoding": "^0.1.0" 500 | }, 501 | "peerDependenciesMeta": { 502 | "encoding": { 503 | "optional": true 504 | } 505 | } 506 | }, 507 | "node_modules/once": { 508 | "version": "1.4.0", 509 | "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", 510 | "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", 511 | "dependencies": { 512 | "wrappy": "1" 513 | } 514 | }, 515 | "node_modules/p-limit": { 516 | "version": "2.3.0", 517 | "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", 518 | "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", 519 | "dependencies": { 520 | "p-try": "^2.0.0" 521 | }, 522 | "engines": { 523 | "node": ">=6" 524 | }, 525 | "funding": { 526 | "url": "https://github.com/sponsors/sindresorhus" 527 | } 528 | }, 529 | "node_modules/p-locate": { 530 | "version": "4.1.0", 531 | "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", 532 | "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", 533 | "dependencies": { 534 | "p-limit": "^2.2.0" 535 | }, 536 | "engines": { 537 | "node": ">=8" 538 | } 539 | }, 540 | "node_modules/p-try": { 541 | "version": "2.2.0", 542 | "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", 543 | "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", 544 | "engines": { 545 | "node": ">=6" 546 | } 547 | }, 548 | "node_modules/path-exists": { 549 | "version": "4.0.0", 550 | "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", 551 | "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", 552 | "engines": { 553 | "node": ">=8" 554 | } 555 | }, 556 | "node_modules/path-is-absolute": { 557 | "version": "1.0.1", 558 | "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", 559 | "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", 560 | "engines": { 561 | "node": ">=0.10.0" 562 | } 563 | }, 564 | "node_modules/path-parse": { 565 | "version": "1.0.7", 566 | "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", 567 | "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==" 568 | }, 569 | "node_modules/pend": { 570 | "version": "1.2.0", 571 | "resolved": "https://registry.npmjs.org/pend/-/pend-1.2.0.tgz", 572 | "integrity": "sha1-elfrVQpng/kRUzH89GY9XI4AelA=" 573 | }, 574 | "node_modules/pkg-dir": { 575 | "version": "4.2.0", 576 | "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-4.2.0.tgz", 577 | "integrity": "sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==", 578 | "dependencies": { 579 | "find-up": "^4.0.0" 580 | }, 581 | "engines": { 582 | "node": ">=8" 583 | } 584 | }, 585 | "node_modules/progress": { 586 | "version": "2.0.3", 587 | "resolved": "https://registry.npmjs.org/progress/-/progress-2.0.3.tgz", 588 | "integrity": "sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==", 589 | "engines": { 590 | "node": ">=0.4.0" 591 | } 592 | }, 593 | "node_modules/proxy-from-env": { 594 | "version": "1.1.0", 595 | "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz", 596 | "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==" 597 | }, 598 | "node_modules/pump": { 599 | "version": "3.0.0", 600 | "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", 601 | "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==", 602 | "dependencies": { 603 | "end-of-stream": "^1.1.0", 604 | "once": "^1.3.1" 605 | } 606 | }, 607 | "node_modules/puppeteer": { 608 | "version": "13.3.2", 609 | "resolved": "https://registry.npmjs.org/puppeteer/-/puppeteer-13.3.2.tgz", 610 | "integrity": "sha512-TIt8/R0eaUwY1c0/O0sCJpSglvGEWVoWFfGZ2dNtxX3eHuBo1ln9abaWfxTjZfsrkYATLSs8oqEdRZpMNnCsvg==", 611 | "hasInstallScript": true, 612 | "dependencies": { 613 | "cross-fetch": "3.1.5", 614 | "debug": "4.3.3", 615 | "devtools-protocol": "0.0.960912", 616 | "extract-zip": "2.0.1", 617 | "https-proxy-agent": "5.0.0", 618 | "pkg-dir": "4.2.0", 619 | "progress": "2.0.3", 620 | "proxy-from-env": "1.1.0", 621 | "rimraf": "3.0.2", 622 | "tar-fs": "2.1.1", 623 | "unbzip2-stream": "1.4.3", 624 | "ws": "8.5.0" 625 | }, 626 | "engines": { 627 | "node": ">=10.18.1" 628 | } 629 | }, 630 | "node_modules/readable-stream": { 631 | "version": "3.6.0", 632 | "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", 633 | "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", 634 | "dependencies": { 635 | "inherits": "^2.0.3", 636 | "string_decoder": "^1.1.1", 637 | "util-deprecate": "^1.0.1" 638 | }, 639 | "engines": { 640 | "node": ">= 6" 641 | } 642 | }, 643 | "node_modules/rechoir": { 644 | "version": "0.6.2", 645 | "resolved": "https://registry.npmjs.org/rechoir/-/rechoir-0.6.2.tgz", 646 | "integrity": "sha1-hSBLVNuoLVdC4oyWdW70OvUOM4Q=", 647 | "dependencies": { 648 | "resolve": "^1.1.6" 649 | }, 650 | "engines": { 651 | "node": ">= 0.10" 652 | } 653 | }, 654 | "node_modules/resolve": { 655 | "version": "1.22.0", 656 | "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.0.tgz", 657 | "integrity": "sha512-Hhtrw0nLeSrFQ7phPp4OOcVjLPIeMnRlr5mcnVuMe7M/7eBn98A3hmFRLoFo3DLZkivSYwhRUJTyPyWAk56WLw==", 658 | "dependencies": { 659 | "is-core-module": "^2.8.1", 660 | "path-parse": "^1.0.7", 661 | "supports-preserve-symlinks-flag": "^1.0.0" 662 | }, 663 | "bin": { 664 | "resolve": "bin/resolve" 665 | }, 666 | "funding": { 667 | "url": "https://github.com/sponsors/ljharb" 668 | } 669 | }, 670 | "node_modules/rimraf": { 671 | "version": "3.0.2", 672 | "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", 673 | "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", 674 | "dependencies": { 675 | "glob": "^7.1.3" 676 | }, 677 | "bin": { 678 | "rimraf": "bin.js" 679 | }, 680 | "funding": { 681 | "url": "https://github.com/sponsors/isaacs" 682 | } 683 | }, 684 | "node_modules/safe-buffer": { 685 | "version": "5.2.1", 686 | "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", 687 | "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", 688 | "funding": [ 689 | { 690 | "type": "github", 691 | "url": "https://github.com/sponsors/feross" 692 | }, 693 | { 694 | "type": "patreon", 695 | "url": "https://www.patreon.com/feross" 696 | }, 697 | { 698 | "type": "consulting", 699 | "url": "https://feross.org/support" 700 | } 701 | ] 702 | }, 703 | "node_modules/safe-merge-files": { 704 | "version": "0.2.3", 705 | "resolved": "https://registry.npmjs.org/safe-merge-files/-/safe-merge-files-0.2.3.tgz", 706 | "integrity": "sha512-Md4IMqk7xOCGZBPER1fDi72Rc3EOaMDFufmINCtW8mSpaBvAlYIQZOgDwnuj8HM5OXgqq/iREd5ZLCQMNsaglg==", 707 | "dependencies": { 708 | "deasync": "^0.1.14", 709 | "diff": "^4.0.1" 710 | } 711 | }, 712 | "node_modules/safe-merge-files/node_modules/diff": { 713 | "version": "4.0.2", 714 | "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz", 715 | "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==", 716 | "engines": { 717 | "node": ">=0.3.1" 718 | } 719 | }, 720 | "node_modules/shelljs": { 721 | "version": "0.8.5", 722 | "resolved": "https://registry.npmjs.org/shelljs/-/shelljs-0.8.5.tgz", 723 | "integrity": "sha512-TiwcRcrkhHvbrZbnRcFYMLl30Dfov3HKqzp5tO5b4pt6G/SezKcYhmDg15zXVBswHmctSAQKznqNW2LO5tTDow==", 724 | "dependencies": { 725 | "glob": "^7.0.0", 726 | "interpret": "^1.0.0", 727 | "rechoir": "^0.6.2" 728 | }, 729 | "bin": { 730 | "shjs": "bin/shjs" 731 | }, 732 | "engines": { 733 | "node": ">=4" 734 | } 735 | }, 736 | "node_modules/string_decoder": { 737 | "version": "1.3.0", 738 | "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", 739 | "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", 740 | "dependencies": { 741 | "safe-buffer": "~5.2.0" 742 | } 743 | }, 744 | "node_modules/string-width": { 745 | "version": "4.2.3", 746 | "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", 747 | "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", 748 | "dependencies": { 749 | "emoji-regex": "^8.0.0", 750 | "is-fullwidth-code-point": "^3.0.0", 751 | "strip-ansi": "^6.0.1" 752 | }, 753 | "engines": { 754 | "node": ">=8" 755 | } 756 | }, 757 | "node_modules/strip-ansi": { 758 | "version": "6.0.1", 759 | "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", 760 | "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", 761 | "dependencies": { 762 | "ansi-regex": "^5.0.1" 763 | }, 764 | "engines": { 765 | "node": ">=8" 766 | } 767 | }, 768 | "node_modules/supports-preserve-symlinks-flag": { 769 | "version": "1.0.0", 770 | "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", 771 | "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", 772 | "engines": { 773 | "node": ">= 0.4" 774 | }, 775 | "funding": { 776 | "url": "https://github.com/sponsors/ljharb" 777 | } 778 | }, 779 | "node_modules/tar-fs": { 780 | "version": "2.1.1", 781 | "resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-2.1.1.tgz", 782 | "integrity": "sha512-V0r2Y9scmbDRLCNex/+hYzvp/zyYjvFbHPNgVTKfQvVrb6guiE/fxP+XblDNR011utopbkex2nM4dHNV6GDsng==", 783 | "dependencies": { 784 | "chownr": "^1.1.1", 785 | "mkdirp-classic": "^0.5.2", 786 | "pump": "^3.0.0", 787 | "tar-stream": "^2.1.4" 788 | } 789 | }, 790 | "node_modules/tar-stream": { 791 | "version": "2.2.0", 792 | "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-2.2.0.tgz", 793 | "integrity": "sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ==", 794 | "dependencies": { 795 | "bl": "^4.0.3", 796 | "end-of-stream": "^1.4.1", 797 | "fs-constants": "^1.0.0", 798 | "inherits": "^2.0.3", 799 | "readable-stream": "^3.1.1" 800 | }, 801 | "engines": { 802 | "node": ">=6" 803 | } 804 | }, 805 | "node_modules/through": { 806 | "version": "2.3.8", 807 | "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", 808 | "integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=" 809 | }, 810 | "node_modules/tiny-each-async": { 811 | "version": "2.0.3", 812 | "resolved": "https://registry.npmjs.org/tiny-each-async/-/tiny-each-async-2.0.3.tgz", 813 | "integrity": "sha1-jru/1tYpXxNwAD+7NxYq/loKUdE=" 814 | }, 815 | "node_modules/tr46": { 816 | "version": "0.0.3", 817 | "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", 818 | "integrity": "sha1-gYT9NH2snNwYWZLzpmIuFLnZq2o=" 819 | }, 820 | "node_modules/unbzip2-stream": { 821 | "version": "1.4.3", 822 | "resolved": "https://registry.npmjs.org/unbzip2-stream/-/unbzip2-stream-1.4.3.tgz", 823 | "integrity": "sha512-mlExGW4w71ebDJviH16lQLtZS32VKqsSfk80GCfUlwT/4/hNRFsoscrF/c++9xinkMzECL1uL9DDwXqFWkruPg==", 824 | "dependencies": { 825 | "buffer": "^5.2.1", 826 | "through": "^2.3.8" 827 | } 828 | }, 829 | "node_modules/universalify": { 830 | "version": "2.0.0", 831 | "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz", 832 | "integrity": "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==", 833 | "engines": { 834 | "node": ">= 10.0.0" 835 | } 836 | }, 837 | "node_modules/util-deprecate": { 838 | "version": "1.0.2", 839 | "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", 840 | "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=" 841 | }, 842 | "node_modules/webidl-conversions": { 843 | "version": "3.0.1", 844 | "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", 845 | "integrity": "sha1-JFNCdeKnvGvnvIZhHMFq4KVlSHE=" 846 | }, 847 | "node_modules/whatwg-url": { 848 | "version": "5.0.0", 849 | "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", 850 | "integrity": "sha1-lmRU6HZUYuN2RNNib2dCzotwll0=", 851 | "dependencies": { 852 | "tr46": "~0.0.3", 853 | "webidl-conversions": "^3.0.0" 854 | } 855 | }, 856 | "node_modules/wrappy": { 857 | "version": "1.0.2", 858 | "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", 859 | "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=" 860 | }, 861 | "node_modules/ws": { 862 | "version": "8.5.0", 863 | "resolved": "https://registry.npmjs.org/ws/-/ws-8.5.0.tgz", 864 | "integrity": "sha512-BWX0SWVgLPzYwF8lTzEy1egjhS4S4OEAHfsO8o65WOVsrnSRGaSiUaa9e0ggGlkMTtBlmOpEXiie9RUcBO86qg==", 865 | "engines": { 866 | "node": ">=10.0.0" 867 | }, 868 | "peerDependencies": { 869 | "bufferutil": "^4.0.1", 870 | "utf-8-validate": "^5.0.2" 871 | }, 872 | "peerDependenciesMeta": { 873 | "bufferutil": { 874 | "optional": true 875 | }, 876 | "utf-8-validate": { 877 | "optional": true 878 | } 879 | } 880 | }, 881 | "node_modules/yauzl": { 882 | "version": "2.10.0", 883 | "resolved": "https://registry.npmjs.org/yauzl/-/yauzl-2.10.0.tgz", 884 | "integrity": "sha1-x+sXyT4RLLEIb6bY5R+wZnt5pfk=", 885 | "dependencies": { 886 | "buffer-crc32": "~0.2.3", 887 | "fd-slicer": "~1.1.0" 888 | } 889 | } 890 | }, 891 | "dependencies": { 892 | "@types/node": { 893 | "version": "17.0.18", 894 | "resolved": "https://registry.npmjs.org/@types/node/-/node-17.0.18.tgz", 895 | "integrity": "sha512-eKj4f/BsN/qcculZiRSujogjvp5O/k4lOW5m35NopjZM/QwLOR075a8pJW5hD+Rtdm2DaCVPENS6KtSQnUD6BA==", 896 | "optional": true 897 | }, 898 | "@types/yauzl": { 899 | "version": "2.9.2", 900 | "resolved": "https://registry.npmjs.org/@types/yauzl/-/yauzl-2.9.2.tgz", 901 | "integrity": "sha512-8uALY5LTvSuHgloDVUvWP3pIauILm+8/0pDMokuDYIoNsOkSwd5AiHBTSEJjKTDcZr5z8UpgOWZkxBF4iJftoA==", 902 | "optional": true, 903 | "requires": { 904 | "@types/node": "*" 905 | } 906 | }, 907 | "agent-base": { 908 | "version": "6.0.2", 909 | "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", 910 | "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", 911 | "requires": { 912 | "debug": "4" 913 | } 914 | }, 915 | "ansi-regex": { 916 | "version": "5.0.1", 917 | "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", 918 | "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==" 919 | }, 920 | "balanced-match": { 921 | "version": "1.0.2", 922 | "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", 923 | "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==" 924 | }, 925 | "base64-js": { 926 | "version": "1.5.1", 927 | "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", 928 | "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==" 929 | }, 930 | "bindings": { 931 | "version": "1.5.0", 932 | "resolved": "https://registry.npmjs.org/bindings/-/bindings-1.5.0.tgz", 933 | "integrity": "sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ==", 934 | "requires": { 935 | "file-uri-to-path": "1.0.0" 936 | } 937 | }, 938 | "bl": { 939 | "version": "4.1.0", 940 | "resolved": "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz", 941 | "integrity": "sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==", 942 | "requires": { 943 | "buffer": "^5.5.0", 944 | "inherits": "^2.0.4", 945 | "readable-stream": "^3.4.0" 946 | } 947 | }, 948 | "brace-expansion": { 949 | "version": "1.1.11", 950 | "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", 951 | "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", 952 | "requires": { 953 | "balanced-match": "^1.0.0", 954 | "concat-map": "0.0.1" 955 | } 956 | }, 957 | "buffer": { 958 | "version": "5.7.1", 959 | "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz", 960 | "integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==", 961 | "requires": { 962 | "base64-js": "^1.3.1", 963 | "ieee754": "^1.1.13" 964 | } 965 | }, 966 | "buffer-crc32": { 967 | "version": "0.2.13", 968 | "resolved": "https://registry.npmjs.org/buffer-crc32/-/buffer-crc32-0.2.13.tgz", 969 | "integrity": "sha1-DTM+PwDqxQqhRUq9MO+MKl2ackI=" 970 | }, 971 | "chownr": { 972 | "version": "1.1.4", 973 | "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.4.tgz", 974 | "integrity": "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==" 975 | }, 976 | "cli-progress": { 977 | "version": "3.10.0", 978 | "resolved": "https://registry.npmjs.org/cli-progress/-/cli-progress-3.10.0.tgz", 979 | "integrity": "sha512-kLORQrhYCAtUPLZxqsAt2YJGOvRdt34+O6jl5cQGb7iF3dM55FQZlTR+rQyIK9JUcO9bBMwZsTlND+3dmFU2Cw==", 980 | "requires": { 981 | "string-width": "^4.2.0" 982 | } 983 | }, 984 | "colors": { 985 | "version": "1.4.0", 986 | "resolved": "https://registry.npmjs.org/colors/-/colors-1.4.0.tgz", 987 | "integrity": "sha512-a+UqTh4kgZg/SlGvfbzDHpgRu7AAQOmmqRHJnxhRZICKFUT91brVhNNt58CMWU9PsBbv3PDCZUHbVxuDiH2mtA==" 988 | }, 989 | "concat-map": { 990 | "version": "0.0.1", 991 | "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", 992 | "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=" 993 | }, 994 | "cross-fetch": { 995 | "version": "3.1.5", 996 | "resolved": "https://registry.npmjs.org/cross-fetch/-/cross-fetch-3.1.5.tgz", 997 | "integrity": "sha512-lvb1SBsI0Z7GDwmuid+mU3kWVBwTVUbe7S0H52yaaAdQOXq2YktTCZdlAcNKFzE6QtRz0snpw9bNiPeOIkkQvw==", 998 | "requires": { 999 | "node-fetch": "2.6.7" 1000 | } 1001 | }, 1002 | "deasync": { 1003 | "version": "0.1.24", 1004 | "resolved": "https://registry.npmjs.org/deasync/-/deasync-0.1.24.tgz", 1005 | "integrity": "sha512-i98vg42xNfRZCymummMAN0rIcQ1gZFinSe3btvPIvy6JFTaeHcumeKybRo2HTv86nasfmT0nEgAn2ggLZhOCVA==", 1006 | "requires": { 1007 | "bindings": "^1.5.0", 1008 | "node-addon-api": "^1.7.1" 1009 | } 1010 | }, 1011 | "debug": { 1012 | "version": "4.3.3", 1013 | "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.3.tgz", 1014 | "integrity": "sha512-/zxw5+vh1Tfv+4Qn7a5nsbcJKPaSvCDhojn6FEl9vupwK2VCSDtEiEtqr8DFtzYFOdz63LBkxec7DYuc2jon6Q==", 1015 | "requires": { 1016 | "ms": "2.1.2" 1017 | } 1018 | }, 1019 | "devtools-protocol": { 1020 | "version": "0.0.960912", 1021 | "resolved": "https://registry.npmjs.org/devtools-protocol/-/devtools-protocol-0.0.960912.tgz", 1022 | "integrity": "sha512-I3hWmV9rWHbdnUdmMKHF2NuYutIM2kXz2mdXW8ha7TbRlGTVs+PF+PsB5QWvpCek4Fy9B+msiispCfwlhG5Sqg==" 1023 | }, 1024 | "diff": { 1025 | "version": "5.0.0", 1026 | "resolved": "https://registry.npmjs.org/diff/-/diff-5.0.0.tgz", 1027 | "integrity": "sha512-/VTCrvm5Z0JGty/BWHljh+BAiw3IK+2j87NGMu8Nwc/f48WoDAC395uomO9ZD117ZOBaHmkX1oyLvkVM/aIT3w==" 1028 | }, 1029 | "emoji-regex": { 1030 | "version": "8.0.0", 1031 | "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", 1032 | "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" 1033 | }, 1034 | "end-of-stream": { 1035 | "version": "1.4.4", 1036 | "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", 1037 | "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==", 1038 | "requires": { 1039 | "once": "^1.4.0" 1040 | } 1041 | }, 1042 | "extract-zip": { 1043 | "version": "2.0.1", 1044 | "resolved": "https://registry.npmjs.org/extract-zip/-/extract-zip-2.0.1.tgz", 1045 | "integrity": "sha512-GDhU9ntwuKyGXdZBUgTIe+vXnWj0fppUEtMDL0+idd5Sta8TGpHssn/eusA9mrPr9qNDym6SxAYZjNvCn/9RBg==", 1046 | "requires": { 1047 | "@types/yauzl": "^2.9.1", 1048 | "debug": "^4.1.1", 1049 | "get-stream": "^5.1.0", 1050 | "yauzl": "^2.10.0" 1051 | } 1052 | }, 1053 | "fd-slicer": { 1054 | "version": "1.1.0", 1055 | "resolved": "https://registry.npmjs.org/fd-slicer/-/fd-slicer-1.1.0.tgz", 1056 | "integrity": "sha1-JcfInLH5B3+IkbvmHY85Dq4lbx4=", 1057 | "requires": { 1058 | "pend": "~1.2.0" 1059 | } 1060 | }, 1061 | "file-uri-to-path": { 1062 | "version": "1.0.0", 1063 | "resolved": "https://registry.npmjs.org/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz", 1064 | "integrity": "sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==" 1065 | }, 1066 | "find-up": { 1067 | "version": "4.1.0", 1068 | "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", 1069 | "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", 1070 | "requires": { 1071 | "locate-path": "^5.0.0", 1072 | "path-exists": "^4.0.0" 1073 | } 1074 | }, 1075 | "fs-constants": { 1076 | "version": "1.0.0", 1077 | "resolved": "https://registry.npmjs.org/fs-constants/-/fs-constants-1.0.0.tgz", 1078 | "integrity": "sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==" 1079 | }, 1080 | "fs-extra": { 1081 | "version": "10.0.0", 1082 | "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.0.0.tgz", 1083 | "integrity": "sha512-C5owb14u9eJwizKGdchcDUQeFtlSHHthBk8pbX9Vc1PFZrLombudjDnNns88aYslCyF6IY5SUw3Roz6xShcEIQ==", 1084 | "requires": { 1085 | "graceful-fs": "^4.2.0", 1086 | "jsonfile": "^6.0.1", 1087 | "universalify": "^2.0.0" 1088 | } 1089 | }, 1090 | "fs.realpath": { 1091 | "version": "1.0.0", 1092 | "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", 1093 | "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=" 1094 | }, 1095 | "function-bind": { 1096 | "version": "1.1.1", 1097 | "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", 1098 | "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==" 1099 | }, 1100 | "gar": { 1101 | "version": "1.0.4", 1102 | "resolved": "https://registry.npmjs.org/gar/-/gar-1.0.4.tgz", 1103 | "integrity": "sha512-w4n9cPWyP7aHxKxYHFQMegj7WIAsL/YX/C4Bs5Rr8s1H9M1rNtRWRsw+ovYMkXDQ5S4ZbYHsHAPmevPjPgw44w==" 1104 | }, 1105 | "get-folder-size": { 1106 | "version": "2.0.1", 1107 | "resolved": "https://registry.npmjs.org/get-folder-size/-/get-folder-size-2.0.1.tgz", 1108 | "integrity": "sha512-+CEb+GDCM7tkOS2wdMKTn9vU7DgnKUTuDlehkNJKNSovdCOVxs14OfKCk4cvSaR3za4gj+OBdl9opPN9xrJ0zA==", 1109 | "requires": { 1110 | "gar": "^1.0.4", 1111 | "tiny-each-async": "2.0.3" 1112 | } 1113 | }, 1114 | "get-stream": { 1115 | "version": "5.2.0", 1116 | "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.2.0.tgz", 1117 | "integrity": "sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==", 1118 | "requires": { 1119 | "pump": "^3.0.0" 1120 | } 1121 | }, 1122 | "glob": { 1123 | "version": "7.2.0", 1124 | "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.0.tgz", 1125 | "integrity": "sha512-lmLf6gtyrPq8tTjSmrO94wBeQbFR3HbLHbuyD69wuyQkImp2hWqMGB47OX65FBkPffO641IP9jWa1z4ivqG26Q==", 1126 | "requires": { 1127 | "fs.realpath": "^1.0.0", 1128 | "inflight": "^1.0.4", 1129 | "inherits": "2", 1130 | "minimatch": "^3.0.4", 1131 | "once": "^1.3.0", 1132 | "path-is-absolute": "^1.0.0" 1133 | } 1134 | }, 1135 | "graceful-fs": { 1136 | "version": "4.2.9", 1137 | "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.9.tgz", 1138 | "integrity": "sha512-NtNxqUcXgpW2iMrfqSfR73Glt39K+BLwWsPs94yR63v45T0Wbej7eRmL5cWfwEgqXnmjQp3zaJTshdRW/qC2ZQ==" 1139 | }, 1140 | "has": { 1141 | "version": "1.0.3", 1142 | "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", 1143 | "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", 1144 | "requires": { 1145 | "function-bind": "^1.1.1" 1146 | } 1147 | }, 1148 | "https-proxy-agent": { 1149 | "version": "5.0.0", 1150 | "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.0.tgz", 1151 | "integrity": "sha512-EkYm5BcKUGiduxzSt3Eppko+PiNWNEpa4ySk9vTC6wDsQJW9rHSa+UhGNJoRYp7bz6Ht1eaRIa6QaJqO5rCFbA==", 1152 | "requires": { 1153 | "agent-base": "6", 1154 | "debug": "4" 1155 | } 1156 | }, 1157 | "ieee754": { 1158 | "version": "1.2.1", 1159 | "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", 1160 | "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==" 1161 | }, 1162 | "inflight": { 1163 | "version": "1.0.6", 1164 | "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", 1165 | "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", 1166 | "requires": { 1167 | "once": "^1.3.0", 1168 | "wrappy": "1" 1169 | } 1170 | }, 1171 | "inherits": { 1172 | "version": "2.0.4", 1173 | "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", 1174 | "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" 1175 | }, 1176 | "interpret": { 1177 | "version": "1.4.0", 1178 | "resolved": "https://registry.npmjs.org/interpret/-/interpret-1.4.0.tgz", 1179 | "integrity": "sha512-agE4QfB2Lkp9uICn7BAqoscw4SZP9kTE2hxiFI3jBPmXJfdqiahTbUuKGsMoN2GtqL9AxhYioAcVvgsb1HvRbA==" 1180 | }, 1181 | "is-core-module": { 1182 | "version": "2.8.1", 1183 | "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.8.1.tgz", 1184 | "integrity": "sha512-SdNCUs284hr40hFTFP6l0IfZ/RSrMXF3qgoRHd3/79unUTvrFO/JoXwkGm+5J/Oe3E/b5GsnG330uUNgRpu1PA==", 1185 | "requires": { 1186 | "has": "^1.0.3" 1187 | } 1188 | }, 1189 | "is-fullwidth-code-point": { 1190 | "version": "3.0.0", 1191 | "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", 1192 | "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==" 1193 | }, 1194 | "jsonfile": { 1195 | "version": "6.1.0", 1196 | "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", 1197 | "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", 1198 | "requires": { 1199 | "graceful-fs": "^4.1.6", 1200 | "universalify": "^2.0.0" 1201 | } 1202 | }, 1203 | "locate-path": { 1204 | "version": "5.0.0", 1205 | "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", 1206 | "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", 1207 | "requires": { 1208 | "p-locate": "^4.1.0" 1209 | } 1210 | }, 1211 | "minimatch": { 1212 | "version": "3.1.2", 1213 | "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", 1214 | "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", 1215 | "requires": { 1216 | "brace-expansion": "^1.1.7" 1217 | } 1218 | }, 1219 | "mkdirp-classic": { 1220 | "version": "0.5.3", 1221 | "resolved": "https://registry.npmjs.org/mkdirp-classic/-/mkdirp-classic-0.5.3.tgz", 1222 | "integrity": "sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A==" 1223 | }, 1224 | "ms": { 1225 | "version": "2.1.2", 1226 | "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", 1227 | "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" 1228 | }, 1229 | "node-addon-api": { 1230 | "version": "1.7.2", 1231 | "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-1.7.2.tgz", 1232 | "integrity": "sha512-ibPK3iA+vaY1eEjESkQkM0BbCqFOaZMiXRTtdB0u7b4djtY6JnsjvPdUHVMg6xQt3B8fpTTWHI9A+ADjM9frzg==" 1233 | }, 1234 | "node-fetch": { 1235 | "version": "2.6.7", 1236 | "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.7.tgz", 1237 | "integrity": "sha512-ZjMPFEfVx5j+y2yF35Kzx5sF7kDzxuDj6ziH4FFbOp87zKDZNx8yExJIb05OGF4Nlt9IHFIMBkRl41VdvcNdbQ==", 1238 | "requires": { 1239 | "whatwg-url": "^5.0.0" 1240 | } 1241 | }, 1242 | "once": { 1243 | "version": "1.4.0", 1244 | "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", 1245 | "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", 1246 | "requires": { 1247 | "wrappy": "1" 1248 | } 1249 | }, 1250 | "p-limit": { 1251 | "version": "2.3.0", 1252 | "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", 1253 | "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", 1254 | "requires": { 1255 | "p-try": "^2.0.0" 1256 | } 1257 | }, 1258 | "p-locate": { 1259 | "version": "4.1.0", 1260 | "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", 1261 | "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", 1262 | "requires": { 1263 | "p-limit": "^2.2.0" 1264 | } 1265 | }, 1266 | "p-try": { 1267 | "version": "2.2.0", 1268 | "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", 1269 | "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==" 1270 | }, 1271 | "path-exists": { 1272 | "version": "4.0.0", 1273 | "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", 1274 | "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==" 1275 | }, 1276 | "path-is-absolute": { 1277 | "version": "1.0.1", 1278 | "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", 1279 | "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=" 1280 | }, 1281 | "path-parse": { 1282 | "version": "1.0.7", 1283 | "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", 1284 | "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==" 1285 | }, 1286 | "pend": { 1287 | "version": "1.2.0", 1288 | "resolved": "https://registry.npmjs.org/pend/-/pend-1.2.0.tgz", 1289 | "integrity": "sha1-elfrVQpng/kRUzH89GY9XI4AelA=" 1290 | }, 1291 | "pkg-dir": { 1292 | "version": "4.2.0", 1293 | "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-4.2.0.tgz", 1294 | "integrity": "sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==", 1295 | "requires": { 1296 | "find-up": "^4.0.0" 1297 | } 1298 | }, 1299 | "progress": { 1300 | "version": "2.0.3", 1301 | "resolved": "https://registry.npmjs.org/progress/-/progress-2.0.3.tgz", 1302 | "integrity": "sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==" 1303 | }, 1304 | "proxy-from-env": { 1305 | "version": "1.1.0", 1306 | "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz", 1307 | "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==" 1308 | }, 1309 | "pump": { 1310 | "version": "3.0.0", 1311 | "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", 1312 | "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==", 1313 | "requires": { 1314 | "end-of-stream": "^1.1.0", 1315 | "once": "^1.3.1" 1316 | } 1317 | }, 1318 | "puppeteer": { 1319 | "version": "13.3.2", 1320 | "resolved": "https://registry.npmjs.org/puppeteer/-/puppeteer-13.3.2.tgz", 1321 | "integrity": "sha512-TIt8/R0eaUwY1c0/O0sCJpSglvGEWVoWFfGZ2dNtxX3eHuBo1ln9abaWfxTjZfsrkYATLSs8oqEdRZpMNnCsvg==", 1322 | "requires": { 1323 | "cross-fetch": "3.1.5", 1324 | "debug": "4.3.3", 1325 | "devtools-protocol": "0.0.960912", 1326 | "extract-zip": "2.0.1", 1327 | "https-proxy-agent": "5.0.0", 1328 | "pkg-dir": "4.2.0", 1329 | "progress": "2.0.3", 1330 | "proxy-from-env": "1.1.0", 1331 | "rimraf": "3.0.2", 1332 | "tar-fs": "2.1.1", 1333 | "unbzip2-stream": "1.4.3", 1334 | "ws": "8.5.0" 1335 | } 1336 | }, 1337 | "readable-stream": { 1338 | "version": "3.6.0", 1339 | "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", 1340 | "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", 1341 | "requires": { 1342 | "inherits": "^2.0.3", 1343 | "string_decoder": "^1.1.1", 1344 | "util-deprecate": "^1.0.1" 1345 | } 1346 | }, 1347 | "rechoir": { 1348 | "version": "0.6.2", 1349 | "resolved": "https://registry.npmjs.org/rechoir/-/rechoir-0.6.2.tgz", 1350 | "integrity": "sha1-hSBLVNuoLVdC4oyWdW70OvUOM4Q=", 1351 | "requires": { 1352 | "resolve": "^1.1.6" 1353 | } 1354 | }, 1355 | "resolve": { 1356 | "version": "1.22.0", 1357 | "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.0.tgz", 1358 | "integrity": "sha512-Hhtrw0nLeSrFQ7phPp4OOcVjLPIeMnRlr5mcnVuMe7M/7eBn98A3hmFRLoFo3DLZkivSYwhRUJTyPyWAk56WLw==", 1359 | "requires": { 1360 | "is-core-module": "^2.8.1", 1361 | "path-parse": "^1.0.7", 1362 | "supports-preserve-symlinks-flag": "^1.0.0" 1363 | } 1364 | }, 1365 | "rimraf": { 1366 | "version": "3.0.2", 1367 | "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", 1368 | "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", 1369 | "requires": { 1370 | "glob": "^7.1.3" 1371 | } 1372 | }, 1373 | "safe-buffer": { 1374 | "version": "5.2.1", 1375 | "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", 1376 | "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==" 1377 | }, 1378 | "safe-merge-files": { 1379 | "version": "0.2.3", 1380 | "resolved": "https://registry.npmjs.org/safe-merge-files/-/safe-merge-files-0.2.3.tgz", 1381 | "integrity": "sha512-Md4IMqk7xOCGZBPER1fDi72Rc3EOaMDFufmINCtW8mSpaBvAlYIQZOgDwnuj8HM5OXgqq/iREd5ZLCQMNsaglg==", 1382 | "requires": { 1383 | "deasync": "^0.1.14", 1384 | "diff": "^4.0.1" 1385 | }, 1386 | "dependencies": { 1387 | "diff": { 1388 | "version": "4.0.2", 1389 | "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz", 1390 | "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==" 1391 | } 1392 | } 1393 | }, 1394 | "shelljs": { 1395 | "version": "0.8.5", 1396 | "resolved": "https://registry.npmjs.org/shelljs/-/shelljs-0.8.5.tgz", 1397 | "integrity": "sha512-TiwcRcrkhHvbrZbnRcFYMLl30Dfov3HKqzp5tO5b4pt6G/SezKcYhmDg15zXVBswHmctSAQKznqNW2LO5tTDow==", 1398 | "requires": { 1399 | "glob": "^7.0.0", 1400 | "interpret": "^1.0.0", 1401 | "rechoir": "^0.6.2" 1402 | } 1403 | }, 1404 | "string_decoder": { 1405 | "version": "1.3.0", 1406 | "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", 1407 | "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", 1408 | "requires": { 1409 | "safe-buffer": "~5.2.0" 1410 | } 1411 | }, 1412 | "string-width": { 1413 | "version": "4.2.3", 1414 | "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", 1415 | "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", 1416 | "requires": { 1417 | "emoji-regex": "^8.0.0", 1418 | "is-fullwidth-code-point": "^3.0.0", 1419 | "strip-ansi": "^6.0.1" 1420 | } 1421 | }, 1422 | "strip-ansi": { 1423 | "version": "6.0.1", 1424 | "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", 1425 | "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", 1426 | "requires": { 1427 | "ansi-regex": "^5.0.1" 1428 | } 1429 | }, 1430 | "supports-preserve-symlinks-flag": { 1431 | "version": "1.0.0", 1432 | "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", 1433 | "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==" 1434 | }, 1435 | "tar-fs": { 1436 | "version": "2.1.1", 1437 | "resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-2.1.1.tgz", 1438 | "integrity": "sha512-V0r2Y9scmbDRLCNex/+hYzvp/zyYjvFbHPNgVTKfQvVrb6guiE/fxP+XblDNR011utopbkex2nM4dHNV6GDsng==", 1439 | "requires": { 1440 | "chownr": "^1.1.1", 1441 | "mkdirp-classic": "^0.5.2", 1442 | "pump": "^3.0.0", 1443 | "tar-stream": "^2.1.4" 1444 | } 1445 | }, 1446 | "tar-stream": { 1447 | "version": "2.2.0", 1448 | "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-2.2.0.tgz", 1449 | "integrity": "sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ==", 1450 | "requires": { 1451 | "bl": "^4.0.3", 1452 | "end-of-stream": "^1.4.1", 1453 | "fs-constants": "^1.0.0", 1454 | "inherits": "^2.0.3", 1455 | "readable-stream": "^3.1.1" 1456 | } 1457 | }, 1458 | "through": { 1459 | "version": "2.3.8", 1460 | "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", 1461 | "integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=" 1462 | }, 1463 | "tiny-each-async": { 1464 | "version": "2.0.3", 1465 | "resolved": "https://registry.npmjs.org/tiny-each-async/-/tiny-each-async-2.0.3.tgz", 1466 | "integrity": "sha1-jru/1tYpXxNwAD+7NxYq/loKUdE=" 1467 | }, 1468 | "tr46": { 1469 | "version": "0.0.3", 1470 | "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", 1471 | "integrity": "sha1-gYT9NH2snNwYWZLzpmIuFLnZq2o=" 1472 | }, 1473 | "unbzip2-stream": { 1474 | "version": "1.4.3", 1475 | "resolved": "https://registry.npmjs.org/unbzip2-stream/-/unbzip2-stream-1.4.3.tgz", 1476 | "integrity": "sha512-mlExGW4w71ebDJviH16lQLtZS32VKqsSfk80GCfUlwT/4/hNRFsoscrF/c++9xinkMzECL1uL9DDwXqFWkruPg==", 1477 | "requires": { 1478 | "buffer": "^5.2.1", 1479 | "through": "^2.3.8" 1480 | } 1481 | }, 1482 | "universalify": { 1483 | "version": "2.0.0", 1484 | "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz", 1485 | "integrity": "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==" 1486 | }, 1487 | "util-deprecate": { 1488 | "version": "1.0.2", 1489 | "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", 1490 | "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=" 1491 | }, 1492 | "webidl-conversions": { 1493 | "version": "3.0.1", 1494 | "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", 1495 | "integrity": "sha1-JFNCdeKnvGvnvIZhHMFq4KVlSHE=" 1496 | }, 1497 | "whatwg-url": { 1498 | "version": "5.0.0", 1499 | "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", 1500 | "integrity": "sha1-lmRU6HZUYuN2RNNib2dCzotwll0=", 1501 | "requires": { 1502 | "tr46": "~0.0.3", 1503 | "webidl-conversions": "^3.0.0" 1504 | } 1505 | }, 1506 | "wrappy": { 1507 | "version": "1.0.2", 1508 | "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", 1509 | "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=" 1510 | }, 1511 | "ws": { 1512 | "version": "8.5.0", 1513 | "resolved": "https://registry.npmjs.org/ws/-/ws-8.5.0.tgz", 1514 | "integrity": "sha512-BWX0SWVgLPzYwF8lTzEy1egjhS4S4OEAHfsO8o65WOVsrnSRGaSiUaa9e0ggGlkMTtBlmOpEXiie9RUcBO86qg==", 1515 | "requires": {} 1516 | }, 1517 | "yauzl": { 1518 | "version": "2.10.0", 1519 | "resolved": "https://registry.npmjs.org/yauzl/-/yauzl-2.10.0.tgz", 1520 | "integrity": "sha1-x+sXyT4RLLEIb6bY5R+wZnt5pfk=", 1521 | "requires": { 1522 | "buffer-crc32": "~0.2.3", 1523 | "fd-slicer": "~1.1.0" 1524 | } 1525 | } 1526 | } 1527 | } 1528 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "custom-chromium", 3 | "version": "2.0.0", 4 | "description": "", 5 | "main": "index.js", 6 | "scripts": { 7 | "setup": "node ./builder/cmd/setup.js", 8 | "restore": "node ./builder/cmd/restore.js", 9 | "launch": "node ./builder/cmd/launch.js", 10 | "build": "node ./builder/cmd/build.js", 11 | "gen": "node ./builder/cmd/gen.js", 12 | "dist": "node ./builder/cmd/dist.js" 13 | }, 14 | "author": "", 15 | "license": "ISC", 16 | "dependencies": { 17 | "cli-progress": "^3.10.0", 18 | "colors": "^1.4.0", 19 | "diff": "^5.0.0", 20 | "fs-extra": "^10.0.0", 21 | "get-folder-size": "2.0.1", 22 | "puppeteer": "^13.3.2", 23 | "safe-merge-files": "^0.2.3", 24 | "shelljs": "^0.8.5" 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /updates/src/base/base_switches.cc: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2012 The Chromium Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style license that can be 3 | // found in the LICENSE file. 4 | 5 | #include "base/base_switches.h" 6 | #include "build/build_config.h" 7 | #include "build/chromeos_buildflags.h" 8 | 9 | namespace switches { 10 | //START-UPDATES 11 | const char kCustomDeviceData[] = "custom-device-data"; 12 | //END-UPDATES 13 | 14 | // Delays execution of TaskPriority::BEST_EFFORT tasks until shutdown. 15 | const char kDisableBestEffortTasks[] = "disable-best-effort-tasks"; 16 | 17 | // Disables the crash reporting. 18 | const char kDisableBreakpad[] = "disable-breakpad"; 19 | 20 | // Comma-separated list of feature names to disable. See also kEnableFeatures. 21 | const char kDisableFeatures[] = "disable-features"; 22 | 23 | // Force disabling of low-end device mode when set. 24 | const char kDisableLowEndDeviceMode[] = "disable-low-end-device-mode"; 25 | 26 | // Indicates that crash reporting should be enabled. On platforms where helper 27 | // processes cannot access to files needed to make this decision, this flag is 28 | // generated internally. 29 | const char kEnableCrashReporter[] = "enable-crash-reporter"; 30 | 31 | // Comma-separated list of feature names to enable. See also kDisableFeatures. 32 | const char kEnableFeatures[] = "enable-features"; 33 | 34 | // Force low-end device mode when set. 35 | const char kEnableLowEndDeviceMode[] = "enable-low-end-device-mode"; 36 | 37 | // Enable the use of background thread priorities for background tasks in the 38 | // ThreadPool even on systems where it is disabled by default, e.g. due to 39 | // concerns about priority inversions. 40 | const char kEnableBackgroundThreadPool[] = "enable-background-thread-pool"; 41 | 42 | // Handle to the shared memory segment containing field trial state that is to 43 | // be shared between processes. The argument to this switch is made of 4 44 | // segments, separated by commas: 45 | // 1. The platform-specific handle id for the shared memory as a string. 46 | // 2. The high 64 bits of the shared memory block GUID. 47 | // 3. The low 64 bits of the shared memory block GUID. 48 | // 4. The size of the shared memory segment as a string. 49 | const char kFieldTrialHandle[] = "field-trial-handle"; 50 | 51 | // This option can be used to force field trials when testing changes locally. 52 | // The argument is a list of name and value pairs, separated by slashes. If a 53 | // trial name is prefixed with an asterisk, that trial will start activated. 54 | // For example, the following argument defines two trials, with the second one 55 | // activated: "GoogleNow/Enable/*MaterialDesignNTP/Default/" This option can 56 | // also be used by the browser process to send the list of trials to a 57 | // non-browser process, using the same format. See 58 | // FieldTrialList::CreateTrialsFromString() in field_trial.h for details. 59 | const char kForceFieldTrials[] = "force-fieldtrials"; 60 | 61 | // Generates full memory crash dump. 62 | const char kFullMemoryCrashReport[] = "full-memory-crash-report"; 63 | 64 | // Logs information about all tasks posted with TaskPriority::BEST_EFFORT. Use 65 | // this to diagnose issues that are thought to be caused by 66 | // TaskPriority::BEST_EFFORT execution fences. Note: Tasks posted to a 67 | // non-BEST_EFFORT UpdateableSequencedTaskRunner whose priority is later lowered 68 | // to BEST_EFFORT are not logged. 69 | const char kLogBestEffortTasks[] = "log-best-effort-tasks"; 70 | 71 | // Suppresses all error dialogs when present. 72 | const char kNoErrorDialogs[] = "noerrdialogs"; 73 | 74 | // Starts the sampling based profiler for the browser process at startup. This 75 | // will only work if chrome has been built with the gn arg enable_profiling = 76 | // true. The output will go to the value of kProfilingFile. 77 | const char kProfilingAtStart[] = "profiling-at-start"; 78 | 79 | // Specifies a location for profiling output. This will only work if chrome has 80 | // been built with the gyp variable profiling=1 or gn arg enable_profiling=true. 81 | // 82 | // {pid} if present will be replaced by the pid of the process. 83 | // {count} if present will be incremented each time a profile is generated 84 | // for this process. 85 | // The default is chrome-profile-{pid} for the browser and test-profile-{pid} 86 | // for tests. 87 | const char kProfilingFile[] = "profiling-file"; 88 | 89 | // Controls whether profile data is periodically flushed to a file. Normally 90 | // the data gets written on exit but cases exist where chromium doesn't exit 91 | // cleanly (especially when using single-process). A time in seconds can be 92 | // specified. 93 | const char kProfilingFlush[] = "profiling-flush"; 94 | 95 | // When running certain tests that spawn child processes, this switch indicates 96 | // to the test framework that the current process is a child process. 97 | const char kTestChildProcess[] = "test-child-process"; 98 | 99 | // When running certain tests that spawn child processes, this switch indicates 100 | // to the test framework that the current process should not initialize ICU to 101 | // avoid creating any scoped handles too early in startup. 102 | const char kTestDoNotInitializeIcu[] = "test-do-not-initialize-icu"; 103 | 104 | // Sends trace events from these categories to a file. 105 | // --trace-to-file on its own sends to default categories. 106 | const char kTraceToFile[] = "trace-to-file"; 107 | 108 | // Specifies the file name for --trace-to-file. If unspecified, it will 109 | // go to a default file name. 110 | const char kTraceToFileName[] = "trace-to-file-name"; 111 | 112 | // Gives the default maximal active V-logging level; 0 is the default. 113 | // Normally positive values are used for V-logging levels. 114 | const char kV[] = "v"; 115 | 116 | // Gives the per-module maximal V-logging levels to override the value 117 | // given by --v. E.g. "my_module=2,foo*=3" would change the logging 118 | // level for all code in source files "my_module.*" and "foo*.*" 119 | // ("-inl" suffixes are also disregarded for this matching). 120 | // 121 | // Any pattern containing a forward or backward slash will be tested 122 | // against the whole pathname and not just the module. E.g., 123 | // "*/foo/bar/*=2" would change the logging level for all code in 124 | // source files under a "foo/bar" directory. 125 | const char kVModule[] = "vmodule"; 126 | 127 | // Will wait for 60 seconds for a debugger to come to attach to the process. 128 | const char kWaitForDebugger[] = "wait-for-debugger"; 129 | 130 | #if BUILDFLAG(IS_WIN) 131 | // Disable high-resolution timer on Windows. 132 | const char kDisableHighResTimer[] = "disable-highres-timer"; 133 | 134 | // Disables the USB keyboard detection for blocking the OSK on Win8+. 135 | const char kDisableUsbKeyboardDetect[] = "disable-usb-keyboard-detect"; 136 | #endif 137 | 138 | // TODO(crbug.com/1052397): Revisit the macro expression once build flag switch 139 | // of lacros-chrome is complete. 140 | #if BUILDFLAG(IS_LINUX) && !BUILDFLAG(IS_CHROMEOS_ASH) && \ 141 | !BUILDFLAG(IS_CHROMEOS_LACROS) 142 | // The /dev/shm partition is too small in certain VM environments, causing 143 | // Chrome to fail or crash (see http://crbug.com/715363). Use this flag to 144 | // work-around this issue (a temporary directory will always be used to create 145 | // anonymous shared memory files). 146 | const char kDisableDevShmUsage[] = "disable-dev-shm-usage"; 147 | #endif 148 | 149 | #if BUILDFLAG(IS_POSIX) 150 | // Used for turning on Breakpad crash reporting in a debug environment where 151 | // crash reporting is typically compiled but disabled. 152 | const char kEnableCrashReporterForTesting[] = 153 | "enable-crash-reporter-for-testing"; 154 | #endif 155 | 156 | #if BUILDFLAG(IS_ANDROID) 157 | // Enables the reached code profiler that samples all threads in all processes 158 | // to determine which functions are almost never executed. 159 | const char kEnableReachedCodeProfiler[] = "enable-reached-code-profiler"; 160 | 161 | // Specifies the profiling interval in microseconds for reached code profiler. 162 | const char kReachedCodeSamplingIntervalUs[] = 163 | "reached-code-sampling-interval-us"; 164 | 165 | // Default country code to be used for search engine localization. 166 | const char kDefaultCountryCodeAtInstall[] = "default-country-code"; 167 | 168 | // Adds additional thread idle time information into the trace event output. 169 | const char kEnableIdleTracing[] = "enable-idle-tracing"; 170 | 171 | // The field trial parameters and their values when testing changes locally. 172 | const char kForceFieldTrialParams[] = "force-fieldtrial-params"; 173 | 174 | #endif 175 | 176 | #if BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS) 177 | // Controls whether or not retired instruction counts are surfaced for threads 178 | // in trace events on Linux. 179 | // 180 | // This flag requires the BPF sandbox to be disabled. 181 | const char kEnableThreadInstructionCount[] = "enable-thread-instruction-count"; 182 | 183 | // TODO(crbug.com/1176772): Remove kEnableCrashpad and IsCrashpadEnabled() when 184 | // Crashpad is fully enabled on Linux. Indicates that Crashpad should be 185 | // enabled. 186 | extern const char kEnableCrashpad[] = "enable-crashpad"; 187 | #endif 188 | 189 | #if BUILDFLAG(IS_CHROMEOS_ASH) || BUILDFLAG(IS_CHROMEOS_LACROS) 190 | // Override the default scheduling boosting value for urgent tasks. 191 | // This can be adjusted if a specific chromeos device shows better perf/power 192 | // ratio (e.g. by running video conference tests). 193 | // Currently, this values directs to linux scheduler's utilization min clamp. 194 | // Range is 0(no biased load) ~ 100(mamximum load value). 195 | const char kSchedulerBoostUrgent[] = "scheduler-boost-urgent"; 196 | #endif 197 | 198 | } // namespace switches 199 | -------------------------------------------------------------------------------- /updates/src/base/base_switches.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2012 The Chromium Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style license that can be 3 | // found in the LICENSE file. 4 | 5 | // Defines all the "base" command-line switches. 6 | 7 | #ifndef BASE_BASE_SWITCHES_H_ 8 | #define BASE_BASE_SWITCHES_H_ 9 | 10 | #include "build/build_config.h" 11 | #include "build/chromeos_buildflags.h" 12 | 13 | namespace switches { 14 | //START-UPDATES 15 | extern const char kCustomDeviceData[]; 16 | //END-UPDATES 17 | 18 | extern const char kDisableBestEffortTasks[]; 19 | extern const char kDisableBreakpad[]; 20 | extern const char kDisableFeatures[]; 21 | extern const char kDisableLowEndDeviceMode[]; 22 | extern const char kEnableCrashReporter[]; 23 | extern const char kEnableFeatures[]; 24 | extern const char kEnableLowEndDeviceMode[]; 25 | extern const char kEnableBackgroundThreadPool[]; 26 | extern const char kFieldTrialHandle[]; 27 | extern const char kForceFieldTrials[]; 28 | extern const char kFullMemoryCrashReport[]; 29 | extern const char kLogBestEffortTasks[]; 30 | extern const char kNoErrorDialogs[]; 31 | extern const char kProfilingAtStart[]; 32 | extern const char kProfilingFile[]; 33 | extern const char kProfilingFlush[]; 34 | extern const char kTestChildProcess[]; 35 | extern const char kTestDoNotInitializeIcu[]; 36 | extern const char kTraceToFile[]; 37 | extern const char kTraceToFileName[]; 38 | extern const char kV[]; 39 | extern const char kVModule[]; 40 | extern const char kWaitForDebugger[]; 41 | 42 | #if BUILDFLAG(IS_WIN) 43 | extern const char kDisableHighResTimer[]; 44 | extern const char kDisableUsbKeyboardDetect[]; 45 | #endif 46 | 47 | // TODO(crbug.com/1052397): Revisit the macro expression once build flag switch 48 | // of lacros-chrome is complete. 49 | #if BUILDFLAG(IS_LINUX) && !BUILDFLAG(IS_CHROMEOS_ASH) && \ 50 | !BUILDFLAG(IS_CHROMEOS_LACROS) 51 | extern const char kDisableDevShmUsage[]; 52 | #endif 53 | 54 | #if BUILDFLAG(IS_POSIX) 55 | extern const char kEnableCrashReporterForTesting[]; 56 | #endif 57 | 58 | #if BUILDFLAG(IS_ANDROID) 59 | extern const char kEnableReachedCodeProfiler[]; 60 | extern const char kReachedCodeSamplingIntervalUs[]; 61 | extern const char kDefaultCountryCodeAtInstall[]; 62 | extern const char kEnableIdleTracing[]; 63 | extern const char kForceFieldTrialParams[]; 64 | #endif 65 | 66 | #if BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS) 67 | extern const char kEnableThreadInstructionCount[]; 68 | 69 | // TODO(crbug.com/1176772): Remove kEnableCrashpad and IsCrashpadEnabled() when 70 | // Crashpad is fully enabled on Linux. 71 | extern const char kEnableCrashpad[]; 72 | #endif 73 | 74 | #if BUILDFLAG(IS_CHROMEOS_ASH) || BUILDFLAG(IS_CHROMEOS_LACROS) 75 | extern const char kSchedulerBoostUrgent[]; 76 | #endif 77 | 78 | } // namespace switches 79 | 80 | #endif // BASE_BASE_SWITCHES_H_ 81 | -------------------------------------------------------------------------------- /updates/src/base/custom_device.cc: -------------------------------------------------------------------------------- 1 | #include "base/custom_device.h" 2 | 3 | #include 4 | #include 5 | #include 6 | 7 | #include "base/json/json_reader.h" 8 | #include "base/values.h" 9 | #include "base/command_line.h" 10 | #include "base/base_switches.h" 11 | 12 | #include "build/build_config.h" 13 | 14 | namespace base { 15 | 16 | CustomDevice* CustomDevice::instance_ = nullptr; 17 | 18 | CustomDevice::CustomDevice() { 19 | Load(); 20 | } 21 | 22 | void CustomDevice::Init() { 23 | instance_ = new CustomDevice(); 24 | } 25 | 26 | bool CustomDevice::HasJSON() const { 27 | if (JSON && JSON->is_dict()) { 28 | return true; 29 | } else { 30 | return false; 31 | } 32 | } 33 | 34 | bool CustomDevice::HasDict(std::string dictKey) const { 35 | if (HasJSON()) { 36 | const auto* res = JSON->FindKey(dictKey); 37 | if (res && res->is_dict()) { 38 | return true; 39 | } 40 | } 41 | return false; 42 | } 43 | 44 | void CustomDevice::Load() { 45 | const base::CommandLine& CMD = *base::CommandLine::ForCurrentProcess(); 46 | if (CMD.HasSwitch(switches::kCustomDeviceData)) { 47 | std::string strJSON = CMD.GetSwitchValueASCII(switches::kCustomDeviceData); 48 | JSON = base::JSONReader::Read(strJSON); 49 | } 50 | } 51 | 52 | CustomDevice* CustomDevice::GetInstance() { 53 | if (!instance_) { 54 | CustomDevice::Init(); 55 | } 56 | return instance_; 57 | } 58 | 59 | int CustomDevice::GetScreenProp(std::string prop, int defaultValue) const { 60 | if (HasDict("screen")) { 61 | const auto* screen = JSON->FindKey("screen"); 62 | const auto* propValue = screen->FindKey(prop); 63 | if (propValue) { 64 | return propValue->GetInt(); 65 | } 66 | } 67 | return defaultValue; 68 | } 69 | 70 | float CustomDevice::GetNavigatorFloatProp(std::string prop, float defaultValue) const { 71 | if (HasDict("navigator")) { 72 | const auto* navigator = JSON->FindKey("navigator"); 73 | const auto* propValue = navigator->FindKey(prop); 74 | if (propValue) { 75 | return propValue->GetInt(); 76 | } 77 | } 78 | return defaultValue; 79 | } 80 | 81 | std::string CustomDevice::GetNavigatorStringProp(std::string prop, std::string defaultValue) const { 82 | if (HasDict("navigator")) { 83 | const auto* navigator = JSON->FindKey("navigator"); 84 | const auto* propValue = navigator->FindKey(prop); 85 | if (propValue) { 86 | return propValue->GetString(); 87 | } 88 | } 89 | return ""; 90 | } 91 | 92 | std::string CustomDevice::GetNavigatorPlatform() const { 93 | std::string result = ""; 94 | if (HasDict("navigator")) { 95 | const auto* navigator = JSON->FindKey("navigator"); 96 | const auto* propValue = navigator->FindKey("platform"); 97 | if (propValue) { 98 | result = propValue->GetString(); 99 | } 100 | } 101 | return result; 102 | } 103 | 104 | std::string CustomDevice::GetChromeMajorVersion() const { 105 | if (HasDict("navigator")) { 106 | const auto* navigator = JSON->FindKey("navigator"); 107 | const auto* propValue = navigator->FindKey("userAgent"); 108 | if (propValue) { 109 | regex_t re; 110 | regmatch_t pm; 111 | regcomp(&re, "Chrome\\/[0-9]+", REG_EXTENDED); 112 | std::string userAgent = propValue->GetString(); 113 | int res = regexec(&re, userAgent.data(), 1, &pm, 0); 114 | regfree(&re); 115 | if (res == 0) { 116 | int start = pm.rm_so + 7; 117 | int len = pm.rm_eo - pm.rm_so - 7; 118 | return userAgent.substr(start, len); 119 | } 120 | } 121 | } 122 | return ""; 123 | } 124 | 125 | bool CustomDevice::HasFont(std::string fontName) const { 126 | if (HasJSON()) { 127 | const auto* res = JSON->FindKey("fonts"); 128 | if (res && res->is_dict()) { 129 | const auto* font = res->FindKey(fontName); 130 | return font && font->is_dict(); 131 | } 132 | } 133 | return false; 134 | } 135 | 136 | } // namespace base 137 | -------------------------------------------------------------------------------- /updates/src/base/custom_device.h: -------------------------------------------------------------------------------- 1 | #ifndef BASE_CUSTOM_DEVICE_H_ 2 | #define BASE_CUSTOM_DEVICE_H_ 3 | 4 | #include "base/base_export.h" 5 | #include "build/build_config.h" 6 | #include "base/values.h" 7 | 8 | namespace base { 9 | 10 | class BASE_EXPORT CustomDevice { 11 | public: 12 | static CustomDevice* GetInstance(); 13 | 14 | int GetScreenProp(std::string prop, int defaultValue) const; 15 | float GetNavigatorFloatProp(std::string prop, float defaultValue) const; 16 | std::string GetNavigatorStringProp(std::string prop, std::string defaultValue) const; 17 | std::string GetNavigatorPlatform() const; 18 | std::string GetChromeMajorVersion() const; 19 | 20 | bool HasJSON() const; 21 | bool HasDict(std::string dictKey) const; 22 | bool HasFont(std::string dictKey) const; 23 | 24 | ~CustomDevice(); 25 | 26 | private: 27 | CustomDevice(); 28 | CustomDevice(CustomDevice const&); 29 | CustomDevice& operator = (CustomDevice const&); 30 | 31 | static void Init(); 32 | static CustomDevice* instance_; 33 | 34 | void Load(); 35 | 36 | absl::optional JSON; 37 | 38 | }; 39 | 40 | } // namespace base 41 | 42 | #endif // BASE_CUSTOM_DEVICE_H_ 43 | -------------------------------------------------------------------------------- /updates/src/third_party/blink/renderer/core/css/local_font_face_source.cc: -------------------------------------------------------------------------------- 1 | // Copyright 2014 The Chromium Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style license that can be 3 | // found in the LICENSE file. 4 | 5 | #include "third_party/blink/renderer/core/css/local_font_face_source.h" 6 | 7 | #include "base/metrics/histogram_functions.h" 8 | #include "build/build_config.h" 9 | #include "third_party/blink/renderer/core/css/css_custom_font_data.h" 10 | #include "third_party/blink/renderer/core/css/css_font_face.h" 11 | #include "third_party/blink/renderer/core/probe/core_probes.h" 12 | #include "third_party/blink/renderer/platform/fonts/font_cache.h" 13 | #include "third_party/blink/renderer/platform/fonts/font_description.h" 14 | #include "third_party/blink/renderer/platform/fonts/font_global_context.h" 15 | #include "third_party/blink/renderer/platform/fonts/font_selector.h" 16 | #include "third_party/blink/renderer/platform/fonts/font_unique_name_lookup.h" 17 | #include "third_party/blink/renderer/platform/fonts/simple_font_data.h" 18 | #include "third_party/blink/renderer/platform/heap/persistent.h" 19 | #include "third_party/blink/renderer/platform/wtf/functional.h" 20 | //START-UPDATES 21 | #include 22 | #include "base/custom_device.h" 23 | //END-UPDATES 24 | 25 | namespace blink { 26 | 27 | LocalFontFaceSource::LocalFontFaceSource(CSSFontFace* css_font_face, 28 | FontSelector* font_selector, 29 | const String& font_name) 30 | : face_(css_font_face), 31 | font_selector_(font_selector), 32 | font_name_(font_name) {} 33 | 34 | LocalFontFaceSource::~LocalFontFaceSource() {} 35 | 36 | bool LocalFontFaceSource::IsLocalNonBlocking() const { 37 | FontUniqueNameLookup* unique_name_lookup = 38 | FontGlobalContext::Get().GetFontUniqueNameLookup(); 39 | if (!unique_name_lookup) 40 | return true; 41 | return unique_name_lookup->IsFontUniqueNameLookupReadyForSyncLookup(); 42 | } 43 | 44 | bool LocalFontFaceSource::IsLocalFontAvailable( 45 | const FontDescription& font_description) const { 46 | // TODO(crbug.com/1027158): Remove metrics code after metrics collected. 47 | // TODO(crbug.com/1025945): Properly handle Windows prior to 10 and Android. 48 | bool font_available = FontCache::Get().IsPlatformFontUniqueNameMatchAvailable( 49 | font_description, font_name_); 50 | //START-UPDATES 51 | if (base::CustomDevice::GetInstance()->HasDict("fonts")) { 52 | if (base::CustomDevice::GetInstance()->HasFont(font_name_.Utf8())) { 53 | // std::cout << "font available" << font_name_ << "\n"; 54 | font_selector_->ReportSuccessfulLocalFontMatch(font_name_); 55 | return true; 56 | } else { 57 | // std::cout << "font not available" << font_name_ << "\n"; 58 | font_selector_->ReportFailedLocalFontMatch(font_name_); 59 | return false; 60 | } 61 | } 62 | //END-UPDATES 63 | if (font_available) 64 | font_selector_->ReportSuccessfulLocalFontMatch(font_name_); 65 | else 66 | font_selector_->ReportFailedLocalFontMatch(font_name_); 67 | return font_available; 68 | } 69 | 70 | scoped_refptr 71 | LocalFontFaceSource::CreateLoadingFallbackFontData( 72 | const FontDescription& font_description) { 73 | FontCachePurgePreventer font_cache_purge_preventer; 74 | scoped_refptr temporary_font = 75 | FontCache::Get().GetLastResortFallbackFont(font_description, 76 | kDoNotRetain); 77 | if (!temporary_font) { 78 | NOTREACHED(); 79 | return nullptr; 80 | } 81 | scoped_refptr css_font_data = 82 | CSSCustomFontData::Create(this, CSSCustomFontData::kVisibleFallback); 83 | return SimpleFontData::Create(temporary_font->PlatformData(), css_font_data); 84 | } 85 | 86 | scoped_refptr LocalFontFaceSource::CreateFontData( 87 | const FontDescription& font_description, 88 | const FontSelectionCapabilities&) { 89 | if (!IsValid()) { 90 | ReportFontLookup(font_description, nullptr); 91 | return nullptr; 92 | } 93 | 94 | bool local_fonts_enabled = true; 95 | probe::LocalFontsEnabled(font_selector_->GetExecutionContext(), 96 | &local_fonts_enabled); 97 | 98 | if (!local_fonts_enabled) 99 | return nullptr; 100 | 101 | if (IsValid() && IsLoading()) { 102 | scoped_refptr fallback_font_data = 103 | CreateLoadingFallbackFontData(font_description); 104 | ReportFontLookup(font_description, fallback_font_data.get(), 105 | true /* is_loading_fallback */); 106 | return fallback_font_data; 107 | } 108 | 109 | // FIXME(drott) crbug.com/627143: We still have the issue of matching 110 | // family name instead of postscript name for local fonts. However, we 111 | // should definitely not try to take into account the full requested 112 | // font description including the width, slope, weight styling when 113 | // trying to match against local fonts. An unstyled FontDescription 114 | // needs to be used here, or practically none at all. Instead we 115 | // should only look for the postscript or full font name. 116 | // However, when passing a style-neutral FontDescription we can't 117 | // match Roboto Bold and Thin anymore on Android given the CSS Google 118 | // Fonts sends, compare crbug.com/765980. So for now, we continue to 119 | // pass font_description to avoid breaking Google Fonts. 120 | FontDescription unstyled_description(font_description); 121 | #if !BUILDFLAG(IS_ANDROID) 122 | unstyled_description.SetStretch(NormalWidthValue()); 123 | unstyled_description.SetStyle(NormalSlopeValue()); 124 | unstyled_description.SetWeight(NormalWeightValue()); 125 | #endif 126 | scoped_refptr font_data = FontCache::Get().GetFontData( 127 | unstyled_description, font_name_, AlternateFontName::kLocalUniqueFace); 128 | histograms_.Record(font_data.get()); 129 | ReportFontLookup(unstyled_description, font_data.get()); 130 | return font_data; 131 | } 132 | 133 | void LocalFontFaceSource::BeginLoadIfNeeded() { 134 | if (IsLoaded()) 135 | return; 136 | 137 | FontUniqueNameLookup* unique_name_lookup = 138 | FontGlobalContext::Get().GetFontUniqueNameLookup(); 139 | DCHECK(unique_name_lookup); 140 | unique_name_lookup->PrepareFontUniqueNameLookup( 141 | WTF::Bind(&LocalFontFaceSource::NotifyFontUniqueNameLookupReady, 142 | WrapWeakPersistent(this))); 143 | face_->DidBeginLoad(); 144 | } 145 | 146 | void LocalFontFaceSource::NotifyFontUniqueNameLookupReady() { 147 | PruneTable(); 148 | 149 | if (face_->FontLoaded(this)) { 150 | font_selector_->FontFaceInvalidated( 151 | FontInvalidationReason::kGeneralInvalidation); 152 | } 153 | } 154 | 155 | bool LocalFontFaceSource::IsLoaded() const { 156 | return IsLocalNonBlocking(); 157 | } 158 | 159 | bool LocalFontFaceSource::IsLoading() const { 160 | return !IsLocalNonBlocking(); 161 | } 162 | 163 | bool LocalFontFaceSource::IsValid() const { 164 | return IsLoading() || IsLocalFontAvailable(FontDescription()); 165 | } 166 | 167 | void LocalFontFaceSource::LocalFontHistograms::Record(bool load_success) { 168 | if (reported_) 169 | return; 170 | reported_ = true; 171 | base::UmaHistogramBoolean("WebFont.LocalFontUsed", load_success); 172 | } 173 | 174 | void LocalFontFaceSource::Trace(Visitor* visitor) const { 175 | visitor->Trace(face_); 176 | visitor->Trace(font_selector_); 177 | CSSFontFaceSource::Trace(visitor); 178 | } 179 | 180 | void LocalFontFaceSource::ReportFontLookup( 181 | const FontDescription& font_description, 182 | SimpleFontData* font_data, 183 | bool is_loading_fallback) { 184 | font_selector_->ReportFontLookupByUniqueNameOnly( 185 | font_name_, font_description, font_data, is_loading_fallback); 186 | } 187 | 188 | } // namespace blink 189 | -------------------------------------------------------------------------------- /updates/src/third_party/blink/renderer/core/css/media_values.cc: -------------------------------------------------------------------------------- 1 | // Copyright 2014 The Chromium Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style license that can be 3 | // found in the LICENSE file. 4 | 5 | #include "third_party/blink/renderer/core/css/media_values.h" 6 | 7 | #include "third_party/blink/public/platform/platform.h" 8 | #include "third_party/blink/public/platform/web_theme_engine.h" 9 | #include "third_party/blink/renderer/core/css/css_resolution_units.h" 10 | #include "third_party/blink/renderer/core/css/media_feature_overrides.h" 11 | #include "third_party/blink/renderer/core/css/media_values.h" 12 | #include "third_party/blink/renderer/core/css/media_values_cached.h" 13 | #include "third_party/blink/renderer/core/css/media_values_dynamic.h" 14 | #include "third_party/blink/renderer/core/css/style_engine.h" 15 | #include "third_party/blink/renderer/core/css_value_keywords.h" 16 | #include "third_party/blink/renderer/core/dom/document.h" 17 | #include "third_party/blink/renderer/core/dom/element.h" 18 | #include "third_party/blink/renderer/core/frame/local_frame.h" 19 | #include "third_party/blink/renderer/core/frame/local_frame_view.h" 20 | #include "third_party/blink/renderer/core/frame/settings.h" 21 | #include "third_party/blink/renderer/core/page/chrome_client.h" 22 | #include "third_party/blink/renderer/core/page/page.h" 23 | #include "third_party/blink/renderer/platform/graphics/color_space_gamut.h" 24 | #include "third_party/blink/renderer/platform/network/network_state_notifier.h" 25 | #include "third_party/blink/renderer/platform/widget/frame_widget.h" 26 | #include "ui/display/screen_info.h" 27 | //START-UPDATES 28 | #include "base/custom_device.h" 29 | //END-UPDATES 30 | 31 | namespace blink { 32 | 33 | ForcedColors CSSValueIDToForcedColors(CSSValueID id) { 34 | switch (id) { 35 | case CSSValueID::kActive: 36 | return ForcedColors::kActive; 37 | case CSSValueID::kNone: 38 | return ForcedColors::kNone; 39 | default: 40 | NOTREACHED(); 41 | return ForcedColors::kNone; 42 | } 43 | } 44 | 45 | mojom::blink::PreferredColorScheme CSSValueIDToPreferredColorScheme( 46 | CSSValueID id) { 47 | switch (id) { 48 | case CSSValueID::kLight: 49 | return mojom::blink::PreferredColorScheme::kLight; 50 | case CSSValueID::kDark: 51 | return mojom::blink::PreferredColorScheme::kDark; 52 | default: 53 | NOTREACHED(); 54 | return mojom::blink::PreferredColorScheme::kLight; 55 | } 56 | } 57 | 58 | mojom::blink::PreferredContrast CSSValueIDToPreferredContrast(CSSValueID id) { 59 | switch (id) { 60 | case CSSValueID::kMore: 61 | return mojom::blink::PreferredContrast::kMore; 62 | case CSSValueID::kLess: 63 | return mojom::blink::PreferredContrast::kLess; 64 | case CSSValueID::kNoPreference: 65 | return mojom::blink::PreferredContrast::kNoPreference; 66 | case CSSValueID::kCustom: 67 | return mojom::blink::PreferredContrast::kCustom; 68 | default: 69 | NOTREACHED(); 70 | return mojom::blink::PreferredContrast::kNoPreference; 71 | } 72 | } 73 | 74 | absl::optional MediaValues::InlineSize() const { 75 | if (IsHorizontalWritingMode(GetWritingMode())) 76 | return Width(); 77 | return Height(); 78 | } 79 | 80 | absl::optional MediaValues::BlockSize() const { 81 | if (IsHorizontalWritingMode(GetWritingMode())) 82 | return Height(); 83 | return Width(); 84 | } 85 | 86 | MediaValues* MediaValues::CreateDynamicIfFrameExists(LocalFrame* frame) { 87 | if (frame) 88 | return MediaValuesDynamic::Create(frame); 89 | return MakeGarbageCollected(); 90 | } 91 | 92 | double MediaValues::ViewportInlineSize() const { 93 | return IsHorizontalWritingMode(GetWritingMode()) ? ViewportWidth() 94 | : ViewportHeight(); 95 | } 96 | 97 | double MediaValues::ViewportBlockSize() const { 98 | return IsHorizontalWritingMode(GetWritingMode()) ? ViewportHeight() 99 | : ViewportWidth(); 100 | } 101 | 102 | double MediaValues::SmallViewportInlineSize() const { 103 | return IsHorizontalWritingMode(GetWritingMode()) ? SmallViewportWidth() 104 | : SmallViewportHeight(); 105 | } 106 | 107 | double MediaValues::SmallViewportBlockSize() const { 108 | return IsHorizontalWritingMode(GetWritingMode()) ? SmallViewportHeight() 109 | : SmallViewportWidth(); 110 | } 111 | 112 | double MediaValues::LargeViewportInlineSize() const { 113 | return IsHorizontalWritingMode(GetWritingMode()) ? LargeViewportWidth() 114 | : LargeViewportHeight(); 115 | } 116 | 117 | double MediaValues::LargeViewportBlockSize() const { 118 | return IsHorizontalWritingMode(GetWritingMode()) ? LargeViewportHeight() 119 | : LargeViewportWidth(); 120 | } 121 | 122 | double MediaValues::DynamicViewportInlineSize() const { 123 | return IsHorizontalWritingMode(GetWritingMode()) ? DynamicViewportWidth() 124 | : DynamicViewportHeight(); 125 | } 126 | 127 | double MediaValues::DynamicViewportBlockSize() const { 128 | return IsHorizontalWritingMode(GetWritingMode()) ? DynamicViewportHeight() 129 | : DynamicViewportWidth(); 130 | } 131 | 132 | double MediaValues::CalculateViewportWidth(LocalFrame* frame) { 133 | DCHECK(frame); 134 | DCHECK(frame->View()); 135 | DCHECK(frame->GetDocument()); 136 | return frame->View()->ViewportSizeForMediaQueries().width(); 137 | } 138 | 139 | double MediaValues::CalculateViewportHeight(LocalFrame* frame) { 140 | DCHECK(frame); 141 | DCHECK(frame->View()); 142 | DCHECK(frame->GetDocument()); 143 | return frame->View()->ViewportSizeForMediaQueries().height(); 144 | } 145 | 146 | double MediaValues::CalculateSmallViewportWidth(LocalFrame* frame) { 147 | DCHECK(frame); 148 | DCHECK(frame->View()); 149 | DCHECK(frame->GetDocument()); 150 | return frame->View()->SmallViewportSizeForViewportUnits().width(); 151 | } 152 | 153 | double MediaValues::CalculateSmallViewportHeight(LocalFrame* frame) { 154 | DCHECK(frame); 155 | DCHECK(frame->View()); 156 | DCHECK(frame->GetDocument()); 157 | return frame->View()->SmallViewportSizeForViewportUnits().height(); 158 | } 159 | 160 | double MediaValues::CalculateLargeViewportWidth(LocalFrame* frame) { 161 | DCHECK(frame); 162 | DCHECK(frame->View()); 163 | DCHECK(frame->GetDocument()); 164 | return frame->View()->LargeViewportSizeForViewportUnits().width(); 165 | } 166 | 167 | double MediaValues::CalculateLargeViewportHeight(LocalFrame* frame) { 168 | DCHECK(frame); 169 | DCHECK(frame->View()); 170 | DCHECK(frame->GetDocument()); 171 | return frame->View()->LargeViewportSizeForViewportUnits().height(); 172 | } 173 | 174 | double MediaValues::CalculateDynamicViewportWidth(LocalFrame* frame) { 175 | DCHECK(frame); 176 | DCHECK(frame->View()); 177 | DCHECK(frame->GetDocument()); 178 | return frame->View()->DynamicViewportSizeForViewportUnits().width(); 179 | } 180 | 181 | double MediaValues::CalculateDynamicViewportHeight(LocalFrame* frame) { 182 | DCHECK(frame); 183 | DCHECK(frame->View()); 184 | DCHECK(frame->GetDocument()); 185 | return frame->View()->DynamicViewportSizeForViewportUnits().height(); 186 | } 187 | 188 | int MediaValues::CalculateDeviceWidth(LocalFrame* frame) { 189 | DCHECK(frame && frame->View() && frame->GetSettings() && frame->GetPage()); 190 | const display::ScreenInfo& screen_info = 191 | frame->GetPage()->GetChromeClient().GetScreenInfo(*frame); 192 | int device_width = screen_info.rect.width(); 193 | if (frame->GetSettings()->GetReportScreenSizeInPhysicalPixelsQuirk()) { 194 | device_width = static_cast( 195 | lroundf(device_width * screen_info.device_scale_factor)); 196 | } 197 | //START-UPDATES 198 | if (base::CustomDevice::GetInstance()->HasDict("screen")) { 199 | return base::CustomDevice::GetInstance()->GetScreenProp( 200 | "width", 201 | device_width 202 | ); 203 | } 204 | //END-UPDATES 205 | return device_width; 206 | } 207 | 208 | int MediaValues::CalculateDeviceHeight(LocalFrame* frame) { 209 | DCHECK(frame && frame->View() && frame->GetSettings() && frame->GetPage()); 210 | const display::ScreenInfo& screen_info = 211 | frame->GetPage()->GetChromeClient().GetScreenInfo(*frame); 212 | int device_height = screen_info.rect.height(); 213 | if (frame->GetSettings()->GetReportScreenSizeInPhysicalPixelsQuirk()) { 214 | device_height = static_cast( 215 | lroundf(device_height * screen_info.device_scale_factor)); 216 | } 217 | //START-UPDATES 218 | if (base::CustomDevice::GetInstance()->HasDict("screen")) { 219 | return base::CustomDevice::GetInstance()->GetScreenProp( 220 | "height", 221 | device_height 222 | ); 223 | } 224 | //END-UPDATES 225 | return device_height; 226 | } 227 | 228 | bool MediaValues::CalculateStrictMode(LocalFrame* frame) { 229 | DCHECK(frame); 230 | DCHECK(frame->GetDocument()); 231 | return !frame->GetDocument()->InQuirksMode(); 232 | } 233 | 234 | float MediaValues::CalculateDevicePixelRatio(LocalFrame* frame) { 235 | return frame->DevicePixelRatio(); 236 | } 237 | 238 | bool MediaValues::CalculateDeviceSupportsHDR(LocalFrame* frame) { 239 | DCHECK(frame); 240 | DCHECK(frame->GetPage()); 241 | return frame->GetPage() 242 | ->GetChromeClient() 243 | .GetScreenInfo(*frame) 244 | .display_color_spaces.SupportsHDR(); 245 | } 246 | 247 | int MediaValues::CalculateColorBitsPerComponent(LocalFrame* frame) { 248 | DCHECK(frame); 249 | DCHECK(frame->GetPage()); 250 | const display::ScreenInfo& screen_info = 251 | frame->GetPage()->GetChromeClient().GetScreenInfo(*frame); 252 | if (screen_info.is_monochrome) 253 | return 0; 254 | return screen_info.depth_per_component; 255 | } 256 | 257 | int MediaValues::CalculateMonochromeBitsPerComponent(LocalFrame* frame) { 258 | DCHECK(frame); 259 | DCHECK(frame->GetPage()); 260 | const display::ScreenInfo& screen_info = 261 | frame->GetPage()->GetChromeClient().GetScreenInfo(*frame); 262 | if (!screen_info.is_monochrome) 263 | return 0; 264 | return screen_info.depth_per_component; 265 | } 266 | 267 | float MediaValues::CalculateEmSize(LocalFrame* frame) { 268 | DCHECK(frame); 269 | DCHECK(frame->GetDocument()); 270 | const ComputedStyle* style = frame->GetDocument()->GetComputedStyle(); 271 | DCHECK(style); 272 | CSSToLengthConversionData::FontSizes font_sizes(style, style); 273 | return font_sizes.Em(); 274 | } 275 | 276 | float MediaValues::CalculateExSize(LocalFrame* frame) { 277 | DCHECK(frame); 278 | DCHECK(frame->GetDocument()); 279 | const ComputedStyle* style = frame->GetDocument()->GetComputedStyle(); 280 | DCHECK(style); 281 | CSSToLengthConversionData::FontSizes font_sizes(style, style); 282 | // Font metrics are based on the used font which is scaled to match the size 283 | // of CSS pixels. Need to scale back to CSS pixels. 284 | return font_sizes.Ex() / font_sizes.Zoom(); 285 | } 286 | 287 | float MediaValues::CalculateChSize(LocalFrame* frame) { 288 | DCHECK(frame); 289 | DCHECK(frame->GetDocument()); 290 | const ComputedStyle* style = frame->GetDocument()->GetComputedStyle(); 291 | DCHECK(style); 292 | CSSToLengthConversionData::FontSizes font_sizes(style, style); 293 | // Font metrics are based on the used font which is scaled to match the size 294 | // of CSS pixels. Need to scale back to CSS pixels. 295 | return font_sizes.Ch() / font_sizes.Zoom(); 296 | } 297 | 298 | const String MediaValues::CalculateMediaType(LocalFrame* frame) { 299 | DCHECK(frame); 300 | if (!frame->View()) 301 | return g_empty_atom; 302 | return frame->View()->MediaType(); 303 | } 304 | 305 | mojom::blink::DisplayMode MediaValues::CalculateDisplayMode(LocalFrame* frame) { 306 | DCHECK(frame); 307 | 308 | blink::mojom::DisplayMode mode = 309 | frame->GetPage()->GetSettings().GetDisplayModeOverride(); 310 | if (mode != mojom::blink::DisplayMode::kUndefined) 311 | return mode; 312 | 313 | FrameWidget* widget = frame->GetWidgetForLocalRoot(); 314 | if (!widget) // Is null in non-ordinary Pages. 315 | return mojom::blink::DisplayMode::kBrowser; 316 | 317 | return widget->DisplayMode(); 318 | } 319 | 320 | bool MediaValues::CalculateThreeDEnabled(LocalFrame* frame) { 321 | return frame->GetPage()->GetSettings().GetAcceleratedCompositingEnabled(); 322 | } 323 | 324 | bool MediaValues::CalculateInImmersiveMode(LocalFrame* frame) { 325 | DCHECK(frame); 326 | DCHECK(frame->GetSettings()); 327 | return frame->GetSettings()->GetImmersiveModeEnabled(); 328 | } 329 | 330 | mojom::blink::PointerType MediaValues::CalculatePrimaryPointerType( 331 | LocalFrame* frame) { 332 | DCHECK(frame); 333 | DCHECK(frame->GetSettings()); 334 | return frame->GetSettings()->GetPrimaryPointerType(); 335 | } 336 | 337 | int MediaValues::CalculateAvailablePointerTypes(LocalFrame* frame) { 338 | DCHECK(frame); 339 | DCHECK(frame->GetSettings()); 340 | return frame->GetSettings()->GetAvailablePointerTypes(); 341 | } 342 | 343 | mojom::blink::HoverType MediaValues::CalculatePrimaryHoverType( 344 | LocalFrame* frame) { 345 | DCHECK(frame); 346 | DCHECK(frame->GetSettings()); 347 | return frame->GetSettings()->GetPrimaryHoverType(); 348 | } 349 | 350 | int MediaValues::CalculateAvailableHoverTypes(LocalFrame* frame) { 351 | DCHECK(frame); 352 | DCHECK(frame->GetSettings()); 353 | return frame->GetSettings()->GetAvailableHoverTypes(); 354 | } 355 | 356 | ColorSpaceGamut MediaValues::CalculateColorGamut(LocalFrame* frame) { 357 | DCHECK(frame); 358 | DCHECK(frame->GetPage()); 359 | if (const auto* overrides = frame->GetPage()->GetMediaFeatureOverrides()) { 360 | MediaQueryExpValue value = overrides->GetOverride("color-gamut"); 361 | if (value.IsValid()) { 362 | if (value.Id() == CSSValueID::kSRGB) 363 | return ColorSpaceGamut::SRGB; 364 | if (value.Id() == CSSValueID::kP3) 365 | return ColorSpaceGamut::P3; 366 | // Rec. 2020 is also known as ITU-R-Empfehlung BT.2020. 367 | if (value.Id() == CSSValueID::kRec2020) 368 | return ColorSpaceGamut::BT2020; 369 | NOTREACHED(); 370 | } 371 | } 372 | return color_space_utilities::GetColorSpaceGamut( 373 | frame->GetPage()->GetChromeClient().GetScreenInfo(*frame)); 374 | } 375 | 376 | mojom::blink::PreferredColorScheme MediaValues::CalculatePreferredColorScheme( 377 | LocalFrame* frame) { 378 | DCHECK(frame); 379 | DCHECK(frame->GetSettings()); 380 | DCHECK(frame->GetDocument()); 381 | DCHECK(frame->GetPage()); 382 | if (const auto* overrides = frame->GetPage()->GetMediaFeatureOverrides()) { 383 | MediaQueryExpValue value = overrides->GetOverride("prefers-color-scheme"); 384 | if (value.IsValid()) 385 | return CSSValueIDToPreferredColorScheme(value.Id()); 386 | } 387 | return frame->GetDocument()->GetStyleEngine().GetPreferredColorScheme(); 388 | } 389 | 390 | mojom::blink::PreferredContrast MediaValues::CalculatePreferredContrast( 391 | LocalFrame* frame) { 392 | DCHECK(frame); 393 | DCHECK(frame->GetSettings()); 394 | DCHECK(frame->GetPage()); 395 | if (const auto* overrides = frame->GetPage()->GetMediaFeatureOverrides()) { 396 | MediaQueryExpValue value = overrides->GetOverride("prefers-contrast"); 397 | if (value.IsValid()) 398 | return CSSValueIDToPreferredContrast(value.Id()); 399 | } 400 | return frame->GetSettings()->GetPreferredContrast(); 401 | } 402 | 403 | bool MediaValues::CalculatePrefersReducedMotion(LocalFrame* frame) { 404 | DCHECK(frame); 405 | DCHECK(frame->GetSettings()); 406 | if (const auto* overrides = frame->GetPage()->GetMediaFeatureOverrides()) { 407 | MediaQueryExpValue value = overrides->GetOverride("prefers-reduced-motion"); 408 | if (value.IsValid()) 409 | return value.Id() == CSSValueID::kReduce; 410 | } 411 | return frame->GetSettings()->GetPrefersReducedMotion(); 412 | } 413 | 414 | bool MediaValues::CalculatePrefersReducedData(LocalFrame* frame) { 415 | DCHECK(frame); 416 | DCHECK(frame->GetSettings()); 417 | if (const auto* overrides = frame->GetPage()->GetMediaFeatureOverrides()) { 418 | MediaQueryExpValue value = overrides->GetOverride("prefers-reduced-data"); 419 | if (value.IsValid()) 420 | return value.Id() == CSSValueID::kReduce; 421 | } 422 | return (GetNetworkStateNotifier().SaveDataEnabled() && 423 | !frame->GetSettings()->GetDataSaverHoldbackWebApi()); 424 | } 425 | 426 | ForcedColors MediaValues::CalculateForcedColors(LocalFrame* frame) { 427 | DCHECK(frame); 428 | DCHECK(frame->GetSettings()); 429 | if (const auto* overrides = frame->GetPage()->GetMediaFeatureOverrides()) { 430 | MediaQueryExpValue value = overrides->GetOverride("forced-colors"); 431 | if (value.IsValid()) 432 | return CSSValueIDToForcedColors(value.Id()); 433 | } 434 | if (Platform::Current() && Platform::Current()->ThemeEngine()) 435 | return Platform::Current()->ThemeEngine()->GetForcedColors(); 436 | else 437 | return ForcedColors::kNone; 438 | } 439 | 440 | NavigationControls MediaValues::CalculateNavigationControls(LocalFrame* frame) { 441 | DCHECK(frame); 442 | DCHECK(frame->GetSettings()); 443 | return frame->GetSettings()->GetNavigationControls(); 444 | } 445 | 446 | int MediaValues::CalculateHorizontalViewportSegments(LocalFrame* frame) { 447 | if (!frame->GetWidgetForLocalRoot()) 448 | return 1; 449 | 450 | WebVector window_segments = 451 | frame->GetWidgetForLocalRoot()->WindowSegments(); 452 | WTF::HashSet unique_x; 453 | for (const auto& segment : window_segments) { 454 | // HashSet can't have 0 as a key, so add 1 to all the values we see. 455 | unique_x.insert(segment.x() + 1); 456 | } 457 | 458 | return static_cast(unique_x.size()); 459 | } 460 | 461 | int MediaValues::CalculateVerticalViewportSegments(LocalFrame* frame) { 462 | if (!frame->GetWidgetForLocalRoot()) 463 | return 1; 464 | 465 | WebVector window_segments = 466 | frame->GetWidgetForLocalRoot()->WindowSegments(); 467 | WTF::HashSet unique_y; 468 | for (const auto& segment : window_segments) { 469 | // HashSet can't have 0 as a key, so add 1 to all the values we see. 470 | unique_y.insert(segment.y() + 1); 471 | } 472 | 473 | return static_cast(unique_y.size()); 474 | } 475 | 476 | device::mojom::blink::DevicePostureType MediaValues::CalculateDevicePosture( 477 | LocalFrame* frame) { 478 | return frame->GetDevicePosture(); 479 | } 480 | 481 | bool MediaValues::ComputeLengthImpl(double value, 482 | CSSPrimitiveValue::UnitType type, 483 | double& result) const { 484 | // The logic in this function is duplicated from 485 | // CSSToLengthConversionData::ZoomedComputedPixels() because 486 | // MediaValues::ComputeLength() needs nearly identical logic, but we haven't 487 | // found a way to make CSSToLengthConversionData::ZoomedComputedPixels() more 488 | // generic (to solve both cases) without hurting performance. 489 | // TODO: Unite the logic here with CSSToLengthConversionData in a performant 490 | // way. 491 | switch (type) { 492 | case CSSPrimitiveValue::UnitType::kEms: 493 | result = value * EmSize(); 494 | return true; 495 | case CSSPrimitiveValue::UnitType::kRems: 496 | result = value * RemSize(); 497 | return true; 498 | case CSSPrimitiveValue::UnitType::kPixels: 499 | case CSSPrimitiveValue::UnitType::kUserUnits: 500 | result = value; 501 | return true; 502 | case CSSPrimitiveValue::UnitType::kExs: 503 | result = value * ExSize(); 504 | return true; 505 | case CSSPrimitiveValue::UnitType::kChs: 506 | result = value * ChSize(); 507 | return true; 508 | case CSSPrimitiveValue::UnitType::kViewportWidth: 509 | result = (value * ViewportWidth()) / 100.0; 510 | return true; 511 | case CSSPrimitiveValue::UnitType::kViewportHeight: 512 | result = (value * ViewportHeight()) / 100.0; 513 | return true; 514 | case CSSPrimitiveValue::UnitType::kViewportInlineSize: 515 | result = (value * ViewportInlineSize()) / 100.0; 516 | return true; 517 | case CSSPrimitiveValue::UnitType::kViewportBlockSize: 518 | result = (value * ViewportBlockSize()) / 100.0; 519 | return true; 520 | case CSSPrimitiveValue::UnitType::kViewportMin: 521 | result = (value * std::min(ViewportWidth(), ViewportHeight())) / 100.0; 522 | return true; 523 | case CSSPrimitiveValue::UnitType::kViewportMax: 524 | result = (value * std::max(ViewportWidth(), ViewportHeight())) / 100.0; 525 | return true; 526 | case CSSPrimitiveValue::UnitType::kSmallViewportWidth: 527 | result = (value * SmallViewportWidth()) / 100.0; 528 | return true; 529 | case CSSPrimitiveValue::UnitType::kSmallViewportHeight: 530 | result = (value * SmallViewportHeight()) / 100.0; 531 | return true; 532 | case CSSPrimitiveValue::UnitType::kSmallViewportInlineSize: 533 | result = (value * SmallViewportInlineSize()) / 100.0; 534 | return true; 535 | case CSSPrimitiveValue::UnitType::kSmallViewportBlockSize: 536 | result = (value * SmallViewportBlockSize()) / 100.0; 537 | return true; 538 | case CSSPrimitiveValue::UnitType::kSmallViewportMin: 539 | result = (value * std::min(SmallViewportWidth(), SmallViewportHeight())) / 540 | 100.0; 541 | return true; 542 | case CSSPrimitiveValue::UnitType::kSmallViewportMax: 543 | result = (value * std::max(SmallViewportWidth(), SmallViewportHeight())) / 544 | 100.0; 545 | return true; 546 | case CSSPrimitiveValue::UnitType::kLargeViewportWidth: 547 | result = (value * LargeViewportWidth()) / 100.0; 548 | return true; 549 | case CSSPrimitiveValue::UnitType::kLargeViewportHeight: 550 | result = (value * LargeViewportHeight()) / 100.0; 551 | return true; 552 | case CSSPrimitiveValue::UnitType::kLargeViewportInlineSize: 553 | result = (value * LargeViewportInlineSize()) / 100.0; 554 | return true; 555 | case CSSPrimitiveValue::UnitType::kLargeViewportBlockSize: 556 | result = (value * LargeViewportBlockSize()) / 100.0; 557 | return true; 558 | case CSSPrimitiveValue::UnitType::kLargeViewportMin: 559 | result = (value * std::min(LargeViewportWidth(), LargeViewportHeight())) / 560 | 100.0; 561 | return true; 562 | case CSSPrimitiveValue::UnitType::kLargeViewportMax: 563 | result = (value * std::max(LargeViewportWidth(), LargeViewportHeight())) / 564 | 100.0; 565 | return true; 566 | case CSSPrimitiveValue::UnitType::kDynamicViewportWidth: 567 | result = (value * DynamicViewportWidth()) / 100.0; 568 | return true; 569 | case CSSPrimitiveValue::UnitType::kDynamicViewportHeight: 570 | result = (value * DynamicViewportHeight()) / 100.0; 571 | return true; 572 | case CSSPrimitiveValue::UnitType::kDynamicViewportInlineSize: 573 | result = (value * DynamicViewportInlineSize()) / 100.0; 574 | return true; 575 | case CSSPrimitiveValue::UnitType::kDynamicViewportBlockSize: 576 | result = (value * DynamicViewportBlockSize()) / 100.0; 577 | return true; 578 | case CSSPrimitiveValue::UnitType::kDynamicViewportMin: 579 | result = 580 | (value * std::min(DynamicViewportWidth(), DynamicViewportHeight())) / 581 | 100.0; 582 | return true; 583 | case CSSPrimitiveValue::UnitType::kDynamicViewportMax: 584 | result = 585 | (value * std::max(DynamicViewportWidth(), DynamicViewportHeight())) / 586 | 100.0; 587 | return true; 588 | case CSSPrimitiveValue::UnitType::kCentimeters: 589 | result = value * kCssPixelsPerCentimeter; 590 | return true; 591 | case CSSPrimitiveValue::UnitType::kMillimeters: 592 | result = value * kCssPixelsPerMillimeter; 593 | return true; 594 | case CSSPrimitiveValue::UnitType::kQuarterMillimeters: 595 | result = value * kCssPixelsPerQuarterMillimeter; 596 | return true; 597 | case CSSPrimitiveValue::UnitType::kInches: 598 | result = value * kCssPixelsPerInch; 599 | return true; 600 | case CSSPrimitiveValue::UnitType::kPoints: 601 | result = value * kCssPixelsPerPoint; 602 | return true; 603 | case CSSPrimitiveValue::UnitType::kPicas: 604 | result = value * kCssPixelsPerPica; 605 | return true; 606 | default: 607 | return false; 608 | } 609 | } 610 | 611 | } // namespace blink 612 | -------------------------------------------------------------------------------- /updates/src/third_party/blink/renderer/core/frame/navigator.cc: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2000 Harri Porten (porten@kde.org) 3 | * Copyright (c) 2000 Daniel Molkentin (molkentin@kde.org) 4 | * Copyright (c) 2000 Stefan Schimanski (schimmi@kde.org) 5 | * Copyright (C) 2003, 2004, 2005, 2006 Apple Computer, Inc. 6 | * Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies) 7 | * 8 | * This library is free software; you can redistribute it and/or 9 | * modify it under the terms of the GNU Lesser General Public 10 | * License as published by the Free Software Foundation; either 11 | * version 2 of the License, or (at your option) any later version. 12 | * 13 | * This library is distributed in the hope that it will be useful, 14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 16 | * Lesser General Public License for more details. 17 | * 18 | * You should have received a copy of the GNU Lesser General Public 19 | * License along with this library; if not, write to the Free Software 20 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, 21 | * MA 02110-1301, USA 22 | */ 23 | 24 | #include "third_party/blink/renderer/core/frame/navigator.h" 25 | 26 | #include "third_party/blink/public/common/user_agent/user_agent_metadata.h" 27 | #include "third_party/blink/renderer/bindings/core/v8/script_controller.h" 28 | #include "third_party/blink/renderer/core/dom/document.h" 29 | #include "third_party/blink/renderer/core/execution_context/navigator_base.h" 30 | #include "third_party/blink/renderer/core/frame/local_dom_window.h" 31 | #include "third_party/blink/renderer/core/frame/local_frame.h" 32 | #include "third_party/blink/renderer/core/frame/settings.h" 33 | #include "third_party/blink/renderer/core/loader/frame_loader.h" 34 | #include "third_party/blink/renderer/core/page/chrome_client.h" 35 | #include "third_party/blink/renderer/core/page/page.h" 36 | #include "third_party/blink/renderer/core/probe/core_probes.h" 37 | #include "third_party/blink/renderer/platform/instrumentation/memory_pressure_listener.h" 38 | #include "third_party/blink/renderer/platform/language.h" 39 | //START-UPDATES 40 | #include "base/custom_device.h" 41 | //END-UPDATES 42 | 43 | namespace blink { 44 | 45 | Navigator::Navigator(ExecutionContext* context) : NavigatorBase(context) {} 46 | 47 | String Navigator::productSub() const { 48 | //START-UPDATES 49 | const std::string value = base::CustomDevice::GetInstance()->GetNavigatorStringProp("productSub", "20030107"); 50 | if (!value.empty()) { 51 | return value.data(); 52 | } 53 | //END-UPDATES 54 | return "20030107"; 55 | } 56 | 57 | String Navigator::vendor() const { 58 | // Do not change without good cause. History: 59 | // https://code.google.com/p/chromium/issues/detail?id=276813 60 | // https://www.w3.org/Bugs/Public/show_bug.cgi?id=27786 61 | // https://groups.google.com/a/chromium.org/forum/#!topic/blink-dev/QrgyulnqvmE 62 | //START-UPDATES 63 | const std::string value = base::CustomDevice::GetInstance()->GetNavigatorStringProp("vendor", "Google Inc."); 64 | if (!value.empty()) { 65 | return value.data(); 66 | } 67 | //END-UPDATES 68 | return "Google Inc."; 69 | } 70 | 71 | String Navigator::vendorSub() const { 72 | //START-UPDATES 73 | const std::string value = base::CustomDevice::GetInstance()->GetNavigatorStringProp("vendorSub", ""); 74 | if (!value.empty()) { 75 | return value.data(); 76 | } 77 | //END-UPDATES 78 | return ""; 79 | } 80 | 81 | String Navigator::platform() const { 82 | // TODO(955620): Consider changing devtools overrides to only allow overriding 83 | // the platform with a frozen platform to distinguish between 84 | // mobile and desktop when ReduceUserAgent is enabled. 85 | if (!DomWindow()) 86 | return NavigatorBase::platform(); 87 | const String& platform_override = 88 | DomWindow()->GetFrame()->GetSettings()->GetNavigatorPlatformOverride(); 89 | return platform_override.IsEmpty() ? NavigatorBase::platform() 90 | : platform_override; 91 | } 92 | 93 | bool Navigator::cookieEnabled() const { 94 | if (!DomWindow()) 95 | return false; 96 | 97 | Settings* settings = DomWindow()->GetFrame()->GetSettings(); 98 | if (!settings || !settings->GetCookieEnabled()) 99 | return false; 100 | 101 | return DomWindow()->document()->CookiesEnabled(); 102 | } 103 | 104 | bool Navigator::webdriver() const { 105 | if (RuntimeEnabledFeatures::AutomationControlledEnabled()) 106 | return true; 107 | 108 | bool automation_enabled = false; 109 | probe::ApplyAutomationOverride(GetExecutionContext(), automation_enabled); 110 | return automation_enabled; 111 | } 112 | 113 | String Navigator::GetAcceptLanguages() { 114 | if (!DomWindow()) 115 | return DefaultLanguage(); 116 | 117 | return DomWindow() 118 | ->GetFrame() 119 | ->GetPage() 120 | ->GetChromeClient() 121 | .AcceptLanguages(); 122 | } 123 | 124 | void Navigator::Trace(Visitor* visitor) const { 125 | NavigatorBase::Trace(visitor); 126 | Supplementable::Trace(visitor); 127 | } 128 | 129 | } // namespace blink 130 | -------------------------------------------------------------------------------- /updates/src/third_party/blink/renderer/core/frame/navigator_concurrent_hardware.cc: -------------------------------------------------------------------------------- 1 | // Copyright 2014 The Chromium Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style license that can be 3 | // found in the LICENSE file. 4 | 5 | #include "third_party/blink/renderer/core/frame/navigator_concurrent_hardware.h" 6 | 7 | #include "base/system/sys_info.h" 8 | //START-UPDATES 9 | #include "base/custom_device.h" 10 | //END-UPDATES 11 | 12 | namespace blink { 13 | 14 | unsigned NavigatorConcurrentHardware::hardwareConcurrency() const { 15 | //START-UPDATES 16 | if (base::CustomDevice::GetInstance()->HasDict("navigator")) { 17 | return base::CustomDevice::GetInstance()->GetNavigatorFloatProp( 18 | "hardwareConcurrency", 19 | base::SysInfo::NumberOfProcessors() 20 | ); 21 | } 22 | //END-UPDATES 23 | return static_cast(base::SysInfo::NumberOfProcessors()); 24 | } 25 | 26 | } // namespace blink 27 | -------------------------------------------------------------------------------- /updates/src/third_party/blink/renderer/core/frame/navigator_device_memory.cc: -------------------------------------------------------------------------------- 1 | // Copyright 2014 The Chromium Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style license that can be 3 | // found in the LICENSE file. 4 | 5 | #include "third_party/blink/renderer/core/frame/navigator_device_memory.h" 6 | 7 | #include "third_party/blink/public/common/device_memory/approximated_device_memory.h" 8 | #include "third_party/blink/public/common/privacy_budget/identifiability_metrics.h" 9 | #include "third_party/blink/public/common/privacy_budget/identifiability_metric_builder.h" 10 | #include "third_party/blink/public/mojom/web_feature/web_feature.mojom-shared.h" 11 | #include "third_party/blink/renderer/core/dom/document.h" 12 | #include "third_party/blink/renderer/core/frame/local_dom_window.h" 13 | //START-UPDATES 14 | #include "base/custom_device.h" 15 | //END-UPDATES 16 | 17 | namespace blink { 18 | 19 | float NavigatorDeviceMemory::deviceMemory() const { 20 | //START-UPDATES 21 | if (base::CustomDevice::GetInstance()->HasDict("navigator")) { 22 | return base::CustomDevice::GetInstance()->GetNavigatorFloatProp( 23 | "deviceMemory", 24 | ApproximatedDeviceMemory::GetApproximatedDeviceMemory() 25 | ); 26 | } 27 | //END-UPDATES 28 | return ApproximatedDeviceMemory::GetApproximatedDeviceMemory(); 29 | } 30 | 31 | } // namespace blink 32 | -------------------------------------------------------------------------------- /updates/src/third_party/blink/renderer/core/frame/navigator_id.cc: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2008 Apple Inc. All Rights Reserved. 3 | * Copyright (C) 2013 Samsung Electronics. All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions are 7 | * met: 8 | * 9 | * * Redistributions of source code must retain the above copyright 10 | * notice, this list of conditions and the following disclaimer. 11 | * * Redistributions in binary form must reproduce the above 12 | * copyright notice, this list of conditions and the following disclaimer 13 | * in the documentation and/or other materials provided with the 14 | * distribution. 15 | * * Neither the name of Google Inc. nor the names of its 16 | * contributors may be used to endorse or promote products derived from 17 | * this software without specific prior written permission. 18 | * 19 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 20 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 21 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 22 | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 23 | * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 24 | * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 25 | * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 26 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 27 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 28 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 29 | * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30 | */ 31 | 32 | #include "third_party/blink/renderer/core/frame/navigator_id.h" 33 | 34 | #include "base/feature_list.h" 35 | #include "build/build_config.h" 36 | #include "third_party/blink/public/common/features.h" 37 | #include "third_party/blink/renderer/platform/wtf/text/string_builder.h" 38 | //START-UPDATES 39 | #include "base/custom_device.h" 40 | //END-UPDATES 41 | 42 | #if !BUILDFLAG(IS_MAC) && !BUILDFLAG(IS_WIN) 43 | #include 44 | #include "third_party/blink/renderer/platform/wtf/thread_specific.h" 45 | #include "third_party/blink/renderer/platform/wtf/threading.h" 46 | #endif 47 | 48 | namespace blink { 49 | 50 | String NavigatorID::appCodeName() { 51 | return "Mozilla"; 52 | } 53 | 54 | String NavigatorID::appName() { 55 | return "Netscape"; 56 | } 57 | 58 | String NavigatorID::appVersion() { 59 | // Version is everything in the user agent string past the "Mozilla/" prefix. 60 | const String& agent = userAgent(); 61 | return agent.Substring(agent.find('/') + 1); 62 | } 63 | 64 | String NavigatorID::platform() const { 65 | //START-UPDATES 66 | const std::string platform = base::CustomDevice::GetInstance()->GetNavigatorPlatform(); 67 | if (!platform.empty()) { 68 | return platform.data(); 69 | } 70 | //END-UPDATES 71 | #if BUILDFLAG(IS_MAC) 72 | // Match Safari and Mozilla on Mac x86. 73 | return "MacIntel"; 74 | #elif BUILDFLAG(IS_WIN) 75 | // Match Safari and Mozilla on Windows. 76 | return "Win32"; 77 | #else // Unix-like systems 78 | struct utsname osname; 79 | DEFINE_THREAD_SAFE_STATIC_LOCAL(ThreadSpecific, platform_name, ()); 80 | if (platform_name->IsNull()) { 81 | StringBuilder result; 82 | if (uname(&osname) >= 0) { 83 | result.Append(osname.sysname); 84 | if (strlen(osname.machine) != 0) { 85 | result.Append(" "); 86 | result.Append(osname.machine); 87 | } 88 | } 89 | *platform_name = result.ToString(); 90 | } 91 | return *platform_name; 92 | #endif 93 | } 94 | 95 | String NavigatorID::product() { 96 | return "Gecko"; 97 | } 98 | 99 | } // namespace blink 100 | -------------------------------------------------------------------------------- /updates/src/third_party/blink/renderer/core/frame/navigator_ua_data.cc: -------------------------------------------------------------------------------- 1 | // Copyright 2020 The Chromium Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style license that can be 3 | // found in the LICENSE file. 4 | 5 | #include "third_party/blink/renderer/core/frame/navigator_ua_data.h" 6 | 7 | #include "base/compiler_specific.h" 8 | #include "base/task/single_thread_task_runner.h" 9 | #include "third_party/blink/public/common/privacy_budget/identifiability_metric_builder.h" 10 | #include "third_party/blink/public/common/privacy_budget/identifiability_study_settings.h" 11 | #include "third_party/blink/public/common/privacy_budget/identifiable_surface.h" 12 | #include "third_party/blink/public/common/privacy_budget/identifiable_token.h" 13 | #include "third_party/blink/public/common/privacy_budget/identifiable_token_builder.h" 14 | #include "third_party/blink/public/mojom/web_feature/web_feature.mojom-blink.h" 15 | #include "third_party/blink/renderer/bindings/core/v8/script_promise_resolver.h" 16 | #include "third_party/blink/renderer/bindings/core/v8/v8_ua_data_values.h" 17 | #include "third_party/blink/renderer/core/execution_context/execution_context.h" 18 | #include "third_party/blink/renderer/core/page/page.h" 19 | //START-UPDATES 20 | #include "base/custom_device.h" 21 | //END-UPDATES 22 | 23 | namespace blink { 24 | 25 | namespace { 26 | 27 | // Record identifiability study metrics for a single field requested by a 28 | // getHighEntropyValues() call if the user is in the study. 29 | void MaybeRecordMetric(bool record_identifiability, 30 | const String& hint, 31 | const String& value, 32 | ExecutionContext* execution_context) { 33 | if (LIKELY(!record_identifiability)) 34 | return; 35 | auto identifiable_surface = IdentifiableSurface::FromTypeAndToken( 36 | IdentifiableSurface::Type::kNavigatorUAData_GetHighEntropyValues, 37 | IdentifiableToken(hint.Utf8())); 38 | IdentifiabilityMetricBuilder(execution_context->UkmSourceID()) 39 | .Add(identifiable_surface, IdentifiableToken(value.Utf8())) 40 | .Record(execution_context->UkmRecorder()); 41 | } 42 | 43 | } // namespace 44 | 45 | NavigatorUAData::NavigatorUAData(ExecutionContext* context) 46 | : ExecutionContextClient(context) { 47 | NavigatorUABrandVersion* dict = NavigatorUABrandVersion::Create(); 48 | dict->setBrand(""); 49 | dict->setVersion(""); 50 | empty_brand_set_.push_back(dict); 51 | } 52 | 53 | void NavigatorUAData::AddBrandVersion(const String& brand, 54 | const String& version) { 55 | NavigatorUABrandVersion* dict = NavigatorUABrandVersion::Create(); 56 | dict->setBrand(brand); 57 | dict->setVersion(version); 58 | brand_set_.push_back(dict); 59 | } 60 | 61 | void NavigatorUAData::AddBrandFullVersion(const String& brand, 62 | const String& version) { 63 | NavigatorUABrandVersion* dict = NavigatorUABrandVersion::Create(); 64 | dict->setBrand(brand); 65 | dict->setVersion(version); 66 | full_version_list_.push_back(dict); 67 | } 68 | 69 | void NavigatorUAData::SetBrandVersionList( 70 | const UserAgentBrandList& brand_version_list) { 71 | //START-UPDATES 72 | const std::string majorVersion = base::CustomDevice::GetInstance()->GetChromeMajorVersion(); 73 | if (!majorVersion.empty()) { 74 | AddBrandVersion(" Not A;Brand", "99"); 75 | AddBrandVersion("Chromium", majorVersion.data()); 76 | AddBrandVersion("Google Chrome", majorVersion.data()); 77 | return; 78 | } 79 | //END-UPDATES 80 | for (const auto& brand_version : brand_version_list) { 81 | AddBrandVersion(String::FromUTF8(brand_version.brand), 82 | String::FromUTF8(brand_version.version)); 83 | } 84 | } 85 | 86 | void NavigatorUAData::SetFullVersionList( 87 | const UserAgentBrandList& full_version_list) { 88 | for (const auto& brand_version : full_version_list) { 89 | AddBrandFullVersion(String::FromUTF8(brand_version.brand), 90 | String::FromUTF8(brand_version.version)); 91 | } 92 | } 93 | 94 | void NavigatorUAData::SetMobile(bool mobile) { 95 | is_mobile_ = mobile; 96 | } 97 | 98 | void NavigatorUAData::SetPlatform(const String& brand, const String& version) { 99 | //START-UPDATES 100 | const std::string navigatorPlatform = base::CustomDevice::GetInstance()->GetNavigatorPlatform(); 101 | if (!navigatorPlatform.empty()) { 102 | platform_ = navigatorPlatform.data(); 103 | platform_version_ = version; 104 | return; 105 | } 106 | //END-UPDATES 107 | platform_ = brand; 108 | platform_version_ = version; 109 | } 110 | 111 | void NavigatorUAData::SetArchitecture(const String& architecture) { 112 | architecture_ = architecture; 113 | } 114 | 115 | void NavigatorUAData::SetModel(const String& model) { 116 | model_ = model; 117 | } 118 | 119 | void NavigatorUAData::SetUAFullVersion(const String& ua_full_version) { 120 | ua_full_version_ = ua_full_version; 121 | } 122 | 123 | void NavigatorUAData::SetBitness(const String& bitness) { 124 | bitness_ = bitness; 125 | } 126 | 127 | void NavigatorUAData::SetWoW64(bool wow64) { 128 | is_wow64_ = wow64; 129 | } 130 | 131 | bool NavigatorUAData::mobile() const { 132 | if (GetExecutionContext()) { 133 | return is_mobile_; 134 | } 135 | return false; 136 | } 137 | 138 | const HeapVector>& NavigatorUAData::brands() 139 | const { 140 | if (GetExecutionContext()) { 141 | return brand_set_; 142 | } 143 | return empty_brand_set_; 144 | } 145 | 146 | const String& NavigatorUAData::platform() const { 147 | if (GetExecutionContext()) { 148 | return platform_; 149 | } 150 | return WTF::g_empty_string; 151 | } 152 | 153 | ScriptPromise NavigatorUAData::getHighEntropyValues( 154 | ScriptState* script_state, 155 | Vector& hints) const { 156 | auto* resolver = MakeGarbageCollected(script_state); 157 | ScriptPromise promise = resolver->Promise(); 158 | auto* execution_context = 159 | ExecutionContext::From(script_state); // GetExecutionContext(); 160 | DCHECK(execution_context); 161 | 162 | bool record_identifiability = 163 | IdentifiabilityStudySettings::Get()->ShouldSample( 164 | IdentifiableSurface::Type::kNavigatorUAData_GetHighEntropyValues); 165 | UADataValues* values = MakeGarbageCollected(); 166 | // According to 167 | // https://wicg.github.io/ua-client-hints/#getHighEntropyValues, brands, 168 | // mobile and platform should be included regardless of whether they were 169 | // asked for. 170 | 171 | // TODO: It'd be faster to compare hint when turning |hints| into an 172 | // AtomicString vector and turning the const string literals |hint| into 173 | // AtomicStrings as well. 174 | for (const String& hint : hints) { 175 | values->setBrands(brand_set_); 176 | values->setMobile(is_mobile_); 177 | values->setPlatform(platform_); 178 | MaybeRecordMetric(record_identifiability, hint, platform_, 179 | execution_context); 180 | 181 | if (hint == "platformVersion") { 182 | values->setPlatformVersion(platform_version_); 183 | MaybeRecordMetric(record_identifiability, hint, platform_version_, 184 | execution_context); 185 | } else if (hint == "architecture") { 186 | values->setArchitecture(architecture_); 187 | MaybeRecordMetric(record_identifiability, hint, architecture_, 188 | execution_context); 189 | } else if (hint == "model") { 190 | values->setModel(model_); 191 | MaybeRecordMetric(record_identifiability, hint, model_, 192 | execution_context); 193 | } else if (hint == "uaFullVersion") { 194 | values->setUaFullVersion(ua_full_version_); 195 | MaybeRecordMetric(record_identifiability, hint, ua_full_version_, 196 | execution_context); 197 | } else if (hint == "bitness") { 198 | values->setBitness(bitness_); 199 | MaybeRecordMetric(record_identifiability, hint, bitness_, 200 | execution_context); 201 | } else if (hint == "fullVersionList") { 202 | values->setFullVersionList(full_version_list_); 203 | } else if (hint == "wow64") { 204 | values->setWow64(is_wow64_); 205 | MaybeRecordMetric(record_identifiability, hint, is_wow64_ ? "?1" : "?0", 206 | execution_context); 207 | } 208 | } 209 | 210 | execution_context->GetTaskRunner(TaskType::kPermission) 211 | ->PostTask( 212 | FROM_HERE, 213 | WTF::Bind([](ScriptPromiseResolver* resolver, 214 | UADataValues* values) { resolver->Resolve(values); }, 215 | WrapPersistent(resolver), WrapPersistent(values))); 216 | 217 | return promise; 218 | } 219 | 220 | ScriptValue NavigatorUAData::toJSON(ScriptState* script_state) const { 221 | V8ObjectBuilder builder(script_state); 222 | builder.Add("brands", brands()); 223 | builder.Add("mobile", mobile()); 224 | return builder.GetScriptValue(); 225 | } 226 | 227 | void NavigatorUAData::Trace(Visitor* visitor) const { 228 | visitor->Trace(brand_set_); 229 | visitor->Trace(full_version_list_); 230 | visitor->Trace(empty_brand_set_); 231 | ScriptWrappable::Trace(visitor); 232 | ExecutionContextClient::Trace(visitor); 233 | } 234 | 235 | } // namespace blink 236 | -------------------------------------------------------------------------------- /updates/src/third_party/blink/renderer/core/frame/screen.cc: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2007 Apple Inc. All rights reserved. 3 | * 4 | * Redistribution and use in source and binary forms, with or without 5 | * modification, are permitted provided that the following conditions 6 | * are met: 7 | * 8 | * 1. Redistributions of source code must retain the above copyright 9 | * notice, this list of conditions and the following disclaimer. 10 | * 2. Redistributions in binary form must reproduce the above copyright 11 | * notice, this list of conditions and the following disclaimer in the 12 | * documentation and/or other materials provided with the distribution. 13 | * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of 14 | * its contributors may be used to endorse or promote products derived 15 | * from this software without specific prior written permission. 16 | * 17 | * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY 18 | * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 19 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 20 | * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY 21 | * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 22 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 23 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 24 | * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 26 | * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 | */ 28 | 29 | #include "third_party/blink/renderer/core/frame/screen.h" 30 | //START-UPDATES 31 | #include "base/custom_device.h" 32 | //END-UPDATES 33 | 34 | #include "base/numerics/safe_conversions.h" 35 | #include "third_party/blink/public/mojom/permissions_policy/permissions_policy_feature.mojom-blink.h" 36 | #include "third_party/blink/renderer/core/event_target_names.h" 37 | #include "third_party/blink/renderer/core/frame/local_dom_window.h" 38 | #include "third_party/blink/renderer/core/frame/local_frame.h" 39 | #include "third_party/blink/renderer/core/frame/settings.h" 40 | #include "third_party/blink/renderer/core/page/chrome_client.h" 41 | #include "ui/display/screen_info.h" 42 | #include "ui/display/screen_infos.h" 43 | 44 | namespace blink { 45 | 46 | namespace { 47 | 48 | } // namespace 49 | 50 | Screen::Screen(LocalDOMWindow* window, int64_t display_id) 51 | : ExecutionContextClient(window), display_id_(display_id) {} 52 | 53 | // static 54 | bool Screen::AreWebExposedScreenPropertiesEqual( 55 | const display::ScreenInfo& prev, 56 | const display::ScreenInfo& current) { 57 | // height() / width() use rect / device_scale_factor 58 | if (prev.rect.size() != current.rect.size()) 59 | return false; 60 | 61 | // Note: comparing device_scale_factor is a bit of a lie as Screen only uses 62 | // this with the PhysicalPixelsQuirk (see width() / height() below). However, 63 | // this value likely changes rarely and should not throw many false positives. 64 | if (prev.device_scale_factor != current.device_scale_factor) 65 | return false; 66 | 67 | // availLeft() / availTop() / availHeight() / availWidth() use available_rect 68 | if (prev.available_rect != current.available_rect) 69 | return false; 70 | 71 | // colorDepth() / pixelDepth() use depth 72 | if (prev.depth != current.depth) 73 | return false; 74 | 75 | // isExtended() 76 | if (prev.is_extended != current.is_extended) 77 | return false; 78 | 79 | return true; 80 | } 81 | 82 | int Screen::height() const { 83 | if (!DomWindow()) 84 | return 0; 85 | LocalFrame* frame = DomWindow()->GetFrame(); 86 | const display::ScreenInfo& screen_info = GetScreenInfo(); 87 | //START-UPDATES 88 | if (base::CustomDevice::GetInstance()->HasDict("screen")) { 89 | return base::CustomDevice::GetInstance()->GetScreenProp( 90 | "height", 91 | screen_info.rect.height() 92 | ); 93 | } 94 | //END-UPDATES 95 | if (frame->GetSettings()->GetReportScreenSizeInPhysicalPixelsQuirk()) { 96 | return base::ClampRound(screen_info.rect.height() * 97 | screen_info.device_scale_factor); 98 | } 99 | return screen_info.rect.height(); 100 | } 101 | 102 | int Screen::width() const { 103 | if (!DomWindow()) 104 | return 0; 105 | LocalFrame* frame = DomWindow()->GetFrame(); 106 | const display::ScreenInfo& screen_info = GetScreenInfo(); 107 | //START-UPDATES 108 | if (base::CustomDevice::GetInstance()->HasDict("screen")) { 109 | return base::CustomDevice::GetInstance()->GetScreenProp( 110 | "width", 111 | screen_info.rect.width() 112 | ); 113 | } 114 | //END-UPDATES 115 | if (frame->GetSettings()->GetReportScreenSizeInPhysicalPixelsQuirk()) { 116 | return base::ClampRound(screen_info.rect.width() * 117 | screen_info.device_scale_factor); 118 | } 119 | return screen_info.rect.width(); 120 | } 121 | 122 | unsigned Screen::colorDepth() const { 123 | if (!DomWindow()) 124 | return 0; 125 | //START-UPDATES 126 | if (base::CustomDevice::GetInstance()->HasDict("screen")) { 127 | return base::CustomDevice::GetInstance()->GetScreenProp( 128 | "colorDepth", 129 | GetScreenInfo().depth 130 | ); 131 | } 132 | //END-UPDATES 133 | return base::saturated_cast(GetScreenInfo().depth); 134 | } 135 | 136 | unsigned Screen::pixelDepth() const { 137 | //START-UPDATES 138 | if (base::CustomDevice::GetInstance()->HasDict("screen")) { 139 | return base::CustomDevice::GetInstance()->GetScreenProp( 140 | "pixelDepth", 141 | colorDepth() 142 | ); 143 | } 144 | //END-UPDATES 145 | return colorDepth(); 146 | } 147 | 148 | int Screen::availLeft() const { 149 | if (!DomWindow()) 150 | return 0; 151 | LocalFrame* frame = DomWindow()->GetFrame(); 152 | const display::ScreenInfo& screen_info = GetScreenInfo(); 153 | //START-UPDATES 154 | if (base::CustomDevice::GetInstance()->HasDict("screen")) { 155 | return base::CustomDevice::GetInstance()->GetScreenProp( 156 | "availLeft", 157 | screen_info.available_rect.x() 158 | ); 159 | } 160 | //END-UPDATES 161 | if (frame->GetSettings()->GetReportScreenSizeInPhysicalPixelsQuirk()) { 162 | return base::ClampRound(screen_info.available_rect.x() * 163 | screen_info.device_scale_factor); 164 | } 165 | return screen_info.available_rect.x(); 166 | } 167 | 168 | int Screen::availTop() const { 169 | if (!DomWindow()) 170 | return 0; 171 | LocalFrame* frame = DomWindow()->GetFrame(); 172 | const display::ScreenInfo& screen_info = GetScreenInfo(); 173 | //START-UPDATES 174 | if (base::CustomDevice::GetInstance()->HasDict("screen")) { 175 | return base::CustomDevice::GetInstance()->GetScreenProp( 176 | "availTop", 177 | screen_info.available_rect.y() 178 | ); 179 | } 180 | //END-UPDATES 181 | if (frame->GetSettings()->GetReportScreenSizeInPhysicalPixelsQuirk()) { 182 | return base::ClampRound(screen_info.available_rect.y() * 183 | screen_info.device_scale_factor); 184 | } 185 | return screen_info.available_rect.y(); 186 | } 187 | 188 | int Screen::availHeight() const { 189 | if (!DomWindow()) 190 | return 0; 191 | LocalFrame* frame = DomWindow()->GetFrame(); 192 | const display::ScreenInfo& screen_info = GetScreenInfo(); 193 | //START-UPDATES 194 | if (base::CustomDevice::GetInstance()->HasDict("screen")) { 195 | return base::CustomDevice::GetInstance()->GetScreenProp( 196 | "availHeight", 197 | screen_info.available_rect.height() 198 | ); 199 | } 200 | //END-UPDATES 201 | if (frame->GetSettings()->GetReportScreenSizeInPhysicalPixelsQuirk()) { 202 | return base::ClampRound(screen_info.available_rect.height() * 203 | screen_info.device_scale_factor); 204 | } 205 | return screen_info.available_rect.height(); 206 | } 207 | 208 | int Screen::availWidth() const { 209 | if (!DomWindow()) 210 | return 0; 211 | LocalFrame* frame = DomWindow()->GetFrame(); 212 | const display::ScreenInfo& screen_info = GetScreenInfo(); 213 | //START-UPDATES 214 | if (base::CustomDevice::GetInstance()->HasDict("screen")) { 215 | return base::CustomDevice::GetInstance()->GetScreenProp( 216 | "availWidth", 217 | screen_info.available_rect.width() 218 | ); 219 | } 220 | //END-UPDATES 221 | if (frame->GetSettings()->GetReportScreenSizeInPhysicalPixelsQuirk()) { 222 | return base::ClampRound(screen_info.available_rect.width() * 223 | screen_info.device_scale_factor); 224 | } 225 | return screen_info.available_rect.width(); 226 | } 227 | 228 | void Screen::Trace(Visitor* visitor) const { 229 | EventTargetWithInlineData::Trace(visitor); 230 | ExecutionContextClient::Trace(visitor); 231 | Supplementable::Trace(visitor); 232 | } 233 | 234 | const WTF::AtomicString& Screen::InterfaceName() const { 235 | return event_target_names::kScreen; 236 | } 237 | 238 | ExecutionContext* Screen::GetExecutionContext() const { 239 | return ExecutionContextClient::GetExecutionContext(); 240 | } 241 | 242 | bool Screen::isExtended() const { 243 | if (!DomWindow()) 244 | return false; 245 | auto* context = GetExecutionContext(); 246 | if (!context->IsFeatureEnabled( 247 | mojom::blink::PermissionsPolicyFeature::kWindowPlacement)) { 248 | return false; 249 | } 250 | 251 | return GetScreenInfo().is_extended; 252 | } 253 | 254 | const display::ScreenInfo& Screen::GetScreenInfo() const { 255 | DCHECK(DomWindow()); 256 | LocalFrame* frame = DomWindow()->GetFrame(); 257 | 258 | const auto& screen_infos = frame->GetChromeClient().GetScreenInfos(*frame); 259 | for (const auto& screen : screen_infos.screen_infos) { 260 | if (screen.display_id == display_id_) 261 | return screen; 262 | } 263 | DEFINE_STATIC_LOCAL(display::ScreenInfo, kEmptyScreenInfo, ()); 264 | return kEmptyScreenInfo; 265 | } 266 | 267 | } // namespace blink 268 | --------------------------------------------------------------------------------