mirror of
https://github.com/electron/electron.git
synced 2026-02-19 03:14:51 -05:00
Compare commits
114 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
b36b2e3781 | ||
|
|
5646f87c03 | ||
|
|
a14c789a4c | ||
|
|
2e6ec46eae | ||
|
|
d91bcef773 | ||
|
|
02992b8ad7 | ||
|
|
0f92cf21a8 | ||
|
|
25ed5f2d97 | ||
|
|
0fe1a95694 | ||
|
|
8fb011092a | ||
|
|
44fee2f8eb | ||
|
|
b9400a8ab9 | ||
|
|
a35a12228d | ||
|
|
19c126ff6e | ||
|
|
9e5aec2f75 | ||
|
|
d6c1957d61 | ||
|
|
65ce13ee56 | ||
|
|
93e609dd58 | ||
|
|
a22683ed73 | ||
|
|
86431323bb | ||
|
|
d15cc63aa4 | ||
|
|
66dd03293b | ||
|
|
addd2440c1 | ||
|
|
3a1945bd6c | ||
|
|
75290948ac | ||
|
|
9bb03e9e03 | ||
|
|
d585bf3250 | ||
|
|
fb3abffd16 | ||
|
|
2a04149140 | ||
|
|
b384447377 | ||
|
|
160afc8d19 | ||
|
|
eb4ce2a84e | ||
|
|
5dc084c428 | ||
|
|
52c019c3c7 | ||
|
|
c1cb799e5e | ||
|
|
7118979852 | ||
|
|
22d81d3054 | ||
|
|
bd3e9aa527 | ||
|
|
7bae935a0d | ||
|
|
bcca5c5bd8 | ||
|
|
305d26ce1f | ||
|
|
fe864864ae | ||
|
|
085a15fd95 | ||
|
|
b3281b4f97 | ||
|
|
16b78a4eff | ||
|
|
95277d1580 | ||
|
|
f97264499b | ||
|
|
25b9c1c35e | ||
|
|
23f6aecf38 | ||
|
|
f72cf8c2f5 | ||
|
|
36f4b59c04 | ||
|
|
b653897e0f | ||
|
|
322f1c3f89 | ||
|
|
3b0832275e | ||
|
|
009263c240 | ||
|
|
70aa51cb44 | ||
|
|
0a97730080 | ||
|
|
9b5df7f95c | ||
|
|
d8194ea6fd | ||
|
|
e306e8cd0d | ||
|
|
478c25c39d | ||
|
|
ca680a14b6 | ||
|
|
eaf8f6776f | ||
|
|
da40d1e7db | ||
|
|
252f9cbd50 | ||
|
|
5a91ea8cdb | ||
|
|
c460c53c10 | ||
|
|
f7367f0312 | ||
|
|
75ba569e73 | ||
|
|
044399047a | ||
|
|
ecf9633370 | ||
|
|
d6aea2703e | ||
|
|
88e44b0d7e | ||
|
|
5b4acf406c | ||
|
|
af7d3b7171 | ||
|
|
d10adccf3f | ||
|
|
26e74b355b | ||
|
|
5463996d00 | ||
|
|
93e6cbb60b | ||
|
|
9d02e5d4fd | ||
|
|
7f002fe3a3 | ||
|
|
cc77aba367 | ||
|
|
7d46fb5d40 | ||
|
|
14e85ae55d | ||
|
|
cb8925c454 | ||
|
|
032c0a1416 | ||
|
|
27009989fe | ||
|
|
cf1d2103b8 | ||
|
|
3eb78b89e3 | ||
|
|
a8a5c44b3e | ||
|
|
73c87bcfc6 | ||
|
|
39ff8744ea | ||
|
|
2bbc560e22 | ||
|
|
590711fdd8 | ||
|
|
14baae0436 | ||
|
|
76c6e64d18 | ||
|
|
a09db1f6fe | ||
|
|
66ac88bc82 | ||
|
|
6654e37197 | ||
|
|
ff50d30a42 | ||
|
|
609f2d5e64 | ||
|
|
9716ae5a35 | ||
|
|
7d79120dac | ||
|
|
ee521475e3 | ||
|
|
3c6be55e13 | ||
|
|
0b031afcef | ||
|
|
3a61e4ce16 | ||
|
|
f4fc41b877 | ||
|
|
bd1e0176f5 | ||
|
|
16b72c0315 | ||
|
|
e9f673f322 | ||
|
|
e78bfc119c | ||
|
|
1b4eeda7eb | ||
|
|
90c299f3ad |
1
.circleci/.gitignore
vendored
Normal file
1
.circleci/.gitignore
vendored
Normal file
@@ -0,0 +1 @@
|
||||
config-staging
|
||||
@@ -6,6 +6,7 @@ setup: true
|
||||
# Orbs
|
||||
orbs:
|
||||
path-filtering: circleci/path-filtering@0.1.0
|
||||
continuation: circleci/continuation@0.2.0
|
||||
|
||||
# All input parameters to pass to build config
|
||||
parameters:
|
||||
@@ -13,7 +14,7 @@ parameters:
|
||||
type: boolean
|
||||
default: false
|
||||
|
||||
upload-to-s3:
|
||||
upload-to-storage:
|
||||
type: string
|
||||
default: '1'
|
||||
|
||||
@@ -43,103 +44,33 @@ parameters:
|
||||
default: all
|
||||
enum: ["all", "osx-x64", "osx-arm64", "mas-x64", "mas-arm64"]
|
||||
|
||||
# Envs
|
||||
env-global: &env-global
|
||||
ELECTRON_OUT_DIR: Default
|
||||
|
||||
env-linux-medium: &env-linux-medium
|
||||
<<: *env-global
|
||||
NUMBER_OF_NINJA_PROCESSES: 3
|
||||
|
||||
# Executors
|
||||
executors:
|
||||
linux-docker:
|
||||
parameters:
|
||||
size:
|
||||
description: "Docker executor size"
|
||||
default: 2xlarge+
|
||||
type: enum
|
||||
enum: ["medium", "xlarge", "2xlarge+"]
|
||||
docker:
|
||||
- image: ghcr.io/electron/build:27db4a3e3512bfd2e47f58cea69922da0835f1d9
|
||||
resource_class: << parameters.size >>
|
||||
|
||||
# List of always run steps
|
||||
step-checkout-electron: &step-checkout-electron
|
||||
checkout:
|
||||
path: src/electron
|
||||
|
||||
steps-lint: &steps-lint
|
||||
steps:
|
||||
- *step-checkout-electron
|
||||
- run:
|
||||
name: Setup third_party Depot Tools
|
||||
command: |
|
||||
# "depot_tools" has to be checkout into "//third_party/depot_tools" so pylint.py can a "pylintrc" file.
|
||||
git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git src/third_party/depot_tools
|
||||
echo 'export PATH="$PATH:'"$PWD"'/src/third_party/depot_tools"' >> $BASH_ENV
|
||||
- run:
|
||||
name: Download GN Binary
|
||||
command: |
|
||||
chromium_revision="$(grep -A1 chromium_version src/electron/DEPS | tr -d '\n' | cut -d\' -f4)"
|
||||
gn_version="$(curl -sL "https://chromium.googlesource.com/chromium/src/+/${chromium_revision}/DEPS?format=TEXT" | base64 -d | grep gn_version | head -n1 | cut -d\' -f4)"
|
||||
|
||||
cipd ensure -ensure-file - -root . \<<-CIPD
|
||||
\$ServiceURL https://chrome-infra-packages.appspot.com/
|
||||
@Subdir src/buildtools/linux64
|
||||
gn/gn/linux-amd64 $gn_version
|
||||
CIPD
|
||||
|
||||
echo 'export CHROMIUM_BUILDTOOLS_PATH="'"$PWD"'/src/buildtools"' >> $BASH_ENV
|
||||
- run:
|
||||
name: Download clang-format Binary
|
||||
command: |
|
||||
chromium_revision="$(grep -A1 chromium_version src/electron/DEPS | tr -d '\n' | cut -d\' -f4)"
|
||||
|
||||
sha1_path='buildtools/linux64/clang-format.sha1'
|
||||
curl -sL "https://chromium.googlesource.com/chromium/src/+/${chromium_revision}/${sha1_path}?format=TEXT" | base64 -d > "src/${sha1_path}"
|
||||
|
||||
download_from_google_storage.py --no_resume --no_auth --bucket chromium-clang-format -s "src/${sha1_path}"
|
||||
- run:
|
||||
name: Run Lint
|
||||
command: |
|
||||
# gn.py tries to find a gclient root folder starting from the current dir.
|
||||
# When it fails and returns "None" path, the whole script fails. Let's "fix" it.
|
||||
touch .gclient
|
||||
# Another option would be to checkout "buildtools" inside the Electron checkout,
|
||||
# but then we would lint its contents (at least gn format), and it doesn't pass it.
|
||||
|
||||
cd src/electron
|
||||
node script/yarn install --frozen-lockfile
|
||||
node script/yarn lint
|
||||
- run:
|
||||
name: Run Script Typechecker
|
||||
command: |
|
||||
cd src/electron
|
||||
node script/yarn tsc -p tsconfig.script.json
|
||||
|
||||
# List of always run jobs.
|
||||
jobs:
|
||||
lint:
|
||||
executor:
|
||||
name: linux-docker
|
||||
size: medium
|
||||
environment:
|
||||
<<: *env-linux-medium
|
||||
<<: *steps-lint
|
||||
|
||||
# Initial setup workflow
|
||||
workflows:
|
||||
lint:
|
||||
jobs:
|
||||
# Job inherited from path-filtering orb
|
||||
- path-filtering/filter:
|
||||
generate-config:
|
||||
docker:
|
||||
- image: cimg/node:16.14
|
||||
steps:
|
||||
- checkout
|
||||
- path-filtering/set-parameters:
|
||||
base-revision: main
|
||||
# Params for mapping; `path-to-test parameter-to-set value-for-parameter` for each row
|
||||
mapping: |
|
||||
^((?!docs/).)*$ run-build-mac true
|
||||
^((?!docs/).)*$ run-build-linux true
|
||||
docs/.* run-docs-only true
|
||||
^((?!docs/).)*$ run-docs-only false
|
||||
config-path: .circleci/build_config.yml
|
||||
- lint
|
||||
- run:
|
||||
command: |
|
||||
cd .circleci/config
|
||||
yarn
|
||||
export CIRCLECI_BINARY="$HOME/circleci"
|
||||
curl -fLSs https://raw.githubusercontent.com/CircleCI-Public/circleci-cli/master/install.sh | DESTDIR=$CIRCLECI_BINARY bash
|
||||
node build.js
|
||||
name: Pack config.yml
|
||||
- continuation/continue:
|
||||
configuration_path: .circleci/config-staging/built.yml
|
||||
parameters: /tmp/pipeline-parameters.json
|
||||
|
||||
# Initial setup workflow
|
||||
workflows:
|
||||
setup:
|
||||
jobs:
|
||||
- generate-config
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
34
.circleci/config/build.js
Normal file
34
.circleci/config/build.js
Normal file
@@ -0,0 +1,34 @@
|
||||
const cp = require('child_process');
|
||||
const fs = require('fs-extra');
|
||||
const path = require('path');
|
||||
const yaml = require('js-yaml');
|
||||
|
||||
const STAGING_DIR = path.resolve(__dirname, '..', 'config-staging');
|
||||
|
||||
function copyAndExpand(dir = './') {
|
||||
const absDir = path.resolve(__dirname, dir);
|
||||
const targetDir = path.resolve(STAGING_DIR, dir);
|
||||
|
||||
if (!fs.existsSync(targetDir)) {
|
||||
fs.mkdirSync(targetDir);
|
||||
}
|
||||
|
||||
for (const file of fs.readdirSync(absDir)) {
|
||||
if (!file.endsWith('.yml')) {
|
||||
if (fs.statSync(path.resolve(absDir, file)).isDirectory()) {
|
||||
copyAndExpand(path.join(dir, file));
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
fs.writeFileSync(path.resolve(targetDir, file), yaml.dump(yaml.load(fs.readFileSync(path.resolve(absDir, file), 'utf8')), {
|
||||
noRefs: true,
|
||||
}));
|
||||
}
|
||||
}
|
||||
|
||||
if (fs.pathExists(STAGING_DIR)) fs.removeSync(STAGING_DIR);
|
||||
copyAndExpand();
|
||||
|
||||
const output = cp.spawnSync(process.env.CIRCLECI_BINARY || 'circleci', ['config', 'pack', STAGING_DIR]);
|
||||
fs.writeFileSync(path.resolve(STAGING_DIR, 'built.yml'), output.stdout.toString());
|
||||
51
.circleci/config/jobs/lint.yml
Normal file
51
.circleci/config/jobs/lint.yml
Normal file
@@ -0,0 +1,51 @@
|
||||
executor:
|
||||
name: linux-docker
|
||||
size: medium
|
||||
steps:
|
||||
- checkout:
|
||||
path: src/electron
|
||||
- run:
|
||||
name: Setup third_party Depot Tools
|
||||
command: |
|
||||
# "depot_tools" has to be checkout into "//third_party/depot_tools" so pylint.py can a "pylintrc" file.
|
||||
git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git src/third_party/depot_tools
|
||||
echo 'export PATH="$PATH:'"$PWD"'/src/third_party/depot_tools"' >> $BASH_ENV
|
||||
- run:
|
||||
name: Download GN Binary
|
||||
command: |
|
||||
chromium_revision="$(grep -A1 chromium_version src/electron/DEPS | tr -d '\n' | cut -d\' -f4)"
|
||||
gn_version="$(curl -sL "https://chromium.googlesource.com/chromium/src/+/${chromium_revision}/DEPS?format=TEXT" | base64 -d | grep gn_version | head -n1 | cut -d\' -f4)"
|
||||
|
||||
cipd ensure -ensure-file - -root . \<<-CIPD
|
||||
\$ServiceURL https://chrome-infra-packages.appspot.com/
|
||||
@Subdir src/buildtools/linux64
|
||||
gn/gn/linux-amd64 $gn_version
|
||||
CIPD
|
||||
|
||||
echo 'export CHROMIUM_BUILDTOOLS_PATH="'"$PWD"'/src/buildtools"' >> $BASH_ENV
|
||||
- run:
|
||||
name: Download clang-format Binary
|
||||
command: |
|
||||
chromium_revision="$(grep -A1 chromium_version src/electron/DEPS | tr -d '\n' | cut -d\' -f4)"
|
||||
|
||||
sha1_path='buildtools/linux64/clang-format.sha1'
|
||||
curl -sL "https://chromium.googlesource.com/chromium/src/+/${chromium_revision}/${sha1_path}?format=TEXT" | base64 -d > "src/${sha1_path}"
|
||||
|
||||
download_from_google_storage.py --no_resume --no_auth --bucket chromium-clang-format -s "src/${sha1_path}"
|
||||
- run:
|
||||
name: Run Lint
|
||||
command: |
|
||||
# gn.py tries to find a gclient root folder starting from the current dir.
|
||||
# When it fails and returns "None" path, the whole script fails. Let's "fix" it.
|
||||
touch .gclient
|
||||
# Another option would be to checkout "buildtools" inside the Electron checkout,
|
||||
# but then we would lint its contents (at least gn format), and it doesn't pass it.
|
||||
|
||||
cd src/electron
|
||||
node script/yarn install --frozen-lockfile
|
||||
node script/yarn lint
|
||||
- run:
|
||||
name: Run Script Typechecker
|
||||
command: |
|
||||
cd src/electron
|
||||
node script/yarn tsc -p tsconfig.script.json
|
||||
10
.circleci/config/package.json
Normal file
10
.circleci/config/package.json
Normal file
@@ -0,0 +1,10 @@
|
||||
{
|
||||
"name": "@electron/circleci-config",
|
||||
"version": "0.0.0",
|
||||
"private": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"fs-extra": "^10.1.0",
|
||||
"js-yaml": "^4.1.0"
|
||||
}
|
||||
}
|
||||
43
.circleci/config/yarn.lock
Normal file
43
.circleci/config/yarn.lock
Normal file
@@ -0,0 +1,43 @@
|
||||
# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.
|
||||
# yarn lockfile v1
|
||||
|
||||
|
||||
argparse@^2.0.1:
|
||||
version "2.0.1"
|
||||
resolved "https://registry.yarnpkg.com/argparse/-/argparse-2.0.1.tgz#246f50f3ca78a3240f6c997e8a9bd1eac49e4b38"
|
||||
integrity sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==
|
||||
|
||||
fs-extra@^10.1.0:
|
||||
version "10.1.0"
|
||||
resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-10.1.0.tgz#02873cfbc4084dde127eaa5f9905eef2325d1abf"
|
||||
integrity sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==
|
||||
dependencies:
|
||||
graceful-fs "^4.2.0"
|
||||
jsonfile "^6.0.1"
|
||||
universalify "^2.0.0"
|
||||
|
||||
graceful-fs@^4.1.6, graceful-fs@^4.2.0:
|
||||
version "4.2.10"
|
||||
resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.10.tgz#147d3a006da4ca3ce14728c7aefc287c367d7a6c"
|
||||
integrity sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA==
|
||||
|
||||
js-yaml@^4.1.0:
|
||||
version "4.1.0"
|
||||
resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-4.1.0.tgz#c1fb65f8f5017901cdd2c951864ba18458a10602"
|
||||
integrity sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==
|
||||
dependencies:
|
||||
argparse "^2.0.1"
|
||||
|
||||
jsonfile@^6.0.1:
|
||||
version "6.1.0"
|
||||
resolved "https://registry.yarnpkg.com/jsonfile/-/jsonfile-6.1.0.tgz#bc55b2634793c679ec6403094eb13698a6ec0aae"
|
||||
integrity sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==
|
||||
dependencies:
|
||||
universalify "^2.0.0"
|
||||
optionalDependencies:
|
||||
graceful-fs "^4.1.6"
|
||||
|
||||
universalify@^2.0.0:
|
||||
version "2.0.0"
|
||||
resolved "https://registry.yarnpkg.com/universalify/-/universalify-2.0.0.tgz#75a4984efedc4b08975c5aeb73f530d02df25717"
|
||||
integrity sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==
|
||||
20
.github/workflows/semantic.yml
vendored
Normal file
20
.github/workflows/semantic.yml
vendored
Normal file
@@ -0,0 +1,20 @@
|
||||
name: "Check Semantic Commit"
|
||||
|
||||
on:
|
||||
pull_request_target:
|
||||
types:
|
||||
- opened
|
||||
- edited
|
||||
- synchronize
|
||||
|
||||
jobs:
|
||||
main:
|
||||
name: Validate PR Title
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: semantic-pull-request
|
||||
uses: amannn/action-semantic-pull-request@v4
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
with:
|
||||
validateSingleCommit: false
|
||||
5
BUILD.gn
5
BUILD.gn
@@ -1047,7 +1047,6 @@ if (is_mac) {
|
||||
"shell/app/electron_main_mac.cc",
|
||||
"shell/app/uv_stdio_fix.cc",
|
||||
"shell/app/uv_stdio_fix.h",
|
||||
"shell/common/electron_constants.cc",
|
||||
]
|
||||
include_dirs = [ "." ]
|
||||
deps = [
|
||||
@@ -1264,6 +1263,10 @@ if (is_mac) {
|
||||
if (!is_component_build && is_component_ffmpeg) {
|
||||
configs += [ "//build/config/gcc:rpath_for_built_shared_libraries" ]
|
||||
}
|
||||
|
||||
if (is_linux) {
|
||||
deps += [ "//sandbox/linux:chrome_sandbox" ]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1 +1 @@
|
||||
17.3.1
|
||||
17.4.8
|
||||
@@ -11,7 +11,7 @@
|
||||
# - "TARGET_ARCH" Choose from {'ia32', 'x64', 'arm', 'arm64', 'mips64el'}.
|
||||
# Is used in some publishing scripts, but does NOT affect the Electron binary.
|
||||
# Must match 'target_cpu' passed to "GN_EXTRA_ARGS" and "NPM_CONFIG_ARCH" value.
|
||||
# - "UPLOAD_TO_S3" Set it to '1' upload a release to the S3 bucket.
|
||||
# - "UPLOAD_TO_STORAGE" Set it to '1' upload a release to the Azure bucket.
|
||||
# Otherwise the release will be uploaded to the Github Releases.
|
||||
# (The value is only checked if "ELECTRON_RELEASE" is defined.)
|
||||
#
|
||||
@@ -231,9 +231,9 @@ deploy_script:
|
||||
- cd electron
|
||||
- ps: >-
|
||||
if (Test-Path Env:\ELECTRON_RELEASE) {
|
||||
if (Test-Path Env:\UPLOAD_TO_S3) {
|
||||
Write-Output "Uploading Electron release distribution to s3"
|
||||
& python script\release\uploaders\upload.py --verbose --upload_to_s3
|
||||
if (Test-Path Env:\UPLOAD_TO_STORAGE) {
|
||||
Write-Output "Uploading Electron release distribution to azure"
|
||||
& python script\release\uploaders\upload.py --verbose --upload_to_storage
|
||||
} else {
|
||||
Write-Output "Uploading Electron release distribution to github releases"
|
||||
& python script\release\uploaders\upload.py --verbose
|
||||
|
||||
@@ -19,6 +19,9 @@ proprietary_codecs = true
|
||||
ffmpeg_branding = "Chrome"
|
||||
|
||||
enable_basic_printing = true
|
||||
|
||||
# Removes DLLs from the build, which are only meant to be used for Chromium development.
|
||||
# See https://github.com/electron/electron/pull/17985
|
||||
angle_enable_vulkan_validation_layers = false
|
||||
dawn_enable_vulkan_validation_layers = false
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
#!/usr/bin/env python
|
||||
#!/usr/bin/env python3
|
||||
|
||||
import os
|
||||
import subprocess
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
#!/usr/bin/env python
|
||||
#!/usr/bin/env python3
|
||||
from __future__ import print_function
|
||||
import os
|
||||
import subprocess
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
#!/usr/bin/env python
|
||||
#!/usr/bin/env python3
|
||||
import os
|
||||
import subprocess
|
||||
import sys
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
#!/usr/bin/env python
|
||||
#!/usr/bin/env python3
|
||||
from __future__ import print_function
|
||||
import os
|
||||
import subprocess
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
#!/usr/bin/env python
|
||||
#!/usr/bin/env python3
|
||||
from __future__ import print_function
|
||||
import os
|
||||
import subprocess
|
||||
|
||||
@@ -457,7 +457,7 @@ window.onbeforeunload = (e) => {
|
||||
// a non-void value will silently cancel the close.
|
||||
// It is recommended to use the dialog API to let the user confirm closing the
|
||||
// application.
|
||||
e.returnValue = false // equivalent to `return false` but not recommended
|
||||
e.returnValue = false
|
||||
}
|
||||
```
|
||||
|
||||
@@ -1811,6 +1811,16 @@ with `addBrowserView` or `setBrowserView`.
|
||||
**Note:** The BrowserView API is currently experimental and may change or be
|
||||
removed in future Electron releases.
|
||||
|
||||
#### `win.setTitleBarOverlay(options)` _Windows_
|
||||
|
||||
* `options` Object
|
||||
* `color` String (optional) _Windows_ - The CSS color of the Window Controls Overlay when enabled.
|
||||
* `symbolColor` String (optional) _Windows_ - The CSS color of the symbols on the Window Controls Overlay when enabled.
|
||||
* `height` Integer (optional) _Windows_ - The height of the title bar and Window Controls Overlay in pixels.
|
||||
|
||||
On a Window with Window Controls Overlay already enabled, this method updates
|
||||
the style of the title bar overlay.
|
||||
|
||||
[runtime-enabled-features]: https://cs.chromium.org/chromium/src/third_party/blink/renderer/platform/runtime_enabled_features.json5?l=70
|
||||
[page-visibility-api]: https://developer.mozilla.org/en-US/docs/Web/API/Page_Visibility_API
|
||||
[quick-look]: https://en.wikipedia.org/wiki/Quick_Look
|
||||
|
||||
@@ -18,9 +18,9 @@ The `safeStorage` module has the following methods:
|
||||
|
||||
Returns `boolean` - Whether encryption is available.
|
||||
|
||||
On Linux, returns true if the secret key is
|
||||
available. On MacOS, returns true if Keychain is available.
|
||||
On Windows, returns true with no other preconditions.
|
||||
On Linux, returns true if the app has emitted the `ready` event and the secret key is available.
|
||||
On MacOS, returns true if Keychain is available.
|
||||
On Windows, returns true once the app has emitted the `ready` event.
|
||||
|
||||
### `safeStorage.encryptString(plainText)`
|
||||
|
||||
|
||||
@@ -7,21 +7,7 @@ Follow the guidelines below for building **Electron itself** on Linux, for the p
|
||||
## Prerequisites
|
||||
|
||||
* At least 25GB disk space and 8GB RAM.
|
||||
* Python 2.7.x. Some distributions like CentOS 6.x still use Python 2.6.x
|
||||
so you may need to check your Python version with `python -V`.
|
||||
|
||||
Please also ensure that your system and Python version support at least TLS 1.2.
|
||||
For a quick test, run the following script:
|
||||
|
||||
```sh
|
||||
$ npx @electron/check-python-tls
|
||||
```
|
||||
|
||||
If the script returns that your configuration is using an outdated security
|
||||
protocol, use your system's package manager to update Python to the latest
|
||||
version in the 2.7.x branch. Alternatively, visit https://www.python.org/downloads/
|
||||
for detailed instructions.
|
||||
|
||||
* Python >= 3.7.
|
||||
* Node.js. There are various ways to install Node. You can download
|
||||
source code from [nodejs.org](https://nodejs.org) and compile it.
|
||||
Doing so permits installing Node on your own home directory as a standard user.
|
||||
|
||||
@@ -6,45 +6,12 @@ Follow the guidelines below for building **Electron itself** on macOS, for the p
|
||||
|
||||
## Prerequisites
|
||||
|
||||
* macOS >= 10.11.6
|
||||
* [Xcode](https://developer.apple.com/technologies/tools/) >= 9.0.0
|
||||
* macOS >= 11.6.0
|
||||
* [Xcode](https://developer.apple.com/technologies/tools/). The exact version
|
||||
needed depends on what branch you are building, but the latest version of
|
||||
Xcode is generally a good bet for building `main`.
|
||||
* [node.js](https://nodejs.org) (external)
|
||||
* Python 2.7 with support for TLS 1.2
|
||||
|
||||
## Python
|
||||
|
||||
Please also ensure that your system and Python version support at least TLS 1.2.
|
||||
This depends on both your version of macOS and Python. For a quick test, run:
|
||||
|
||||
```sh
|
||||
$ npx @electron/check-python-tls
|
||||
```
|
||||
|
||||
If the script returns that your configuration is using an outdated security
|
||||
protocol, you can either update macOS to High Sierra or install a new version
|
||||
of Python 2.7.x. To upgrade Python, use [Homebrew](https://brew.sh/):
|
||||
|
||||
```sh
|
||||
$ brew install python@2 && brew link python@2 --force
|
||||
```
|
||||
|
||||
If you are using Python as provided by Homebrew, you also need to install
|
||||
the following Python modules:
|
||||
|
||||
* [pyobjc](https://pypi.org/project/pyobjc/#description)
|
||||
|
||||
You can use `pip` to install it:
|
||||
|
||||
```sh
|
||||
$ pip install pyobjc
|
||||
```
|
||||
|
||||
## macOS SDK
|
||||
|
||||
If you're developing Electron and don't plan to redistribute your
|
||||
custom Electron build, you may skip this section.
|
||||
|
||||
Official Electron builds are built with [Xcode 12.2](https://download.developer.apple.com/Developer_Tools/Xcode_12.2/Xcode_12.2.xip), and the macOS 11.0 SDK. Building with a newer SDK works too, but the releases currently use the 11.0 SDK.
|
||||
* Python >= 3.7
|
||||
|
||||
## Building Electron
|
||||
|
||||
|
||||
@@ -28,7 +28,7 @@ For C++ and Python, we follow Chromium's [Coding
|
||||
Style](https://chromium.googlesource.com/chromium/src/+/refs/heads/main/styleguide/styleguide.md).
|
||||
There is also a script `script/cpplint.py` to check whether all files conform.
|
||||
|
||||
The Python version we are using now is Python 2.7.
|
||||
The Python version we are using now is Python 3.9.
|
||||
|
||||
The C++ code uses a lot of Chromium's abstractions and types, so it's
|
||||
recommended to get acquainted with them. A good place to start is
|
||||
|
||||
@@ -177,6 +177,7 @@ template("electron_paks") {
|
||||
"${root_gen_dir}/components/strings/components_strings_",
|
||||
"${root_gen_dir}/third_party/blink/public/strings/blink_strings_",
|
||||
"${root_gen_dir}/device/bluetooth/strings/bluetooth_strings_",
|
||||
"${root_gen_dir}/extensions/strings/extensions_strings_",
|
||||
"${root_gen_dir}/services/strings/services_strings_",
|
||||
"${root_gen_dir}/ui/strings/app_locale_settings_",
|
||||
"${root_gen_dir}/ui/strings/ax_strings_",
|
||||
@@ -186,6 +187,7 @@ template("electron_paks") {
|
||||
"//chrome/app/resources:platform_locale_settings",
|
||||
"//components/strings:components_strings",
|
||||
"//device/bluetooth/strings",
|
||||
"//extensions/strings",
|
||||
"//services/strings",
|
||||
"//third_party/blink/public/strings",
|
||||
"//ui/strings:app_locale_settings",
|
||||
|
||||
@@ -72,7 +72,10 @@ BrowserWindow.getAllWindows = () => {
|
||||
|
||||
BrowserWindow.getFocusedWindow = () => {
|
||||
for (const window of BrowserWindow.getAllWindows()) {
|
||||
if (window.isFocused() || window.isDevToolsFocused()) return window;
|
||||
const hasWC = window.webContents && !window.webContents.isDestroyed();
|
||||
if (!window.isDestroyed() && hasWC) {
|
||||
if (window.isFocused() || window.isDevToolsFocused()) return window;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
};
|
||||
|
||||
@@ -613,6 +613,7 @@ WebContents.prototype._init = function () {
|
||||
});
|
||||
|
||||
this.on('-ipc-ports' as any, function (event: Electron.IpcMainEvent, internal: boolean, channel: string, message: any, ports: any[]) {
|
||||
addSenderFrameToEvent(event);
|
||||
event.ports = ports.map(p => new MessagePortMain(p));
|
||||
ipcMain.emit(channel, event, message);
|
||||
});
|
||||
|
||||
11
package.json
11
package.json
@@ -1,9 +1,10 @@
|
||||
{
|
||||
"name": "electron",
|
||||
"version": "17.3.1",
|
||||
"version": "17.4.8",
|
||||
"repository": "https://github.com/electron/electron",
|
||||
"description": "Build cross platform desktop apps with JavaScript, HTML, and CSS",
|
||||
"devDependencies": {
|
||||
"@azure/storage-blob": "^12.9.0",
|
||||
"@electron/docs-parser": "^0.12.3",
|
||||
"@electron/typescript-definitions": "^8.9.5",
|
||||
"@octokit/auth-app": "^2.10.0",
|
||||
@@ -78,14 +79,14 @@
|
||||
"generate-version-json": "node script/generate-version-json.js",
|
||||
"lint": "node ./script/lint.js && npm run lint:clang-format && npm run lint:docs",
|
||||
"lint:js": "node ./script/lint.js --js",
|
||||
"lint:clang-format": "python script/run-clang-format.py -r -c shell/ || (echo \"\\nCode not formatted correctly.\" && exit 1)",
|
||||
"lint:clang-format": "python3 script/run-clang-format.py -r -c shell/ || (echo \"\\nCode not formatted correctly.\" && exit 1)",
|
||||
"lint:clang-tidy": "ts-node ./script/run-clang-tidy.ts",
|
||||
"lint:cpp": "node ./script/lint.js --cc",
|
||||
"lint:objc": "node ./script/lint.js --objc",
|
||||
"lint:py": "node ./script/lint.js --py",
|
||||
"lint:gn": "node ./script/lint.js --gn",
|
||||
"lint:docs": "remark docs -qf && npm run lint:js-in-markdown && npm run create-typescript-definitions && npm run lint:docs-relative-links && npm run lint:markdownlint",
|
||||
"lint:docs-relative-links": "python ./script/check-relative-doc-links.py",
|
||||
"lint:docs-relative-links": "python3 ./script/check-relative-doc-links.py",
|
||||
"lint:markdownlint": "markdownlint \"*.md\" \"docs/**/*.md\"",
|
||||
"lint:js-in-markdown": "standard-markdown docs",
|
||||
"create-api-json": "electron-docs-parser --dir=./",
|
||||
@@ -116,14 +117,14 @@
|
||||
"ts-node script/gen-filenames.ts"
|
||||
],
|
||||
"*.{cc,mm,c,h}": [
|
||||
"python script/run-clang-format.py -r -c --fix"
|
||||
"python3 script/run-clang-format.py -r -c --fix"
|
||||
],
|
||||
"*.md": [
|
||||
"npm run lint:docs"
|
||||
],
|
||||
"*.{gn,gni}": [
|
||||
"npm run gn-check",
|
||||
"python script/run-gn-format.py"
|
||||
"python3 script/run-gn-format.py"
|
||||
],
|
||||
"*.py": [
|
||||
"node script/lint.js --py --fix --only --"
|
||||
|
||||
9
patches/angle/.patches
Normal file
9
patches/angle/.patches
Normal file
@@ -0,0 +1,9 @@
|
||||
cherry-pick-d27d9d059b51.patch
|
||||
m100_fix_crash_when_pausing_xfb_then_deleting_a_buffer.patch
|
||||
cherry-pick-d49484c21e3c.patch
|
||||
cherry-pick-a602a068e022.patch
|
||||
cherry-pick-a4f71e40e571.patch
|
||||
cherry-pick-9768648fffc9.patch
|
||||
cherry-pick-03aa5ae75c29.patch
|
||||
cherry-pick-801b904aea7d.patch
|
||||
cherry-pick-6661eb4900da.patch
|
||||
76
patches/angle/cherry-pick-03aa5ae75c29.patch
Normal file
76
patches/angle/cherry-pick-03aa5ae75c29.patch
Normal file
@@ -0,0 +1,76 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Geoff Lang <geofflang@google.com>
|
||||
Date: Wed, 1 Jun 2022 11:22:42 -0400
|
||||
Subject: M102: Ignore eglBind/ReleaseTexImage calls for lost contexts.
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
|
||||
eglBindTexImage and eglReleaseTexImage no-op when no context is
|
||||
current. Extend this to lost contexts to match the behaviour of making
|
||||
a GL call on a lost context.
|
||||
|
||||
This avoids potential unexpected bad accesses in the backends.
|
||||
|
||||
Bug: chromium:1316578
|
||||
Change-Id: I7b309c297e0c803019720733dee2950abb4c4b5f
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/3683869
|
||||
Reviewed-by: Jamie Madill <jmadill@chromium.org>
|
||||
Reviewed-by: Alexis Hétu <sugoi@google.com>
|
||||
Reviewed-by: Alexis Hétu <sugoi@chromium.org>
|
||||
Commit-Queue: Geoff Lang <geofflang@chromium.org>
|
||||
(cherry picked from commit bfab7e60a15dc6f72e34406d3f2a3996cd8d0be2)
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/3691180
|
||||
|
||||
diff --git a/src/libANGLE/validationEGL.cpp b/src/libANGLE/validationEGL.cpp
|
||||
index 7d2d43afa2cacf4445c528209b1fba6c1c6485c4..49d92219af76cbc8049f5c29a60fba3b26459bd0 100644
|
||||
--- a/src/libANGLE/validationEGL.cpp
|
||||
+++ b/src/libANGLE/validationEGL.cpp
|
||||
@@ -4762,7 +4762,7 @@ bool ValidateBindTexImage(const ValidationContext *val,
|
||||
}
|
||||
|
||||
gl::Context *context = val->eglThread->getContext();
|
||||
- if (context)
|
||||
+ if (context && !context->isContextLost())
|
||||
{
|
||||
gl::TextureType type = egl_gl::EGLTextureTargetToTextureType(surface->getTextureTarget());
|
||||
gl::Texture *textureObject = context->getTextureByType(type);
|
||||
diff --git a/src/libGLESv2/egl_stubs.cpp b/src/libGLESv2/egl_stubs.cpp
|
||||
index fa37ae68e8e87aefd111440463611f737665691b..0b9d155d0d74f5b6b60667243d03182cc8b4d442 100644
|
||||
--- a/src/libGLESv2/egl_stubs.cpp
|
||||
+++ b/src/libGLESv2/egl_stubs.cpp
|
||||
@@ -61,7 +61,7 @@ EGLBoolean BindTexImage(Thread *thread, Display *display, Surface *eglSurface, E
|
||||
GetDisplayIfValid(display), EGL_FALSE);
|
||||
|
||||
gl::Context *context = thread->getContext();
|
||||
- if (context)
|
||||
+ if (context && !context->isContextLost())
|
||||
{
|
||||
gl::TextureType type =
|
||||
egl_gl::EGLTextureTargetToTextureType(eglSurface->getTextureTarget());
|
||||
@@ -569,15 +569,18 @@ EGLBoolean ReleaseTexImage(Thread *thread, Display *display, Surface *eglSurface
|
||||
{
|
||||
ANGLE_EGL_TRY_RETURN(thread, display->prepareForCall(), "eglReleaseTexImage",
|
||||
GetDisplayIfValid(display), EGL_FALSE);
|
||||
- gl::Texture *texture = eglSurface->getBoundTexture();
|
||||
-
|
||||
- if (texture)
|
||||
+ gl::Context *context = thread->getContext();
|
||||
+ if (context && !context->isContextLost())
|
||||
{
|
||||
- ANGLE_EGL_TRY_RETURN(thread, eglSurface->releaseTexImage(thread->getContext(), buffer),
|
||||
- "eglReleaseTexImage", GetSurfaceIfValid(display, eglSurface),
|
||||
- EGL_FALSE);
|
||||
- }
|
||||
+ gl::Texture *texture = eglSurface->getBoundTexture();
|
||||
|
||||
+ if (texture)
|
||||
+ {
|
||||
+ ANGLE_EGL_TRY_RETURN(thread, eglSurface->releaseTexImage(thread->getContext(), buffer),
|
||||
+ "eglReleaseTexImage", GetSurfaceIfValid(display, eglSurface),
|
||||
+ EGL_FALSE);
|
||||
+ }
|
||||
+ }
|
||||
thread->setSuccess();
|
||||
return EGL_TRUE;
|
||||
}
|
||||
27
patches/angle/cherry-pick-6661eb4900da.patch
Normal file
27
patches/angle/cherry-pick-6661eb4900da.patch
Normal file
@@ -0,0 +1,27 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Jamie Madill <jmadill@chromium.org>
|
||||
Date: Mon, 2 May 2022 15:42:23 -0400
|
||||
Subject: Fix validation cache when deleting a Transform Feedback.
|
||||
|
||||
Bug: chromium:1320024
|
||||
Change-Id: I76ef85a3c65c663c138d8caebd4ef2c0da53cd4f
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/3621780
|
||||
Commit-Queue: Jamie Madill <jmadill@chromium.org>
|
||||
Reviewed-by: Shahbaz Youssefi <syoussefi@chromium.org>
|
||||
Commit-Queue: Shahbaz Youssefi <syoussefi@chromium.org>
|
||||
(cherry picked from commit 84e42c3b04da9e2c9d93d35bb6f2b1830fef22f4)
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/3650697
|
||||
Reviewed-by: Geoff Lang <geofflang@chromium.org>
|
||||
|
||||
diff --git a/src/libANGLE/Context.cpp b/src/libANGLE/Context.cpp
|
||||
index 141d106c8ea4c92ecf1e01b3fa7c3bf11ba7d5d3..e74d323b833d66e2891eaf77deb4225d98766036 100644
|
||||
--- a/src/libANGLE/Context.cpp
|
||||
+++ b/src/libANGLE/Context.cpp
|
||||
@@ -3020,6 +3020,7 @@ void Context::detachTransformFeedback(TransformFeedbackID transformFeedback)
|
||||
if (mState.removeTransformFeedbackBinding(this, transformFeedback))
|
||||
{
|
||||
bindTransformFeedback(GL_TRANSFORM_FEEDBACK, {0});
|
||||
+ mStateCache.onActiveTransformFeedbackChange(this);
|
||||
}
|
||||
}
|
||||
|
||||
238
patches/angle/cherry-pick-801b904aea7d.patch
Normal file
238
patches/angle/cherry-pick-801b904aea7d.patch
Normal file
@@ -0,0 +1,238 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Jamie Madill <jmadill@chromium.org>
|
||||
Date: Fri, 20 May 2022 10:26:15 -0400
|
||||
Subject: D3D: Fix race condition with parallel shader compile.
|
||||
|
||||
Bug: chromium:1317673
|
||||
Change-Id: I0fb7c9a66248852e41e8700e80c295393ef941e8
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/3651153
|
||||
Reviewed-by: Jie A Chen <jie.a.chen@intel.com>
|
||||
Reviewed-by: Lingfeng Yang <lfy@google.com>
|
||||
Commit-Queue: Jamie Madill <jmadill@chromium.org>
|
||||
(cherry picked from commit 4a20c9143abbf29c649cf643182735e8952089e3)
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/3691050
|
||||
Bot-Commit: Rubber Stamper <rubber-stamper@appspot.gserviceaccount.com>
|
||||
|
||||
diff --git a/src/libANGLE/renderer/d3d/ProgramD3D.cpp b/src/libANGLE/renderer/d3d/ProgramD3D.cpp
|
||||
index 59fe34fc46a1bfbc7b4be1aad6ad84b6da303b5b..3256357a80d69739661ec1fd32220d3037145875 100644
|
||||
--- a/src/libANGLE/renderer/d3d/ProgramD3D.cpp
|
||||
+++ b/src/libANGLE/renderer/d3d/ProgramD3D.cpp
|
||||
@@ -1687,12 +1687,6 @@ class ProgramD3D::GetVertexExecutableTask : public ProgramD3D::GetExecutableTask
|
||||
angle::Result run() override
|
||||
{
|
||||
ANGLE_TRACE_EVENT0("gpu.angle", "ProgramD3D::GetVertexExecutableTask::run");
|
||||
- if (!mProgram->mState.getAttachedShader(gl::ShaderType::Vertex))
|
||||
- {
|
||||
- return angle::Result::Continue;
|
||||
- }
|
||||
-
|
||||
- mProgram->updateCachedInputLayoutFromShader();
|
||||
|
||||
ANGLE_TRY(mProgram->getVertexExecutableForCachedInputLayout(this, &mExecutable, &mInfoLog));
|
||||
|
||||
@@ -2147,6 +2141,11 @@ std::unique_ptr<LinkEvent> ProgramD3D::link(const gl::Context *context,
|
||||
|
||||
linkResources(resources);
|
||||
|
||||
+ if (mState.getAttachedShader(gl::ShaderType::Vertex))
|
||||
+ {
|
||||
+ updateCachedInputLayoutFromShader();
|
||||
+ }
|
||||
+
|
||||
return compileProgramExecutables(context, infoLog);
|
||||
}
|
||||
}
|
||||
diff --git a/src/tests/gl_tests/ParallelShaderCompileTest.cpp b/src/tests/gl_tests/ParallelShaderCompileTest.cpp
|
||||
index bcd88ef01308759085c8244ad2058efe68686f2b..a98aff540c642617bba366b2e238519942d7e349 100644
|
||||
--- a/src/tests/gl_tests/ParallelShaderCompileTest.cpp
|
||||
+++ b/src/tests/gl_tests/ParallelShaderCompileTest.cpp
|
||||
@@ -58,9 +58,10 @@ class ParallelShaderCompileTest : public ANGLETest
|
||||
Task(int id) : mID(id) {}
|
||||
virtual ~Task() {}
|
||||
|
||||
- virtual bool compile() = 0;
|
||||
- virtual bool isCompileCompleted() = 0;
|
||||
- virtual bool link() = 0;
|
||||
+ virtual bool compile() = 0;
|
||||
+ virtual bool isCompileCompleted() = 0;
|
||||
+ virtual bool link() = 0;
|
||||
+ virtual void postLink() {}
|
||||
virtual void runAndVerify(ParallelShaderCompileTest *test) = 0;
|
||||
|
||||
bool isLinkCompleted()
|
||||
@@ -71,7 +72,7 @@ class ParallelShaderCompileTest : public ANGLETest
|
||||
}
|
||||
|
||||
protected:
|
||||
- std::string insertRandomString(const std::string &source)
|
||||
+ static std::string InsertRandomString(const std::string &source)
|
||||
{
|
||||
RNG rng;
|
||||
std::ostringstream ostream;
|
||||
@@ -80,7 +81,7 @@ class ParallelShaderCompileTest : public ANGLETest
|
||||
return ostream.str();
|
||||
}
|
||||
|
||||
- GLuint CompileShader(GLenum type, const std::string &source)
|
||||
+ static GLuint CompileShader(GLenum type, const std::string &source)
|
||||
{
|
||||
GLuint shader = glCreateShader(type);
|
||||
|
||||
@@ -90,7 +91,14 @@ class ParallelShaderCompileTest : public ANGLETest
|
||||
return shader;
|
||||
}
|
||||
|
||||
- bool checkShader(GLuint shader)
|
||||
+ static void RecompileShader(GLuint shader, const std::string &source)
|
||||
+ {
|
||||
+ const char *sourceArray[1] = {source.c_str()};
|
||||
+ glShaderSource(shader, 1, sourceArray, nullptr);
|
||||
+ glCompileShader(shader);
|
||||
+ }
|
||||
+
|
||||
+ static bool CheckShader(GLuint shader)
|
||||
{
|
||||
GLint compileResult;
|
||||
glGetShaderiv(shader, GL_COMPILE_STATUS, &compileResult);
|
||||
@@ -129,7 +137,7 @@ class ParallelShaderCompileTest : public ANGLETest
|
||||
TaskRunner() {}
|
||||
~TaskRunner() {}
|
||||
|
||||
- void run(ParallelShaderCompileTest *test)
|
||||
+ void run(ParallelShaderCompileTest *test, unsigned int pollInterval)
|
||||
{
|
||||
|
||||
std::vector<std::unique_ptr<T>> compileTasks;
|
||||
@@ -151,6 +159,7 @@ class ParallelShaderCompileTest : public ANGLETest
|
||||
if (task->isCompileCompleted())
|
||||
{
|
||||
bool isLinking = task->link();
|
||||
+ task->postLink();
|
||||
ASSERT_TRUE(isLinking);
|
||||
linkTasks.push_back(std::move(task));
|
||||
compileTasks.erase(compileTasks.begin() + i);
|
||||
@@ -158,7 +167,10 @@ class ParallelShaderCompileTest : public ANGLETest
|
||||
}
|
||||
++i;
|
||||
}
|
||||
- angle::Sleep(kPollInterval);
|
||||
+ if (pollInterval != 0)
|
||||
+ {
|
||||
+ angle::Sleep(pollInterval);
|
||||
+ }
|
||||
}
|
||||
|
||||
while (!linkTasks.empty())
|
||||
@@ -173,9 +185,16 @@ class ParallelShaderCompileTest : public ANGLETest
|
||||
linkTasks.erase(linkTasks.begin() + i);
|
||||
continue;
|
||||
}
|
||||
+ else
|
||||
+ {
|
||||
+ task->postLink();
|
||||
+ }
|
||||
++i;
|
||||
}
|
||||
- angle::Sleep(kPollInterval);
|
||||
+ if (pollInterval != 0)
|
||||
+ {
|
||||
+ angle::Sleep(pollInterval);
|
||||
+ }
|
||||
}
|
||||
}
|
||||
};
|
||||
@@ -192,9 +211,9 @@ class ParallelShaderCompileTest : public ANGLETest
|
||||
bool compile() override
|
||||
{
|
||||
mVertexShader =
|
||||
- CompileShader(GL_VERTEX_SHADER, insertRandomString(essl1_shaders::vs::Simple()));
|
||||
+ CompileShader(GL_VERTEX_SHADER, InsertRandomString(essl1_shaders::vs::Simple()));
|
||||
mFragmentShader = CompileShader(GL_FRAGMENT_SHADER,
|
||||
- insertRandomString(essl1_shaders::fs::UniformColor()));
|
||||
+ InsertRandomString(essl1_shaders::fs::UniformColor()));
|
||||
return (mVertexShader != 0 && mFragmentShader != 0);
|
||||
}
|
||||
|
||||
@@ -213,7 +232,7 @@ class ParallelShaderCompileTest : public ANGLETest
|
||||
bool link() override
|
||||
{
|
||||
mProgram = 0;
|
||||
- if (checkShader(mVertexShader) && checkShader(mFragmentShader))
|
||||
+ if (CheckShader(mVertexShader) && CheckShader(mFragmentShader))
|
||||
{
|
||||
mProgram = glCreateProgram();
|
||||
glAttachShader(mProgram, mVertexShader);
|
||||
@@ -244,10 +263,25 @@ class ParallelShaderCompileTest : public ANGLETest
|
||||
ASSERT_GL_NO_ERROR();
|
||||
}
|
||||
|
||||
+ protected:
|
||||
+ void recompile()
|
||||
+ {
|
||||
+ RecompileShader(mVertexShader, essl1_shaders::vs::Simple());
|
||||
+ RecompileShader(mFragmentShader, essl1_shaders::fs::UniformColor());
|
||||
+ }
|
||||
+
|
||||
private:
|
||||
- GLColor mColor;
|
||||
GLuint mVertexShader;
|
||||
GLuint mFragmentShader;
|
||||
+ GLColor mColor;
|
||||
+ };
|
||||
+
|
||||
+ class ClearColorWithDrawRecompile : public ClearColorWithDraw
|
||||
+ {
|
||||
+ public:
|
||||
+ ClearColorWithDrawRecompile(int taskID) : ClearColorWithDraw(taskID) {}
|
||||
+
|
||||
+ void postLink() override { recompile(); }
|
||||
};
|
||||
|
||||
class ImageLoadStore : public Task
|
||||
@@ -268,7 +302,7 @@ void main()
|
||||
imageStore(uImage_2, ivec2(gl_LocalInvocationID.xy), value);
|
||||
})";
|
||||
|
||||
- mShader = CompileShader(GL_COMPUTE_SHADER, insertRandomString(kCSSource));
|
||||
+ mShader = CompileShader(GL_COMPUTE_SHADER, InsertRandomString(kCSSource));
|
||||
return mShader != 0;
|
||||
}
|
||||
|
||||
@@ -282,7 +316,7 @@ void main()
|
||||
bool link() override
|
||||
{
|
||||
mProgram = 0;
|
||||
- if (checkShader(mShader))
|
||||
+ if (CheckShader(mShader))
|
||||
{
|
||||
mProgram = glCreateProgram();
|
||||
glAttachShader(mProgram, mShader);
|
||||
@@ -370,7 +404,18 @@ TEST_P(ParallelShaderCompileTest, LinkAndDrawManyPrograms)
|
||||
ANGLE_SKIP_TEST_IF(!ensureParallelShaderCompileExtensionAvailable());
|
||||
|
||||
TaskRunner<ClearColorWithDraw> runner;
|
||||
- runner.run(this);
|
||||
+ runner.run(this, kPollInterval);
|
||||
+}
|
||||
+
|
||||
+// Tests no crash in case that the Shader starts another compile while the Program being attached
|
||||
+// to is still linking.
|
||||
+// crbug.com/1317673
|
||||
+TEST_P(ParallelShaderCompileTest, LinkProgramAndRecompileShader)
|
||||
+{
|
||||
+ ANGLE_SKIP_TEST_IF(!ensureParallelShaderCompileExtensionAvailable());
|
||||
+
|
||||
+ TaskRunner<ClearColorWithDrawRecompile> runner;
|
||||
+ runner.run(this, 0);
|
||||
}
|
||||
|
||||
class ParallelShaderCompileTestES31 : public ParallelShaderCompileTest
|
||||
@@ -389,7 +434,7 @@ TEST_P(ParallelShaderCompileTestES31, LinkAndDispatchManyPrograms)
|
||||
ANGLE_SKIP_TEST_IF(!ensureParallelShaderCompileExtensionAvailable());
|
||||
|
||||
TaskRunner<ImageLoadStore> runner;
|
||||
- runner.run(this);
|
||||
+ runner.run(this, kPollInterval);
|
||||
}
|
||||
|
||||
ANGLE_INSTANTIATE_TEST_ES2(ParallelShaderCompileTest);
|
||||
26
patches/angle/cherry-pick-9768648fffc9.patch
Normal file
26
patches/angle/cherry-pick-9768648fffc9.patch
Normal file
@@ -0,0 +1,26 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: SeongHwan Park <ggabu423@gmail.com>
|
||||
Date: Tue, 31 May 2022 02:41:32 +0900
|
||||
Subject: Fix to invalidate cache when binding Transform Feedback.
|
||||
|
||||
Bug: chromium:1330379
|
||||
Change-Id: I091116286ac511c50f9abcffa4d3cf350be920b4
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/3677115
|
||||
Commit-Queue: Jamie Madill <jmadill@chromium.org>
|
||||
Reviewed-by: Jamie Madill <jmadill@chromium.org>
|
||||
(cherry picked from commit d96cee6685099f6bcc392a4d20d28c8ec484673a)
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/3691799
|
||||
Reviewed-by: Shahbaz Youssefi <syoussefi@chromium.org>
|
||||
|
||||
diff --git a/src/libANGLE/Context.cpp b/src/libANGLE/Context.cpp
|
||||
index 6b4d8d826ef3518ad11b1b39c78634f05d464b39..141d106c8ea4c92ecf1e01b3fa7c3bf11ba7d5d3 100644
|
||||
--- a/src/libANGLE/Context.cpp
|
||||
+++ b/src/libANGLE/Context.cpp
|
||||
@@ -1306,6 +1306,7 @@ void Context::bindTransformFeedback(GLenum target, TransformFeedbackID transform
|
||||
TransformFeedback *transformFeedback =
|
||||
checkTransformFeedbackAllocation(transformFeedbackHandle);
|
||||
mState.setTransformFeedbackBinding(this, transformFeedback);
|
||||
+ mStateCache.onActiveTransformFeedbackChange(this);
|
||||
}
|
||||
|
||||
void Context::bindProgramPipeline(ProgramPipelineID pipelineHandle)
|
||||
58
patches/angle/cherry-pick-a4f71e40e571.patch
Normal file
58
patches/angle/cherry-pick-a4f71e40e571.patch
Normal file
@@ -0,0 +1,58 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Geoff Lang <geofflang@google.com>
|
||||
Date: Fri, 1 Apr 2022 11:38:17 -0400
|
||||
Subject: Fix CheckedNumeric using the wrong type.
|
||||
|
||||
Validation for glBufferSubData checks that the buffer is large enough
|
||||
for size+offset but verifies they fit in a size_t which is a different
|
||||
type than the deduced type for size+offset on 32-bit systems.
|
||||
|
||||
Use decltype to ensure that we always verify there is no overflow on the
|
||||
correct type.
|
||||
|
||||
Bug: chromium:1298867
|
||||
Change-Id: I82f534b2d227d3273a763e626ebeae068dc918dc
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/3563515
|
||||
Reviewed-by: Jamie Madill <jmadill@chromium.org>
|
||||
Reviewed-by: Jonah Ryan-Davis <jonahr@google.com>
|
||||
Commit-Queue: Geoff Lang <geofflang@chromium.org>
|
||||
(cherry picked from commit c458b5add432c3da98ef370680518d0af7e4d4e3)
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/3630020
|
||||
|
||||
diff --git a/src/libANGLE/validationES2.cpp b/src/libANGLE/validationES2.cpp
|
||||
index 947bed25cad67a0182a0396e635f2e52f5cd5704..cbe932a6d2131322d6dbb3c17a0cd05af551e462 100644
|
||||
--- a/src/libANGLE/validationES2.cpp
|
||||
+++ b/src/libANGLE/validationES2.cpp
|
||||
@@ -3620,7 +3620,7 @@ bool ValidateBufferSubData(const Context *context,
|
||||
}
|
||||
|
||||
// Check for possible overflow of size + offset
|
||||
- angle::CheckedNumeric<size_t> checkedSize(size);
|
||||
+ angle::CheckedNumeric<decltype(size + offset)> checkedSize(size);
|
||||
checkedSize += offset;
|
||||
if (!checkedSize.IsValid())
|
||||
{
|
||||
diff --git a/src/tests/gl_tests/BufferDataTest.cpp b/src/tests/gl_tests/BufferDataTest.cpp
|
||||
index 325ba67bc6997afbdadf80ccbd994ec8b3ce9521..b993f95c1d8e103f24054f21853fb326c2e12112 100644
|
||||
--- a/src/tests/gl_tests/BufferDataTest.cpp
|
||||
+++ b/src/tests/gl_tests/BufferDataTest.cpp
|
||||
@@ -824,6 +824,19 @@ TEST_P(BufferDataTest, MapWriteArrayBufferDataDrawArrays)
|
||||
EXPECT_GL_NO_ERROR();
|
||||
}
|
||||
|
||||
+// Verify that buffer sub data uploads are properly validated within the buffer size range on 32-bit
|
||||
+// systems.
|
||||
+TEST_P(BufferDataTest, BufferSizeValidation32Bit)
|
||||
+{
|
||||
+ GLBuffer buffer;
|
||||
+ glBindBuffer(GL_ARRAY_BUFFER, buffer);
|
||||
+ glBufferData(GL_ARRAY_BUFFER, 100, nullptr, GL_STATIC_DRAW);
|
||||
+
|
||||
+ GLubyte data = 0;
|
||||
+ glBufferSubData(GL_ARRAY_BUFFER, std::numeric_limits<uint32_t>::max(), 1, &data);
|
||||
+ EXPECT_GL_ERROR(GL_INVALID_VALUE);
|
||||
+}
|
||||
+
|
||||
// Tests a null crash bug caused by copying from null back-end buffer pointer
|
||||
// when calling bufferData again after drawing without calling bufferData in D3D11.
|
||||
TEST_P(BufferDataTestES3, DrawWithNotCallingBufferData)
|
||||
31
patches/angle/cherry-pick-a602a068e022.patch
Normal file
31
patches/angle/cherry-pick-a602a068e022.patch
Normal file
@@ -0,0 +1,31 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Jamie Madill <jmadill@chromium.org>
|
||||
Date: Tue, 19 Apr 2022 17:01:20 -0400
|
||||
Subject: Fix validate state cache after XFB buffer deleted.
|
||||
|
||||
Bug: chromium:1317650
|
||||
Change-Id: Iec9f1167c3b2957091dd0f4ef3efcfcd7c4bf3c0
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/3594250
|
||||
Reviewed-by: Shahbaz Youssefi <syoussefi@chromium.org>
|
||||
Auto-Submit: Jamie Madill <jmadill@chromium.org>
|
||||
Commit-Queue: Jamie Madill <jmadill@chromium.org>
|
||||
(cherry picked from commit 4efc4ee6830a8a53a0daf9daa3c7aa835db4220f)
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/3621779
|
||||
Reviewed-by: Amirali Abdolrashidi <abdolrashidi@google.com>
|
||||
|
||||
diff --git a/src/libANGLE/State.cpp b/src/libANGLE/State.cpp
|
||||
index ae245e4abdf9818d6aec83e4badad9811ed492b3..e9635038a1d4cc0ab5211b94c22d44f353388d64 100644
|
||||
--- a/src/libANGLE/State.cpp
|
||||
+++ b/src/libANGLE/State.cpp
|
||||
@@ -2174,10 +2174,7 @@ angle::Result State::detachBuffer(Context *context, const Buffer *buffer)
|
||||
if (curTransformFeedback)
|
||||
{
|
||||
ANGLE_TRY(curTransformFeedback->detachBuffer(context, bufferID));
|
||||
- if (isTransformFeedbackActiveUnpaused())
|
||||
- {
|
||||
- context->getStateCache().onActiveTransformFeedbackChange(context);
|
||||
- }
|
||||
+ context->getStateCache().onActiveTransformFeedbackChange(context);
|
||||
}
|
||||
|
||||
if (getVertexArray()->detachBuffer(context, bufferID))
|
||||
100
patches/angle/cherry-pick-d27d9d059b51.patch
Normal file
100
patches/angle/cherry-pick-d27d9d059b51.patch
Normal file
@@ -0,0 +1,100 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Charlie Lao <cclao@google.com>
|
||||
Date: Tue, 15 Mar 2022 09:39:36 -0700
|
||||
Subject: Vulkan: Update mCurrentElementArrayBuffersync based on dirty bit
|
||||
|
||||
M96 merge issues:
|
||||
ContextVk.cpp:
|
||||
ContextVk::setupIndexedDraw: vertexArrayVk/getVertexArray() isn't present in M96
|
||||
ContextVk::syncState: M96 uses mVertexArray instead of vertexArrayVk
|
||||
VertexArrayVk.cpp:
|
||||
VertexArrayVk::updateCurrentElementArrayBuffer doesn't exist in M9
|
||||
Created it and kept M96 logic for retrieving buffer/offset
|
||||
|
||||
The previous fix crrev.com/c/3513553 has run into corner case that
|
||||
requires more follow up change crrev.com/c/3522565. But with that, there
|
||||
is report that now we are hitting assertion in
|
||||
handleDirtyGraphicsIndexBuffer(). This becomes a bit fragile This new
|
||||
fix relies on the DIRTY_BIT_INDEX_BUFFER dirty bit and should be more
|
||||
reliable as long as the dirty bit is set properly (if not, then we have
|
||||
other bug that it won't even send down vulkan command to bind the
|
||||
correct element buffer). We could further optimize the code path and
|
||||
create a fast path for most common usages in the future.
|
||||
|
||||
Bug: chromium:1299261
|
||||
Change-Id: Ifa8f86d431798c9ca4c128ed71a3e9e0a3537ccb
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/3526021
|
||||
Commit-Queue: Charlie Lao <cclao@google.com>
|
||||
(cherry picked from commit 349636a05a3577a127adb6c79a1e947890bbe462)
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/3605834
|
||||
Reviewed-by: Achuith Bhandarkar <achuith@chromium.org>
|
||||
Reviewed-by: Charlie Lao <cclao@google.com>
|
||||
|
||||
diff --git a/src/libANGLE/renderer/vulkan/ContextVk.cpp b/src/libANGLE/renderer/vulkan/ContextVk.cpp
|
||||
index aa1e5fa793e98a284b3d5dbda58778b8c2f1eeef..d9f6bcd54943bd211f1dc2b1ea149c21a79979a0 100644
|
||||
--- a/src/libANGLE/renderer/vulkan/ContextVk.cpp
|
||||
+++ b/src/libANGLE/renderer/vulkan/ContextVk.cpp
|
||||
@@ -1062,6 +1062,17 @@ angle::Result ContextVk::setupIndexedDraw(const gl::Context *context,
|
||||
mGraphicsDirtyBits.set(DIRTY_BIT_INDEX_BUFFER);
|
||||
mLastIndexBufferOffset = indices;
|
||||
}
|
||||
+
|
||||
+ // When you draw with LineLoop mode or GL_UNSIGNED_BYTE type, we may allocate its own
|
||||
+ // element buffer and modify mCurrentElementArrayBuffer. When we switch out of that draw
|
||||
+ // mode, we must reset mCurrentElementArrayBuffer back to the vertexArray's element buffer.
|
||||
+ // Since in either case we set DIRTY_BIT_INDEX_BUFFER dirty bit, we use this bit to re-sync
|
||||
+ // mCurrentElementArrayBuffer.
|
||||
+ if (mGraphicsDirtyBits[DIRTY_BIT_INDEX_BUFFER])
|
||||
+ {
|
||||
+ mVertexArray->updateCurrentElementArrayBuffer();
|
||||
+ }
|
||||
+
|
||||
if (shouldConvertUint8VkIndexType(indexType) && mGraphicsDirtyBits[DIRTY_BIT_INDEX_BUFFER])
|
||||
{
|
||||
ANGLE_VK_PERF_WARNING(this, GL_DEBUG_SEVERITY_LOW,
|
||||
diff --git a/src/libANGLE/renderer/vulkan/VertexArrayVk.cpp b/src/libANGLE/renderer/vulkan/VertexArrayVk.cpp
|
||||
index eb401bfd8c1ccfc750d34b46e95d97c54a5a0fac..fd6fcf4c339f7d189217545e10c4c808e103f671 100644
|
||||
--- a/src/libANGLE/renderer/vulkan/VertexArrayVk.cpp
|
||||
+++ b/src/libANGLE/renderer/vulkan/VertexArrayVk.cpp
|
||||
@@ -454,6 +454,17 @@ angle::Result VertexArrayVk::convertVertexBufferCPU(ContextVk *contextVk,
|
||||
return angle::Result::Continue;
|
||||
}
|
||||
|
||||
+void VertexArrayVk::updateCurrentElementArrayBuffer()
|
||||
+{
|
||||
+ ASSERT(mState.getElementArrayBuffer() != nullptr);
|
||||
+ ASSERT(mState.getElementArrayBuffer()->getSize() > 0);
|
||||
+ gl::Buffer *bufferGL = mState.getElementArrayBuffer();
|
||||
+ BufferVk *bufferVk = vk::GetImpl(bufferGL);
|
||||
+ mCurrentElementArrayBuffer =
|
||||
+ &bufferVk->getBufferAndOffset(&mCurrentElementArrayBufferOffset);
|
||||
+
|
||||
+}
|
||||
+
|
||||
angle::Result VertexArrayVk::syncState(const gl::Context *context,
|
||||
const gl::VertexArray::DirtyBits &dirtyBits,
|
||||
gl::VertexArray::DirtyAttribBitsArray *attribBits,
|
||||
@@ -479,9 +490,7 @@ angle::Result VertexArrayVk::syncState(const gl::Context *context,
|
||||
{
|
||||
// Note that just updating buffer data may still result in a new
|
||||
// vk::BufferHelper allocation.
|
||||
- BufferVk *bufferVk = vk::GetImpl(bufferGL);
|
||||
- mCurrentElementArrayBuffer =
|
||||
- &bufferVk->getBufferAndOffset(&mCurrentElementArrayBufferOffset);
|
||||
+ updateCurrentElementArrayBuffer();
|
||||
}
|
||||
else
|
||||
{
|
||||
diff --git a/src/libANGLE/renderer/vulkan/VertexArrayVk.h b/src/libANGLE/renderer/vulkan/VertexArrayVk.h
|
||||
index c198265bf8ba2017a13fce558826862f450218b5..0b98a9ed46b7cd4b9588973c74b0bbaf9172ab6c 100644
|
||||
--- a/src/libANGLE/renderer/vulkan/VertexArrayVk.h
|
||||
+++ b/src/libANGLE/renderer/vulkan/VertexArrayVk.h
|
||||
@@ -34,6 +34,8 @@ class VertexArrayVk : public VertexArrayImpl
|
||||
|
||||
angle::Result updateActiveAttribInfo(ContextVk *contextVk);
|
||||
|
||||
+ void updateCurrentElementArrayBuffer();
|
||||
+
|
||||
angle::Result updateDefaultAttrib(ContextVk *contextVk,
|
||||
size_t attribIndex,
|
||||
VkBuffer bufferHandle,
|
||||
33
patches/angle/cherry-pick-d49484c21e3c.patch
Normal file
33
patches/angle/cherry-pick-d49484c21e3c.patch
Normal file
@@ -0,0 +1,33 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Jamie Madill <jmadill@chromium.org>
|
||||
Date: Mon, 11 Apr 2022 12:29:00 -0400
|
||||
Subject: Add error check on resuming XFB with deleted buffer.
|
||||
|
||||
Bug: chromium:1313905
|
||||
Change-Id: I22c6f6400b05ca32c922fba9a3b9d4b5841ca8b8
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/3578378
|
||||
Auto-Submit: Jamie Madill <jmadill@chromium.org>
|
||||
Reviewed-by: Geoff Lang <geofflang@chromium.org>
|
||||
Commit-Queue: Jamie Madill <jmadill@chromium.org>
|
||||
(cherry picked from commit 5c85fd4e11a3835a0719223a7cedb978d309da21)
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/3594103
|
||||
Reviewed-by: Shahbaz Youssefi <syoussefi@chromium.org>
|
||||
|
||||
diff --git a/src/libANGLE/validationES3.cpp b/src/libANGLE/validationES3.cpp
|
||||
index 6fd5489332361c50c160228b089ec6108303f363..8d2f294b3a766b1cc3fff1472726503a11df0bcb 100644
|
||||
--- a/src/libANGLE/validationES3.cpp
|
||||
+++ b/src/libANGLE/validationES3.cpp
|
||||
@@ -4287,6 +4287,13 @@ bool ValidateResumeTransformFeedback(const Context *context, angle::EntryPoint e
|
||||
return false;
|
||||
}
|
||||
|
||||
+ if (!ValidateProgramExecutableXFBBuffersPresent(context,
|
||||
+ context->getState().getProgramExecutable()))
|
||||
+ {
|
||||
+ context->validationError(entryPoint, GL_INVALID_OPERATION, kTransformFeedbackBufferMissing);
|
||||
+ return false;
|
||||
+ }
|
||||
+
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,60 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Jamie Madill <jmadill@chromium.org>
|
||||
Date: Mon, 14 Mar 2022 10:37:31 -0400
|
||||
Subject: Fix crash when pausing XFB then deleting a buffer.
|
||||
|
||||
Fix is to validate XFB buffer bindings even if we're paused.
|
||||
This is undefined behaviour so we can use any non-crashing solution.
|
||||
|
||||
Bug: chromium:1305190
|
||||
Change-Id: Ib95404cdb13adbde7f34d6cc77473a8b3cbf1de7
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/3522283
|
||||
Reviewed-by: Geoff Lang <geofflang@chromium.org>
|
||||
Commit-Queue: Jamie Madill <jmadill@chromium.org>
|
||||
(cherry picked from commit 708ce9cfd63bc8eab7c48987612a2dedce78c69a)
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/3594105
|
||||
Reviewed-by: Shahbaz Youssefi <syoussefi@chromium.org>
|
||||
|
||||
diff --git a/src/libANGLE/validationES.cpp b/src/libANGLE/validationES.cpp
|
||||
index e0281742d46d709f5f20a9d472256c5e475b627a..4cd36918f485f51cef2d6532a90bb8583b2861ab 100644
|
||||
--- a/src/libANGLE/validationES.cpp
|
||||
+++ b/src/libANGLE/validationES.cpp
|
||||
@@ -4087,7 +4087,7 @@ const char *ValidateDrawStates(const Context *context)
|
||||
}
|
||||
}
|
||||
|
||||
- if (state.isTransformFeedbackActiveUnpaused())
|
||||
+ if (state.isTransformFeedbackActive())
|
||||
{
|
||||
if (!ValidateProgramExecutableXFBBuffersPresent(context, executable))
|
||||
{
|
||||
diff --git a/src/tests/gl_tests/TransformFeedbackTest.cpp b/src/tests/gl_tests/TransformFeedbackTest.cpp
|
||||
index c93cd02406390471f24005b61c7cf3e4703700a9..d495f8bf7ffe917cc6722a05c92ac2fa71d0376b 100644
|
||||
--- a/src/tests/gl_tests/TransformFeedbackTest.cpp
|
||||
+++ b/src/tests/gl_tests/TransformFeedbackTest.cpp
|
||||
@@ -3902,6 +3902,25 @@ void main()
|
||||
EXPECT_GL_NO_ERROR();
|
||||
}
|
||||
|
||||
+// Same as the above, with a paused transform feedback.
|
||||
+TEST_P(TransformFeedbackTest, DeletePausedTransformFeedbackBuffer)
|
||||
+{
|
||||
+ ANGLE_GL_PROGRAM_TRANSFORM_FEEDBACK(testProgram, essl1_shaders::vs::Simple(),
|
||||
+ essl1_shaders::fs::Green(), {"gl_Position"},
|
||||
+ GL_INTERLEAVED_ATTRIBS);
|
||||
+ glUseProgram(testProgram);
|
||||
+
|
||||
+ GLBuffer buffer;
|
||||
+ glBindBuffer(GL_PIXEL_UNPACK_BUFFER, buffer);
|
||||
+ glBufferData(GL_PIXEL_UNPACK_BUFFER, 3, nullptr, GL_STATIC_DRAW);
|
||||
+ glBindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0, buffer);
|
||||
+
|
||||
+ glBeginTransformFeedback(GL_POINTS);
|
||||
+ glPauseTransformFeedback();
|
||||
+ buffer.reset();
|
||||
+ glDrawArrays(GL_POINTS, 0, 1);
|
||||
+}
|
||||
+
|
||||
GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(TransformFeedbackTest);
|
||||
ANGLE_INSTANTIATE_TEST_ES3(TransformFeedbackTest);
|
||||
|
||||
@@ -119,3 +119,30 @@ remove_incorrect_width_height_adjustments.patch
|
||||
set_dpi_correctly_during_main_window_creation.patch
|
||||
ui_gtk_public_header.patch
|
||||
introduce_ozoneplatform_electron_can_call_x11_property.patch
|
||||
revert_motionmark_avoid_unnecessary_ipc_on_mac.patch
|
||||
cherry-pick-a1dc371d6680.patch
|
||||
cherry-pick-1665a1d16d46.patch
|
||||
use-after-free_of_id_and_idref_attributes.patch
|
||||
fix_--without-valid_build.patch
|
||||
cherry-pick-4d26949260aa.patch
|
||||
skia_renderer_use_rectf_intersect_in_applyscissor.patch
|
||||
cherry-pick-1a31e2110440.patch
|
||||
cherry-pick-5cb934a23ddf.patch
|
||||
use_iserrordocument_to_prevent_bfcacheing_of_interstitials_and.patch
|
||||
cherry-pick-5ff02e4d7368.patch
|
||||
cherry-pick-5361d836aeb1.patch
|
||||
cherry-pick-5be8e065f43e.patch
|
||||
cherry-pick-12ba78f3fa7a.patch
|
||||
reland_fix_noopener_case_for_user_activation_consumption.patch
|
||||
fsa_pass_file_ownership_to_worker_for_async_fsarfd_file_operations.patch
|
||||
merge_to_m100_don_t_use_getoriginalopener_to_get_opener_s_origin_on.patch
|
||||
cherry-pick-ec0cce63f47d.patch
|
||||
cherry-pick-99c3f3bfd507.patch
|
||||
cherry-pick-f1504440487f.patch
|
||||
cherry-pick-21139756239b.patch
|
||||
cherry-pick-919b1ffe1fe7.patch
|
||||
cherry-pick-2782c7bc5bbe.patch
|
||||
cherry-pick-f1dd785e021e.patch
|
||||
cherry-pick-f3d01ff794dc.patch
|
||||
cherry-pick-b03797bdb1df.patch
|
||||
posix_replace_doubleforkandexec_with_forkandspawn.patch
|
||||
|
||||
89
patches/chromium/cherry-pick-12ba78f3fa7a.patch
Normal file
89
patches/chromium/cherry-pick-12ba78f3fa7a.patch
Normal file
@@ -0,0 +1,89 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Xiaocheng Hu <xiaochengh@chromium.org>
|
||||
Date: Mon, 25 Apr 2022 20:57:43 +0000
|
||||
Subject: Sanitize DragData markup before inserting it into document
|
||||
|
||||
(cherry picked from commit 5164a0fe3391283663e1196cf4576ec233985e89)
|
||||
|
||||
Fixed: 1315040
|
||||
Change-Id: I8a0ddfb983d12c185f7e943d3d5277788199b011
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3579670
|
||||
Quick-Run: Xiaocheng Hu <xiaochengh@chromium.org>
|
||||
Auto-Submit: Xiaocheng Hu <xiaochengh@chromium.org>
|
||||
Commit-Queue: Kent Tamura <tkent@chromium.org>
|
||||
Cr-Original-Commit-Position: refs/heads/main@{#991324}
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3589799
|
||||
Reviewed-by: Achuith Bhandarkar <achuith@chromium.org>
|
||||
Owners-Override: Achuith Bhandarkar <achuith@chromium.org>
|
||||
Commit-Queue: Roger Felipe Zanoni da Silva <rzanoni@google.com>
|
||||
Cr-Commit-Position: refs/branch-heads/4664@{#1602}
|
||||
Cr-Branched-From: 24dc4ee75e01a29d390d43c9c264372a169273a7-refs/heads/main@{#929512}
|
||||
|
||||
diff --git a/third_party/blink/renderer/core/page/drag_data.cc b/third_party/blink/renderer/core/page/drag_data.cc
|
||||
index 2ce56b1fefe016ac34a1a3011a595fab342abfa5..4fb86bc645386ee806544ee3647b0a333cd8afc4 100644
|
||||
--- a/third_party/blink/renderer/core/page/drag_data.cc
|
||||
+++ b/third_party/blink/renderer/core/page/drag_data.cc
|
||||
@@ -131,8 +131,8 @@ DocumentFragment* DragData::AsFragment(LocalFrame* frame) const {
|
||||
platform_drag_data_->HtmlAndBaseURL(html, base_url);
|
||||
DCHECK(frame->GetDocument());
|
||||
if (DocumentFragment* fragment =
|
||||
- CreateFragmentFromMarkup(*frame->GetDocument(), html, base_url,
|
||||
- kDisallowScriptingAndPluginContent))
|
||||
+ CreateSanitizedFragmentFromMarkupWithContext(
|
||||
+ *frame->GetDocument(), html, 0, html.length(), base_url))
|
||||
return fragment;
|
||||
}
|
||||
|
||||
diff --git a/third_party/blink/web_tests/editing/pasteboard/drag-and-drop-svg-use-sanitize.html b/third_party/blink/web_tests/editing/pasteboard/drag-and-drop-svg-use-sanitize.html
|
||||
new file mode 100644
|
||||
index 0000000000000000000000000000000000000000..58551d28341d851dbd99322e2a5d3af68b3b0c72
|
||||
--- /dev/null
|
||||
+++ b/third_party/blink/web_tests/editing/pasteboard/drag-and-drop-svg-use-sanitize.html
|
||||
@@ -0,0 +1,47 @@
|
||||
+<!doctype html>
|
||||
+<script src="../../resources/testharness.js"></script>
|
||||
+<script src="../../resources/testharnessreport.js"></script>
|
||||
+
|
||||
+<div id="drag-from" draggable=true>Drag from</div>
|
||||
+<div id="drag-to" contenteditable>Drag to</div>
|
||||
+
|
||||
+<script>
|
||||
+function computePoint(element) {
|
||||
+ return {
|
||||
+ x: element.offsetLeft + element.offsetWidth / 2,
|
||||
+ y: element.offsetTop + element.offsetHeight / 2
|
||||
+ };
|
||||
+}
|
||||
+
|
||||
+let dragged = false;
|
||||
+let executed = false;
|
||||
+const payload = `
|
||||
+ <svg><use href="data:image/svg+xml,<svg id='x' xmlns='http://www.w3.org/2000/svg'><image href='fake' onerror='executed=true' /></svg>#x" />
|
||||
+`;
|
||||
+
|
||||
+const dragFrom = document.getElementById('drag-from');
|
||||
+dragFrom.ondragstart = event => {
|
||||
+ dragged = true;
|
||||
+ event.dataTransfer.setData('text/html', payload);
|
||||
+}
|
||||
+
|
||||
+const dragTo = document.getElementById('drag-to');
|
||||
+
|
||||
+promise_test(async test => {
|
||||
+ assert_own_property(window, 'eventSender', 'This test requires eventSender to simulate drag and drop');
|
||||
+
|
||||
+ const fromPoint = computePoint(dragFrom);
|
||||
+ eventSender.mouseMoveTo(fromPoint.x, fromPoint.y);
|
||||
+ eventSender.mouseDown();
|
||||
+
|
||||
+ const toPoint = computePoint(dragTo);
|
||||
+ eventSender.mouseMoveTo(toPoint.x, toPoint.y);
|
||||
+ eventSender.mouseUp();
|
||||
+
|
||||
+ assert_true(dragged, 'Element should be dragged');
|
||||
+
|
||||
+ // The 'error' event is dispatched asynchronously.
|
||||
+ await new Promise(resolve => test.step_timeout(resolve, 100));
|
||||
+ assert_false(executed, 'Script should be blocked');
|
||||
+}, 'Script in SVG use href should be sanitized');
|
||||
+</script>
|
||||
118
patches/chromium/cherry-pick-1665a1d16d46.patch
Normal file
118
patches/chromium/cherry-pick-1665a1d16d46.patch
Normal file
@@ -0,0 +1,118 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: "msw@chromium.org" <msw@chromium.org>
|
||||
Date: Tue, 1 Feb 2022 21:16:10 +0000
|
||||
Subject: Reland "Make web cursor size limits match on browser and renderer"
|
||||
|
||||
This reverts commit 38a8343085e53889eba48fcff78a6c2295927333.
|
||||
|
||||
Reason for revert: Fix without regressing https://crbug.com/1292426
|
||||
(Increased WebCursor limit 128->150px to support DevToolsEyeDropper)
|
||||
|
||||
Original change's description:
|
||||
> Revert "Make web cursor size limits match on browser and renderer"
|
||||
>
|
||||
> This reverts commit 868b44dd8b4a1a3b9698f561ca17f75e4ec78dd2.
|
||||
>
|
||||
> Reason for revert: https://crbug.com/1292426
|
||||
>
|
||||
> Original change's description:
|
||||
> > Make web cursor size limits match on browser and renderer
|
||||
> >
|
||||
> > Use NSCursor arrowCursor on Mac for ui::mojom::CursorType::kNull.
|
||||
> > (i.e. when WebCursor is constructed with an overly large custom cursor)
|
||||
> >
|
||||
> > Bug: 1246188
|
||||
> > Test: Automated unit tests and WPTs
|
||||
> > Change-Id: I89627fa13cba96b755b8f80adbc91cfc865b6b1b
|
||||
> > Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3413912
|
||||
> > Reviewed-by: Henrique Ferreiro <hferreiro@igalia.com>
|
||||
> > Reviewed-by: Charlie Harrison <csharrison@chromium.org>
|
||||
> > Commit-Queue: Mike Wasserman <msw@chromium.org>
|
||||
> > Auto-Submit: Mike Wasserman <msw@chromium.org>
|
||||
> > Cr-Commit-Position: refs/heads/main@{#964378}
|
||||
>
|
||||
> Bug: 1246188
|
||||
> Change-Id: Id7b3b88e65c012993537ce96c2b5064b7b76646e
|
||||
> Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3428347
|
||||
> Bot-Commit: Rubber Stamper <rubber-stamper@appspot.gserviceaccount.com>
|
||||
> Commit-Queue: Mike Wasserman <msw@chromium.org>
|
||||
> Cr-Commit-Position: refs/heads/main@{#965475}
|
||||
|
||||
Fixed: 1246188
|
||||
Bug: 1292426
|
||||
Change-Id: I5a490603c3e21e17f3136a3d792a18429eb3f633
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3428624
|
||||
Auto-Submit: Mike Wasserman <msw@chromium.org>
|
||||
Reviewed-by: Charlie Harrison <csharrison@chromium.org>
|
||||
Commit-Queue: Mike Wasserman <msw@chromium.org>
|
||||
Reviewed-by: Henrique Ferreiro <hferreiro@igalia.com>
|
||||
Cr-Commit-Position: refs/heads/main@{#965857}
|
||||
|
||||
diff --git a/content/common/cursors/webcursor.cc b/content/common/cursors/webcursor.cc
|
||||
index c8b6b9d3f75d0cac98cc4ab8e71b68117837c1dc..4c80616e41e6ba5b171ae09d06d7f4110589f70a 100644
|
||||
--- a/content/common/cursors/webcursor.cc
|
||||
+++ b/content/common/cursors/webcursor.cc
|
||||
@@ -22,16 +22,19 @@ WebCursor::WebCursor(const ui::Cursor& cursor) {
|
||||
WebCursor::WebCursor(const WebCursor& other) = default;
|
||||
|
||||
bool WebCursor::SetCursor(const ui::Cursor& cursor) {
|
||||
- static constexpr int kMaxSize = 1024;
|
||||
+ // This value is just large enough to accommodate:
|
||||
+ // - kMaximumCursorSize in Blink's EventHandler
|
||||
+ // - kCursorSize in Chrome's DevToolsEyeDropper
|
||||
+ static constexpr int kMaximumCursorSize = 150;
|
||||
if (cursor.image_scale_factor() < 0.01f ||
|
||||
cursor.image_scale_factor() > 100.f ||
|
||||
(cursor.type() == ui::mojom::CursorType::kCustom &&
|
||||
- (cursor.custom_bitmap().width() > kMaxSize ||
|
||||
- cursor.custom_bitmap().height() > kMaxSize ||
|
||||
+ (cursor.custom_bitmap().width() > kMaximumCursorSize ||
|
||||
+ cursor.custom_bitmap().height() > kMaximumCursorSize ||
|
||||
cursor.custom_bitmap().width() / cursor.image_scale_factor() >
|
||||
- kMaxSize ||
|
||||
+ kMaximumCursorSize ||
|
||||
cursor.custom_bitmap().height() / cursor.image_scale_factor() >
|
||||
- kMaxSize))) {
|
||||
+ kMaximumCursorSize))) {
|
||||
return false;
|
||||
}
|
||||
|
||||
diff --git a/content/common/cursors/webcursor_mac.mm b/content/common/cursors/webcursor_mac.mm
|
||||
index f85c421f8581abe191738eaee133004b729a817d..fdc70bdff2ddc517f3e341dd16263ae89d8b153f 100644
|
||||
--- a/content/common/cursors/webcursor_mac.mm
|
||||
+++ b/content/common/cursors/webcursor_mac.mm
|
||||
@@ -265,6 +265,7 @@ - (CrCoreCursorType)_coreCursorType {
|
||||
case ui::mojom::CursorType::kCustom:
|
||||
return CreateCustomCursor(cursor_);
|
||||
case ui::mojom::CursorType::kNull:
|
||||
+ return [NSCursor arrowCursor];
|
||||
case ui::mojom::CursorType::kDndNone:
|
||||
case ui::mojom::CursorType::kDndMove:
|
||||
case ui::mojom::CursorType::kDndCopy:
|
||||
diff --git a/content/common/cursors/webcursor_unittest.cc b/content/common/cursors/webcursor_unittest.cc
|
||||
index 8f53ffa052f1f60d4eedccca5a4bc32941966963..9b2d8dec85e73b73108f40bca90237b4465e5043 100644
|
||||
--- a/content/common/cursors/webcursor_unittest.cc
|
||||
+++ b/content/common/cursors/webcursor_unittest.cc
|
||||
@@ -122,11 +122,11 @@ TEST(WebCursorTest, SetCursor) {
|
||||
|
||||
// SetCursor should return false when the image width is too large.
|
||||
cursor.set_image_scale_factor(1.f);
|
||||
- cursor.set_custom_bitmap(CreateTestBitmap(1025, 3));
|
||||
+ cursor.set_custom_bitmap(CreateTestBitmap(151, 3));
|
||||
EXPECT_FALSE(webcursor.SetCursor(cursor));
|
||||
|
||||
// SetCursor should return false when the image height is too large.
|
||||
- cursor.set_custom_bitmap(CreateTestBitmap(3, 1025));
|
||||
+ cursor.set_custom_bitmap(CreateTestBitmap(3, 151));
|
||||
EXPECT_FALSE(webcursor.SetCursor(cursor));
|
||||
|
||||
// SetCursor should return false when the scaled image width is too large.
|
||||
@@ -136,7 +136,7 @@ TEST(WebCursorTest, SetCursor) {
|
||||
|
||||
// SetCursor should return false when the scaled image height is too large.
|
||||
cursor.set_image_scale_factor(0.1f);
|
||||
- cursor.set_custom_bitmap(CreateTestBitmap(5, 200));
|
||||
+ cursor.set_custom_bitmap(CreateTestBitmap(5, 20));
|
||||
EXPECT_FALSE(webcursor.SetCursor(cursor));
|
||||
}
|
||||
|
||||
62
patches/chromium/cherry-pick-1a31e2110440.patch
Normal file
62
patches/chromium/cherry-pick-1a31e2110440.patch
Normal file
@@ -0,0 +1,62 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Anders Hartvoll Ruud <andruud@chromium.org>
|
||||
Date: Tue, 5 Apr 2022 20:44:33 +0000
|
||||
Subject: Disallow CSS-wide keywords for StylePropertyMap.set
|
||||
|
||||
We don't support this properly, and the spec does not handle CSS-keywords
|
||||
either. Disallow it until we can add proper support for this.
|
||||
|
||||
(cherry picked from commit 02e4b18febb37de8baea718bc2f62cfb5fe56e23)
|
||||
|
||||
Fixed: 1292905
|
||||
Bug: 1310761
|
||||
Change-Id: Ieb3d20edfea72c2ccb0928536fdfd86d10aad1a9
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3551609
|
||||
Reviewed-by: Rune Lillesveen <futhark@chromium.org>
|
||||
Commit-Queue: Anders Hartvoll Ruud <andruud@chromium.org>
|
||||
Cr-Original-Commit-Position: refs/heads/main@{#986411}
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3572186
|
||||
Commit-Queue: Srinivas Sista <srinivassista@chromium.org>
|
||||
Auto-Submit: Srinivas Sista <srinivassista@chromium.org>
|
||||
Commit-Queue: Rune Lillesveen <futhark@chromium.org>
|
||||
Cr-Commit-Position: refs/branch-heads/4896@{#1041}
|
||||
Cr-Branched-From: 1f63ff4bc27570761b35ffbc7f938f6586f7bee8-refs/heads/main@{#972766}
|
||||
|
||||
diff --git a/third_party/blink/renderer/build/scripts/core/css/templates/cssom_keywords.cc.tmpl b/third_party/blink/renderer/build/scripts/core/css/templates/cssom_keywords.cc.tmpl
|
||||
index 925272d4967a33043cc3a53bd7de448ab03ca805..75597baf3aae8e9a1981153353202fb3e35b7850 100644
|
||||
--- a/third_party/blink/renderer/build/scripts/core/css/templates/cssom_keywords.cc.tmpl
|
||||
+++ b/third_party/blink/renderer/build/scripts/core/css/templates/cssom_keywords.cc.tmpl
|
||||
@@ -20,8 +20,10 @@ bool CSSOMKeywords::ValidKeywordForProperty(CSSPropertyID id,
|
||||
return false;
|
||||
}
|
||||
|
||||
- if (css_parsing_utils::IsCSSWideKeyword(valueID))
|
||||
- return true;
|
||||
+ if (css_parsing_utils::IsCSSWideKeyword(valueID)) {
|
||||
+ // TODO(crbug.com/1310761): Support CSS-wide keywords in custom props.
|
||||
+ return id != CSSPropertyID::kVariable;
|
||||
+ }
|
||||
|
||||
switch (id) {
|
||||
{% for property in properties if property.keywordIDs and 'Keyword' in property.typedom_types %}
|
||||
diff --git a/third_party/blink/web_tests/external/wpt/css/css-typed-om/set-css-wide-in-custom-property-crash.html b/third_party/blink/web_tests/external/wpt/css/css-typed-om/set-css-wide-in-custom-property-crash.html
|
||||
new file mode 100644
|
||||
index 0000000000000000000000000000000000000000..bc977c9889889bd8a35eccc48ac28e25871b1ec9
|
||||
--- /dev/null
|
||||
+++ b/third_party/blink/web_tests/external/wpt/css/css-typed-om/set-css-wide-in-custom-property-crash.html
|
||||
@@ -0,0 +1,15 @@
|
||||
+<!DOCTYPE html>
|
||||
+<title>Don't crash when setting a CSS-wide keyword on a custom property</title>
|
||||
+<link rel="help" href="https://drafts.css-houdini.org/css-typed-om-1/#dom-stylepropertymap-set">
|
||||
+<link rel="help" href="https://crbug.com/1310761<">
|
||||
+<div id="target">
|
||||
+ Don't crash
|
||||
+</div>
|
||||
+<script>
|
||||
+ for (let keyword of ['initial', 'inherit', 'unset', 'revert', 'revert-layer']) {
|
||||
+ try {
|
||||
+ target.attributeStyleMap.set('--x', new CSSKeywordValue(keyword));
|
||||
+ } catch (e) {
|
||||
+ }
|
||||
+ }
|
||||
+</script>
|
||||
114
patches/chromium/cherry-pick-21139756239b.patch
Normal file
114
patches/chromium/cherry-pick-21139756239b.patch
Normal file
@@ -0,0 +1,114 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Ari Chivukula <arichiv@chromium.org>
|
||||
Date: Tue, 17 May 2022 18:17:07 +0000
|
||||
Subject: {M102 PICK} [IndexedDB] Use-After-Free Fix
|
||||
|
||||
We can't guarantee order in the task the constructor dispatches the same
|
||||
way we could before due to all the async changes. Let's be sure all the
|
||||
objects exist before using them now. Long term, we need to address
|
||||
ownership of the idb context.
|
||||
|
||||
Bug: 1324864, 1218100
|
||||
Change-Id: Id5753297a4c966432028a1e7e063c5f1bed6f619
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3646994
|
||||
Reviewed-by: Ayu Ishii <ayui@chromium.org>
|
||||
Commit-Queue: Srinivas Sista <srinivassista@chromium.org>
|
||||
Cr-Commit-Position: refs/branch-heads/5005@{#812}
|
||||
Cr-Branched-From: 5b4d9450fee01f821b6400e947b3839727643a71-refs/heads/main@{#992738}
|
||||
|
||||
diff --git a/content/browser/indexed_db/indexed_db_context_impl.cc b/content/browser/indexed_db/indexed_db_context_impl.cc
|
||||
index 6a7d303385aaf9bd8e0581c580ab328096ef5950..3afb1edf4cdc0baef105b680ec82007c66b40940 100644
|
||||
--- a/content/browser/indexed_db/indexed_db_context_impl.cc
|
||||
+++ b/content/browser/indexed_db/indexed_db_context_impl.cc
|
||||
@@ -167,38 +167,32 @@ IndexedDBContextImpl::IndexedDBContextImpl(
|
||||
std::move(quota_client_remote),
|
||||
storage::QuotaClientType::kIndexedDatabase,
|
||||
{blink::mojom::StorageType::kTemporary});
|
||||
+ IDBTaskRunner()->PostTask(
|
||||
+ FROM_HERE, base::BindOnce(&IndexedDBContextImpl::BindPipesOnIDBSequence,
|
||||
+ weak_factory_.GetWeakPtr(),
|
||||
+ std::move(quota_client_receiver),
|
||||
+ std::move(blob_storage_context),
|
||||
+ std::move(file_system_access_context)));
|
||||
+}
|
||||
|
||||
- // This is safe because the IndexedDBContextImpl must be destructed on the
|
||||
- // IDBTaskRunner, and this task will always happen before that.
|
||||
- idb_task_runner_->PostTask(
|
||||
- FROM_HERE,
|
||||
- base::BindOnce(
|
||||
- [](mojo::Remote<storage::mojom::BlobStorageContext>*
|
||||
- blob_storage_context,
|
||||
- mojo::Remote<storage::mojom::FileSystemAccessContext>*
|
||||
- file_system_access_context,
|
||||
- mojo::Receiver<storage::mojom::QuotaClient>* quota_client_receiver,
|
||||
- mojo::PendingRemote<storage::mojom::BlobStorageContext>
|
||||
- pending_blob_storage_context,
|
||||
- mojo::PendingRemote<storage::mojom::FileSystemAccessContext>
|
||||
- pending_file_system_access_context,
|
||||
- mojo::PendingReceiver<storage::mojom::QuotaClient>
|
||||
- quota_client_pending_receiver) {
|
||||
- quota_client_receiver->Bind(
|
||||
- std::move(quota_client_pending_receiver));
|
||||
- if (pending_blob_storage_context) {
|
||||
- blob_storage_context->Bind(
|
||||
- std::move(pending_blob_storage_context));
|
||||
- }
|
||||
- if (pending_file_system_access_context) {
|
||||
- file_system_access_context->Bind(
|
||||
- std::move(pending_file_system_access_context));
|
||||
- }
|
||||
- },
|
||||
- &blob_storage_context_, &file_system_access_context_,
|
||||
- "a_client_receiver_, std::move(blob_storage_context),
|
||||
- std::move(file_system_access_context),
|
||||
- std::move(quota_client_receiver)));
|
||||
+void IndexedDBContextImpl::BindPipesOnIDBSequence(
|
||||
+ mojo::PendingReceiver<storage::mojom::QuotaClient>
|
||||
+ pending_quota_client_receiver,
|
||||
+ mojo::PendingRemote<storage::mojom::BlobStorageContext>
|
||||
+ pending_blob_storage_context,
|
||||
+ mojo::PendingRemote<storage::mojom::FileSystemAccessContext>
|
||||
+ pending_file_system_access_context) {
|
||||
+ DCHECK(IDBTaskRunner()->RunsTasksInCurrentSequence());
|
||||
+ if (pending_quota_client_receiver) {
|
||||
+ quota_client_receiver_.Bind(std::move(pending_quota_client_receiver));
|
||||
+ }
|
||||
+ if (pending_blob_storage_context) {
|
||||
+ blob_storage_context_.Bind(std::move(pending_blob_storage_context));
|
||||
+ }
|
||||
+ if (pending_file_system_access_context) {
|
||||
+ file_system_access_context_.Bind(
|
||||
+ std::move(pending_file_system_access_context));
|
||||
+ }
|
||||
}
|
||||
|
||||
void IndexedDBContextImpl::Bind(
|
||||
diff --git a/content/browser/indexed_db/indexed_db_context_impl.h b/content/browser/indexed_db/indexed_db_context_impl.h
|
||||
index 4b874b244778d831e0fa8ca3bbfd7e751897923e..ad2f984e130ece867c0f0dc7ca9ae52b8ec12ae9 100644
|
||||
--- a/content/browser/indexed_db/indexed_db_context_impl.h
|
||||
+++ b/content/browser/indexed_db/indexed_db_context_impl.h
|
||||
@@ -224,6 +224,14 @@ class CONTENT_EXPORT IndexedDBContextImpl
|
||||
|
||||
~IndexedDBContextImpl() override;
|
||||
|
||||
+ void BindPipesOnIDBSequence(
|
||||
+ mojo::PendingReceiver<storage::mojom::QuotaClient>
|
||||
+ pending_quota_client_receiver,
|
||||
+ mojo::PendingRemote<storage::mojom::BlobStorageContext>
|
||||
+ pending_blob_storage_context,
|
||||
+ mojo::PendingRemote<storage::mojom::FileSystemAccessContext>
|
||||
+ pending_file_system_access_context);
|
||||
+
|
||||
// Binds receiver on bucket retrieval to ensure that a bucket always exists
|
||||
// for a storage key.
|
||||
void BindIndexedDBWithBucket(
|
||||
@@ -282,6 +290,8 @@ class CONTENT_EXPORT IndexedDBContextImpl
|
||||
mojo::Receiver<storage::mojom::QuotaClient> quota_client_receiver_;
|
||||
const std::unique_ptr<storage::FilesystemProxy> filesystem_proxy_;
|
||||
|
||||
+ // weak_factory_->GetWeakPtr() may be used on any thread, but the resulting
|
||||
+ // pointer must only be checked/used on idb_task_runner_.
|
||||
base::WeakPtrFactory<IndexedDBContextImpl> weak_factory_{this};
|
||||
};
|
||||
|
||||
139
patches/chromium/cherry-pick-2782c7bc5bbe.patch
Normal file
139
patches/chromium/cherry-pick-2782c7bc5bbe.patch
Normal file
@@ -0,0 +1,139 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Marijn Kruisselbrink <mek@chromium.org>
|
||||
Date: Wed, 27 Apr 2022 20:51:50 +0000
|
||||
Subject: Reland "Close a MessagePort if it is created in a destroyed context."
|
||||
|
||||
This is a reland of commit 068f13cc5aa5f7a6e9faf28d8731275e64cb657b
|
||||
|
||||
This reland changes the timeout in the test from 3 to 2 seconds, because
|
||||
two 3 second timeouts is too long for chrome's default overall test
|
||||
timeout of 6 seconds on non-dcheck release builds.
|
||||
|
||||
Original change's description:
|
||||
> Close a MessagePort if it is created in a destroyed context.
|
||||
>
|
||||
> MessagePort assumes it is only destroyed either after ContextDestroyed,
|
||||
> or after the port has been closed explicitly. As it turns out ports that
|
||||
> were created in an already detached iframe would violate this invariant,
|
||||
> causing issues.
|
||||
>
|
||||
> Bug: 1228661
|
||||
> Change-Id: Ib1abce15f1d1d15f044de19fe0534767db488af0
|
||||
> Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3561845
|
||||
> Reviewed-by: Jeremy Roman <jbroman@chromium.org>
|
||||
> Commit-Queue: Marijn Kruisselbrink <mek@chromium.org>
|
||||
> Cr-Commit-Position: refs/heads/main@{#988859}
|
||||
|
||||
Bug: 1228661
|
||||
Change-Id: Ifc5ec866678667b0d81438e2a2c8e5ada6e19d8c
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3609249
|
||||
Commit-Queue: Jeremy Roman <jbroman@chromium.org>
|
||||
Reviewed-by: Jeremy Roman <jbroman@chromium.org>
|
||||
Auto-Submit: Marijn Kruisselbrink <mek@chromium.org>
|
||||
Cr-Commit-Position: refs/heads/main@{#996880}
|
||||
|
||||
diff --git a/third_party/blink/renderer/core/messaging/message_port.cc b/third_party/blink/renderer/core/messaging/message_port.cc
|
||||
index 6f67b21803fcdc2498ef207878d1541e04822fca..7f3df8ea567f91cd063122aab63a5c5424ab7919 100644
|
||||
--- a/third_party/blink/renderer/core/messaging/message_port.cc
|
||||
+++ b/third_party/blink/renderer/core/messaging/message_port.cc
|
||||
@@ -55,7 +55,11 @@
|
||||
namespace blink {
|
||||
|
||||
MessagePort::MessagePort(ExecutionContext& execution_context)
|
||||
- : ExecutionContextLifecycleObserver(&execution_context),
|
||||
+ : ExecutionContextLifecycleObserver(execution_context.IsContextDestroyed()
|
||||
+ ? nullptr
|
||||
+ : &execution_context),
|
||||
+ // Ports in a destroyed context start out in a closed state.
|
||||
+ closed_(execution_context.IsContextDestroyed()),
|
||||
task_runner_(execution_context.GetTaskRunner(TaskType::kPostedMessage)) {}
|
||||
|
||||
MessagePort::~MessagePort() {
|
||||
@@ -168,10 +172,21 @@ void MessagePort::Entangle(MessagePortDescriptor port) {
|
||||
DCHECK(port.IsValid());
|
||||
DCHECK(!connector_);
|
||||
|
||||
+ // If the context was already destroyed, there is no reason to actually
|
||||
+ // entangle the port and create a Connector. No messages will ever be able to
|
||||
+ // be sent or received anyway, as StartReceiving will never be called.
|
||||
+ if (!GetExecutionContext())
|
||||
+ return;
|
||||
+
|
||||
port_ = std::move(port);
|
||||
connector_ = std::make_unique<mojo::Connector>(
|
||||
port_.TakeHandleToEntangle(GetExecutionContext()),
|
||||
mojo::Connector::SINGLE_THREADED_SEND);
|
||||
+ // The raw `this` is safe despite `this` being a garbage collected object
|
||||
+ // because we make sure that:
|
||||
+ // 1. This object will not be garbage collected while it is connected and
|
||||
+ // the execution context is not destroyed, and
|
||||
+ // 2. when the execution context is destroyed, the connector_ is reset.
|
||||
connector_->set_incoming_receiver(this);
|
||||
connector_->set_connection_error_handler(
|
||||
WTF::Bind(&MessagePort::close, WrapWeakPersistent(this)));
|
||||
diff --git a/third_party/blink/renderer/core/messaging/message_port.h b/third_party/blink/renderer/core/messaging/message_port.h
|
||||
index 83d7901d99ad01ba039ea1ffa3dbee2595fc31ff..f9baba3c6d13992508da48a13c97bb10c8ec56e0 100644
|
||||
--- a/third_party/blink/renderer/core/messaging/message_port.h
|
||||
+++ b/third_party/blink/renderer/core/messaging/message_port.h
|
||||
@@ -148,7 +148,7 @@ class CORE_EXPORT MessagePort : public EventTargetWithInlineData,
|
||||
std::unique_ptr<mojo::Connector> connector_;
|
||||
|
||||
bool started_ = false;
|
||||
- bool closed_ = false;
|
||||
+ bool closed_;
|
||||
|
||||
scoped_refptr<base::SingleThreadTaskRunner> task_runner_;
|
||||
|
||||
diff --git a/third_party/blink/web_tests/external/wpt/webmessaging/message-channels/detached-iframe.window.js b/third_party/blink/web_tests/external/wpt/webmessaging/message-channels/detached-iframe.window.js
|
||||
new file mode 100644
|
||||
index 0000000000000000000000000000000000000000..c1effaf141b7246320883e293b58dabbc3572123
|
||||
--- /dev/null
|
||||
+++ b/third_party/blink/web_tests/external/wpt/webmessaging/message-channels/detached-iframe.window.js
|
||||
@@ -0,0 +1,47 @@
|
||||
+// META: title=MessageChannel in a detached iframe test
|
||||
+// META: script=/service-workers/service-worker/resources/test-helpers.sub.js
|
||||
+// Pull in the with_iframe helper function from the service worker tests
|
||||
+
|
||||
+
|
||||
+const IframeAction = {
|
||||
+ REMOVE_BEFORE_CREATION: 'remove-before-creation',
|
||||
+ REMOVE_AFTER_CREATION: 'remove-after-creation',
|
||||
+};
|
||||
+
|
||||
+async function detached_frame_test(t, action) {
|
||||
+ const iframe = await with_iframe('about:blank');
|
||||
+ const iframe_MessageChannel = iframe.contentWindow.MessageChannel;
|
||||
+
|
||||
+ if (action === IframeAction.REMOVE_BEFORE_CREATION) {
|
||||
+ iframe.remove();
|
||||
+ }
|
||||
+
|
||||
+ (() => {
|
||||
+ const mc = new iframe_MessageChannel();
|
||||
+ mc.port1.postMessage("boo");
|
||||
+ mc.port2.onmessage = t.unreached_func("message event received");
|
||||
+ mc.port2.onmessageerror = t.unreached_func("message event received");
|
||||
+ })();
|
||||
+
|
||||
+ if (action === IframeAction.REMOVE_AFTER_CREATION) {
|
||||
+ iframe.remove();
|
||||
+ }
|
||||
+
|
||||
+ // TODO(https://github.com/web-platform-tests/wpt/issues/7899): Change to
|
||||
+ // some sort of cross-browser GC trigger.
|
||||
+ if (self.gc) self.gc();
|
||||
+
|
||||
+ // We are testing that neither of the above two events fire. We assume that a 2 second timeout
|
||||
+ // is good enough. We can't use any other API for an end condition because each MessagePort has
|
||||
+ // its own independent port message queue, which has no ordering guarantees relative to other
|
||||
+ // APIs.
|
||||
+ await new Promise(resolve => t.step_timeout(resolve, 2000));
|
||||
+}
|
||||
+
|
||||
+promise_test(async (t) => {
|
||||
+ return detached_frame_test(t, IframeAction.REMOVE_AFTER_CREATION);
|
||||
+}, 'MessageChannel created from a detached iframe should not send messages (remove after create)');
|
||||
+
|
||||
+promise_test(async (t) => {
|
||||
+ return detached_frame_test(t, IframeAction.REMOVE_BEFORE_CREATION);
|
||||
+}, 'MessageChannel created from a detached iframe should not send messages (remove before create)');
|
||||
154
patches/chromium/cherry-pick-4d26949260aa.patch
Normal file
154
patches/chromium/cherry-pick-4d26949260aa.patch
Normal file
@@ -0,0 +1,154 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Yutaka Hirano <yhirano@chromium.org>
|
||||
Date: Fri, 4 Feb 2022 10:16:05 +0000
|
||||
Subject: Don't interpret informational response body as HTTP/0.9 response
|
||||
|
||||
An informational (1xx) response with body can be interpreted as an
|
||||
informational response followed by an HTTP/0.9 response. It is confusing
|
||||
so let's stop doing that.
|
||||
|
||||
Bug: 1291482
|
||||
Change-Id: Ic3823838614330d761f11360a783859e5baa260e
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3428433
|
||||
Reviewed-by: Matt Menke <mmenke@chromium.org>
|
||||
Reviewed-by: Kenichi Ishibashi <bashi@chromium.org>
|
||||
Reviewed-by: Mike West <mkwst@chromium.org>
|
||||
Commit-Queue: Yutaka Hirano <yhirano@chromium.org>
|
||||
Cr-Commit-Position: refs/heads/main@{#967169}
|
||||
|
||||
diff --git a/net/http/http_stream_parser.cc b/net/http/http_stream_parser.cc
|
||||
index a5f7bb10a01abb00db5d4ae15104f305027145b2..aaa22ac7001420c4d9c44a76af5a58bfbdc7deda 100644
|
||||
--- a/net/http/http_stream_parser.cc
|
||||
+++ b/net/http/http_stream_parser.cc
|
||||
@@ -1014,15 +1014,23 @@ int HttpStreamParser::ParseResponseHeaders(int end_offset) {
|
||||
base::StringPiece(read_buf_->StartOfBuffer(), end_offset));
|
||||
if (!headers)
|
||||
return net::ERR_INVALID_HTTP_RESPONSE;
|
||||
+ has_seen_status_line_ = true;
|
||||
} else {
|
||||
// Enough data was read -- there is no status line, so this is HTTP/0.9, or
|
||||
// the server is broken / doesn't speak HTTP.
|
||||
|
||||
- // If the port is not the default for the scheme, assume it's not a real
|
||||
- // HTTP/0.9 response, and fail the request.
|
||||
+ if (has_seen_status_line_) {
|
||||
+ // If we saw a status line previously, the server can speak HTTP/1.x so it
|
||||
+ // is not reasonable to interpret the response as an HTTP/0.9 response.
|
||||
+ return ERR_INVALID_HTTP_RESPONSE;
|
||||
+ }
|
||||
+
|
||||
base::StringPiece scheme = request_->url.scheme_piece();
|
||||
if (url::DefaultPortForScheme(scheme.data(), scheme.length()) !=
|
||||
request_->url.EffectiveIntPort()) {
|
||||
+ // If the port is not the default for the scheme, assume it's not a real
|
||||
+ // HTTP/0.9 response, and fail the request.
|
||||
+
|
||||
// Allow Shoutcast responses over HTTP, as it's somewhat common and relies
|
||||
// on HTTP/0.9 on weird ports to work.
|
||||
// See
|
||||
diff --git a/net/http/http_stream_parser.h b/net/http/http_stream_parser.h
|
||||
index 508b5296d6ff93689facc16939be2c720f42bf48..0c0619bdcf49328d1b737e2c3485d5beff99d0d1 100644
|
||||
--- a/net/http/http_stream_parser.h
|
||||
+++ b/net/http/http_stream_parser.h
|
||||
@@ -275,6 +275,11 @@ class NET_EXPORT_PRIVATE HttpStreamParser {
|
||||
// True if reading a keep-alive response. False if not, or if don't yet know.
|
||||
bool response_is_keep_alive_;
|
||||
|
||||
+ // True if we've seen a response that has an HTTP status line. This is
|
||||
+ // persistent across multiple response parsing. If we see a status line
|
||||
+ // for a response, this will remain true forever.
|
||||
+ bool has_seen_status_line_ = false;
|
||||
+
|
||||
// Keep track of the number of response body bytes read so far.
|
||||
int64_t response_body_read_;
|
||||
|
||||
diff --git a/net/http/http_stream_parser_unittest.cc b/net/http/http_stream_parser_unittest.cc
|
||||
index 3a394e629874d8ffff6eec02609e6009571a6733..e25b78539dfec4b27e6ddf2052967cab91141770 100644
|
||||
--- a/net/http/http_stream_parser_unittest.cc
|
||||
+++ b/net/http/http_stream_parser_unittest.cc
|
||||
@@ -1399,6 +1399,25 @@ TEST(HttpStreamParser, Http09PortTests) {
|
||||
}
|
||||
}
|
||||
|
||||
+TEST(HttpStreamParser, ContinueWithBody) {
|
||||
+ const std::string kResponse =
|
||||
+ "HTTP/1.1 100 Continue\r\n\r\nhello\r\nworld\r\n";
|
||||
+
|
||||
+ SimpleGetRunner get_runner;
|
||||
+ get_runner.set_url(GURL("http://foo.com/"));
|
||||
+ get_runner.AddRead(kResponse);
|
||||
+ get_runner.SetupParserAndSendRequest();
|
||||
+
|
||||
+ get_runner.ReadHeadersExpectingError(OK);
|
||||
+ ASSERT_TRUE(get_runner.response_info()->headers);
|
||||
+ EXPECT_EQ("HTTP/1.1 100 Continue",
|
||||
+ get_runner.response_info()->headers->GetStatusLine());
|
||||
+
|
||||
+ // We ignore informational responses and start reading the next response in
|
||||
+ // the stream. This simulates the behavior.
|
||||
+ get_runner.ReadHeadersExpectingError(ERR_INVALID_HTTP_RESPONSE);
|
||||
+}
|
||||
+
|
||||
TEST(HttpStreamParser, NullFails) {
|
||||
const char kTestHeaders[] =
|
||||
"HTTP/1.1 200 OK\r\n"
|
||||
diff --git a/third_party/blink/web_tests/external/wpt/fetch/security/1xx-response.any-expected.txt b/third_party/blink/web_tests/external/wpt/fetch/security/1xx-response.any-expected.txt
|
||||
new file mode 100644
|
||||
index 0000000000000000000000000000000000000000..6ac068363a83816939013bbde88a7584aca4f307
|
||||
--- /dev/null
|
||||
+++ b/third_party/blink/web_tests/external/wpt/fetch/security/1xx-response.any-expected.txt
|
||||
@@ -0,0 +1,7 @@
|
||||
+This is a testharness.js-based test.
|
||||
+PASS Status(100) should be ignored.
|
||||
+FAIL Status(101) should be accepted, with removing body. promise_test: Unhandled rejection with value: object "TypeError: Failed to fetch"
|
||||
+PASS Status(103) should be ignored.
|
||||
+PASS Status(199) should be ignored.
|
||||
+Harness: the test ran to completion.
|
||||
+
|
||||
diff --git a/third_party/blink/web_tests/external/wpt/fetch/security/1xx-response.any.js b/third_party/blink/web_tests/external/wpt/fetch/security/1xx-response.any.js
|
||||
new file mode 100644
|
||||
index 0000000000000000000000000000000000000000..df4dafcd80b38af93b688dcb318cfaf1978a939f
|
||||
--- /dev/null
|
||||
+++ b/third_party/blink/web_tests/external/wpt/fetch/security/1xx-response.any.js
|
||||
@@ -0,0 +1,28 @@
|
||||
+promise_test(async (t) => {
|
||||
+ // The 100 response should be ignored, then the transaction ends, which
|
||||
+ // should lead to an error.
|
||||
+ await promise_rejects_js(
|
||||
+ t, TypeError, fetch('/common/text-plain.txt?pipe=status(100)'));
|
||||
+}, 'Status(100) should be ignored.');
|
||||
+
|
||||
+// This behavior is being discussed at https://github.com/whatwg/fetch/issues/1397.
|
||||
+promise_test(async (t) => {
|
||||
+ const res = await fetch('/common/text-plain.txt?pipe=status(101)');
|
||||
+ assert_equals(res.status, 101);
|
||||
+ const body = await res.text();
|
||||
+ assert_equals(body, '');
|
||||
+}, 'Status(101) should be accepted, with removing body.');
|
||||
+
|
||||
+promise_test(async (t) => {
|
||||
+ // The 103 response should be ignored, then the transaction ends, which
|
||||
+ // should lead to an error.
|
||||
+ await promise_rejects_js(
|
||||
+ t, TypeError, fetch('/common/text-plain.txt?pipe=status(103)'));
|
||||
+}, 'Status(103) should be ignored.');
|
||||
+
|
||||
+promise_test(async (t) => {
|
||||
+ // The 199 response should be ignored, then the transaction ends, which
|
||||
+ // should lead to an error.
|
||||
+ await promise_rejects_js(
|
||||
+ t, TypeError, fetch('/common/text-plain.txt?pipe=status(199)'));
|
||||
+}, 'Status(199) should be ignored.');
|
||||
diff --git a/third_party/blink/web_tests/external/wpt/fetch/security/1xx-response.any.worker-expected.txt b/third_party/blink/web_tests/external/wpt/fetch/security/1xx-response.any.worker-expected.txt
|
||||
new file mode 100644
|
||||
index 0000000000000000000000000000000000000000..6ac068363a83816939013bbde88a7584aca4f307
|
||||
--- /dev/null
|
||||
+++ b/third_party/blink/web_tests/external/wpt/fetch/security/1xx-response.any.worker-expected.txt
|
||||
@@ -0,0 +1,7 @@
|
||||
+This is a testharness.js-based test.
|
||||
+PASS Status(100) should be ignored.
|
||||
+FAIL Status(101) should be accepted, with removing body. promise_test: Unhandled rejection with value: object "TypeError: Failed to fetch"
|
||||
+PASS Status(103) should be ignored.
|
||||
+PASS Status(199) should be ignored.
|
||||
+Harness: the test ran to completion.
|
||||
+
|
||||
84
patches/chromium/cherry-pick-5361d836aeb1.patch
Normal file
84
patches/chromium/cherry-pick-5361d836aeb1.patch
Normal file
@@ -0,0 +1,84 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Austin Eng <enga@chromium.org>
|
||||
Date: Mon, 25 Apr 2022 21:01:40 +0000
|
||||
Subject: Add bounds check to WebGPUDecoderImpl::DoRequestDevice
|
||||
|
||||
(cherry picked from commit bee4701c99cbbbb25c0bd6c5c79a40f63f1b1e47)
|
||||
|
||||
Fixed: chromium:1314754
|
||||
Change-Id: Id23af9cc3df08cca3ce7d627e3761c9a65a2c802
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3580555
|
||||
Commit-Queue: Austin Eng <enga@chromium.org>
|
||||
Cr-Original-Commit-Position: refs/heads/main@{#991510}
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3589810
|
||||
Reviewed-by: Achuith Bhandarkar <achuith@chromium.org>
|
||||
Owners-Override: Achuith Bhandarkar <achuith@chromium.org>
|
||||
Commit-Queue: Roger Felipe Zanoni da Silva <rzanoni@google.com>
|
||||
Cr-Commit-Position: refs/branch-heads/4664@{#1603}
|
||||
Cr-Branched-From: 24dc4ee75e01a29d390d43c9c264372a169273a7-refs/heads/main@{#929512}
|
||||
|
||||
diff --git a/gpu/command_buffer/service/webgpu_decoder_impl.cc b/gpu/command_buffer/service/webgpu_decoder_impl.cc
|
||||
index 39f2652a69e3b0e7494c8de3dee5453c4d447941..6879bddb8354e3f57f1431f05f30801e267940f5 100644
|
||||
--- a/gpu/command_buffer/service/webgpu_decoder_impl.cc
|
||||
+++ b/gpu/command_buffer/service/webgpu_decoder_impl.cc
|
||||
@@ -423,11 +423,12 @@ class WebGPUDecoderImpl final : public WebGPUDecoder {
|
||||
|
||||
int32_t GetPreferredAdapterIndex(PowerPreference power_preference) const;
|
||||
|
||||
- void DoRequestDevice(DawnRequestDeviceSerial request_device_serial,
|
||||
- int32_t requested_adapter_index,
|
||||
- uint32_t device_id,
|
||||
- uint32_t device_generation,
|
||||
- const WGPUDeviceProperties& requested_device_properties);
|
||||
+ error::Error DoRequestDevice(
|
||||
+ DawnRequestDeviceSerial request_device_serial,
|
||||
+ int32_t requested_adapter_index,
|
||||
+ uint32_t device_id,
|
||||
+ uint32_t device_generation,
|
||||
+ const WGPUDeviceProperties& requested_device_properties);
|
||||
void OnRequestDeviceCallback(DawnRequestDeviceSerial request_device_serial,
|
||||
size_t requested_adapter_index,
|
||||
uint32_t device_id,
|
||||
@@ -582,16 +583,16 @@ ContextResult WebGPUDecoderImpl::Initialize() {
|
||||
return ContextResult::kSuccess;
|
||||
}
|
||||
|
||||
-void WebGPUDecoderImpl::DoRequestDevice(
|
||||
+error::Error WebGPUDecoderImpl::DoRequestDevice(
|
||||
DawnRequestDeviceSerial request_device_serial,
|
||||
int32_t requested_adapter_index,
|
||||
uint32_t device_id,
|
||||
uint32_t device_generation,
|
||||
const WGPUDeviceProperties& request_device_properties) {
|
||||
- DCHECK_LE(0, requested_adapter_index);
|
||||
-
|
||||
- DCHECK_LT(static_cast<size_t>(requested_adapter_index),
|
||||
- dawn_adapters_.size());
|
||||
+ if (requested_adapter_index < 0 ||
|
||||
+ static_cast<uint32_t>(requested_adapter_index) >= dawn_adapters_.size()) {
|
||||
+ return error::kOutOfBounds;
|
||||
+ }
|
||||
|
||||
dawn_native::DawnDeviceDescriptor device_descriptor;
|
||||
if (request_device_properties.textureCompressionBC) {
|
||||
@@ -666,6 +667,8 @@ void WebGPUDecoderImpl::DoRequestDevice(
|
||||
std::move(*callback).Run(status, wgpu_device, message);
|
||||
},
|
||||
new CallbackT(std::move(callback)));
|
||||
+
|
||||
+ return error::kNoError;
|
||||
}
|
||||
|
||||
void WebGPUDecoderImpl::OnRequestDeviceCallback(
|
||||
@@ -1083,9 +1086,8 @@ error::Error WebGPUDecoderImpl::HandleRequestDevice(
|
||||
}
|
||||
}
|
||||
|
||||
- DoRequestDevice(request_device_serial, adapter_service_id, device_id,
|
||||
- device_generation, device_properties);
|
||||
- return error::kNoError;
|
||||
+ return DoRequestDevice(request_device_serial, adapter_service_id, device_id,
|
||||
+ device_generation, device_properties);
|
||||
}
|
||||
|
||||
error::Error WebGPUDecoderImpl::HandleDawnCommands(
|
||||
36
patches/chromium/cherry-pick-5be8e065f43e.patch
Normal file
36
patches/chromium/cherry-pick-5be8e065f43e.patch
Normal file
@@ -0,0 +1,36 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Gregg Tavares <gman@chromium.org>
|
||||
Date: Fri, 29 Apr 2022 15:23:33 +0000
|
||||
Subject: Check for error when calling ComputeImageSizeInBytes
|
||||
|
||||
(cherry picked from commit f3244fe50ba6c64ab6a75f1370d8dd983927fae6)
|
||||
|
||||
Bug: chromium:1304987
|
||||
Change-Id: I8311231156fca3200ce74d79db59d910a1a0e33a
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3556686
|
||||
Commit-Queue: Gregg Tavares <gman@chromium.org>
|
||||
Cr-Original-Commit-Position: refs/heads/main@{#986304}
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3597078
|
||||
Owners-Override: Victor-Gabriel Savu <vsavu@google.com>
|
||||
Reviewed-by: Victor-Gabriel Savu <vsavu@google.com>
|
||||
Commit-Queue: Roger Felipe Zanoni da Silva <rzanoni@google.com>
|
||||
Cr-Commit-Position: refs/branch-heads/4664@{#1609}
|
||||
Cr-Branched-From: 24dc4ee75e01a29d390d43c9c264372a169273a7-refs/heads/main@{#929512}
|
||||
|
||||
diff --git a/third_party/blink/renderer/platform/graphics/gpu/webgl_image_conversion.cc b/third_party/blink/renderer/platform/graphics/gpu/webgl_image_conversion.cc
|
||||
index 76a005a168a0e40d1e53016e461e96353ca463c5..b63b7c15d42bcdafed0bcbaced8cc13894c67035 100644
|
||||
--- a/third_party/blink/renderer/platform/graphics/gpu/webgl_image_conversion.cc
|
||||
+++ b/third_party/blink/renderer/platform/graphics/gpu/webgl_image_conversion.cc
|
||||
@@ -3996,8 +3996,10 @@ bool WebGLImageConversion::ExtractTextureData(
|
||||
data.resize(width * height * bytes_per_pixel);
|
||||
|
||||
unsigned image_size_in_bytes, skip_size_in_bytes;
|
||||
- ComputeImageSizeInBytes(format, type, width, height, 1, unpack_params,
|
||||
- &image_size_in_bytes, nullptr, &skip_size_in_bytes);
|
||||
+ if (ComputeImageSizeInBytes(format, type, width, height, 1, unpack_params,
|
||||
+ &image_size_in_bytes, nullptr,
|
||||
+ &skip_size_in_bytes) != GL_NO_ERROR)
|
||||
+ return false;
|
||||
const uint8_t* src_data = static_cast<const uint8_t*>(pixels);
|
||||
if (skip_size_in_bytes) {
|
||||
src_data += skip_size_in_bytes;
|
||||
431
patches/chromium/cherry-pick-5cb934a23ddf.patch
Normal file
431
patches/chromium/cherry-pick-5cb934a23ddf.patch
Normal file
@@ -0,0 +1,431 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Marijn Kruisselbrink <mek@chromium.org>
|
||||
Date: Tue, 5 Apr 2022 20:09:23 +0000
|
||||
Subject: M100: Change ownership of BlobBytesProvider.
|
||||
|
||||
Rather than immediately passing ownership to a cross-thread
|
||||
SelfOwnedReceiver while retaining a raw pointer, instead maintain
|
||||
ownership in a unique_ptr as long as it is needed, only transferring
|
||||
ownership to a SelfOwnedReceiver when BlobData is done with the
|
||||
BlobBytesProvider.
|
||||
|
||||
Also clean-up/tighten down sequence checks for BlobBytesProvider a bit.
|
||||
|
||||
(cherry picked from commit 7222e9825fc02acc962e005c59885ee2f26df185)
|
||||
|
||||
Bug: 1285234
|
||||
Change-Id: I7273e886a0bab2ae489b680d786991c9e4ff1dbb
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3553304
|
||||
Reviewed-by: Austin Sullivan <asully@chromium.org>
|
||||
Commit-Queue: Marijn Kruisselbrink <mek@chromium.org>
|
||||
Cr-Original-Commit-Position: refs/heads/main@{#986111}
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3568972
|
||||
Auto-Submit: Marijn Kruisselbrink <mek@chromium.org>
|
||||
Bot-Commit: Rubber Stamper <rubber-stamper@appspot.gserviceaccount.com>
|
||||
Cr-Commit-Position: refs/branch-heads/4896@{#1040}
|
||||
Cr-Branched-From: 1f63ff4bc27570761b35ffbc7f938f6586f7bee8-refs/heads/main@{#972766}
|
||||
|
||||
diff --git a/third_party/blink/renderer/platform/blob/blob_bytes_provider.cc b/third_party/blink/renderer/platform/blob/blob_bytes_provider.cc
|
||||
index fd27f1280e1745103879ffa4df563c21f4c46afd..125acccdd268c134a0608b739b5036ce2c455f26 100644
|
||||
--- a/third_party/blink/renderer/platform/blob/blob_bytes_provider.cc
|
||||
+++ b/third_party/blink/renderer/platform/blob/blob_bytes_provider.cc
|
||||
@@ -32,13 +32,10 @@ class BlobBytesStreamer {
|
||||
|
||||
public:
|
||||
BlobBytesStreamer(Vector<scoped_refptr<RawData>> data,
|
||||
- mojo::ScopedDataPipeProducerHandle pipe,
|
||||
- scoped_refptr<base::SequencedTaskRunner> task_runner)
|
||||
+ mojo::ScopedDataPipeProducerHandle pipe)
|
||||
: data_(std::move(data)),
|
||||
pipe_(std::move(pipe)),
|
||||
- watcher_(FROM_HERE,
|
||||
- mojo::SimpleWatcher::ArmingPolicy::AUTOMATIC,
|
||||
- std::move(task_runner)) {
|
||||
+ watcher_(FROM_HERE, mojo::SimpleWatcher::ArmingPolicy::AUTOMATIC) {
|
||||
watcher_.Watch(pipe_.get(), MOJO_HANDLE_SIGNAL_WRITABLE,
|
||||
MOJO_WATCH_CONDITION_SATISFIED,
|
||||
WTF::BindRepeating(&BlobBytesStreamer::OnWritable,
|
||||
@@ -46,6 +43,8 @@ class BlobBytesStreamer {
|
||||
}
|
||||
|
||||
void OnWritable(MojoResult result, const mojo::HandleSignalsState& state) {
|
||||
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
|
||||
+
|
||||
if (result == MOJO_RESULT_CANCELLED ||
|
||||
result == MOJO_RESULT_FAILED_PRECONDITION) {
|
||||
delete this;
|
||||
@@ -85,15 +84,18 @@ class BlobBytesStreamer {
|
||||
|
||||
private:
|
||||
// The index of the item currently being written.
|
||||
- wtf_size_t current_item_ = 0;
|
||||
+ wtf_size_t current_item_ GUARDED_BY_CONTEXT(sequence_checker_) = 0;
|
||||
// The offset into the current item of the first byte not yet written to the
|
||||
// data pipe.
|
||||
- size_t current_item_offset_ = 0;
|
||||
+ size_t current_item_offset_ GUARDED_BY_CONTEXT(sequence_checker_) = 0;
|
||||
// The data being written.
|
||||
- Vector<scoped_refptr<RawData>> data_;
|
||||
+ Vector<scoped_refptr<RawData>> data_ GUARDED_BY_CONTEXT(sequence_checker_);
|
||||
+
|
||||
+ mojo::ScopedDataPipeProducerHandle pipe_
|
||||
+ GUARDED_BY_CONTEXT(sequence_checker_);
|
||||
+ mojo::SimpleWatcher watcher_ GUARDED_BY_CONTEXT(sequence_checker_);
|
||||
|
||||
- mojo::ScopedDataPipeProducerHandle pipe_;
|
||||
- mojo::SimpleWatcher watcher_;
|
||||
+ SEQUENCE_CHECKER(sequence_checker_);
|
||||
};
|
||||
|
||||
// This keeps the process alive while blobs are being transferred.
|
||||
@@ -119,31 +121,8 @@ void DecreaseChildProcessRefCount() {
|
||||
|
||||
constexpr size_t BlobBytesProvider::kMaxConsolidatedItemSizeInBytes;
|
||||
|
||||
-// static
|
||||
-BlobBytesProvider* BlobBytesProvider::CreateAndBind(
|
||||
- mojo::PendingReceiver<mojom::blink::BytesProvider> receiver) {
|
||||
- auto task_runner = base::ThreadPool::CreateSequencedTaskRunner(
|
||||
- {base::MayBlock(), base::TaskPriority::USER_VISIBLE});
|
||||
- auto provider = base::WrapUnique(new BlobBytesProvider(task_runner));
|
||||
- auto* result = provider.get();
|
||||
- // TODO(mek): Consider binding BytesProvider on the IPC thread instead, only
|
||||
- // using the MayBlock taskrunner for actual file operations.
|
||||
- PostCrossThreadTask(
|
||||
- *task_runner, FROM_HERE,
|
||||
- CrossThreadBindOnce(
|
||||
- [](std::unique_ptr<BlobBytesProvider> provider,
|
||||
- mojo::PendingReceiver<mojom::blink::BytesProvider> receiver) {
|
||||
- mojo::MakeSelfOwnedReceiver(std::move(provider),
|
||||
- std::move(receiver));
|
||||
- },
|
||||
- std::move(provider), std::move(receiver)));
|
||||
- return result;
|
||||
-}
|
||||
-
|
||||
-// static
|
||||
-std::unique_ptr<BlobBytesProvider> BlobBytesProvider::CreateForTesting(
|
||||
- scoped_refptr<base::SequencedTaskRunner> task_runner) {
|
||||
- return base::WrapUnique(new BlobBytesProvider(std::move(task_runner)));
|
||||
+BlobBytesProvider::BlobBytesProvider() {
|
||||
+ IncreaseChildProcessRefCount();
|
||||
}
|
||||
|
||||
BlobBytesProvider::~BlobBytesProvider() {
|
||||
@@ -151,6 +130,8 @@ BlobBytesProvider::~BlobBytesProvider() {
|
||||
}
|
||||
|
||||
void BlobBytesProvider::AppendData(scoped_refptr<RawData> data) {
|
||||
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
|
||||
+
|
||||
if (!data_.IsEmpty()) {
|
||||
uint64_t last_offset = offsets_.IsEmpty() ? 0 : offsets_.back();
|
||||
offsets_.push_back(last_offset + data_.back()->length());
|
||||
@@ -159,6 +140,8 @@ void BlobBytesProvider::AppendData(scoped_refptr<RawData> data) {
|
||||
}
|
||||
|
||||
void BlobBytesProvider::AppendData(base::span<const char> data) {
|
||||
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
|
||||
+
|
||||
if (data_.IsEmpty() ||
|
||||
data_.back()->length() + data.size() > kMaxConsolidatedItemSizeInBytes) {
|
||||
AppendData(RawData::Create());
|
||||
@@ -167,8 +150,32 @@ void BlobBytesProvider::AppendData(base::span<const char> data) {
|
||||
data.data(), base::checked_cast<wtf_size_t>(data.size()));
|
||||
}
|
||||
|
||||
+// static
|
||||
+void BlobBytesProvider::Bind(
|
||||
+ std::unique_ptr<BlobBytesProvider> provider,
|
||||
+ mojo::PendingReceiver<mojom::blink::BytesProvider> receiver) {
|
||||
+ DCHECK_CALLED_ON_VALID_SEQUENCE(provider->sequence_checker_);
|
||||
+ DETACH_FROM_SEQUENCE(provider->sequence_checker_);
|
||||
+
|
||||
+ auto task_runner = base::ThreadPool::CreateSequencedTaskRunner(
|
||||
+ {base::MayBlock(), base::TaskPriority::USER_VISIBLE});
|
||||
+ // TODO(mek): Consider binding BytesProvider on the IPC thread instead, only
|
||||
+ // using the MayBlock taskrunner for actual file operations.
|
||||
+ PostCrossThreadTask(
|
||||
+ *task_runner, FROM_HERE,
|
||||
+ CrossThreadBindOnce(
|
||||
+ [](std::unique_ptr<BlobBytesProvider> provider,
|
||||
+ mojo::PendingReceiver<mojom::blink::BytesProvider> receiver) {
|
||||
+ DCHECK_CALLED_ON_VALID_SEQUENCE(provider->sequence_checker_);
|
||||
+ mojo::MakeSelfOwnedReceiver(std::move(provider),
|
||||
+ std::move(receiver));
|
||||
+ },
|
||||
+ std::move(provider), std::move(receiver)));
|
||||
+}
|
||||
+
|
||||
void BlobBytesProvider::RequestAsReply(RequestAsReplyCallback callback) {
|
||||
- DCHECK(task_runner_->RunsTasksInCurrentSequence());
|
||||
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
|
||||
+
|
||||
// TODO(mek): Once better metrics are created we could experiment with ways
|
||||
// to reduce the number of copies of data that are made here.
|
||||
Vector<uint8_t> result;
|
||||
@@ -179,9 +186,10 @@ void BlobBytesProvider::RequestAsReply(RequestAsReplyCallback callback) {
|
||||
|
||||
void BlobBytesProvider::RequestAsStream(
|
||||
mojo::ScopedDataPipeProducerHandle pipe) {
|
||||
- DCHECK(task_runner_->RunsTasksInCurrentSequence());
|
||||
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
|
||||
+
|
||||
// BlobBytesStreamer will self delete when done.
|
||||
- new BlobBytesStreamer(std::move(data_), std::move(pipe), task_runner_);
|
||||
+ new BlobBytesStreamer(std::move(data_), std::move(pipe));
|
||||
}
|
||||
|
||||
void BlobBytesProvider::RequestAsFile(uint64_t source_offset,
|
||||
@@ -189,7 +197,7 @@ void BlobBytesProvider::RequestAsFile(uint64_t source_offset,
|
||||
base::File file,
|
||||
uint64_t file_offset,
|
||||
RequestAsFileCallback callback) {
|
||||
- DCHECK(task_runner_->RunsTasksInCurrentSequence());
|
||||
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
|
||||
|
||||
if (!file.IsValid()) {
|
||||
std::move(callback).Run(absl::nullopt);
|
||||
@@ -257,10 +265,4 @@ void BlobBytesProvider::RequestAsFile(uint64_t source_offset,
|
||||
std::move(callback).Run(info.last_modified);
|
||||
}
|
||||
|
||||
-BlobBytesProvider::BlobBytesProvider(
|
||||
- scoped_refptr<base::SequencedTaskRunner> task_runner)
|
||||
- : task_runner_(std::move(task_runner)) {
|
||||
- IncreaseChildProcessRefCount();
|
||||
-}
|
||||
-
|
||||
} // namespace blink
|
||||
diff --git a/third_party/blink/renderer/platform/blob/blob_bytes_provider.h b/third_party/blink/renderer/platform/blob/blob_bytes_provider.h
|
||||
index 94e0172b7d411c8442b3949e8c82590f0b331fea..662cc02ecec7346ef32c44452cab38878c323edb 100644
|
||||
--- a/third_party/blink/renderer/platform/blob/blob_bytes_provider.h
|
||||
+++ b/third_party/blink/renderer/platform/blob/blob_bytes_provider.h
|
||||
@@ -6,6 +6,7 @@
|
||||
#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_BLOB_BLOB_BYTES_PROVIDER_H_
|
||||
|
||||
#include "base/gtest_prod_util.h"
|
||||
+#include "base/sequence_checker.h"
|
||||
#include "base/task/sequenced_task_runner.h"
|
||||
#include "third_party/blink/public/mojom/blob/blob_registry.mojom-blink-forward.h"
|
||||
#include "third_party/blink/public/mojom/blob/data_element.mojom-blink.h"
|
||||
@@ -17,8 +18,8 @@ namespace blink {
|
||||
// making up a blob to the browser process, at the request of the blob service.
|
||||
//
|
||||
// Typical usage of this class creates and calls AppendData on one thread, and
|
||||
-// then transfers ownership of the class to a different thread where it will be
|
||||
-// bound to a mojo pipe, such that the various Request* methods are called on a
|
||||
+// then transfers ownership of the class to a different thread using the `Bind`
|
||||
+// method. This ensures that the various Request* methods are called on a
|
||||
// thread that is allowed to do File IO.
|
||||
class PLATFORM_EXPORT BlobBytesProvider : public mojom::blink::BytesProvider {
|
||||
public:
|
||||
@@ -26,19 +27,17 @@ class PLATFORM_EXPORT BlobBytesProvider : public mojom::blink::BytesProvider {
|
||||
// data appended to the same item.
|
||||
static constexpr size_t kMaxConsolidatedItemSizeInBytes = 15 * 1024;
|
||||
|
||||
- // Creates a new instance, and binds it on a new SequencedTaskRunner. The
|
||||
- // returned instance should only be considered valid as long as the request
|
||||
- // passed in to this method is still known to be valid.
|
||||
- static BlobBytesProvider* CreateAndBind(
|
||||
- mojo::PendingReceiver<mojom::blink::BytesProvider>);
|
||||
- static std::unique_ptr<BlobBytesProvider> CreateForTesting(
|
||||
- scoped_refptr<base::SequencedTaskRunner>);
|
||||
-
|
||||
+ BlobBytesProvider();
|
||||
~BlobBytesProvider() override;
|
||||
|
||||
void AppendData(scoped_refptr<RawData>);
|
||||
void AppendData(base::span<const char>);
|
||||
|
||||
+ // Binds `provider` to `receiver` on a threadpool task runner, transferring
|
||||
+ // ownership.
|
||||
+ static void Bind(std::unique_ptr<BlobBytesProvider> provider,
|
||||
+ mojo::PendingReceiver<mojom::blink::BytesProvider> receiver);
|
||||
+
|
||||
// BytesProvider implementation:
|
||||
void RequestAsReply(RequestAsReplyCallback) override;
|
||||
void RequestAsStream(mojo::ScopedDataPipeProducerHandle) override;
|
||||
@@ -51,17 +50,13 @@ class PLATFORM_EXPORT BlobBytesProvider : public mojom::blink::BytesProvider {
|
||||
private:
|
||||
FRIEND_TEST_ALL_PREFIXES(BlobBytesProviderTest, Consolidation);
|
||||
|
||||
- BlobBytesProvider(scoped_refptr<base::SequencedTaskRunner>);
|
||||
-
|
||||
- // The task runner this class is bound on, as well as what is used by the
|
||||
- // RequestAsStream method to monitor the data pipe.
|
||||
- scoped_refptr<base::SequencedTaskRunner> task_runner_;
|
||||
-
|
||||
- Vector<scoped_refptr<RawData>> data_;
|
||||
+ Vector<scoped_refptr<RawData>> data_ GUARDED_BY_CONTEXT(sequence_checker_);
|
||||
// |offsets_| always contains exactly one fewer item than |data_| (except when
|
||||
// |data_| itself is empty).
|
||||
// offsets_[x] is equal to the sum of data_[i].length for all i <= x.
|
||||
- Vector<uint64_t> offsets_;
|
||||
+ Vector<uint64_t> offsets_ GUARDED_BY_CONTEXT(sequence_checker_);
|
||||
+
|
||||
+ SEQUENCE_CHECKER(sequence_checker_);
|
||||
};
|
||||
|
||||
} // namespace blink
|
||||
diff --git a/third_party/blink/renderer/platform/blob/blob_bytes_provider_test.cc b/third_party/blink/renderer/platform/blob/blob_bytes_provider_test.cc
|
||||
index 227955f6c0762ab7015597fc3c6a6dada823b507..27bdebcbd7a96b579efdb9372d1de4e543b55f4d 100644
|
||||
--- a/third_party/blink/renderer/platform/blob/blob_bytes_provider_test.cc
|
||||
+++ b/third_party/blink/renderer/platform/blob/blob_bytes_provider_test.cc
|
||||
@@ -52,8 +52,7 @@ class BlobBytesProviderTest : public testing::Test {
|
||||
|
||||
std::unique_ptr<BlobBytesProvider> CreateProvider(
|
||||
scoped_refptr<RawData> data = nullptr) {
|
||||
- auto result = BlobBytesProvider::CreateForTesting(
|
||||
- blink::scheduler::GetSequencedTaskRunnerForTesting());
|
||||
+ auto result = std::make_unique<BlobBytesProvider>();
|
||||
if (data)
|
||||
result->AppendData(std::move(data));
|
||||
return result;
|
||||
@@ -73,6 +72,8 @@ class BlobBytesProviderTest : public testing::Test {
|
||||
|
||||
TEST_F(BlobBytesProviderTest, Consolidation) {
|
||||
auto data = CreateProvider();
|
||||
+ DCHECK_CALLED_ON_VALID_SEQUENCE(data->sequence_checker_);
|
||||
+
|
||||
data->AppendData(base::make_span("abc", 3));
|
||||
data->AppendData(base::make_span("def", 3));
|
||||
data->AppendData(base::make_span("ps1", 3));
|
||||
diff --git a/third_party/blink/renderer/platform/blob/blob_data.cc b/third_party/blink/renderer/platform/blob/blob_data.cc
|
||||
index 6e3b98983f45b8583d8a7bb0fa51ad0fa73ecfa6..065820bf854e24ee4f1ef69fe1aff75755a27111 100644
|
||||
--- a/third_party/blink/renderer/platform/blob/blob_data.cc
|
||||
+++ b/third_party/blink/renderer/platform/blob/blob_data.cc
|
||||
@@ -107,6 +107,12 @@ BlobData::BlobData(FileCompositionStatus composition)
|
||||
BlobData::~BlobData() = default;
|
||||
|
||||
Vector<mojom::blink::DataElementPtr> BlobData::ReleaseElements() {
|
||||
+ if (last_bytes_provider_) {
|
||||
+ DCHECK(last_bytes_provider_receiver_);
|
||||
+ BlobBytesProvider::Bind(std::move(last_bytes_provider_),
|
||||
+ std::move(last_bytes_provider_receiver_));
|
||||
+ }
|
||||
+
|
||||
return std::move(elements_);
|
||||
}
|
||||
|
||||
@@ -141,16 +147,6 @@ std::unique_ptr<BlobData> BlobData::CreateForFileSystemURLWithUnknownSize(
|
||||
return data;
|
||||
}
|
||||
|
||||
-void BlobData::DetachFromCurrentThread() {
|
||||
- content_type_ = content_type_.IsolatedCopy();
|
||||
- for (auto& element : elements_) {
|
||||
- if (element->is_file_filesystem()) {
|
||||
- auto& file_element = element->get_file_filesystem();
|
||||
- file_element->url = file_element->url.Copy();
|
||||
- }
|
||||
- }
|
||||
-}
|
||||
-
|
||||
void BlobData::SetContentType(const String& content_type) {
|
||||
if (IsValidBlobType(content_type))
|
||||
content_type_ = content_type;
|
||||
@@ -274,6 +270,7 @@ void BlobData::AppendDataInternal(base::span<const char> data,
|
||||
if (!elements_.IsEmpty() && elements_.back()->is_bytes()) {
|
||||
// Append bytes to previous element.
|
||||
DCHECK(last_bytes_provider_);
|
||||
+ DCHECK(last_bytes_provider_receiver_);
|
||||
const auto& bytes_element = elements_.back()->get_bytes();
|
||||
bytes_element->length += data.size();
|
||||
if (should_embed_bytes && bytes_element->embedded_data) {
|
||||
@@ -285,9 +282,18 @@ void BlobData::AppendDataInternal(base::span<const char> data,
|
||||
bytes_element->embedded_data = absl::nullopt;
|
||||
}
|
||||
} else {
|
||||
+ if (last_bytes_provider_) {
|
||||
+ // If `last_bytes_provider_` is set, but the previous element is not a
|
||||
+ // bytes element, a new BytesProvider will be created and we need to
|
||||
+ // make sure to bind the previous one first.
|
||||
+ DCHECK(last_bytes_provider_receiver_);
|
||||
+ BlobBytesProvider::Bind(std::move(last_bytes_provider_),
|
||||
+ std::move(last_bytes_provider_receiver_));
|
||||
+ }
|
||||
mojo::PendingRemote<BytesProvider> bytes_provider_remote;
|
||||
- last_bytes_provider_ = BlobBytesProvider::CreateAndBind(
|
||||
- bytes_provider_remote.InitWithNewPipeAndPassReceiver());
|
||||
+ last_bytes_provider_ = std::make_unique<BlobBytesProvider>();
|
||||
+ last_bytes_provider_receiver_ =
|
||||
+ bytes_provider_remote.InitWithNewPipeAndPassReceiver();
|
||||
|
||||
auto bytes_element = DataElementBytes::New(
|
||||
data.size(), absl::nullopt, std::move(bytes_provider_remote));
|
||||
diff --git a/third_party/blink/renderer/platform/blob/blob_data.h b/third_party/blink/renderer/platform/blob/blob_data.h
|
||||
index 17cf9a704f1f0238e5f7f2ed754b1b9f37acdc6a..bfb88005916987eb61d533f53f5090dddc543cd5 100644
|
||||
--- a/third_party/blink/renderer/platform/blob/blob_data.h
|
||||
+++ b/third_party/blink/renderer/platform/blob/blob_data.h
|
||||
@@ -44,6 +44,7 @@
|
||||
#include "mojo/public/cpp/bindings/pending_remote.h"
|
||||
#include "mojo/public/cpp/bindings/struct_ptr.h"
|
||||
#include "third_party/abseil-cpp/absl/types/optional.h"
|
||||
+#include "third_party/blink/public/mojom/blob/data_element.mojom-blink-forward.h"
|
||||
#include "third_party/blink/renderer/platform/weborigin/kurl.h"
|
||||
#include "third_party/blink/renderer/platform/wtf/allocator/allocator.h"
|
||||
#include "third_party/blink/renderer/platform/wtf/forward.h"
|
||||
@@ -120,13 +121,10 @@ class PLATFORM_EXPORT BlobData {
|
||||
const KURL& file_system_url,
|
||||
const absl::optional<base::Time>& expected_modification_time);
|
||||
|
||||
- // Detaches from current thread so that it can be passed to another thread.
|
||||
- void DetachFromCurrentThread();
|
||||
-
|
||||
const String& ContentType() const { return content_type_; }
|
||||
void SetContentType(const String&);
|
||||
|
||||
- const Vector<mojom::blink::DataElementPtr>& Elements() const {
|
||||
+ const Vector<mojom::blink::DataElementPtr>& ElementsForTesting() const {
|
||||
return elements_;
|
||||
}
|
||||
Vector<mojom::blink::DataElementPtr> ReleaseElements();
|
||||
@@ -168,7 +166,15 @@ class PLATFORM_EXPORT BlobData {
|
||||
|
||||
Vector<mojom::blink::DataElementPtr> elements_;
|
||||
size_t current_memory_population_ = 0;
|
||||
- BlobBytesProvider* last_bytes_provider_ = nullptr;
|
||||
+
|
||||
+ // These two members are used to combine multiple consecutive 'bytes' elements
|
||||
+ // (as created by `AppendBytes`, `AppendData` or `AppendText`) into a single
|
||||
+ // element. When one has a value the other also has a value. Before using
|
||||
+ // `elements_` to actually create a blob, `last_bytes_provider_` should be
|
||||
+ // bound to `last_bytes_provider_receiver_`.
|
||||
+ std::unique_ptr<BlobBytesProvider> last_bytes_provider_;
|
||||
+ mojo::PendingReceiver<mojom::blink::BytesProvider>
|
||||
+ last_bytes_provider_receiver_;
|
||||
};
|
||||
|
||||
class PLATFORM_EXPORT BlobDataHandle
|
||||
diff --git a/third_party/blink/renderer/platform/blob/blob_data_test.cc b/third_party/blink/renderer/platform/blob/blob_data_test.cc
|
||||
index 60a811d1736c035a846fb9a8e0945c3203b2b6b4..1bad0fcf3a29e5420dff6a51c5e57714b063eb03 100644
|
||||
--- a/third_party/blink/renderer/platform/blob/blob_data_test.cc
|
||||
+++ b/third_party/blink/renderer/platform/blob/blob_data_test.cc
|
||||
@@ -315,7 +315,7 @@ TEST_F(BlobDataHandleTest, CreateFromMergedBytes) {
|
||||
auto data = std::make_unique<BlobData>();
|
||||
data->AppendBytes(medium_test_data_.data(), medium_test_data_.size());
|
||||
data->AppendBytes(small_test_data_.data(), small_test_data_.size());
|
||||
- EXPECT_EQ(1u, data->Elements().size());
|
||||
+ EXPECT_EQ(1u, data->ElementsForTesting().size());
|
||||
|
||||
Vector<uint8_t> expected_data = medium_test_data_;
|
||||
expected_data.AppendVector(small_test_data_);
|
||||
@@ -331,7 +331,7 @@ TEST_F(BlobDataHandleTest, CreateFromMergedLargeAndSmallBytes) {
|
||||
auto data = std::make_unique<BlobData>();
|
||||
data->AppendBytes(large_test_data_.data(), large_test_data_.size());
|
||||
data->AppendBytes(small_test_data_.data(), small_test_data_.size());
|
||||
- EXPECT_EQ(1u, data->Elements().size());
|
||||
+ EXPECT_EQ(1u, data->ElementsForTesting().size());
|
||||
|
||||
Vector<uint8_t> expected_data = large_test_data_;
|
||||
expected_data.AppendVector(small_test_data_);
|
||||
@@ -347,7 +347,7 @@ TEST_F(BlobDataHandleTest, CreateFromMergedSmallAndLargeBytes) {
|
||||
auto data = std::make_unique<BlobData>();
|
||||
data->AppendBytes(small_test_data_.data(), small_test_data_.size());
|
||||
data->AppendBytes(large_test_data_.data(), large_test_data_.size());
|
||||
- EXPECT_EQ(1u, data->Elements().size());
|
||||
+ EXPECT_EQ(1u, data->ElementsForTesting().size());
|
||||
|
||||
Vector<uint8_t> expected_data = small_test_data_;
|
||||
expected_data.AppendVector(large_test_data_);
|
||||
40
patches/chromium/cherry-pick-5ff02e4d7368.patch
Normal file
40
patches/chromium/cherry-pick-5ff02e4d7368.patch
Normal file
@@ -0,0 +1,40 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: UwU UwU <uwu7586@gmail.com>
|
||||
Date: Tue, 19 Apr 2022 15:10:38 +0000
|
||||
Subject: NavigatorManagedData: Prevent iterator invalidation during Promise
|
||||
resolution
|
||||
|
||||
(cherry picked from commit 6083135252280d9b43e26169eb35154a9ac861ea)
|
||||
|
||||
Bug: 1307223
|
||||
Change-Id: Iead6cf8c6236a95dbdfe7877c912f6ba86b370ac
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3532439
|
||||
Commit-Queue: Anqing Zhao <anqing@chromium.org>
|
||||
Cr-Original-Commit-Position: refs/heads/main@{#984230}
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3577263
|
||||
Reviewed-by: Artem Sumaneev <asumaneev@google.com>
|
||||
Owners-Override: Artem Sumaneev <asumaneev@google.com>
|
||||
Commit-Queue: Roger Felipe Zanoni da Silva <rzanoni@google.com>
|
||||
Cr-Commit-Position: refs/branch-heads/4664@{#1591}
|
||||
Cr-Branched-From: 24dc4ee75e01a29d390d43c9c264372a169273a7-refs/heads/main@{#929512}
|
||||
|
||||
diff --git a/third_party/blink/renderer/modules/managed_device/navigator_managed_data.cc b/third_party/blink/renderer/modules/managed_device/navigator_managed_data.cc
|
||||
index 2df64ff2c51dfe080cd50b46199e9c1d77ea26db..32b48ca0157a52d322aa4e00d18d4e662d3b1c4a 100644
|
||||
--- a/third_party/blink/renderer/modules/managed_device/navigator_managed_data.cc
|
||||
+++ b/third_party/blink/renderer/modules/managed_device/navigator_managed_data.cc
|
||||
@@ -108,8 +108,14 @@ void NavigatorManagedData::OnServiceConnectionError() {
|
||||
!managed_configuration_service_.is_connected()) {
|
||||
managed_configuration_service_.reset();
|
||||
}
|
||||
+
|
||||
+ // Move the set to a local variable to prevent script execution in Reject()
|
||||
+ // from invalidating the iterator used by the loop.
|
||||
+ HeapHashSet<Member<ScriptPromiseResolver>> pending_promises;
|
||||
+ pending_promises_.swap(pending_promises);
|
||||
+
|
||||
// Resolve all pending promises with a failure.
|
||||
- for (ScriptPromiseResolver* resolver : pending_promises_) {
|
||||
+ for (ScriptPromiseResolver* resolver : pending_promises) {
|
||||
resolver->Reject(
|
||||
MakeGarbageCollected<DOMException>(DOMExceptionCode::kNotAllowedError,
|
||||
kNotHighTrustedAppExceptionMessage));
|
||||
393
patches/chromium/cherry-pick-919b1ffe1fe7.patch
Normal file
393
patches/chromium/cherry-pick-919b1ffe1fe7.patch
Normal file
@@ -0,0 +1,393 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Alex Rudenko <alexrudenko@chromium.org>
|
||||
Date: Tue, 26 Apr 2022 05:53:56 +0000
|
||||
Subject: DevTools: store weak references to nodes in inspect_tools
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
|
||||
This CL changes how the configuration for persistent overlays is stored.
|
||||
Instead of trying to save a strong reference to a DOM node, we can
|
||||
store weak references instead. This requires using a HeapHashMap as
|
||||
vectors don't support weak reference elements.
|
||||
|
||||
(cherry picked from commit 2e0a0b83e1340e948a27cdc319bea8f32849d414)
|
||||
|
||||
Fixed: 1314310
|
||||
Change-Id: I27ce12730d7598bc84d01adf421923af9a53dc67
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3593092
|
||||
Reviewed-by: Danil Somsikov <dsv@chromium.org>
|
||||
Reviewed-by: Changhao Han <changhaohan@chromium.org>
|
||||
Reviewed-by: Andrey Kosyakov <caseq@chromium.org>
|
||||
Commit-Queue: Alex Rudenko <alexrudenko@chromium.org>
|
||||
Cr-Original-Commit-Position: refs/heads/main@{#994866}
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3604262
|
||||
Auto-Submit: Alex Rudenko <alexrudenko@chromium.org>
|
||||
Reviewed-by: Simon Zünd <szuend@chromium.org>
|
||||
Commit-Queue: Simon Zünd <szuend@chromium.org>
|
||||
Cr-Commit-Position: refs/branch-heads/5005@{#163}
|
||||
Cr-Branched-From: 5b4d9450fee01f821b6400e947b3839727643a71-refs/heads/main@{#992738}
|
||||
|
||||
diff --git a/third_party/blink/renderer/core/inspector/inspect_tools.cc b/third_party/blink/renderer/core/inspector/inspect_tools.cc
|
||||
index 7a417795a2fae0936cf1f168fc2b046fb2a0b0fd..2f8335981ac7679a9e8c3d0059dfff4b8a025ac4 100644
|
||||
--- a/third_party/blink/renderer/core/inspector/inspect_tools.cc
|
||||
+++ b/third_party/blink/renderer/core/inspector/inspect_tools.cc
|
||||
@@ -477,14 +477,14 @@ bool PersistentTool::HideOnMouseMove() {
|
||||
void PersistentTool::Draw(float scale) {
|
||||
for (auto& entry : grid_node_highlights_) {
|
||||
std::unique_ptr<protocol::Value> highlight =
|
||||
- InspectorGridHighlight(entry.first.Get(), *(entry.second));
|
||||
+ InspectorGridHighlight(entry.key, *(entry.value));
|
||||
if (!highlight)
|
||||
continue;
|
||||
overlay_->EvaluateInOverlay("drawGridHighlight", std::move(highlight));
|
||||
}
|
||||
for (auto& entry : flex_container_configs_) {
|
||||
std::unique_ptr<protocol::Value> highlight =
|
||||
- InspectorFlexContainerHighlight(entry.first.Get(), *(entry.second));
|
||||
+ InspectorFlexContainerHighlight(entry.key, *(entry.value));
|
||||
if (!highlight)
|
||||
continue;
|
||||
overlay_->EvaluateInOverlay("drawFlexContainerHighlight",
|
||||
@@ -492,7 +492,7 @@ void PersistentTool::Draw(float scale) {
|
||||
}
|
||||
for (auto& entry : scroll_snap_configs_) {
|
||||
std::unique_ptr<protocol::Value> highlight =
|
||||
- InspectorScrollSnapHighlight(entry.first.Get(), *(entry.second));
|
||||
+ InspectorScrollSnapHighlight(entry.key, *(entry.value));
|
||||
if (!highlight)
|
||||
continue;
|
||||
overlay_->EvaluateInOverlay("drawScrollSnapHighlight",
|
||||
@@ -500,17 +500,15 @@ void PersistentTool::Draw(float scale) {
|
||||
}
|
||||
for (auto& entry : container_query_configs_) {
|
||||
std::unique_ptr<protocol::Value> highlight =
|
||||
- InspectorContainerQueryHighlight(entry.first.Get(), *(entry.second));
|
||||
+ InspectorContainerQueryHighlight(entry.key, *(entry.value));
|
||||
if (!highlight)
|
||||
continue;
|
||||
overlay_->EvaluateInOverlay("drawContainerQueryHighlight",
|
||||
std::move(highlight));
|
||||
}
|
||||
- for (wtf_size_t i = 0; i < isolated_element_configs_.size(); ++i) {
|
||||
- auto& entry = isolated_element_configs_.at(i);
|
||||
+ for (auto& entry : isolated_element_configs_) {
|
||||
std::unique_ptr<protocol::Value> highlight =
|
||||
- InspectorIsolatedElementHighlight(entry.first.Get(), *(entry.second),
|
||||
- i);
|
||||
+ InspectorIsolatedElementHighlight(entry.key, *(entry.value));
|
||||
if (!highlight)
|
||||
continue;
|
||||
overlay_->EvaluateInOverlay("drawIsolatedElementHighlight",
|
||||
@@ -548,9 +546,11 @@ void PersistentTool::Dispatch(const ScriptValue& message,
|
||||
|
||||
Element* element = nullptr;
|
||||
if (highlight_type == "isolatedElement") {
|
||||
- if (index < static_cast<int>(isolated_element_configs_.size()) &&
|
||||
- index >= 0) {
|
||||
- element = isolated_element_configs_.at(index).first.Get();
|
||||
+ for (auto& entry : isolated_element_configs_) {
|
||||
+ if (entry.value->highlight_index == index) {
|
||||
+ element = entry.key;
|
||||
+ break;
|
||||
+ }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -571,7 +571,7 @@ PersistentTool::GetGridInspectorHighlightsAsJson() const {
|
||||
protocol::ListValue::create();
|
||||
for (auto& entry : grid_node_highlights_) {
|
||||
std::unique_ptr<protocol::Value> highlight =
|
||||
- InspectorGridHighlight(entry.first.Get(), *(entry.second));
|
||||
+ InspectorGridHighlight(entry.key, *(entry.value));
|
||||
if (!highlight)
|
||||
continue;
|
||||
highlights->pushValue(std::move(highlight));
|
||||
@@ -584,6 +584,15 @@ PersistentTool::GetGridInspectorHighlightsAsJson() const {
|
||||
return result;
|
||||
}
|
||||
|
||||
+void PersistentTool::Trace(Visitor* visitor) const {
|
||||
+ InspectTool::Trace(visitor);
|
||||
+ visitor->Trace(grid_node_highlights_);
|
||||
+ visitor->Trace(flex_container_configs_);
|
||||
+ visitor->Trace(scroll_snap_configs_);
|
||||
+ visitor->Trace(container_query_configs_);
|
||||
+ visitor->Trace(isolated_element_configs_);
|
||||
+}
|
||||
+
|
||||
// SourceOrderTool -----------------------------------------------------------
|
||||
|
||||
SourceOrderTool::SourceOrderTool(
|
||||
diff --git a/third_party/blink/renderer/core/inspector/inspect_tools.h b/third_party/blink/renderer/core/inspector/inspect_tools.h
|
||||
index 1f558bec19b510fc80b884a6fe00144123c8aee3..2c45dc42dac388df5dbfe95949c41721944e14c4 100644
|
||||
--- a/third_party/blink/renderer/core/inspector/inspect_tools.h
|
||||
+++ b/third_party/blink/renderer/core/inspector/inspect_tools.h
|
||||
@@ -145,23 +145,20 @@ class SourceOrderTool : public InspectTool {
|
||||
};
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
-
|
||||
-using GridConfigs = Vector<
|
||||
- std::pair<Member<Node>, std::unique_ptr<InspectorGridHighlightConfig>>>;
|
||||
+using GridConfigs = HeapHashMap<WeakMember<Node>,
|
||||
+ std::unique_ptr<InspectorGridHighlightConfig>>;
|
||||
using FlexContainerConfigs =
|
||||
- Vector<std::pair<Member<Node>,
|
||||
- std::unique_ptr<InspectorFlexContainerHighlightConfig>>>;
|
||||
-using ScrollSnapConfigs = Vector<
|
||||
- std::pair<Member<Node>,
|
||||
- std::unique_ptr<InspectorScrollSnapContainerHighlightConfig>>>;
|
||||
-
|
||||
-using ContainerQueryConfigs = Vector<std::pair<
|
||||
- Member<Node>,
|
||||
- std::unique_ptr<InspectorContainerQueryContainerHighlightConfig>>>;
|
||||
-
|
||||
+ HeapHashMap<WeakMember<Node>,
|
||||
+ std::unique_ptr<InspectorFlexContainerHighlightConfig>>;
|
||||
+using ScrollSnapConfigs =
|
||||
+ HeapHashMap<WeakMember<Node>,
|
||||
+ std::unique_ptr<InspectorScrollSnapContainerHighlightConfig>>;
|
||||
+using ContainerQueryConfigs = HeapHashMap<
|
||||
+ WeakMember<Node>,
|
||||
+ std::unique_ptr<InspectorContainerQueryContainerHighlightConfig>>;
|
||||
using IsolatedElementConfigs =
|
||||
- Vector<std::pair<Member<Element>,
|
||||
- std::unique_ptr<InspectorIsolationModeHighlightConfig>>>;
|
||||
+ HeapHashMap<WeakMember<Element>,
|
||||
+ std::unique_ptr<InspectorIsolationModeHighlightConfig>>;
|
||||
|
||||
class PersistentTool : public InspectTool {
|
||||
using InspectTool::InspectTool;
|
||||
@@ -181,6 +178,8 @@ class PersistentTool : public InspectTool {
|
||||
std::unique_ptr<protocol::DictionaryValue> GetGridInspectorHighlightsAsJson()
|
||||
const;
|
||||
|
||||
+ void Trace(Visitor* visitor) const override;
|
||||
+
|
||||
private:
|
||||
bool ForwardEventsToOverlay() override;
|
||||
bool HideOnMouseMove() override;
|
||||
diff --git a/third_party/blink/renderer/core/inspector/inspector_highlight.cc b/third_party/blink/renderer/core/inspector/inspector_highlight.cc
|
||||
index 74edb4b3c0b557988e7ac297a2e502497c792eec..357aea702b828bbb7797377677bdbddbaa50e3b9 100644
|
||||
--- a/third_party/blink/renderer/core/inspector/inspector_highlight.cc
|
||||
+++ b/third_party/blink/renderer/core/inspector/inspector_highlight.cc
|
||||
@@ -2428,8 +2428,7 @@ std::unique_ptr<protocol::DictionaryValue> InspectorContainerQueryHighlight(
|
||||
|
||||
std::unique_ptr<protocol::DictionaryValue> InspectorIsolatedElementHighlight(
|
||||
Element* element,
|
||||
- const InspectorIsolationModeHighlightConfig& config,
|
||||
- int highlight_index) {
|
||||
+ const InspectorIsolationModeHighlightConfig& config) {
|
||||
LocalFrameView* frame_view = element->GetDocument().View();
|
||||
if (!frame_view)
|
||||
return nullptr;
|
||||
@@ -2441,7 +2440,7 @@ std::unique_ptr<protocol::DictionaryValue> InspectorIsolatedElementHighlight(
|
||||
if (!isolated_element_info)
|
||||
return nullptr;
|
||||
|
||||
- isolated_element_info->setInteger("highlightIndex", highlight_index);
|
||||
+ isolated_element_info->setInteger("highlightIndex", config.highlight_index);
|
||||
return isolated_element_info;
|
||||
}
|
||||
|
||||
diff --git a/third_party/blink/renderer/core/inspector/inspector_highlight.h b/third_party/blink/renderer/core/inspector/inspector_highlight.h
|
||||
index 53884fd75b8a861df3b33cc730304d344f5cda2a..897445629fdc6bbfe36c750027acce992a965d46 100644
|
||||
--- a/third_party/blink/renderer/core/inspector/inspector_highlight.h
|
||||
+++ b/third_party/blink/renderer/core/inspector/inspector_highlight.h
|
||||
@@ -145,6 +145,7 @@ struct CORE_EXPORT InspectorIsolationModeHighlightConfig {
|
||||
Color resizer_color;
|
||||
Color resizer_handle_color;
|
||||
Color mask_color;
|
||||
+ int highlight_index = 0;
|
||||
};
|
||||
|
||||
struct CORE_EXPORT InspectorHighlightConfig {
|
||||
@@ -300,8 +301,7 @@ std::unique_ptr<protocol::DictionaryValue> InspectorContainerQueryHighlight(
|
||||
|
||||
std::unique_ptr<protocol::DictionaryValue> InspectorIsolatedElementHighlight(
|
||||
Element* element,
|
||||
- const InspectorIsolationModeHighlightConfig& config,
|
||||
- int highlight_index);
|
||||
+ const InspectorIsolationModeHighlightConfig& config);
|
||||
|
||||
// CORE_EXPORT is required to make these functions available for unit tests.
|
||||
std::unique_ptr<protocol::DictionaryValue> CORE_EXPORT
|
||||
diff --git a/third_party/blink/renderer/core/inspector/inspector_overlay_agent.cc b/third_party/blink/renderer/core/inspector/inspector_overlay_agent.cc
|
||||
index f061849584a4a228b86cffb20ce3ab74c0a25409..d8c9a48da6ed4b08681268d495a2e60efb8308b6 100644
|
||||
--- a/third_party/blink/renderer/core/inspector/inspector_overlay_agent.cc
|
||||
+++ b/third_party/blink/renderer/core/inspector/inspector_overlay_agent.cc
|
||||
@@ -711,7 +711,7 @@ Response InspectorOverlayAgent::setShowGridOverlays(
|
||||
MakeGarbageCollected<PersistentTool>(this, GetFrontend());
|
||||
}
|
||||
|
||||
- Vector<std::pair<Member<Node>, std::unique_ptr<InspectorGridHighlightConfig>>>
|
||||
+ HeapHashMap<WeakMember<Node>, std::unique_ptr<InspectorGridHighlightConfig>>
|
||||
configs;
|
||||
for (std::unique_ptr<protocol::Overlay::GridNodeHighlightConfig>& config :
|
||||
*grid_node_highlight_configs) {
|
||||
@@ -719,9 +719,8 @@ Response InspectorOverlayAgent::setShowGridOverlays(
|
||||
Response response = dom_agent_->AssertNode(config->getNodeId(), node);
|
||||
if (!response.IsSuccess())
|
||||
return response;
|
||||
- configs.push_back(
|
||||
- std::make_pair(node, InspectorOverlayAgent::ToGridHighlightConfig(
|
||||
- config->getGridHighlightConfig())));
|
||||
+ configs.insert(node, InspectorOverlayAgent::ToGridHighlightConfig(
|
||||
+ config->getGridHighlightConfig()));
|
||||
}
|
||||
|
||||
persistent_tool_->SetGridConfigs(std::move(configs));
|
||||
@@ -739,8 +738,8 @@ Response InspectorOverlayAgent::setShowFlexOverlays(
|
||||
MakeGarbageCollected<PersistentTool>(this, GetFrontend());
|
||||
}
|
||||
|
||||
- Vector<std::pair<Member<Node>,
|
||||
- std::unique_ptr<InspectorFlexContainerHighlightConfig>>>
|
||||
+ HeapHashMap<WeakMember<Node>,
|
||||
+ std::unique_ptr<InspectorFlexContainerHighlightConfig>>
|
||||
configs;
|
||||
|
||||
for (std::unique_ptr<protocol::Overlay::FlexNodeHighlightConfig>& config :
|
||||
@@ -749,9 +748,8 @@ Response InspectorOverlayAgent::setShowFlexOverlays(
|
||||
Response response = dom_agent_->AssertNode(config->getNodeId(), node);
|
||||
if (!response.IsSuccess())
|
||||
return response;
|
||||
- configs.push_back(std::make_pair(
|
||||
- node, InspectorOverlayAgent::ToFlexContainerHighlightConfig(
|
||||
- config->getFlexContainerHighlightConfig())));
|
||||
+ configs.insert(node, InspectorOverlayAgent::ToFlexContainerHighlightConfig(
|
||||
+ config->getFlexContainerHighlightConfig()));
|
||||
}
|
||||
|
||||
persistent_tool_->SetFlexContainerConfigs(std::move(configs));
|
||||
@@ -770,9 +768,8 @@ Response InspectorOverlayAgent::setShowScrollSnapOverlays(
|
||||
MakeGarbageCollected<PersistentTool>(this, GetFrontend());
|
||||
}
|
||||
|
||||
- Vector<
|
||||
- std::pair<Member<Node>,
|
||||
- std::unique_ptr<InspectorScrollSnapContainerHighlightConfig>>>
|
||||
+ HeapHashMap<WeakMember<Node>,
|
||||
+ std::unique_ptr<InspectorScrollSnapContainerHighlightConfig>>
|
||||
configs;
|
||||
|
||||
for (std::unique_ptr<protocol::Overlay::ScrollSnapHighlightConfig>& config :
|
||||
@@ -781,9 +778,9 @@ Response InspectorOverlayAgent::setShowScrollSnapOverlays(
|
||||
Response response = dom_agent_->AssertNode(config->getNodeId(), node);
|
||||
if (!response.IsSuccess())
|
||||
return response;
|
||||
- configs.push_back(std::make_pair(
|
||||
- node, InspectorOverlayAgent::ToScrollSnapContainerHighlightConfig(
|
||||
- config->getScrollSnapContainerHighlightConfig())));
|
||||
+ configs.insert(node,
|
||||
+ InspectorOverlayAgent::ToScrollSnapContainerHighlightConfig(
|
||||
+ config->getScrollSnapContainerHighlightConfig()));
|
||||
}
|
||||
|
||||
persistent_tool_->SetScrollSnapConfigs(std::move(configs));
|
||||
@@ -802,9 +799,8 @@ Response InspectorOverlayAgent::setShowContainerQueryOverlays(
|
||||
MakeGarbageCollected<PersistentTool>(this, GetFrontend());
|
||||
}
|
||||
|
||||
- Vector<std::pair<
|
||||
- Member<Node>,
|
||||
- std::unique_ptr<InspectorContainerQueryContainerHighlightConfig>>>
|
||||
+ HeapHashMap<WeakMember<Node>,
|
||||
+ std::unique_ptr<InspectorContainerQueryContainerHighlightConfig>>
|
||||
configs;
|
||||
|
||||
for (std::unique_ptr<protocol::Overlay::ContainerQueryHighlightConfig>&
|
||||
@@ -813,9 +809,9 @@ Response InspectorOverlayAgent::setShowContainerQueryOverlays(
|
||||
Response response = dom_agent_->AssertNode(config->getNodeId(), node);
|
||||
if (!response.IsSuccess())
|
||||
return response;
|
||||
- configs.push_back(std::make_pair(
|
||||
+ configs.insert(
|
||||
node, InspectorOverlayAgent::ToContainerQueryContainerHighlightConfig(
|
||||
- config->getContainerQueryContainerHighlightConfig())));
|
||||
+ config->getContainerQueryContainerHighlightConfig()));
|
||||
}
|
||||
|
||||
persistent_tool_->SetContainerQueryConfigs(std::move(configs));
|
||||
@@ -834,10 +830,11 @@ Response InspectorOverlayAgent::setShowIsolatedElements(
|
||||
MakeGarbageCollected<PersistentTool>(this, GetFrontend());
|
||||
}
|
||||
|
||||
- Vector<std::pair<Member<Element>,
|
||||
- std::unique_ptr<InspectorIsolationModeHighlightConfig>>>
|
||||
+ HeapHashMap<WeakMember<Element>,
|
||||
+ std::unique_ptr<InspectorIsolationModeHighlightConfig>>
|
||||
configs;
|
||||
|
||||
+ int idx = 0;
|
||||
for (std::unique_ptr<protocol::Overlay::IsolatedElementHighlightConfig>&
|
||||
config : *isolated_element_highlight_configs) {
|
||||
Element* element = nullptr;
|
||||
@@ -845,9 +842,10 @@ Response InspectorOverlayAgent::setShowIsolatedElements(
|
||||
Response response = dom_agent_->AssertElement(config->getNodeId(), element);
|
||||
if (!response.IsSuccess())
|
||||
return response;
|
||||
- configs.push_back(std::make_pair(
|
||||
- element, InspectorOverlayAgent::ToIsolationModeHighlightConfig(
|
||||
- config->getIsolationModeHighlightConfig())));
|
||||
+ configs.insert(element,
|
||||
+ InspectorOverlayAgent::ToIsolationModeHighlightConfig(
|
||||
+ config->getIsolationModeHighlightConfig(), idx));
|
||||
+ idx++;
|
||||
}
|
||||
|
||||
persistent_tool_->SetIsolatedElementConfigs(std::move(configs));
|
||||
@@ -951,16 +949,16 @@ Response InspectorOverlayAgent::getGridHighlightObjectsForTest(
|
||||
std::unique_ptr<protocol::Array<int>> node_ids,
|
||||
std::unique_ptr<protocol::DictionaryValue>* highlights) {
|
||||
PersistentTool persistent_tool(this, GetFrontend());
|
||||
- Vector<std::pair<Member<Node>, std::unique_ptr<InspectorGridHighlightConfig>>>
|
||||
+
|
||||
+ HeapHashMap<WeakMember<Node>, std::unique_ptr<InspectorGridHighlightConfig>>
|
||||
configs;
|
||||
for (const int node_id : *node_ids) {
|
||||
Node* node = nullptr;
|
||||
Response response = dom_agent_->AssertNode(node_id, node);
|
||||
if (!response.IsSuccess())
|
||||
return response;
|
||||
- configs.push_back(
|
||||
- std::make_pair(node, std::make_unique<InspectorGridHighlightConfig>(
|
||||
- InspectorHighlight::DefaultGridConfig())));
|
||||
+ configs.insert(node, std::make_unique<InspectorGridHighlightConfig>(
|
||||
+ InspectorHighlight::DefaultGridConfig()));
|
||||
}
|
||||
persistent_tool.SetGridConfigs(std::move(configs));
|
||||
*highlights = persistent_tool.GetGridInspectorHighlightsAsJson();
|
||||
@@ -1728,7 +1726,8 @@ InspectorOverlayAgent::ToFlexItemHighlightConfig(
|
||||
// static
|
||||
std::unique_ptr<InspectorIsolationModeHighlightConfig>
|
||||
InspectorOverlayAgent::ToIsolationModeHighlightConfig(
|
||||
- protocol::Overlay::IsolationModeHighlightConfig* config) {
|
||||
+ protocol::Overlay::IsolationModeHighlightConfig* config,
|
||||
+ int idx) {
|
||||
if (!config) {
|
||||
return nullptr;
|
||||
}
|
||||
@@ -1740,6 +1739,7 @@ InspectorOverlayAgent::ToIsolationModeHighlightConfig(
|
||||
InspectorDOMAgent::ParseColor(config->getResizerHandleColor(nullptr));
|
||||
highlight_config->mask_color =
|
||||
InspectorDOMAgent::ParseColor(config->getMaskColor(nullptr));
|
||||
+ highlight_config->highlight_index = idx;
|
||||
|
||||
return highlight_config;
|
||||
}
|
||||
diff --git a/third_party/blink/renderer/core/inspector/inspector_overlay_agent.h b/third_party/blink/renderer/core/inspector/inspector_overlay_agent.h
|
||||
index ee9963de2b918cba7fd786c85f6c1ad1884ae5f8..d70123303569c7626a4c3117d542d66e0c375ac1 100644
|
||||
--- a/third_party/blink/renderer/core/inspector/inspector_overlay_agent.h
|
||||
+++ b/third_party/blink/renderer/core/inspector/inspector_overlay_agent.h
|
||||
@@ -161,7 +161,8 @@ class CORE_EXPORT InspectorOverlayAgent final
|
||||
ToFlexItemHighlightConfig(protocol::Overlay::FlexItemHighlightConfig*);
|
||||
static std::unique_ptr<InspectorIsolationModeHighlightConfig>
|
||||
ToIsolationModeHighlightConfig(
|
||||
- protocol::Overlay::IsolationModeHighlightConfig*);
|
||||
+ protocol::Overlay::IsolationModeHighlightConfig*,
|
||||
+ int highlight_index);
|
||||
static absl::optional<LineStyle> ToLineStyle(protocol::Overlay::LineStyle*);
|
||||
static absl::optional<BoxStyle> ToBoxStyle(protocol::Overlay::BoxStyle*);
|
||||
static std::unique_ptr<InspectorHighlightConfig> ToHighlightConfig(
|
||||
64
patches/chromium/cherry-pick-99c3f3bfd507.patch
Normal file
64
patches/chromium/cherry-pick-99c3f3bfd507.patch
Normal file
@@ -0,0 +1,64 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Eugene Zemtsov <eugene@chromium.org>
|
||||
Date: Fri, 8 Apr 2022 23:28:35 +0000
|
||||
Subject: Only destroy successfully created compression session in VT encoder
|
||||
|
||||
This is a defensive change, since we don't have a repro on hand.
|
||||
My guess is that VTCompressionSessionCreate() might fail to create a
|
||||
compression session, but still write a value to compressionSessionOut.
|
||||
It makes VTCompressionSessionInvalidate() access uninitialized memory.
|
||||
|
||||
That's why this CL makes sure that we only destroy a compression session
|
||||
if VTCompressionSessionCreate() reports success.
|
||||
|
||||
Bug: 1312563
|
||||
Change-Id: I468ce0e10bad251ca0b62b568607dbc5c32ba8bc
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3575680
|
||||
Reviewed-by: Dale Curtis <dalecurtis@chromium.org>
|
||||
Commit-Queue: Eugene Zemtsov <eugene@chromium.org>
|
||||
Cr-Commit-Position: refs/heads/main@{#990654}
|
||||
|
||||
diff --git a/media/gpu/mac/vt_video_encode_accelerator_mac.cc b/media/gpu/mac/vt_video_encode_accelerator_mac.cc
|
||||
index 06333aaeca6b8bfd10d6809bcace4177ac7fd368..c265ff94617dfedca60ad9b3f1ce3de3364cfe56 100644
|
||||
--- a/media/gpu/mac/vt_video_encode_accelerator_mac.cc
|
||||
+++ b/media/gpu/mac/vt_video_encode_accelerator_mac.cc
|
||||
@@ -129,13 +129,13 @@ VTVideoEncodeAccelerator::GetSupportedProfiles() {
|
||||
SupportedProfiles profiles;
|
||||
const bool rv = CreateCompressionSession(
|
||||
gfx::Size(kDefaultResolutionWidth, kDefaultResolutionHeight));
|
||||
- DestroyCompressionSession();
|
||||
if (!rv) {
|
||||
VLOG(1)
|
||||
<< "Hardware encode acceleration is not available on this platform.";
|
||||
return profiles;
|
||||
}
|
||||
|
||||
+ DestroyCompressionSession();
|
||||
SupportedProfile profile;
|
||||
profile.max_framerate_numerator = kMaxFrameRateNumerator;
|
||||
profile.max_framerate_denominator = kMaxFrameRateDenominator;
|
||||
@@ -533,10 +533,8 @@ bool VTVideoEncodeAccelerator::ResetCompressionSession() {
|
||||
DestroyCompressionSession();
|
||||
|
||||
bool session_rv = CreateCompressionSession(input_visible_size_);
|
||||
- if (!session_rv) {
|
||||
- DestroyCompressionSession();
|
||||
+ if (!session_rv)
|
||||
return false;
|
||||
- }
|
||||
|
||||
const bool configure_rv = ConfigureCompressionSession();
|
||||
if (configure_rv)
|
||||
@@ -572,6 +570,12 @@ bool VTVideoEncodeAccelerator::CreateCompressionSession(
|
||||
&VTVideoEncodeAccelerator::CompressionCallback,
|
||||
reinterpret_cast<void*>(this), compression_session_.InitializeInto());
|
||||
if (status != noErr) {
|
||||
+ // IMPORTANT: ScopedCFTypeRef::release() doesn't call CFRelease().
|
||||
+ // In case of an error VTCompressionSessionCreate() is not supposed to
|
||||
+ // write a non-null value into compression_session_, but just in case,
|
||||
+ // we'll clear it without calling CFRelease() because it can be unsafe
|
||||
+ // to call on a not fully created session.
|
||||
+ (void)compression_session_.release();
|
||||
DLOG(ERROR) << " VTCompressionSessionCreate failed: " << status;
|
||||
return false;
|
||||
}
|
||||
413
patches/chromium/cherry-pick-a1dc371d6680.patch
Normal file
413
patches/chromium/cherry-pick-a1dc371d6680.patch
Normal file
@@ -0,0 +1,413 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Jack Hsieh <chengweih@chromium.org>
|
||||
Date: Fri, 21 Jan 2022 00:01:43 +0000
|
||||
Subject: usb: Fix OOB access with non-sequential interfaces
|
||||
|
||||
When accessing a usb device with non-sequential interface number or
|
||||
alternative setting value, it might end up using index out of the
|
||||
internal array allocated size. It is caused by using incorrect
|
||||
parameters (i.e interface_number and alternate_setting) into the
|
||||
callback which expects taking interface_index and alternate_index. Fix
|
||||
it by passing the correct parameters which are already available in the
|
||||
function to the callback.
|
||||
|
||||
Bug: 1286816
|
||||
Change-Id: I6b3533f944f94e94e63959b99718858e089449da
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3384715
|
||||
Reviewed-by: Reilly Grant <reillyg@chromium.org>
|
||||
Commit-Queue: Jack Hsieh <chengweih@chromium.org>
|
||||
Cr-Commit-Position: refs/heads/main@{#961679}
|
||||
|
||||
diff --git a/third_party/blink/renderer/modules/webusb/usb_device.cc b/third_party/blink/renderer/modules/webusb/usb_device.cc
|
||||
index aef73449348e4636be9f8fc90bfc07ac65b03326..82da58974c51c3a593d5c2a272d0a0f05361dfdb 100644
|
||||
--- a/third_party/blink/renderer/modules/webusb/usb_device.cc
|
||||
+++ b/third_party/blink/renderer/modules/webusb/usb_device.cc
|
||||
@@ -132,9 +132,9 @@ bool USBDevice::IsInterfaceClaimed(wtf_size_t configuration_index,
|
||||
claimed_interfaces_[interface_index];
|
||||
}
|
||||
|
||||
-wtf_size_t USBDevice::SelectedAlternateInterface(
|
||||
+wtf_size_t USBDevice::SelectedAlternateInterfaceIndex(
|
||||
wtf_size_t interface_index) const {
|
||||
- return selected_alternates_[interface_index];
|
||||
+ return selected_alternate_indices_[interface_index];
|
||||
}
|
||||
|
||||
USBConfiguration* USBDevice::configuration() const {
|
||||
@@ -302,7 +302,7 @@ ScriptPromise USBDevice::selectAlternateInterface(ScriptState* script_state,
|
||||
device_->SetInterfaceAlternateSetting(
|
||||
interface_number, alternate_setting,
|
||||
WTF::Bind(&USBDevice::AsyncSelectAlternateInterface,
|
||||
- WrapPersistent(this), interface_number, alternate_setting,
|
||||
+ WrapPersistent(this), interface_index, alternate_index,
|
||||
WrapPersistent(resolver)));
|
||||
}
|
||||
}
|
||||
@@ -744,7 +744,7 @@ void USBDevice::SetEndpointsForInterface(wtf_size_t interface_index, bool set) {
|
||||
const auto& configuration = *Info().configurations[configuration_index_];
|
||||
const auto& interface = *configuration.interfaces[interface_index];
|
||||
const auto& alternate =
|
||||
- *interface.alternates[selected_alternates_[interface_index]];
|
||||
+ *interface.alternates[selected_alternate_indices_[interface_index]];
|
||||
for (const auto& endpoint : alternate.endpoints) {
|
||||
uint8_t endpoint_number = endpoint->endpoint_number;
|
||||
if (endpoint_number == 0 || endpoint_number >= kEndpointsBitsNumber)
|
||||
@@ -792,7 +792,7 @@ void USBDevice::OnDeviceOpenedOrClosed(bool opened) {
|
||||
opened_ = opened;
|
||||
if (!opened_) {
|
||||
claimed_interfaces_.Fill(false);
|
||||
- selected_alternates_.Fill(0);
|
||||
+ selected_alternate_indices_.Fill(0);
|
||||
in_endpoints_.reset();
|
||||
out_endpoints_.reset();
|
||||
}
|
||||
@@ -825,8 +825,8 @@ void USBDevice::OnConfigurationSelected(bool success,
|
||||
claimed_interfaces_.Fill(false);
|
||||
interface_state_change_in_progress_.resize(num_interfaces);
|
||||
interface_state_change_in_progress_.Fill(false);
|
||||
- selected_alternates_.resize(num_interfaces);
|
||||
- selected_alternates_.Fill(0);
|
||||
+ selected_alternate_indices_.resize(num_interfaces);
|
||||
+ selected_alternate_indices_.Fill(0);
|
||||
in_endpoints_.reset();
|
||||
out_endpoints_.reset();
|
||||
}
|
||||
@@ -887,7 +887,7 @@ void USBDevice::OnInterfaceClaimedOrUnclaimed(bool claimed,
|
||||
claimed_interfaces_[interface_index] = true;
|
||||
} else {
|
||||
claimed_interfaces_[interface_index] = false;
|
||||
- selected_alternates_[interface_index] = 0;
|
||||
+ selected_alternate_indices_[interface_index] = 0;
|
||||
}
|
||||
SetEndpointsForInterface(interface_index, claimed);
|
||||
interface_state_change_in_progress_[interface_index] = false;
|
||||
@@ -901,7 +901,7 @@ void USBDevice::AsyncSelectAlternateInterface(wtf_size_t interface_index,
|
||||
return;
|
||||
|
||||
if (success)
|
||||
- selected_alternates_[interface_index] = alternate_index;
|
||||
+ selected_alternate_indices_[interface_index] = alternate_index;
|
||||
SetEndpointsForInterface(interface_index, success);
|
||||
interface_state_change_in_progress_[interface_index] = false;
|
||||
|
||||
diff --git a/third_party/blink/renderer/modules/webusb/usb_device.h b/third_party/blink/renderer/modules/webusb/usb_device.h
|
||||
index 21231db5f4d6f949b4d371143c631a6f33dcb1e4..cb199d2f2ac4c27f2db7f153d51408e604b5f6f0 100644
|
||||
--- a/third_party/blink/renderer/modules/webusb/usb_device.h
|
||||
+++ b/third_party/blink/renderer/modules/webusb/usb_device.h
|
||||
@@ -40,7 +40,7 @@ class USBDevice : public ScriptWrappable,
|
||||
}
|
||||
bool IsInterfaceClaimed(wtf_size_t configuration_index,
|
||||
wtf_size_t interface_index) const;
|
||||
- wtf_size_t SelectedAlternateInterface(wtf_size_t interface_index) const;
|
||||
+ wtf_size_t SelectedAlternateInterfaceIndex(wtf_size_t interface_index) const;
|
||||
|
||||
// USBDevice.idl
|
||||
uint8_t usbVersionMajor() const { return Info().usb_version_major; }
|
||||
@@ -179,7 +179,7 @@ class USBDevice : public ScriptWrappable,
|
||||
// configured. Use the index returned by FindInterfaceIndex().
|
||||
WTF::Vector<bool> claimed_interfaces_;
|
||||
WTF::Vector<bool> interface_state_change_in_progress_;
|
||||
- WTF::Vector<wtf_size_t> selected_alternates_;
|
||||
+ WTF::Vector<wtf_size_t> selected_alternate_indices_;
|
||||
|
||||
// These bit sets have one entry for each endpoint. Index using the endpoint
|
||||
// number (lower 4 bits of the endpoint address).
|
||||
diff --git a/third_party/blink/renderer/modules/webusb/usb_interface.cc b/third_party/blink/renderer/modules/webusb/usb_interface.cc
|
||||
index bba6f5eb58d56e9372f9cef8e38e2f1493a94678..2ecc28054831e076f85832d97bd95a738d6657b2 100644
|
||||
--- a/third_party/blink/renderer/modules/webusb/usb_interface.cc
|
||||
+++ b/third_party/blink/renderer/modules/webusb/usb_interface.cc
|
||||
@@ -53,7 +53,7 @@ const device::mojom::blink::UsbInterfaceInfo& USBInterface::Info() const {
|
||||
USBAlternateInterface* USBInterface::alternate() const {
|
||||
if (device_->IsInterfaceClaimed(configuration_index_, interface_index_)) {
|
||||
return USBAlternateInterface::Create(
|
||||
- this, device_->SelectedAlternateInterface(interface_index_));
|
||||
+ this, device_->SelectedAlternateInterfaceIndex(interface_index_));
|
||||
}
|
||||
return USBAlternateInterface::Create(this, 0);
|
||||
}
|
||||
diff --git a/third_party/blink/web_tests/external/wpt/webusb/resources/fake-devices.js b/third_party/blink/web_tests/external/wpt/webusb/resources/fake-devices.js
|
||||
index 975d2242c949740217c050beea72db908ef46fc7..c5c5cadaa6af48f676565775d1dc8e27efffc3a2 100644
|
||||
--- a/third_party/blink/web_tests/external/wpt/webusb/resources/fake-devices.js
|
||||
+++ b/third_party/blink/web_tests/external/wpt/webusb/resources/fake-devices.js
|
||||
@@ -16,75 +16,160 @@ let fakeDeviceInit = {
|
||||
productName: 'The amazing imaginary printer',
|
||||
serialNumber: '4',
|
||||
activeConfigurationValue: 0,
|
||||
- configurations: [{
|
||||
- configurationValue: 1,
|
||||
- configurationName: 'Printer Mode',
|
||||
- interfaces: [{
|
||||
- interfaceNumber: 0,
|
||||
- alternates: [{
|
||||
- alternateSetting: 0,
|
||||
- interfaceClass: 0xff,
|
||||
- interfaceSubclass: 0x01,
|
||||
- interfaceProtocol: 0x01,
|
||||
- interfaceName: 'Control',
|
||||
- endpoints: [{
|
||||
- endpointNumber: 1,
|
||||
- direction: 'in',
|
||||
- type: 'interrupt',
|
||||
- packetSize: 8
|
||||
- }]
|
||||
+ configurations: [
|
||||
+ {
|
||||
+ configurationValue: 1,
|
||||
+ configurationName: 'Printer Mode',
|
||||
+ interfaces: [
|
||||
+ {
|
||||
+ interfaceNumber: 0,
|
||||
+ alternates: [{
|
||||
+ alternateSetting: 0,
|
||||
+ interfaceClass: 0xff,
|
||||
+ interfaceSubclass: 0x01,
|
||||
+ interfaceProtocol: 0x01,
|
||||
+ interfaceName: 'Control',
|
||||
+ endpoints: [{
|
||||
+ endpointNumber: 1,
|
||||
+ direction: 'in',
|
||||
+ type: 'interrupt',
|
||||
+ packetSize: 8
|
||||
+ }]
|
||||
+ }]
|
||||
+ },
|
||||
+ {
|
||||
+ interfaceNumber: 1,
|
||||
+ alternates: [{
|
||||
+ alternateSetting: 0,
|
||||
+ interfaceClass: 0xff,
|
||||
+ interfaceSubclass: 0x02,
|
||||
+ interfaceProtocol: 0x01,
|
||||
+ interfaceName: 'Data',
|
||||
+ endpoints: [
|
||||
+ {
|
||||
+ endpointNumber: 2,
|
||||
+ direction: 'in',
|
||||
+ type: 'bulk',
|
||||
+ packetSize: 1024
|
||||
+ },
|
||||
+ {
|
||||
+ endpointNumber: 2,
|
||||
+ direction: 'out',
|
||||
+ type: 'bulk',
|
||||
+ packetSize: 1024
|
||||
+ }
|
||||
+ ]
|
||||
+ }]
|
||||
+ }
|
||||
+ ]
|
||||
+ },
|
||||
+ {
|
||||
+ configurationValue: 2,
|
||||
+ configurationName: 'Fighting Robot Mode',
|
||||
+ interfaces: [{
|
||||
+ interfaceNumber: 0,
|
||||
+ alternates: [
|
||||
+ {
|
||||
+ alternateSetting: 0,
|
||||
+ interfaceClass: 0xff,
|
||||
+ interfaceSubclass: 0x42,
|
||||
+ interfaceProtocol: 0x01,
|
||||
+ interfaceName: 'Disabled',
|
||||
+ endpoints: []
|
||||
+ },
|
||||
+ {
|
||||
+ alternateSetting: 1,
|
||||
+ interfaceClass: 0xff,
|
||||
+ interfaceSubclass: 0x42,
|
||||
+ interfaceProtocol: 0x01,
|
||||
+ interfaceName: 'Activate!',
|
||||
+ endpoints: [
|
||||
+ {
|
||||
+ endpointNumber: 1,
|
||||
+ direction: 'in',
|
||||
+ type: 'isochronous',
|
||||
+ packetSize: 1024
|
||||
+ },
|
||||
+ {
|
||||
+ endpointNumber: 1,
|
||||
+ direction: 'out',
|
||||
+ type: 'isochronous',
|
||||
+ packetSize: 1024
|
||||
+ }
|
||||
+ ]
|
||||
+ }
|
||||
+ ]
|
||||
}]
|
||||
- }, {
|
||||
- interfaceNumber: 1,
|
||||
- alternates: [{
|
||||
- alternateSetting: 0,
|
||||
- interfaceClass: 0xff,
|
||||
- interfaceSubclass: 0x02,
|
||||
- interfaceProtocol: 0x01,
|
||||
- interfaceName: 'Data',
|
||||
- endpoints: [{
|
||||
- endpointNumber: 2,
|
||||
- direction: 'in',
|
||||
- type: 'bulk',
|
||||
- packetSize: 1024
|
||||
- }, {
|
||||
- endpointNumber: 2,
|
||||
- direction: 'out',
|
||||
- type: 'bulk',
|
||||
- packetSize: 1024
|
||||
- }]
|
||||
- }]
|
||||
- }]
|
||||
- }, {
|
||||
- configurationValue: 2,
|
||||
- configurationName: 'Fighting Robot Mode',
|
||||
- interfaces: [{
|
||||
- interfaceNumber: 0,
|
||||
- alternates: [{
|
||||
- alternateSetting: 0,
|
||||
- interfaceClass: 0xff,
|
||||
- interfaceSubclass: 0x42,
|
||||
- interfaceProtocol: 0x01,
|
||||
- interfaceName: 'Disabled',
|
||||
- endpoints: []
|
||||
- }, {
|
||||
- alternateSetting: 1,
|
||||
- interfaceClass: 0xff,
|
||||
- interfaceSubclass: 0x42,
|
||||
- interfaceProtocol: 0x01,
|
||||
- interfaceName: 'Activate!',
|
||||
- endpoints: [{
|
||||
- endpointNumber: 1,
|
||||
- direction: 'in',
|
||||
- type: 'isochronous',
|
||||
- packetSize: 1024
|
||||
- }, {
|
||||
- endpointNumber: 1,
|
||||
- direction: 'out',
|
||||
- type: 'isochronous',
|
||||
- packetSize: 1024
|
||||
- }]
|
||||
- }]
|
||||
- }]
|
||||
- }]
|
||||
+ },
|
||||
+ {
|
||||
+ configurationValue: 3,
|
||||
+ configurationName: 'Non-sequential interface number and alternate ' +
|
||||
+ 'setting Mode',
|
||||
+ interfaces: [
|
||||
+ {
|
||||
+ interfaceNumber: 0,
|
||||
+ alternates: [
|
||||
+ {
|
||||
+ alternateSetting: 0,
|
||||
+ interfaceClass: 0xff,
|
||||
+ interfaceSubclass: 0x01,
|
||||
+ interfaceProtocol: 0x01,
|
||||
+ interfaceName: 'Control',
|
||||
+ endpoints: [{
|
||||
+ endpointNumber: 1,
|
||||
+ direction: 'in',
|
||||
+ type: 'interrupt',
|
||||
+ packetSize: 8
|
||||
+ }]
|
||||
+ },
|
||||
+ {
|
||||
+ alternateSetting: 2,
|
||||
+ interfaceClass: 0xff,
|
||||
+ interfaceSubclass: 0x02,
|
||||
+ interfaceProtocol: 0x01,
|
||||
+ interfaceName: 'Data',
|
||||
+ endpoints: [
|
||||
+ {
|
||||
+ endpointNumber: 2,
|
||||
+ direction: 'in',
|
||||
+ type: 'bulk',
|
||||
+ packetSize: 1024
|
||||
+ },
|
||||
+ {
|
||||
+ endpointNumber: 2,
|
||||
+ direction: 'out',
|
||||
+ type: 'bulk',
|
||||
+ packetSize: 1024
|
||||
+ }
|
||||
+ ]
|
||||
+ }
|
||||
+ ]
|
||||
+ },
|
||||
+ {
|
||||
+ interfaceNumber: 2,
|
||||
+ alternates: [{
|
||||
+ alternateSetting: 0,
|
||||
+ interfaceClass: 0xff,
|
||||
+ interfaceSubclass: 0x02,
|
||||
+ interfaceProtocol: 0x01,
|
||||
+ interfaceName: 'Data',
|
||||
+ endpoints: [
|
||||
+ {
|
||||
+ endpointNumber: 2,
|
||||
+ direction: 'in',
|
||||
+ type: 'bulk',
|
||||
+ packetSize: 1024
|
||||
+ },
|
||||
+ {
|
||||
+ endpointNumber: 2,
|
||||
+ direction: 'out',
|
||||
+ type: 'bulk',
|
||||
+ packetSize: 1024
|
||||
+ }
|
||||
+ ]
|
||||
+ }]
|
||||
+ }
|
||||
+ ]
|
||||
+ }
|
||||
+ ]
|
||||
};
|
||||
diff --git a/third_party/blink/web_tests/external/wpt/webusb/usbDevice.https.any.js b/third_party/blink/web_tests/external/wpt/webusb/usbDevice.https.any.js
|
||||
index 5bfd841d5248e91a5cabf10d00d78db23d11f0e5..527d238d69b703b1fcf5d8a001d02e9f87b5689a 100644
|
||||
--- a/third_party/blink/web_tests/external/wpt/webusb/usbDevice.https.any.js
|
||||
+++ b/third_party/blink/web_tests/external/wpt/webusb/usbDevice.https.any.js
|
||||
@@ -236,10 +236,11 @@ usb_test(() => {
|
||||
return getFakeDevice().then(({ device }) => {
|
||||
assert_equals(device.configuration, null);
|
||||
return device.open()
|
||||
- .then(() => assertRejectsWithError(
|
||||
- device.selectConfiguration(3), 'NotFoundError',
|
||||
- 'The configuration value provided is not supported by the device.'))
|
||||
- .then(() => device.close());
|
||||
+ .then(
|
||||
+ () => assertRejectsWithError(
|
||||
+ device.selectConfiguration(10), 'NotFoundError',
|
||||
+ 'The configuration value provided is not supported by the device.'))
|
||||
+ .then(() => device.close());
|
||||
});
|
||||
}, 'selectConfiguration rejects on invalid configurations');
|
||||
|
||||
@@ -431,6 +432,30 @@ usb_test(() => {
|
||||
});
|
||||
}, 'can select an alternate interface');
|
||||
|
||||
+usb_test(
|
||||
+ async () => {
|
||||
+ const {device} = await getFakeDevice();
|
||||
+ await device.open();
|
||||
+ await device.selectConfiguration(3);
|
||||
+ await device.claimInterface(2);
|
||||
+ await device.selectAlternateInterface(2, 0);
|
||||
+ await device.close();
|
||||
+ },
|
||||
+ 'can select an alternate interface on a setting with non-sequential ' +
|
||||
+ 'interface number');
|
||||
+
|
||||
+usb_test(
|
||||
+ async () => {
|
||||
+ const {device} = await getFakeDevice();
|
||||
+ await device.open();
|
||||
+ await device.selectConfiguration(3);
|
||||
+ await device.claimInterface(0);
|
||||
+ await device.selectAlternateInterface(0, 2);
|
||||
+ await device.close();
|
||||
+ },
|
||||
+ 'can select an alternate interface on a setting with non-sequential ' +
|
||||
+ 'alternative setting value');
|
||||
+
|
||||
usb_test(() => {
|
||||
return getFakeDevice().then(({ device }) => {
|
||||
return device.open()
|
||||
195
patches/chromium/cherry-pick-b03797bdb1df.patch
Normal file
195
patches/chromium/cherry-pick-b03797bdb1df.patch
Normal file
@@ -0,0 +1,195 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Xiaocheng Hu <xiaochengh@chromium.org>
|
||||
Date: Mon, 2 May 2022 23:43:40 +0000
|
||||
Subject: Markup sanitization should iterate until markup is stable
|
||||
|
||||
There are cases where parsing a markup and then serializing it does not
|
||||
round trip, which can be used to inject XSS. Current sanitization code
|
||||
only does one round of parsing and serializing, which does not remove
|
||||
XSS injections that hide deeper.
|
||||
|
||||
Hence this patch makes sanitization algorithm iterate until the markup
|
||||
is stable, or declares failure if it doesn't stabilize after many tries.
|
||||
|
||||
(cherry picked from commit 19280353fb92d0ff7d048d7cec28d6a23befbce0)
|
||||
|
||||
Fixed: 1315563
|
||||
Change-Id: I4a3ebe1fda6df0e04a24d863b2b48df2110af209
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3611826
|
||||
Commit-Queue: Xiaocheng Hu <xiaochengh@chromium.org>
|
||||
Reviewed-by: Yoshifumi Inoue <yosin@chromium.org>
|
||||
Cr-Original-Commit-Position: refs/heads/main@{#997032}
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3621618
|
||||
Auto-Submit: Xiaocheng Hu <xiaochengh@chromium.org>
|
||||
Reviewed-by: Joey Arhar <jarhar@chromium.org>
|
||||
Commit-Queue: Joey Arhar <jarhar@chromium.org>
|
||||
Cr-Commit-Position: refs/branch-heads/5005@{#363}
|
||||
Cr-Branched-From: 5b4d9450fee01f821b6400e947b3839727643a71-refs/heads/main@{#992738}
|
||||
|
||||
diff --git a/third_party/blink/renderer/core/editing/serializers/serialization.cc b/third_party/blink/renderer/core/editing/serializers/serialization.cc
|
||||
index 4ee332fa16a1bda54e6ba99c8063876fb046adaa..463fd9a37671b92c9af68ff5f3c0e8ddd5f1c62c 100644
|
||||
--- a/third_party/blink/renderer/core/editing/serializers/serialization.cc
|
||||
+++ b/third_party/blink/renderer/core/editing/serializers/serialization.cc
|
||||
@@ -835,6 +835,12 @@ static bool StripSVGUseDataURLs(Node& node) {
|
||||
return stripped;
|
||||
}
|
||||
|
||||
+namespace {
|
||||
+
|
||||
+constexpr unsigned kMaxSanitizationIterations = 16;
|
||||
+
|
||||
+} // namespace
|
||||
+
|
||||
DocumentFragment* CreateSanitizedFragmentFromMarkupWithContext(
|
||||
Document& document,
|
||||
const String& raw_markup,
|
||||
@@ -844,42 +850,56 @@ DocumentFragment* CreateSanitizedFragmentFromMarkupWithContext(
|
||||
if (raw_markup.IsEmpty())
|
||||
return nullptr;
|
||||
|
||||
- Document* staging_document = CreateStagingDocumentForMarkupSanitization(
|
||||
- *document.GetFrame()->GetFrameScheduler()->GetAgentGroupScheduler());
|
||||
- Element* body = staging_document->body();
|
||||
-
|
||||
- DocumentFragment* fragment = CreateFragmentFromMarkupWithContext(
|
||||
- *staging_document, raw_markup, fragment_start, fragment_end, KURL(),
|
||||
- kDisallowScriptingAndPluginContent);
|
||||
- if (!fragment) {
|
||||
- staging_document->GetPage()->WillBeDestroyed();
|
||||
- return nullptr;
|
||||
- }
|
||||
+ // Iterate on parsing, sanitization and serialization until the markup is
|
||||
+ // stable, or if we have exceeded the maximum allowed number of iterations.
|
||||
+ String last_markup;
|
||||
+ String markup = raw_markup;
|
||||
+ for (unsigned iteration = 0;
|
||||
+ iteration < kMaxSanitizationIterations && last_markup != markup;
|
||||
+ ++iteration) {
|
||||
+ last_markup = markup;
|
||||
+
|
||||
+ Document* staging_document = CreateStagingDocumentForMarkupSanitization(
|
||||
+ *document.GetFrame()->GetFrameScheduler()->GetAgentGroupScheduler());
|
||||
+ Element* body = staging_document->body();
|
||||
+
|
||||
+ DocumentFragment* fragment = CreateFragmentFromMarkupWithContext(
|
||||
+ *staging_document, last_markup, fragment_start, fragment_end, KURL(),
|
||||
+ kDisallowScriptingAndPluginContent);
|
||||
+ if (!fragment) {
|
||||
+ staging_document->GetPage()->WillBeDestroyed();
|
||||
+ return nullptr;
|
||||
+ }
|
||||
|
||||
- bool needs_sanitization = false;
|
||||
- if (ContainsStyleElements(*fragment))
|
||||
- needs_sanitization = true;
|
||||
- if (StripSVGUseDataURLs(*fragment))
|
||||
- needs_sanitization = true;
|
||||
+ bool needs_sanitization = false;
|
||||
+ if (ContainsStyleElements(*fragment))
|
||||
+ needs_sanitization = true;
|
||||
+ if (StripSVGUseDataURLs(*fragment))
|
||||
+ needs_sanitization = true;
|
||||
|
||||
- if (!needs_sanitization) {
|
||||
+ if (!needs_sanitization) {
|
||||
+ markup = CreateMarkup(fragment);
|
||||
+ } else {
|
||||
+ body->appendChild(fragment);
|
||||
+ staging_document->UpdateStyleAndLayout(DocumentUpdateReason::kEditing);
|
||||
+
|
||||
+ // This sanitizes stylesheets in the markup into element inline styles
|
||||
+ markup = CreateMarkup(Position::FirstPositionInNode(*body),
|
||||
+ Position::LastPositionInNode(*body),
|
||||
+ CreateMarkupOptions::Builder()
|
||||
+ .SetShouldAnnotateForInterchange(true)
|
||||
+ .SetIsForMarkupSanitization(true)
|
||||
+ .Build());
|
||||
+ }
|
||||
staging_document->GetPage()->WillBeDestroyed();
|
||||
- return CreateFragmentFromMarkupWithContext(
|
||||
- document, raw_markup, fragment_start, fragment_end, base_url,
|
||||
- kDisallowScriptingAndPluginContent);
|
||||
+
|
||||
+ fragment_start = 0;
|
||||
+ fragment_end = markup.length();
|
||||
}
|
||||
|
||||
- body->appendChild(fragment);
|
||||
- staging_document->UpdateStyleAndLayout(DocumentUpdateReason::kEditing);
|
||||
-
|
||||
- // This sanitizes stylesheets in the markup into element inline styles
|
||||
- String markup = CreateMarkup(Position::FirstPositionInNode(*body),
|
||||
- Position::LastPositionInNode(*body),
|
||||
- CreateMarkupOptions::Builder()
|
||||
- .SetShouldAnnotateForInterchange(true)
|
||||
- .SetIsForMarkupSanitization(true)
|
||||
- .Build());
|
||||
- staging_document->GetPage()->WillBeDestroyed();
|
||||
+ // Sanitization failed because markup can't stabilize.
|
||||
+ if (last_markup != markup)
|
||||
+ return nullptr;
|
||||
|
||||
return CreateFragmentFromMarkup(document, markup, base_url,
|
||||
kDisallowScriptingAndPluginContent);
|
||||
diff --git a/third_party/blink/web_tests/editing/pasteboard/paste-svg-use.html b/third_party/blink/web_tests/editing/pasteboard/paste-svg-use.html
|
||||
index c03ca90d492a5e2af883f68811baa7660ef1cdc2..1af77f8faa4501f577e28297f013e170775bc86a 100644
|
||||
--- a/third_party/blink/web_tests/editing/pasteboard/paste-svg-use.html
|
||||
+++ b/third_party/blink/web_tests/editing/pasteboard/paste-svg-use.html
|
||||
@@ -32,6 +32,6 @@ selection_test(
|
||||
<use href=data:application/xml;base64,PHN2ZyBpZD0neCcgeG1sbnM9J2h0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnJz4KPGEgaHJlZj0namF2YXNjcmlwdDphbGVydCgxMjMpJz4KICAgIDxyZWN0IHdpZHRoPScxMDAlJyBoZWlnaHQ9JzEwMCUnIGZpbGw9J2xpZ2h0Ymx1ZScgLz4KICAgICA8dGV4dCB4PScwJyB5PScwJyBmaWxsPSdibGFjayc+CiAgICAgICA8dHNwYW4geD0nMCcgZHk9JzEuMmVtJz5Pb3BzLCB0aGVyZSdzIHNvbWV0aGluZyB3cm9uZyB3aXRoIHRoZSBwYWdlITwvdHNwYW4+CiAgICAgPHRzcGFuIHg9JzAnIGR5PScxLjJlbSc+UGxlYXNlIGNsaWNrIGhlcmUgdG8gcmVsb2FkLjwvdHNwYW4+Cjwvc3ZnPg==#x>"></noscript>asdasd`);
|
||||
selection.document.execCommand('paste');
|
||||
},
|
||||
- '<div contenteditable>|<noscript><u title="</noscript><div contenteditable="false"><svg></svg></div></div>',
|
||||
+ '<div contenteditable><div><br></div><div> <u title="</div><div> </div><div> ">asdasd|</div></div>',
|
||||
'Paste blocks data URI in SVG use element injection via <noscript>');
|
||||
</script>
|
||||
diff --git a/third_party/blink/web_tests/external/wpt/clipboard-apis/async-navigator-clipboard-read-sanitize.https.html b/third_party/blink/web_tests/external/wpt/clipboard-apis/async-navigator-clipboard-read-sanitize.https.html
|
||||
new file mode 100644
|
||||
index 0000000000000000000000000000000000000000..9e0ab2ee740f85ea4e9de9d3f1d2ac43bee5a985
|
||||
--- /dev/null
|
||||
+++ b/third_party/blink/web_tests/external/wpt/clipboard-apis/async-navigator-clipboard-read-sanitize.https.html
|
||||
@@ -0,0 +1,44 @@
|
||||
+<!doctype html>
|
||||
+<meta charset="utf-8">
|
||||
+<title>Async Clipboard.read() should sanitize text/html</title>
|
||||
+<link rel="help" href="https://w3c.github.io/clipboard-apis/#dom-clipboard-read">
|
||||
+<link rel="help" href="https://bugs.chromium.org/p/chromium/issues/detail?id=1315563">
|
||||
+<script src="/resources/testharness.js"></script>
|
||||
+<script src="/resources/testharnessreport.js"></script>
|
||||
+<script src="/resources/testdriver.js"></script>
|
||||
+<script src="/resources/testdriver-vendor.js"></script>
|
||||
+
|
||||
+<p><button id="button">Put payload in the clipboard</button></p>
|
||||
+<div id="output"></div>
|
||||
+
|
||||
+<script>
|
||||
+let testFailed = false;
|
||||
+function fail() {
|
||||
+ testFailed = true;
|
||||
+}
|
||||
+
|
||||
+button.onclick = () => document.execCommand('copy');
|
||||
+document.oncopy = ev => {
|
||||
+ ev.preventDefault();
|
||||
+ ev.clipboardData.setData(
|
||||
+ 'text/html',
|
||||
+ `<form><math><mtext></form><form><mglyph><xmp></math><img src=invalid onerror=fail()></xmp>`);
|
||||
+};
|
||||
+
|
||||
+promise_test(async test => {
|
||||
+ await test_driver.set_permission({name: 'clipboard-read'}, 'granted');
|
||||
+ await test_driver.click(button);
|
||||
+
|
||||
+ const items = await navigator.clipboard.read();
|
||||
+ const htmlBlob = await items[0].getType("text/html");
|
||||
+ const html = await htmlBlob.text();
|
||||
+
|
||||
+ // This inserts an image with `onerror` handler if `html` is not properly sanitized
|
||||
+ output.innerHTML = html;
|
||||
+
|
||||
+ // Allow the 'error' event to be dispatched asynchronously
|
||||
+ await new Promise(resolve => test.step_timeout(resolve, 100));
|
||||
+
|
||||
+ assert_false(testFailed);
|
||||
+});
|
||||
+</script>
|
||||
160
patches/chromium/cherry-pick-ec0cce63f47d.patch
Normal file
160
patches/chromium/cherry-pick-ec0cce63f47d.patch
Normal file
@@ -0,0 +1,160 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Corentin Pescheloche <cpescheloche@fb.com>
|
||||
Date: Tue, 10 May 2022 14:05:53 +0000
|
||||
Subject: Cleanup profiler group detached profilers
|
||||
|
||||
ProfilerGroup keeps track of detached profilers to be able to gracefully
|
||||
stop leaked profilers when the corresponding ExecutionContext is
|
||||
destroyed.
|
||||
|
||||
(cherry picked from commit 9f9d5fd2f3085414fc8776bf556fb5c4fa2dac2c)
|
||||
|
||||
Change-Id: I4fdbbc3a5208819397d742c9ecbff117f839691c
|
||||
Bug: chromium:1297283
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3594570
|
||||
Commit-Queue: Corentin Pescheloche <cpescheloche@fb.com>
|
||||
Cr-Original-Commit-Position: refs/heads/main@{#994316}
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3620956
|
||||
Reviewed-by: Oleh Lamzin <lamzin@google.com>
|
||||
Owners-Override: Oleh Lamzin <lamzin@google.com>
|
||||
Commit-Queue: Roger Felipe Zanoni da Silva <rzanoni@google.com>
|
||||
Auto-Submit: Roger Felipe Zanoni da Silva <rzanoni@google.com>
|
||||
Cr-Commit-Position: refs/branch-heads/4664@{#1629}
|
||||
Cr-Branched-From: 24dc4ee75e01a29d390d43c9c264372a169273a7-refs/heads/main@{#929512}
|
||||
|
||||
diff --git a/third_party/blink/renderer/core/timing/profiler_group.cc b/third_party/blink/renderer/core/timing/profiler_group.cc
|
||||
index 6638ee38519674036c6c45cf6cd1a4eff023289b..f498a122f5a491226720a36dc729364028148eaa 100644
|
||||
--- a/third_party/blink/renderer/core/timing/profiler_group.cc
|
||||
+++ b/third_party/blink/renderer/core/timing/profiler_group.cc
|
||||
@@ -110,8 +110,7 @@ ProfilerGroup::ProfilerGroup(v8::Isolate* isolate)
|
||||
: isolate_(isolate),
|
||||
cpu_profiler_(nullptr),
|
||||
next_profiler_id_(0),
|
||||
- num_active_profilers_(0) {
|
||||
-}
|
||||
+ num_active_profilers_(0) {}
|
||||
|
||||
void DiscardedSamplesDelegate::Notify() {
|
||||
if (profiler_group_) {
|
||||
@@ -234,6 +233,8 @@ void ProfilerGroup::WillBeDestroyed() {
|
||||
DCHECK(!profilers_.Contains(profiler));
|
||||
}
|
||||
|
||||
+ StopDetachedProfilers();
|
||||
+
|
||||
if (cpu_profiler_)
|
||||
TeardownV8Profiler();
|
||||
}
|
||||
@@ -304,18 +305,49 @@ void ProfilerGroup::CancelProfiler(Profiler* profiler) {
|
||||
|
||||
void ProfilerGroup::CancelProfilerAsync(ScriptState* script_state,
|
||||
Profiler* profiler) {
|
||||
+ DCHECK(IsMainThread());
|
||||
DCHECK(cpu_profiler_);
|
||||
DCHECK(!profiler->stopped());
|
||||
profilers_.erase(profiler);
|
||||
|
||||
+ // register the profiler to be cleaned up in case its associated context
|
||||
+ // gets destroyed before the cleanup task is executed.
|
||||
+ detached_profiler_ids_.push_back(profiler->ProfilerId());
|
||||
+
|
||||
// Since it's possible for the profiler to get destructed along with its
|
||||
// associated context, dispatch a task to cleanup context-independent isolate
|
||||
// resources (rather than use the context's task runner).
|
||||
ThreadScheduler::Current()->V8TaskRunner()->PostTask(
|
||||
- FROM_HERE, WTF::Bind(&ProfilerGroup::CancelProfilerImpl,
|
||||
+ FROM_HERE, WTF::Bind(&ProfilerGroup::StopDetachedProfiler,
|
||||
WrapPersistent(this), profiler->ProfilerId()));
|
||||
}
|
||||
|
||||
+void ProfilerGroup::StopDetachedProfiler(String profiler_id) {
|
||||
+ DCHECK(IsMainThread());
|
||||
+
|
||||
+ // we use a vector instead of a map because the expected number of profiler
|
||||
+ // is expected to be very small
|
||||
+ auto* it = std::find(detached_profiler_ids_.begin(),
|
||||
+ detached_profiler_ids_.end(), profiler_id);
|
||||
+
|
||||
+ if (it == detached_profiler_ids_.end()) {
|
||||
+ // Profiler already stopped
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
+ CancelProfilerImpl(profiler_id);
|
||||
+ detached_profiler_ids_.erase(it);
|
||||
+}
|
||||
+
|
||||
+void ProfilerGroup::StopDetachedProfilers() {
|
||||
+ DCHECK(IsMainThread());
|
||||
+
|
||||
+ for (auto& detached_profiler_id : detached_profiler_ids_) {
|
||||
+ CancelProfilerImpl(detached_profiler_id);
|
||||
+ }
|
||||
+ detached_profiler_ids_.clear();
|
||||
+}
|
||||
+
|
||||
void ProfilerGroup::CancelProfilerImpl(String profiler_id) {
|
||||
if (!cpu_profiler_)
|
||||
return;
|
||||
diff --git a/third_party/blink/renderer/core/timing/profiler_group.h b/third_party/blink/renderer/core/timing/profiler_group.h
|
||||
index 2cdbd795f4265086073b8c378ede4f7c6c60e3e3..ede25fa5656f32d1982077eda43585b70743fd63 100644
|
||||
--- a/third_party/blink/renderer/core/timing/profiler_group.h
|
||||
+++ b/third_party/blink/renderer/core/timing/profiler_group.h
|
||||
@@ -81,6 +81,10 @@ class CORE_EXPORT ProfilerGroup
|
||||
// Internal implementation of cancel.
|
||||
void CancelProfilerImpl(String profiler_id);
|
||||
|
||||
+ // Clean context independent resources for leaked profilers
|
||||
+ void StopDetachedProfiler(String profiler_id);
|
||||
+ void StopDetachedProfilers();
|
||||
+
|
||||
// Generates an unused string identifier to use for a new profiling session.
|
||||
String NextProfilerId();
|
||||
|
||||
@@ -88,9 +92,11 @@ class CORE_EXPORT ProfilerGroup
|
||||
v8::CpuProfiler* cpu_profiler_;
|
||||
int next_profiler_id_;
|
||||
int num_active_profilers_;
|
||||
-
|
||||
HeapHashSet<WeakMember<Profiler>> profilers_;
|
||||
|
||||
+ // Store the ids of leaked collected profilers that needs to be stopped
|
||||
+ Vector<String> detached_profiler_ids_;
|
||||
+
|
||||
// A set of observers, one for each ExecutionContext that has profiling
|
||||
// enabled.
|
||||
HeapHashSet<Member<ProfilingContextObserver>> context_observers_;
|
||||
diff --git a/third_party/blink/renderer/core/timing/profiler_group_test.cc b/third_party/blink/renderer/core/timing/profiler_group_test.cc
|
||||
index adedff31f007ca2deff401ec93b39641f4ea516e..1c6dd092c36a27710085a03c74fa12e212adccb4 100644
|
||||
--- a/third_party/blink/renderer/core/timing/profiler_group_test.cc
|
||||
+++ b/third_party/blink/renderer/core/timing/profiler_group_test.cc
|
||||
@@ -262,4 +262,29 @@ TEST(ProfilerGroupTest, LeakProfilerWithContext) {
|
||||
test::RunPendingTasks();
|
||||
}
|
||||
|
||||
+// Tests that a ProfilerGroup doesn't crash if the ProfilerGroup is destroyed
|
||||
+// before a Profiler::Dispose is ran.
|
||||
+TEST(ProfilerGroupTest, Bug1297283) {
|
||||
+ {
|
||||
+ V8TestingScope scope;
|
||||
+ ProfilerGroup* profiler_group = ProfilerGroup::From(scope.GetIsolate());
|
||||
+ profiler_group->OnProfilingContextAdded(scope.GetExecutionContext());
|
||||
+
|
||||
+ ProfilerInitOptions* init_options = ProfilerInitOptions::Create();
|
||||
+ init_options->setSampleInterval(0);
|
||||
+ init_options->setMaxBufferSize(0);
|
||||
+ Profiler* profiler = profiler_group->CreateProfiler(
|
||||
+ scope.GetScriptState(), *init_options, base::TimeTicks(),
|
||||
+ scope.GetExceptionState());
|
||||
+ EXPECT_FALSE(profiler->stopped());
|
||||
+
|
||||
+ // Force a collection of the underlying Profiler
|
||||
+ profiler = nullptr;
|
||||
+ ThreadState::Current()->CollectAllGarbageForTesting();
|
||||
+ // Exit Scope deallocating Context triggering ProfilerGroup::WillBeDestroyed
|
||||
+ // Ensure doesn't crash.
|
||||
+ }
|
||||
+ test::RunPendingTasks();
|
||||
+}
|
||||
+
|
||||
} // namespace blink
|
||||
68
patches/chromium/cherry-pick-f1504440487f.patch
Normal file
68
patches/chromium/cherry-pick-f1504440487f.patch
Normal file
@@ -0,0 +1,68 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Justin Novosad <junov@chromium.org>
|
||||
Date: Thu, 2 Jun 2022 19:35:57 +0000
|
||||
Subject: PaintOpReader: Harden PaintImage deserialization
|
||||
|
||||
This fix prevents the deserialization of PaintImage pixel data from
|
||||
reading data out of bounds when the block of serialized pixel data isn't
|
||||
large enough to cover the expected amount of data, given the size and
|
||||
format of the image.
|
||||
|
||||
(cherry picked from commit e89ea1489429a9a9e49e70d5d4e8d018fbafb6ac)
|
||||
|
||||
Bug: 1325298
|
||||
Change-Id: Icbeb405d2031d7d8ce4537836d7996ce7885f6d1
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3669596
|
||||
Commit-Queue: Justin Novosad <junov@chromium.org>
|
||||
Reviewed-by: Jonathan Ross <jonross@chromium.org>
|
||||
Cr-Original-Commit-Position: refs/heads/main@{#1007804}
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3687975
|
||||
Bot-Commit: Rubber Stamper <rubber-stamper@appspot.gserviceaccount.com>
|
||||
Reviewed-by: Justin Novosad <junov@chromium.org>
|
||||
Auto-Submit: Srinivas Sista <srinivassista@chromium.org>
|
||||
Commit-Queue: Srinivas Sista <srinivassista@chromium.org>
|
||||
Cr-Commit-Position: refs/branch-heads/5005@{#1093}
|
||||
Cr-Branched-From: 5b4d9450fee01f821b6400e947b3839727643a71-refs/heads/main@{#992738}
|
||||
|
||||
diff --git a/cc/paint/paint_op_reader.cc b/cc/paint/paint_op_reader.cc
|
||||
index d71230cfc47944ca538ec8e007f652640e752b63..e34a5fb540dfa2626ab4d0a655e4ba85aa2b8921 100644
|
||||
--- a/cc/paint/paint_op_reader.cc
|
||||
+++ b/cc/paint/paint_op_reader.cc
|
||||
@@ -329,6 +329,10 @@ void PaintOpReader::Read(PaintImage* image) {
|
||||
|
||||
SkImageInfo image_info =
|
||||
SkImageInfo::Make(width, height, color_type, kPremul_SkAlphaType);
|
||||
+ if (pixel_size < image_info.computeMinByteSize()) {
|
||||
+ SetInvalid(DeserializationError::kInsufficientPixelData);
|
||||
+ return;
|
||||
+ }
|
||||
const volatile void* pixel_data = ExtractReadableMemory(pixel_size);
|
||||
if (!valid_)
|
||||
return;
|
||||
diff --git a/cc/paint/paint_op_reader.h b/cc/paint/paint_op_reader.h
|
||||
index 201cdfde5eea3a07e31a3d6a50a5119485d5c1fc..af784145a9365ea2f776a1020145c0b83c63f16d 100644
|
||||
--- a/cc/paint/paint_op_reader.h
|
||||
+++ b/cc/paint/paint_op_reader.h
|
||||
@@ -180,8 +180,9 @@ class CC_PAINT_EXPORT PaintOpReader {
|
||||
kSharedImageProviderNoAccess = 50,
|
||||
kSharedImageProviderSkImageCreationFailed = 51,
|
||||
kZeroSkColorFilterBytes = 52,
|
||||
+ kInsufficientPixelData = 53,
|
||||
|
||||
- kMaxValue = kZeroSkColorFilterBytes,
|
||||
+ kMaxValue = kInsufficientPixelData
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
diff --git a/tools/metrics/histograms/enums.xml b/tools/metrics/histograms/enums.xml
|
||||
index 5faaf3cfd3c0231ad34f651023aeec5d74d9c19b..e15f292c099cfc8bf9cb8613f73517f2f241d91f 100644
|
||||
--- a/tools/metrics/histograms/enums.xml
|
||||
+++ b/tools/metrics/histograms/enums.xml
|
||||
@@ -66406,6 +66406,7 @@ Called by update_net_trust_anchors.py.-->
|
||||
<int value="50" label="SharedImageProvider no access"/>
|
||||
<int value="51" label="SharedImageProvider SkImage creation failed"/>
|
||||
<int value="52" label="Zero SkColorFilter bytes"/>
|
||||
+ <int value="53" label="Insufficient Pixel Data"/>
|
||||
</enum>
|
||||
|
||||
<enum name="PaletteModeCancelType">
|
||||
229
patches/chromium/cherry-pick-f1dd785e021e.patch
Normal file
229
patches/chromium/cherry-pick-f1dd785e021e.patch
Normal file
@@ -0,0 +1,229 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Austin Sullivan <asully@chromium.org>
|
||||
Date: Mon, 16 May 2022 18:20:27 +0000
|
||||
Subject: M102: FSA: Sanitize .scf files
|
||||
|
||||
.scf files can be used to execute code without opening the file.
|
||||
Sanitize these files the same way we sanitize .lnk files.
|
||||
|
||||
Also updates filename sanitization logic to be consistent in blocking
|
||||
.lnk and .local extensions on all OSes.
|
||||
|
||||
(cherry picked from commit 988164c6c4a563c3d4c0dedba295d09472dfc15f)
|
||||
|
||||
Bug: 1227995
|
||||
Change-Id: I4b018f1ba524c783547e18630db9addc9fb126e6
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3089422
|
||||
Reviewed-by: Marijn Kruisselbrink <mek@chromium.org>
|
||||
Commit-Queue: Marijn Kruisselbrink <mek@chromium.org>
|
||||
Cr-Original-Commit-Position: refs/heads/main@{#1002147}
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3648322
|
||||
Auto-Submit: Austin Sullivan <asully@chromium.org>
|
||||
Commit-Queue: Austin Sullivan <asully@chromium.org>
|
||||
Cr-Commit-Position: refs/branch-heads/5005@{#759}
|
||||
Cr-Branched-From: 5b4d9450fee01f821b6400e947b3839727643a71-refs/heads/main@{#992738}
|
||||
|
||||
diff --git a/content/browser/file_system_access/file_system_access_directory_handle_impl.cc b/content/browser/file_system_access/file_system_access_directory_handle_impl.cc
|
||||
index 22e0fa6d237bda2819916d630a4de5583e56fe10..b6e3c97f044e1babbf8489b95e6db311ae8385b6 100644
|
||||
--- a/content/browser/file_system_access/file_system_access_directory_handle_impl.cc
|
||||
+++ b/content/browser/file_system_access/file_system_access_directory_handle_impl.cc
|
||||
@@ -438,10 +438,13 @@ namespace {
|
||||
bool IsShellIntegratedExtension(const base::FilePath::StringType& extension) {
|
||||
base::FilePath::StringType extension_lower = base::ToLowerASCII(extension);
|
||||
|
||||
- // .lnk files may be used to execute arbitrary code (see
|
||||
- // https://nvd.nist.gov/vuln/detail/CVE-2010-2568).
|
||||
- if (extension_lower == FILE_PATH_LITERAL("lnk"))
|
||||
+ // .lnk and .scf files may be used to execute arbitrary code (see
|
||||
+ // https://nvd.nist.gov/vuln/detail/CVE-2010-2568 and
|
||||
+ // https://crbug.com/1227995, respectively).
|
||||
+ if (extension_lower == FILE_PATH_LITERAL("lnk") ||
|
||||
+ extension_lower == FILE_PATH_LITERAL("scf")) {
|
||||
return true;
|
||||
+ }
|
||||
|
||||
// Setting a file's extension to a CLSID may conceal its actual file type on
|
||||
// some Windows versions (see https://nvd.nist.gov/vuln/detail/CVE-2004-0420).
|
||||
diff --git a/content/browser/file_system_access/file_system_access_manager_impl.cc b/content/browser/file_system_access/file_system_access_manager_impl.cc
|
||||
index ac3fc8ceade37805dafcafd0b9e44eb2a196513a..e2b13687d664b0ee29c320d89cc6ee00d6134717 100644
|
||||
--- a/content/browser/file_system_access/file_system_access_manager_impl.cc
|
||||
+++ b/content/browser/file_system_access/file_system_access_manager_impl.cc
|
||||
@@ -517,6 +517,16 @@ void FileSystemAccessManagerImpl::SetDefaultPathAndShowPicker(
|
||||
suggested_name_path =
|
||||
net::GenerateFileName(GURL(), std::string(), std::string(),
|
||||
suggested_name, std::string(), std::string());
|
||||
+
|
||||
+ auto suggested_extension = suggested_name_path.Extension();
|
||||
+ // Our version of `IsShellIntegratedExtension()` is more stringent than
|
||||
+ // the version used in `net::GenerateFileName()`. See
|
||||
+ // `FileSystemChooser::IsShellIntegratedExtension()` for details.
|
||||
+ if (FileSystemChooser::IsShellIntegratedExtension(suggested_extension)) {
|
||||
+ suggested_extension = FILE_PATH_LITERAL("download");
|
||||
+ suggested_name_path =
|
||||
+ suggested_name_path.ReplaceExtension(suggested_extension);
|
||||
+ }
|
||||
}
|
||||
|
||||
FileSystemChooser::Options file_system_chooser_options(
|
||||
diff --git a/content/browser/file_system_access/file_system_chooser.cc b/content/browser/file_system_access/file_system_chooser.cc
|
||||
index 6c5665aff03c28b8d4699aafcfda48648db3f47d..2f9d3b4dc999bbc7ddb16c05f2f1dd3ec12f6e15 100644
|
||||
--- a/content/browser/file_system_access/file_system_chooser.cc
|
||||
+++ b/content/browser/file_system_access/file_system_chooser.cc
|
||||
@@ -71,33 +71,6 @@ base::FilePath::StringType GetLastExtension(
|
||||
: extension;
|
||||
}
|
||||
|
||||
-// Returns whether the specified extension receives special handling by the
|
||||
-// Windows shell.
|
||||
-bool IsShellIntegratedExtension(const base::FilePath::StringType& extension) {
|
||||
- // TODO(https://crbug.com/1154757): Figure out some way to unify this with
|
||||
- // net::IsSafePortablePathComponent, with the result probably ending up in
|
||||
- // base/i18n/file_util_icu.h.
|
||||
- base::FilePath::StringType extension_lower = base::ToLowerASCII(extension);
|
||||
-
|
||||
- // .lnk files may be used to execute arbitrary code (see
|
||||
- // https://nvd.nist.gov/vuln/detail/CVE-2010-2568). .local files are used by
|
||||
- // Windows to determine which DLLs to load for an application.
|
||||
- if ((extension_lower == FILE_PATH_LITERAL("local")) ||
|
||||
- (extension_lower == FILE_PATH_LITERAL("lnk"))) {
|
||||
- return true;
|
||||
- }
|
||||
-
|
||||
- // Setting a file's extension to a CLSID may conceal its actual file type on
|
||||
- // some Windows versions (see https://nvd.nist.gov/vuln/detail/CVE-2004-0420).
|
||||
- if (!extension_lower.empty() &&
|
||||
- (extension_lower.front() == FILE_PATH_LITERAL('{')) &&
|
||||
- (extension_lower.back() == FILE_PATH_LITERAL('}'))) {
|
||||
- return true;
|
||||
- }
|
||||
-
|
||||
- return false;
|
||||
-}
|
||||
-
|
||||
// Extension validation primarily takes place in the renderer. This checks for a
|
||||
// subset of invalid extensions in the event the renderer is compromised.
|
||||
bool IsInvalidExtension(base::FilePath::StringType& extension) {
|
||||
@@ -105,7 +78,7 @@ bool IsInvalidExtension(base::FilePath::StringType& extension) {
|
||||
auto extension16 = base::UTF8ToUTF16(component8);
|
||||
|
||||
return !base::i18n::IsFilenameLegal(extension16) ||
|
||||
- IsShellIntegratedExtension(GetLastExtension(extension));
|
||||
+ FileSystemChooser::IsShellIntegratedExtension(extension);
|
||||
}
|
||||
|
||||
// Converts the accepted mime types and extensions from `option` into a list
|
||||
@@ -290,6 +263,40 @@ void FileSystemChooser::CreateAndShow(
|
||||
/*params=*/nullptr);
|
||||
}
|
||||
|
||||
+// static
|
||||
+bool FileSystemChooser::IsShellIntegratedExtension(
|
||||
+ const base::FilePath::StringType& extension) {
|
||||
+ // TODO(https://crbug.com/1154757): Figure out some way to unify this with
|
||||
+ // net::IsSafePortablePathComponent, with the result probably ending up in
|
||||
+ // base/i18n/file_util_icu.h.
|
||||
+ // - For the sake of consistency across platforms, we sanitize '.lnk' and
|
||||
+ // '.local' files on all platforms (not just Windows)
|
||||
+ // - There are some extensions (i.e. '.scf') we would like to sanitize which
|
||||
+ // `net::GenerateFileName()` does not
|
||||
+ base::FilePath::StringType extension_lower =
|
||||
+ base::ToLowerASCII(GetLastExtension(extension));
|
||||
+
|
||||
+ // .lnk and .scf files may be used to execute arbitrary code (see
|
||||
+ // https://nvd.nist.gov/vuln/detail/CVE-2010-2568 and
|
||||
+ // https://crbug.com/1227995, respectively). .local files are used by Windows
|
||||
+ // to determine which DLLs to load for an application.
|
||||
+ if ((extension_lower == FILE_PATH_LITERAL("lnk")) ||
|
||||
+ (extension_lower == FILE_PATH_LITERAL("local")) ||
|
||||
+ (extension_lower == FILE_PATH_LITERAL("scf"))) {
|
||||
+ return true;
|
||||
+ }
|
||||
+
|
||||
+ // Setting a file's extension to a CLSID may conceal its actual file type on
|
||||
+ // some Windows versions (see https://nvd.nist.gov/vuln/detail/CVE-2004-0420).
|
||||
+ if (!extension_lower.empty() &&
|
||||
+ (extension_lower.front() == FILE_PATH_LITERAL('{')) &&
|
||||
+ (extension_lower.back() == FILE_PATH_LITERAL('}'))) {
|
||||
+ return true;
|
||||
+ }
|
||||
+
|
||||
+ return false;
|
||||
+}
|
||||
+
|
||||
FileSystemChooser::FileSystemChooser(ui::SelectFileDialog::Type type,
|
||||
ResultCallback callback,
|
||||
base::ScopedClosureRunner fullscreen_block)
|
||||
diff --git a/content/browser/file_system_access/file_system_chooser.h b/content/browser/file_system_access/file_system_chooser.h
|
||||
index 07c8e7fda7d96496f58ed9a9e6cba6558c8c37df..925df7f5ef1d1bb94926afbe29beda248ae5aabc 100644
|
||||
--- a/content/browser/file_system_access/file_system_chooser.h
|
||||
+++ b/content/browser/file_system_access/file_system_chooser.h
|
||||
@@ -68,6 +68,12 @@ class CONTENT_EXPORT FileSystemChooser : public ui::SelectFileDialog::Listener {
|
||||
ResultCallback callback,
|
||||
base::ScopedClosureRunner fullscreen_block);
|
||||
|
||||
+ // Returns whether the specified extension receives special handling by the
|
||||
+ // Windows shell. These extensions should be sanitized before being shown in
|
||||
+ // the "save as" file picker.
|
||||
+ static bool IsShellIntegratedExtension(
|
||||
+ const base::FilePath::StringType& extension);
|
||||
+
|
||||
FileSystemChooser(ui::SelectFileDialog::Type type,
|
||||
ResultCallback callback,
|
||||
base::ScopedClosureRunner fullscreen_block);
|
||||
diff --git a/content/browser/file_system_access/file_system_chooser_browsertest.cc b/content/browser/file_system_access/file_system_chooser_browsertest.cc
|
||||
index b5bebd08526f684337194a8cc0f08a0b345a65a7..6033251755d68d83bc5c8300630eaebacbd2f3ce 100644
|
||||
--- a/content/browser/file_system_access/file_system_chooser_browsertest.cc
|
||||
+++ b/content/browser/file_system_access/file_system_chooser_browsertest.cc
|
||||
@@ -1557,21 +1557,28 @@ IN_PROC_BROWSER_TEST_F(FileSystemChooserBrowserTest, SuggestedName) {
|
||||
"not_matching.jpg", false});
|
||||
|
||||
#if defined(OS_WIN)
|
||||
- // ".local" and ".lnk" extensions should be sanitized on Windows.
|
||||
+ // ".lnk", ".local", and ".scf" extensions should be sanitized.
|
||||
name_infos.push_back({"dangerous_extension.local", ListValueOf(".local"),
|
||||
true, "dangerous_extension.download", false});
|
||||
name_infos.push_back({"dangerous_extension.lnk", ListValueOf(".lnk"), true,
|
||||
"dangerous_extension.download", false});
|
||||
-#else
|
||||
- // ".local" and ".lnk" extensions should be allowed on other OSes.
|
||||
- // TODO(https://crbug.com/1154757): `expected_exclude_accept_all_option` is
|
||||
- // false here because ".local" and ".lnk" extensions are not allowed in
|
||||
- // `accepts`, but are only sanitized by net::GenerateSafeFileName on Windows.
|
||||
- name_infos.push_back({"dangerous_extension.local", ListValueOf(".local"),
|
||||
- true, "dangerous_extension.local", false});
|
||||
- name_infos.push_back({"dangerous_extension.lnk", ListValueOf(".lnk"), true,
|
||||
- "dangerous_extension.lnk", false});
|
||||
-#endif
|
||||
+ name_infos.push_back({"dangerous_extension.scf", ListValueOf(".scf"), true,
|
||||
+ "dangerous_extension.download", false});
|
||||
+ // Compound extensions ending in a dangerous extension should be sanitized.
|
||||
+ name_infos.push_back({"dangerous_extension.png.local", ListValueOf(".local"),
|
||||
+ true, "dangerous_extension.png.download", false});
|
||||
+ name_infos.push_back({"dangerous_extension.png.lnk", ListValueOf(".lnk"),
|
||||
+ true, "dangerous_extension.png.download", false});
|
||||
+ name_infos.push_back({"dangerous_extension.png.scf", ListValueOf(".scf"),
|
||||
+ true, "dangerous_extension.png.download", false});
|
||||
+ // Compound extensions not ending in a dangerous extension should not be
|
||||
+ // sanitized.
|
||||
+ name_infos.push_back({"dangerous_extension.local.png", ListValueOf(".png"),
|
||||
+ true, "dangerous_extension.local.png", true});
|
||||
+ name_infos.push_back({"dangerous_extension.lnk.png", ListValueOf(".png"),
|
||||
+ true, "dangerous_extension.lnk.png", true});
|
||||
+ name_infos.push_back({"dangerous_extension.scf.png", ListValueOf(".png"),
|
||||
+ true, "dangerous_extension.scf.png", true});
|
||||
// Invalid characters should be sanitized.
|
||||
name_infos.push_back({R"(inv*l:d\\ch%rבאמת!a<ters🤓.txt)",
|
||||
ListValueOf(".txt"), true,
|
||||
diff --git a/content/browser/file_system_access/file_system_chooser_unittest.cc b/content/browser/file_system_access/file_system_chooser_unittest.cc
|
||||
index 373de41cf5ddead27b5e036c1cc14448a731250a..9b27d6305bd00a19d94b5ec49f21a7ecff7ddc48 100644
|
||||
--- a/content/browser/file_system_access/file_system_chooser_unittest.cc
|
||||
+++ b/content/browser/file_system_access/file_system_chooser_unittest.cc
|
||||
@@ -189,7 +189,7 @@ TEST_F(FileSystemChooserTest, IgnoreShellIntegratedExtensions) {
|
||||
accepts.emplace_back(blink::mojom::ChooseFileSystemEntryAcceptsOption::New(
|
||||
u"", std::vector<std::string>({}),
|
||||
std::vector<std::string>(
|
||||
- {"lnk", "foo.lnk", "foo.bar.local", "text", "local"})));
|
||||
+ {"lnk", "foo.lnk", "foo.bar.local", "text", "local", "scf"})));
|
||||
SyncShowDialog(std::move(accepts), /*include_accepts_all=*/false);
|
||||
|
||||
ASSERT_TRUE(dialog_params.file_types);
|
||||
123
patches/chromium/cherry-pick-f3d01ff794dc.patch
Normal file
123
patches/chromium/cherry-pick-f3d01ff794dc.patch
Normal file
@@ -0,0 +1,123 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Alvin Ji <alvinji@chromium.org>
|
||||
Date: Thu, 28 Apr 2022 00:44:28 +0000
|
||||
Subject: Introduce isLowEnergyDevice() for safely downward static_cast from
|
||||
BluetoothDeviceMac to BluetoothLowEnergyDeviceMac
|
||||
|
||||
device/bluetooth/bluetooth_adapter_mac.mm has two non safely downward static_cast BluetoothDevice to BluetoothLowEnergyDeviceMac
|
||||
|
||||
To avoid it, we introduce isLowEnergyDevice() to BluetoothDeviceMac so we could identify LE bluetooth device from classic bluetooth device then safely cast it downward.
|
||||
|
||||
(cherry picked from commit 2582158fc555edee390a050a64c1b89994a6b349)
|
||||
|
||||
Bug: 1318610
|
||||
Change-Id: Iaf082fc2c40270237bbc0b000b80faa7f94b1026
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3601727
|
||||
Reviewed-by: Reilly Grant <reillyg@chromium.org>
|
||||
Commit-Queue: Alvin Ji <alvinji@chromium.org>
|
||||
Cr-Original-Commit-Position: refs/heads/main@{#995419}
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3606585
|
||||
Bot-Commit: Rubber Stamper <rubber-stamper@appspot.gserviceaccount.com>
|
||||
Cr-Commit-Position: refs/branch-heads/5005@{#217}
|
||||
Cr-Branched-From: 5b4d9450fee01f821b6400e947b3839727643a71-refs/heads/main@{#992738}
|
||||
|
||||
diff --git a/device/bluetooth/bluetooth_adapter_mac.mm b/device/bluetooth/bluetooth_adapter_mac.mm
|
||||
index 902e77ce90a60c835a9a324decf3d0dd094f1c85..947dec239a51d3965de69d99e509931f27811c33 100644
|
||||
--- a/device/bluetooth/bluetooth_adapter_mac.mm
|
||||
+++ b/device/bluetooth/bluetooth_adapter_mac.mm
|
||||
@@ -764,6 +764,11 @@ CBCentralManagerState GetCBManagerState(CBCentralManager* manager) {
|
||||
DVLOG(1)
|
||||
<< "Central no longer powered on. Notifying of device disconnection.";
|
||||
for (BluetoothDevice* device : GetDevices()) {
|
||||
+ // GetDevices() returns instances of BluetoothClassicDeviceMac and
|
||||
+ // BluetoothLowEnergyDeviceMac. The DidDisconnectPeripheral() method is
|
||||
+ // only available on BluetoothLowEnergyDeviceMac.
|
||||
+ if (!static_cast<BluetoothDeviceMac*>(device)->IsLowEnergyDevice())
|
||||
+ continue;
|
||||
BluetoothLowEnergyDeviceMac* device_mac =
|
||||
static_cast<BluetoothLowEnergyDeviceMac*>(device);
|
||||
if (device_mac->IsGattConnected()) {
|
||||
@@ -901,9 +906,16 @@ CBCentralManagerState GetCBManagerState(CBCentralManager* manager) {
|
||||
BluetoothLowEnergyDeviceMac::GetPeripheralHashAddress(peripheral);
|
||||
auto iter = devices_.find(device_address);
|
||||
if (iter == devices_.end()) {
|
||||
- return nil;
|
||||
- }
|
||||
- return static_cast<BluetoothLowEnergyDeviceMac*>(iter->second.get());
|
||||
+ return nullptr;
|
||||
+ }
|
||||
+ // device_mac can be BluetoothClassicDeviceMac* or
|
||||
+ // BluetoothLowEnergyDeviceMac* To return valid BluetoothLowEnergyDeviceMac*
|
||||
+ // we need to first check with IsLowEnergyDevice()
|
||||
+ BluetoothDeviceMac* device_mac =
|
||||
+ static_cast<BluetoothDeviceMac*>(iter->second.get());
|
||||
+ return device_mac->IsLowEnergyDevice()
|
||||
+ ? static_cast<BluetoothLowEnergyDeviceMac*>(device_mac)
|
||||
+ : nullptr;
|
||||
}
|
||||
|
||||
bool BluetoothAdapterMac::DoesCollideWithKnownDevice(
|
||||
diff --git a/device/bluetooth/bluetooth_classic_device_mac.h b/device/bluetooth/bluetooth_classic_device_mac.h
|
||||
index b11dbbdec75ca276c6e9df50a00e4e3a97d5be8c..a7deb96690e2b64ed82ede5ade5591935ec0f308 100644
|
||||
--- a/device/bluetooth/bluetooth_classic_device_mac.h
|
||||
+++ b/device/bluetooth/bluetooth_classic_device_mac.h
|
||||
@@ -82,6 +82,7 @@ class BluetoothClassicDeviceMac : public BluetoothDeviceMac {
|
||||
// Returns the Bluetooth address for the |device|. The returned address has a
|
||||
// normalized format (see below).
|
||||
static std::string GetDeviceAddress(IOBluetoothDevice* device);
|
||||
+ bool IsLowEnergyDevice() override;
|
||||
|
||||
protected:
|
||||
// BluetoothDevice override
|
||||
diff --git a/device/bluetooth/bluetooth_classic_device_mac.mm b/device/bluetooth/bluetooth_classic_device_mac.mm
|
||||
index 3794ce8d808fe611f73d76177f0eb6890fc038c2..e98d27462abdfe080129026c58cf74fd1807914e 100644
|
||||
--- a/device/bluetooth/bluetooth_classic_device_mac.mm
|
||||
+++ b/device/bluetooth/bluetooth_classic_device_mac.mm
|
||||
@@ -296,4 +296,8 @@ BluetoothUUID ExtractUuid(IOBluetoothSDPDataElement* service_class_data) {
|
||||
base::SysNSStringToUTF8([device addressString]));
|
||||
}
|
||||
|
||||
+bool BluetoothClassicDeviceMac::IsLowEnergyDevice() {
|
||||
+ return false;
|
||||
+}
|
||||
+
|
||||
} // namespace device
|
||||
diff --git a/device/bluetooth/bluetooth_device_mac.h b/device/bluetooth/bluetooth_device_mac.h
|
||||
index 10245db6516b08a8e50e6637011a3a960440625c..0213e20aee170aae0a4b73e93f47c418110ef289 100644
|
||||
--- a/device/bluetooth/bluetooth_device_mac.h
|
||||
+++ b/device/bluetooth/bluetooth_device_mac.h
|
||||
@@ -30,6 +30,7 @@ class DEVICE_BLUETOOTH_EXPORT BluetoothDeviceMac : public BluetoothDevice {
|
||||
BluetoothGattService::GattErrorCode error_code);
|
||||
static BluetoothGattService::GattErrorCode GetGattErrorCodeFromNSError(
|
||||
NSError* error);
|
||||
+ virtual bool IsLowEnergyDevice() = 0;
|
||||
|
||||
protected:
|
||||
BluetoothDeviceMac(BluetoothAdapterMac* adapter);
|
||||
diff --git a/device/bluetooth/bluetooth_low_energy_device_mac.h b/device/bluetooth/bluetooth_low_energy_device_mac.h
|
||||
index 75988caca296d7f6d766a35f60f2ee1d6cec2246..05d3d514039df5db84d311471d58c2005b3db08f 100644
|
||||
--- a/device/bluetooth/bluetooth_low_energy_device_mac.h
|
||||
+++ b/device/bluetooth/bluetooth_low_energy_device_mac.h
|
||||
@@ -83,6 +83,7 @@ class DEVICE_BLUETOOTH_EXPORT BluetoothLowEnergyDeviceMac
|
||||
const device::BluetoothUUID& uuid,
|
||||
ConnectToServiceCallback callback,
|
||||
ConnectToServiceErrorCallback error_callback) override;
|
||||
+ bool IsLowEnergyDevice() override;
|
||||
|
||||
protected:
|
||||
// BluetoothDevice override.
|
||||
diff --git a/device/bluetooth/bluetooth_low_energy_device_mac.mm b/device/bluetooth/bluetooth_low_energy_device_mac.mm
|
||||
index 9a89728b0fc47cd7ca6e20d2ffbe7483010cbe39..73b1bee8e64664bdc98e45869accdf0ade2250b0 100644
|
||||
--- a/device/bluetooth/bluetooth_low_energy_device_mac.mm
|
||||
+++ b/device/bluetooth/bluetooth_low_energy_device_mac.mm
|
||||
@@ -207,6 +207,10 @@ @interface CBPeripheral (HighSierraSDK)
|
||||
NOTIMPLEMENTED();
|
||||
}
|
||||
|
||||
+bool BluetoothLowEnergyDeviceMac::IsLowEnergyDevice() {
|
||||
+ return true;
|
||||
+}
|
||||
+
|
||||
void BluetoothLowEnergyDeviceMac::CreateGattConnectionImpl(
|
||||
absl::optional<BluetoothUUID> serivce_uuid) {
|
||||
if (!IsGattConnected()) {
|
||||
83
patches/chromium/fix_--without-valid_build.patch
Normal file
83
patches/chromium/fix_--without-valid_build.patch
Normal file
@@ -0,0 +1,83 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Nick Wellnhofer <wellnhofer@aevum.de>
|
||||
Date: Tue, 22 Feb 2022 11:51:08 +0100
|
||||
Subject: Fix --without-valid build
|
||||
|
||||
Regressed in commit 652dd12a.
|
||||
|
||||
diff --git a/third_party/libxml/src/valid.c b/third_party/libxml/src/valid.c
|
||||
index 8e596f1db3db40a5decc5f4b529abc7588c6bd66..9684683a08018ca1185f85414f358791bfb1264b 100644
|
||||
--- a/third_party/libxml/src/valid.c
|
||||
+++ b/third_party/libxml/src/valid.c
|
||||
@@ -479,35 +479,6 @@ nodeVPop(xmlValidCtxtPtr ctxt)
|
||||
return (ret);
|
||||
}
|
||||
|
||||
-/**
|
||||
- * xmlValidNormalizeString:
|
||||
- * @str: a string
|
||||
- *
|
||||
- * Normalize a string in-place.
|
||||
- */
|
||||
-static void
|
||||
-xmlValidNormalizeString(xmlChar *str) {
|
||||
- xmlChar *dst;
|
||||
- const xmlChar *src;
|
||||
-
|
||||
- if (str == NULL)
|
||||
- return;
|
||||
- src = str;
|
||||
- dst = str;
|
||||
-
|
||||
- while (*src == 0x20) src++;
|
||||
- while (*src != 0) {
|
||||
- if (*src == 0x20) {
|
||||
- while (*src == 0x20) src++;
|
||||
- if (*src != 0)
|
||||
- *dst++ = 0x20;
|
||||
- } else {
|
||||
- *dst++ = *src++;
|
||||
- }
|
||||
- }
|
||||
- *dst = 0;
|
||||
-}
|
||||
-
|
||||
#ifdef DEBUG_VALID_ALGO
|
||||
static void
|
||||
xmlValidPrintNode(xmlNodePtr cur) {
|
||||
@@ -2636,6 +2607,35 @@ xmlDumpNotationTable(xmlBufferPtr buf, xmlNotationTablePtr table) {
|
||||
(xmlDictOwns(dict, (const xmlChar *)(str)) == 0))) \
|
||||
xmlFree((char *)(str));
|
||||
|
||||
+/**
|
||||
+ * xmlValidNormalizeString:
|
||||
+ * @str: a string
|
||||
+ *
|
||||
+ * Normalize a string in-place.
|
||||
+ */
|
||||
+static void
|
||||
+xmlValidNormalizeString(xmlChar *str) {
|
||||
+ xmlChar *dst;
|
||||
+ const xmlChar *src;
|
||||
+
|
||||
+ if (str == NULL)
|
||||
+ return;
|
||||
+ src = str;
|
||||
+ dst = str;
|
||||
+
|
||||
+ while (*src == 0x20) src++;
|
||||
+ while (*src != 0) {
|
||||
+ if (*src == 0x20) {
|
||||
+ while (*src == 0x20) src++;
|
||||
+ if (*src != 0)
|
||||
+ *dst++ = 0x20;
|
||||
+ } else {
|
||||
+ *dst++ = *src++;
|
||||
+ }
|
||||
+ }
|
||||
+ *dst = 0;
|
||||
+}
|
||||
+
|
||||
static int
|
||||
xmlIsStreaming(xmlValidCtxtPtr ctxt) {
|
||||
xmlParserCtxtPtr pctxt;
|
||||
@@ -0,0 +1,404 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Austin Sullivan <asully@chromium.org>
|
||||
Date: Fri, 11 Mar 2022 10:08:55 +0000
|
||||
Subject: FSA: Pass File ownership to worker for async FSARFD file operations
|
||||
|
||||
We cannot access the backing file as a member of the
|
||||
FileSystemAccessRegularFileDelegate since WrapCrossThreadPersistent
|
||||
does NOT cancel the task posted to the worker pool if delegate is
|
||||
destroyed. Passing ownership to the worker task ensures the file must
|
||||
be alive when used. After the operation, ownership of the file is
|
||||
passed back to the delegate.
|
||||
|
||||
This pattern was already used for the SetLength operation on old Macs.
|
||||
|
||||
Bug: 1299743
|
||||
Change-Id: Ie00c09e8f77dc353f280af726a68ed6c572b750b
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3498864
|
||||
Reviewed-by: Marijn Kruisselbrink <mek@chromium.org>
|
||||
Commit-Queue: Austin Sullivan <asully@chromium.org>
|
||||
Cr-Commit-Position: refs/heads/main@{#980167}
|
||||
|
||||
diff --git a/third_party/blink/renderer/modules/file_system_access/file_system_access_regular_file_delegate.cc b/third_party/blink/renderer/modules/file_system_access/file_system_access_regular_file_delegate.cc
|
||||
index bf5d3bdaace198e4da56cab27aef9d1cfa178136..a1f346c5afd6c2f3f41069a6dda4744179b1af05 100644
|
||||
--- a/third_party/blink/renderer/modules/file_system_access/file_system_access_regular_file_delegate.cc
|
||||
+++ b/third_party/blink/renderer/modules/file_system_access/file_system_access_regular_file_delegate.cc
|
||||
@@ -18,6 +18,7 @@
|
||||
#include "third_party/blink/renderer/platform/scheduler/public/worker_pool.h"
|
||||
#include "third_party/blink/renderer/platform/wtf/cross_thread_functional.h"
|
||||
#include "third_party/blink/renderer/platform/wtf/functional.h"
|
||||
+#include "third_party/blink/renderer/platform/wtf/wtf.h"
|
||||
|
||||
#if defined(OS_MAC)
|
||||
#include "base/mac/mac_util.h"
|
||||
@@ -64,6 +65,8 @@ FileSystemAccessRegularFileDelegate::FileSystemAccessRegularFileDelegate(
|
||||
base::FileErrorOr<int> FileSystemAccessRegularFileDelegate::Read(
|
||||
int64_t offset,
|
||||
base::span<uint8_t> data) {
|
||||
+ DCHECK_GE(offset, 0);
|
||||
+
|
||||
int size = base::checked_cast<int>(data.size());
|
||||
int result =
|
||||
backing_file_.Read(offset, reinterpret_cast<char*>(data.data()), size);
|
||||
@@ -74,13 +77,14 @@ base::FileErrorOr<int> FileSystemAccessRegularFileDelegate::Read(
|
||||
}
|
||||
|
||||
base::FileErrorOr<int> FileSystemAccessRegularFileDelegate::Write(
|
||||
- int64_t write_offset,
|
||||
+ int64_t offset,
|
||||
const base::span<uint8_t> data) {
|
||||
+ DCHECK_GE(offset, 0);
|
||||
+
|
||||
int write_size = base::checked_cast<int>(data.size());
|
||||
|
||||
int64_t write_end_offset;
|
||||
- if (!base::CheckAdd(write_offset, write_size)
|
||||
- .AssignIfValid(&write_end_offset)) {
|
||||
+ if (!base::CheckAdd(offset, write_size).AssignIfValid(&write_end_offset)) {
|
||||
return base::File::FILE_ERROR_NO_SPACE;
|
||||
}
|
||||
|
||||
@@ -88,8 +92,8 @@ base::FileErrorOr<int> FileSystemAccessRegularFileDelegate::Write(
|
||||
return base::File::FILE_ERROR_NO_SPACE;
|
||||
}
|
||||
|
||||
- int result = backing_file_.Write(
|
||||
- write_offset, reinterpret_cast<char*>(data.data()), write_size);
|
||||
+ int result = backing_file_.Write(offset, reinterpret_cast<char*>(data.data()),
|
||||
+ write_size);
|
||||
if (write_size == result) {
|
||||
capacity_tracker_->CommitFileSizeChange(write_end_offset);
|
||||
return result;
|
||||
@@ -112,16 +116,19 @@ void FileSystemAccessRegularFileDelegate::GetLength(
|
||||
FROM_HERE, {base::MayBlock()},
|
||||
CrossThreadBindOnce(&FileSystemAccessRegularFileDelegate::DoGetLength,
|
||||
WrapCrossThreadPersistent(this),
|
||||
- std::move(wrapped_callback), task_runner_));
|
||||
+ std::move(wrapped_callback), std::move(backing_file_),
|
||||
+ task_runner_));
|
||||
}
|
||||
|
||||
// static
|
||||
void FileSystemAccessRegularFileDelegate::DoGetLength(
|
||||
CrossThreadPersistent<FileSystemAccessRegularFileDelegate> delegate,
|
||||
- WTF::CrossThreadOnceFunction<void(base::FileErrorOr<int64_t>)>
|
||||
- wrapped_callback,
|
||||
+ CrossThreadOnceFunction<void(base::FileErrorOr<int64_t>)> callback,
|
||||
+ base::File file,
|
||||
scoped_refptr<base::SequencedTaskRunner> task_runner) {
|
||||
- int64_t length = delegate->backing_file_.GetLength();
|
||||
+ DCHECK(!IsMainThread());
|
||||
+
|
||||
+ int64_t length = file.GetLength();
|
||||
|
||||
// If the length is negative, the file operation failed. Get the last error
|
||||
// now before another file operation might run.
|
||||
@@ -130,7 +137,19 @@ void FileSystemAccessRegularFileDelegate::DoGetLength(
|
||||
|
||||
PostCrossThreadTask(
|
||||
*task_runner, FROM_HERE,
|
||||
- CrossThreadBindOnce(std::move(wrapped_callback), std::move(result)));
|
||||
+ CrossThreadBindOnce(&FileSystemAccessRegularFileDelegate::DidGetLength,
|
||||
+ std::move(delegate), std::move(callback),
|
||||
+ std::move(file), std::move(result)));
|
||||
+}
|
||||
+
|
||||
+void FileSystemAccessRegularFileDelegate::DidGetLength(
|
||||
+ CrossThreadOnceFunction<void(base::FileErrorOr<int64_t>)> callback,
|
||||
+ base::File file,
|
||||
+ base::FileErrorOr<int64_t> error_or_length) {
|
||||
+ DCHECK(task_runner_->RunsTasksInCurrentSequence());
|
||||
+ backing_file_ = std::move(file);
|
||||
+
|
||||
+ std::move(callback).Run(std::move(error_or_length));
|
||||
}
|
||||
|
||||
void FileSystemAccessRegularFileDelegate::SetLength(
|
||||
@@ -161,6 +180,9 @@ void FileSystemAccessRegularFileDelegate::DidCheckSetLengthCapacity(
|
||||
return;
|
||||
}
|
||||
|
||||
+ auto wrapped_callback =
|
||||
+ CrossThreadOnceFunction<void(bool)>(std::move(callback));
|
||||
+
|
||||
#if defined(OS_MAC)
|
||||
// On macOS < 10.15, a sandboxing limitation causes failures in ftruncate()
|
||||
// syscalls issued from renderers. For this reason, base::File::SetLength()
|
||||
@@ -173,81 +195,57 @@ void FileSystemAccessRegularFileDelegate::DidCheckSetLengthCapacity(
|
||||
}
|
||||
file_utilities_host_->SetLength(
|
||||
std::move(backing_file_), new_length,
|
||||
- WTF::Bind(&FileSystemAccessRegularFileDelegate::DidSetLengthIPC,
|
||||
- WrapPersistent(this), std::move(callback), new_length));
|
||||
+ WTF::Bind(&FileSystemAccessRegularFileDelegate::DidSetLength,
|
||||
+ WrapPersistent(this), std::move(wrapped_callback),
|
||||
+ new_length));
|
||||
return;
|
||||
}
|
||||
#endif // defined(OS_MAC)
|
||||
|
||||
- auto wrapped_callback =
|
||||
- CrossThreadOnceFunction<void(bool)>(std::move(callback));
|
||||
-
|
||||
// Truncate file on a worker thread and reply back to this sequence.
|
||||
worker_pool::PostTask(
|
||||
FROM_HERE, {base::MayBlock()},
|
||||
CrossThreadBindOnce(&FileSystemAccessRegularFileDelegate::DoSetLength,
|
||||
WrapCrossThreadPersistent(this),
|
||||
- std::move(wrapped_callback), task_runner_,
|
||||
- new_length));
|
||||
+ std::move(wrapped_callback), std::move(backing_file_),
|
||||
+ task_runner_, new_length));
|
||||
}
|
||||
|
||||
// static
|
||||
void FileSystemAccessRegularFileDelegate::DoSetLength(
|
||||
CrossThreadPersistent<FileSystemAccessRegularFileDelegate> delegate,
|
||||
- CrossThreadOnceFunction<void(bool)> wrapped_callback,
|
||||
+ CrossThreadOnceFunction<void(bool)> callback,
|
||||
+ base::File file,
|
||||
scoped_refptr<base::SequencedTaskRunner> task_runner,
|
||||
int64_t length) {
|
||||
- bool result = delegate->backing_file_.SetLength(length);
|
||||
-
|
||||
- if (!result) {
|
||||
- // If the operation failed, the previously requested capacity is not
|
||||
- // returned and no change in file size is recorded. This assumes that
|
||||
- // setLength operations either succeed or do not change the file's length,
|
||||
- // which is consistent with the way other file operations are implemented in
|
||||
- // File System Access.
|
||||
- PostCrossThreadTask(
|
||||
- *task_runner, FROM_HERE,
|
||||
- CrossThreadBindOnce(std::move(wrapped_callback), std::move(result)));
|
||||
- return;
|
||||
- }
|
||||
+ DCHECK(!IsMainThread());
|
||||
+
|
||||
+ bool success = file.SetLength(length);
|
||||
+
|
||||
PostCrossThreadTask(
|
||||
*task_runner, FROM_HERE,
|
||||
- CrossThreadBindOnce(
|
||||
- &FileSystemAccessRegularFileDelegate::DidSuccessfulSetLength,
|
||||
- std::move(delegate), length, std::move(wrapped_callback)));
|
||||
-}
|
||||
-
|
||||
-void FileSystemAccessRegularFileDelegate::DidSuccessfulSetLength(
|
||||
- int64_t new_length,
|
||||
- CrossThreadOnceFunction<void(bool)> callback) {
|
||||
- DCHECK(task_runner_->RunsTasksInCurrentSequence());
|
||||
- capacity_tracker_->CommitFileSizeChange(new_length);
|
||||
- std::move(callback).Run(true);
|
||||
+ CrossThreadBindOnce(&FileSystemAccessRegularFileDelegate::DidSetLength,
|
||||
+ std::move(delegate), std::move(callback), length,
|
||||
+ std::move(file), success));
|
||||
}
|
||||
|
||||
-#if defined(OS_MAC)
|
||||
-void FileSystemAccessRegularFileDelegate::DidSetLengthIPC(
|
||||
- base::OnceCallback<void(bool)> callback,
|
||||
+void FileSystemAccessRegularFileDelegate::DidSetLength(
|
||||
+ CrossThreadOnceFunction<void(bool)> callback,
|
||||
int64_t new_length,
|
||||
base::File file,
|
||||
bool success) {
|
||||
DCHECK(task_runner_->RunsTasksInCurrentSequence());
|
||||
backing_file_ = std::move(file);
|
||||
|
||||
- if (!success) {
|
||||
- // If the operation failed, the previously requested capacity is not
|
||||
- // returned and no change in file size is recorded. This assumes that
|
||||
- // setLength operations either succeed or do not change the file's length,
|
||||
- // which is consistent with the way other file operations are implemented in
|
||||
- // File System Access.
|
||||
- std::move(callback).Run(success);
|
||||
- return;
|
||||
- }
|
||||
- auto wrapped_callback =
|
||||
- CrossThreadOnceFunction<void(bool)>(std::move(callback));
|
||||
- DidSuccessfulSetLength(new_length, std::move(wrapped_callback));
|
||||
+ // If the operation failed, no change in file size is recorded. This assumes
|
||||
+ // that setLength operations either succeed or do not change the file's
|
||||
+ // length, which is consistent with the way other file operations are
|
||||
+ // implemented in File System Access.
|
||||
+ if (success)
|
||||
+ capacity_tracker_->CommitFileSizeChange(new_length);
|
||||
+
|
||||
+ std::move(callback).Run(success);
|
||||
}
|
||||
-#endif // defined(OS_MAC)
|
||||
|
||||
void FileSystemAccessRegularFileDelegate::Flush(
|
||||
base::OnceCallback<void(bool)> callback) {
|
||||
@@ -259,17 +257,34 @@ void FileSystemAccessRegularFileDelegate::Flush(
|
||||
FROM_HERE, {base::MayBlock()},
|
||||
CrossThreadBindOnce(&FileSystemAccessRegularFileDelegate::DoFlush,
|
||||
WrapCrossThreadPersistent(this),
|
||||
- std::move(wrapped_callback), task_runner_));
|
||||
+ std::move(wrapped_callback), std::move(backing_file_),
|
||||
+ task_runner_));
|
||||
}
|
||||
|
||||
// static
|
||||
void FileSystemAccessRegularFileDelegate::DoFlush(
|
||||
CrossThreadPersistent<FileSystemAccessRegularFileDelegate> delegate,
|
||||
- CrossThreadOnceFunction<void(bool)> wrapped_callback,
|
||||
+ CrossThreadOnceFunction<void(bool)> callback,
|
||||
+ base::File file,
|
||||
scoped_refptr<base::SequencedTaskRunner> task_runner) {
|
||||
- bool result = delegate->backing_file_.Flush();
|
||||
- PostCrossThreadTask(*task_runner, FROM_HERE,
|
||||
- CrossThreadBindOnce(std::move(wrapped_callback), result));
|
||||
+ DCHECK(!IsMainThread());
|
||||
+
|
||||
+ bool success = file.Flush();
|
||||
+ PostCrossThreadTask(
|
||||
+ *task_runner, FROM_HERE,
|
||||
+ CrossThreadBindOnce(&FileSystemAccessRegularFileDelegate::DidFlush,
|
||||
+ std::move(delegate), std::move(callback),
|
||||
+ std::move(file), success));
|
||||
+}
|
||||
+
|
||||
+void FileSystemAccessRegularFileDelegate::DidFlush(
|
||||
+ CrossThreadOnceFunction<void(bool)> callback,
|
||||
+ base::File file,
|
||||
+ bool success) {
|
||||
+ DCHECK(task_runner_->RunsTasksInCurrentSequence());
|
||||
+ backing_file_ = std::move(file);
|
||||
+
|
||||
+ std::move(callback).Run(success);
|
||||
}
|
||||
|
||||
void FileSystemAccessRegularFileDelegate::Close(base::OnceClosure callback) {
|
||||
@@ -280,16 +295,33 @@ void FileSystemAccessRegularFileDelegate::Close(base::OnceClosure callback) {
|
||||
FROM_HERE, {base::MayBlock()},
|
||||
CrossThreadBindOnce(&FileSystemAccessRegularFileDelegate::DoClose,
|
||||
WrapCrossThreadPersistent(this),
|
||||
- std::move(wrapped_callback), task_runner_));
|
||||
+ std::move(wrapped_callback), std::move(backing_file_),
|
||||
+ task_runner_));
|
||||
}
|
||||
|
||||
// static
|
||||
void FileSystemAccessRegularFileDelegate::DoClose(
|
||||
CrossThreadPersistent<FileSystemAccessRegularFileDelegate> delegate,
|
||||
- CrossThreadOnceClosure wrapped_callback,
|
||||
+ CrossThreadOnceClosure callback,
|
||||
+ base::File file,
|
||||
scoped_refptr<base::SequencedTaskRunner> task_runner) {
|
||||
- delegate->backing_file_.Close();
|
||||
- PostCrossThreadTask(*task_runner, FROM_HERE, std::move(wrapped_callback));
|
||||
+ DCHECK(!IsMainThread());
|
||||
+
|
||||
+ file.Close();
|
||||
+ PostCrossThreadTask(
|
||||
+ *task_runner, FROM_HERE,
|
||||
+ CrossThreadBindOnce(&FileSystemAccessRegularFileDelegate::DidClose,
|
||||
+ std::move(delegate), std::move(callback),
|
||||
+ std::move(file)));
|
||||
+}
|
||||
+
|
||||
+void FileSystemAccessRegularFileDelegate::DidClose(
|
||||
+ CrossThreadOnceClosure callback,
|
||||
+ base::File file) {
|
||||
+ DCHECK(task_runner_->RunsTasksInCurrentSequence());
|
||||
+ backing_file_ = std::move(file);
|
||||
+
|
||||
+ std::move(callback).Run();
|
||||
}
|
||||
|
||||
} // namespace blink
|
||||
diff --git a/third_party/blink/renderer/modules/file_system_access/file_system_access_regular_file_delegate.h b/third_party/blink/renderer/modules/file_system_access/file_system_access_regular_file_delegate.h
|
||||
index 6ecde8f42f4f8ee623d0b79b361dab3d2801021d..f1267ef98e083feaa472e6d1b14c8e1bb8df7b96 100644
|
||||
--- a/third_party/blink/renderer/modules/file_system_access/file_system_access_regular_file_delegate.h
|
||||
+++ b/third_party/blink/renderer/modules/file_system_access/file_system_access_regular_file_delegate.h
|
||||
@@ -28,6 +28,11 @@ namespace blink {
|
||||
|
||||
// Non-incognito implementation of the FileSystemAccessFileDelegate. This class
|
||||
// is a thin wrapper around an OS-level file descriptor.
|
||||
+//
|
||||
+// For async file operations, ownership of the file descriptor is passed to
|
||||
+// `task_runner_` to ensure it stays alive while being used. Ownership is passed
|
||||
+// back to the delegate once the operation completes. The delegate must not be
|
||||
+// used while there is an in-progress operation.
|
||||
class FileSystemAccessRegularFileDelegate final
|
||||
: public FileSystemAccessFileDelegate {
|
||||
public:
|
||||
@@ -71,24 +76,55 @@ class FileSystemAccessRegularFileDelegate final
|
||||
bool IsValid() const override { return backing_file_.IsValid(); }
|
||||
|
||||
private:
|
||||
+ // All async file operations perform I/O via a worker pool, off the main
|
||||
+ // thread. To keep `backing_file_` from being garbage-collected, ownership is
|
||||
+ // passed to the worker thread during the file operation. Concurrent file
|
||||
+ // operations is NOT supported.
|
||||
+
|
||||
+ // Performs the file I/O part of getSize(), off the main thread.
|
||||
static void DoGetLength(
|
||||
CrossThreadPersistent<FileSystemAccessRegularFileDelegate> delegate,
|
||||
- CrossThreadOnceFunction<void(base::FileErrorOr<int64_t>)>
|
||||
- wrapped_callback,
|
||||
+ CrossThreadOnceFunction<void(base::FileErrorOr<int64_t>)> callback,
|
||||
+ base::File file,
|
||||
scoped_refptr<base::SequencedTaskRunner> file_task_runner);
|
||||
+ // Performs the post file I/O part of getSize(), on the main thread.
|
||||
+ void DidGetLength(
|
||||
+ CrossThreadOnceFunction<void(base::FileErrorOr<int64_t>)> callback,
|
||||
+ base::File file,
|
||||
+ base::FileErrorOr<int64_t> error_or_length);
|
||||
+
|
||||
+ // Performs the file I/O part of truncate(), off the main thread.
|
||||
static void DoSetLength(
|
||||
CrossThreadPersistent<FileSystemAccessRegularFileDelegate> delegate,
|
||||
- CrossThreadOnceFunction<void(bool)> wrapped_callback,
|
||||
+ CrossThreadOnceFunction<void(bool)> callback,
|
||||
+ base::File file,
|
||||
scoped_refptr<base::SequencedTaskRunner> task_runner,
|
||||
int64_t length);
|
||||
+ // Performs the post file I/O part of truncate(), on the main thread.
|
||||
+ void DidSetLength(CrossThreadOnceFunction<void(bool)> callback,
|
||||
+ int64_t new_length,
|
||||
+ base::File file,
|
||||
+ bool success);
|
||||
+
|
||||
+ // Performs the file I/O part of flush(), off the main thread.
|
||||
static void DoFlush(
|
||||
CrossThreadPersistent<FileSystemAccessRegularFileDelegate> delegate,
|
||||
- CrossThreadOnceFunction<void(bool)> wrapped_callback,
|
||||
+ CrossThreadOnceFunction<void(bool)> callback,
|
||||
+ base::File file,
|
||||
scoped_refptr<base::SequencedTaskRunner> task_runner);
|
||||
+ // Performs the post file I/O part of flush(), on the main thread.
|
||||
+ void DidFlush(CrossThreadOnceFunction<void(bool)> callback,
|
||||
+ base::File file,
|
||||
+ bool success);
|
||||
+
|
||||
+ // Performs the file I/O part of close(), off the main thread.
|
||||
static void DoClose(
|
||||
CrossThreadPersistent<FileSystemAccessRegularFileDelegate> delegate,
|
||||
- CrossThreadOnceClosure wrapped_callback,
|
||||
+ CrossThreadOnceClosure callback,
|
||||
+ base::File file,
|
||||
scoped_refptr<base::SequencedTaskRunner> task_runner);
|
||||
+ // Performs the post file I/O part of close(), on the main thread.
|
||||
+ void DidClose(CrossThreadOnceClosure callback, base::File file);
|
||||
|
||||
// Called after preconditions for SetLength, including the requesting
|
||||
// additional capacity (if needed), have been performed.
|
||||
@@ -98,16 +134,7 @@ class FileSystemAccessRegularFileDelegate final
|
||||
int64_t new_length,
|
||||
bool request_capacity_result);
|
||||
|
||||
- // Called after SetLength was successfully performed.
|
||||
- void DidSuccessfulSetLength(int64_t new_length,
|
||||
- CrossThreadOnceFunction<void(bool)> callback);
|
||||
-
|
||||
#if defined(OS_MAC)
|
||||
- void DidSetLengthIPC(base::OnceCallback<void(bool)> callback,
|
||||
- int64_t new_length,
|
||||
- base::File file,
|
||||
- bool result);
|
||||
-
|
||||
// We need the FileUtilitiesHost only on Mac, where we have to execute
|
||||
// base::File::SetLength on the browser process, see crbug.com/1084565.
|
||||
// We need the context_ to create the instance of FileUtilitiesHost lazily.
|
||||
@@ -0,0 +1,217 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Rakina Zata Amni <rakina@chromium.org>
|
||||
Date: Mon, 25 Apr 2022 06:18:19 +0000
|
||||
Subject: Don't use GetOriginalOpener to get opener's origin on FrameTree
|
||||
initialization
|
||||
|
||||
When setting the origin of the new main RFH on FrameTree initialization,
|
||||
we base it on the opener's origin if it exists. GetOriginalOpener()
|
||||
was used to get the opener, but that function will actually return the
|
||||
main frame of the opener. This means when the FrameTree is opened by a
|
||||
non-main frame, we might inherit the wrong origin.
|
||||
|
||||
This CL fixes the bug by getting the actual opener using GetOpener()
|
||||
instead, and adds a regression test and warning note to
|
||||
GetOriginalOpener().
|
||||
|
||||
(cherry picked from commit 4eb716ef5cdbca4db3a9377ee6390964d0d4025f)
|
||||
|
||||
Bug: 1311820, 1291764
|
||||
Change-Id: I7e6f63a394ba4188eee3ce3043b174a2695508eb
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3564826
|
||||
Reviewed-by: Charlie Reis <creis@chromium.org>
|
||||
Commit-Queue: Rakina Zata Amni <rakina@chromium.org>
|
||||
Cr-Original-Commit-Position: refs/heads/main@{#989165}
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3600157
|
||||
Auto-Submit: Rakina Zata Amni <rakina@chromium.org>
|
||||
Reviewed-by: Nidhi Jaju <nidhijaju@chromium.org>
|
||||
Commit-Queue: Nidhi Jaju <nidhijaju@chromium.org>
|
||||
Owners-Override: Nidhi Jaju <nidhijaju@chromium.org>
|
||||
Cr-Commit-Position: refs/branch-heads/4896@{#1179}
|
||||
Cr-Branched-From: 1f63ff4bc27570761b35ffbc7f938f6586f7bee8-refs/heads/main@{#972766}
|
||||
|
||||
diff --git a/content/browser/renderer_host/frame_tree.cc b/content/browser/renderer_host/frame_tree.cc
|
||||
index dc8f28bdefb7c490104c2e88fb71f7cc91db0fda..7193d75e5daa83b4749c8e1e2497a2e99cc03ef3 100644
|
||||
--- a/content/browser/renderer_host/frame_tree.cc
|
||||
+++ b/content/browser/renderer_host/frame_tree.cc
|
||||
@@ -789,7 +789,7 @@ void FrameTree::RegisterExistingOriginToPreventOptInIsolation(
|
||||
void FrameTree::Init(SiteInstance* main_frame_site_instance,
|
||||
bool renderer_initiated_creation,
|
||||
const std::string& main_frame_name,
|
||||
- RenderFrameHostImpl* opener) {
|
||||
+ RenderFrameHostImpl* opener_for_origin) {
|
||||
// blink::FrameTree::SetName always keeps |unique_name| empty in case of a
|
||||
// main frame - let's do the same thing here.
|
||||
std::string unique_name;
|
||||
@@ -800,16 +800,16 @@ void FrameTree::Init(SiteInstance* main_frame_site_instance,
|
||||
|
||||
// The initial empty document should inherit the origin of its opener (the
|
||||
// origin may change after the first commit), except when they are in
|
||||
- // different browsing context groups (`renderer_initiated_creation` is false),
|
||||
- // where it should use a new opaque origin.
|
||||
+ // different browsing context groups (`renderer_initiated_creation` will be
|
||||
+ // false), where it should use a new opaque origin.
|
||||
// See also https://crbug.com/932067.
|
||||
//
|
||||
// Note that the origin of the new frame might depend on sandbox flags.
|
||||
// Checking sandbox flags of the new frame should be safe at this point,
|
||||
// because the flags should be already inherited when creating the root node.
|
||||
- DCHECK(!renderer_initiated_creation || opener);
|
||||
+ DCHECK(!renderer_initiated_creation || opener_for_origin);
|
||||
root_->current_frame_host()->SetOriginDependentStateOfNewFrame(
|
||||
- renderer_initiated_creation ? opener->GetLastCommittedOrigin()
|
||||
+ renderer_initiated_creation ? opener_for_origin->GetLastCommittedOrigin()
|
||||
: url::Origin());
|
||||
|
||||
if (blink::features::IsInitialNavigationEntryEnabled())
|
||||
diff --git a/content/browser/renderer_host/frame_tree.h b/content/browser/renderer_host/frame_tree.h
|
||||
index d1f7db763fabe942e6322e8781331df6998a6a28..ca0a0e16f4ccdf77eb1feb1fb197230579c1b01b 100644
|
||||
--- a/content/browser/renderer_host/frame_tree.h
|
||||
+++ b/content/browser/renderer_host/frame_tree.h
|
||||
@@ -204,7 +204,7 @@ class CONTENT_EXPORT FrameTree {
|
||||
// Initializes the main frame for this FrameTree. That is it creates the
|
||||
// initial RenderFrameHost in the root node's RenderFrameHostManager, and also
|
||||
// creates an initial NavigationEntry (if the InitialNavigationEntry feature
|
||||
- // is enabled) that potentially inherits `opener`'s origin in its
|
||||
+ // is enabled) that potentially inherits `opener_for_origin`'s origin in its
|
||||
// NavigationController. This method will call back into the delegates so it
|
||||
// should only be called once they have completed their initialization.
|
||||
// TODO(carlscab): It would be great if initialization could happened in the
|
||||
@@ -212,7 +212,7 @@ class CONTENT_EXPORT FrameTree {
|
||||
void Init(SiteInstance* main_frame_site_instance,
|
||||
bool renderer_initiated_creation,
|
||||
const std::string& main_frame_name,
|
||||
- RenderFrameHostImpl* opener);
|
||||
+ RenderFrameHostImpl* opener_for_origin);
|
||||
|
||||
Type type() const { return type_; }
|
||||
|
||||
diff --git a/content/browser/renderer_host/render_frame_host_impl_browsertest.cc b/content/browser/renderer_host/render_frame_host_impl_browsertest.cc
|
||||
index bf1494b76230c77d9dac8c66f16b4349dfb15ae8..e6b582af29dd6fa274cc0740aa272b1e62c2725c 100644
|
||||
--- a/content/browser/renderer_host/render_frame_host_impl_browsertest.cc
|
||||
+++ b/content/browser/renderer_host/render_frame_host_impl_browsertest.cc
|
||||
@@ -6543,6 +6543,80 @@ IN_PROC_BROWSER_TEST_F(RenderFrameHostImplBrowserTest, ErrorDocuments) {
|
||||
EXPECT_TRUE(child_b->IsErrorDocument());
|
||||
}
|
||||
|
||||
+// Tests that a popup that is opened by a subframe inherits the subframe's
|
||||
+// origin, instead of the main frame's origin.
|
||||
+// Regression test for https://crbug.com/1311820 and https://crbug.com/1291764.
|
||||
+IN_PROC_BROWSER_TEST_F(RenderFrameHostImplBrowserTest,
|
||||
+ PopupOpenedBySubframeHasCorrectOrigin) {
|
||||
+ GURL main_url(embedded_test_server()->GetURL(
|
||||
+ "a.com", "/cross_site_iframe_factory.html?a(b)"));
|
||||
+ // Navigate to a page with a cross-site iframe.
|
||||
+ EXPECT_TRUE(NavigateToURL(shell(), main_url));
|
||||
+ FrameTreeNode* root = web_contents()->GetPrimaryFrameTree().root();
|
||||
+ FrameTreeNode* child = root->child_at(0);
|
||||
+
|
||||
+ // Verify that the main frame & subframe origin differs.
|
||||
+ url::Origin a_origin = url::Origin::Create(main_url);
|
||||
+ url::Origin b_origin = url::Origin::Create(child->current_url());
|
||||
+ EXPECT_EQ(a_origin, root->current_frame_host()->GetLastCommittedOrigin());
|
||||
+ EXPECT_EQ(b_origin, child->current_frame_host()->GetLastCommittedOrigin());
|
||||
+ EXPECT_NE(a_origin, b_origin);
|
||||
+
|
||||
+ {
|
||||
+ // From the subframe, open a popup that stays on the initial empty
|
||||
+ // document.
|
||||
+ WebContentsAddedObserver popup_observer;
|
||||
+ ASSERT_TRUE(ExecJs(child, "var w = window.open('/nocontent');"));
|
||||
+ WebContentsImpl* popup =
|
||||
+ static_cast<WebContentsImpl*>(popup_observer.GetWebContents());
|
||||
+ FrameTreeNode* popup_frame = popup->GetMainFrame()->frame_tree_node();
|
||||
+
|
||||
+ // The popup should inherit the subframe's origin. Before the fix for
|
||||
+ // https://crbug.com/1311820, the popup used to inherit the main frame's
|
||||
+ // origin instead.
|
||||
+ EXPECT_EQ(b_origin,
|
||||
+ popup_frame->current_frame_host()->GetLastCommittedOrigin());
|
||||
+ EXPECT_EQ(b_origin.Serialize(), EvalJs(popup_frame, "self.origin"));
|
||||
+
|
||||
+ // Try calling document.open() on the popup from itself.
|
||||
+ // This used to cause a renderer kill as the browser used to notice the
|
||||
+ // current origin & process lock mismatched when the document.open()
|
||||
+ // notification IPC arrives.
|
||||
+ EXPECT_EQ(GURL("about:blank"), EvalJs(popup_frame, "location.href"));
|
||||
+ EXPECT_TRUE(ExecJs(popup_frame, "document.open()"));
|
||||
+ EXPECT_EQ(GURL("about:blank"), EvalJs(popup_frame, "location.href"));
|
||||
+
|
||||
+ // Try updating the URL of the popup to the opener subframe's URL by
|
||||
+ // calling document.open() on the popup from the opener subframe.
|
||||
+ // This used to cause a renderer kill as the browser used to expect that
|
||||
+ // the popup frame can only update to URLs under `a_origin`, while the
|
||||
+ // new URL is under `b_origin`. See also https://crbug.com/1291764.
|
||||
+ EXPECT_TRUE(ExecJs(child, "w.document.open()"));
|
||||
+ EXPECT_EQ(child->current_url().spec(),
|
||||
+ EvalJs(popup_frame, "location.href"));
|
||||
+ }
|
||||
+
|
||||
+ {
|
||||
+ // From the subframe, open a popup that stays on the initial empty
|
||||
+ // document, and specify 'noopener' to sever the opener relationship.
|
||||
+ WebContentsAddedObserver popup_observer;
|
||||
+ ASSERT_TRUE(
|
||||
+ ExecJs(child, "var w = window.open('/nocontent', '', 'noopener');"));
|
||||
+ WebContentsImpl* popup =
|
||||
+ static_cast<WebContentsImpl*>(popup_observer.GetWebContents());
|
||||
+ FrameTreeNode* popup_frame = popup->GetMainFrame()->frame_tree_node();
|
||||
+ EXPECT_EQ(nullptr, EvalJs(popup_frame, "window.opener"));
|
||||
+
|
||||
+ // The popup should use a new opaque origin, instead of the subframe's
|
||||
+ // origin.
|
||||
+ EXPECT_NE(b_origin,
|
||||
+ popup_frame->current_frame_host()->GetLastCommittedOrigin());
|
||||
+ EXPECT_TRUE(
|
||||
+ popup_frame->current_frame_host()->GetLastCommittedOrigin().opaque());
|
||||
+ EXPECT_EQ("null", EvalJs(popup_frame, "self.origin"));
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
class RenderFrameHostImplAvoidUnnecessaryBeforeUnloadBrowserTest
|
||||
: public RenderFrameHostImplBeforeUnloadBrowserTest {
|
||||
public:
|
||||
diff --git a/content/browser/web_contents/web_contents_impl.cc b/content/browser/web_contents/web_contents_impl.cc
|
||||
index 00a701c92c6b3ab7aa00e6f7bfc40febc7d0439e..f66907f633fe51f220164ca8ebbf16a8059ee843 100644
|
||||
--- a/content/browser/web_contents/web_contents_impl.cc
|
||||
+++ b/content/browser/web_contents/web_contents_impl.cc
|
||||
@@ -2971,9 +2971,18 @@ void WebContentsImpl::Init(const WebContents::CreateParams& params) {
|
||||
->PreventAssociationWithSpareProcess();
|
||||
}
|
||||
|
||||
+ // Iniitalize the primary FrameTree.
|
||||
+ // Note that GetOpener() is used here to get the opener for origin
|
||||
+ // inheritance, instead of other similar functions:
|
||||
+ // - GetOriginalOpener(), which would always return the main frame of the
|
||||
+ // opener, which might be different from the actual opener.
|
||||
+ // - FindOpenerRFH(), which will still return the opener frame if the
|
||||
+ // opener is suppressed (e.g. due to 'noopener'). The opener should not
|
||||
+ // be used for origin inheritance purposes in those cases, so this should
|
||||
+ // not pass the opener for those cases.
|
||||
primary_frame_tree_.Init(site_instance.get(),
|
||||
params.renderer_initiated_creation,
|
||||
- params.main_frame_name, GetOriginalOpener());
|
||||
+ params.main_frame_name, GetOpener());
|
||||
|
||||
if (params.view && params.delegate_view) {
|
||||
view_.reset(params.view);
|
||||
diff --git a/content/public/browser/web_contents.h b/content/public/browser/web_contents.h
|
||||
index aa10ae9a2154fe28c3df749c9f6c493f9101a567..52f2cd80da6ef870c9123faf388b9bfadc936b66 100644
|
||||
--- a/content/public/browser/web_contents.h
|
||||
+++ b/content/public/browser/web_contents.h
|
||||
@@ -1075,8 +1075,13 @@ class WebContents : public PageNavigator,
|
||||
// original owner, etc.
|
||||
virtual bool HasOriginalOpener() = 0;
|
||||
|
||||
- // Returns the original opener if HasOriginalOpener() is true, or nullptr
|
||||
- // otherwise.
|
||||
+ // Returns the original opener's main frame if HasOriginalOpener() is true, or
|
||||
+ // nullptr otherwise. NOTE: This will always be the main frame of the actual
|
||||
+ // original opener's frame tree, so it might be different from the actual
|
||||
+ // original opener if it is a subframe. See https://crbug.com/705316 for more
|
||||
+ // context.
|
||||
+ // TODO(https://crbug.com/1311820): Consider renaming this function and other
|
||||
+ // things related to "original openers", to make the quirk more obvious.
|
||||
virtual RenderFrameHost* GetOriginalOpener() = 0;
|
||||
|
||||
// Returns the WakeLockContext accociated with this WebContents.
|
||||
@@ -0,0 +1,641 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Darshan Sen <raisinten@gmail.com>
|
||||
Date: Fri, 17 Jun 2022 13:19:32 +0530
|
||||
Subject: posix: Replace DoubleForkAndExec() with ForkAndSpawn()
|
||||
|
||||
The DoubleForkAndExec() function was taking over 622 milliseconds to run
|
||||
on macOS 11 (BigSur) on Intel i5-1038NG7. I did some debugging by adding
|
||||
some custom traces and found that the fork() syscall is the bottleneck
|
||||
here, i.e., the first fork() takes around 359 milliseconds and the
|
||||
nested fork() takes around 263 milliseconds. Replacing the nested fork()
|
||||
and exec() with posix_spawn() reduces the time consumption to 257
|
||||
milliseconds!
|
||||
|
||||
See https://github.com/libuv/libuv/pull/3064 to know why fork() is so
|
||||
slow on macOS and why posix_spawn() is a better replacement.
|
||||
|
||||
Another point to note is that even base::LaunchProcess() from Chromium
|
||||
calls posix_spawnp() on macOS -
|
||||
https://source.chromium.org/chromium/chromium/src/+/8f8d82dea0fa8f11f57c74dbb65126f8daba58f7:base/process/launch_mac.cc;l=295-296
|
||||
|
||||
Change-Id: I25c6ee9629a1ae5d0c32b361b56a1ce0b4b0fd26
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/crashpad/crashpad/+/3641386
|
||||
Reviewed-by: Mark Mentovai <mark@chromium.org>
|
||||
Commit-Queue: Mark Mentovai <mark@chromium.org>
|
||||
|
||||
diff --git a/third_party/crashpad/crashpad/AUTHORS b/third_party/crashpad/crashpad/AUTHORS
|
||||
index 8dcac3238870920d374b86033d05d77ebde351e9..02103924332eddbd158c04f8a395bb4a247e8bd9 100644
|
||||
--- a/third_party/crashpad/crashpad/AUTHORS
|
||||
+++ b/third_party/crashpad/crashpad/AUTHORS
|
||||
@@ -12,3 +12,4 @@ Opera Software ASA
|
||||
Vewd Software AS
|
||||
LG Electronics, Inc.
|
||||
MIPS Technologies, Inc.
|
||||
+Darshan Sen <raisinten@gmail.com>
|
||||
diff --git a/third_party/crashpad/crashpad/client/crashpad_client_linux.cc b/third_party/crashpad/crashpad/client/crashpad_client_linux.cc
|
||||
index eccf204ca119a5e0b803a18df07835916f7abb22..b35f0c1b9486032f49a9154c92d277a79434a7ad 100644
|
||||
--- a/third_party/crashpad/crashpad/client/crashpad_client_linux.cc
|
||||
+++ b/third_party/crashpad/crashpad/client/crashpad_client_linux.cc
|
||||
@@ -40,7 +40,7 @@
|
||||
#include "util/linux/socket.h"
|
||||
#include "util/misc/address_sanitizer.h"
|
||||
#include "util/misc/from_pointer_cast.h"
|
||||
-#include "util/posix/double_fork_and_exec.h"
|
||||
+#include "util/posix/fork_and_spawn.h"
|
||||
#include "util/posix/scoped_mmap.h"
|
||||
#include "util/posix/signals.h"
|
||||
|
||||
@@ -401,7 +401,7 @@ bool CrashpadClient::StartHandler(
|
||||
|
||||
argv.push_back(FormatArgumentInt("initial-client-fd", handler_sock.get()));
|
||||
argv.push_back("--shared-client-connection");
|
||||
- if (!DoubleForkAndExec(argv, nullptr, handler_sock.get(), false, nullptr)) {
|
||||
+ if (!ForkAndSpawn(argv, nullptr, handler_sock.get(), false, nullptr)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -555,7 +555,7 @@ bool CrashpadClient::StartJavaHandlerForClient(
|
||||
int socket) {
|
||||
std::vector<std::string> argv = BuildAppProcessArgs(
|
||||
class_name, database, metrics_dir, url, annotations, arguments, socket);
|
||||
- return DoubleForkAndExec(argv, env, socket, false, nullptr);
|
||||
+ return ForkAndSpawn(argv, env, socket, false, nullptr);
|
||||
}
|
||||
|
||||
bool CrashpadClient::StartHandlerWithLinkerAtCrash(
|
||||
@@ -604,7 +604,7 @@ bool CrashpadClient::StartHandlerWithLinkerForClient(
|
||||
annotations,
|
||||
arguments,
|
||||
socket);
|
||||
- return DoubleForkAndExec(argv, env, socket, false, nullptr);
|
||||
+ return ForkAndSpawn(argv, env, socket, false, nullptr);
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -638,7 +638,7 @@ bool CrashpadClient::StartHandlerForClient(
|
||||
|
||||
argv.push_back(FormatArgumentInt("initial-client-fd", socket));
|
||||
|
||||
- return DoubleForkAndExec(argv, nullptr, socket, true, nullptr);
|
||||
+ return ForkAndSpawn(argv, nullptr, socket, true, nullptr);
|
||||
}
|
||||
|
||||
// static
|
||||
diff --git a/third_party/crashpad/crashpad/client/crashpad_client_mac.cc b/third_party/crashpad/crashpad/client/crashpad_client_mac.cc
|
||||
index b4a365d0204612b4e4621b2e8c30d266a10e1bc1..59c7a800ad903b91a88d0ef0cb1a01a1d8036e52 100644
|
||||
--- a/third_party/crashpad/crashpad/client/crashpad_client_mac.cc
|
||||
+++ b/third_party/crashpad/crashpad/client/crashpad_client_mac.cc
|
||||
@@ -36,7 +36,7 @@
|
||||
#include "util/mach/notify_server.h"
|
||||
#include "util/misc/clock.h"
|
||||
#include "util/misc/implicit_cast.h"
|
||||
-#include "util/posix/double_fork_and_exec.h"
|
||||
+#include "util/posix/fork_and_spawn.h"
|
||||
|
||||
namespace crashpad {
|
||||
|
||||
@@ -343,7 +343,7 @@ class HandlerStarter final : public NotifyServer::DefaultInterface {
|
||||
// this parent process, which was probably using the exception server now
|
||||
// being restarted. The handler can’t monitor itself for its own crashes via
|
||||
// this interface.
|
||||
- if (!DoubleForkAndExec(
|
||||
+ if (!ForkAndSpawn(
|
||||
argv,
|
||||
nullptr,
|
||||
server_write_fd.get(),
|
||||
diff --git a/third_party/crashpad/crashpad/handler/linux/cros_crash_report_exception_handler.cc b/third_party/crashpad/crashpad/handler/linux/cros_crash_report_exception_handler.cc
|
||||
index 9e58d94aa499fdb7271a78ea21a1dcc1b12e3a52..3caa3b987b35be575558a312026cf6f19485c418 100644
|
||||
--- a/third_party/crashpad/crashpad/handler/linux/cros_crash_report_exception_handler.cc
|
||||
+++ b/third_party/crashpad/crashpad/handler/linux/cros_crash_report_exception_handler.cc
|
||||
@@ -29,7 +29,7 @@
|
||||
#include "util/linux/ptrace_client.h"
|
||||
#include "util/misc/metrics.h"
|
||||
#include "util/misc/uuid.h"
|
||||
-#include "util/posix/double_fork_and_exec.h"
|
||||
+#include "util/posix/fork_and_spawn.h"
|
||||
|
||||
namespace crashpad {
|
||||
|
||||
@@ -266,12 +266,11 @@ bool CrosCrashReportExceptionHandler::HandleExceptionWithConnection(
|
||||
argv.push_back("--always_allow_feedback");
|
||||
}
|
||||
|
||||
- if (!DoubleForkAndExec(argv,
|
||||
- nullptr /* envp */,
|
||||
- file_writer.fd() /* preserve_fd */,
|
||||
- false /* use_path */,
|
||||
- nullptr /* child_function */)) {
|
||||
- LOG(ERROR) << "DoubleForkAndExec failed";
|
||||
+ if (!ForkAndSpawn(argv,
|
||||
+ nullptr /* envp */,
|
||||
+ file_writer.fd() /* preserve_fd */,
|
||||
+ false /* use_path */,
|
||||
+ nullptr /* child_function */)) {
|
||||
Metrics::ExceptionCaptureResult(
|
||||
Metrics::CaptureResult::kFinishedWritingCrashReportFailed);
|
||||
return false;
|
||||
diff --git a/third_party/crashpad/crashpad/util/BUILD.gn b/third_party/crashpad/crashpad/util/BUILD.gn
|
||||
index 9f178d10a9151340d34f17f2d04eef791a8d174b..20467df262354ac85e4d5ef71259e4539994c67a 100644
|
||||
--- a/third_party/crashpad/crashpad/util/BUILD.gn
|
||||
+++ b/third_party/crashpad/crashpad/util/BUILD.gn
|
||||
@@ -296,10 +296,10 @@ crashpad_static_library("util") {
|
||||
sources += [
|
||||
"posix/close_multiple.cc",
|
||||
"posix/close_multiple.h",
|
||||
- "posix/double_fork_and_exec.cc",
|
||||
- "posix/double_fork_and_exec.h",
|
||||
"posix/drop_privileges.cc",
|
||||
"posix/drop_privileges.h",
|
||||
+ "posix/fork_and_spawn.cc",
|
||||
+ "posix/fork_and_spawn.h",
|
||||
"posix/process_info.h",
|
||||
|
||||
# These map signals to and from strings. While Fuchsia defines some of
|
||||
diff --git a/third_party/crashpad/crashpad/util/posix/double_fork_and_exec.cc b/third_party/crashpad/crashpad/util/posix/double_fork_and_exec.cc
|
||||
deleted file mode 100644
|
||||
index 1960430954d3f6459dce688493db5c42047567b0..0000000000000000000000000000000000000000
|
||||
--- a/third_party/crashpad/crashpad/util/posix/double_fork_and_exec.cc
|
||||
+++ /dev/null
|
||||
@@ -1,166 +0,0 @@
|
||||
-// Copyright 2017 The Crashpad Authors. All rights reserved.
|
||||
-//
|
||||
-// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
-// you may not use this file except in compliance with the License.
|
||||
-// You may obtain a copy of the License at
|
||||
-//
|
||||
-// http://www.apache.org/licenses/LICENSE-2.0
|
||||
-//
|
||||
-// Unless required by applicable law or agreed to in writing, software
|
||||
-// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
-// See the License for the specific language governing permissions and
|
||||
-// limitations under the License.
|
||||
-
|
||||
-#include "util/posix/double_fork_and_exec.h"
|
||||
-
|
||||
-#include <stdlib.h>
|
||||
-#include <string.h>
|
||||
-#include <sys/wait.h>
|
||||
-#include <unistd.h>
|
||||
-
|
||||
-#include "base/check_op.h"
|
||||
-#include "base/logging.h"
|
||||
-#include "base/posix/eintr_wrapper.h"
|
||||
-#include "base/strings/stringprintf.h"
|
||||
-#include "util/posix/close_multiple.h"
|
||||
-
|
||||
-namespace crashpad {
|
||||
-
|
||||
-bool DoubleForkAndExec(const std::vector<std::string>& argv,
|
||||
- const std::vector<std::string>* envp,
|
||||
- int preserve_fd,
|
||||
- bool use_path,
|
||||
- void (*child_function)()) {
|
||||
- DCHECK(!envp || !use_path);
|
||||
-
|
||||
- // argv_c contains const char* pointers and is terminated by nullptr. This is
|
||||
- // suitable for passing to execv(). Although argv_c is not used in the parent
|
||||
- // process, it must be built in the parent process because it’s unsafe to do
|
||||
- // so in the child or grandchild process.
|
||||
- std::vector<const char*> argv_c;
|
||||
- argv_c.reserve(argv.size() + 1);
|
||||
- for (const std::string& argument : argv) {
|
||||
- argv_c.push_back(argument.c_str());
|
||||
- }
|
||||
- argv_c.push_back(nullptr);
|
||||
-
|
||||
- std::vector<const char*> envp_c;
|
||||
- if (envp) {
|
||||
- envp_c.reserve(envp->size() + 1);
|
||||
- for (const std::string& variable : *envp) {
|
||||
- envp_c.push_back(variable.c_str());
|
||||
- }
|
||||
- envp_c.push_back(nullptr);
|
||||
- }
|
||||
-
|
||||
- // Double-fork(). The three processes involved are parent, child, and
|
||||
- // grandchild. The grandchild will call execv(). The child exits immediately
|
||||
- // after spawning the grandchild, so the grandchild becomes an orphan and its
|
||||
- // parent process ID becomes 1. This relieves the parent and child of the
|
||||
- // responsibility to reap the grandchild with waitpid() or similar. The
|
||||
- // grandchild is expected to outlive the parent process, so the parent
|
||||
- // shouldn’t be concerned with reaping it. This approach means that accidental
|
||||
- // early termination of the handler process will not result in a zombie
|
||||
- // process.
|
||||
- pid_t pid = fork();
|
||||
- if (pid < 0) {
|
||||
- PLOG(ERROR) << "fork";
|
||||
- return false;
|
||||
- }
|
||||
-
|
||||
- if (pid == 0) {
|
||||
- // Child process.
|
||||
-
|
||||
- if (child_function) {
|
||||
- child_function();
|
||||
- }
|
||||
-
|
||||
- // Call setsid(), creating a new process group and a new session, both led
|
||||
- // by this process. The new process group has no controlling terminal. This
|
||||
- // disconnects it from signals generated by the parent process’ terminal.
|
||||
- //
|
||||
- // setsid() is done in the child instead of the grandchild so that the
|
||||
- // grandchild will not be a session leader. If it were a session leader, an
|
||||
- // accidental open() of a terminal device without O_NOCTTY would make that
|
||||
- // terminal the controlling terminal.
|
||||
- //
|
||||
- // It’s not desirable for the grandchild to have a controlling terminal. The
|
||||
- // grandchild manages its own lifetime, such as by monitoring clients on its
|
||||
- // own and exiting when it loses all clients and when it deems it
|
||||
- // appropraite to do so. It may serve clients in different process groups or
|
||||
- // sessions than its original client, and receiving signals intended for its
|
||||
- // original client’s process group could be harmful in that case.
|
||||
- PCHECK(setsid() != -1) << "setsid";
|
||||
-
|
||||
- pid = fork();
|
||||
- if (pid < 0) {
|
||||
- PLOG(FATAL) << "fork";
|
||||
- }
|
||||
-
|
||||
- if (pid > 0) {
|
||||
- // Child process.
|
||||
-
|
||||
- // _exit() instead of exit(), because fork() was called.
|
||||
- _exit(EXIT_SUCCESS);
|
||||
- }
|
||||
-
|
||||
- // Grandchild process.
|
||||
-
|
||||
- CloseMultipleNowOrOnExec(STDERR_FILENO + 1, preserve_fd);
|
||||
-
|
||||
- // &argv_c[0] is a pointer to a pointer to const char data, but because of
|
||||
- // how C (not C++) works, execvp() wants a pointer to a const pointer to
|
||||
- // char data. It modifies neither the data nor the pointers, so the
|
||||
- // const_cast is safe.
|
||||
- char* const* argv_for_execv = const_cast<char* const*>(&argv_c[0]);
|
||||
-
|
||||
- if (envp) {
|
||||
- // This cast is safe for the same reason that the argv_for_execv cast is.
|
||||
- char* const* envp_for_execv = const_cast<char* const*>(&envp_c[0]);
|
||||
- execve(argv_for_execv[0], argv_for_execv, envp_for_execv);
|
||||
- PLOG(FATAL) << "execve " << argv_for_execv[0];
|
||||
- }
|
||||
-
|
||||
- if (use_path) {
|
||||
- execvp(argv_for_execv[0], argv_for_execv);
|
||||
- PLOG(FATAL) << "execvp " << argv_for_execv[0];
|
||||
- }
|
||||
-
|
||||
- execv(argv_for_execv[0], argv_for_execv);
|
||||
- PLOG(FATAL) << "execv " << argv_for_execv[0];
|
||||
- }
|
||||
-
|
||||
- // waitpid() for the child, so that it does not become a zombie process. The
|
||||
- // child normally exits quickly.
|
||||
- //
|
||||
- // Failures from this point on may result in the accumulation of a zombie, but
|
||||
- // should not be considered fatal. Log only warnings, but don’t treat these
|
||||
- // failures as a failure of the function overall.
|
||||
- int status;
|
||||
- pid_t wait_pid = HANDLE_EINTR(waitpid(pid, &status, 0));
|
||||
- if (wait_pid == -1) {
|
||||
- PLOG(WARNING) << "waitpid";
|
||||
- return true;
|
||||
- }
|
||||
- DCHECK_EQ(wait_pid, pid);
|
||||
-
|
||||
- if (WIFSIGNALED(status)) {
|
||||
- int sig = WTERMSIG(status);
|
||||
- LOG(WARNING) << base::StringPrintf(
|
||||
- "intermediate process terminated by signal %d (%s)%s",
|
||||
- sig,
|
||||
- strsignal(sig),
|
||||
- WCOREDUMP(status) ? " (core dumped)" : "");
|
||||
- } else if (!WIFEXITED(status)) {
|
||||
- LOG(WARNING) << base::StringPrintf(
|
||||
- "intermediate process: unknown termination 0x%x", status);
|
||||
- } else if (WEXITSTATUS(status) != EXIT_SUCCESS) {
|
||||
- LOG(WARNING) << "intermediate process exited with code "
|
||||
- << WEXITSTATUS(status);
|
||||
- }
|
||||
-
|
||||
- return true;
|
||||
-}
|
||||
-
|
||||
-} // namespace crashpad
|
||||
diff --git a/third_party/crashpad/crashpad/util/posix/fork_and_spawn.cc b/third_party/crashpad/crashpad/util/posix/fork_and_spawn.cc
|
||||
new file mode 100644
|
||||
index 0000000000000000000000000000000000000000..0f11eea3c61db156bc2d2322ab1c38ff44ac35bc
|
||||
--- /dev/null
|
||||
+++ b/third_party/crashpad/crashpad/util/posix/fork_and_spawn.cc
|
||||
@@ -0,0 +1,235 @@
|
||||
+// Copyright 2017 The Crashpad Authors. All rights reserved.
|
||||
+//
|
||||
+// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
+// you may not use this file except in compliance with the License.
|
||||
+// You may obtain a copy of the License at
|
||||
+//
|
||||
+// http://www.apache.org/licenses/LICENSE-2.0
|
||||
+//
|
||||
+// Unless required by applicable law or agreed to in writing, software
|
||||
+// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
+// See the License for the specific language governing permissions and
|
||||
+// limitations under the License.
|
||||
+
|
||||
+#include "util/posix/fork_and_spawn.h"
|
||||
+
|
||||
+#include <errno.h>
|
||||
+#include <spawn.h>
|
||||
+#include <stdlib.h>
|
||||
+#include <string.h>
|
||||
+#include <sys/wait.h>
|
||||
+#include <unistd.h>
|
||||
+
|
||||
+#include "base/check.h"
|
||||
+#include "base/check_op.h"
|
||||
+#include "base/logging.h"
|
||||
+#include "base/posix/eintr_wrapper.h"
|
||||
+#include "base/strings/stringprintf.h"
|
||||
+#include "build/build_config.h"
|
||||
+#include "util/posix/close_multiple.h"
|
||||
+
|
||||
+extern char** environ;
|
||||
+
|
||||
+namespace crashpad {
|
||||
+
|
||||
+namespace {
|
||||
+
|
||||
+#if defined(OS_MAC)
|
||||
+
|
||||
+class PosixSpawnAttr {
|
||||
+ public:
|
||||
+ PosixSpawnAttr() {
|
||||
+ PCHECK((errno = posix_spawnattr_init(&attr_)) == 0)
|
||||
+ << "posix_spawnattr_init";
|
||||
+ }
|
||||
+
|
||||
+ PosixSpawnAttr(const PosixSpawnAttr&) = delete;
|
||||
+ PosixSpawnAttr& operator=(const PosixSpawnAttr&) = delete;
|
||||
+
|
||||
+ ~PosixSpawnAttr() {
|
||||
+ PCHECK((errno = posix_spawnattr_destroy(&attr_)) == 0)
|
||||
+ << "posix_spawnattr_destroy";
|
||||
+ }
|
||||
+
|
||||
+ void SetFlags(short flags) {
|
||||
+ PCHECK((errno = posix_spawnattr_setflags(&attr_, flags)) == 0)
|
||||
+ << "posix_spawnattr_setflags";
|
||||
+ }
|
||||
+
|
||||
+ const posix_spawnattr_t* Get() const { return &attr_; }
|
||||
+
|
||||
+ private:
|
||||
+ posix_spawnattr_t attr_;
|
||||
+};
|
||||
+
|
||||
+class PosixSpawnFileActions {
|
||||
+ public:
|
||||
+ PosixSpawnFileActions() {
|
||||
+ PCHECK((errno = posix_spawn_file_actions_init(&file_actions_)) == 0)
|
||||
+ << "posix_spawn_file_actions_init";
|
||||
+ }
|
||||
+
|
||||
+ PosixSpawnFileActions(const PosixSpawnFileActions&) = delete;
|
||||
+ PosixSpawnFileActions& operator=(const PosixSpawnFileActions&) = delete;
|
||||
+
|
||||
+ ~PosixSpawnFileActions() {
|
||||
+ PCHECK((errno = posix_spawn_file_actions_destroy(&file_actions_)) == 0)
|
||||
+ << "posix_spawn_file_actions_destroy";
|
||||
+ }
|
||||
+
|
||||
+ void AddInheritedFileDescriptor(int fd) {
|
||||
+ PCHECK((errno = posix_spawn_file_actions_addinherit_np(&file_actions_,
|
||||
+ fd)) == 0)
|
||||
+ << "posix_spawn_file_actions_addinherit_np";
|
||||
+ }
|
||||
+
|
||||
+ const posix_spawn_file_actions_t* Get() const { return &file_actions_; }
|
||||
+
|
||||
+ private:
|
||||
+ posix_spawn_file_actions_t file_actions_;
|
||||
+};
|
||||
+
|
||||
+#endif
|
||||
+
|
||||
+} // namespace
|
||||
+
|
||||
+bool ForkAndSpawn(const std::vector<std::string>& argv,
|
||||
+ const std::vector<std::string>* envp,
|
||||
+ int preserve_fd,
|
||||
+ bool use_path,
|
||||
+ void (*child_function)()) {
|
||||
+ // argv_c contains const char* pointers and is terminated by nullptr. This is
|
||||
+ // suitable for passing to posix_spawn() or posix_spawnp(). Although argv_c is
|
||||
+ // not used in the parent process, it must be built in the parent process
|
||||
+ // because it’s unsafe to do so in the child.
|
||||
+ std::vector<const char*> argv_c;
|
||||
+ argv_c.reserve(argv.size() + 1);
|
||||
+ for (const std::string& argument : argv) {
|
||||
+ argv_c.push_back(argument.c_str());
|
||||
+ }
|
||||
+ argv_c.push_back(nullptr);
|
||||
+
|
||||
+ std::vector<const char*> envp_c;
|
||||
+ if (envp) {
|
||||
+ envp_c.reserve(envp->size() + 1);
|
||||
+ for (const std::string& variable : *envp) {
|
||||
+ envp_c.push_back(variable.c_str());
|
||||
+ }
|
||||
+ envp_c.push_back(nullptr);
|
||||
+ }
|
||||
+
|
||||
+ // The three processes involved are parent, child, and grandchild. The child
|
||||
+ // exits immediately after spawning the grandchild, so the grandchild becomes
|
||||
+ // an orphan and its parent process ID becomes 1. This relieves the parent and
|
||||
+ // child of the responsibility to reap the grandchild with waitpid() or
|
||||
+ // similar. The grandchild is expected to outlive the parent process, so the
|
||||
+ // parent shouldn’t be concerned with reaping it. This approach means that
|
||||
+ // accidental early termination of the handler process will not result in a
|
||||
+ // zombie process.
|
||||
+ pid_t pid = fork();
|
||||
+ if (pid < 0) {
|
||||
+ PLOG(ERROR) << "fork";
|
||||
+ return false;
|
||||
+ }
|
||||
+
|
||||
+ if (pid == 0) {
|
||||
+ // Child process.
|
||||
+
|
||||
+ if (child_function) {
|
||||
+ child_function();
|
||||
+ }
|
||||
+
|
||||
+ // Call setsid(), creating a new process group and a new session, both led
|
||||
+ // by this process. The new process group has no controlling terminal. This
|
||||
+ // disconnects it from signals generated by the parent process’ terminal.
|
||||
+ //
|
||||
+ // setsid() is done in the child instead of the grandchild so that the
|
||||
+ // grandchild will not be a session leader. If it were a session leader, an
|
||||
+ // accidental open() of a terminal device without O_NOCTTY would make that
|
||||
+ // terminal the controlling terminal.
|
||||
+ //
|
||||
+ // It’s not desirable for the grandchild to have a controlling terminal. The
|
||||
+ // grandchild manages its own lifetime, such as by monitoring clients on its
|
||||
+ // own and exiting when it loses all clients and when it deems it
|
||||
+ // appropraite to do so. It may serve clients in different process groups or
|
||||
+ // sessions than its original client, and receiving signals intended for its
|
||||
+ // original client’s process group could be harmful in that case.
|
||||
+ PCHECK(setsid() != -1) << "setsid";
|
||||
+
|
||||
+ // &argv_c[0] is a pointer to a pointer to const char data, but because of
|
||||
+ // how C (not C++) works, posix_spawn() and posix_spawnp() want a pointer to
|
||||
+ // a const pointer to char data. They modifies neither the data nor the
|
||||
+ // pointers, so the const_cast is safe.
|
||||
+ char* const* argv_for_spawn = const_cast<char* const*>(argv_c.data());
|
||||
+
|
||||
+ // This cast is safe for the same reason that the argv_for_spawn cast is.
|
||||
+ char* const* envp_for_spawn =
|
||||
+ envp ? const_cast<char* const*>(envp_c.data()) : environ;
|
||||
+
|
||||
+#if defined(OS_MAC)
|
||||
+ PosixSpawnAttr attr;
|
||||
+ attr.SetFlags(POSIX_SPAWN_CLOEXEC_DEFAULT);
|
||||
+
|
||||
+ PosixSpawnFileActions file_actions;
|
||||
+ for (int fd = 0; fd <= STDERR_FILENO; ++fd) {
|
||||
+ file_actions.AddInheritedFileDescriptor(fd);
|
||||
+ }
|
||||
+ file_actions.AddInheritedFileDescriptor(preserve_fd);
|
||||
+
|
||||
+ const posix_spawnattr_t* attr_p = attr.Get();
|
||||
+ const posix_spawn_file_actions_t* file_actions_p = file_actions.Get();
|
||||
+#else
|
||||
+ CloseMultipleNowOrOnExec(STDERR_FILENO + 1, preserve_fd);
|
||||
+
|
||||
+ const posix_spawnattr_t* attr_p = nullptr;
|
||||
+ const posix_spawn_file_actions_t* file_actions_p = nullptr;
|
||||
+#endif
|
||||
+
|
||||
+ auto posix_spawn_fp = use_path ? posix_spawnp : posix_spawn;
|
||||
+ if ((errno = posix_spawn_fp(&pid,
|
||||
+ argv_for_spawn[0],
|
||||
+ file_actions_p,
|
||||
+ attr_p,
|
||||
+ argv_for_spawn,
|
||||
+ envp_for_spawn)) != 0) {
|
||||
+ PLOG(FATAL) << (use_path ? "posix_spawnp" : "posix_spawn");
|
||||
+ }
|
||||
+
|
||||
+ // _exit() instead of exit(), because fork() was called.
|
||||
+ _exit(EXIT_SUCCESS);
|
||||
+ }
|
||||
+
|
||||
+ // waitpid() for the child, so that it does not become a zombie process. The
|
||||
+ // child normally exits quickly.
|
||||
+ //
|
||||
+ // Failures from this point on may result in the accumulation of a zombie, but
|
||||
+ // should not be considered fatal. Log only warnings, but don’t treat these
|
||||
+ // failures as a failure of the function overall.
|
||||
+ int status;
|
||||
+ pid_t wait_pid = HANDLE_EINTR(waitpid(pid, &status, 0));
|
||||
+ if (wait_pid == -1) {
|
||||
+ PLOG(WARNING) << "waitpid";
|
||||
+ return true;
|
||||
+ }
|
||||
+ DCHECK_EQ(wait_pid, pid);
|
||||
+
|
||||
+ if (WIFSIGNALED(status)) {
|
||||
+ int sig = WTERMSIG(status);
|
||||
+ LOG(WARNING) << base::StringPrintf(
|
||||
+ "intermediate process terminated by signal %d (%s)%s",
|
||||
+ sig,
|
||||
+ strsignal(sig),
|
||||
+ WCOREDUMP(status) ? " (core dumped)" : "");
|
||||
+ } else if (!WIFEXITED(status)) {
|
||||
+ LOG(WARNING) << base::StringPrintf(
|
||||
+ "intermediate process: unknown termination 0x%x", status);
|
||||
+ } else if (WEXITSTATUS(status) != EXIT_SUCCESS) {
|
||||
+ LOG(WARNING) << "intermediate process exited with code "
|
||||
+ << WEXITSTATUS(status);
|
||||
+ }
|
||||
+
|
||||
+ return true;
|
||||
+}
|
||||
+
|
||||
+} // namespace crashpad
|
||||
diff --git a/third_party/crashpad/crashpad/util/posix/double_fork_and_exec.h b/third_party/crashpad/crashpad/util/posix/fork_and_spawn.h
|
||||
similarity index 76%
|
||||
rename from third_party/crashpad/crashpad/util/posix/double_fork_and_exec.h
|
||||
rename to third_party/crashpad/crashpad/util/posix/fork_and_spawn.h
|
||||
index 02fc0f28f196b447132a2dcfaebdaaa5a916a38a..fc55aa3a37652e4ba18c66db90124abd9cad2e51 100644
|
||||
--- a/third_party/crashpad/crashpad/util/posix/double_fork_and_exec.h
|
||||
+++ b/third_party/crashpad/crashpad/util/posix/fork_and_spawn.h
|
||||
@@ -12,8 +12,8 @@
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
-#ifndef CRASHPAD_UTIL_POSIX_DOUBLE_FORK_AND_EXEC_H_
|
||||
-#define CRASHPAD_UTIL_POSIX_DOUBLE_FORK_AND_EXEC_H_
|
||||
+#ifndef CRASHPAD_UTIL_POSIX_FORK_AND_SPAWN_H_
|
||||
+#define CRASHPAD_UTIL_POSIX_FORK_AND_SPAWN_H_
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
@@ -23,7 +23,7 @@ namespace crashpad {
|
||||
//! \brief Executes a (grand-)child process.
|
||||
//!
|
||||
//! The grandchild process will be started through the
|
||||
-//! double-`fork()`-and-`execv()` pattern. This allows the grandchild to fully
|
||||
+//! `fork()`-and-`posix_spawn()` pattern. This allows the grandchild to fully
|
||||
//! disassociate from the parent. The grandchild will not be a member of the
|
||||
//! parent’s process group or session and will not have a controlling terminal,
|
||||
//! providing isolation from signals not intended for it. The grandchild’s
|
||||
@@ -37,7 +37,7 @@ namespace crashpad {
|
||||
//! \param[in] argv The argument vector to start the grandchild process with.
|
||||
//! `argv[0]` is used as the path to the executable.
|
||||
//! \param[in] envp A vector of environment variables of the form `var=value` to
|
||||
-//! be passed to `execve()`. If this value is `nullptr`, the current
|
||||
+//! be passed to `posix_spawn()`. If this value is `nullptr`, the current
|
||||
//! environment is used.
|
||||
//! \param[in] preserve_fd A file descriptor to be inherited by the grandchild
|
||||
//! process. This file descriptor is inherited in addition to the three file
|
||||
@@ -45,16 +45,13 @@ namespace crashpad {
|
||||
//! if no additional file descriptors are to be inherited.
|
||||
//! \param[in] use_path Whether to consult the `PATH` environment variable when
|
||||
//! requested to start an executable at a non-absolute path. If `false`,
|
||||
-//! `execv()`, which does not consult `PATH`, will be used. If `true`,
|
||||
-//! `execvp()`, which does consult `PATH`, will be used.
|
||||
+//! `posix_spawn()`, which does not consult `PATH`, will be used. If `true`,
|
||||
+//! `posix_spawnp()`, which does consult `PATH`, will be used.
|
||||
//! \param[in] child_function If not `nullptr`, this function will be called in
|
||||
-//! the intermediate child process, prior to the second `fork()`. Take note
|
||||
+//! the intermediate child process, prior to the `posix_spawn()`. Take note
|
||||
//! that this function will run in the context of a forked process, and must
|
||||
//! be safe for that purpose.
|
||||
//!
|
||||
-//! Setting both \a envp to a value other than `nullptr` and \a use_path to
|
||||
-//! `true` is not currently supported.
|
||||
-//!
|
||||
//! \return `true` on success, and `false` on failure with a message logged.
|
||||
//! Only failures that occur in the parent process that indicate a definite
|
||||
//! failure to start the the grandchild are reported in the return value.
|
||||
@@ -63,12 +60,12 @@ namespace crashpad {
|
||||
//! terminating. The caller assumes the responsibility for detecting such
|
||||
//! failures, for example, by observing a failure to perform a successful
|
||||
//! handshake with the grandchild process.
|
||||
-bool DoubleForkAndExec(const std::vector<std::string>& argv,
|
||||
- const std::vector<std::string>* envp,
|
||||
- int preserve_fd,
|
||||
- bool use_path,
|
||||
- void (*child_function)());
|
||||
+bool ForkAndSpawn(const std::vector<std::string>& argv,
|
||||
+ const std::vector<std::string>* envp,
|
||||
+ int preserve_fd,
|
||||
+ bool use_path,
|
||||
+ void (*child_function)());
|
||||
|
||||
} // namespace crashpad
|
||||
|
||||
-#endif // CRASHPAD_UTIL_POSIX_DOUBLE_FORK_AND_EXEC_H_
|
||||
+#endif // CRASHPAD_UTIL_POSIX_FORK_AND_SPAWN_H_
|
||||
@@ -0,0 +1,242 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Garrett Tanzer <gtanzer@chromium.org>
|
||||
Date: Wed, 2 Mar 2022 18:33:42 +0000
|
||||
Subject: Reland "Fix noopener case for user activation consumption"
|
||||
|
||||
This is a reland of e9828a82b5c182dc9a7fb0ae7226c35ba1726e7d
|
||||
|
||||
The MSAN error is from checking status before err in
|
||||
content/renderer/render_view_impl.cc .
|
||||
https://ci.chromium.org/ui/p/chromium/builders/ci/Linux%20ChromiumOS%20MSan%20Tests/b8821495655905086193/overview
|
||||
|
||||
The fix is to split the check for err and kIgnore into two checks,
|
||||
and put the err check before kBlocked.
|
||||
|
||||
It is probably possible for the browser to consume user activation
|
||||
but then eventually mojo returns an error and the renderer doesn't
|
||||
consume activation, but that seems pretty marginal.
|
||||
|
||||
Original change's description:
|
||||
> Fix noopener case for user activation consumption
|
||||
>
|
||||
>
|
||||
> The flow for user activation consumption in window.open was as follows:
|
||||
>
|
||||
> Renderer: ask the browser to create a new window
|
||||
> Browser: consume transient user activation (in the browser, and via RPC
|
||||
> to remote frames only)
|
||||
> Browser: return success for opener, return ignore for noopener
|
||||
> Renderer: consume transient user activation upon success
|
||||
>
|
||||
> So in the noopener case, the renderer with the local frame where the
|
||||
> window.open originated didn't have its transient user activation
|
||||
> consumed.
|
||||
>
|
||||
>
|
||||
> The new behavior is to consume user activation in the calling renderer
|
||||
> whenever it is consumed in the browser. We accomplish this by returning
|
||||
> a distinct value kBlocked to represent failure before the browser
|
||||
> consumes user activation.
|
||||
>
|
||||
> Bug: 1264543, 1291210
|
||||
> Change-Id: Iffb6e3fd772bef625d3d28e600e6fb73d70ab29f
|
||||
> Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3468171
|
||||
> Reviewed-by: Dominic Farolino <dom@chromium.org>
|
||||
> Reviewed-by: Ken Buchanan <kenrb@chromium.org>
|
||||
> Reviewed-by: Mustaq Ahmed <mustaq@chromium.org>
|
||||
> Reviewed-by: Charles Reis <creis@chromium.org>
|
||||
> Reviewed-by: Jonathan Ross <jonross@chromium.org>
|
||||
> Reviewed-by: Daniel Cheng <dcheng@chromium.org>
|
||||
> Commit-Queue: Garrett Tanzer <gtanzer@chromium.org>
|
||||
> Cr-Commit-Position: refs/heads/main@{#973876}
|
||||
|
||||
Bug: 1264543, 1291210
|
||||
Change-Id: Ie27c4d68db34dfd98adee7cc5c743953dad59834
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3481666
|
||||
Reviewed-by: Jonathan Ross <jonross@chromium.org>
|
||||
Reviewed-by: Daniel Cheng <dcheng@chromium.org>
|
||||
Reviewed-by: Mustaq Ahmed <mustaq@chromium.org>
|
||||
Reviewed-by: Ken Buchanan <kenrb@chromium.org>
|
||||
Reviewed-by: Charles Reis <creis@chromium.org>
|
||||
Commit-Queue: Garrett Tanzer <gtanzer@chromium.org>
|
||||
Cr-Commit-Position: refs/heads/main@{#976745}
|
||||
|
||||
diff --git a/chrome/browser/site_isolation/chrome_site_per_process_browsertest.cc b/chrome/browser/site_isolation/chrome_site_per_process_browsertest.cc
|
||||
index 84867adc5ec36ac76a4d043e80d331ff314858d5..6c21360f68569805989598e525c89ad44ecaba11 100644
|
||||
--- a/chrome/browser/site_isolation/chrome_site_per_process_browsertest.cc
|
||||
+++ b/chrome/browser/site_isolation/chrome_site_per_process_browsertest.cc
|
||||
@@ -1187,6 +1187,52 @@ IN_PROC_BROWSER_TEST_F(ChromeSitePerProcessTest,
|
||||
EXPECT_FALSE(frame_c_popup_opened);
|
||||
}
|
||||
|
||||
+// Test that opening a window with `noopener` consumes user activation.
|
||||
+// crbug.com/1264543, crbug.com/1291210
|
||||
+IN_PROC_BROWSER_TEST_F(ChromeSitePerProcessTest,
|
||||
+ UserActivationConsumptionNoopener) {
|
||||
+ // Start on a page a.com.
|
||||
+ GURL main_url(embedded_test_server()->GetURL(
|
||||
+ "a.com", "/cross_site_iframe_factory.html?a"));
|
||||
+ ASSERT_TRUE(ui_test_utils::NavigateToURL(browser(), main_url));
|
||||
+ content::WebContents* web_contents =
|
||||
+ browser()->tab_strip_model()->GetActiveWebContents();
|
||||
+
|
||||
+ // Activate the frame by executing a dummy script.
|
||||
+ const std::string no_op_script = "// No-op script";
|
||||
+ EXPECT_TRUE(ExecuteScript(web_contents, no_op_script));
|
||||
+
|
||||
+ // Add a popup observer.
|
||||
+ content::TestNavigationObserver popup_observer(nullptr);
|
||||
+ popup_observer.StartWatchingNewWebContents();
|
||||
+
|
||||
+ // Open a popup from the frame, with `noopener`. This should consume
|
||||
+ // transient user activation.
|
||||
+ GURL popup_url(embedded_test_server()->GetURL("popup.com", "/"));
|
||||
+ EXPECT_TRUE(ExecuteScriptWithoutUserGesture(
|
||||
+ web_contents,
|
||||
+ base::StringPrintf(
|
||||
+ "window.w = window.open('%s'+'title1.html', '_blank', 'noopener');",
|
||||
+ popup_url.spec().c_str())));
|
||||
+
|
||||
+ // Try to open another popup.
|
||||
+ EXPECT_TRUE(ExecuteScriptWithoutUserGesture(
|
||||
+ web_contents,
|
||||
+ base::StringPrintf(
|
||||
+ "window.w = window.open('%s'+'title2.html', '_blank', 'noopener');",
|
||||
+ popup_url.spec().c_str())));
|
||||
+
|
||||
+ // Wait and check that only one popup was opened.
|
||||
+ popup_observer.Wait();
|
||||
+ EXPECT_EQ(2, browser()->tab_strip_model()->count());
|
||||
+
|
||||
+ content::WebContents* popup =
|
||||
+ browser()->tab_strip_model()->GetActiveWebContents();
|
||||
+ EXPECT_EQ(embedded_test_server()->GetURL("popup.com", "/title1.html"),
|
||||
+ popup->GetLastCommittedURL());
|
||||
+ EXPECT_NE(popup, web_contents);
|
||||
+}
|
||||
+
|
||||
// TODO(crbug.com/1021895): Flaky.
|
||||
// Tests that a cross-site iframe runs its beforeunload handler when closing a
|
||||
// tab. See https://crbug.com/853021.
|
||||
diff --git a/content/browser/renderer_host/render_frame_host_impl.cc b/content/browser/renderer_host/render_frame_host_impl.cc
|
||||
index 6bcd908794675c046bbfed26a979f7fbf123b190..4fc8b67dc616ed744735d5f6ce9a6d985edcef09 100644
|
||||
--- a/content/browser/renderer_host/render_frame_host_impl.cc
|
||||
+++ b/content/browser/renderer_host/render_frame_host_impl.cc
|
||||
@@ -6639,17 +6639,22 @@ void RenderFrameHostImpl::CreateNewWindow(
|
||||
effective_transient_activation_state, params->opener_suppressed,
|
||||
&no_javascript_access);
|
||||
|
||||
- bool was_consumed = false;
|
||||
- if (can_create_window) {
|
||||
- // Consume activation even w/o User Activation v2, to sync other renderers
|
||||
- // with calling renderer.
|
||||
- was_consumed = frame_tree_node_->UpdateUserActivationState(
|
||||
- blink::mojom::UserActivationUpdateType::kConsumeTransientActivation,
|
||||
- blink::mojom::UserActivationNotificationType::kNone);
|
||||
- } else {
|
||||
- std::move(callback).Run(mojom::CreateNewWindowStatus::kIgnore, nullptr);
|
||||
- return;
|
||||
- }
|
||||
+ // If this frame isn't allowed to create a window, return early (before we
|
||||
+ // consume transient user activation).
|
||||
+ if (!can_create_window) {
|
||||
+ std::move(callback).Run(mojom::CreateNewWindowStatus::kBlocked, nullptr);
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
+ // Otherwise, consume user activation before we proceed. In particular, it is
|
||||
+ // important to do this before we return from the |opener_suppressed| case
|
||||
+ // below.
|
||||
+ // NB: This call will consume activations in the browser and the remote frame
|
||||
+ // proxies for this frame. The initiating renderer will consume its view of
|
||||
+ // the activations after we return.
|
||||
+ bool was_consumed = frame_tree_node_->UpdateUserActivationState(
|
||||
+ blink::mojom::UserActivationUpdateType::kConsumeTransientActivation,
|
||||
+ blink::mojom::UserActivationNotificationType::kNone);
|
||||
|
||||
// For Android WebView, we support a pop-up like behavior for window.open()
|
||||
// even if the embedding app doesn't support multiple windows. In this case,
|
||||
diff --git a/content/common/frame.mojom b/content/common/frame.mojom
|
||||
index da44b637ee5fdf371974f322aaf1a07ba8c018d7..44444b35b55e6dd3af181b256515d4dad6cba749 100644
|
||||
--- a/content/common/frame.mojom
|
||||
+++ b/content/common/frame.mojom
|
||||
@@ -558,8 +558,10 @@ struct CreateNewWindowParams {
|
||||
|
||||
// Operation result when the renderer asks the browser to create a new window.
|
||||
enum CreateNewWindowStatus {
|
||||
- // Ignore creation of the new window. This can happen because creation is
|
||||
- // blocked or because the new window should have no opener relationship.
|
||||
+ // Creation of the new window was blocked, e.g. because the source frame
|
||||
+ // doesn't have user activation.
|
||||
+ kBlocked,
|
||||
+ // Ignore creation of the new window, e.g. because noopener is in effect.
|
||||
kIgnore,
|
||||
// Reuse the current window rather than creating a new window.
|
||||
kReuse,
|
||||
diff --git a/content/renderer/render_view_impl.cc b/content/renderer/render_view_impl.cc
|
||||
index 190b517cea51bd3eae29695ba45efb22c4c82877..e1d189467bbd266de01da186c1fac6e20c9f35ad 100644
|
||||
--- a/content/renderer/render_view_impl.cc
|
||||
+++ b/content/renderer/render_view_impl.cc
|
||||
@@ -310,8 +310,27 @@ WebView* RenderViewImpl::CreateView(
|
||||
mojom::CreateNewWindowStatus status;
|
||||
mojom::CreateNewWindowReplyPtr reply;
|
||||
auto* frame_host = creator_frame->GetFrameHost();
|
||||
- bool err = !frame_host->CreateNewWindow(std::move(params), &status, &reply);
|
||||
- if (err || status == mojom::CreateNewWindowStatus::kIgnore)
|
||||
+ if (!frame_host->CreateNewWindow(std::move(params), &status, &reply)) {
|
||||
+ // The sync IPC failed, e.g. maybe the render process is in the middle of
|
||||
+ // shutting down. Can't create a new window without the browser process,
|
||||
+ // so just bail out.
|
||||
+ return nullptr;
|
||||
+ }
|
||||
+
|
||||
+ // If creation of the window was blocked (e.g. because this frame doesn't
|
||||
+ // have user activation), return before consuming user activation. A frame
|
||||
+ // that isn't allowed to open a window shouldn't be able to consume the
|
||||
+ // activation for the rest of the frame tree.
|
||||
+ if (status == mojom::CreateNewWindowStatus::kBlocked)
|
||||
+ return nullptr;
|
||||
+
|
||||
+ // Consume the transient user activation in the current renderer.
|
||||
+ consumed_user_gesture = creator->ConsumeTransientUserActivation(
|
||||
+ blink::UserActivationUpdateSource::kBrowser);
|
||||
+
|
||||
+ // If we should ignore the new window (e.g. because of `noopener`), return
|
||||
+ // now that user activation was consumed.
|
||||
+ if (status == mojom::CreateNewWindowStatus::kIgnore)
|
||||
return nullptr;
|
||||
|
||||
// For Android WebView, we support a pop-up like behavior for window.open()
|
||||
@@ -331,11 +350,6 @@ WebView* RenderViewImpl::CreateView(
|
||||
DCHECK_NE(MSG_ROUTING_NONE, reply->main_frame_route_id);
|
||||
DCHECK_NE(MSG_ROUTING_NONE, reply->widget_params->routing_id);
|
||||
|
||||
- // The browser allowed creation of a new window and consumed the user
|
||||
- // activation.
|
||||
- consumed_user_gesture = creator->ConsumeTransientUserActivation(
|
||||
- blink::UserActivationUpdateSource::kBrowser);
|
||||
-
|
||||
// While this view may be a background extension page, it can spawn a visible
|
||||
// render view. So we just assume that the new one is not another background
|
||||
// page instead of passing on our own value.
|
||||
diff --git a/third_party/blink/web_tests/wpt_internal/fenced_frame/restrict-size.https.html b/third_party/blink/web_tests/wpt_internal/fenced_frame/restrict-size.https.html
|
||||
new file mode 100644
|
||||
index 0000000000000000000000000000000000000000..5668407d7e1e6ac7840fc47b76869787cb3f3d63
|
||||
--- /dev/null
|
||||
+++ b/third_party/blink/web_tests/wpt_internal/fenced_frame/restrict-size.https.html
|
||||
@@ -0,0 +1,15 @@
|
||||
+<!DOCTYPE html>
|
||||
+<title>Test fencedframe size restrictions in opaque ads mode.</title>
|
||||
+<script src="/resources/testharness.js"></script>
|
||||
+<script src="/resources/testharnessreport.js"></script>
|
||||
+<script src="/common/utils.js"></script>
|
||||
+<script src="/common/dispatcher/dispatcher.js"></script>
|
||||
+<script src="resources/utils.js"></script>
|
||||
+
|
||||
+<body>
|
||||
+<script>
|
||||
+promise_test(async () => {
|
||||
+ const frame = attachFencedFrameContext();
|
||||
+}, 'restrict fencedframe size');
|
||||
+</script>
|
||||
+</body>
|
||||
@@ -0,0 +1,72 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Nico Weber <thakis@chromium.org>
|
||||
Date: Thu, 24 Feb 2022 18:15:16 +0000
|
||||
Subject: Revert "[motionmark] Avoid unnecessary IPC on mac."
|
||||
|
||||
This reverts
|
||||
https://chromium-review.googlesource.com/c/chromium/src/+/2923689
|
||||
|
||||
It caused us to never hit 120 Hz on ProMotion displays. Revert until
|
||||
we can figure out a fix.
|
||||
|
||||
Bug: 1274172
|
||||
Change-Id: Ia09bb0fdaf63509e08755346844dc58b59d8bb6a
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3488608
|
||||
Commit-Queue: Nico Weber <thakis@chromium.org>
|
||||
Auto-Submit: Nico Weber <thakis@chromium.org>
|
||||
Reviewed-by: Sadrul Chowdhury <sadrul@chromium.org>
|
||||
Commit-Queue: Sadrul Chowdhury <sadrul@chromium.org>
|
||||
Cr-Commit-Position: refs/heads/main@{#974729}
|
||||
|
||||
diff --git a/components/viz/service/frame_sinks/root_compositor_frame_sink_impl.cc b/components/viz/service/frame_sinks/root_compositor_frame_sink_impl.cc
|
||||
index 6efcb84af529a78e9ebc1234ef4d0c8834270c29..94bef837cb6b4c2ac379f6cab6fdcc8599c7e0c2 100644
|
||||
--- a/components/viz/service/frame_sinks/root_compositor_frame_sink_impl.cc
|
||||
+++ b/components/viz/service/frame_sinks/root_compositor_frame_sink_impl.cc
|
||||
@@ -510,13 +510,10 @@ base::ScopedClosureRunner RootCompositorFrameSinkImpl::GetCacheBackBufferCb() {
|
||||
|
||||
void RootCompositorFrameSinkImpl::DisplayDidReceiveCALayerParams(
|
||||
const gfx::CALayerParams& ca_layer_params) {
|
||||
- if (last_ca_layer_params_ == ca_layer_params)
|
||||
- return;
|
||||
#if defined(OS_APPLE)
|
||||
// If |ca_layer_params| should have content only when there exists a client
|
||||
// to send it to.
|
||||
DCHECK(ca_layer_params.is_empty || display_client_);
|
||||
- last_ca_layer_params_ = ca_layer_params;
|
||||
if (display_client_)
|
||||
display_client_->OnDisplayReceivedCALayerParams(ca_layer_params);
|
||||
#else
|
||||
diff --git a/components/viz/service/frame_sinks/root_compositor_frame_sink_impl.h b/components/viz/service/frame_sinks/root_compositor_frame_sink_impl.h
|
||||
index cd3ed5baba3198d4f827cebf7ba89a5fefdf7087..ddb31074f8dbdbf88e4a1126f414b1afbdd589db 100644
|
||||
--- a/components/viz/service/frame_sinks/root_compositor_frame_sink_impl.h
|
||||
+++ b/components/viz/service/frame_sinks/root_compositor_frame_sink_impl.h
|
||||
@@ -193,8 +193,6 @@ class VIZ_SERVICE_EXPORT RootCompositorFrameSinkImpl
|
||||
gfx::Size last_swap_pixel_size_;
|
||||
#endif
|
||||
|
||||
- gfx::CALayerParams last_ca_layer_params_;
|
||||
-
|
||||
#if defined(OS_ANDROID)
|
||||
// Let client control whether it wants `DidCompleteSwapWithSize`.
|
||||
bool enable_swap_competion_callback_ = false;
|
||||
diff --git a/ui/gfx/ca_layer_params.h b/ui/gfx/ca_layer_params.h
|
||||
index ba5767a80d13e848b7281f55307f6569a1524ce3..dcee2ec9de0e759b868b0de2c7106b2cf084c41c 100644
|
||||
--- a/ui/gfx/ca_layer_params.h
|
||||
+++ b/ui/gfx/ca_layer_params.h
|
||||
@@ -26,16 +26,6 @@ struct GFX_EXPORT CALayerParams {
|
||||
CALayerParams& operator=(const CALayerParams& params);
|
||||
~CALayerParams();
|
||||
|
||||
- bool operator==(const CALayerParams& params) const {
|
||||
- return is_empty == params.is_empty &&
|
||||
- ca_context_id == params.ca_context_id &&
|
||||
-#if defined(OS_MAC)
|
||||
- io_surface_mach_port == params.io_surface_mach_port &&
|
||||
-#endif
|
||||
- pixel_size == params.pixel_size &&
|
||||
- scale_factor == params.scale_factor;
|
||||
- }
|
||||
-
|
||||
// The |is_empty| flag is used to short-circuit code to handle CALayerParams
|
||||
// on non-macOS platforms.
|
||||
bool is_empty = true;
|
||||
@@ -0,0 +1,79 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Michael Ludwig <michaelludwig@google.com>
|
||||
Date: Sat, 2 Apr 2022 01:05:15 +0000
|
||||
Subject: Use RectF::Intersect in ApplyScissor
|
||||
|
||||
(cherry picked from commit 540e2ecde447b0757dd5bb079a59d8faef3183c1)
|
||||
|
||||
Bug: 1299287, 1307317
|
||||
Change-Id: I026090466ebfb3dee0e9daf0609f04babcf42092
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3516507
|
||||
Reviewed-by: Kyle Charbonneau <kylechar@chromium.org>
|
||||
Reviewed-by: Brian Sheedy <bsheedy@chromium.org>
|
||||
Commit-Queue: Michael Ludwig <michaelludwig@google.com>
|
||||
Cr-Original-Commit-Position: refs/heads/main@{#982400}
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3564640
|
||||
Cr-Commit-Position: refs/branch-heads/4896@{#1017}
|
||||
Cr-Branched-From: 1f63ff4bc27570761b35ffbc7f938f6586f7bee8-refs/heads/main@{#972766}
|
||||
|
||||
diff --git a/components/viz/service/display/skia_renderer.cc b/components/viz/service/display/skia_renderer.cc
|
||||
index ab0f0531ba9431cdadec734fe4215bcdbc39dae4..8c87ef7cce26bf9832549146f801c15b9d963e0f 100644
|
||||
--- a/components/viz/service/display/skia_renderer.cc
|
||||
+++ b/components/viz/service/display/skia_renderer.cc
|
||||
@@ -1421,34 +1421,20 @@ void SkiaRenderer::DrawQuadParams::ApplyScissor(
|
||||
// device space, it will be contained in in the original scissor.
|
||||
// Applying the scissor explicitly means avoiding a clipRect() call and
|
||||
// allows more quads to be batched together in a DrawEdgeAAImageSet call
|
||||
- float left_inset = local_scissor.x() - visible_rect.x();
|
||||
- float top_inset = local_scissor.y() - visible_rect.y();
|
||||
- float right_inset = visible_rect.right() - local_scissor.right();
|
||||
- float bottom_inset = visible_rect.bottom() - local_scissor.bottom();
|
||||
+ float x_epsilon = kAAEpsilon / content_device_transform.matrix().get(0, 0);
|
||||
+ float y_epsilon = kAAEpsilon / content_device_transform.matrix().get(1, 1);
|
||||
|
||||
- // The scissor is a non-AA clip, so we unset the bit flag for clipped edges.
|
||||
- if (left_inset >= kAAEpsilon) {
|
||||
+ // The scissor is a non-AA clip, so unset the bit flag for clipped edges.
|
||||
+ if (local_scissor.x() - visible_rect.x() >= x_epsilon)
|
||||
aa_flags &= ~SkCanvas::kLeft_QuadAAFlag;
|
||||
- } else {
|
||||
- left_inset = 0;
|
||||
- }
|
||||
- if (top_inset >= kAAEpsilon) {
|
||||
+ if (local_scissor.y() - visible_rect.y() >= y_epsilon)
|
||||
aa_flags &= ~SkCanvas::kTop_QuadAAFlag;
|
||||
- } else {
|
||||
- top_inset = 0;
|
||||
- }
|
||||
- if (right_inset >= kAAEpsilon) {
|
||||
+ if (visible_rect.right() - local_scissor.right() >= x_epsilon)
|
||||
aa_flags &= ~SkCanvas::kRight_QuadAAFlag;
|
||||
- } else {
|
||||
- right_inset = 0;
|
||||
- }
|
||||
- if (bottom_inset >= kAAEpsilon) {
|
||||
+ if (visible_rect.bottom() - local_scissor.bottom() >= y_epsilon)
|
||||
aa_flags &= ~SkCanvas::kBottom_QuadAAFlag;
|
||||
- } else {
|
||||
- bottom_inset = 0;
|
||||
- }
|
||||
|
||||
- visible_rect.Inset(left_inset, top_inset, right_inset, bottom_inset);
|
||||
+ visible_rect.Intersect(local_scissor);
|
||||
vis_tex_coords = visible_rect;
|
||||
scissor_rect.reset();
|
||||
}
|
||||
diff --git a/content/test/gpu/gpu_tests/test_expectations/pixel_expectations.txt b/content/test/gpu/gpu_tests/test_expectations/pixel_expectations.txt
|
||||
index 0b88dc6803e39d76acb2e4e42b8140b35ff49b34..132b9c5480ff6557909305259e624b89b502b050 100644
|
||||
--- a/content/test/gpu/gpu_tests/test_expectations/pixel_expectations.txt
|
||||
+++ b/content/test/gpu/gpu_tests/test_expectations/pixel_expectations.txt
|
||||
@@ -339,6 +339,9 @@ crbug.com/948141 Pixel_CanvasDisplaySRGBAccelerated2D [ Failure ]
|
||||
crbug.com/883500 [ android android-nexus-5 ] Pixel_BackgroundImage [ Failure ]
|
||||
crbug.com/1029389 [ android android-nexus-5 ] Pixel_PrecisionRoundedCorner [ Failure ]
|
||||
|
||||
+# Fails on Nexus 5X.
|
||||
+crbug.com/1307317 [ android android-chromium android-nexus-5x ] Pixel_PrecisionRoundedCorner [ Failure ]
|
||||
+
|
||||
# Flakes on Nexus 5X.
|
||||
crbug.com/883500 [ android android-chromium android-nexus-5x ] Pixel_BackgroundImage [ RetryOnFailure ]
|
||||
crbug.com/1065514 [ android android-chromium android-nexus-5x ] Pixel_WebGLReadPixelsTabSwitch [ RetryOnFailure ]
|
||||
@@ -7,7 +7,7 @@ Make chrome's install-sysroot scripts point to our custom sysroot builds,
|
||||
which include extra deps that Electron needs (e.g. libnotify)
|
||||
|
||||
diff --git a/build/linux/sysroot_scripts/install-sysroot.py b/build/linux/sysroot_scripts/install-sysroot.py
|
||||
index ada6208644cb22c9f51c571f9509e335c0836163..86b55223fc21adf0e01cb276ebc613f6ea24f8b2 100755
|
||||
index ada6208644cb22c9f51c571f9509e335c0836163..8f7169a0837a80c05faebce85ab4feac9e02bde2 100755
|
||||
--- a/build/linux/sysroot_scripts/install-sysroot.py
|
||||
+++ b/build/linux/sysroot_scripts/install-sysroot.py
|
||||
@@ -41,9 +41,11 @@ except ImportError:
|
||||
@@ -19,8 +19,8 @@ index ada6208644cb22c9f51c571f9509e335c0836163..86b55223fc21adf0e01cb276ebc613f6
|
||||
|
||||
-URL_PREFIX = 'https://commondatastorage.googleapis.com'
|
||||
-URL_PATH = 'chrome-linux-sysroot/toolchain'
|
||||
+URL_PREFIX = 'https://s3.amazonaws.com'
|
||||
+URL_PATH = 'electronjs-sysroots/toolchain'
|
||||
+URL_PREFIX = 'https://dev-cdn.electronjs.org'
|
||||
+URL_PATH = 'linux-sysroots'
|
||||
|
||||
VALID_ARCHS = ('arm', 'arm64', 'i386', 'amd64', 'mips', 'mips64el')
|
||||
|
||||
|
||||
190
patches/chromium/use-after-free_of_id_and_idref_attributes.patch
Normal file
190
patches/chromium/use-after-free_of_id_and_idref_attributes.patch
Normal file
@@ -0,0 +1,190 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Nick Wellnhofer <wellnhofer@aevum.de>
|
||||
Date: Tue, 8 Feb 2022 03:29:24 +0100
|
||||
Subject: Use-after-free of ID and IDREF attributes
|
||||
|
||||
If a document is parsed with XML_PARSE_DTDVALID and without
|
||||
XML_PARSE_NOENT, the value of ID attributes has to be normalized after
|
||||
potentially expanding entities in xmlRemoveID. Otherwise, later calls
|
||||
to xmlGetID can return a pointer to previously freed memory.
|
||||
|
||||
ID attributes which are empty or contain only whitespace after
|
||||
entity expansion are affected in a similar way. This is fixed by
|
||||
not storing such attributes in the ID table.
|
||||
|
||||
The test to detect streaming mode when validating against a DTD was
|
||||
broken. In connection with the defects above, this could result in a
|
||||
use-after-free when using the xmlReader interface with validation.
|
||||
Fix detection of streaming mode to avoid similar issues. (This changes
|
||||
the expected result of a test case. But as far as I can tell, using the
|
||||
XML reader with XIncludes referencing the root document never worked
|
||||
properly, anyway.)
|
||||
|
||||
All of these issues can result in denial of service. Using xmlReader
|
||||
with validation could result in disclosure of memory via the error
|
||||
channel, typically stderr. The security impact of xmlGetID returning
|
||||
a pointer to freed memory depends on the application. The typical use
|
||||
case of calling xmlGetID on an unmodified document is not affected.
|
||||
|
||||
diff --git a/third_party/libxml/src/valid.c b/third_party/libxml/src/valid.c
|
||||
index 5ee391c0418327f5e46293aedafdb353550f6f5b..8e596f1db3db40a5decc5f4b529abc7588c6bd66 100644
|
||||
--- a/third_party/libxml/src/valid.c
|
||||
+++ b/third_party/libxml/src/valid.c
|
||||
@@ -479,6 +479,35 @@ nodeVPop(xmlValidCtxtPtr ctxt)
|
||||
return (ret);
|
||||
}
|
||||
|
||||
+/**
|
||||
+ * xmlValidNormalizeString:
|
||||
+ * @str: a string
|
||||
+ *
|
||||
+ * Normalize a string in-place.
|
||||
+ */
|
||||
+static void
|
||||
+xmlValidNormalizeString(xmlChar *str) {
|
||||
+ xmlChar *dst;
|
||||
+ const xmlChar *src;
|
||||
+
|
||||
+ if (str == NULL)
|
||||
+ return;
|
||||
+ src = str;
|
||||
+ dst = str;
|
||||
+
|
||||
+ while (*src == 0x20) src++;
|
||||
+ while (*src != 0) {
|
||||
+ if (*src == 0x20) {
|
||||
+ while (*src == 0x20) src++;
|
||||
+ if (*src != 0)
|
||||
+ *dst++ = 0x20;
|
||||
+ } else {
|
||||
+ *dst++ = *src++;
|
||||
+ }
|
||||
+ }
|
||||
+ *dst = 0;
|
||||
+}
|
||||
+
|
||||
#ifdef DEBUG_VALID_ALGO
|
||||
static void
|
||||
xmlValidPrintNode(xmlNodePtr cur) {
|
||||
@@ -2607,6 +2636,24 @@ xmlDumpNotationTable(xmlBufferPtr buf, xmlNotationTablePtr table) {
|
||||
(xmlDictOwns(dict, (const xmlChar *)(str)) == 0))) \
|
||||
xmlFree((char *)(str));
|
||||
|
||||
+static int
|
||||
+xmlIsStreaming(xmlValidCtxtPtr ctxt) {
|
||||
+ xmlParserCtxtPtr pctxt;
|
||||
+
|
||||
+ if (ctxt == NULL)
|
||||
+ return(0);
|
||||
+ /*
|
||||
+ * These magic values are also abused to detect whether we're validating
|
||||
+ * while parsing a document. In this case, userData points to the parser
|
||||
+ * context.
|
||||
+ */
|
||||
+ if ((ctxt->finishDtd != XML_CTXT_FINISH_DTD_0) &&
|
||||
+ (ctxt->finishDtd != XML_CTXT_FINISH_DTD_1))
|
||||
+ return(0);
|
||||
+ pctxt = ctxt->userData;
|
||||
+ return(pctxt->parseMode == XML_PARSE_READER);
|
||||
+}
|
||||
+
|
||||
/**
|
||||
* xmlFreeID:
|
||||
* @not: A id
|
||||
@@ -2650,7 +2697,7 @@ xmlAddID(xmlValidCtxtPtr ctxt, xmlDocPtr doc, const xmlChar *value,
|
||||
if (doc == NULL) {
|
||||
return(NULL);
|
||||
}
|
||||
- if (value == NULL) {
|
||||
+ if ((value == NULL) || (value[0] == 0)) {
|
||||
return(NULL);
|
||||
}
|
||||
if (attr == NULL) {
|
||||
@@ -2681,7 +2728,7 @@ xmlAddID(xmlValidCtxtPtr ctxt, xmlDocPtr doc, const xmlChar *value,
|
||||
*/
|
||||
ret->value = xmlStrdup(value);
|
||||
ret->doc = doc;
|
||||
- if ((ctxt != NULL) && (ctxt->vstateNr != 0)) {
|
||||
+ if (xmlIsStreaming(ctxt)) {
|
||||
/*
|
||||
* Operating in streaming mode, attr is gonna disappear
|
||||
*/
|
||||
@@ -2820,6 +2867,7 @@ xmlRemoveID(xmlDocPtr doc, xmlAttrPtr attr) {
|
||||
ID = xmlNodeListGetString(doc, attr->children, 1);
|
||||
if (ID == NULL)
|
||||
return(-1);
|
||||
+ xmlValidNormalizeString(ID);
|
||||
|
||||
id = xmlHashLookup(table, ID);
|
||||
if (id == NULL || id->attr != attr) {
|
||||
@@ -3009,7 +3057,7 @@ xmlAddRef(xmlValidCtxtPtr ctxt, xmlDocPtr doc, const xmlChar *value,
|
||||
* fill the structure.
|
||||
*/
|
||||
ret->value = xmlStrdup(value);
|
||||
- if ((ctxt != NULL) && (ctxt->vstateNr != 0)) {
|
||||
+ if (xmlIsStreaming(ctxt)) {
|
||||
/*
|
||||
* Operating in streaming mode, attr is gonna disappear
|
||||
*/
|
||||
@@ -4028,8 +4076,7 @@ xmlValidateAttributeValue2(xmlValidCtxtPtr ctxt, xmlDocPtr doc,
|
||||
xmlChar *
|
||||
xmlValidCtxtNormalizeAttributeValue(xmlValidCtxtPtr ctxt, xmlDocPtr doc,
|
||||
xmlNodePtr elem, const xmlChar *name, const xmlChar *value) {
|
||||
- xmlChar *ret, *dst;
|
||||
- const xmlChar *src;
|
||||
+ xmlChar *ret;
|
||||
xmlAttributePtr attrDecl = NULL;
|
||||
int extsubset = 0;
|
||||
|
||||
@@ -4070,19 +4117,7 @@ xmlValidCtxtNormalizeAttributeValue(xmlValidCtxtPtr ctxt, xmlDocPtr doc,
|
||||
ret = xmlStrdup(value);
|
||||
if (ret == NULL)
|
||||
return(NULL);
|
||||
- src = value;
|
||||
- dst = ret;
|
||||
- while (*src == 0x20) src++;
|
||||
- while (*src != 0) {
|
||||
- if (*src == 0x20) {
|
||||
- while (*src == 0x20) src++;
|
||||
- if (*src != 0)
|
||||
- *dst++ = 0x20;
|
||||
- } else {
|
||||
- *dst++ = *src++;
|
||||
- }
|
||||
- }
|
||||
- *dst = 0;
|
||||
+ xmlValidNormalizeString(ret);
|
||||
if ((doc->standalone) && (extsubset == 1) && (!xmlStrEqual(value, ret))) {
|
||||
xmlErrValidNode(ctxt, elem, XML_DTD_NOT_STANDALONE,
|
||||
"standalone: %s on %s value had to be normalized based on external subset declaration\n",
|
||||
@@ -4114,8 +4149,7 @@ xmlValidCtxtNormalizeAttributeValue(xmlValidCtxtPtr ctxt, xmlDocPtr doc,
|
||||
xmlChar *
|
||||
xmlValidNormalizeAttributeValue(xmlDocPtr doc, xmlNodePtr elem,
|
||||
const xmlChar *name, const xmlChar *value) {
|
||||
- xmlChar *ret, *dst;
|
||||
- const xmlChar *src;
|
||||
+ xmlChar *ret;
|
||||
xmlAttributePtr attrDecl = NULL;
|
||||
|
||||
if (doc == NULL) return(NULL);
|
||||
@@ -4145,19 +4179,7 @@ xmlValidNormalizeAttributeValue(xmlDocPtr doc, xmlNodePtr elem,
|
||||
ret = xmlStrdup(value);
|
||||
if (ret == NULL)
|
||||
return(NULL);
|
||||
- src = value;
|
||||
- dst = ret;
|
||||
- while (*src == 0x20) src++;
|
||||
- while (*src != 0) {
|
||||
- if (*src == 0x20) {
|
||||
- while (*src == 0x20) src++;
|
||||
- if (*src != 0)
|
||||
- *dst++ = 0x20;
|
||||
- } else {
|
||||
- *dst++ = *src++;
|
||||
- }
|
||||
- }
|
||||
- *dst = 0;
|
||||
+ xmlValidNormalizeString(ret);
|
||||
return(ret);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,266 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Fergal Daly <fergal@chromium.org>
|
||||
Date: Thu, 7 Apr 2022 02:16:11 +0000
|
||||
Subject: Use IsErrorDocument() to prevent BFCacheing of interstitials and
|
||||
errors.
|
||||
|
||||
In the bug, a crash occurs because we try to cache an interstitial. We
|
||||
catch some error documents via status codes etc but interstitials do
|
||||
not consistently set those. Checking IsErrorDocument() is more reliable.
|
||||
|
||||
(cherry picked from commit 7a05b426c6c51254a08de9a8dee8db9c1911b9c9)
|
||||
|
||||
Bug: 1274308,1287996,1283050
|
||||
Change-Id: Ifec662c169c77e33ca5dc4d56b0e42c8d71f1d97
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3319862
|
||||
Commit-Queue: Fergal Daly <fergal@chromium.org>
|
||||
Reviewed-by: Rakina Zata Amni <rakina@chromium.org>
|
||||
Reviewed-by: Andrey Kosyakov <caseq@chromium.org>
|
||||
Reviewed-by: Alexander Timin <altimin@chromium.org>
|
||||
Cr-Original-Commit-Position: refs/heads/main@{#981026}
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3559271
|
||||
Reviewed-by: Hiroki Nakagawa <nhiroki@chromium.org>
|
||||
Owners-Override: Hiroki Nakagawa <nhiroki@chromium.org>
|
||||
Commit-Queue: Rakina Zata Amni <rakina@chromium.org>
|
||||
Cr-Commit-Position: refs/branch-heads/4896@{#1065}
|
||||
Cr-Branched-From: 1f63ff4bc27570761b35ffbc7f938f6586f7bee8-refs/heads/main@{#972766}
|
||||
|
||||
diff --git a/base/tracing/protos/chrome_track_event.proto b/base/tracing/protos/chrome_track_event.proto
|
||||
index d85626908f9c9e8ddb661a34cb89be4523b07ee4..47df2f78c611f0ac47b4de85078e07b01f603306 100644
|
||||
--- a/base/tracing/protos/chrome_track_event.proto
|
||||
+++ b/base/tracing/protos/chrome_track_event.proto
|
||||
@@ -514,6 +514,7 @@ message BackForwardCacheCanStoreDocumentResult {
|
||||
CACHE_CONTROL_NO_STORE_HTTP_ONLY_COOKIE_MODIFIED = 51;
|
||||
NO_RESPONSE_HEAD = 52;
|
||||
ACTIVATION_NAVIGATION_DISALLOWED_FOR_BUG_1234857 = 53;
|
||||
+ ERROR_DOCUMENT = 54;
|
||||
}
|
||||
|
||||
optional BackForwardCacheNotRestoredReason
|
||||
diff --git a/content/browser/back_forward_cache_basics_browsertest.cc b/content/browser/back_forward_cache_basics_browsertest.cc
|
||||
index 450e27a2e7a3477a08c911923bd6d055dba5a77d..0511b468f25d3430e3e725ae262ca45c6777a6f8 100644
|
||||
--- a/content/browser/back_forward_cache_basics_browsertest.cc
|
||||
+++ b/content/browser/back_forward_cache_basics_browsertest.cc
|
||||
@@ -744,7 +744,8 @@ IN_PROC_BROWSER_TEST_F(BackForwardCacheBrowserTest,
|
||||
EXPECT_FALSE(WaitForLoadStop(shell()->web_contents()));
|
||||
ExpectNotRestored(
|
||||
{BackForwardCacheMetrics::NotRestoredReason::kHTTPStatusNotOK,
|
||||
- BackForwardCacheMetrics::NotRestoredReason::kNoResponseHead},
|
||||
+ BackForwardCacheMetrics::NotRestoredReason::kNoResponseHead,
|
||||
+ NotRestoredReason::kErrorDocument},
|
||||
{}, {}, {}, {}, FROM_HERE);
|
||||
}
|
||||
|
||||
diff --git a/content/browser/back_forward_cache_browsertest.cc b/content/browser/back_forward_cache_browsertest.cc
|
||||
index 72d9f9b0c056a384d446f576b725e53e78d5474f..51d3829bee15be4bb8e315908772b6ab02a8ee56 100644
|
||||
--- a/content/browser/back_forward_cache_browsertest.cc
|
||||
+++ b/content/browser/back_forward_cache_browsertest.cc
|
||||
@@ -52,6 +52,7 @@
|
||||
#include "content/public/test/test_navigation_throttle_inserter.h"
|
||||
#include "content/public/test/test_utils.h"
|
||||
#include "content/public/test/text_input_test_utils.h"
|
||||
+#include "content/public/test/url_loader_interceptor.h"
|
||||
#include "content/shell/browser/shell.h"
|
||||
#include "content/shell/browser/shell_javascript_dialog_manager.h"
|
||||
#include "content/test/web_contents_observer_test_utils.h"
|
||||
@@ -665,6 +666,23 @@ void BackForwardCacheBrowserTest::ExpectBrowsingInstanceNotSwappedReasons(
|
||||
<< location.ToString();
|
||||
}
|
||||
|
||||
+void BackForwardCacheBrowserTest::NavigateAndBlock(GURL url,
|
||||
+ int history_offset) {
|
||||
+ // Block the navigation with an error.
|
||||
+ std::unique_ptr<URLLoaderInterceptor> url_interceptor =
|
||||
+ URLLoaderInterceptor::SetupRequestFailForURL(url,
|
||||
+ net::ERR_BLOCKED_BY_CLIENT);
|
||||
+ TestNavigationManager manager(web_contents(), url);
|
||||
+ if (history_offset) {
|
||||
+ shell()->GoBackOrForward(history_offset);
|
||||
+ } else {
|
||||
+ shell()->LoadURL(url);
|
||||
+ }
|
||||
+ manager.WaitForNavigationFinished();
|
||||
+ ASSERT_EQ(current_frame_host()->GetLastCommittedURL(), url);
|
||||
+ ASSERT_TRUE(current_frame_host()->IsErrorDocument());
|
||||
+}
|
||||
+
|
||||
std::initializer_list<RenderFrameHostImpl*> Elements(
|
||||
std::initializer_list<RenderFrameHostImpl*> t) {
|
||||
return t;
|
||||
diff --git a/content/browser/back_forward_cache_browsertest.h b/content/browser/back_forward_cache_browsertest.h
|
||||
index fa1c8d0223ba43366ff34acd2a150901ca04b239..e5c915382bbffd8ded673b9c997532eded4184f4 100644
|
||||
--- a/content/browser/back_forward_cache_browsertest.h
|
||||
+++ b/content/browser/back_forward_cache_browsertest.h
|
||||
@@ -167,6 +167,11 @@ class BackForwardCacheBrowserTest : public ContentBrowserTest,
|
||||
|
||||
void ReleaseKeyboardLock(RenderFrameHostImpl* rfh);
|
||||
|
||||
+ // Start a navigation to |url| but block it on an error. If |history_offset|
|
||||
+ // is not 0, then the navigation will be a history navigation and this will
|
||||
+ // assert that the URL after navigation is |url|.
|
||||
+ void NavigateAndBlock(GURL url, int history_offset);
|
||||
+
|
||||
base::HistogramTester histogram_tester_;
|
||||
|
||||
bool same_site_back_forward_cache_enabled_ = true;
|
||||
diff --git a/content/browser/back_forward_cache_internal_browsertest.cc b/content/browser/back_forward_cache_internal_browsertest.cc
|
||||
index aad18a04a8775c937fa2ccb57cc2f102da729dbe..41e637bb394d4f5df3cd86d467336e7457e4aa39 100644
|
||||
--- a/content/browser/back_forward_cache_internal_browsertest.cc
|
||||
+++ b/content/browser/back_forward_cache_internal_browsertest.cc
|
||||
@@ -3659,4 +3659,69 @@ IN_PROC_BROWSER_TEST_F(BackForwardCacheBrowserTest,
|
||||
tester.IsDisabledForFrameWithReason(process_id, routing_id, reason));
|
||||
}
|
||||
|
||||
+// Test that when we navigate away from an error page and back with no error
|
||||
+// that we don't serve the error page from BFCache.
|
||||
+IN_PROC_BROWSER_TEST_F(BackForwardCacheBrowserTest,
|
||||
+ ErrorDocumentNotCachedWithSecondError) {
|
||||
+ ASSERT_TRUE(embedded_test_server()->Start());
|
||||
+
|
||||
+ GURL url_a(embedded_test_server()->GetURL("a.com", "/title1.html"));
|
||||
+ GURL url_b(embedded_test_server()->GetURL("b.com", "/title1.html"));
|
||||
+
|
||||
+ // Navigate to a.com.
|
||||
+ ASSERT_TRUE(NavigateToURL(web_contents(), url_a));
|
||||
+
|
||||
+ // Navigate to b.com and block due to an error.
|
||||
+ NavigateAndBlock(url_b, /*history_offset=*/0);
|
||||
+ RenderFrameHostImplWrapper rfh_b(current_frame_host());
|
||||
+
|
||||
+ // Navigate back to a.com.
|
||||
+ ASSERT_TRUE(HistoryGoBack(web_contents()));
|
||||
+ ExpectRestored(FROM_HERE);
|
||||
+ ASSERT_TRUE(rfh_b.WaitUntilRenderFrameDeleted());
|
||||
+
|
||||
+ // Navigate forward to b.com again and block with an error again.
|
||||
+ NavigateAndBlock(url_b, /*history_offset=*/1);
|
||||
+ ExpectNotRestored(
|
||||
+ {NotRestoredReason::kHTTPStatusNotOK, NotRestoredReason::kNoResponseHead,
|
||||
+ NotRestoredReason::kErrorDocument},
|
||||
+ {}, {}, {}, {}, FROM_HERE);
|
||||
+}
|
||||
+
|
||||
+// Test that when we navigate away from an error page and back with no error
|
||||
+// that we don't serve the error page from BFCache.
|
||||
+IN_PROC_BROWSER_TEST_F(BackForwardCacheBrowserTest,
|
||||
+ ErrorDocumentNotCachedWithoutSecondError) {
|
||||
+ ASSERT_TRUE(embedded_test_server()->Start());
|
||||
+
|
||||
+ GURL url_a(embedded_test_server()->GetURL("a.com", "/title1.html"));
|
||||
+ GURL url_b(embedded_test_server()->GetURL("b.com", "/title1.html"));
|
||||
+
|
||||
+ // Navigate to a.com.
|
||||
+ ASSERT_TRUE(NavigateToURL(web_contents(), url_a));
|
||||
+
|
||||
+ // Navigate to b.com and block due to an error.
|
||||
+ NavigateAndBlock(url_b, /*history_offset=*/0);
|
||||
+ RenderFrameHostImplWrapper rfh_b(current_frame_host());
|
||||
+
|
||||
+ int history_entry_id =
|
||||
+ web_contents()->GetController().GetLastCommittedEntry()->GetUniqueID();
|
||||
+
|
||||
+ // Navigate back to a.com.
|
||||
+ ASSERT_TRUE(HistoryGoBack(web_contents()));
|
||||
+ ASSERT_TRUE(rfh_b.WaitUntilRenderFrameDeleted());
|
||||
+
|
||||
+ // Navigate forward to b.com again with no error.
|
||||
+ ASSERT_TRUE(HistoryGoForward(web_contents()));
|
||||
+
|
||||
+ // We would normally confirm that the blocking reasons are correct, however,
|
||||
+ // when performing a history navigations back to an error document, a new
|
||||
+ // entry is created and the reasons in the old entry are not recorded.
|
||||
+ //
|
||||
+ // Check that we indeed got a new history entry.
|
||||
+ ASSERT_NE(
|
||||
+ history_entry_id,
|
||||
+ web_contents()->GetController().GetLastCommittedEntry()->GetUniqueID());
|
||||
+}
|
||||
+
|
||||
} // namespace content
|
||||
diff --git a/content/browser/devtools/protocol/page_handler.cc b/content/browser/devtools/protocol/page_handler.cc
|
||||
index d48b48718e5eb3ca09b439af4766d8749cb0be98..842fdf70c1d826d5fb26a2e8c2a3f228a18b24ea 100644
|
||||
--- a/content/browser/devtools/protocol/page_handler.cc
|
||||
+++ b/content/browser/devtools/protocol/page_handler.cc
|
||||
@@ -1407,6 +1407,8 @@ Page::BackForwardCacheNotRestoredReason NotRestoredReasonToProtocol(
|
||||
case Reason::kActivationNavigationsDisallowedForBug1234857:
|
||||
return Page::BackForwardCacheNotRestoredReasonEnum::
|
||||
ActivationNavigationsDisallowedForBug1234857;
|
||||
+ case Reason::kErrorDocument:
|
||||
+ return Page::BackForwardCacheNotRestoredReasonEnum::ErrorDocument;
|
||||
case Reason::kBlocklistedFeatures:
|
||||
// Blocklisted features should be handled separately and be broken down
|
||||
// into sub reasons.
|
||||
@@ -1686,6 +1688,7 @@ Page::BackForwardCacheNotRestoredReasonType MapNotRestoredReasonToType(
|
||||
case Reason::kCacheControlNoStoreCookieModified:
|
||||
case Reason::kCacheControlNoStoreHTTPOnlyCookieModified:
|
||||
case Reason::kNoResponseHead:
|
||||
+ case Reason::kErrorDocument:
|
||||
return Page::BackForwardCacheNotRestoredReasonTypeEnum::Circumstantial;
|
||||
case Reason::kOptInUnloadHeaderNotPresent:
|
||||
case Reason::kUnloadHandlerExistsInMainFrame:
|
||||
diff --git a/content/browser/renderer_host/back_forward_cache_can_store_document_result.cc b/content/browser/renderer_host/back_forward_cache_can_store_document_result.cc
|
||||
index 9077a176fff2af3ec4a84f918e81601b618902df..d2b7608067198a4bc623854feb8c1495a6662a87 100644
|
||||
--- a/content/browser/renderer_host/back_forward_cache_can_store_document_result.cc
|
||||
+++ b/content/browser/renderer_host/back_forward_cache_can_store_document_result.cc
|
||||
@@ -183,6 +183,8 @@ ProtoEnum::BackForwardCacheNotRestoredReason NotRestoredReasonToTraceEnum(
|
||||
return ProtoEnum::NO_RESPONSE_HEAD;
|
||||
case Reason::kActivationNavigationsDisallowedForBug1234857:
|
||||
return ProtoEnum::ACTIVATION_NAVIGATION_DISALLOWED_FOR_BUG_1234857;
|
||||
+ case Reason::kErrorDocument:
|
||||
+ return ProtoEnum::ERROR_DOCUMENT;
|
||||
case Reason::kBlocklistedFeatures:
|
||||
return ProtoEnum::BLOCKLISTED_FEATURES;
|
||||
case Reason::kUnknown:
|
||||
@@ -396,6 +398,8 @@ std::string BackForwardCacheCanStoreDocumentResult::NotRestoredReasonToString(
|
||||
return "Activation navigations are disallowed to avoid bypassing "
|
||||
"PasswordProtectionService as a workaround for "
|
||||
"https://crbug.com/1234857.";
|
||||
+ case Reason::kErrorDocument:
|
||||
+ return "Error documents cannot be stored in bfcache";
|
||||
}
|
||||
}
|
||||
|
||||
diff --git a/content/browser/renderer_host/back_forward_cache_impl.cc b/content/browser/renderer_host/back_forward_cache_impl.cc
|
||||
index ac7cb84e8059be774f48da429e21fd40a7bc53b8..5db2853cdb207bc3ceeccd9bf5ec0092db0aed25 100644
|
||||
--- a/content/browser/renderer_host/back_forward_cache_impl.cc
|
||||
+++ b/content/browser/renderer_host/back_forward_cache_impl.cc
|
||||
@@ -727,6 +727,13 @@ BackForwardCacheImpl::CanPotentiallyStorePageLater(RenderFrameHostImpl* rfh) {
|
||||
if (rfh->last_http_status_code() != net::HTTP_OK)
|
||||
result.No(BackForwardCacheMetrics::NotRestoredReason::kHTTPStatusNotOK);
|
||||
|
||||
+ // Interstitials and other internal error pages should set an error status
|
||||
+ // code but there's no guarantee, e.g. https://crbug/1274308,
|
||||
+ // https://crbug/1287996. This catches those cases. It might also make the
|
||||
+ // kHTTPStatusNotOK check redundant.
|
||||
+ if (rfh->IsErrorDocument())
|
||||
+ result.No(BackForwardCacheMetrics::NotRestoredReason::kErrorDocument);
|
||||
+
|
||||
// Only store documents that were fetched via HTTP GET method.
|
||||
if (rfh->last_http_method() != net::HttpRequestHeaders::kGetMethod)
|
||||
result.No(BackForwardCacheMetrics::NotRestoredReason::kHTTPMethodNotGET);
|
||||
diff --git a/content/browser/renderer_host/back_forward_cache_metrics.h b/content/browser/renderer_host/back_forward_cache_metrics.h
|
||||
index 05289d0ab65faf2939f74d76530091b8a9efd123..c2338608889ce4936c3a8b00833a5205c74a78af 100644
|
||||
--- a/content/browser/renderer_host/back_forward_cache_metrics.h
|
||||
+++ b/content/browser/renderer_host/back_forward_cache_metrics.h
|
||||
@@ -110,7 +110,8 @@ class BackForwardCacheMetrics
|
||||
kCacheControlNoStoreHTTPOnlyCookieModified = 55,
|
||||
kNoResponseHead = 56,
|
||||
kActivationNavigationsDisallowedForBug1234857 = 57,
|
||||
- kMaxValue = kActivationNavigationsDisallowedForBug1234857,
|
||||
+ kErrorDocument = 58,
|
||||
+ kMaxValue = kErrorDocument,
|
||||
};
|
||||
|
||||
using NotRestoredReasons =
|
||||
diff --git a/third_party/blink/public/devtools_protocol/browser_protocol.pdl b/third_party/blink/public/devtools_protocol/browser_protocol.pdl
|
||||
index 0ae53ce429dbc1bf254ac773e0499dfe07273d46..d7231d7cdf9c230b24cb661a86bd64da5d6e7eb8 100644
|
||||
--- a/third_party/blink/public/devtools_protocol/browser_protocol.pdl
|
||||
+++ b/third_party/blink/public/devtools_protocol/browser_protocol.pdl
|
||||
@@ -7988,6 +7988,7 @@ domain Page
|
||||
NoResponseHead
|
||||
Unknown
|
||||
ActivationNavigationsDisallowedForBug1234857
|
||||
+ ErrorDocument
|
||||
#Blocklisted features
|
||||
WebSocket
|
||||
WebTransport
|
||||
@@ -11,9 +11,15 @@
|
||||
|
||||
"src/electron/patches/node": "src/third_party/electron_node",
|
||||
|
||||
"src/electron/patches/ffmpeg": "src/third_party/ffmpeg",
|
||||
|
||||
"src/electron/patches/squirrel.mac": "src/third_party/squirrel.mac",
|
||||
|
||||
"src/electron/patches/Mantle": "src/third_party/squirrel.mac/vendor/Mantle",
|
||||
|
||||
"src/electron/patches/ReactiveObjC": "src/third_party/squirrel.mac/vendor/ReactiveObjC"
|
||||
"src/electron/patches/ReactiveObjC": "src/third_party/squirrel.mac/vendor/ReactiveObjC",
|
||||
|
||||
"src/electron/patches/angle": "src/third_party/angle",
|
||||
|
||||
"src/electron/patches/icu": "src/third_party/icu"
|
||||
}
|
||||
|
||||
1
patches/ffmpeg/.patches
Normal file
1
patches/ffmpeg/.patches
Normal file
@@ -0,0 +1 @@
|
||||
cherry-pick-e481fc655a62.patch
|
||||
27
patches/ffmpeg/cherry-pick-e481fc655a62.patch
Normal file
27
patches/ffmpeg/cherry-pick-e481fc655a62.patch
Normal file
@@ -0,0 +1,27 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Dan Sanders <sandersd@chromium.org>
|
||||
Date: Tue, 3 May 2022 14:39:37 -0700
|
||||
Subject: Do not parse late SEI messages during decoding.
|
||||
|
||||
Bug: 1306751
|
||||
Change-Id: I2088b9ff89bd8eee8ab82675258af302d9bfccf9
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/third_party/ffmpeg/+/3625832
|
||||
Reviewed-by: Dale Curtis <dalecurtis@chromium.org>
|
||||
|
||||
diff --git a/libavcodec/h264dec.c b/libavcodec/h264dec.c
|
||||
index d7bcba332d4c0b2fdc3c6679de84738b4cd49623..f639a9206bbd8fcd7797b177c0a36008b5274ab5 100644
|
||||
--- a/libavcodec/h264dec.c
|
||||
+++ b/libavcodec/h264dec.c
|
||||
@@ -678,6 +678,12 @@ static int decode_nal_units(H264Context *h, const uint8_t *buf, int buf_size)
|
||||
avpriv_request_sample(avctx, "data partitioning");
|
||||
break;
|
||||
case H264_NAL_SEI:
|
||||
+ // If setup is finished, threads can contend over the contents of
|
||||
+ // the active SEI.
|
||||
+ if (h->setup_finished) {
|
||||
+ av_log(h->avctx, AV_LOG_DEBUG, "Late SEI\n");
|
||||
+ break;
|
||||
+ }
|
||||
ret = ff_h264_sei_decode(&h->sei, &nal->gb, &h->ps, avctx);
|
||||
h->has_recovery_point = h->has_recovery_point || h->sei.recovery_point.recovery_frame_cnt != -1;
|
||||
if (avctx->debug & FF_DEBUG_GREEN_MD)
|
||||
1
patches/icu/.patches
Normal file
1
patches/icu/.patches
Normal file
@@ -0,0 +1 @@
|
||||
cherry-pick-14e51893e5b5.patch
|
||||
415
patches/icu/cherry-pick-14e51893e5b5.patch
Normal file
415
patches/icu/cherry-pick-14e51893e5b5.patch
Normal file
@@ -0,0 +1,415 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Frank Tang <ftang@chromium.org>
|
||||
Date: Fri, 29 Apr 2022 16:50:59 -0700
|
||||
Subject: CP PR 2070 fix int32 overflow
|
||||
|
||||
https://github.com/unicode-org/icu/pull/2070
|
||||
https://unicode-org.atlassian.net/browse/ICU-22005
|
||||
|
||||
Bug: chromium:1316946
|
||||
Change-Id: I6cd7d687a55b6cc157b1afa52365908be2992fa6
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/deps/icu/+/3614280
|
||||
Reviewed-by: Jungshik Shin <jshin@chromium.org>
|
||||
(cherry picked from commit 85814e1af52482199a13d284545623ffbc9eef83)
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/deps/icu/+/3632709
|
||||
|
||||
diff --git a/README.chromium b/README.chromium
|
||||
index db26d214ccf1b452339c1f9de759c4c9c7aafe58..2b319327cbfea9b7fb7a1ca240bbbd272e1dab14 100644
|
||||
--- a/README.chromium
|
||||
+++ b/README.chromium
|
||||
@@ -264,3 +264,7 @@ D. Local Modifications
|
||||
- upstream bug:
|
||||
https://unicode-org.atlassian.net/browse/ICU-21865
|
||||
|
||||
+12. Patch i18n/formatted_string_builder to fix int32_t overflow bug
|
||||
+ patches/formatted_string_builder.patch
|
||||
+ - https://github.com/unicode-org/icu/pull/2070
|
||||
+ - https://unicode-org.atlassian.net/browse/ICU-22005
|
||||
diff --git a/patches/formatted_string_builder.patch b/patches/formatted_string_builder.patch
|
||||
new file mode 100644
|
||||
index 0000000000000000000000000000000000000000..4fad6f18601f7b4097e2d46bfe6660bec2e2882d
|
||||
--- /dev/null
|
||||
+++ b/patches/formatted_string_builder.patch
|
||||
@@ -0,0 +1,191 @@
|
||||
+diff --git a/source/i18n/formatted_string_builder.cpp b/source/i18n/formatted_string_builder.cpp
|
||||
+index 73407864..628fbea8 100644
|
||||
+--- a/source/i18n/formatted_string_builder.cpp
|
||||
++++ b/source/i18n/formatted_string_builder.cpp
|
||||
+@@ -6,6 +6,7 @@
|
||||
+ #if !UCONFIG_NO_FORMATTING
|
||||
+
|
||||
+ #include "formatted_string_builder.h"
|
||||
++#include "putilimp.h"
|
||||
+ #include "unicode/ustring.h"
|
||||
+ #include "unicode/utf16.h"
|
||||
+ #include "unicode/unum.h" // for UNumberFormatFields literals
|
||||
+@@ -197,6 +198,9 @@ FormattedStringBuilder::splice(int32_t startThis, int32_t endThis, const Unicod
|
||||
+ int32_t thisLength = endThis - startThis;
|
||||
+ int32_t otherLength = endOther - startOther;
|
||||
+ int32_t count = otherLength - thisLength;
|
||||
++ if (U_FAILURE(status)) {
|
||||
++ return count;
|
||||
++ }
|
||||
+ int32_t position;
|
||||
+ if (count > 0) {
|
||||
+ // Overall, chars need to be added.
|
||||
+@@ -221,6 +225,9 @@ int32_t FormattedStringBuilder::append(const FormattedStringBuilder &other, UErr
|
||||
+
|
||||
+ int32_t
|
||||
+ FormattedStringBuilder::insert(int32_t index, const FormattedStringBuilder &other, UErrorCode &status) {
|
||||
++ if (U_FAILURE(status)) {
|
||||
++ return 0;
|
||||
++ }
|
||||
+ if (this == &other) {
|
||||
+ status = U_ILLEGAL_ARGUMENT_ERROR;
|
||||
+ return 0;
|
||||
+@@ -255,12 +262,18 @@ int32_t FormattedStringBuilder::prepareForInsert(int32_t index, int32_t count, U
|
||||
+ U_ASSERT(index >= 0);
|
||||
+ U_ASSERT(index <= fLength);
|
||||
+ U_ASSERT(count >= 0);
|
||||
++ U_ASSERT(fZero >= 0);
|
||||
++ U_ASSERT(fLength >= 0);
|
||||
++ U_ASSERT(getCapacity() - fZero >= fLength);
|
||||
++ if (U_FAILURE(status)) {
|
||||
++ return count;
|
||||
++ }
|
||||
+ if (index == 0 && fZero - count >= 0) {
|
||||
+ // Append to start
|
||||
+ fZero -= count;
|
||||
+ fLength += count;
|
||||
+ return fZero;
|
||||
+- } else if (index == fLength && fZero + fLength + count < getCapacity()) {
|
||||
++ } else if (index == fLength && count <= getCapacity() - fZero - fLength) {
|
||||
+ // Append to end
|
||||
+ fLength += count;
|
||||
+ return fZero + fLength - count;
|
||||
+@@ -275,18 +288,26 @@ int32_t FormattedStringBuilder::prepareForInsertHelper(int32_t index, int32_t co
|
||||
+ int32_t oldZero = fZero;
|
||||
+ char16_t *oldChars = getCharPtr();
|
||||
+ Field *oldFields = getFieldPtr();
|
||||
+- if (fLength + count > oldCapacity) {
|
||||
+- if ((fLength + count) > INT32_MAX / 2) {
|
||||
+- // If we continue, then newCapacity will overflow int32_t in the next line.
|
||||
++ int32_t newLength;
|
||||
++ if (uprv_add32_overflow(fLength, count, &newLength)) {
|
||||
++ status = U_INPUT_TOO_LONG_ERROR;
|
||||
++ return -1;
|
||||
++ }
|
||||
++ int32_t newZero;
|
||||
++ if (newLength > oldCapacity) {
|
||||
++ if (newLength > INT32_MAX / 2) {
|
||||
++ // We do not support more than 1G char16_t in this code because
|
||||
++ // dealing with >2G *bytes* can cause subtle bugs.
|
||||
+ status = U_INPUT_TOO_LONG_ERROR;
|
||||
+ return -1;
|
||||
+ }
|
||||
+- int32_t newCapacity = (fLength + count) * 2;
|
||||
+- int32_t newZero = newCapacity / 2 - (fLength + count) / 2;
|
||||
++ // Keep newCapacity also to at most 1G char16_t.
|
||||
++ int32_t newCapacity = newLength * 2;
|
||||
++ newZero = (newCapacity - newLength) / 2;
|
||||
+
|
||||
+ // C++ note: malloc appears in two places: here and in the assignment operator.
|
||||
+- auto newChars = static_cast<char16_t *> (uprv_malloc(sizeof(char16_t) * newCapacity));
|
||||
+- auto newFields = static_cast<Field *>(uprv_malloc(sizeof(Field) * newCapacity));
|
||||
++ auto newChars = static_cast<char16_t *> (uprv_malloc(sizeof(char16_t) * static_cast<size_t>(newCapacity)));
|
||||
++ auto newFields = static_cast<Field *>(uprv_malloc(sizeof(Field) * static_cast<size_t>(newCapacity)));
|
||||
+ if (newChars == nullptr || newFields == nullptr) {
|
||||
+ uprv_free(newChars);
|
||||
+ uprv_free(newFields);
|
||||
+@@ -315,10 +336,8 @@ int32_t FormattedStringBuilder::prepareForInsertHelper(int32_t index, int32_t co
|
||||
+ fChars.heap.capacity = newCapacity;
|
||||
+ fFields.heap.ptr = newFields;
|
||||
+ fFields.heap.capacity = newCapacity;
|
||||
+- fZero = newZero;
|
||||
+- fLength += count;
|
||||
+ } else {
|
||||
+- int32_t newZero = oldCapacity / 2 - (fLength + count) / 2;
|
||||
++ newZero = (oldCapacity - newLength) / 2;
|
||||
+
|
||||
+ // C++ note: memmove is required because src and dest may overlap.
|
||||
+ // First copy the entire string to the location of the prefix, and then move the suffix
|
||||
+@@ -331,18 +350,20 @@ int32_t FormattedStringBuilder::prepareForInsertHelper(int32_t index, int32_t co
|
||||
+ uprv_memmove2(oldFields + newZero + index + count,
|
||||
+ oldFields + newZero + index,
|
||||
+ sizeof(Field) * (fLength - index));
|
||||
+-
|
||||
+- fZero = newZero;
|
||||
+- fLength += count;
|
||||
+ }
|
||||
+- U_ASSERT((fZero + index) >= 0);
|
||||
++ fZero = newZero;
|
||||
++ fLength = newLength;
|
||||
+ return fZero + index;
|
||||
+ }
|
||||
+
|
||||
+ int32_t FormattedStringBuilder::remove(int32_t index, int32_t count) {
|
||||
+- // TODO: Reset the heap here? (If the string after removal can fit on stack?)
|
||||
++ U_ASSERT(0 <= index);
|
||||
++ U_ASSERT(index <= fLength);
|
||||
++ U_ASSERT(count <= (fLength - index));
|
||||
++ U_ASSERT(index <= getCapacity() - fZero);
|
||||
++
|
||||
+ int32_t position = index + fZero;
|
||||
+- U_ASSERT(position >= 0);
|
||||
++ // TODO: Reset the heap here? (If the string after removal can fit on stack?)
|
||||
+ uprv_memmove2(getCharPtr() + position,
|
||||
+ getCharPtr() + position + count,
|
||||
+ sizeof(char16_t) * (fLength - index - count));
|
||||
+diff --git a/source/test/intltest/formatted_string_builder_test.cpp b/source/test/intltest/formatted_string_builder_test.cpp
|
||||
+index 45721a32..57294e24 100644
|
||||
+--- a/source/test/intltest/formatted_string_builder_test.cpp
|
||||
++++ b/source/test/intltest/formatted_string_builder_test.cpp
|
||||
+@@ -22,6 +22,7 @@ class FormattedStringBuilderTest : public IntlTest {
|
||||
+ void testFields();
|
||||
+ void testUnlimitedCapacity();
|
||||
+ void testCodePoints();
|
||||
++ void testInsertOverflow();
|
||||
+
|
||||
+ void runIndexedTest(int32_t index, UBool exec, const char *&name, char *par = 0) override;
|
||||
+
|
||||
+@@ -50,6 +51,7 @@ void FormattedStringBuilderTest::runIndexedTest(int32_t index, UBool exec, const
|
||||
+ TESTCASE_AUTO(testFields);
|
||||
+ TESTCASE_AUTO(testUnlimitedCapacity);
|
||||
+ TESTCASE_AUTO(testCodePoints);
|
||||
++ TESTCASE_AUTO(testInsertOverflow);
|
||||
+ TESTCASE_AUTO_END;
|
||||
+ }
|
||||
+
|
||||
+@@ -308,6 +310,45 @@ void FormattedStringBuilderTest::testCodePoints() {
|
||||
+ assertEquals("Code point count is 2", 2, nsb.codePointCount());
|
||||
+ }
|
||||
+
|
||||
++void FormattedStringBuilderTest::testInsertOverflow() {
|
||||
++ if (quick) return;
|
||||
++ // Setup the test fixture in sb, sb2, ustr.
|
||||
++ UErrorCode status = U_ZERO_ERROR;
|
||||
++ FormattedStringBuilder sb;
|
||||
++ int32_t data_length = INT32_MAX / 2;
|
||||
++ UnicodeString ustr(data_length, u'a', data_length);
|
||||
++ sb.append(ustr, kUndefinedField, status);
|
||||
++ assertSuccess("Setup the first FormattedStringBuilder", status);
|
||||
++
|
||||
++ FormattedStringBuilder sb2;
|
||||
++ sb2.append(ustr, kUndefinedField, status);
|
||||
++ sb2.insert(0, ustr, 0, data_length / 2, kUndefinedField, status);
|
||||
++ sb2.writeTerminator(status);
|
||||
++ assertSuccess("Setup the second FormattedStringBuilder", status);
|
||||
++
|
||||
++ ustr = sb2.toUnicodeString();
|
||||
++ // Complete setting up the test fixture in sb, sb2 and ustr.
|
||||
++
|
||||
++ // Test splice() of the second UnicodeString
|
||||
++ sb.splice(0, 1, ustr, 1, ustr.length(),
|
||||
++ kUndefinedField, status);
|
||||
++ assertEquals(
|
||||
++ "splice() long text should not crash but return U_INPUT_TOO_LONG_ERROR",
|
||||
++ U_INPUT_TOO_LONG_ERROR, status);
|
||||
++
|
||||
++ // Test sb.insert() of the first FormattedStringBuilder with the second one.
|
||||
++ sb.insert(0, sb2, status);
|
||||
++ assertEquals(
|
||||
++ "insert() long FormattedStringBuilder should not crash but return "
|
||||
++ "U_INPUT_TOO_LONG_ERROR", U_INPUT_TOO_LONG_ERROR, status);
|
||||
++
|
||||
++ // Test sb.insert() of the first FormattedStringBuilder with UnicodeString.
|
||||
++ sb.insert(0, ustr, 0, ustr.length(), kUndefinedField, status);
|
||||
++ assertEquals(
|
||||
++ "insert() long UnicodeString should not crash but return "
|
||||
++ "U_INPUT_TOO_LONG_ERROR", U_INPUT_TOO_LONG_ERROR, status);
|
||||
++}
|
||||
++
|
||||
+ void FormattedStringBuilderTest::assertEqualsImpl(const UnicodeString &a, const FormattedStringBuilder &b) {
|
||||
+ // TODO: Why won't this compile without the IntlTest:: qualifier?
|
||||
+ IntlTest::assertEquals("Lengths should be the same", a.length(), b.length());
|
||||
diff --git a/source/i18n/formatted_string_builder.cpp b/source/i18n/formatted_string_builder.cpp
|
||||
index 734078644b88efd47b47a58e97fee5bd06afb4f8..628fbea871167619f60cc6eed0ee4b7776dab7fe 100644
|
||||
--- a/source/i18n/formatted_string_builder.cpp
|
||||
+++ b/source/i18n/formatted_string_builder.cpp
|
||||
@@ -6,6 +6,7 @@
|
||||
#if !UCONFIG_NO_FORMATTING
|
||||
|
||||
#include "formatted_string_builder.h"
|
||||
+#include "putilimp.h"
|
||||
#include "unicode/ustring.h"
|
||||
#include "unicode/utf16.h"
|
||||
#include "unicode/unum.h" // for UNumberFormatFields literals
|
||||
@@ -197,6 +198,9 @@ FormattedStringBuilder::splice(int32_t startThis, int32_t endThis, const Unicod
|
||||
int32_t thisLength = endThis - startThis;
|
||||
int32_t otherLength = endOther - startOther;
|
||||
int32_t count = otherLength - thisLength;
|
||||
+ if (U_FAILURE(status)) {
|
||||
+ return count;
|
||||
+ }
|
||||
int32_t position;
|
||||
if (count > 0) {
|
||||
// Overall, chars need to be added.
|
||||
@@ -221,6 +225,9 @@ int32_t FormattedStringBuilder::append(const FormattedStringBuilder &other, UErr
|
||||
|
||||
int32_t
|
||||
FormattedStringBuilder::insert(int32_t index, const FormattedStringBuilder &other, UErrorCode &status) {
|
||||
+ if (U_FAILURE(status)) {
|
||||
+ return 0;
|
||||
+ }
|
||||
if (this == &other) {
|
||||
status = U_ILLEGAL_ARGUMENT_ERROR;
|
||||
return 0;
|
||||
@@ -255,12 +262,18 @@ int32_t FormattedStringBuilder::prepareForInsert(int32_t index, int32_t count, U
|
||||
U_ASSERT(index >= 0);
|
||||
U_ASSERT(index <= fLength);
|
||||
U_ASSERT(count >= 0);
|
||||
+ U_ASSERT(fZero >= 0);
|
||||
+ U_ASSERT(fLength >= 0);
|
||||
+ U_ASSERT(getCapacity() - fZero >= fLength);
|
||||
+ if (U_FAILURE(status)) {
|
||||
+ return count;
|
||||
+ }
|
||||
if (index == 0 && fZero - count >= 0) {
|
||||
// Append to start
|
||||
fZero -= count;
|
||||
fLength += count;
|
||||
return fZero;
|
||||
- } else if (index == fLength && fZero + fLength + count < getCapacity()) {
|
||||
+ } else if (index == fLength && count <= getCapacity() - fZero - fLength) {
|
||||
// Append to end
|
||||
fLength += count;
|
||||
return fZero + fLength - count;
|
||||
@@ -275,18 +288,26 @@ int32_t FormattedStringBuilder::prepareForInsertHelper(int32_t index, int32_t co
|
||||
int32_t oldZero = fZero;
|
||||
char16_t *oldChars = getCharPtr();
|
||||
Field *oldFields = getFieldPtr();
|
||||
- if (fLength + count > oldCapacity) {
|
||||
- if ((fLength + count) > INT32_MAX / 2) {
|
||||
- // If we continue, then newCapacity will overflow int32_t in the next line.
|
||||
+ int32_t newLength;
|
||||
+ if (uprv_add32_overflow(fLength, count, &newLength)) {
|
||||
+ status = U_INPUT_TOO_LONG_ERROR;
|
||||
+ return -1;
|
||||
+ }
|
||||
+ int32_t newZero;
|
||||
+ if (newLength > oldCapacity) {
|
||||
+ if (newLength > INT32_MAX / 2) {
|
||||
+ // We do not support more than 1G char16_t in this code because
|
||||
+ // dealing with >2G *bytes* can cause subtle bugs.
|
||||
status = U_INPUT_TOO_LONG_ERROR;
|
||||
return -1;
|
||||
}
|
||||
- int32_t newCapacity = (fLength + count) * 2;
|
||||
- int32_t newZero = newCapacity / 2 - (fLength + count) / 2;
|
||||
+ // Keep newCapacity also to at most 1G char16_t.
|
||||
+ int32_t newCapacity = newLength * 2;
|
||||
+ newZero = (newCapacity - newLength) / 2;
|
||||
|
||||
// C++ note: malloc appears in two places: here and in the assignment operator.
|
||||
- auto newChars = static_cast<char16_t *> (uprv_malloc(sizeof(char16_t) * newCapacity));
|
||||
- auto newFields = static_cast<Field *>(uprv_malloc(sizeof(Field) * newCapacity));
|
||||
+ auto newChars = static_cast<char16_t *> (uprv_malloc(sizeof(char16_t) * static_cast<size_t>(newCapacity)));
|
||||
+ auto newFields = static_cast<Field *>(uprv_malloc(sizeof(Field) * static_cast<size_t>(newCapacity)));
|
||||
if (newChars == nullptr || newFields == nullptr) {
|
||||
uprv_free(newChars);
|
||||
uprv_free(newFields);
|
||||
@@ -315,10 +336,8 @@ int32_t FormattedStringBuilder::prepareForInsertHelper(int32_t index, int32_t co
|
||||
fChars.heap.capacity = newCapacity;
|
||||
fFields.heap.ptr = newFields;
|
||||
fFields.heap.capacity = newCapacity;
|
||||
- fZero = newZero;
|
||||
- fLength += count;
|
||||
} else {
|
||||
- int32_t newZero = oldCapacity / 2 - (fLength + count) / 2;
|
||||
+ newZero = (oldCapacity - newLength) / 2;
|
||||
|
||||
// C++ note: memmove is required because src and dest may overlap.
|
||||
// First copy the entire string to the location of the prefix, and then move the suffix
|
||||
@@ -331,18 +350,20 @@ int32_t FormattedStringBuilder::prepareForInsertHelper(int32_t index, int32_t co
|
||||
uprv_memmove2(oldFields + newZero + index + count,
|
||||
oldFields + newZero + index,
|
||||
sizeof(Field) * (fLength - index));
|
||||
-
|
||||
- fZero = newZero;
|
||||
- fLength += count;
|
||||
}
|
||||
- U_ASSERT((fZero + index) >= 0);
|
||||
+ fZero = newZero;
|
||||
+ fLength = newLength;
|
||||
return fZero + index;
|
||||
}
|
||||
|
||||
int32_t FormattedStringBuilder::remove(int32_t index, int32_t count) {
|
||||
- // TODO: Reset the heap here? (If the string after removal can fit on stack?)
|
||||
+ U_ASSERT(0 <= index);
|
||||
+ U_ASSERT(index <= fLength);
|
||||
+ U_ASSERT(count <= (fLength - index));
|
||||
+ U_ASSERT(index <= getCapacity() - fZero);
|
||||
+
|
||||
int32_t position = index + fZero;
|
||||
- U_ASSERT(position >= 0);
|
||||
+ // TODO: Reset the heap here? (If the string after removal can fit on stack?)
|
||||
uprv_memmove2(getCharPtr() + position,
|
||||
getCharPtr() + position + count,
|
||||
sizeof(char16_t) * (fLength - index - count));
|
||||
diff --git a/source/test/intltest/formatted_string_builder_test.cpp b/source/test/intltest/formatted_string_builder_test.cpp
|
||||
index 45721a320ac816b3cf35a40fd7c0db6ff9ccf206..57294e2485639983cbd3a98a78ba236068846cb8 100644
|
||||
--- a/source/test/intltest/formatted_string_builder_test.cpp
|
||||
+++ b/source/test/intltest/formatted_string_builder_test.cpp
|
||||
@@ -22,6 +22,7 @@ class FormattedStringBuilderTest : public IntlTest {
|
||||
void testFields();
|
||||
void testUnlimitedCapacity();
|
||||
void testCodePoints();
|
||||
+ void testInsertOverflow();
|
||||
|
||||
void runIndexedTest(int32_t index, UBool exec, const char *&name, char *par = 0) override;
|
||||
|
||||
@@ -50,6 +51,7 @@ void FormattedStringBuilderTest::runIndexedTest(int32_t index, UBool exec, const
|
||||
TESTCASE_AUTO(testFields);
|
||||
TESTCASE_AUTO(testUnlimitedCapacity);
|
||||
TESTCASE_AUTO(testCodePoints);
|
||||
+ TESTCASE_AUTO(testInsertOverflow);
|
||||
TESTCASE_AUTO_END;
|
||||
}
|
||||
|
||||
@@ -308,6 +310,45 @@ void FormattedStringBuilderTest::testCodePoints() {
|
||||
assertEquals("Code point count is 2", 2, nsb.codePointCount());
|
||||
}
|
||||
|
||||
+void FormattedStringBuilderTest::testInsertOverflow() {
|
||||
+ if (quick) return;
|
||||
+ // Setup the test fixture in sb, sb2, ustr.
|
||||
+ UErrorCode status = U_ZERO_ERROR;
|
||||
+ FormattedStringBuilder sb;
|
||||
+ int32_t data_length = INT32_MAX / 2;
|
||||
+ UnicodeString ustr(data_length, u'a', data_length);
|
||||
+ sb.append(ustr, kUndefinedField, status);
|
||||
+ assertSuccess("Setup the first FormattedStringBuilder", status);
|
||||
+
|
||||
+ FormattedStringBuilder sb2;
|
||||
+ sb2.append(ustr, kUndefinedField, status);
|
||||
+ sb2.insert(0, ustr, 0, data_length / 2, kUndefinedField, status);
|
||||
+ sb2.writeTerminator(status);
|
||||
+ assertSuccess("Setup the second FormattedStringBuilder", status);
|
||||
+
|
||||
+ ustr = sb2.toUnicodeString();
|
||||
+ // Complete setting up the test fixture in sb, sb2 and ustr.
|
||||
+
|
||||
+ // Test splice() of the second UnicodeString
|
||||
+ sb.splice(0, 1, ustr, 1, ustr.length(),
|
||||
+ kUndefinedField, status);
|
||||
+ assertEquals(
|
||||
+ "splice() long text should not crash but return U_INPUT_TOO_LONG_ERROR",
|
||||
+ U_INPUT_TOO_LONG_ERROR, status);
|
||||
+
|
||||
+ // Test sb.insert() of the first FormattedStringBuilder with the second one.
|
||||
+ sb.insert(0, sb2, status);
|
||||
+ assertEquals(
|
||||
+ "insert() long FormattedStringBuilder should not crash but return "
|
||||
+ "U_INPUT_TOO_LONG_ERROR", U_INPUT_TOO_LONG_ERROR, status);
|
||||
+
|
||||
+ // Test sb.insert() of the first FormattedStringBuilder with UnicodeString.
|
||||
+ sb.insert(0, ustr, 0, ustr.length(), kUndefinedField, status);
|
||||
+ assertEquals(
|
||||
+ "insert() long UnicodeString should not crash but return "
|
||||
+ "U_INPUT_TOO_LONG_ERROR", U_INPUT_TOO_LONG_ERROR, status);
|
||||
+}
|
||||
+
|
||||
void FormattedStringBuilderTest::assertEqualsImpl(const UnicodeString &a, const FormattedStringBuilder &b) {
|
||||
// TODO: Why won't this compile without the IntlTest:: qualifier?
|
||||
IntlTest::assertEquals("Lengths should be the same", a.length(), b.length());
|
||||
@@ -44,3 +44,6 @@ process_simplify_uv_write_int_calls_3519.patch
|
||||
macos_don_t_use_thread-unsafe_strtok_3524.patch
|
||||
process_fix_hang_after_note_exit_3521.patch
|
||||
worker_thread_add_asar_support.patch
|
||||
macos_avoid_posix_spawnp_cwd_bug_3597.patch
|
||||
build_disable_v8_pointer_compression_on_32bit_archs.patch
|
||||
feat_add_knostartdebugsignalhandler_to_environment_to_prevent.patch
|
||||
|
||||
@@ -1793,11 +1793,11 @@ index 08e957472cfeca84af8cdc951af3c0de99c7b56c..330d77e868a50e1d0b71d773ab6b4b33
|
||||
// which the Node binary being built supports.
|
||||
diff --git a/tools/generate_gn_filenames_json.py b/tools/generate_gn_filenames_json.py
|
||||
new file mode 100755
|
||||
index 0000000000000000000000000000000000000000..8f884a41f57630ac432eb85ebfc9b8bc82cddaca
|
||||
index 0000000000000000000000000000000000000000..87621ba1d7f1c80aadb81461824b0c2edab1de22
|
||||
--- /dev/null
|
||||
+++ b/tools/generate_gn_filenames_json.py
|
||||
@@ -0,0 +1,75 @@
|
||||
+#!/usr/bin/env python
|
||||
+#!/usr/bin/env python3
|
||||
+import json
|
||||
+import os
|
||||
+import sys
|
||||
@@ -1874,11 +1874,11 @@ index 0000000000000000000000000000000000000000..8f884a41f57630ac432eb85ebfc9b8bc
|
||||
+ f.write('\n')
|
||||
diff --git a/tools/generate_node_version_header.py b/tools/generate_node_version_header.py
|
||||
new file mode 100755
|
||||
index 0000000000000000000000000000000000000000..3088ae4bdf814ae255c9805ebd393b2eee17e941
|
||||
index 0000000000000000000000000000000000000000..2a92eccfa582df361f2a889c0d9b32c1059baa7d
|
||||
--- /dev/null
|
||||
+++ b/tools/generate_node_version_header.py
|
||||
@@ -0,0 +1,25 @@
|
||||
+#!/usr/bin/env python
|
||||
+#!/usr/bin/env python3
|
||||
+import re
|
||||
+import sys
|
||||
+
|
||||
|
||||
@@ -0,0 +1,31 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Cheng Zhao <zcbenz@gmail.com>
|
||||
Date: Tue, 12 Oct 2021 10:41:55 +0900
|
||||
Subject: build: disable v8 pointer compression on 32bit archs
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
|
||||
PR-URL: https://github.com/nodejs/node/pull/40418
|
||||
Reviewed-By: Jiawen Geng <technicalcute@gmail.com>
|
||||
Reviewed-By: Stewart X Addison <sxa@redhat.com>
|
||||
Reviewed-By: Tobias Nießen <tniessen@tnie.de>
|
||||
Reviewed-By: Minwoo Jung <nodecorelab@gmail.com>
|
||||
Reviewed-By: Michael Dawson <midawson@redhat.com>
|
||||
|
||||
diff --git a/common.gypi b/common.gypi
|
||||
index 8a85c7c3d0ab0e2906c417f2cc2fc9ca584fd601..f6ea8340b696103d0949df7fb7b75a1d05e90f87 100644
|
||||
--- a/common.gypi
|
||||
+++ b/common.gypi
|
||||
@@ -130,6 +130,11 @@
|
||||
['target_arch == "arm64" or target_arch == "x64"', {
|
||||
'v8_enable_pointer_compression': 1,
|
||||
}],
|
||||
+ # V8 pointer compression only supports 64bit architectures.
|
||||
+ ['target_arch in "arm ia32 mips mipsel ppc x32"', {
|
||||
+ 'v8_enable_pointer_compression': 0,
|
||||
+ 'v8_enable_31bit_smis_on_64bit_arch': 0,
|
||||
+ }],
|
||||
['target_arch in "ppc64 s390x"', {
|
||||
'v8_enable_backtrace': 1,
|
||||
}],
|
||||
@@ -0,0 +1,69 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Samuel Attard <samuel.r.attard@gmail.com>
|
||||
Date: Mon, 7 Mar 2022 16:36:28 -0800
|
||||
Subject: feat: add kNoStartDebugSignalHandler to Environment to prevent
|
||||
SIGUSR1 handling
|
||||
|
||||
This patch should be upstreamed, it allows embedders to prevent the call to StartDebugSignalHandler which handles SIGUSR1 and starts the inspector agent. Apps that have --inspect disabled also don't want SIGUSR1 to have this affect.
|
||||
|
||||
diff --git a/src/env-inl.h b/src/env-inl.h
|
||||
index 845e00208af4b12960ed8b3f3926323af7685185..1ebc33324907654d16e9c0e19b2955efbac7cac7 100644
|
||||
--- a/src/env-inl.h
|
||||
+++ b/src/env-inl.h
|
||||
@@ -896,6 +896,10 @@ inline bool Environment::should_initialize_inspector() const {
|
||||
return (flags_ & EnvironmentFlags::kNoInitializeInspector) == 0;
|
||||
}
|
||||
|
||||
+inline bool Environment::should_start_debug_signal_handler() const {
|
||||
+ return (flags_ & EnvironmentFlags::kNoStartDebugSignalHandler) == 0;
|
||||
+}
|
||||
+
|
||||
bool Environment::filehandle_close_warning() const {
|
||||
return emit_filehandle_warning_;
|
||||
}
|
||||
diff --git a/src/env.h b/src/env.h
|
||||
index ab8334bf0e3405fee4d21a4b541bd1164d92ca89..b2537ebd44bc5b37dd97752735f84e87de1f24bf 100644
|
||||
--- a/src/env.h
|
||||
+++ b/src/env.h
|
||||
@@ -1207,6 +1207,7 @@ class Environment : public MemoryRetainer {
|
||||
inline bool hide_console_windows() const;
|
||||
inline bool no_global_search_paths() const;
|
||||
inline bool should_initialize_inspector() const;
|
||||
+ inline bool should_start_debug_signal_handler() const;
|
||||
inline uint64_t thread_id() const;
|
||||
inline worker::Worker* worker_context() const;
|
||||
Environment* worker_parent_env() const;
|
||||
diff --git a/src/inspector_agent.cc b/src/inspector_agent.cc
|
||||
index c4a3322c6d972fc2052af75b79389c522924d9c5..39ff8df415be1908ba404fba34d9cedda04a88af 100644
|
||||
--- a/src/inspector_agent.cc
|
||||
+++ b/src/inspector_agent.cc
|
||||
@@ -680,8 +680,10 @@ bool Agent::Start(const std::string& path,
|
||||
StartIoThreadAsyncCallback));
|
||||
uv_unref(reinterpret_cast<uv_handle_t*>(&start_io_thread_async));
|
||||
start_io_thread_async.data = this;
|
||||
- // Ignore failure, SIGUSR1 won't work, but that should not block node start.
|
||||
- StartDebugSignalHandler();
|
||||
+ if (parent_env_->should_start_debug_signal_handler()) {
|
||||
+ // Ignore failure, SIGUSR1 won't work, but that should not block node start.
|
||||
+ StartDebugSignalHandler();
|
||||
+ }
|
||||
|
||||
parent_env_->AddCleanupHook([](void* data) {
|
||||
Environment* env = static_cast<Environment*>(data);
|
||||
diff --git a/src/node.h b/src/node.h
|
||||
index 4201c0d0460b032721ef42a26d79c38a9ee20c24..6873fc89406b046823db9e45234eb7f6b767099d 100644
|
||||
--- a/src/node.h
|
||||
+++ b/src/node.h
|
||||
@@ -425,7 +425,11 @@ enum Flags : uint64_t {
|
||||
// Controls whether or not the Environment should call InitializeInspector.
|
||||
// This control is needed by embedders who may not want to initialize the V8
|
||||
// inspector in situations where it already exists.
|
||||
- kNoInitializeInspector = 1 << 8
|
||||
+ kNoInitializeInspector = 1 << 8,
|
||||
+ // Controls where or not the InspectorAgent for this Environment should
|
||||
+ // call StartDebugSignalHandler. This control is needed by embedders who may
|
||||
+ // not want to allow other processes to start the V8 inspector.
|
||||
+ kNoStartDebugSignalHandler = 1 << 9
|
||||
};
|
||||
} // namespace EnvironmentFlags
|
||||
|
||||
111
patches/node/macos_avoid_posix_spawnp_cwd_bug_3597.patch
Normal file
111
patches/node/macos_avoid_posix_spawnp_cwd_bug_3597.patch
Normal file
@@ -0,0 +1,111 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Jameson Nash <vtjnash@gmail.com>
|
||||
Date: Fri, 15 Apr 2022 14:10:27 -0400
|
||||
Subject: macos: avoid posix_spawnp() cwd bug (#3597)
|
||||
|
||||
macOS 10.15 has a bug where configuring the working directory with
|
||||
posix_spawn_file_actions_addchdir_np() makes posix_spawnp() fail with
|
||||
ENOENT even though the executable is spawned successfully.
|
||||
|
||||
diff --git a/deps/uv/src/unix/process.c b/deps/uv/src/unix/process.c
|
||||
index c8816b85b7e531648064e739fb89257565ad64bb..de51bac3d0e8daf519d35c6a3994f1479590607a 100644
|
||||
--- a/deps/uv/src/unix/process.c
|
||||
+++ b/deps/uv/src/unix/process.c
|
||||
@@ -671,27 +671,25 @@ static int uv__spawn_resolve_and_spawn(const uv_process_options_t* options,
|
||||
if (options->env != NULL)
|
||||
env = options->env;
|
||||
|
||||
- /* If options->file contains a slash, posix_spawn/posix_spawnp behave
|
||||
- * the same, and don't involve PATH resolution at all. Otherwise, if
|
||||
- * options->file does not include a slash, but no custom environment is
|
||||
- * to be used, the environment used for path resolution as well for the
|
||||
- * child process is that of the parent process, so posix_spawnp is the
|
||||
- * way to go. */
|
||||
- if (strchr(options->file, '/') != NULL || options->env == NULL) {
|
||||
+ /* If options->file contains a slash, posix_spawn/posix_spawnp should behave
|
||||
+ * the same, and do not involve PATH resolution at all. The libc
|
||||
+ * `posix_spawnp` provided by Apple is buggy (since 10.15), so we now emulate it
|
||||
+ * here, per https://github.com/libuv/libuv/pull/3583. */
|
||||
+ if (strchr(options->file, '/') != NULL) {
|
||||
do
|
||||
- err = posix_spawnp(pid, options->file, actions, attrs, options->args, env);
|
||||
+ err = posix_spawn(pid, options->file, actions, attrs, options->args, env);
|
||||
while (err == EINTR);
|
||||
return err;
|
||||
}
|
||||
|
||||
/* Look for the definition of PATH in the provided env */
|
||||
- path = uv__spawn_find_path_in_env(options->env);
|
||||
+ path = uv__spawn_find_path_in_env(env);
|
||||
|
||||
/* The following resolution logic (execvpe emulation) is copied from
|
||||
* https://git.musl-libc.org/cgit/musl/tree/src/process/execvp.c
|
||||
* and adapted to work for our specific usage */
|
||||
|
||||
- /* If no path was provided in options->env, use the default value
|
||||
+ /* If no path was provided in env, use the default value
|
||||
* to look for the executable */
|
||||
if (path == NULL)
|
||||
path = _PATH_DEFPATH;
|
||||
diff --git a/deps/uv/test/test-list.h b/deps/uv/test/test-list.h
|
||||
index 58489c4be7b3a7b36d5b01a1f07d411ef3d99ae3..b4c039706417ab679c4f24a863118e736635371c 100644
|
||||
--- a/deps/uv/test/test-list.h
|
||||
+++ b/deps/uv/test/test-list.h
|
||||
@@ -319,6 +319,7 @@ TEST_DECLARE (spawn_inherit_streams)
|
||||
TEST_DECLARE (spawn_quoted_path)
|
||||
TEST_DECLARE (spawn_tcp_server)
|
||||
TEST_DECLARE (spawn_exercise_sigchld_issue)
|
||||
+TEST_DECLARE (spawn_relative_path)
|
||||
TEST_DECLARE (fs_poll)
|
||||
TEST_DECLARE (fs_poll_getpath)
|
||||
TEST_DECLARE (fs_poll_close_request)
|
||||
@@ -946,6 +947,7 @@ TASK_LIST_START
|
||||
TEST_ENTRY (spawn_quoted_path)
|
||||
TEST_ENTRY (spawn_tcp_server)
|
||||
TEST_ENTRY (spawn_exercise_sigchld_issue)
|
||||
+ TEST_ENTRY (spawn_relative_path)
|
||||
TEST_ENTRY (fs_poll)
|
||||
TEST_ENTRY (fs_poll_getpath)
|
||||
TEST_ENTRY (fs_poll_close_request)
|
||||
diff --git a/deps/uv/test/test-spawn.c b/deps/uv/test/test-spawn.c
|
||||
index dfd5458ef37c664af9a55a8383bdb3121885db3b..de9c710020ef7da66e45f5617a8a697e698fa202 100644
|
||||
--- a/deps/uv/test/test-spawn.c
|
||||
+++ b/deps/uv/test/test-spawn.c
|
||||
@@ -1981,3 +1981,37 @@ void spawn_stdin_stdout(void) {
|
||||
}
|
||||
}
|
||||
#endif /* !_WIN32 */
|
||||
+
|
||||
+TEST_IMPL(spawn_relative_path) {
|
||||
+ char* sep;
|
||||
+
|
||||
+ init_process_options("spawn_helper1", exit_cb);
|
||||
+
|
||||
+ exepath_size = sizeof(exepath) - 2;
|
||||
+ ASSERT_EQ(0, uv_exepath(exepath, &exepath_size));
|
||||
+ exepath[exepath_size] = '\0';
|
||||
+
|
||||
+ /* Poor man's basename(3). */
|
||||
+ sep = strrchr(exepath, '/');
|
||||
+ if (sep == NULL)
|
||||
+ sep = strrchr(exepath, '\\');
|
||||
+ ASSERT_NOT_NULL(sep);
|
||||
+
|
||||
+ /* Split into dirname and basename and make basename relative. */
|
||||
+ memmove(sep + 2, sep, 1 + strlen(sep));
|
||||
+ sep[0] = '\0';
|
||||
+ sep[1] = '.';
|
||||
+ sep[2] = '/';
|
||||
+
|
||||
+ options.cwd = exepath;
|
||||
+ options.file = options.args[0] = sep + 1;
|
||||
+
|
||||
+ ASSERT_EQ(0, uv_spawn(uv_default_loop(), &process, &options));
|
||||
+ ASSERT_EQ(0, uv_run(uv_default_loop(), UV_RUN_DEFAULT));
|
||||
+
|
||||
+ ASSERT_EQ(1, exit_cb_called);
|
||||
+ ASSERT_EQ(1, close_cb_called);
|
||||
+
|
||||
+ MAKE_VALGRIND_HAPPY();
|
||||
+ return 0;
|
||||
+}
|
||||
@@ -511,11 +511,11 @@ index 0000000000000000000000000000000000000000..bdfaf95f3eca65b3e0831db1b66f651d
|
||||
+}
|
||||
diff --git a/build/xcrun.py b/build/xcrun.py
|
||||
new file mode 100644
|
||||
index 0000000000000000000000000000000000000000..18ac587f80441106405d00fafd9ee1f25b147772
|
||||
index 0000000000000000000000000000000000000000..a7aeeb7d3e187bd91ef12ed860d1e37eaea31fc1
|
||||
--- /dev/null
|
||||
+++ b/build/xcrun.py
|
||||
@@ -0,0 +1,14 @@
|
||||
+#!/usr/bin/env python
|
||||
+#!/usr/bin/env python3
|
||||
+from __future__ import print_function
|
||||
+import os
|
||||
+import subprocess
|
||||
|
||||
@@ -8,3 +8,9 @@ fix_build_deprecated_attirbute_for_older_msvc_versions.patch
|
||||
fix_disable_implies_dcheck_for_node_stream_array_buffers.patch
|
||||
fix_use_allocationtype_kold_in_v8_scriptormodule_legacy_lifetime.patch
|
||||
fix_destructor_for_embedderstatescope.patch
|
||||
cherry-pick-36b66b5cc991.patch
|
||||
cherry-pick-f546ac11eec7.patch
|
||||
cherry-pick-e42dbcdedb7a.patch
|
||||
cherry-pick-b2d3ef69ef99.patch
|
||||
cherry-pick-2004594a46c8.patch
|
||||
cherry-pick-723ed8a9cfff.patch
|
||||
|
||||
62
patches/v8/cherry-pick-2004594a46c8.patch
Normal file
62
patches/v8/cherry-pick-2004594a46c8.patch
Normal file
@@ -0,0 +1,62 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Nico Hartmann <nicohartmann@chromium.org>
|
||||
Date: Thu, 17 Mar 2022 17:03:12 +0100
|
||||
Subject: Fix NumberConstant used with Word32 rep in ISel
|
||||
|
||||
Bug: chromium:1304658
|
||||
|
||||
(cherry picked from commit bbea5909c797dec7c620b9fee43d80a1420c2e08)
|
||||
|
||||
No-Try: true
|
||||
No-Presubmit: true
|
||||
No-Tree-Checks: true
|
||||
Change-Id: I6a82603a7c5de5ae8f5a895990c1a904bbdd39b2
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/3532263
|
||||
Auto-Submit: Nico Hartmann <nicohartmann@chromium.org>
|
||||
Commit-Queue: Tobias Tebbi <tebbi@chromium.org>
|
||||
Cr-Original-Commit-Position: refs/heads/main@{#79526}
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/3541919
|
||||
Reviewed-by: Nico Hartmann <nicohartmann@chromium.org>
|
||||
Commit-Queue: Roger Felipe Zanoni da Silva <rzanoni@google.com>
|
||||
Cr-Commit-Position: refs/branch-heads/9.6@{#58}
|
||||
Cr-Branched-From: 0b7bda016178bf438f09b3c93da572ae3663a1f7-refs/heads/9.6.180@{#1}
|
||||
Cr-Branched-From: 41a5a247d9430b953e38631e88d17790306f7a4c-refs/heads/main@{#77244}
|
||||
|
||||
diff --git a/src/compiler/backend/instruction-selector.cc b/src/compiler/backend/instruction-selector.cc
|
||||
index fc04b37ec3fe1a3f4e9db0a1ba825b71696ec0cb..c6b41ca79120c1f553e4c10eff8d3285bf9bbe91 100644
|
||||
--- a/src/compiler/backend/instruction-selector.cc
|
||||
+++ b/src/compiler/backend/instruction-selector.cc
|
||||
@@ -30,6 +30,14 @@ namespace v8 {
|
||||
namespace internal {
|
||||
namespace compiler {
|
||||
|
||||
+Smi NumberConstantToSmi(Node* node) {
|
||||
+ DCHECK_EQ(node->opcode(), IrOpcode::kNumberConstant);
|
||||
+ const double d = OpParameter<double>(node->op());
|
||||
+ Smi smi = Smi::FromInt(static_cast<int32_t>(d));
|
||||
+ CHECK_EQ(smi.value(), d);
|
||||
+ return smi;
|
||||
+}
|
||||
+
|
||||
InstructionSelector::InstructionSelector(
|
||||
Zone* zone, size_t node_count, Linkage* linkage,
|
||||
InstructionSequence* sequence, Schedule* schedule,
|
||||
@@ -501,11 +509,17 @@ InstructionOperand OperandForDeopt(Isolate* isolate, OperandGenerator* g,
|
||||
switch (input->opcode()) {
|
||||
case IrOpcode::kInt32Constant:
|
||||
case IrOpcode::kInt64Constant:
|
||||
- case IrOpcode::kNumberConstant:
|
||||
case IrOpcode::kFloat32Constant:
|
||||
case IrOpcode::kFloat64Constant:
|
||||
case IrOpcode::kDelayedStringConstant:
|
||||
return g->UseImmediate(input);
|
||||
+ case IrOpcode::kNumberConstant:
|
||||
+ if (rep == MachineRepresentation::kWord32) {
|
||||
+ Smi smi = NumberConstantToSmi(input);
|
||||
+ return g->UseImmediate(static_cast<int32_t>(smi.ptr()));
|
||||
+ } else {
|
||||
+ return g->UseImmediate(input);
|
||||
+ }
|
||||
case IrOpcode::kCompressedHeapConstant:
|
||||
case IrOpcode::kHeapConstant: {
|
||||
if (!CanBeTaggedOrCompressedPointer(rep)) {
|
||||
142
patches/v8/cherry-pick-36b66b5cc991.patch
Normal file
142
patches/v8/cherry-pick-36b66b5cc991.patch
Normal file
@@ -0,0 +1,142 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Igor Sheludko <ishell@chromium.org>
|
||||
Date: Fri, 1 Apr 2022 17:41:24 +0200
|
||||
Subject: Merged: [runtime] Fix handling of interceptors, pt.3
|
||||
|
||||
... in JSObject::DefineOwnPropertyIgnoreAttributes().
|
||||
Don't execute interceptor again if it declined to handle the operation.
|
||||
|
||||
Bug: chromium:1311641
|
||||
(cherry picked from commit c4e66b89b4ecd0e90b31e9e4ed08d38085a84c49)
|
||||
|
||||
Change-Id: Ie9aef5a98959403f6a26e6bef7f4a77d312bd62a
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/3563560
|
||||
Reviewed-by: Toon Verwaest <verwaest@chromium.org>
|
||||
Cr-Commit-Position: refs/branch-heads/10.0@{#16}
|
||||
Cr-Branched-From: 6ea73a738c467dc26abbbe84e27a36aac1c6e119-refs/heads/10.0.139@{#1}
|
||||
Cr-Branched-From: ccc689011280419901e6ee42cae39980c0e96030-refs/heads/main@{#79131}
|
||||
|
||||
diff --git a/src/objects/js-objects.cc b/src/objects/js-objects.cc
|
||||
index 1df13df72c29f804168ab1f57117650922378a07..d823bba604936c1c99b4e3aea694afc8fa267d83 100644
|
||||
--- a/src/objects/js-objects.cc
|
||||
+++ b/src/objects/js-objects.cc
|
||||
@@ -3451,9 +3451,18 @@ Maybe<bool> JSObject::DefineOwnPropertyIgnoreAttributes(
|
||||
if (can_define.IsNothing() || !can_define.FromJust()) {
|
||||
return can_define;
|
||||
}
|
||||
- it->Restart();
|
||||
}
|
||||
- break;
|
||||
+
|
||||
+ // The interceptor declined to handle the operation, so proceed defining
|
||||
+ // own property without the interceptor.
|
||||
+ Isolate* isolate = it->isolate();
|
||||
+ Handle<Object> receiver = it->GetReceiver();
|
||||
+ LookupIterator::Configuration c = LookupIterator::OWN_SKIP_INTERCEPTOR;
|
||||
+ LookupIterator own_lookup =
|
||||
+ it->IsElement() ? LookupIterator(isolate, receiver, it->index(), c)
|
||||
+ : LookupIterator(isolate, receiver, it->name(), c);
|
||||
+ return JSObject::DefineOwnPropertyIgnoreAttributes(
|
||||
+ &own_lookup, value, attributes, should_throw, handling, semantics);
|
||||
}
|
||||
|
||||
case LookupIterator::ACCESSOR: {
|
||||
diff --git a/test/cctest/test-api-interceptors.cc b/test/cctest/test-api-interceptors.cc
|
||||
index 909795ece407ac2089f15e562d308733371fbb65..7eb96a54f77519a8b968d40fab4d01070e0ed179 100644
|
||||
--- a/test/cctest/test-api-interceptors.cc
|
||||
+++ b/test/cctest/test-api-interceptors.cc
|
||||
@@ -60,6 +60,16 @@ void EmptyInterceptorDeleter(
|
||||
void EmptyInterceptorEnumerator(
|
||||
const v8::PropertyCallbackInfo<v8::Array>& info) {}
|
||||
|
||||
+void EmptyInterceptorDefinerWithSideEffect(
|
||||
+ Local<Name> name, const v8::PropertyDescriptor& desc,
|
||||
+ const v8::PropertyCallbackInfo<v8::Value>& info) {
|
||||
+ ApiTestFuzzer::Fuzz();
|
||||
+ v8::Local<v8::Value> result = CompileRun("interceptor_definer_side_effect()");
|
||||
+ if (!result->IsNull()) {
|
||||
+ info.GetReturnValue().Set(result);
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
void SimpleAccessorGetter(Local<String> name,
|
||||
const v8::PropertyCallbackInfo<v8::Value>& info) {
|
||||
Local<Object> self = info.This().As<Object>();
|
||||
@@ -869,13 +879,17 @@ THREADED_TEST(InterceptorHasOwnPropertyCausingGC) {
|
||||
namespace {
|
||||
|
||||
void CheckInterceptorIC(v8::GenericNamedPropertyGetterCallback getter,
|
||||
+ v8::GenericNamedPropertySetterCallback setter,
|
||||
v8::GenericNamedPropertyQueryCallback query,
|
||||
- const char* source, int expected) {
|
||||
+ v8::GenericNamedPropertyDefinerCallback definer,
|
||||
+ v8::PropertyHandlerFlags flags, const char* source,
|
||||
+ int expected) {
|
||||
v8::Isolate* isolate = CcTest::isolate();
|
||||
v8::HandleScope scope(isolate);
|
||||
v8::Local<v8::ObjectTemplate> templ = ObjectTemplate::New(isolate);
|
||||
templ->SetHandler(v8::NamedPropertyHandlerConfiguration(
|
||||
- getter, nullptr, query, nullptr, nullptr, v8_str("data")));
|
||||
+ getter, setter, query, nullptr /* deleter */, nullptr /* enumerator */,
|
||||
+ definer, nullptr /* descriptor */, v8_str("data"), flags));
|
||||
LocalContext context;
|
||||
context->Global()
|
||||
->Set(context.local(), v8_str("o"),
|
||||
@@ -885,9 +899,17 @@ void CheckInterceptorIC(v8::GenericNamedPropertyGetterCallback getter,
|
||||
CHECK_EQ(expected, value->Int32Value(context.local()).FromJust());
|
||||
}
|
||||
|
||||
+void CheckInterceptorIC(v8::GenericNamedPropertyGetterCallback getter,
|
||||
+ v8::GenericNamedPropertyQueryCallback query,
|
||||
+ const char* source, int expected) {
|
||||
+ CheckInterceptorIC(getter, nullptr, query, nullptr,
|
||||
+ v8::PropertyHandlerFlags::kNone, source, expected);
|
||||
+}
|
||||
+
|
||||
void CheckInterceptorLoadIC(v8::GenericNamedPropertyGetterCallback getter,
|
||||
const char* source, int expected) {
|
||||
- CheckInterceptorIC(getter, nullptr, source, expected);
|
||||
+ CheckInterceptorIC(getter, nullptr, nullptr, nullptr,
|
||||
+ v8::PropertyHandlerFlags::kNone, source, expected);
|
||||
}
|
||||
|
||||
void InterceptorLoadICGetter(Local<Name> name,
|
||||
@@ -1581,6 +1603,38 @@ THREADED_TEST(InterceptorStoreICWithSideEffectfulCallbacks) {
|
||||
19);
|
||||
}
|
||||
|
||||
+THREADED_TEST(InterceptorDefineICWithSideEffectfulCallbacks) {
|
||||
+ CheckInterceptorIC(EmptyInterceptorGetter, EmptyInterceptorSetter,
|
||||
+ EmptyInterceptorQuery,
|
||||
+ EmptyInterceptorDefinerWithSideEffect,
|
||||
+ v8::PropertyHandlerFlags::kNonMasking,
|
||||
+ "let inside_side_effect = false;"
|
||||
+ "let interceptor_definer_side_effect = function() {"
|
||||
+ " if (!inside_side_effect) {"
|
||||
+ " inside_side_effect = true;"
|
||||
+ " o.y = 153;"
|
||||
+ " inside_side_effect = false;"
|
||||
+ " }"
|
||||
+ " return null;"
|
||||
+ "};"
|
||||
+ "class Base {"
|
||||
+ " constructor(arg) {"
|
||||
+ " return arg;"
|
||||
+ " }"
|
||||
+ "}"
|
||||
+ "class ClassWithField extends Base {"
|
||||
+ " y = (() => {"
|
||||
+ " return 42;"
|
||||
+ " })();"
|
||||
+ " constructor(arg) {"
|
||||
+ " super(arg);"
|
||||
+ " }"
|
||||
+ "}"
|
||||
+ "new ClassWithField(o);"
|
||||
+ "o.y",
|
||||
+ 42);
|
||||
+}
|
||||
+
|
||||
static void InterceptorStoreICSetter(
|
||||
Local<Name> key, Local<Value> value,
|
||||
const v8::PropertyCallbackInfo<v8::Value>& info) {
|
||||
195
patches/v8/cherry-pick-723ed8a9cfff.patch
Normal file
195
patches/v8/cherry-pick-723ed8a9cfff.patch
Normal file
@@ -0,0 +1,195 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Jakob Kummerow <jkummerow@chromium.org>
|
||||
Date: Mon, 2 May 2022 19:52:11 +0200
|
||||
Subject: Merged: [wasm] Fix Int64Lowering for tagged stack-passed parameters
|
||||
|
||||
When lowering signatures, we must preserve the separation of parameters
|
||||
into tagged and untagged sections.
|
||||
|
||||
Fixed: chromium:1320614
|
||||
(cherry picked from commit 8062598f26127d833c237acb3da154c91c1ec7e7)
|
||||
|
||||
Change-Id: I2f84535f785ce5c96e9c892994416986965eaa40
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/3632515
|
||||
Commit-Queue: Jakob Kummerow <jkummerow@chromium.org>
|
||||
Reviewed-by: Shu-yu Guo <syg@chromium.org>
|
||||
Cr-Commit-Position: refs/branch-heads/10.1@{#28}
|
||||
Cr-Branched-From: b003970395b7efcc309eb30b4ca06dd8385acd55-refs/heads/10.1.124@{#1}
|
||||
Cr-Branched-From: e62f556862624103ea1da5b9dcef9b216832033b-refs/heads/main@{#79503}
|
||||
|
||||
diff --git a/src/compiler/wasm-compiler.cc b/src/compiler/wasm-compiler.cc
|
||||
index 07bb41358898fbd9c5968fb8a37dff161e71ed65..5bd325035726d4e91ede2b54076dd0d2cfdce8c0 100644
|
||||
--- a/src/compiler/wasm-compiler.cc
|
||||
+++ b/src/compiler/wasm-compiler.cc
|
||||
@@ -8233,16 +8233,10 @@ class LinkageLocationAllocator {
|
||||
// must be offset to just before the param slots, using this |slot_offset_|.
|
||||
int slot_offset_;
|
||||
};
|
||||
-} // namespace
|
||||
|
||||
-// General code uses the above configuration data.
|
||||
-CallDescriptor* GetWasmCallDescriptor(Zone* zone, const wasm::FunctionSig* fsig,
|
||||
- WasmCallKind call_kind,
|
||||
- bool need_frame_state) {
|
||||
- // The extra here is to accomodate the instance object as first parameter
|
||||
- // and, when specified, the additional callable.
|
||||
- bool extra_callable_param =
|
||||
- call_kind == kWasmImportWrapper || call_kind == kWasmCapiFunction;
|
||||
+LocationSignature* BuildLocations(Zone* zone, const wasm::FunctionSig* fsig,
|
||||
+ bool extra_callable_param,
|
||||
+ int* parameter_slots, int* return_slots) {
|
||||
int extra_params = extra_callable_param ? 2 : 1;
|
||||
LocationSignature::Builder locations(zone, fsig->return_count(),
|
||||
fsig->parameter_count() + extra_params);
|
||||
@@ -8285,19 +8279,37 @@ CallDescriptor* GetWasmCallDescriptor(Zone* zone, const wasm::FunctionSig* fsig,
|
||||
kJSFunctionRegister.code(), MachineType::TaggedPointer()));
|
||||
}
|
||||
|
||||
- int parameter_slots = AddArgumentPaddingSlots(params.NumStackSlots());
|
||||
+ *parameter_slots = AddArgumentPaddingSlots(params.NumStackSlots());
|
||||
|
||||
// Add return location(s).
|
||||
LinkageLocationAllocator rets(wasm::kGpReturnRegisters,
|
||||
- wasm::kFpReturnRegisters, parameter_slots);
|
||||
+ wasm::kFpReturnRegisters, *parameter_slots);
|
||||
|
||||
- const int return_count = static_cast<int>(locations.return_count_);
|
||||
- for (int i = 0; i < return_count; i++) {
|
||||
+ const size_t return_count = locations.return_count_;
|
||||
+ for (size_t i = 0; i < return_count; i++) {
|
||||
MachineRepresentation ret = fsig->GetReturn(i).machine_representation();
|
||||
locations.AddReturn(rets.Next(ret));
|
||||
}
|
||||
|
||||
- int return_slots = rets.NumStackSlots();
|
||||
+ *return_slots = rets.NumStackSlots();
|
||||
+
|
||||
+ return locations.Build();
|
||||
+}
|
||||
+} // namespace
|
||||
+
|
||||
+// General code uses the above configuration data.
|
||||
+CallDescriptor* GetWasmCallDescriptor(Zone* zone, const wasm::FunctionSig* fsig,
|
||||
+ WasmCallKind call_kind,
|
||||
+ bool need_frame_state) {
|
||||
+ // The extra here is to accomodate the instance object as first parameter
|
||||
+ // and, when specified, the additional callable.
|
||||
+ bool extra_callable_param =
|
||||
+ call_kind == kWasmImportWrapper || call_kind == kWasmCapiFunction;
|
||||
+
|
||||
+ int parameter_slots;
|
||||
+ int return_slots;
|
||||
+ LocationSignature* location_sig = BuildLocations(
|
||||
+ zone, fsig, extra_callable_param, ¶meter_slots, &return_slots);
|
||||
|
||||
const RegList kCalleeSaveRegisters = 0;
|
||||
const RegList kCalleeSaveFPRegisters = 0;
|
||||
@@ -8323,7 +8335,7 @@ CallDescriptor* GetWasmCallDescriptor(Zone* zone, const wasm::FunctionSig* fsig,
|
||||
descriptor_kind, // kind
|
||||
target_type, // target MachineType
|
||||
target_loc, // target location
|
||||
- locations.Build(), // location_sig
|
||||
+ location_sig, // location_sig
|
||||
parameter_slots, // parameter slot count
|
||||
compiler::Operator::kNoProperties, // properties
|
||||
kCalleeSaveRegisters, // callee-saved registers
|
||||
@@ -8374,78 +8386,45 @@ const wasm::FunctionSig* ReplaceTypeInSig(Zone* zone,
|
||||
CallDescriptor* ReplaceTypeInCallDescriptorWith(
|
||||
Zone* zone, const CallDescriptor* call_descriptor, size_t num_replacements,
|
||||
wasm::ValueType input_type, wasm::ValueType output_type) {
|
||||
- size_t parameter_count = call_descriptor->ParameterCount();
|
||||
- size_t return_count = call_descriptor->ReturnCount();
|
||||
- for (size_t i = 0; i < call_descriptor->ParameterCount(); i++) {
|
||||
- if (call_descriptor->GetParameterType(i) == input_type.machine_type()) {
|
||||
- parameter_count += num_replacements - 1;
|
||||
+ if (call_descriptor->wasm_sig() == nullptr) {
|
||||
+ // This happens for builtins calls. They need no replacements anyway.
|
||||
+#if DEBUG
|
||||
+ for (size_t i = 0; i < call_descriptor->ParameterCount(); i++) {
|
||||
+ DCHECK_NE(call_descriptor->GetParameterType(i),
|
||||
+ input_type.machine_type());
|
||||
}
|
||||
- }
|
||||
- for (size_t i = 0; i < call_descriptor->ReturnCount(); i++) {
|
||||
- if (call_descriptor->GetReturnType(i) == input_type.machine_type()) {
|
||||
- return_count += num_replacements - 1;
|
||||
+ for (size_t i = 0; i < call_descriptor->ReturnCount(); i++) {
|
||||
+ DCHECK_NE(call_descriptor->GetReturnType(i), input_type.machine_type());
|
||||
}
|
||||
+#endif
|
||||
+ return const_cast<CallDescriptor*>(call_descriptor);
|
||||
}
|
||||
- if (parameter_count == call_descriptor->ParameterCount() &&
|
||||
- return_count == call_descriptor->ReturnCount()) {
|
||||
+ const wasm::FunctionSig* sig =
|
||||
+ ReplaceTypeInSig(zone, call_descriptor->wasm_sig(), input_type,
|
||||
+ output_type, num_replacements);
|
||||
+ // If {ReplaceTypeInSig} took the early fast path, there's nothing to do.
|
||||
+ if (sig == call_descriptor->wasm_sig()) {
|
||||
return const_cast<CallDescriptor*>(call_descriptor);
|
||||
}
|
||||
|
||||
- LocationSignature::Builder locations(zone, return_count, parameter_count);
|
||||
-
|
||||
// The last parameter may be the special callable parameter. In that case we
|
||||
// have to preserve it as the last parameter, i.e. we allocate it in the new
|
||||
// location signature again in the same register.
|
||||
- bool has_callable_param =
|
||||
+ bool extra_callable_param =
|
||||
(call_descriptor->GetInputLocation(call_descriptor->InputCount() - 1) ==
|
||||
LinkageLocation::ForRegister(kJSFunctionRegister.code(),
|
||||
MachineType::TaggedPointer()));
|
||||
- LinkageLocationAllocator params(
|
||||
- wasm::kGpParamRegisters, wasm::kFpParamRegisters, 0 /* no slot offset */);
|
||||
-
|
||||
- for (size_t i = 0;
|
||||
- i < call_descriptor->ParameterCount() - (has_callable_param ? 1 : 0);
|
||||
- i++) {
|
||||
- if (call_descriptor->GetParameterType(i) == input_type.machine_type()) {
|
||||
- for (size_t j = 0; j < num_replacements; j++) {
|
||||
- locations.AddParam(params.Next(output_type.machine_representation()));
|
||||
- }
|
||||
- } else {
|
||||
- locations.AddParam(
|
||||
- params.Next(call_descriptor->GetParameterType(i).representation()));
|
||||
- }
|
||||
- }
|
||||
- if (has_callable_param) {
|
||||
- locations.AddParam(LinkageLocation::ForRegister(
|
||||
- kJSFunctionRegister.code(), MachineType::TaggedPointer()));
|
||||
- }
|
||||
-
|
||||
- int parameter_slots = AddArgumentPaddingSlots(params.NumStackSlots());
|
||||
-
|
||||
- LinkageLocationAllocator rets(wasm::kGpReturnRegisters,
|
||||
- wasm::kFpReturnRegisters, parameter_slots);
|
||||
-
|
||||
- for (size_t i = 0; i < call_descriptor->ReturnCount(); i++) {
|
||||
- if (call_descriptor->GetReturnType(i) == input_type.machine_type()) {
|
||||
- for (size_t j = 0; j < num_replacements; j++) {
|
||||
- locations.AddReturn(rets.Next(output_type.machine_representation()));
|
||||
- }
|
||||
- } else {
|
||||
- locations.AddReturn(
|
||||
- rets.Next(call_descriptor->GetReturnType(i).representation()));
|
||||
- }
|
||||
- }
|
||||
-
|
||||
- int return_slots = rets.NumStackSlots();
|
||||
|
||||
- auto sig = ReplaceTypeInSig(zone, call_descriptor->wasm_sig(), input_type,
|
||||
- output_type, num_replacements);
|
||||
+ int parameter_slots;
|
||||
+ int return_slots;
|
||||
+ LocationSignature* location_sig = BuildLocations(
|
||||
+ zone, sig, extra_callable_param, ¶meter_slots, &return_slots);
|
||||
|
||||
return zone->New<CallDescriptor>( // --
|
||||
call_descriptor->kind(), // kind
|
||||
call_descriptor->GetInputType(0), // target MachineType
|
||||
call_descriptor->GetInputLocation(0), // target location
|
||||
- locations.Build(), // location_sig
|
||||
+ location_sig, // location_sig
|
||||
parameter_slots, // parameter slot count
|
||||
call_descriptor->properties(), // properties
|
||||
call_descriptor->CalleeSavedRegisters(), // callee-saved registers
|
||||
79
patches/v8/cherry-pick-b2d3ef69ef99.patch
Normal file
79
patches/v8/cherry-pick-b2d3ef69ef99.patch
Normal file
@@ -0,0 +1,79 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Tobias Tebbi <tebbi@chromium.org>
|
||||
Date: Wed, 13 Apr 2022 16:30:36 +0000
|
||||
Subject: mark receiver and function as escaping
|
||||
|
||||
(cherry picked from commit 8081a5ffa7ebdb0e5b35cf63aa0490ad3578b940)
|
||||
|
||||
Bug: chromium:1315901
|
||||
No-Try: true
|
||||
No-Presubmit: true
|
||||
No-Tree-Checks: true
|
||||
Change-Id: Ic44bfcae32aba202ba25c5f59fe579214a444584
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/3584117
|
||||
Commit-Queue: Tobias Tebbi <tebbi@chromium.org>
|
||||
Cr-Original-Commit-Position: refs/heads/main@{#79968}
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/3584531
|
||||
Reviewed-by: Tobias Tebbi <tebbi@chromium.org>
|
||||
Reviewed-by: Nico Hartmann <nicohartmann@chromium.org>
|
||||
Commit-Queue: Roger Felipe Zanoni da Silva <rzanoni@google.com>
|
||||
Cr-Commit-Position: refs/branch-heads/9.6@{#62}
|
||||
Cr-Branched-From: 0b7bda016178bf438f09b3c93da572ae3663a1f7-refs/heads/9.6.180@{#1}
|
||||
Cr-Branched-From: 41a5a247d9430b953e38631e88d17790306f7a4c-refs/heads/main@{#77244}
|
||||
|
||||
diff --git a/src/compiler/escape-analysis.cc b/src/compiler/escape-analysis.cc
|
||||
index bf693c71dc670fdf290c6c5b84012d9965978c69..fe8126f9638e77ef72ddc56c7ae67822786d3020 100644
|
||||
--- a/src/compiler/escape-analysis.cc
|
||||
+++ b/src/compiler/escape-analysis.cc
|
||||
@@ -5,10 +5,12 @@
|
||||
#include "src/compiler/escape-analysis.h"
|
||||
|
||||
#include "src/codegen/tick-counter.h"
|
||||
+#include "src/compiler/frame-states.h"
|
||||
#include "src/compiler/linkage.h"
|
||||
#include "src/compiler/node-matchers.h"
|
||||
#include "src/compiler/operator-properties.h"
|
||||
#include "src/compiler/simplified-operator.h"
|
||||
+#include "src/compiler/state-values-utils.h"
|
||||
#include "src/handles/handles-inl.h"
|
||||
#include "src/init/bootstrapper.h"
|
||||
#include "src/objects/map-inl.h"
|
||||
@@ -224,6 +226,11 @@ class EscapeAnalysisTracker : public ZoneObject {
|
||||
return tracker_->ResolveReplacement(
|
||||
NodeProperties::GetContextInput(current_node()));
|
||||
}
|
||||
+ // Accessing the current node is fine for `FrameState nodes.
|
||||
+ Node* CurrentNode() {
|
||||
+ DCHECK_EQ(current_node()->opcode(), IrOpcode::kFrameState);
|
||||
+ return current_node();
|
||||
+ }
|
||||
|
||||
void SetReplacement(Node* replacement) {
|
||||
replacement_ = replacement;
|
||||
@@ -799,9 +806,25 @@ void ReduceNode(const Operator* op, EscapeAnalysisTracker::Scope* current,
|
||||
break;
|
||||
}
|
||||
case IrOpcode::kStateValues:
|
||||
- case IrOpcode::kFrameState:
|
||||
// These uses are always safe.
|
||||
break;
|
||||
+ case IrOpcode::kFrameState: {
|
||||
+ // We mark the receiver as escaping due to the non-standard `.getThis`
|
||||
+ // API.
|
||||
+ FrameState frame_state{current->CurrentNode()};
|
||||
+ if (frame_state.frame_state_info().type() !=
|
||||
+ FrameStateType::kUnoptimizedFunction)
|
||||
+ break;
|
||||
+ StateValuesAccess::iterator it =
|
||||
+ StateValuesAccess(frame_state.parameters()).begin();
|
||||
+ if (!it.done()) {
|
||||
+ if (Node* receiver = it.node()) {
|
||||
+ current->SetEscaped(receiver);
|
||||
+ }
|
||||
+ current->SetEscaped(frame_state.function());
|
||||
+ }
|
||||
+ break;
|
||||
+ }
|
||||
default: {
|
||||
// For unknown nodes, treat all value inputs as escaping.
|
||||
int value_input_count = op->ValueInputCount();
|
||||
37
patches/v8/cherry-pick-e42dbcdedb7a.patch
Normal file
37
patches/v8/cherry-pick-e42dbcdedb7a.patch
Normal file
@@ -0,0 +1,37 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Brendon Tiszka <btiszka@gmail.com>
|
||||
Date: Fri, 18 Mar 2022 01:32:54 -0400
|
||||
Subject: Merged: Update write barrier when storing HeapNumber to last index.
|
||||
|
||||
(cherry picked from commit bdc4f54a50293507d9ef51573bab537883560cc8)
|
||||
|
||||
No-Try: true
|
||||
No-Presubmit: true
|
||||
No-Treechecks: true
|
||||
Bug: chromium:1307610
|
||||
Change-Id: I60aaa0e58e13b705b5eff4b57411a0ad4a2e9b3f
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/3534849
|
||||
Reviewed-by: Jakob Gruber <jgruber@chromium.org>
|
||||
Commit-Queue: Jakob Gruber <jgruber@chromium.org>
|
||||
Cr-Original-Commit-Position: refs/heads/main@{#79538}
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/3565716
|
||||
Reviewed-by: Patrick Thier <pthier@chromium.org>
|
||||
Commit-Queue: Jakob Linke <jgruber@chromium.org>
|
||||
Cr-Commit-Position: refs/branch-heads/10.0@{#18}
|
||||
Cr-Branched-From: 6ea73a738c467dc26abbbe84e27a36aac1c6e119-refs/heads/10.0.139@{#1}
|
||||
Cr-Branched-From: ccc689011280419901e6ee42cae39980c0e96030-refs/heads/main@{#79131}
|
||||
|
||||
diff --git a/src/regexp/regexp-utils.cc b/src/regexp/regexp-utils.cc
|
||||
index dabe5ee4a280eb27a9e3ef3200a712f465f327aa..b26007191d3dbe52b05eb30394520dbce2983b9e 100644
|
||||
--- a/src/regexp/regexp-utils.cc
|
||||
+++ b/src/regexp/regexp-utils.cc
|
||||
@@ -49,7 +49,8 @@ MaybeHandle<Object> RegExpUtils::SetLastIndex(Isolate* isolate,
|
||||
Handle<Object> value_as_object =
|
||||
isolate->factory()->NewNumberFromInt64(value);
|
||||
if (HasInitialRegExpMap(isolate, *recv)) {
|
||||
- JSRegExp::cast(*recv).set_last_index(*value_as_object, SKIP_WRITE_BARRIER);
|
||||
+ JSRegExp::cast(*recv).set_last_index(*value_as_object,
|
||||
+ UPDATE_WRITE_BARRIER);
|
||||
return recv;
|
||||
} else {
|
||||
return Object::SetProperty(
|
||||
92
patches/v8/cherry-pick-f546ac11eec7.patch
Normal file
92
patches/v8/cherry-pick-f546ac11eec7.patch
Normal file
@@ -0,0 +1,92 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: =?UTF-8?q?Marja=20H=C3=B6ltt=C3=A4?= <marja@chromium.org>
|
||||
Date: Thu, 24 Mar 2022 17:30:16 +0100
|
||||
Subject: Turn off super ICs
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
|
||||
M96 merge issues:
|
||||
Conflicts in the bytecode test expectations
|
||||
|
||||
They make assumptions which don't hold for API handlers.
|
||||
|
||||
(cherry picked from commit c6b68cbfbd49a24bd9d343d718132125370da729)
|
||||
|
||||
Bug: v8:9237,chromium:1308360
|
||||
No-Try: true
|
||||
No-Presubmit: true
|
||||
No-Tree-Checks: true
|
||||
Change-Id: I9f122c4e75a24d83ef3653cbf7a223ed522e4d13
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/3548899
|
||||
Commit-Queue: Marja Hölttä <marja@chromium.org>
|
||||
Cr-Original-Commit-Position: refs/heads/main@{#79614}
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/3553109
|
||||
Reviewed-by: Igor Sheludko <ishell@chromium.org>
|
||||
Commit-Queue: Roger Felipe Zanoni da Silva <rzanoni@google.com>
|
||||
Cr-Commit-Position: refs/branch-heads/9.6@{#60}
|
||||
Cr-Branched-From: 0b7bda016178bf438f09b3c93da572ae3663a1f7-refs/heads/9.6.180@{#1}
|
||||
Cr-Branched-From: 41a5a247d9430b953e38631e88d17790306f7a4c-refs/heads/main@{#77244}
|
||||
|
||||
diff --git a/src/flags/flag-definitions.h b/src/flags/flag-definitions.h
|
||||
index 6a8eb146770118d9d0d8ae5efc5a7162a094e26b..9c000959f55e42f388ba4ae75b98a6a80201ed44 100644
|
||||
--- a/src/flags/flag-definitions.h
|
||||
+++ b/src/flags/flag-definitions.h
|
||||
@@ -1659,7 +1659,7 @@ DEFINE_INT(max_valid_polymorphic_map_count, 4,
|
||||
DEFINE_BOOL(native_code_counters, DEBUG_BOOL,
|
||||
"generate extra code for manipulating stats counters")
|
||||
|
||||
-DEFINE_BOOL(super_ic, true, "use an IC for super property loads")
|
||||
+DEFINE_BOOL(super_ic, false, "use an IC for super property loads")
|
||||
|
||||
DEFINE_BOOL(enable_mega_dom_ic, false, "use MegaDOM IC state for API objects")
|
||||
|
||||
diff --git a/test/cctest/interpreter/bytecode_expectations/ClassAndSuperClass.golden b/test/cctest/interpreter/bytecode_expectations/ClassAndSuperClass.golden
|
||||
index 82b6e16be98d8dd9d8fe6b8419653d2c02f7bf79..c433538d8ed52c52277f2ad7163fc4b15c29591c 100644
|
||||
--- a/test/cctest/interpreter/bytecode_expectations/ClassAndSuperClass.golden
|
||||
+++ b/test/cctest/interpreter/bytecode_expectations/ClassAndSuperClass.golden
|
||||
@@ -20,14 +20,18 @@ snippet: "
|
||||
test();
|
||||
})();
|
||||
"
|
||||
-frame size: 1
|
||||
+frame size: 5
|
||||
parameter count: 1
|
||||
-bytecode array length: 16
|
||||
+bytecode array length: 24
|
||||
bytecodes: [
|
||||
/* 104 S> */ B(LdaImmutableCurrentContextSlot), U8(2),
|
||||
- /* 117 E> */ B(LdaNamedPropertyFromSuper), R(this), U8(0), U8(1),
|
||||
+ B(Star3),
|
||||
+ B(LdaConstant), U8(0),
|
||||
+ B(Star4),
|
||||
+ B(Mov), R(this), R(2),
|
||||
+ /* 117 E> */ B(CallRuntime), U16(Runtime::kLoadFromSuper), R(2), U8(3),
|
||||
B(Star0),
|
||||
- /* 117 E> */ B(CallAnyReceiver), R(0), R(this), U8(1), U8(3),
|
||||
+ /* 117 E> */ B(CallAnyReceiver), R(0), R(this), U8(1), U8(1),
|
||||
/* 126 E> */ B(AddSmi), I8(1), U8(0),
|
||||
/* 130 S> */ B(Return),
|
||||
]
|
||||
@@ -54,7 +58,7 @@ snippet: "
|
||||
"
|
||||
frame size: 4
|
||||
parameter count: 1
|
||||
-bytecode array length: 24
|
||||
+bytecode array length: 32
|
||||
bytecodes: [
|
||||
/* 130 S> */ B(LdaImmutableCurrentContextSlot), U8(2),
|
||||
B(Star1),
|
||||
@@ -65,7 +69,11 @@ bytecodes: [
|
||||
B(Mov), R(this), R(0),
|
||||
/* 138 E> */ B(CallRuntime), U16(Runtime::kStoreToSuper), R(0), U8(4),
|
||||
/* 143 S> */ B(LdaImmutableCurrentContextSlot), U8(2),
|
||||
- /* 156 E> */ B(LdaNamedPropertyFromSuper), R(this), U8(0), U8(0),
|
||||
+ B(Star1),
|
||||
+ B(LdaConstant), U8(0),
|
||||
+ B(Star2),
|
||||
+ B(Mov), R(this), R(0),
|
||||
+ /* 156 E> */ B(CallRuntime), U16(Runtime::kLoadFromSuper), R(0), U8(3),
|
||||
/* 158 S> */ B(Return),
|
||||
]
|
||||
constant pool: [
|
||||
@@ -1 +1,3 @@
|
||||
add_thread_local_to_x_error_trap_cc.patch
|
||||
adding_fuzzer_for_pcm16b_decoder_and_fixing_a_fuzzer_problem.patch
|
||||
cherry-pick-a18fddcb53e6.patch
|
||||
|
||||
@@ -0,0 +1,111 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Henrik Lundin <henrik.lundin@webrtc.org>
|
||||
Date: Tue, 15 Feb 2022 15:13:34 +0000
|
||||
Subject: Adding fuzzer for PCM16b decoder and fixing a fuzzer problem
|
||||
|
||||
Bug: chromium:1280852
|
||||
Change-Id: I7f6c5de86ceee01156743c0389c59f875e53bb5f
|
||||
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/251580
|
||||
Reviewed-by: Minyue Li <minyue@webrtc.org>
|
||||
Commit-Queue: Henrik Lundin <henrik.lundin@webrtc.org>
|
||||
Cr-Commit-Position: refs/heads/main@{#36005}
|
||||
|
||||
diff --git a/modules/audio_coding/codecs/pcm16b/audio_decoder_pcm16b.cc b/modules/audio_coding/codecs/pcm16b/audio_decoder_pcm16b.cc
|
||||
index 1dd2ff289ee10280963c3db5de58545886c60d49..7761efe8b3b2d1627021e9f19dfb25ca871be049 100644
|
||||
--- a/modules/audio_coding/codecs/pcm16b/audio_decoder_pcm16b.cc
|
||||
+++ b/modules/audio_coding/codecs/pcm16b/audio_decoder_pcm16b.cc
|
||||
@@ -42,7 +42,12 @@ int AudioDecoderPcm16B::DecodeInternal(const uint8_t* encoded,
|
||||
int16_t* decoded,
|
||||
SpeechType* speech_type) {
|
||||
RTC_DCHECK_EQ(sample_rate_hz_, sample_rate_hz);
|
||||
- size_t ret = WebRtcPcm16b_Decode(encoded, encoded_len, decoded);
|
||||
+ // Adjust the encoded length down to ensure the same number of samples in each
|
||||
+ // channel.
|
||||
+ const size_t encoded_len_adjusted =
|
||||
+ PacketDuration(encoded, encoded_len) * 2 *
|
||||
+ Channels(); // 2 bytes per sample per channel
|
||||
+ size_t ret = WebRtcPcm16b_Decode(encoded, encoded_len_adjusted, decoded);
|
||||
*speech_type = ConvertSpeechType(1);
|
||||
return static_cast<int>(ret);
|
||||
}
|
||||
diff --git a/test/fuzzers/BUILD.gn b/test/fuzzers/BUILD.gn
|
||||
index 2e94f40fa2f9deefc867428e1a80aaec3a2d822b..e32da276c91ea67e02eeadf826947e2903090c61 100644
|
||||
--- a/test/fuzzers/BUILD.gn
|
||||
+++ b/test/fuzzers/BUILD.gn
|
||||
@@ -308,6 +308,14 @@ webrtc_fuzzer_test("audio_decoder_multiopus_fuzzer") {
|
||||
]
|
||||
}
|
||||
|
||||
+webrtc_fuzzer_test("audio_decoder_pcm16b_fuzzer") {
|
||||
+ sources = [ "audio_decoder_pcm16b_fuzzer.cc" ]
|
||||
+ deps = [
|
||||
+ ":audio_decoder_fuzzer",
|
||||
+ "../../modules/audio_coding:pcm16b",
|
||||
+ ]
|
||||
+}
|
||||
+
|
||||
rtc_library("audio_encoder_fuzzer") {
|
||||
testonly = true
|
||||
sources = [
|
||||
diff --git a/test/fuzzers/audio_decoder_pcm16b_fuzzer.cc b/test/fuzzers/audio_decoder_pcm16b_fuzzer.cc
|
||||
new file mode 100644
|
||||
index 0000000000000000000000000000000000000000..6e5d6e2190638185578ac71b400913f46f6b67cf
|
||||
--- /dev/null
|
||||
+++ b/test/fuzzers/audio_decoder_pcm16b_fuzzer.cc
|
||||
@@ -0,0 +1,56 @@
|
||||
+/*
|
||||
+ * Copyright (c) 2022 The WebRTC project authors. All Rights Reserved.
|
||||
+ *
|
||||
+ * Use of this source code is governed by a BSD-style license
|
||||
+ * that can be found in the LICENSE file in the root of the source
|
||||
+ * tree. An additional intellectual property rights grant can be found
|
||||
+ * in the file PATENTS. All contributing project authors may
|
||||
+ * be found in the AUTHORS file in the root of the source tree.
|
||||
+ */
|
||||
+
|
||||
+#include <memory>
|
||||
+
|
||||
+#include "modules/audio_coding/codecs/pcm16b/audio_decoder_pcm16b.h"
|
||||
+#include "test/fuzzers/audio_decoder_fuzzer.h"
|
||||
+
|
||||
+namespace webrtc {
|
||||
+void FuzzOneInput(const uint8_t* data, size_t size) {
|
||||
+ if (size > 10000 || size < 2) {
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
+ int sample_rate_hz;
|
||||
+ switch (data[0] % 4) {
|
||||
+ case 0:
|
||||
+ sample_rate_hz = 8000;
|
||||
+ break;
|
||||
+ case 1:
|
||||
+ sample_rate_hz = 16000;
|
||||
+ break;
|
||||
+ case 2:
|
||||
+ sample_rate_hz = 32000;
|
||||
+ break;
|
||||
+ case 3:
|
||||
+ sample_rate_hz = 48000;
|
||||
+ break;
|
||||
+ default:
|
||||
+ RTC_DCHECK_NOTREACHED();
|
||||
+ return;
|
||||
+ }
|
||||
+ const size_t num_channels = data[1] % 16 + 1;
|
||||
+
|
||||
+ // Two first bytes of the data are used. Move forward.
|
||||
+ data += 2;
|
||||
+ size -= 2;
|
||||
+
|
||||
+ AudioDecoderPcm16B dec(sample_rate_hz, num_channels);
|
||||
+ // Allocate a maximum output size of 100 ms.
|
||||
+ const size_t allocated_ouput_size_samples =
|
||||
+ sample_rate_hz * num_channels / 10;
|
||||
+ std::unique_ptr<int16_t[]> output =
|
||||
+ std::make_unique<int16_t[]>(allocated_ouput_size_samples);
|
||||
+ FuzzAudioDecoder(
|
||||
+ DecoderFunctionType::kNormalDecode, data, size, &dec, sample_rate_hz,
|
||||
+ allocated_ouput_size_samples * sizeof(int16_t), output.get());
|
||||
+}
|
||||
+} // namespace webrtc
|
||||
48
patches/webrtc/cherry-pick-a18fddcb53e6.patch
Normal file
48
patches/webrtc/cherry-pick-a18fddcb53e6.patch
Normal file
@@ -0,0 +1,48 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Tony Herre <herre@google.com>
|
||||
Date: Fri, 25 Mar 2022 09:33:14 +0100
|
||||
Subject: Filter out Mac StatusIndicator window from desktop capture list
|
||||
|
||||
Since 12.2, the orange/red indicator at the top right of the screen shows up as a window in the Chrome getDisplayMedia() picker, as it's not filtered out by the existing filters. Screenshots in the bug.
|
||||
|
||||
Bug: chromium:1297731, b/218211225
|
||||
Change-Id: I0f87e8d2af42a5a2e3d84f69fe73596e9cf35622
|
||||
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/251841
|
||||
Reviewed-by: Alexander Cooper <alcooper@chromium.org>
|
||||
Commit-Queue: Tony Herre <herre@google.com>
|
||||
Cr-Commit-Position: refs/heads/main@{#36350}
|
||||
|
||||
diff --git a/modules/desktop_capture/mac/window_list_utils.cc b/modules/desktop_capture/mac/window_list_utils.cc
|
||||
index d2fb20ed4ca0689fd6f51ee994308e876680ab1e..5d881662ea2f2d86d2c33bf20f79d31ef4e7a481 100644
|
||||
--- a/modules/desktop_capture/mac/window_list_utils.cc
|
||||
+++ b/modules/desktop_capture/mac/window_list_utils.cc
|
||||
@@ -31,6 +31,11 @@ namespace webrtc {
|
||||
|
||||
namespace {
|
||||
|
||||
+// WindowName of the status indicator dot shown since Monterey in the taskbar.
|
||||
+// Testing on 12.2.1 shows this is independent of system language setting.
|
||||
+const CFStringRef kStatusIndicator = CFSTR("StatusIndicator");
|
||||
+const CFStringRef kStatusIndicatorOwnerName = CFSTR("Window Server");
|
||||
+
|
||||
bool ToUtf8(const CFStringRef str16, std::string* str8) {
|
||||
size_t maxlen = CFStringGetMaximumSizeForEncoding(CFStringGetLength(str16),
|
||||
kCFStringEncodingUTF8) +
|
||||
@@ -145,6 +150,17 @@ bool GetWindowList(rtc::FunctionView<bool(CFDictionaryRef)> on_window,
|
||||
continue;
|
||||
}
|
||||
|
||||
+ CFStringRef window_owner_name = reinterpret_cast<CFStringRef>(
|
||||
+ CFDictionaryGetValue(window, kCGWindowOwnerName));
|
||||
+ // Ignore the red dot status indicator shown in the stats bar. Unlike the
|
||||
+ // rest of the system UI it has a window_layer of 0, so was otherwise
|
||||
+ // included. See crbug.com/1297731.
|
||||
+ if (window_title && CFEqual(window_title, kStatusIndicator) &&
|
||||
+ window_owner_name &&
|
||||
+ CFEqual(window_owner_name, kStatusIndicatorOwnerName)) {
|
||||
+ continue;
|
||||
+ }
|
||||
+
|
||||
if (!on_window(window)) {
|
||||
break;
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
#!/usr/bin/env python
|
||||
#!/usr/bin/env python3
|
||||
from __future__ import print_function
|
||||
import argparse
|
||||
import os
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
#!/usr/bin/env python
|
||||
#!/usr/bin/env python3
|
||||
|
||||
import argparse
|
||||
import json
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
#!/usr/bin/env python
|
||||
#!/usr/bin/env python3
|
||||
|
||||
from __future__ import print_function
|
||||
import os
|
||||
@@ -41,7 +41,7 @@ def getBrokenLinks(filepath):
|
||||
brokenLinks = []
|
||||
|
||||
try:
|
||||
f = open(filepath, 'r')
|
||||
f = open(filepath, 'r', encoding="utf-8")
|
||||
lines = f.readlines()
|
||||
except KeyboardInterrupt:
|
||||
print('Keyboard interruption while parsing. Please try again.')
|
||||
@@ -77,7 +77,7 @@ def getBrokenLinks(filepath):
|
||||
tempFile = os.path.join(currentDir, sections[0])
|
||||
if os.path.isfile(tempFile):
|
||||
try:
|
||||
newFile = open(tempFile, 'r')
|
||||
newFile = open(tempFile, 'r', encoding="utf-8")
|
||||
newLines = newFile.readlines()
|
||||
except KeyboardInterrupt:
|
||||
print('Keyboard interruption while parsing. Please try again.')
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
#!/usr/bin/env python
|
||||
#!/usr/bin/env python3
|
||||
from __future__ import print_function
|
||||
import argparse
|
||||
import os
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
#!/usr/bin/env python
|
||||
#!/usr/bin/env python3
|
||||
|
||||
import os
|
||||
import subprocess
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
#!/usr/bin/env python
|
||||
#!/usr/bin/env python3
|
||||
|
||||
import argparse
|
||||
import json
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
#!/usr/bin/env python
|
||||
#!/usr/bin/env python3
|
||||
|
||||
from __future__ import print_function
|
||||
import ast
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
#!/usr/bin/env python
|
||||
#!/usr/bin/env python3
|
||||
|
||||
import zipfile
|
||||
import sys
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
#!/usr/bin/env python
|
||||
#!/usr/bin/env python3
|
||||
|
||||
import argparse
|
||||
import sys
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
#!/usr/bin/env python
|
||||
#!/usr/bin/env python3
|
||||
|
||||
import argparse
|
||||
import sys
|
||||
|
||||
43
script/lib/azput.js
Normal file
43
script/lib/azput.js
Normal file
@@ -0,0 +1,43 @@
|
||||
/* eslint-disable camelcase */
|
||||
const { BlobServiceClient } = require('@azure/storage-blob');
|
||||
const fs = require('fs');
|
||||
const path = require('path');
|
||||
|
||||
const blobServiceClient = BlobServiceClient.fromConnectionString(process.env.ELECTRON_ARTIFACTS_BLOB_STORAGE);
|
||||
|
||||
const args = require('minimist')(process.argv.slice(2));
|
||||
|
||||
let { prefix = '/', key_prefix = '', _: files } = args;
|
||||
if (prefix && !prefix.endsWith(path.sep)) prefix = path.resolve(prefix) + path.sep;
|
||||
|
||||
function filenameToKey (file) {
|
||||
file = path.resolve(file);
|
||||
if (file.startsWith(prefix)) file = file.substr(prefix.length - 1);
|
||||
return key_prefix + (path.sep === '\\' ? file.replace(/\\/g, '/') : file);
|
||||
}
|
||||
|
||||
let anErrorOccurred = false;
|
||||
function next (done) {
|
||||
const file = files.shift();
|
||||
if (!file) return done();
|
||||
const key = filenameToKey(file);
|
||||
|
||||
const [containerName, ...keyPath] = key.split('/');
|
||||
const blobKey = keyPath.join('/');
|
||||
console.log(`Uploading '${file}' to container '${containerName}' with key '${blobKey}'...`);
|
||||
|
||||
const containerClient = blobServiceClient.getContainerClient(containerName);
|
||||
const blockBlobClient = containerClient.getBlockBlobClient(blobKey);
|
||||
blockBlobClient.uploadFile(file)
|
||||
.then((uploadBlobResponse) => {
|
||||
console.log(`Upload block blob ${blobKey} successfully: https://artifacts.electronjs.org/${key}`, uploadBlobResponse.requestId);
|
||||
})
|
||||
.catch((err) => {
|
||||
console.error(err);
|
||||
anErrorOccurred = true;
|
||||
})
|
||||
.then(() => next(done));
|
||||
}
|
||||
next(() => {
|
||||
process.exit(anErrorOccurred ? 1 : 0);
|
||||
});
|
||||
@@ -1,4 +1,4 @@
|
||||
#!/usr/bin/env python
|
||||
#!/usr/bin/env python3
|
||||
|
||||
from __future__ import print_function
|
||||
import os
|
||||
@@ -53,17 +53,6 @@ def get_env_var(name):
|
||||
return value
|
||||
|
||||
|
||||
def s3_config():
|
||||
config = (get_env_var('S3_BUCKET'),
|
||||
get_env_var('S3_ACCESS_KEY'),
|
||||
get_env_var('S3_SECRET_KEY'))
|
||||
message = ('Error: Please set the $ELECTRON_S3_BUCKET, '
|
||||
'$ELECTRON_S3_ACCESS_KEY, and '
|
||||
'$ELECTRON_S3_SECRET_KEY environment variables')
|
||||
assert all(len(c) for c in config), message
|
||||
return config
|
||||
|
||||
|
||||
def enable_verbose_mode():
|
||||
print('Running in verbose mode')
|
||||
global verbose_mode
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
#!/usr/bin/env python
|
||||
#!/usr/bin/env python3
|
||||
|
||||
"""Git helper functions.
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
#!/usr/bin/env python
|
||||
#!/usr/bin/env python3
|
||||
|
||||
import codecs
|
||||
import os
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user