mirror of
https://github.com/electron/electron.git
synced 2026-02-19 03:14:51 -05:00
Compare commits
180 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
0f05991c3e | ||
|
|
6bdab4a353 | ||
|
|
6e5f02426a | ||
|
|
30da5dee2a | ||
|
|
bd9c7c41ba | ||
|
|
76f4ced8d4 | ||
|
|
cac38cb6ea | ||
|
|
e8f89da1c4 | ||
|
|
a0f73938cd | ||
|
|
1bf71fa81f | ||
|
|
0de8079b33 | ||
|
|
52fd3da443 | ||
|
|
742aab764e | ||
|
|
1f669c3cc5 | ||
|
|
d26d064082 | ||
|
|
a31e722d43 | ||
|
|
81b923c8f5 | ||
|
|
b745364907 | ||
|
|
91cf2e2163 | ||
|
|
53af38ad54 | ||
|
|
2fef020e06 | ||
|
|
b60dfe4117 | ||
|
|
7e123ac6e5 | ||
|
|
a29136950e | ||
|
|
458a843174 | ||
|
|
e11e12d5b3 | ||
|
|
25ed65150d | ||
|
|
8737aa046d | ||
|
|
0d94bdda50 | ||
|
|
2c3081afb8 | ||
|
|
f583acff46 | ||
|
|
271e98c059 | ||
|
|
8279c02e9a | ||
|
|
ef4cbe86af | ||
|
|
300a40f939 | ||
|
|
79b45ac5f6 | ||
|
|
e5e8dd5156 | ||
|
|
4e75499270 | ||
|
|
1bc5b6177f | ||
|
|
5647382a55 | ||
|
|
fd272d89bc | ||
|
|
d745647c54 | ||
|
|
9038bdd7bc | ||
|
|
bbc862c878 | ||
|
|
ff57df1ecb | ||
|
|
37dfd8be4a | ||
|
|
f043e665dd | ||
|
|
798f151e05 | ||
|
|
a9a3910aa0 | ||
|
|
2f28e10543 | ||
|
|
f1021b93d0 | ||
|
|
6788561bb3 | ||
|
|
35d3f35a44 | ||
|
|
f949a1aafd | ||
|
|
b8e22532b0 | ||
|
|
c2758554ed | ||
|
|
05cb4240bd | ||
|
|
c84b152164 | ||
|
|
20f8c10977 | ||
|
|
38be2dfb25 | ||
|
|
0c371e53a4 | ||
|
|
8e517202ea | ||
|
|
3410147699 | ||
|
|
ce5157236c | ||
|
|
8ec2469379 | ||
|
|
ddf348d609 | ||
|
|
f757a17821 | ||
|
|
8519ba881e | ||
|
|
bd31023314 | ||
|
|
fb0eb6c0ca | ||
|
|
390349e3db | ||
|
|
f6e6873971 | ||
|
|
ecd6918166 | ||
|
|
d54f1d58f7 | ||
|
|
5d5b2bf8e5 | ||
|
|
fa37e1533f | ||
|
|
f9cf232597 | ||
|
|
615c15c914 | ||
|
|
4550baa7a5 | ||
|
|
7469c72d80 | ||
|
|
bedb5e1055 | ||
|
|
6815c823b3 | ||
|
|
78c5a2cf4b | ||
|
|
3c3d279182 | ||
|
|
1c7a612931 | ||
|
|
4615dcbbfd | ||
|
|
3bbe839403 | ||
|
|
0f5967fce2 | ||
|
|
da171befe7 | ||
|
|
c850e2452c | ||
|
|
f3ca6ff998 | ||
|
|
58e9dedd76 | ||
|
|
51a673e7e0 | ||
|
|
fed01fb57d | ||
|
|
65c9f47e15 | ||
|
|
1b54c4bc44 | ||
|
|
f903141394 | ||
|
|
6c1f9f8270 | ||
|
|
7432ea43b7 | ||
|
|
0d1b7be451 | ||
|
|
e0a7f869de | ||
|
|
d9dd6138e2 | ||
|
|
c1651e333b | ||
|
|
c0ea40e71d | ||
|
|
501bb98a10 | ||
|
|
9fe9a0ccc1 | ||
|
|
f6d2b9dc63 | ||
|
|
b04be1dff6 | ||
|
|
656463c2f4 | ||
|
|
a0e9cc6c02 | ||
|
|
27e2c79dd0 | ||
|
|
d74441f00e | ||
|
|
97e52764a8 | ||
|
|
112392c414 | ||
|
|
42c2eecdef | ||
|
|
98603c645e | ||
|
|
11391e7351 | ||
|
|
a636ab7c61 | ||
|
|
53e39eb9c0 | ||
|
|
cccd74e6a6 | ||
|
|
1efa631b56 | ||
|
|
221d2220e1 | ||
|
|
ae3ee8ad00 | ||
|
|
b39a34650f | ||
|
|
8292b3dc0c | ||
|
|
8653dfc8b3 | ||
|
|
1ef9a756e5 | ||
|
|
fdfa5d41d4 | ||
|
|
86e10b06dd | ||
|
|
d2497a14e0 | ||
|
|
5963024ac7 | ||
|
|
26690b12f2 | ||
|
|
1a148a8232 | ||
|
|
cff70f15aa | ||
|
|
a6f094c983 | ||
|
|
04dcbe4c74 | ||
|
|
28def9ed7d | ||
|
|
2089370bbb | ||
|
|
837dc05204 | ||
|
|
9f08e46018 | ||
|
|
6a70d8a6ca | ||
|
|
aab276c532 | ||
|
|
053fea1b44 | ||
|
|
0b0e991a54 | ||
|
|
ec7408a2d4 | ||
|
|
250b7ed3db | ||
|
|
d136430b35 | ||
|
|
79abfe7ac8 | ||
|
|
a18a4609ad | ||
|
|
cdf661939d | ||
|
|
98cf0e5dff | ||
|
|
be9dccfcc6 | ||
|
|
e4bb98195f | ||
|
|
099560c59c | ||
|
|
efd276d31f | ||
|
|
e2cb43768d | ||
|
|
e654f5ecb3 | ||
|
|
f74940b536 | ||
|
|
fe8508a287 | ||
|
|
d5dd50f87e | ||
|
|
952994c591 | ||
|
|
536b5c4e3b | ||
|
|
210bae878f | ||
|
|
9b78227260 | ||
|
|
0a50571460 | ||
|
|
248a6012d5 | ||
|
|
ed52801e09 | ||
|
|
6226507536 | ||
|
|
098a118dce | ||
|
|
56e08fe5f1 | ||
|
|
8dba1cf5fa | ||
|
|
1fc7634f69 | ||
|
|
52e443ec52 | ||
|
|
16be926e0a | ||
|
|
5c2d65c749 | ||
|
|
7bf1d3c110 | ||
|
|
92969d6032 | ||
|
|
b48d0f2cbe | ||
|
|
ff8594b11b | ||
|
|
a41f04028e |
1
.circleci/.gitignore
vendored
Normal file
1
.circleci/.gitignore
vendored
Normal file
@@ -0,0 +1 @@
|
||||
config-staging
|
||||
2601
.circleci/config.yml
2601
.circleci/config.yml
File diff suppressed because it is too large
Load Diff
2457
.circleci/config/base.yml
Normal file
2457
.circleci/config/base.yml
Normal file
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==
|
||||
2
.github/CODEOWNERS
vendored
2
.github/CODEOWNERS
vendored
@@ -4,7 +4,7 @@
|
||||
# https://git-scm.com/docs/gitignore
|
||||
|
||||
# Upgrades WG
|
||||
/patches/ @electron/wg-upgrades
|
||||
/patches/ @electron/wg-upgrades @electron/wg-security
|
||||
DEPS @electron/wg-upgrades
|
||||
|
||||
# Releases WG
|
||||
|
||||
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
|
||||
7
BUILD.gn
7
BUILD.gn
@@ -1367,11 +1367,13 @@ dist_zip("electron_dist_zip") {
|
||||
if (is_linux) {
|
||||
data_deps += [ "//sandbox/linux:chrome_sandbox" ]
|
||||
}
|
||||
deps = data_deps
|
||||
outputs = [ "$root_build_dir/dist.zip" ]
|
||||
}
|
||||
|
||||
dist_zip("electron_ffmpeg_zip") {
|
||||
data_deps = [ "//third_party/ffmpeg" ]
|
||||
deps = data_deps
|
||||
outputs = [ "$root_build_dir/ffmpeg.zip" ]
|
||||
}
|
||||
|
||||
@@ -1389,6 +1391,7 @@ group("electron_chromedriver") {
|
||||
dist_zip("electron_chromedriver_zip") {
|
||||
testonly = true
|
||||
data_deps = electron_chromedriver_deps
|
||||
deps = data_deps
|
||||
outputs = [ "$root_build_dir/chromedriver.zip" ]
|
||||
}
|
||||
|
||||
@@ -1407,6 +1410,7 @@ group("electron_mksnapshot") {
|
||||
|
||||
dist_zip("electron_mksnapshot_zip") {
|
||||
data_deps = mksnapshot_deps
|
||||
deps = data_deps
|
||||
outputs = [ "$root_build_dir/mksnapshot.zip" ]
|
||||
}
|
||||
|
||||
@@ -1417,6 +1421,7 @@ copy("hunspell_dictionaries") {
|
||||
|
||||
dist_zip("hunspell_dictionaries_zip") {
|
||||
data_deps = [ ":hunspell_dictionaries" ]
|
||||
deps = data_deps
|
||||
flatten = true
|
||||
|
||||
outputs = [ "$root_build_dir/hunspell_dictionaries.zip" ]
|
||||
@@ -1430,6 +1435,7 @@ copy("libcxx_headers") {
|
||||
|
||||
dist_zip("libcxx_headers_zip") {
|
||||
data_deps = [ ":libcxx_headers" ]
|
||||
deps = data_deps
|
||||
flatten = true
|
||||
flatten_relative_to = rebase_path(
|
||||
"$target_gen_dir/electron_libcxx_include/buildtools/third_party/libc++/trunk",
|
||||
@@ -1445,6 +1451,7 @@ copy("libcxxabi_headers") {
|
||||
|
||||
dist_zip("libcxxabi_headers_zip") {
|
||||
data_deps = [ ":libcxxabi_headers" ]
|
||||
deps = data_deps
|
||||
flatten = true
|
||||
flatten_relative_to = rebase_path(
|
||||
"$target_gen_dir/electron_libcxxabi_include/buildtools/third_party/libc++abi/trunk",
|
||||
|
||||
@@ -1 +1 @@
|
||||
15.3.2
|
||||
15.5.3
|
||||
40
appveyor.yml
40
appveyor.yml
@@ -66,6 +66,31 @@ build_script:
|
||||
- mkdir src
|
||||
- update_depot_tools.bat
|
||||
- ps: Move-Item $env:APPVEYOR_BUILD_FOLDER -Destination src\electron
|
||||
- ps: >-
|
||||
if (Test-Path 'env:RAW_GOMA_AUTH') {
|
||||
$env:GOMA_OAUTH2_CONFIG_FILE = "$pwd\.goma_oauth2_config"
|
||||
$env:RAW_GOMA_AUTH | Set-Content $env:GOMA_OAUTH2_CONFIG_FILE
|
||||
}
|
||||
- git clone https://github.com/electron/build-tools.git
|
||||
- cd build-tools
|
||||
- npm install
|
||||
- mkdir third_party
|
||||
- ps: >-
|
||||
node -e "require('./src/utils/goma.js').downloadAndPrepare({ gomaOneForAll: true })"
|
||||
- ps: $env:GN_GOMA_FILE = node -e "console.log(require('./src/utils/goma.js').gnFilePath)"
|
||||
- ps: $env:LOCAL_GOMA_DIR = node -e "console.log(require('./src/utils/goma.js').dir)"
|
||||
- cd ..
|
||||
- ps: .\src\electron\script\start-goma.ps1 -gomaDir $env:LOCAL_GOMA_DIR
|
||||
- ps: >-
|
||||
if (Test-Path 'env:RAW_GOMA_AUTH') {
|
||||
$goma_login = python $env:LOCAL_GOMA_DIR\goma_auth.py info
|
||||
if ($goma_login -eq 'Login as Fermi Planck') {
|
||||
Write-warning "Goma authentication is correct";
|
||||
} else {
|
||||
Write-warning "WARNING!!!!!! Goma authentication is incorrect; please update Goma auth token.";
|
||||
$host.SetShouldExit(1)
|
||||
}
|
||||
}
|
||||
- ps: $env:CHROMIUM_BUILDTOOLS_PATH="$pwd\src\buildtools"
|
||||
- ps: >-
|
||||
if ($env:GN_CONFIG -ne 'release') {
|
||||
@@ -129,21 +154,6 @@ build_script:
|
||||
Write-warning "Failed to add third_party\angle\.git; continuing anyway"
|
||||
}
|
||||
}
|
||||
- ps: >-
|
||||
if (Test-Path 'env:RAW_GOMA_AUTH') {
|
||||
$env:GOMA_OAUTH2_CONFIG_FILE = "$pwd\.goma_oauth2_config"
|
||||
$env:RAW_GOMA_AUTH | Set-Content $env:GOMA_OAUTH2_CONFIG_FILE
|
||||
}
|
||||
- git clone https://github.com/electron/build-tools.git
|
||||
- cd build-tools
|
||||
- npm install
|
||||
- mkdir third_party
|
||||
- ps: >-
|
||||
node -e "require('./src/utils/goma.js').downloadAndPrepare({ gomaOneForAll: true })"
|
||||
- ps: $env:GN_GOMA_FILE = node -e "console.log(require('./src/utils/goma.js').gnFilePath)"
|
||||
- ps: $env:LOCAL_GOMA_DIR = node -e "console.log(require('./src/utils/goma.js').dir)"
|
||||
- cd ..
|
||||
- ps: .\src\electron\script\start-goma.ps1 -gomaDir $env:LOCAL_GOMA_DIR
|
||||
- cd src
|
||||
- set BUILD_CONFIG_PATH=//electron/build/args/%GN_CONFIG%.gn
|
||||
- gn gen out/Default "--args=import(\"%BUILD_CONFIG_PATH%\") import(\"%GN_GOMA_FILE%\") %GN_EXTRA_ARGS% "
|
||||
|
||||
@@ -1,9 +1,12 @@
|
||||
from __future__ import with_statement
|
||||
from __future__ import unicode_literals
|
||||
|
||||
import contextlib
|
||||
import sys
|
||||
import os
|
||||
import optparse
|
||||
import json
|
||||
import re
|
||||
import subprocess
|
||||
|
||||
sys.path.append("%s/../../build" % os.path.dirname(os.path.realpath(__file__)))
|
||||
|
||||
@@ -33,36 +36,56 @@ def calculate_hash(root):
|
||||
return CalculateHash('.', None)
|
||||
|
||||
def windows_installed_software():
|
||||
import win32com.client
|
||||
strComputer = "."
|
||||
objWMIService = win32com.client.Dispatch("WbemScripting.SWbemLocator")
|
||||
objSWbemServices = objWMIService.ConnectServer(strComputer, "root\cimv2")
|
||||
colItems = objSWbemServices.ExecQuery("Select * from Win32_Product")
|
||||
items = []
|
||||
powershell_command = [
|
||||
"Get-CimInstance",
|
||||
"-Namespace",
|
||||
"root\cimv2",
|
||||
"-Class",
|
||||
"Win32_product",
|
||||
"|",
|
||||
"Select",
|
||||
"vendor,",
|
||||
"description,",
|
||||
"@{l='install_location';e='InstallLocation'},",
|
||||
"@{l='install_date';e='InstallDate'},",
|
||||
"@{l='install_date_2';e='InstallDate2'},",
|
||||
"caption,",
|
||||
"version,",
|
||||
"name,",
|
||||
"@{l='sku_number';e='SKUNumber'}",
|
||||
"|",
|
||||
"ConvertTo-Json",
|
||||
]
|
||||
|
||||
for objItem in colItems:
|
||||
item = {}
|
||||
if objItem.Caption:
|
||||
item['caption'] = objItem.Caption
|
||||
if objItem.Caption:
|
||||
item['description'] = objItem.Description
|
||||
if objItem.InstallDate:
|
||||
item['install_date'] = objItem.InstallDate
|
||||
if objItem.InstallDate2:
|
||||
item['install_date_2'] = objItem.InstallDate2
|
||||
if objItem.InstallLocation:
|
||||
item['install_location'] = objItem.InstallLocation
|
||||
if objItem.Name:
|
||||
item['name'] = objItem.Name
|
||||
if objItem.SKUNumber:
|
||||
item['sku_number'] = objItem.SKUNumber
|
||||
if objItem.Vendor:
|
||||
item['vendor'] = objItem.Vendor
|
||||
if objItem.Version:
|
||||
item['version'] = objItem.Version
|
||||
items.append(item)
|
||||
proc = subprocess.Popen(
|
||||
["powershell.exe", "-Command", "-"],
|
||||
stdin=subprocess.PIPE,
|
||||
stdout=subprocess.PIPE,
|
||||
)
|
||||
|
||||
return items
|
||||
stdout, _ = proc.communicate(" ".join(powershell_command).encode("utf-8"))
|
||||
|
||||
if proc.returncode != 0:
|
||||
raise RuntimeError("Failed to get list of installed software")
|
||||
|
||||
# On AppVeyor there's other output related to PSReadline,
|
||||
# so grab only the JSON output and ignore everything else
|
||||
json_match = re.match(
|
||||
r".*(\[.*{.*}.*\]).*", stdout.decode("utf-8"), re.DOTALL
|
||||
)
|
||||
|
||||
if not json_match:
|
||||
raise RuntimeError(
|
||||
"Couldn't find JSON output for list of installed software"
|
||||
)
|
||||
|
||||
# Filter out missing keys
|
||||
return list(
|
||||
map(
|
||||
lambda info: {k: info[k] for k in info if info[k]},
|
||||
json.loads(json_match.group(1)),
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
def windows_profile():
|
||||
@@ -89,7 +112,7 @@ def windows_profile():
|
||||
|
||||
def main(options):
|
||||
if sys.platform == 'win32':
|
||||
with open(options.output_json, 'wb') as f:
|
||||
with open(options.output_json, 'w') as f:
|
||||
json.dump(windows_profile(), f)
|
||||
else:
|
||||
raise OSError("Unsupported OS")
|
||||
|
||||
@@ -394,6 +394,7 @@ It creates a new `BrowserWindow` with native properties as set by the `options`.
|
||||
* `titleBarOverlay` Object | Boolean (optional) - When using a frameless window in conjuction with `win.setWindowButtonVisibility(true)` on macOS or using a `titleBarStyle` so that the standard window controls ("traffic lights" on macOS) are visible, this property enables the Window Controls Overlay [JavaScript APIs][overlay-javascript-apis] and [CSS Environment Variables][overlay-css-env-vars]. Specifying `true` will result in an overlay with default system colors. Default is `false`.
|
||||
* `color` String (optional) _Windows_ - The CSS color of the Window Controls Overlay when enabled. Default is the system color.
|
||||
* `symbolColor` String (optional) _Windows_ - The CSS color of the symbols on the Window Controls Overlay when enabled. Default is the system color.
|
||||
* `height` Integer (optional) _macOS_ _Windows_ - The height of the title bar and Window Controls Overlay in pixels. Default is system height.
|
||||
|
||||
When setting minimum or maximum window size with `minWidth`/`maxWidth`/
|
||||
`minHeight`/`maxHeight`, it only constrains the users. It won't prevent you from
|
||||
@@ -999,7 +1000,7 @@ APIs like `win.setSize`.
|
||||
is `true`). Default is `#FFF` (white).
|
||||
|
||||
Sets the background color of the window. See [Setting
|
||||
`backgroundColor`](#setting-backgroundcolor).
|
||||
`backgroundColor`](#setting-the-backgroundcolor-property).
|
||||
|
||||
#### `win.previewFile(path[, displayName])` _macOS_
|
||||
|
||||
@@ -1044,7 +1045,7 @@ Returns [`Rectangle`](structures/rectangle.md) - The `bounds` of the window as `
|
||||
#### `win.getBackgroundColor()`
|
||||
|
||||
Returns `String` - Gets the background color of the window. See [Setting
|
||||
`backgroundColor`](#setting-backgroundcolor).
|
||||
`backgroundColor`](#setting-the-backgroundcolor-property).
|
||||
|
||||
#### `win.setContentBounds(bounds[, animate])`
|
||||
|
||||
|
||||
@@ -76,7 +76,7 @@ Writes `markup` to the clipboard.
|
||||
```js
|
||||
const { clipboard } = require('electron')
|
||||
|
||||
clipboard.writeHTML('<b>Hi</b')
|
||||
clipboard.writeHTML('<b>Hi</b>')
|
||||
```
|
||||
|
||||
### `clipboard.readImage([type])`
|
||||
|
||||
@@ -102,8 +102,8 @@ has been included below for completeness:
|
||||
| `Boolean` | Simple | ✅ | ✅ | N/A |
|
||||
| `Object` | Complex | ✅ | ✅ | Keys must be supported using only "Simple" types in this table. Values must be supported in this table. Prototype modifications are dropped. Sending custom classes will copy values but not the prototype. |
|
||||
| `Array` | Complex | ✅ | ✅ | Same limitations as the `Object` type |
|
||||
| `Error` | Complex | ✅ | ✅ | Errors that are thrown are also copied, this can result in the message and stack trace of the error changing slightly due to being thrown in a different context |
|
||||
| `Promise` | Complex | ✅ | ✅ | Promises are only proxied if they are the return value or exact parameter. Promises nested in arrays or objects will be dropped. |
|
||||
| `Error` | Complex | ✅ | ✅ | Errors that are thrown are also copied, this can result in the message and stack trace of the error changing slightly due to being thrown in a different context, and any custom properties on the Error object [will be lost](https://github.com/electron/electron/issues/25596) |
|
||||
| `Promise` | Complex | ✅ | ✅ | N/A
|
||||
| `Function` | Complex | ✅ | ✅ | Prototype modifications are dropped. Sending classes or constructors will not work. |
|
||||
| [Cloneable Types](https://developer.mozilla.org/en-US/docs/Web/API/Web_Workers_API/Structured_clone_algorithm) | Simple | ✅ | ✅ | See the linked document on cloneable types |
|
||||
| `Element` | Complex | ✅ | ✅ | Prototype modifications are dropped. Sending custom elements will not work. |
|
||||
|
||||
@@ -122,7 +122,7 @@ Prints Chromium's internal logging to the console.
|
||||
|
||||
Setting this variable is the same as passing `--enable-logging`
|
||||
on the command line. For more info, see `--enable-logging` in [command-line
|
||||
switches](./command-line-switches.md#enable-loggingfile).
|
||||
switches](./command-line-switches.md#--enable-loggingfile).
|
||||
|
||||
### `ELECTRON_LOG_FILE`
|
||||
|
||||
@@ -130,7 +130,7 @@ Sets the file destination for Chromium's internal logging.
|
||||
|
||||
Setting this variable is the same as passing `--log-file`
|
||||
on the command line. For more info, see `--log-file` in [command-line
|
||||
switches](./command-line-switches.md#log-filepath).
|
||||
switches](./command-line-switches.md#--log-filepath).
|
||||
|
||||
### `ELECTRON_DEBUG_DRAG_REGIONS`
|
||||
|
||||
|
||||
@@ -67,3 +67,8 @@ or is being instructed to show a high-contrast UI.
|
||||
|
||||
A `Boolean` for if the OS / Chromium currently has an inverted color scheme
|
||||
or is being instructed to use an inverted color scheme.
|
||||
|
||||
### `nativeTheme.inForcedColorsMode` _Windows_ _Readonly_
|
||||
|
||||
A `boolean` indicating whether Chromium is in forced colors mode, controlled by system accessibility settings.
|
||||
Currently, Windows high contrast is the only system setting that triggers forced colors mode.
|
||||
|
||||
@@ -178,7 +178,6 @@ Returns an object with V8 heap statistics. Note that all statistics are reported
|
||||
Returns `Object`:
|
||||
|
||||
* `allocated` Integer - Size of all allocated objects in Kilobytes.
|
||||
* `marked` Integer - Size of all marked objects in Kilobytes.
|
||||
* `total` Integer - Total allocated space in Kilobytes.
|
||||
|
||||
Returns an object with Blink memory information.
|
||||
|
||||
@@ -736,6 +736,8 @@ first available device will be selected. `callback` should be called with
|
||||
`deviceId` to be selected, passing empty string to `callback` will
|
||||
cancel the request.
|
||||
|
||||
If no event listener is added for this event, all bluetooth requests will be cancelled.
|
||||
|
||||
```javascript
|
||||
const { app, BrowserWindow } = require('electron')
|
||||
|
||||
@@ -1610,7 +1612,7 @@ app.whenReady().then(() => {
|
||||
|
||||
* `options` Object (optional)
|
||||
* `mode` String - Opens the devtools with specified dock state, can be
|
||||
`right`, `bottom`, `undocked`, `detach`. Defaults to last used dock state.
|
||||
`left`, `right`, `bottom`, `undocked`, `detach`. Defaults to last used dock state.
|
||||
In `undocked` mode it's possible to dock back. In `detach` mode it's not.
|
||||
* `activate` Boolean (optional) - Whether to bring the opened devtools window
|
||||
to the foreground. The default is `true`.
|
||||
@@ -1838,7 +1840,7 @@ the cursor when dragging.
|
||||
|
||||
#### `contents.savePage(fullPath, saveType)`
|
||||
|
||||
* `fullPath` String - The full file path.
|
||||
* `fullPath` String - The absolute file path.
|
||||
* `saveType` String - Specify the save type.
|
||||
* `HTMLOnly` - Save only the HTML of the page.
|
||||
* `HTMLComplete` - Save complete-html page.
|
||||
|
||||
@@ -64,6 +64,9 @@ window.open('https://github.com', '_blank', 'top=500,left=200,frame=false,nodeIn
|
||||
`features` will be passed to any registered `webContents`'s
|
||||
`did-create-window` event handler in the `options` argument.
|
||||
* `frameName` follows the specification of `windowName` located in the [native documentation](https://developer.mozilla.org/en-US/docs/Web/API/Window/open#parameters).
|
||||
* When opening `about:blank`, the child window's `WebPreferences` will be copied
|
||||
from the parent window, and there is no way to override it because Chromium
|
||||
skips browser side navigation in this case.
|
||||
|
||||
To customize or cancel the creation of the window, you can optionally set an
|
||||
override handler with `webContents.setWindowOpenHandler()` from the main
|
||||
|
||||
@@ -43,8 +43,9 @@ SRV*c:\code\symbols\*https://msdl.microsoft.com/download/symbols;SRV*c:\code\sym
|
||||
|
||||
## Using the symbol server in Visual Studio
|
||||
|
||||

|
||||

|
||||

|
||||
|
||||

|
||||
|
||||
## Troubleshooting: Symbols will not load
|
||||
|
||||
|
||||
BIN
docs/images/vs-options-debugging-symbols.png
Normal file
BIN
docs/images/vs-options-debugging-symbols.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 32 KiB |
BIN
docs/images/vs-tools-options.png
Normal file
BIN
docs/images/vs-tools-options.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 15 KiB |
@@ -56,7 +56,7 @@ will then be your distribution to deliver to users.
|
||||
|
||||
### With an app source code archive
|
||||
|
||||
Instead of from shipping your app by copying all of its source files, you can
|
||||
Instead of shipping your app by copying all of its source files, you can
|
||||
package your app into an [asar] archive to improve the performance of reading
|
||||
files on platforms like Windows, if you are not already using a bundler such
|
||||
as Parcel or Webpack.
|
||||
|
||||
@@ -91,7 +91,7 @@ The above configuration will download from URLs such as
|
||||
`https://npm.taobao.org/mirrors/electron/8.0.0/electron-v8.0.0-linux-x64.zip`.
|
||||
|
||||
If your mirror serves artifacts with different checksums to the official
|
||||
Electron release you may have to set `ELECTRON_USE_REMOTE_CHECKSUMS=1` to
|
||||
Electron release you may have to set `electron_use_remote_checksums=1` to
|
||||
force Electron to use the remote `SHASUMS256.txt` file to verify the checksum
|
||||
instead of the embedded checksums.
|
||||
|
||||
|
||||
@@ -669,16 +669,6 @@ WebContents.prototype._init = function () {
|
||||
postBody
|
||||
};
|
||||
windowOpenOverriddenOptions = this._callWindowOpenHandler(event, details);
|
||||
// if attempting to use this API with the deprecated new-window event,
|
||||
// windowOpenOverriddenOptions will always return null. This ensures
|
||||
// short-term backwards compatibility until new-window is removed.
|
||||
const parsedFeatures = parseFeatures(rawFeatures);
|
||||
const overriddenFeatures: BrowserWindowConstructorOptions = {
|
||||
...parsedFeatures.options,
|
||||
webPreferences: parsedFeatures.webPreferences
|
||||
};
|
||||
windowOpenOverriddenOptions = windowOpenOverriddenOptions || overriddenFeatures;
|
||||
|
||||
if (!event.defaultPrevented) {
|
||||
const secureOverrideWebPreferences = windowOpenOverriddenOptions ? {
|
||||
// Allow setting of backgroundColor as a webPreference even though
|
||||
@@ -688,9 +678,19 @@ WebContents.prototype._init = function () {
|
||||
transparent: windowOpenOverriddenOptions.transparent,
|
||||
...windowOpenOverriddenOptions.webPreferences
|
||||
} : undefined;
|
||||
this._setNextChildWebPreferences(
|
||||
makeWebPreferences({ embedder: event.sender, secureOverrideWebPreferences })
|
||||
);
|
||||
// TODO(zcbenz): The features string is parsed twice: here where it is
|
||||
// passed to C++, and in |makeBrowserWindowOptions| later where it is
|
||||
// not actually used since the WebContents is created here.
|
||||
// We should be able to remove the latter once the |nativeWindowOpen|
|
||||
// option is removed.
|
||||
const { webPreferences: parsedWebPreferences } = parseFeatures(rawFeatures);
|
||||
// Parameters should keep same with |makeBrowserWindowOptions|.
|
||||
const webPreferences = makeWebPreferences({
|
||||
embedder: event.sender,
|
||||
insecureParsedWebPreferences: parsedWebPreferences,
|
||||
secureOverrideWebPreferences
|
||||
});
|
||||
this._setNextChildWebPreferences(webPreferences);
|
||||
}
|
||||
});
|
||||
|
||||
@@ -738,6 +738,14 @@ WebContents.prototype._init = function () {
|
||||
}
|
||||
});
|
||||
|
||||
this.on('select-bluetooth-device', (event, devices, callback) => {
|
||||
if (this.listenerCount('select-bluetooth-device') === 1) {
|
||||
// Cancel it if there are no handlers
|
||||
event.preventDefault();
|
||||
callback('');
|
||||
}
|
||||
});
|
||||
|
||||
const event = process._linkedBinding('electron_browser_event').createEmpty();
|
||||
app.emit('web-contents-created', event, this);
|
||||
|
||||
|
||||
@@ -28,6 +28,17 @@ function sanitizeOptionsForGuest (options: Record<string, any>) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
function makeLoadURLOptions (params: Record<string, any>) {
|
||||
const opts: Electron.LoadURLOptions = {};
|
||||
if (params.httpreferrer) {
|
||||
opts.httpReferrer = params.httpreferrer;
|
||||
}
|
||||
if (params.useragent) {
|
||||
opts.userAgent = params.useragent;
|
||||
}
|
||||
return opts;
|
||||
}
|
||||
|
||||
// Create a new guest instance.
|
||||
const createGuest = function (embedder: Electron.WebContents, params: Record<string, any>) {
|
||||
// eslint-disable-next-line no-undef
|
||||
@@ -51,7 +62,7 @@ const createGuest = function (embedder: Electron.WebContents, params: Record<str
|
||||
|
||||
// Init guest web view after attached.
|
||||
guest.once('did-attach' as any, function (this: Electron.WebContents, event: Electron.Event) {
|
||||
params = this.attachParams!;
|
||||
const params = this.attachParams!;
|
||||
delete this.attachParams;
|
||||
|
||||
const previouslyAttached = this.viewInstanceId != null;
|
||||
@@ -63,14 +74,7 @@ const createGuest = function (embedder: Electron.WebContents, params: Record<str
|
||||
}
|
||||
|
||||
if (params.src) {
|
||||
const opts: Electron.LoadURLOptions = {};
|
||||
if (params.httpreferrer) {
|
||||
opts.httpReferrer = params.httpreferrer;
|
||||
}
|
||||
if (params.useragent) {
|
||||
opts.userAgent = params.useragent;
|
||||
}
|
||||
this.loadURL(params.src, opts);
|
||||
this.loadURL(params.src, params.opts);
|
||||
}
|
||||
embedder.emit('did-attach-webview', event, guest);
|
||||
});
|
||||
@@ -149,13 +153,15 @@ const attachGuest = function (event: Electron.IpcMainInvokeEvent,
|
||||
throw new Error(`Access denied to guestInstanceId: ${guestInstanceId}`);
|
||||
}
|
||||
|
||||
const { instanceId } = params;
|
||||
|
||||
// If this guest is already attached to an element then remove it
|
||||
if (guestInstance.elementInstanceId) {
|
||||
const oldKey = `${guestInstance.embedder.id}-${guestInstance.elementInstanceId}`;
|
||||
embedderElementsMap.delete(oldKey);
|
||||
|
||||
// Remove guest from embedder if moving across web views
|
||||
if (guest.viewInstanceId !== params.instanceId) {
|
||||
if (guest.viewInstanceId !== instanceId) {
|
||||
webViewManager.removeGuest(guestInstance.embedder, guestInstanceId);
|
||||
guestInstance.embedder._sendInternal(`${IPC_MESSAGES.GUEST_VIEW_INTERNAL_DESTROY_GUEST}-${guest.viewInstanceId}`);
|
||||
}
|
||||
@@ -206,12 +212,12 @@ const attachGuest = function (event: Electron.IpcMainInvokeEvent,
|
||||
|
||||
embedder.emit('will-attach-webview', event, webPreferences, params);
|
||||
if (event.defaultPrevented) {
|
||||
if (guest.viewInstanceId == null) guest.viewInstanceId = params.instanceId;
|
||||
if (guest.viewInstanceId == null) guest.viewInstanceId = instanceId;
|
||||
guest.destroy();
|
||||
return;
|
||||
}
|
||||
|
||||
guest.attachParams = params;
|
||||
guest.attachParams = { instanceId, src: params.src, opts: makeLoadURLOptions(params) };
|
||||
embedderElementsMap.set(key, guestInstanceId);
|
||||
|
||||
guest.setEmbedder(embedder);
|
||||
|
||||
@@ -217,6 +217,10 @@ function makeBrowserWindowOptions ({ embedder, features, overrideOptions }: {
|
||||
height: 600,
|
||||
...parsedOptions,
|
||||
...overrideOptions,
|
||||
// Note that for |nativeWindowOpen: true| the WebContents is created in
|
||||
// |api::WebContents::WebContentsCreatedWithFullParams|, with prefs
|
||||
// parsed in the |-will-add-new-contents| event.
|
||||
// The |webPreferences| here is only used by |nativeWindowOpen: false|.
|
||||
webPreferences: makeWebPreferences({
|
||||
embedder,
|
||||
insecureParsedWebPreferences: parsedWebPreferences,
|
||||
|
||||
@@ -27,7 +27,6 @@ export class WebViewImpl {
|
||||
public hasFocus = false
|
||||
public internalInstanceId?: number;
|
||||
public resizeObserver?: ResizeObserver;
|
||||
public userAgentOverride?: string;
|
||||
public viewInstanceId: number
|
||||
|
||||
// on* Event handlers.
|
||||
@@ -180,8 +179,7 @@ export class WebViewImpl {
|
||||
|
||||
buildParams () {
|
||||
const params: Record<string, any> = {
|
||||
instanceId: this.viewInstanceId,
|
||||
userAgentOverride: this.userAgentOverride
|
||||
instanceId: this.viewInstanceId
|
||||
};
|
||||
|
||||
for (const [attributeName, attribute] of this.attributes) {
|
||||
|
||||
@@ -22,7 +22,8 @@ if (isInstalled()) {
|
||||
const platform = process.env.npm_config_platform || process.platform;
|
||||
let arch = process.env.npm_config_arch || process.arch;
|
||||
|
||||
if (platform === 'darwin' && process.platform === 'darwin' && arch === 'x64') {
|
||||
if (platform === 'darwin' && process.platform === 'darwin' && arch === 'x64' &&
|
||||
process.env.npm_config_arch === undefined) {
|
||||
// When downloading for macOS ON macOS and we think we need x64 we should
|
||||
// check if we're running under rosetta and download the arm64 version if appropriate
|
||||
try {
|
||||
|
||||
@@ -1,9 +1,10 @@
|
||||
{
|
||||
"name": "electron",
|
||||
"version": "15.3.2",
|
||||
"version": "15.5.3",
|
||||
"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.2",
|
||||
"@electron/typescript-definitions": "^8.9.5",
|
||||
"@octokit/auth-app": "^2.10.0",
|
||||
@@ -33,7 +34,7 @@
|
||||
"asar": "^3.1.0",
|
||||
"aws-sdk": "^2.727.1",
|
||||
"check-for-leaks": "^1.2.1",
|
||||
"colors": "^1.4.0",
|
||||
"colors": "1.4.0",
|
||||
"dotenv-safe": "^4.0.4",
|
||||
"dugite": "^1.103.0",
|
||||
"eslint": "^7.4.0",
|
||||
|
||||
14
patches/angle/.patches
Normal file
14
patches/angle/.patches
Normal file
@@ -0,0 +1,14 @@
|
||||
cherry-pick-bdffa0ea5148.patch
|
||||
cherry-pick-05e69c75905f.patch
|
||||
cherry-pick-891020ed64d4.patch
|
||||
cherry-pick-2b98abd8cb6c.patch
|
||||
cherry-pick-cc44ae61f37b.patch
|
||||
vangle_change_the_default_vulkan_device_choose_logic.patch
|
||||
m96_validate_samplerformat.patch
|
||||
m98_vulkan_fix_vkcmdresolveimage_extents.patch
|
||||
m98_vulkan_fix_vkcmdresolveimage_offsets.patch
|
||||
cherry-pick-49e8ff16f1fe.patch
|
||||
m99_vulkan_prevent_out_of_bounds_read_in_divisor_emulation_path.patch
|
||||
m99_vulkan_streamvertexdatawithdivisor_write_beyond_buffer_boundary.patch
|
||||
m98_protect_against_deleting_a_current_xfb_buffer.patch
|
||||
m96-lts_vulkan_fix_issue_with_redefining_a_layered_attachment.patch
|
||||
118
patches/angle/cherry-pick-05e69c75905f.patch
Normal file
118
patches/angle/cherry-pick-05e69c75905f.patch
Normal file
@@ -0,0 +1,118 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Lingfeng Yang <lfy@google.com>
|
||||
Date: Wed, 1 Dec 2021 18:16:14 -0800
|
||||
Subject: M96: Vulkan: remove staged updates on storage set
|
||||
|
||||
Previously we would allow staged updates to bigger versions of a texture
|
||||
to go through even if the texture was redefined via glTexStorage*.
|
||||
|
||||
Bug: chromium:1262080
|
||||
Change-Id: I9d861fed68d4a1fdcd0777b97caf729cc74c595e
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/3312718
|
||||
Reviewed-by: Charlie Lao <cclao@google.com>
|
||||
Reviewed-by: Jamie Madill <jmadill@chromium.org>
|
||||
Reviewed-by: Shahbaz Youssefi <syoussefi@chromium.org>
|
||||
Commit-Queue: Lingfeng Yang <lfy@google.com>
|
||||
(cherry picked from commit 929c8ed4e8c3912cf027d843e7a2af47b21e5612)
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/3328001
|
||||
|
||||
diff --git a/src/libANGLE/renderer/vulkan/TextureVk.cpp b/src/libANGLE/renderer/vulkan/TextureVk.cpp
|
||||
index e0be9676912e49d70473ffdcd4d7b1549210be25..b43f41dbae29356f1ffe4f961ed83e0f0e9cdcd2 100644
|
||||
--- a/src/libANGLE/renderer/vulkan/TextureVk.cpp
|
||||
+++ b/src/libANGLE/renderer/vulkan/TextureVk.cpp
|
||||
@@ -1236,6 +1236,10 @@ angle::Result TextureVk::setStorageMultisample(const gl::Context *context,
|
||||
{
|
||||
releaseAndDeleteImageAndViews(contextVk);
|
||||
}
|
||||
+ else if (mImage)
|
||||
+ {
|
||||
+ mImage->releaseStagingBuffer(contextVk->getRenderer());
|
||||
+ }
|
||||
|
||||
const vk::Format &format = renderer->getFormat(internalformat);
|
||||
ANGLE_TRY(ensureImageAllocated(contextVk, format));
|
||||
diff --git a/src/tests/gl_tests/TextureTest.cpp b/src/tests/gl_tests/TextureTest.cpp
|
||||
index e79bc700d4991752289ff3d7c76f2ccbb3ba932a..a3dec629c9ea96b276ff8bf344d4a4628ff20b3b 100644
|
||||
--- a/src/tests/gl_tests/TextureTest.cpp
|
||||
+++ b/src/tests/gl_tests/TextureTest.cpp
|
||||
@@ -9703,6 +9703,73 @@ void main()
|
||||
glUnmapBuffer(GL_SHADER_STORAGE_BUFFER);
|
||||
}
|
||||
|
||||
+class TextureChangeStorageUploadTest : public ANGLETest
|
||||
+{
|
||||
+ protected:
|
||||
+ TextureChangeStorageUploadTest()
|
||||
+ {
|
||||
+ setWindowWidth(256);
|
||||
+ setWindowHeight(256);
|
||||
+ setConfigRedBits(8);
|
||||
+ setConfigGreenBits(8);
|
||||
+ setConfigBlueBits(8);
|
||||
+ setConfigAlphaBits(8);
|
||||
+ }
|
||||
+
|
||||
+ void testSetUp() override
|
||||
+ {
|
||||
+ mProgram = CompileProgram(essl1_shaders::vs::Simple(), essl1_shaders::fs::UniformColor());
|
||||
+ if (mProgram == 0)
|
||||
+ {
|
||||
+ FAIL() << "shader compilation failed.";
|
||||
+ }
|
||||
+
|
||||
+ mColorLocation = glGetUniformLocation(mProgram, essl1_shaders::ColorUniform());
|
||||
+
|
||||
+ glUseProgram(mProgram);
|
||||
+
|
||||
+ glClearColor(0, 0, 0, 0);
|
||||
+ glClearDepthf(0.0);
|
||||
+ glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
||||
+
|
||||
+ glEnable(GL_BLEND);
|
||||
+ glDisable(GL_DEPTH_TEST);
|
||||
+
|
||||
+ glGenTextures(1, &mTexture);
|
||||
+ ASSERT_GL_NO_ERROR();
|
||||
+ }
|
||||
+
|
||||
+ void testTearDown() override
|
||||
+ {
|
||||
+ glDeleteTextures(1, &mTexture);
|
||||
+ glDeleteProgram(mProgram);
|
||||
+ }
|
||||
+
|
||||
+ GLuint mProgram;
|
||||
+ GLint mColorLocation;
|
||||
+ GLuint mTexture;
|
||||
+};
|
||||
+
|
||||
+// Verify that respecifying storage and re-uploading doesn't crash.
|
||||
+TEST_P(TextureChangeStorageUploadTest, Basic)
|
||||
+{
|
||||
+ constexpr int kImageSize = 8; // 4 doesn't trip ASAN
|
||||
+ constexpr int kSmallerImageSize = kImageSize / 2;
|
||||
+ EXPECT_GT(kImageSize, kSmallerImageSize);
|
||||
+ EXPECT_GT(kSmallerImageSize / 2, 0);
|
||||
+
|
||||
+ std::array<GLColor, kImageSize * kImageSize> kColor;
|
||||
+
|
||||
+ glBindTexture(GL_TEXTURE_2D, mTexture);
|
||||
+ glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, kImageSize, kImageSize, 0, GL_RGBA, GL_UNSIGNED_BYTE,
|
||||
+ kColor.data());
|
||||
+ glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, kSmallerImageSize, kSmallerImageSize);
|
||||
+ // need partial update to sidestep optimizations that remove the full upload
|
||||
+ glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, kSmallerImageSize / 2, kSmallerImageSize / 2, GL_RGBA,
|
||||
+ GL_UNSIGNED_BYTE, kColor.data());
|
||||
+ EXPECT_GL_NO_ERROR();
|
||||
+}
|
||||
+
|
||||
// Use this to select which configurations (e.g. which renderer, which GLES major version) these
|
||||
// tests should be run against.
|
||||
#define ES2_EMULATE_COPY_TEX_IMAGE() \
|
||||
@@ -9816,4 +9883,6 @@ ANGLE_INSTANTIATE_TEST_ES31_AND(TextureBufferTestES31, WithDirectSPIRVGeneration
|
||||
GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(CopyImageTestES31);
|
||||
ANGLE_INSTANTIATE_TEST_ES31_AND(CopyImageTestES31, WithDirectSPIRVGeneration(ES31_VULKAN()));
|
||||
|
||||
+ANGLE_INSTANTIATE_TEST_ES3(TextureChangeStorageUploadTest);
|
||||
+
|
||||
} // anonymous namespace
|
||||
96
patches/angle/cherry-pick-2b98abd8cb6c.patch
Normal file
96
patches/angle/cherry-pick-2b98abd8cb6c.patch
Normal file
@@ -0,0 +1,96 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Shahbaz Youssefi <syoussefi@chromium.org>
|
||||
Date: Tue, 30 Nov 2021 23:48:30 -0500
|
||||
Subject: M96: Vulkan: Fix image respecify's usage tracking
|
||||
|
||||
When respecifying an image due to mip level count changes, the previous
|
||||
image is staged as an update to the new image. The resource usage info
|
||||
was not being transferred to the image being staged as an update,
|
||||
causing it to be prematurely deleted.
|
||||
|
||||
Test based on one authored by sugoi@google.com.
|
||||
|
||||
Bug: chromium:1270658
|
||||
Bug: angleproject:4835
|
||||
Change-Id: I9810f8940e0107bc8a04fa3fb9c26a045c0d689c
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/3318257
|
||||
Reviewed-by: Lingfeng Yang <lfy@google.com>
|
||||
|
||||
diff --git a/src/libANGLE/renderer/vulkan/ResourceVk.cpp b/src/libANGLE/renderer/vulkan/ResourceVk.cpp
|
||||
index efb04acf0fe5dc7c2d860ac8cc33dbe30691c4a3..e2cd1e3a96b1fa4e034efe6ed78ea1a787af6af6 100644
|
||||
--- a/src/libANGLE/renderer/vulkan/ResourceVk.cpp
|
||||
+++ b/src/libANGLE/renderer/vulkan/ResourceVk.cpp
|
||||
@@ -26,6 +26,12 @@ Resource::Resource(Resource &&other) : Resource()
|
||||
mUse = std::move(other.mUse);
|
||||
}
|
||||
|
||||
+Resource &Resource::operator=(Resource &&rhs)
|
||||
+{
|
||||
+ std::swap(mUse, rhs.mUse);
|
||||
+ return *this;
|
||||
+}
|
||||
+
|
||||
Resource::~Resource()
|
||||
{
|
||||
mUse.release();
|
||||
diff --git a/src/libANGLE/renderer/vulkan/ResourceVk.h b/src/libANGLE/renderer/vulkan/ResourceVk.h
|
||||
index 67440122bf7fa0f72b5412816853b2eddd770fd4..abab9900b7361c8564cb1ad30e0841eaf873ee2e 100644
|
||||
--- a/src/libANGLE/renderer/vulkan/ResourceVk.h
|
||||
+++ b/src/libANGLE/renderer/vulkan/ResourceVk.h
|
||||
@@ -192,6 +192,7 @@ class Resource : angle::NonCopyable
|
||||
protected:
|
||||
Resource();
|
||||
Resource(Resource &&other);
|
||||
+ Resource &operator=(Resource &&rhs);
|
||||
|
||||
// Current resource lifetime.
|
||||
SharedResourceUse mUse;
|
||||
diff --git a/src/libANGLE/renderer/vulkan/vk_helpers.cpp b/src/libANGLE/renderer/vulkan/vk_helpers.cpp
|
||||
index a06b60d9c2c91280b925b12825e104bdbb757c05..893144ff07760dc1608a4b2d3af565e23ef27ba4 100644
|
||||
--- a/src/libANGLE/renderer/vulkan/vk_helpers.cpp
|
||||
+++ b/src/libANGLE/renderer/vulkan/vk_helpers.cpp
|
||||
@@ -6140,6 +6140,9 @@ void ImageHelper::stageSelfAsSubresourceUpdates(ContextVk *contextVk,
|
||||
// Move the necessary information for staged update to work, and keep the rest as part of this
|
||||
// object.
|
||||
|
||||
+ // Usage info
|
||||
+ prevImage->get().Resource::operator=(std::move(*this));
|
||||
+
|
||||
// Vulkan objects
|
||||
prevImage->get().mImage = std::move(mImage);
|
||||
prevImage->get().mDeviceMemory = std::move(mDeviceMemory);
|
||||
diff --git a/src/tests/gl_tests/MipmapTest.cpp b/src/tests/gl_tests/MipmapTest.cpp
|
||||
index 4db00e78a7d2f7375fdcb9228fbdc83395973125..8a6d01ca36a84a9e294de3f6f0114ee7a54e1d9a 100644
|
||||
--- a/src/tests/gl_tests/MipmapTest.cpp
|
||||
+++ b/src/tests/gl_tests/MipmapTest.cpp
|
||||
@@ -2106,6 +2106,30 @@ TEST_P(MipmapTestES3, GenerateMipmapZeroSize)
|
||||
glGenerateMipmap(GL_TEXTURE_3D);
|
||||
}
|
||||
|
||||
+// Test that reducing the size of the mipchain by resizing the base image then deleting it doesn't
|
||||
+// cause a crash. Issue found by fuzzer.
|
||||
+TEST_P(MipmapTestES3, ResizeBaseMipTo1x1ThenDelete)
|
||||
+{
|
||||
+ GLTexture tex;
|
||||
+ glBindTexture(GL_TEXTURE_2D, tex);
|
||||
+
|
||||
+ std::vector<GLColor> data(2, GLColor::blue);
|
||||
+
|
||||
+ glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE, data.data());
|
||||
+ glTexImage2D(GL_TEXTURE_2D, 1, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, data.data());
|
||||
+
|
||||
+ clearAndDrawQuad(m2DProgram, getWindowWidth(), getWindowHeight());
|
||||
+ EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::blue);
|
||||
+
|
||||
+ data[0] = GLColor::green;
|
||||
+ glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, data.data());
|
||||
+
|
||||
+ clearAndDrawQuad(m2DProgram, getWindowWidth(), getWindowHeight());
|
||||
+
|
||||
+ tex.reset();
|
||||
+ EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::green);
|
||||
+}
|
||||
+
|
||||
// Use this to select which configurations (e.g. which renderer, which GLES major version) these
|
||||
// tests should be run against.
|
||||
ANGLE_INSTANTIATE_TEST_ES2_AND_ES3(MipmapTest);
|
||||
381
patches/angle/cherry-pick-49e8ff16f1fe.patch
Normal file
381
patches/angle/cherry-pick-49e8ff16f1fe.patch
Normal file
@@ -0,0 +1,381 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Shahbaz Youssefi <syoussefi@chromium.org>
|
||||
Date: Tue, 25 Jan 2022 12:15:16 -0500
|
||||
Subject: M99: Vulkan: Fix texture array level redefinition
|
||||
|
||||
When a level of a texture is redefined, all staged updates to that level
|
||||
should be removed, not the ones specific to the new layers. The bug
|
||||
fixed was that if the texture was redefined to have its number of layers
|
||||
changed, the staged higher-layer-count update to the image was not
|
||||
removed.
|
||||
|
||||
Bug: chromium:1289383
|
||||
Change-Id: Iab79c38d846d1abbdd92e11b1b60a3adf0fbde4c
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/3441309
|
||||
Reviewed-by: Lingfeng Yang <lfy@google.com>
|
||||
Reviewed-by: Jamie Madill <jmadill@chromium.org>
|
||||
|
||||
diff --git a/src/libANGLE/renderer/vulkan/TextureVk.cpp b/src/libANGLE/renderer/vulkan/TextureVk.cpp
|
||||
index b43f41dbae29356f1ffe4f961ed83e0f0e9cdcd2..610f720b68d37aaddf142b0dca538749386cef7e 100644
|
||||
--- a/src/libANGLE/renderer/vulkan/TextureVk.cpp
|
||||
+++ b/src/libANGLE/renderer/vulkan/TextureVk.cpp
|
||||
@@ -1553,12 +1553,25 @@ angle::Result TextureVk::redefineLevel(const gl::Context *context,
|
||||
|
||||
if (mImage != nullptr)
|
||||
{
|
||||
- // If there is any staged changes for this index, we can remove them since we're going to
|
||||
+ // If there are any staged changes for this index, we can remove them since we're going to
|
||||
// override them with this call.
|
||||
gl::LevelIndex levelIndexGL(index.getLevelIndex());
|
||||
uint32_t layerIndex = index.hasLayer() ? index.getLayerIndex() : 0;
|
||||
- mImage->removeSingleSubresourceStagedUpdates(contextVk, levelIndexGL, layerIndex,
|
||||
- index.getLayerCount());
|
||||
+ if (gl::IsArrayTextureType(index.getType()))
|
||||
+ {
|
||||
+ // A multi-layer texture is being redefined, remove all updates to this level; the
|
||||
+ // number of layers may have changed.
|
||||
+ mImage->removeStagedUpdates(contextVk, levelIndexGL, levelIndexGL);
|
||||
+ }
|
||||
+ else
|
||||
+ {
|
||||
+ // Otherwise remove only updates to this layer. For example, cube map updates can be
|
||||
+ // done through glTexImage2D, one per cube face (i.e. layer) and so should not remove
|
||||
+ // updates to the other layers.
|
||||
+ ASSERT(index.getLayerCount() == 1);
|
||||
+ mImage->removeSingleSubresourceStagedUpdates(contextVk, levelIndexGL, layerIndex,
|
||||
+ index.getLayerCount());
|
||||
+ }
|
||||
|
||||
if (mImage->valid())
|
||||
{
|
||||
diff --git a/src/tests/gl_tests/MipmapTest.cpp b/src/tests/gl_tests/MipmapTest.cpp
|
||||
index 8a6d01ca36a84a9e294de3f6f0114ee7a54e1d9a..957a52304edc9aa245f9f21e5557cc105cbad789 100644
|
||||
--- a/src/tests/gl_tests/MipmapTest.cpp
|
||||
+++ b/src/tests/gl_tests/MipmapTest.cpp
|
||||
@@ -1686,6 +1686,106 @@ TEST_P(MipmapTestES3, MipmapsForTexture3D)
|
||||
EXPECT_PIXEL_COLOR_EQ(px, py, GLColor::red);
|
||||
}
|
||||
|
||||
+// Create a 2D array, then immediately redefine it to have fewer layers. Regression test for a bug
|
||||
+// in the Vulkan backend where the old higher-layer-count data upload was not removed.
|
||||
+TEST_P(MipmapTestES3, TextureArrayRedefineThenGenerateMipmap)
|
||||
+{
|
||||
+ int px = getWindowWidth() / 2;
|
||||
+ int py = getWindowHeight() / 2;
|
||||
+
|
||||
+ glBindTexture(GL_TEXTURE_2D_ARRAY, mTexture);
|
||||
+
|
||||
+ // Fill the whole texture with red, then redefine it and fill with green
|
||||
+ std::vector<GLColor> pixelsRed(2 * 2 * 4, GLColor::red);
|
||||
+ std::vector<GLColor> pixelsGreen(2 * 2 * 2, GLColor::green);
|
||||
+ glTexImage3D(GL_TEXTURE_2D_ARRAY, 0, GL_RGBA8, 2, 2, 4, 0, GL_RGBA, GL_UNSIGNED_BYTE,
|
||||
+ pixelsRed.data());
|
||||
+ glTexImage3D(GL_TEXTURE_2D_ARRAY, 0, GL_RGBA8, 2, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE,
|
||||
+ pixelsGreen.data());
|
||||
+
|
||||
+ glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST);
|
||||
+ glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||
+ EXPECT_GL_NO_ERROR();
|
||||
+
|
||||
+ // Generate mipmaps
|
||||
+ glGenerateMipmap(GL_TEXTURE_2D_ARRAY);
|
||||
+ EXPECT_GL_NO_ERROR();
|
||||
+
|
||||
+ glUseProgram(mArrayProgram);
|
||||
+ EXPECT_GL_NO_ERROR();
|
||||
+
|
||||
+ // Draw the first slice
|
||||
+ glUniform1i(mTextureArraySliceUniformLocation, 0);
|
||||
+ drawQuad(mArrayProgram, "position", 0.5f);
|
||||
+ EXPECT_GL_NO_ERROR();
|
||||
+ EXPECT_PIXEL_COLOR_EQ(px, py, GLColor::green);
|
||||
+
|
||||
+ // Draw the second slice
|
||||
+ glUniform1i(mTextureArraySliceUniformLocation, 1);
|
||||
+ drawQuad(mArrayProgram, "position", 0.5f);
|
||||
+ EXPECT_GL_NO_ERROR();
|
||||
+ EXPECT_PIXEL_COLOR_EQ(px, py, GLColor::green);
|
||||
+}
|
||||
+
|
||||
+// Create a 2D array, use it, then redefine it to have fewer layers. Regression test for a bug in
|
||||
+// the Vulkan backend where the old higher-layer-count data upload was not removed.
|
||||
+TEST_P(MipmapTestES3, TextureArrayUseThenRedefineThenGenerateMipmap)
|
||||
+{
|
||||
+ int px = getWindowWidth() / 2;
|
||||
+ int py = getWindowHeight() / 2;
|
||||
+
|
||||
+ glBindTexture(GL_TEXTURE_2D_ARRAY, mTexture);
|
||||
+
|
||||
+ // Fill the whole texture with red.
|
||||
+ std::vector<GLColor> pixelsRed(2 * 2 * 4, GLColor::red);
|
||||
+ glTexImage3D(GL_TEXTURE_2D_ARRAY, 0, GL_RGBA8, 2, 2, 4, 0, GL_RGBA, GL_UNSIGNED_BYTE,
|
||||
+ pixelsRed.data());
|
||||
+
|
||||
+ glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST);
|
||||
+ glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||
+ EXPECT_GL_NO_ERROR();
|
||||
+
|
||||
+ // Generate mipmap
|
||||
+ glGenerateMipmap(GL_TEXTURE_2D_ARRAY);
|
||||
+ EXPECT_GL_NO_ERROR();
|
||||
+
|
||||
+ glUseProgram(mArrayProgram);
|
||||
+ EXPECT_GL_NO_ERROR();
|
||||
+
|
||||
+ // Draw the first slice
|
||||
+ glUniform1i(mTextureArraySliceUniformLocation, 0);
|
||||
+ drawQuad(mArrayProgram, "position", 0.5f);
|
||||
+ EXPECT_GL_NO_ERROR();
|
||||
+ EXPECT_PIXEL_COLOR_EQ(px, py, GLColor::red);
|
||||
+
|
||||
+ // Draw the fourth slice
|
||||
+ glUniform1i(mTextureArraySliceUniformLocation, 3);
|
||||
+ drawQuad(mArrayProgram, "position", 0.5f);
|
||||
+ EXPECT_GL_NO_ERROR();
|
||||
+ EXPECT_PIXEL_COLOR_EQ(px, py, GLColor::red);
|
||||
+
|
||||
+ // Redefine the image and fill with green
|
||||
+ std::vector<GLColor> pixelsGreen(2 * 2 * 2, GLColor::green);
|
||||
+ glTexImage3D(GL_TEXTURE_2D_ARRAY, 0, GL_RGBA8, 2, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE,
|
||||
+ pixelsGreen.data());
|
||||
+
|
||||
+ // Generate mipmap
|
||||
+ glGenerateMipmap(GL_TEXTURE_2D_ARRAY);
|
||||
+ EXPECT_GL_NO_ERROR();
|
||||
+
|
||||
+ // Draw the first slice
|
||||
+ glUniform1i(mTextureArraySliceUniformLocation, 0);
|
||||
+ drawQuad(mArrayProgram, "position", 0.5f);
|
||||
+ EXPECT_GL_NO_ERROR();
|
||||
+ EXPECT_PIXEL_COLOR_EQ(px, py, GLColor::green);
|
||||
+
|
||||
+ // Draw the second slice
|
||||
+ glUniform1i(mTextureArraySliceUniformLocation, 1);
|
||||
+ drawQuad(mArrayProgram, "position", 0.5f);
|
||||
+ EXPECT_GL_NO_ERROR();
|
||||
+ EXPECT_PIXEL_COLOR_EQ(px, py, GLColor::green);
|
||||
+}
|
||||
+
|
||||
// Create a 2D texture with levels 0-2, call GenerateMipmap with base level 1 so that level 0 stays
|
||||
// the same, and then sample levels 0 and 2.
|
||||
// GLES 3.0.4 section 3.8.10:
|
||||
diff --git a/src/tests/gl_tests/TextureTest.cpp b/src/tests/gl_tests/TextureTest.cpp
|
||||
index 56bef0186234f59d370669c21f588ea9c5c356fc..772fe27daac3ac0b5f54b8319cef6aa9c980208a 100644
|
||||
--- a/src/tests/gl_tests/TextureTest.cpp
|
||||
+++ b/src/tests/gl_tests/TextureTest.cpp
|
||||
@@ -1028,31 +1028,37 @@ class SamplerArrayAsFunctionParameterTest : public SamplerArrayTest
|
||||
class Texture2DArrayTestES3 : public TexCoordDrawTest
|
||||
{
|
||||
protected:
|
||||
- Texture2DArrayTestES3() : TexCoordDrawTest(), m2DArrayTexture(0), mTextureArrayLocation(-1) {}
|
||||
+ Texture2DArrayTestES3()
|
||||
+ : TexCoordDrawTest(),
|
||||
+ m2DArrayTexture(0),
|
||||
+ mTextureArrayLocation(-1),
|
||||
+ mTextureArraySliceUniformLocation(-1)
|
||||
+ {}
|
||||
|
||||
const char *getVertexShaderSource() override
|
||||
{
|
||||
- return "#version 300 es\n"
|
||||
- "out vec2 texcoord;\n"
|
||||
- "in vec4 position;\n"
|
||||
- "void main()\n"
|
||||
- "{\n"
|
||||
- " gl_Position = vec4(position.xy, 0.0, 1.0);\n"
|
||||
- " texcoord = (position.xy * 0.5) + 0.5;\n"
|
||||
- "}\n";
|
||||
+ return R"(#version 300 es
|
||||
+out vec2 texcoord;
|
||||
+in vec4 position;
|
||||
+void main()
|
||||
+{
|
||||
+ gl_Position = vec4(position.xy, 0.0, 1.0);
|
||||
+ texcoord = (position.xy * 0.5) + 0.5;
|
||||
+})";
|
||||
}
|
||||
|
||||
const char *getFragmentShaderSource() override
|
||||
{
|
||||
- return "#version 300 es\n"
|
||||
- "precision highp float;\n"
|
||||
- "uniform highp sampler2DArray tex2DArray;\n"
|
||||
- "in vec2 texcoord;\n"
|
||||
- "out vec4 fragColor;\n"
|
||||
- "void main()\n"
|
||||
- "{\n"
|
||||
- " fragColor = texture(tex2DArray, vec3(texcoord.x, texcoord.y, 0.0));\n"
|
||||
- "}\n";
|
||||
+ return R"(#version 300 es
|
||||
+precision highp float;
|
||||
+uniform highp sampler2DArray tex2DArray;
|
||||
+uniform int slice;
|
||||
+in vec2 texcoord;
|
||||
+out vec4 fragColor;
|
||||
+void main()
|
||||
+{
|
||||
+ fragColor = texture(tex2DArray, vec3(texcoord, float(slice)));
|
||||
+})";
|
||||
}
|
||||
|
||||
void testSetUp() override
|
||||
@@ -1064,6 +1070,9 @@ class Texture2DArrayTestES3 : public TexCoordDrawTest
|
||||
mTextureArrayLocation = glGetUniformLocation(mProgram, "tex2DArray");
|
||||
ASSERT_NE(-1, mTextureArrayLocation);
|
||||
|
||||
+ mTextureArraySliceUniformLocation = glGetUniformLocation(mProgram, "slice");
|
||||
+ ASSERT_NE(-1, mTextureArraySliceUniformLocation);
|
||||
+
|
||||
glGenTextures(1, &m2DArrayTexture);
|
||||
ASSERT_GL_NO_ERROR();
|
||||
}
|
||||
@@ -1076,6 +1085,7 @@ class Texture2DArrayTestES3 : public TexCoordDrawTest
|
||||
|
||||
GLuint m2DArrayTexture;
|
||||
GLint mTextureArrayLocation;
|
||||
+ GLint mTextureArraySliceUniformLocation;
|
||||
};
|
||||
|
||||
class TextureSizeTextureArrayTest : public TexCoordDrawTest
|
||||
@@ -1718,28 +1728,28 @@ class Texture2DArrayIntegerTestES3 : public Texture2DArrayTestES3
|
||||
|
||||
const char *getVertexShaderSource() override
|
||||
{
|
||||
- return "#version 300 es\n"
|
||||
- "out vec2 texcoord;\n"
|
||||
- "in vec4 position;\n"
|
||||
- "void main()\n"
|
||||
- "{\n"
|
||||
- " gl_Position = vec4(position.xy, 0.0, 1.0);\n"
|
||||
- " texcoord = (position.xy * 0.5) + 0.5;\n"
|
||||
- "}\n";
|
||||
+ return R"(#version 300 es
|
||||
+out vec2 texcoord;
|
||||
+in vec4 position;
|
||||
+void main()
|
||||
+{
|
||||
+ gl_Position = vec4(position.xy, 0.0, 1.0);
|
||||
+ texcoord = (position.xy * 0.5) + 0.5;
|
||||
+})";
|
||||
}
|
||||
|
||||
const char *getFragmentShaderSource() override
|
||||
{
|
||||
- return "#version 300 es\n"
|
||||
- "precision highp float;\n"
|
||||
- "uniform highp usampler2DArray tex2DArray;\n"
|
||||
- "in vec2 texcoord;\n"
|
||||
- "out vec4 fragColor;\n"
|
||||
- "void main()\n"
|
||||
- "{\n"
|
||||
- " fragColor = vec4(texture(tex2DArray, vec3(texcoord.x, texcoord.y, "
|
||||
- "0.0)))/255.0;\n"
|
||||
- "}\n";
|
||||
+ return R"(#version 300 es
|
||||
+precision highp float;
|
||||
+uniform highp usampler2DArray tex2DArray;
|
||||
+uniform int slice;
|
||||
+in vec2 texcoord;
|
||||
+out vec4 fragColor;
|
||||
+void main()
|
||||
+{
|
||||
+ fragColor = vec4(texture(tex2DArray, vec3(texcoord, slice)))/255.0;
|
||||
+})";
|
||||
}
|
||||
};
|
||||
|
||||
@@ -5112,6 +5122,94 @@ TEST_P(Texture2DArrayTestES3, DrawWithLevelsOutsideRangeWithInconsistentDimensio
|
||||
EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::cyan);
|
||||
}
|
||||
|
||||
+// Create a 2D array, then immediately redefine it to have fewer layers. Regression test for a bug
|
||||
+// in the Vulkan backend where the old higher-layer-count data upload was not removed.
|
||||
+TEST_P(Texture2DArrayTestES3, TextureArrayRedefineThenUse)
|
||||
+{
|
||||
+ int px = getWindowWidth() / 2;
|
||||
+ int py = getWindowHeight() / 2;
|
||||
+
|
||||
+ glBindTexture(GL_TEXTURE_2D_ARRAY, m2DArrayTexture);
|
||||
+
|
||||
+ // Fill the whole texture with red, then redefine it and fill with green
|
||||
+ std::vector<GLColor> pixelsRed(2 * 2 * 4, GLColor::red);
|
||||
+ std::vector<GLColor> pixelsGreen(2 * 2 * 2, GLColor::green);
|
||||
+ glTexImage3D(GL_TEXTURE_2D_ARRAY, 0, GL_RGBA8, 2, 2, 4, 0, GL_RGBA, GL_UNSIGNED_BYTE,
|
||||
+ pixelsRed.data());
|
||||
+ glTexImage3D(GL_TEXTURE_2D_ARRAY, 0, GL_RGBA8, 2, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE,
|
||||
+ pixelsGreen.data());
|
||||
+
|
||||
+ glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||
+ glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||
+ EXPECT_GL_NO_ERROR();
|
||||
+
|
||||
+ glUseProgram(mProgram);
|
||||
+ EXPECT_GL_NO_ERROR();
|
||||
+
|
||||
+ // Draw the first slice
|
||||
+ glUniform1i(mTextureArraySliceUniformLocation, 0);
|
||||
+ drawQuad(mProgram, "position", 0.5f);
|
||||
+ EXPECT_GL_NO_ERROR();
|
||||
+ EXPECT_PIXEL_COLOR_EQ(px, py, GLColor::green);
|
||||
+
|
||||
+ // Draw the second slice
|
||||
+ glUniform1i(mTextureArraySliceUniformLocation, 1);
|
||||
+ drawQuad(mProgram, "position", 0.5f);
|
||||
+ EXPECT_GL_NO_ERROR();
|
||||
+ EXPECT_PIXEL_COLOR_EQ(px, py, GLColor::green);
|
||||
+}
|
||||
+
|
||||
+// Create a 2D array, use it, then redefine it to have fewer layers. Regression test for a bug in
|
||||
+// the Vulkan backend where the old higher-layer-count data upload was not removed.
|
||||
+TEST_P(Texture2DArrayTestES3, TextureArrayUseThenRedefineThenUse)
|
||||
+{
|
||||
+ int px = getWindowWidth() / 2;
|
||||
+ int py = getWindowHeight() / 2;
|
||||
+
|
||||
+ glBindTexture(GL_TEXTURE_2D_ARRAY, m2DArrayTexture);
|
||||
+
|
||||
+ // Fill the whole texture with red.
|
||||
+ std::vector<GLColor> pixelsRed(2 * 2 * 4, GLColor::red);
|
||||
+ glTexImage3D(GL_TEXTURE_2D_ARRAY, 0, GL_RGBA8, 2, 2, 4, 0, GL_RGBA, GL_UNSIGNED_BYTE,
|
||||
+ pixelsRed.data());
|
||||
+
|
||||
+ glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||
+ glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||
+ EXPECT_GL_NO_ERROR();
|
||||
+
|
||||
+ glUseProgram(mProgram);
|
||||
+ EXPECT_GL_NO_ERROR();
|
||||
+
|
||||
+ // Draw the first slice
|
||||
+ glUniform1i(mTextureArraySliceUniformLocation, 0);
|
||||
+ drawQuad(mProgram, "position", 0.5f);
|
||||
+ EXPECT_GL_NO_ERROR();
|
||||
+ EXPECT_PIXEL_COLOR_EQ(px, py, GLColor::red);
|
||||
+
|
||||
+ // Draw the fourth slice
|
||||
+ glUniform1i(mTextureArraySliceUniformLocation, 3);
|
||||
+ drawQuad(mProgram, "position", 0.5f);
|
||||
+ EXPECT_GL_NO_ERROR();
|
||||
+ EXPECT_PIXEL_COLOR_EQ(px, py, GLColor::red);
|
||||
+
|
||||
+ // Redefine the image and fill with green
|
||||
+ std::vector<GLColor> pixelsGreen(2 * 2 * 2, GLColor::green);
|
||||
+ glTexImage3D(GL_TEXTURE_2D_ARRAY, 0, GL_RGBA8, 2, 2, 2, 0, GL_RGBA, GL_UNSIGNED_BYTE,
|
||||
+ pixelsGreen.data());
|
||||
+
|
||||
+ // Draw the first slice
|
||||
+ glUniform1i(mTextureArraySliceUniformLocation, 0);
|
||||
+ drawQuad(mProgram, "position", 0.5f);
|
||||
+ EXPECT_GL_NO_ERROR();
|
||||
+ EXPECT_PIXEL_COLOR_EQ(px, py, GLColor::green);
|
||||
+
|
||||
+ // Draw the second slice
|
||||
+ glUniform1i(mTextureArraySliceUniformLocation, 1);
|
||||
+ drawQuad(mProgram, "position", 0.5f);
|
||||
+ EXPECT_GL_NO_ERROR();
|
||||
+ EXPECT_PIXEL_COLOR_EQ(px, py, GLColor::green);
|
||||
+}
|
||||
+
|
||||
// Test that texture completeness is updated if texture max level changes.
|
||||
// GLES 3.0.4 section 3.8.13 Texture completeness
|
||||
TEST_P(Texture2DTestES3, TextureCompletenessChangesWithMaxLevel)
|
||||
163
patches/angle/cherry-pick-891020ed64d4.patch
Normal file
163
patches/angle/cherry-pick-891020ed64d4.patch
Normal file
@@ -0,0 +1,163 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Jonah Ryan-Davis <jonahr@google.com>
|
||||
Date: Mon, 22 Nov 2021 14:30:52 -0500
|
||||
Subject: Ignore the pixel unpack state for compressed textures.
|
||||
|
||||
From OpenGL ES 3 spec: All pixel storage modes are ignored when decoding
|
||||
a compressed texture image
|
||||
This was causing a bad access when calling compressedTexImage3D
|
||||
with GL_UNPACK_IMAGE_HEIGHT greater than the image height.
|
||||
|
||||
Bug: chromium:1267496
|
||||
Change-Id: I9b1f4c645548af64f2695fd23262225a1ad07cd7
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/3296622
|
||||
Commit-Queue: Jonah Ryan-Davis <jonahr@google.com>
|
||||
Reviewed-by: Geoff Lang <geofflang@chromium.org>
|
||||
Reviewed-by: Shahbaz Youssefi <syoussefi@chromium.org>
|
||||
(cherry picked from commit 870f458f507ff7ba0f67b28a30a27955ce79dd3e)
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/3309097
|
||||
Reviewed-by: Jonah Ryan-Davis <jonahr@google.com>
|
||||
Reviewed-by: Jamie Madill <jmadill@chromium.org>
|
||||
|
||||
diff --git a/src/libANGLE/Context.cpp b/src/libANGLE/Context.cpp
|
||||
index c4ce77d612d88a898f8a8164466d25b210e2144b..eb60719ac38543b608c122daebd71b1084ac35f2 100644
|
||||
--- a/src/libANGLE/Context.cpp
|
||||
+++ b/src/libANGLE/Context.cpp
|
||||
@@ -4961,7 +4961,9 @@ void Context::compressedTexImage2D(TextureTarget target,
|
||||
|
||||
Extents size(width, height, 1);
|
||||
Texture *texture = getTextureByTarget(target);
|
||||
- ANGLE_CONTEXT_TRY(texture->setCompressedImage(this, mState.getUnpackState(), target, level,
|
||||
+ // From OpenGL ES 3 spec: All pixel storage modes are ignored when decoding a compressed texture
|
||||
+ // image. So we use an empty PixelUnpackState.
|
||||
+ ANGLE_CONTEXT_TRY(texture->setCompressedImage(this, PixelUnpackState(), target, level,
|
||||
internalformat, size, imageSize,
|
||||
static_cast<const uint8_t *>(data)));
|
||||
}
|
||||
@@ -4993,7 +4995,9 @@ void Context::compressedTexImage3D(TextureTarget target,
|
||||
|
||||
Extents size(width, height, depth);
|
||||
Texture *texture = getTextureByTarget(target);
|
||||
- ANGLE_CONTEXT_TRY(texture->setCompressedImage(this, mState.getUnpackState(), target, level,
|
||||
+ // From OpenGL ES 3 spec: All pixel storage modes are ignored when decoding a compressed texture
|
||||
+ // image. So we use an empty PixelUnpackState.
|
||||
+ ANGLE_CONTEXT_TRY(texture->setCompressedImage(this, PixelUnpackState(), target, level,
|
||||
internalformat, size, imageSize,
|
||||
static_cast<const uint8_t *>(data)));
|
||||
}
|
||||
@@ -5027,8 +5031,10 @@ void Context::compressedTexSubImage2D(TextureTarget target,
|
||||
|
||||
Box area(xoffset, yoffset, 0, width, height, 1);
|
||||
Texture *texture = getTextureByTarget(target);
|
||||
- ANGLE_CONTEXT_TRY(texture->setCompressedSubImage(this, mState.getUnpackState(), target, level,
|
||||
- area, format, imageSize,
|
||||
+ // From OpenGL ES 3 spec: All pixel storage modes are ignored when decoding a compressed texture
|
||||
+ // image. So we use an empty PixelUnpackState.
|
||||
+ ANGLE_CONTEXT_TRY(texture->setCompressedSubImage(this, PixelUnpackState(), target, level, area,
|
||||
+ format, imageSize,
|
||||
static_cast<const uint8_t *>(data)));
|
||||
}
|
||||
|
||||
@@ -5069,8 +5075,10 @@ void Context::compressedTexSubImage3D(TextureTarget target,
|
||||
|
||||
Box area(xoffset, yoffset, zoffset, width, height, depth);
|
||||
Texture *texture = getTextureByTarget(target);
|
||||
- ANGLE_CONTEXT_TRY(texture->setCompressedSubImage(this, mState.getUnpackState(), target, level,
|
||||
- area, format, imageSize,
|
||||
+ // From OpenGL ES 3 spec: All pixel storage modes are ignored when decoding a compressed texture
|
||||
+ // image. So we use an empty PixelUnpackState.
|
||||
+ ANGLE_CONTEXT_TRY(texture->setCompressedSubImage(this, PixelUnpackState(), target, level, area,
|
||||
+ format, imageSize,
|
||||
static_cast<const uint8_t *>(data)));
|
||||
}
|
||||
|
||||
diff --git a/src/tests/gl_tests/TextureTest.cpp b/src/tests/gl_tests/TextureTest.cpp
|
||||
index a3dec629c9ea96b276ff8bf344d4a4628ff20b3b..ba512a11cb023d9caae666ab2634d1e66057d12c 100644
|
||||
--- a/src/tests/gl_tests/TextureTest.cpp
|
||||
+++ b/src/tests/gl_tests/TextureTest.cpp
|
||||
@@ -5151,6 +5151,43 @@ TEST_P(Texture2DTestES3, TextureCompletenessChangesWithMaxLevel)
|
||||
EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::black);
|
||||
}
|
||||
|
||||
+// Test that compressed textures ignore the pixel unpack state.
|
||||
+// (https://crbug.org/1267496)
|
||||
+TEST_P(Texture3DTestES3, PixelUnpackStateTexImage)
|
||||
+{
|
||||
+ ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_texture_compression_s3tc") &&
|
||||
+ !IsGLExtensionEnabled("GL_ANGLE_texture_compression_dxt3"));
|
||||
+
|
||||
+ glPixelStorei(GL_UNPACK_IMAGE_HEIGHT, 5);
|
||||
+ glBindTexture(GL_TEXTURE_2D_ARRAY, mTexture3D);
|
||||
+
|
||||
+ uint8_t data[64] = {0};
|
||||
+ glCompressedTexImage3D(GL_TEXTURE_2D_ARRAY, 0, GL_COMPRESSED_RGBA_S3TC_DXT3_EXT, 4, 4, 4, 0, 64,
|
||||
+ data);
|
||||
+ EXPECT_GL_NO_ERROR();
|
||||
+}
|
||||
+
|
||||
+// Test that compressed textures ignore the pixel unpack state.
|
||||
+// (https://crbug.org/1267496)
|
||||
+TEST_P(Texture3DTestES3, PixelUnpackStateTexSubImage)
|
||||
+{
|
||||
+ ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_texture_compression_s3tc") &&
|
||||
+ !IsGLExtensionEnabled("GL_ANGLE_texture_compression_dxt3"));
|
||||
+
|
||||
+ glBindTexture(GL_TEXTURE_2D_ARRAY, mTexture3D);
|
||||
+
|
||||
+ uint8_t data[64] = {0};
|
||||
+ glCompressedTexImage3D(GL_TEXTURE_2D_ARRAY, 0, GL_COMPRESSED_RGBA_S3TC_DXT3_EXT, 4, 4, 4, 0, 64,
|
||||
+ data);
|
||||
+ EXPECT_GL_NO_ERROR();
|
||||
+
|
||||
+ glPixelStorei(GL_UNPACK_IMAGE_HEIGHT, 5);
|
||||
+
|
||||
+ glCompressedTexSubImage3D(GL_TEXTURE_2D_ARRAY, 0, 0, 0, 0, 4, 4, 4,
|
||||
+ GL_COMPRESSED_RGBA_S3TC_DXT3_EXT, 64, data);
|
||||
+ EXPECT_GL_NO_ERROR();
|
||||
+}
|
||||
+
|
||||
// Test that 3D texture completeness is updated if texture max level changes.
|
||||
// GLES 3.0.4 section 3.8.13 Texture completeness
|
||||
TEST_P(Texture3DTestES3, Texture3DCompletenessChangesWithMaxLevel)
|
||||
@@ -5830,6 +5867,41 @@ TEST_P(Texture2DTestES3, TextureCOMPRESSEDSRGB8ETC2ImplicitAlpha1)
|
||||
EXPECT_PIXEL_ALPHA_EQ(0, 0, 255);
|
||||
}
|
||||
|
||||
+// Test that compressed textures ignore the pixel unpack state.
|
||||
+// (https://crbug.org/1267496)
|
||||
+TEST_P(Texture2DTestES3, PixelUnpackStateTexImage)
|
||||
+{
|
||||
+ ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_texture_compression_s3tc") &&
|
||||
+ !IsGLExtensionEnabled("GL_ANGLE_texture_compression_dxt3"));
|
||||
+
|
||||
+ glPixelStorei(GL_UNPACK_ROW_LENGTH, 5);
|
||||
+ glBindTexture(GL_TEXTURE_2D, mTexture2D);
|
||||
+
|
||||
+ uint8_t data[16] = {0};
|
||||
+ glCompressedTexImage2D(GL_TEXTURE_2D, 0, GL_COMPRESSED_RGBA_S3TC_DXT3_EXT, 4, 4, 0, 16, data);
|
||||
+ EXPECT_GL_NO_ERROR();
|
||||
+}
|
||||
+
|
||||
+// Test that compressed textures ignore the pixel unpack state.
|
||||
+// (https://crbug.org/1267496)
|
||||
+TEST_P(Texture2DTestES3, PixelUnpackStateTexSubImage)
|
||||
+{
|
||||
+ ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_texture_compression_s3tc") &&
|
||||
+ !IsGLExtensionEnabled("GL_ANGLE_texture_compression_dxt3"));
|
||||
+
|
||||
+ glBindTexture(GL_TEXTURE_2D, mTexture2D);
|
||||
+
|
||||
+ uint8_t data[16] = {0};
|
||||
+ glCompressedTexImage2D(GL_TEXTURE_2D, 0, GL_COMPRESSED_RGBA_S3TC_DXT3_EXT, 4, 4, 0, 16, data);
|
||||
+ EXPECT_GL_NO_ERROR();
|
||||
+
|
||||
+ glPixelStorei(GL_UNPACK_ROW_LENGTH, 5);
|
||||
+
|
||||
+ glCompressedTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 4, 4, GL_COMPRESSED_RGBA_S3TC_DXT3_EXT, 16,
|
||||
+ data);
|
||||
+ EXPECT_GL_NO_ERROR();
|
||||
+}
|
||||
+
|
||||
// Copied from Texture2DTest::TexStorage
|
||||
// Test that glTexSubImage2D works properly when glTexStorage2DEXT has initialized the image with a
|
||||
// default color.
|
||||
169
patches/angle/cherry-pick-bdffa0ea5148.patch
Normal file
169
patches/angle/cherry-pick-bdffa0ea5148.patch
Normal file
@@ -0,0 +1,169 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Shahbaz Youssefi <syoussefi@chromium.org>
|
||||
Date: Thu, 2 Dec 2021 14:30:42 -0500
|
||||
Subject: M96: Fix changing attached renderbuffer from MSRTT to non-MSRTT
|
||||
|
||||
FramebufferAttachment::mRenderToTextureSamples was never updated if the
|
||||
renderbuffer storage was changed after attaching to framebuffer.
|
||||
|
||||
Bug: chromium:1272068
|
||||
Change-Id: Icddbb5650354ea16d06c49532d6a8d0ae962ab5f
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/3320923
|
||||
Reviewed-by: Jamie Madill <jmadill@chromium.org>
|
||||
|
||||
diff --git a/src/libANGLE/FramebufferAttachment.cpp b/src/libANGLE/FramebufferAttachment.cpp
|
||||
index 00714d0a0303050893abcd9564e760b22d9b2de5..720d3000d42e6c8c23214e66eee4aa6982216a60 100644
|
||||
--- a/src/libANGLE/FramebufferAttachment.cpp
|
||||
+++ b/src/libANGLE/FramebufferAttachment.cpp
|
||||
@@ -129,7 +129,7 @@ void FramebufferAttachment::attach(const Context *context,
|
||||
mNumViews = numViews;
|
||||
mBaseViewIndex = baseViewIndex;
|
||||
mIsMultiview = isMultiview;
|
||||
- mRenderToTextureSamples = samples;
|
||||
+ mRenderToTextureSamples = type == GL_RENDERBUFFER ? kDefaultRenderToTextureSamples : samples;
|
||||
resource->onAttach(context, framebufferSerial);
|
||||
|
||||
if (mResource != nullptr)
|
||||
@@ -222,6 +222,29 @@ GLint FramebufferAttachment::getBaseViewIndex() const
|
||||
return mBaseViewIndex;
|
||||
}
|
||||
|
||||
+bool FramebufferAttachment::isRenderToTexture() const
|
||||
+{
|
||||
+ ASSERT(mRenderToTextureSamples == kDefaultRenderToTextureSamples || mType == GL_TEXTURE);
|
||||
+
|
||||
+ if (mType == GL_RENDERBUFFER)
|
||||
+ {
|
||||
+ return getRenderbuffer()->getMultisamplingMode() ==
|
||||
+ MultisamplingMode::MultisampledRenderToTexture;
|
||||
+ }
|
||||
+ return mRenderToTextureSamples != kDefaultRenderToTextureSamples;
|
||||
+}
|
||||
+
|
||||
+GLsizei FramebufferAttachment::getRenderToTextureSamples() const
|
||||
+{
|
||||
+ ASSERT(mRenderToTextureSamples == kDefaultRenderToTextureSamples || mType == GL_TEXTURE);
|
||||
+
|
||||
+ if (mType == GL_RENDERBUFFER)
|
||||
+ {
|
||||
+ return getRenderbuffer()->getState().getSamples();
|
||||
+ }
|
||||
+ return mRenderToTextureSamples;
|
||||
+}
|
||||
+
|
||||
Texture *FramebufferAttachment::getTexture() const
|
||||
{
|
||||
return rx::GetAs<Texture>(mResource);
|
||||
diff --git a/src/libANGLE/FramebufferAttachment.h b/src/libANGLE/FramebufferAttachment.h
|
||||
index 7ebf5f5e620cfac47be176fa0bc668353e923104..a5d5bf0eb0c50e37656b241d105be3f35a657585 100644
|
||||
--- a/src/libANGLE/FramebufferAttachment.h
|
||||
+++ b/src/libANGLE/FramebufferAttachment.h
|
||||
@@ -117,11 +117,8 @@ class FramebufferAttachment final
|
||||
bool isMultiview() const;
|
||||
GLint getBaseViewIndex() const;
|
||||
|
||||
- bool isRenderToTexture() const
|
||||
- {
|
||||
- return mRenderToTextureSamples != kDefaultRenderToTextureSamples;
|
||||
- }
|
||||
- GLsizei getRenderToTextureSamples() const { return mRenderToTextureSamples; }
|
||||
+ bool isRenderToTexture() const;
|
||||
+ GLsizei getRenderToTextureSamples() const;
|
||||
|
||||
// The size of the underlying resource the attachment points to. The 'depth' value will
|
||||
// correspond to a 3D texture depth or the layer count of a 2D array texture. For Surfaces and
|
||||
@@ -195,6 +192,14 @@ class FramebufferAttachment final
|
||||
GLsizei mNumViews;
|
||||
bool mIsMultiview;
|
||||
GLint mBaseViewIndex;
|
||||
+ // A single-sampled texture can be attached to a framebuffer either as single-sampled or as
|
||||
+ // multisampled-render-to-texture. In the latter case, |mRenderToTextureSamples| will contain
|
||||
+ // the number of samples. For renderbuffers, the number of samples is inherited from the
|
||||
+ // renderbuffer itself.
|
||||
+ //
|
||||
+ // Note that textures cannot change storage between single and multisample once attached to a
|
||||
+ // framebuffer. Renderbuffers instead can, and caching the number of renderbuffer samples here
|
||||
+ // can lead to stale data.
|
||||
GLsizei mRenderToTextureSamples;
|
||||
};
|
||||
|
||||
@@ -254,8 +259,7 @@ inline Format FramebufferAttachment::getFormat() const
|
||||
|
||||
inline GLsizei FramebufferAttachment::getSamples() const
|
||||
{
|
||||
- return (mRenderToTextureSamples != kDefaultRenderToTextureSamples) ? getRenderToTextureSamples()
|
||||
- : getResourceSamples();
|
||||
+ return isRenderToTexture() ? getRenderToTextureSamples() : getResourceSamples();
|
||||
}
|
||||
|
||||
inline GLsizei FramebufferAttachment::getResourceSamples() const
|
||||
diff --git a/src/tests/gl_tests/FramebufferTest.cpp b/src/tests/gl_tests/FramebufferTest.cpp
|
||||
index ff01848daff091d92e4fdce08bc6842a3bdd3ee9..cd733be3ae5c179860d882e305ec84d093a283ed 100644
|
||||
--- a/src/tests/gl_tests/FramebufferTest.cpp
|
||||
+++ b/src/tests/gl_tests/FramebufferTest.cpp
|
||||
@@ -3366,6 +3366,65 @@ void main() {
|
||||
|
||||
// This shouldn't crash.
|
||||
glDrawArrays(GL_POINTS, 0, 1);
|
||||
+ ASSERT_GL_NO_ERROR();
|
||||
+}
|
||||
+
|
||||
+// Modify renderbuffer attachment samples after bind
|
||||
+TEST_P(FramebufferTest_ES3, BindRenderbufferThenModifySamples)
|
||||
+{
|
||||
+ ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), essl1_shaders::fs::UniformColor());
|
||||
+ glUseProgram(program);
|
||||
+ GLint colorUniformLocation =
|
||||
+ glGetUniformLocation(program, angle::essl1_shaders::ColorUniform());
|
||||
+ ASSERT_NE(colorUniformLocation, -1);
|
||||
+
|
||||
+ GLFramebuffer fbo;
|
||||
+ glBindFramebuffer(GL_FRAMEBUFFER, fbo);
|
||||
+
|
||||
+ GLsizei size = 16;
|
||||
+ glViewport(0, 0, size, size);
|
||||
+
|
||||
+ GLRenderbuffer color;
|
||||
+ glBindRenderbuffer(GL_RENDERBUFFER, color);
|
||||
+
|
||||
+ glRenderbufferStorageMultisample(GL_RENDERBUFFER, 4, GL_RGBA8, size, size);
|
||||
+ glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, color);
|
||||
+ glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA8, size, size);
|
||||
+
|
||||
+ glUniform4f(colorUniformLocation, 1, 0, 0, 1);
|
||||
+ drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f);
|
||||
+
|
||||
+ EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
|
||||
+ ASSERT_GL_NO_ERROR();
|
||||
+}
|
||||
+
|
||||
+// Modify renderbuffer attachment size after bind
|
||||
+TEST_P(FramebufferTest_ES3, BindRenderbufferThenModifySize)
|
||||
+{
|
||||
+ ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Simple(), essl1_shaders::fs::UniformColor());
|
||||
+ glUseProgram(program);
|
||||
+ GLint colorUniformLocation =
|
||||
+ glGetUniformLocation(program, angle::essl1_shaders::ColorUniform());
|
||||
+ ASSERT_NE(colorUniformLocation, -1);
|
||||
+
|
||||
+ GLFramebuffer fbo;
|
||||
+ glBindFramebuffer(GL_FRAMEBUFFER, fbo);
|
||||
+
|
||||
+ GLsizei size = 16;
|
||||
+ glViewport(0, 0, size, size);
|
||||
+
|
||||
+ GLRenderbuffer color;
|
||||
+ glBindRenderbuffer(GL_RENDERBUFFER, color);
|
||||
+
|
||||
+ glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA8, size, size);
|
||||
+ glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, color);
|
||||
+ glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA8, size / 2, size * 2);
|
||||
+
|
||||
+ glUniform4f(colorUniformLocation, 1, 0, 0, 1);
|
||||
+ drawQuad(program, essl1_shaders::PositionAttrib(), 0.5f);
|
||||
+
|
||||
+ EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
|
||||
+ ASSERT_GL_NO_ERROR();
|
||||
}
|
||||
|
||||
ANGLE_INSTANTIATE_TEST_ES2(AddMockTextureNoRenderTargetTest);
|
||||
43
patches/angle/cherry-pick-cc44ae61f37b.patch
Normal file
43
patches/angle/cherry-pick-cc44ae61f37b.patch
Normal file
@@ -0,0 +1,43 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Jamie Madill <jmadill@chromium.org>
|
||||
Date: Tue, 4 Jan 2022 12:28:55 -0500
|
||||
Subject: M96: D3D11: Fix OOB access in vertex conversion code.
|
||||
|
||||
This could happen when using certain combinations of stride and
|
||||
offset. Fix the issue by using checked math.
|
||||
|
||||
Bug: chromium:1274499
|
||||
Change-Id: I3e286a30fe128ab4684ee5e172dc9e3345e3b2f4
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/3365657
|
||||
Reviewed-by: Shahbaz Youssefi <syoussefi@chromium.org>
|
||||
|
||||
diff --git a/src/libANGLE/renderer/d3d/VertexDataManager.cpp b/src/libANGLE/renderer/d3d/VertexDataManager.cpp
|
||||
index 43fcdc8de5a0d15aacf4b06e0e32df008d78f886..031a12e2b8b0e0dee91087c02cbd2f8b17435a2b 100644
|
||||
--- a/src/libANGLE/renderer/d3d/VertexDataManager.cpp
|
||||
+++ b/src/libANGLE/renderer/d3d/VertexDataManager.cpp
|
||||
@@ -58,17 +58,15 @@ int ElementsInBuffer(const gl::VertexAttribute &attrib,
|
||||
const gl::VertexBinding &binding,
|
||||
unsigned int size)
|
||||
{
|
||||
- // Size cannot be larger than a GLsizei
|
||||
- if (size > static_cast<unsigned int>(std::numeric_limits<int>::max()))
|
||||
- {
|
||||
- size = static_cast<unsigned int>(std::numeric_limits<int>::max());
|
||||
- }
|
||||
+ angle::CheckedNumeric<size_t> bufferSize(size);
|
||||
+ angle::CheckedNumeric<size_t> stride = ComputeVertexAttributeStride(attrib, binding);
|
||||
+ angle::CheckedNumeric<size_t> offset = ComputeVertexAttributeOffset(attrib, binding);
|
||||
+ angle::CheckedNumeric<size_t> elementSize = ComputeVertexAttributeTypeSize(attrib);
|
||||
+
|
||||
+ auto elementsInBuffer = (bufferSize - (offset % stride) + (stride - elementSize)) / stride;
|
||||
+ auto elementsInBufferInt = angle::CheckedNumeric<int>::cast(elementsInBuffer);
|
||||
|
||||
- GLsizei stride = static_cast<GLsizei>(ComputeVertexAttributeStride(attrib, binding));
|
||||
- GLsizei offset = static_cast<GLsizei>(ComputeVertexAttributeOffset(attrib, binding));
|
||||
- return (size - offset % stride +
|
||||
- (stride - static_cast<GLsizei>(ComputeVertexAttributeTypeSize(attrib)))) /
|
||||
- stride;
|
||||
+ return elementsInBufferInt.ValueOrDefault(0);
|
||||
}
|
||||
|
||||
// Warning: you should ensure binding really matches attrib.bindingIndex before using this function.
|
||||
@@ -0,0 +1,94 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Jamie Madill <jmadill@chromium.org>
|
||||
Date: Tue, 1 Mar 2022 15:40:38 -0500
|
||||
Subject: Vulkan: Fix issue with redefining a layered attachment.
|
||||
|
||||
The fix ensures we complete level redefinition before we get the
|
||||
layer render target in TextureVk::getAttachmentRenderTarget.
|
||||
|
||||
Bug: chromium:1296866
|
||||
Change-Id: Id7fa8e9fed5e766c30580b09336713c675c4e4f0
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/3498283
|
||||
Commit-Queue: Jamie Madill <jmadill@chromium.org>
|
||||
(cherry picked from commit 348ece42552a99cff88f79c80652b9dd3155ab22)
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/3513754
|
||||
Reviewed-by: Jamie Madill <jmadill@chromium.org>
|
||||
|
||||
diff --git a/src/libANGLE/renderer/vulkan/TextureVk.cpp b/src/libANGLE/renderer/vulkan/TextureVk.cpp
|
||||
index 610f720b68d37aaddf142b0dca538749386cef7e..569118e7137e8ea6dc02cc6247980c2198bf92db 100644
|
||||
--- a/src/libANGLE/renderer/vulkan/TextureVk.cpp
|
||||
+++ b/src/libANGLE/renderer/vulkan/TextureVk.cpp
|
||||
@@ -2174,6 +2174,15 @@ angle::Result TextureVk::getAttachmentRenderTarget(const gl::Context *context,
|
||||
|
||||
ContextVk *contextVk = vk::GetImpl(context);
|
||||
|
||||
+ if (mRedefinedLevels.any())
|
||||
+ {
|
||||
+ // If we have redefined levels, we must flush those out to fix the render targets.
|
||||
+ ANGLE_TRY(respecifyImageStorage(contextVk));
|
||||
+ }
|
||||
+
|
||||
+ // Otherwise, don't flush staged updates here. We'll handle that in FramebufferVk so we can
|
||||
+ // defer clears.
|
||||
+
|
||||
if (!mImage->valid())
|
||||
{
|
||||
// Immutable texture must already have a valid image
|
||||
@@ -2217,8 +2226,6 @@ angle::Result TextureVk::getAttachmentRenderTarget(const gl::Context *context,
|
||||
mState.getType(), samples, *mImage, useRobustInit));
|
||||
}
|
||||
|
||||
- // Don't flush staged updates here. We'll handle that in FramebufferVk so it can defer clears.
|
||||
-
|
||||
GLuint layerIndex = 0, layerCount = 0, imageLayerCount = 0;
|
||||
GetRenderTargetLayerCountAndIndex(mImage, imageIndex, &layerIndex, &layerCount,
|
||||
&imageLayerCount);
|
||||
@@ -2229,10 +2236,14 @@ angle::Result TextureVk::getAttachmentRenderTarget(const gl::Context *context,
|
||||
gl::LevelIndex(imageIndex.getLevelIndex()),
|
||||
renderToTextureIndex);
|
||||
|
||||
- ASSERT(imageIndex.getLevelIndex() <
|
||||
- static_cast<int32_t>(mSingleLayerRenderTargets[renderToTextureIndex].size()));
|
||||
- *rtOut = &mSingleLayerRenderTargets[renderToTextureIndex][imageIndex.getLevelIndex()]
|
||||
- [layerIndex];
|
||||
+ std::vector<RenderTargetVector> &levelRenderTargets =
|
||||
+ mSingleLayerRenderTargets[renderToTextureIndex];
|
||||
+ ASSERT(imageIndex.getLevelIndex() < static_cast<int32_t>(levelRenderTargets.size()));
|
||||
+
|
||||
+ RenderTargetVector &layerRenderTargets = levelRenderTargets[imageIndex.getLevelIndex()];
|
||||
+ ASSERT(imageIndex.getLayerIndex() < static_cast<int32_t>(layerRenderTargets.size()));
|
||||
+
|
||||
+ *rtOut = &layerRenderTargets[layerIndex];
|
||||
}
|
||||
else
|
||||
{
|
||||
diff --git a/src/tests/gl_tests/FramebufferTest.cpp b/src/tests/gl_tests/FramebufferTest.cpp
|
||||
index cd733be3ae5c179860d882e305ec84d093a283ed..c0b745978ae5d28d97bb833f7fe6278872d8d620 100644
|
||||
--- a/src/tests/gl_tests/FramebufferTest.cpp
|
||||
+++ b/src/tests/gl_tests/FramebufferTest.cpp
|
||||
@@ -3427,6 +3427,25 @@ TEST_P(FramebufferTest_ES3, BindRenderbufferThenModifySize)
|
||||
ASSERT_GL_NO_ERROR();
|
||||
}
|
||||
|
||||
+// Tests redefining a layered framebuffer attachment.
|
||||
+TEST_P(FramebufferTest_ES3, RedefineLayerAttachment)
|
||||
+{
|
||||
+ GLTexture texture;
|
||||
+ glBindTexture(GL_TEXTURE_3D, texture);
|
||||
+ std::vector<uint8_t> imgData(20480, 0);
|
||||
+ glTexImage3D(GL_TEXTURE_3D, 0, GL_R8, 8, 8, 8, 0, GL_RED, GL_UNSIGNED_BYTE, imgData.data());
|
||||
+
|
||||
+ GLFramebuffer fbo;
|
||||
+ glBindFramebuffer(GL_FRAMEBUFFER, fbo);
|
||||
+ glFramebufferTextureLayer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, texture, 0, 8);
|
||||
+ glGenerateMipmap(GL_TEXTURE_3D);
|
||||
+
|
||||
+ glTexImage3D(GL_TEXTURE_3D, 0, GL_R8UI, 16, 16, 16, 0, GL_RED_INTEGER, GL_UNSIGNED_BYTE,
|
||||
+ imgData.data());
|
||||
+ glCopyTexSubImage3D(GL_TEXTURE_3D, 0, 0, 0, 2, 2, 15, 16, 16);
|
||||
+ ASSERT_GL_NO_ERROR();
|
||||
+}
|
||||
+
|
||||
ANGLE_INSTANTIATE_TEST_ES2(AddMockTextureNoRenderTargetTest);
|
||||
ANGLE_INSTANTIATE_TEST_ES2(FramebufferTest);
|
||||
ANGLE_INSTANTIATE_TEST_ES2_AND_ES3(FramebufferFormatsTest);
|
||||
115
patches/angle/m96_validate_samplerformat.patch
Normal file
115
patches/angle/m96_validate_samplerformat.patch
Normal file
@@ -0,0 +1,115 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Lingfeng Yang <lfy@google.com>
|
||||
Date: Wed, 1 Dec 2021 17:08:01 -0800
|
||||
Subject: M96: Validate SamplerFormat
|
||||
|
||||
We weren't validating sampler formats in ProgramExecutable validation.
|
||||
|
||||
Bug: chromium:1273661
|
||||
Change-Id: Ida0c67c0c7169ea3f47ceb2d433bee17012a7e5e
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/3312717
|
||||
Reviewed-by: Charlie Lao <cclao@google.com>
|
||||
Reviewed-by: Jamie Madill <jmadill@chromium.org>
|
||||
Commit-Queue: Lingfeng Yang <lfy@google.com>
|
||||
(cherry picked from commit 6d3435fddd7abd67699c3f020d6b4fa21445d9b3)
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/3335173
|
||||
Reviewed-by: Shahbaz Youssefi <syoussefi@chromium.org>
|
||||
|
||||
diff --git a/src/libANGLE/ProgramExecutable.cpp b/src/libANGLE/ProgramExecutable.cpp
|
||||
index baf63ecec6f82fda9dd79a1c398b8e95ec70e321..14e5abdfab36a95f39839fc171e6e0bc3a5dc6e9 100644
|
||||
--- a/src/libANGLE/ProgramExecutable.cpp
|
||||
+++ b/src/libANGLE/ProgramExecutable.cpp
|
||||
@@ -1132,6 +1132,19 @@ bool ProgramExecutable::validateSamplersImpl(InfoLog *infoLog, const Caps &caps)
|
||||
mCachedValidateSamplersResult = false;
|
||||
return false;
|
||||
}
|
||||
+
|
||||
+ if (mActiveSamplerFormats[textureUnit] == SamplerFormat::InvalidEnum)
|
||||
+ {
|
||||
+ if (infoLog)
|
||||
+ {
|
||||
+ (*infoLog) << "Samplers of conflicting formats refer to the same texture "
|
||||
+ "image unit ("
|
||||
+ << textureUnit << ").";
|
||||
+ }
|
||||
+
|
||||
+ mCachedValidateSamplersResult = false;
|
||||
+ return false;
|
||||
+ }
|
||||
}
|
||||
|
||||
mCachedValidateSamplersResult = true;
|
||||
diff --git a/src/tests/gl_tests/TextureTest.cpp b/src/tests/gl_tests/TextureTest.cpp
|
||||
index ba512a11cb023d9caae666ab2634d1e66057d12c..56bef0186234f59d370669c21f588ea9c5c356fc 100644
|
||||
--- a/src/tests/gl_tests/TextureTest.cpp
|
||||
+++ b/src/tests/gl_tests/TextureTest.cpp
|
||||
@@ -9796,8 +9796,6 @@ class TextureChangeStorageUploadTest : public ANGLETest
|
||||
FAIL() << "shader compilation failed.";
|
||||
}
|
||||
|
||||
- mColorLocation = glGetUniformLocation(mProgram, essl1_shaders::ColorUniform());
|
||||
-
|
||||
glUseProgram(mProgram);
|
||||
|
||||
glClearColor(0, 0, 0, 0);
|
||||
@@ -9842,6 +9840,53 @@ TEST_P(TextureChangeStorageUploadTest, Basic)
|
||||
EXPECT_GL_NO_ERROR();
|
||||
}
|
||||
|
||||
+class ExtraSamplerCubeShadowUseTest : public ANGLETest
|
||||
+{
|
||||
+ protected:
|
||||
+ ExtraSamplerCubeShadowUseTest() : ANGLETest() {}
|
||||
+
|
||||
+ const char *getVertexShaderSource() { return "#version 300 es\nvoid main() {}"; }
|
||||
+
|
||||
+ const char *getFragmentShaderSource()
|
||||
+ {
|
||||
+ return R"(#version 300 es
|
||||
+precision mediump float;
|
||||
+
|
||||
+uniform mediump samplerCube var_0002; // this has to be there
|
||||
+uniform highp samplerCubeShadow var_0004; // this has to be a cube shadow sampler
|
||||
+out vec4 color;
|
||||
+void main() {
|
||||
+
|
||||
+ vec4 var_0031 = texture(var_0002, vec3(1,1,1));
|
||||
+ ivec2 size = textureSize(var_0004, 0) ;
|
||||
+ var_0031.x += float(size.y);
|
||||
+
|
||||
+ color = var_0031;
|
||||
+})";
|
||||
+ }
|
||||
+
|
||||
+ void testSetUp() override
|
||||
+ {
|
||||
+ mProgram = CompileProgram(getVertexShaderSource(), getFragmentShaderSource());
|
||||
+ if (mProgram == 0)
|
||||
+ {
|
||||
+ FAIL() << "shader compilation failed.";
|
||||
+ }
|
||||
+ glUseProgram(mProgram);
|
||||
+ ASSERT_GL_NO_ERROR();
|
||||
+ }
|
||||
+
|
||||
+ void testTearDown() override { glDeleteProgram(mProgram); }
|
||||
+
|
||||
+ GLuint mProgram;
|
||||
+};
|
||||
+
|
||||
+TEST_P(ExtraSamplerCubeShadowUseTest, Basic)
|
||||
+{
|
||||
+ glDrawArrays(GL_TRIANGLE_FAN, 0, 3);
|
||||
+ EXPECT_GL_ERROR(GL_INVALID_OPERATION);
|
||||
+}
|
||||
+
|
||||
// Use this to select which configurations (e.g. which renderer, which GLES major version) these
|
||||
// tests should be run against.
|
||||
#define ES2_EMULATE_COPY_TEX_IMAGE() \
|
||||
@@ -9957,4 +10002,6 @@ ANGLE_INSTANTIATE_TEST_ES31_AND(CopyImageTestES31, WithDirectSPIRVGeneration(ES3
|
||||
|
||||
ANGLE_INSTANTIATE_TEST_ES3(TextureChangeStorageUploadTest);
|
||||
|
||||
+ANGLE_INSTANTIATE_TEST_ES3(ExtraSamplerCubeShadowUseTest);
|
||||
+
|
||||
} // anonymous namespace
|
||||
@@ -0,0 +1,109 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Jamie Madill <jmadill@chromium.org>
|
||||
Date: Tue, 1 Mar 2022 16:14:47 -0500
|
||||
Subject: Protect against deleting a current XFB buffer.
|
||||
|
||||
Bug: chromium:1295411
|
||||
Change-Id: I097f272c38e444e0af71aa55c0dc508a07aa0bd3
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/3498262
|
||||
Reviewed-by: Amirali Abdolrashidi <abdolrashidi@google.com>
|
||||
Reviewed-by: Geoff Lang <geofflang@chromium.org>
|
||||
Commit-Queue: Jamie Madill <jmadill@chromium.org>
|
||||
(cherry picked from commit d9002eef2a5f27fc5d6b65d01d02afcfb9a35db1)
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/3514175
|
||||
Reviewed-by: Ian Elliott <ianelliott@google.com>
|
||||
|
||||
diff --git a/src/libANGLE/State.cpp b/src/libANGLE/State.cpp
|
||||
index 8ec1eca3f4bc70da39c838a0f81664043276bc80..182709c348f7490e1ee990a05570c13d7e9d0dd7 100644
|
||||
--- a/src/libANGLE/State.cpp
|
||||
+++ b/src/libANGLE/State.cpp
|
||||
@@ -2115,6 +2115,10 @@ angle::Result State::detachBuffer(Context *context, const Buffer *buffer)
|
||||
if (curTransformFeedback)
|
||||
{
|
||||
ANGLE_TRY(curTransformFeedback->detachBuffer(context, bufferID));
|
||||
+ if (isTransformFeedbackActiveUnpaused())
|
||||
+ {
|
||||
+ context->getStateCache().onActiveTransformFeedbackChange(context);
|
||||
+ }
|
||||
}
|
||||
|
||||
if (getVertexArray()->detachBuffer(context, bufferID))
|
||||
diff --git a/src/libANGLE/validationES.cpp b/src/libANGLE/validationES.cpp
|
||||
index 4c1ec1fc73746e2aba97ea83da5e8bcbd0b41ba5..d5732741dff989b8b8f6f669511bf7bc001c4eaa 100644
|
||||
--- a/src/libANGLE/validationES.cpp
|
||||
+++ b/src/libANGLE/validationES.cpp
|
||||
@@ -3948,6 +3948,14 @@ const char *ValidateDrawStates(const Context *context)
|
||||
return kTessellationShaderRequiresBothControlAndEvaluation;
|
||||
}
|
||||
}
|
||||
+
|
||||
+ if (state.isTransformFeedbackActiveUnpaused())
|
||||
+ {
|
||||
+ if (!ValidateProgramExecutableXFBBuffersPresent(context, executable))
|
||||
+ {
|
||||
+ return kTransformFeedbackBufferMissing;
|
||||
+ }
|
||||
+ }
|
||||
}
|
||||
|
||||
if (programIsYUVOutput != framebufferIsYUV)
|
||||
@@ -8055,4 +8063,21 @@ bool ValidateInvalidateTextureANGLE(const Context *context, TextureType target)
|
||||
return true;
|
||||
}
|
||||
|
||||
+bool ValidateProgramExecutableXFBBuffersPresent(const Context *context,
|
||||
+ const ProgramExecutable *programExecutable)
|
||||
+{
|
||||
+ size_t programXfbCount = programExecutable->getTransformFeedbackBufferCount();
|
||||
+ const TransformFeedback *transformFeedback = context->getState().getCurrentTransformFeedback();
|
||||
+ for (size_t programXfbIndex = 0; programXfbIndex < programXfbCount; ++programXfbIndex)
|
||||
+ {
|
||||
+ const OffsetBindingPointer<Buffer> &buffer =
|
||||
+ transformFeedback->getIndexedBuffer(programXfbIndex);
|
||||
+ if (!buffer.get())
|
||||
+ {
|
||||
+ return false;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ return true;
|
||||
+}
|
||||
} // namespace gl
|
||||
diff --git a/src/libANGLE/validationES.h b/src/libANGLE/validationES.h
|
||||
index f7daadb3de4d0a28f1896bad54bdc59f31a45cd3..934a35f6557462fd8da52fd7de7aba0ee5186dff 100644
|
||||
--- a/src/libANGLE/validationES.h
|
||||
+++ b/src/libANGLE/validationES.h
|
||||
@@ -755,6 +755,9 @@ bool ValidateGetMultisamplefvBase(const Context *context,
|
||||
const GLfloat *val);
|
||||
bool ValidateSampleMaskiBase(const Context *context, GLuint maskNumber, GLbitfield mask);
|
||||
|
||||
+bool ValidateProgramExecutableXFBBuffersPresent(const Context *context,
|
||||
+ const ProgramExecutable *programExecutable);
|
||||
+
|
||||
// We should check with Khronos if returning INVALID_FRAMEBUFFER_OPERATION is OK when querying
|
||||
// implementation format info for incomplete framebuffers. It seems like these queries are
|
||||
// incongruent with the other errors.
|
||||
diff --git a/src/libANGLE/validationES3.cpp b/src/libANGLE/validationES3.cpp
|
||||
index f385ef623cc56658dc5f840ddd3f3c3bf9bf3e05..1523cd5f0093b7b4b03bf0cd5432ee0a15f17dab 100644
|
||||
--- a/src/libANGLE/validationES3.cpp
|
||||
+++ b/src/libANGLE/validationES3.cpp
|
||||
@@ -2786,16 +2786,10 @@ bool ValidateBeginTransformFeedback(const Context *context, PrimitiveMode primit
|
||||
return false;
|
||||
}
|
||||
|
||||
- size_t programXfbCount = programExecutable->getTransformFeedbackBufferCount();
|
||||
- for (size_t programXfbIndex = 0; programXfbIndex < programXfbCount; ++programXfbIndex)
|
||||
+ if (!ValidateProgramExecutableXFBBuffersPresent(context, programExecutable))
|
||||
{
|
||||
- const OffsetBindingPointer<Buffer> &buffer =
|
||||
- transformFeedback->getIndexedBuffer(programXfbIndex);
|
||||
- if (!buffer.get())
|
||||
- {
|
||||
- context->validationError(GL_INVALID_OPERATION, kTransformFeedbackBufferMissing);
|
||||
- return false;
|
||||
- }
|
||||
+ context->validationError(GL_INVALID_OPERATION, kTransformFeedbackBufferMissing);
|
||||
+ return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
112
patches/angle/m98_vulkan_fix_vkcmdresolveimage_extents.patch
Normal file
112
patches/angle/m98_vulkan_fix_vkcmdresolveimage_extents.patch
Normal file
@@ -0,0 +1,112 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Shahbaz Youssefi <syoussefi@chromium.org>
|
||||
Date: Mon, 31 Jan 2022 12:07:43 -0500
|
||||
Subject: M98: Vulkan: Fix vkCmdResolveImage extents
|
||||
|
||||
The source framebuffer's extents were accidentally used instead of the
|
||||
blit area extents.
|
||||
|
||||
Bug: chromium:1288020
|
||||
Change-Id: I5c6128a191deeea2f972dc7f010be9d40c674ce6
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/3457022
|
||||
Reviewed-by: Tim Van Patten <timvp@google.com>
|
||||
|
||||
diff --git a/src/libANGLE/renderer/vulkan/FramebufferVk.cpp b/src/libANGLE/renderer/vulkan/FramebufferVk.cpp
|
||||
index 4f7428217a130482dbbee760d32f183cee2255f6..ac4c4086c28be29a65386ef06cc103d14dfb0d48 100644
|
||||
--- a/src/libANGLE/renderer/vulkan/FramebufferVk.cpp
|
||||
+++ b/src/libANGLE/renderer/vulkan/FramebufferVk.cpp
|
||||
@@ -1459,8 +1459,8 @@ angle::Result FramebufferVk::resolveColorWithCommand(ContextVk *contextVk,
|
||||
resolveRegion.dstOffset.x = params.destOffset[0];
|
||||
resolveRegion.dstOffset.y = params.destOffset[1];
|
||||
resolveRegion.dstOffset.z = 0;
|
||||
- resolveRegion.extent.width = params.srcExtents[0];
|
||||
- resolveRegion.extent.height = params.srcExtents[1];
|
||||
+ resolveRegion.extent.width = params.blitArea.width;
|
||||
+ resolveRegion.extent.height = params.blitArea.height;
|
||||
resolveRegion.extent.depth = 1;
|
||||
|
||||
vk::PerfCounters &perfCounters = contextVk->getPerfCounters();
|
||||
diff --git a/src/tests/angle_end2end_tests_expectations.txt b/src/tests/angle_end2end_tests_expectations.txt
|
||||
index 5712456966c3a77ba73295c083888ad0ab821a78..b9a0423345ba3a19e425a0b7ba7985ca191fdae7 100644
|
||||
--- a/src/tests/angle_end2end_tests_expectations.txt
|
||||
+++ b/src/tests/angle_end2end_tests_expectations.txt
|
||||
@@ -70,6 +70,7 @@
|
||||
// the test says. The test also fails on Intel/Vulkan/Windows.
|
||||
6068 INTEL VULKAN : MultiviewRenderPrimitiveTest.LineLoop/* = SKIP
|
||||
6068 INTEL VULKAN : MultiviewRenderPrimitiveTest.LineStrip/* = SKIP
|
||||
+6962 WIN INTEL VULKAN : BlitFramebufferTestES31.PartialResolve/* = SKIP
|
||||
|
||||
// Mac
|
||||
6025 MAC AMD OPENGL : IndexBufferOffsetTestES3.UseAsUBOThenUpdateThenUInt8Index/* = SKIP
|
||||
diff --git a/src/tests/gl_tests/BlitFramebufferANGLETest.cpp b/src/tests/gl_tests/BlitFramebufferANGLETest.cpp
|
||||
index affed96be99a8e0b819919ce971968168c546ca1..22356a7c65339fe8b1e601f54a3491ea77237432 100644
|
||||
--- a/src/tests/gl_tests/BlitFramebufferANGLETest.cpp
|
||||
+++ b/src/tests/gl_tests/BlitFramebufferANGLETest.cpp
|
||||
@@ -2637,6 +2637,67 @@ TEST_P(BlitFramebufferTest, BlitDepthStencilPixelByPixel)
|
||||
EXPECT_PIXEL_RECT_EQ(64, 0, 128, 1, GLColor::blue);
|
||||
}
|
||||
|
||||
+// Regression test for a bug in the Vulkan backend where vkCmdResolveImage was using the src extents
|
||||
+// as the resolve area instead of the area passed to glBlitFramebuffer.
|
||||
+TEST_P(BlitFramebufferTestES31, PartialResolve)
|
||||
+{
|
||||
+ constexpr GLint kWidth = 16;
|
||||
+ constexpr GLint kHeight = 32;
|
||||
+
|
||||
+ // Read framebuffer is multisampled.
|
||||
+ GLTexture readTexture;
|
||||
+ glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, readTexture);
|
||||
+ glTexStorage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, 4, GL_RGBA8, kWidth, kHeight, GL_TRUE);
|
||||
+
|
||||
+ GLFramebuffer readFbo;
|
||||
+ glBindFramebuffer(GL_FRAMEBUFFER, readFbo);
|
||||
+ glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D_MULTISAMPLE,
|
||||
+ readTexture, 0);
|
||||
+ ASSERT_GL_NO_ERROR();
|
||||
+ ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
|
||||
+
|
||||
+ glClearColor(1, 0, 0, 1);
|
||||
+ glClear(GL_COLOR_BUFFER_BIT);
|
||||
+
|
||||
+ // Draw framebuffer is single sampled. It's bound to a texture with base level the same size as
|
||||
+ // the read framebuffer, but it's bound to mip 1.
|
||||
+ GLTexture drawTexture;
|
||||
+ glBindTexture(GL_TEXTURE_2D, drawTexture);
|
||||
+ glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, kWidth, kHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE,
|
||||
+ nullptr);
|
||||
+ glGenerateMipmap(GL_TEXTURE_2D);
|
||||
+
|
||||
+ GLFramebuffer drawFbo;
|
||||
+ glBindFramebuffer(GL_FRAMEBUFFER, drawFbo);
|
||||
+ glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, drawTexture, 1);
|
||||
+ ASSERT_GL_NO_ERROR();
|
||||
+ ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
|
||||
+
|
||||
+ glClearColor(0, 1, 0, 1);
|
||||
+ glClear(GL_COLOR_BUFFER_BIT);
|
||||
+ EXPECT_PIXEL_RECT_EQ(0, 0, kWidth / 2, kHeight / 2, GLColor::green);
|
||||
+
|
||||
+ constexpr GLint kResolveX0 = 1;
|
||||
+ constexpr GLint kResolveY0 = 2;
|
||||
+ constexpr GLint kResolveX1 = 4;
|
||||
+ constexpr GLint kResolveY1 = 6;
|
||||
+
|
||||
+ // Resolve only a portion of the read framebuffer.
|
||||
+ glBindFramebuffer(GL_READ_FRAMEBUFFER, readFbo);
|
||||
+ glBlitFramebuffer(kResolveX0, kResolveY0, kResolveX1, kResolveY1, kResolveX0, kResolveY0,
|
||||
+ kResolveX1, kResolveY1, GL_COLOR_BUFFER_BIT, GL_NEAREST);
|
||||
+ ASSERT_GL_NO_ERROR();
|
||||
+
|
||||
+ glBindFramebuffer(GL_READ_FRAMEBUFFER, drawFbo);
|
||||
+ EXPECT_PIXEL_RECT_EQ(0, 0, kWidth / 2, kResolveY0, GLColor::green);
|
||||
+ EXPECT_PIXEL_RECT_EQ(0, 0, kResolveX0, kHeight / 2, GLColor::green);
|
||||
+ EXPECT_PIXEL_RECT_EQ(kResolveX1, 0, kWidth / 2 - kResolveX1, kHeight / 2, GLColor::green);
|
||||
+ EXPECT_PIXEL_RECT_EQ(0, kResolveY1, kWidth / 2, kHeight / 2 - kResolveY1, GLColor::green);
|
||||
+
|
||||
+ EXPECT_PIXEL_RECT_EQ(kResolveX0, kResolveY0, kResolveX1 - kResolveX0, kResolveY1 - kResolveY0,
|
||||
+ GLColor::red);
|
||||
+}
|
||||
+
|
||||
// Test that a draw call to a small FBO followed by a resolve of a large FBO works.
|
||||
TEST_P(BlitFramebufferTestES31, DrawToSmallFBOThenResolveLargeFBO)
|
||||
{
|
||||
109
patches/angle/m98_vulkan_fix_vkcmdresolveimage_offsets.patch
Normal file
109
patches/angle/m98_vulkan_fix_vkcmdresolveimage_offsets.patch
Normal file
@@ -0,0 +1,109 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Shahbaz Youssefi <syoussefi@chromium.org>
|
||||
Date: Mon, 7 Feb 2022 13:46:46 -0500
|
||||
Subject: M98: Vulkan: Fix vkCmdResolveImage offsets
|
||||
|
||||
glBlitFramebuffer takes identical regions for src and dst when
|
||||
resolving. vkCmdResolveImage should use the clipped area instead of
|
||||
using the actual offsets passed to this function.
|
||||
|
||||
Bug: chromium:1292537
|
||||
Change-Id: If283a8acbca3249b771facbc30bd9f8080a03656
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/3457023
|
||||
Reviewed-by: Tim Van Patten <timvp@google.com>
|
||||
|
||||
diff --git a/src/libANGLE/renderer/vulkan/FramebufferVk.cpp b/src/libANGLE/renderer/vulkan/FramebufferVk.cpp
|
||||
index ac4c4086c28be29a65386ef06cc103d14dfb0d48..45308e0261b48eed17d144169b698165b04422f9 100644
|
||||
--- a/src/libANGLE/renderer/vulkan/FramebufferVk.cpp
|
||||
+++ b/src/libANGLE/renderer/vulkan/FramebufferVk.cpp
|
||||
@@ -1451,13 +1451,13 @@ angle::Result FramebufferVk::resolveColorWithCommand(ContextVk *contextVk,
|
||||
resolveRegion.srcSubresource.mipLevel = 0;
|
||||
resolveRegion.srcSubresource.baseArrayLayer = params.srcLayer;
|
||||
resolveRegion.srcSubresource.layerCount = 1;
|
||||
- resolveRegion.srcOffset.x = params.srcOffset[0];
|
||||
- resolveRegion.srcOffset.y = params.srcOffset[1];
|
||||
+ resolveRegion.srcOffset.x = params.blitArea.x;
|
||||
+ resolveRegion.srcOffset.y = params.blitArea.y;
|
||||
resolveRegion.srcOffset.z = 0;
|
||||
resolveRegion.dstSubresource.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT;
|
||||
resolveRegion.dstSubresource.layerCount = 1;
|
||||
- resolveRegion.dstOffset.x = params.destOffset[0];
|
||||
- resolveRegion.dstOffset.y = params.destOffset[1];
|
||||
+ resolveRegion.dstOffset.x = params.blitArea.x;
|
||||
+ resolveRegion.dstOffset.y = params.blitArea.y;
|
||||
resolveRegion.dstOffset.z = 0;
|
||||
resolveRegion.extent.width = params.blitArea.width;
|
||||
resolveRegion.extent.height = params.blitArea.height;
|
||||
diff --git a/src/tests/angle_end2end_tests_expectations.txt b/src/tests/angle_end2end_tests_expectations.txt
|
||||
index b9a0423345ba3a19e425a0b7ba7985ca191fdae7..0646a12afacc16fd7df938e615976a28b6da6ab0 100644
|
||||
--- a/src/tests/angle_end2end_tests_expectations.txt
|
||||
+++ b/src/tests/angle_end2end_tests_expectations.txt
|
||||
@@ -15,6 +15,8 @@
|
||||
6142 VULKAN : BlitFramebufferTest.BlitDepthStencilPixelByPixel/* = SKIP
|
||||
6153 VULKAN WIN INTEL : GLSLTest_ES31.StructAndArrayEqualOperator/ES3_1_Vulkan_DirectSPIRVGen = SKIP
|
||||
6153 VULKAN PIXEL4ORXL : GLSLTest_ES31.StructAndArrayEqualOperator/ES3_1_Vulkan_DirectSPIRVGen = SKIP
|
||||
+6989 OPENGL : BlitFramebufferTestES31.OOBResolve/* = SKIP
|
||||
+6989 GLES : BlitFramebufferTestES31.OOBResolve/* = SKIP
|
||||
|
||||
// Direct SPIR-V generation. The following tests pass on some platforms but not others. Need to investigate.
|
||||
4889 VULKAN : GeometryShaderTest.LayeredFramebufferPreRenderClear2DArrayColor/ES3_1_Vulkan_DirectSPIRVGen = SKIP
|
||||
diff --git a/src/tests/gl_tests/BlitFramebufferANGLETest.cpp b/src/tests/gl_tests/BlitFramebufferANGLETest.cpp
|
||||
index 22356a7c65339fe8b1e601f54a3491ea77237432..697cfcc8e10db571a407c0e44da36583614f2cb8 100644
|
||||
--- a/src/tests/gl_tests/BlitFramebufferANGLETest.cpp
|
||||
+++ b/src/tests/gl_tests/BlitFramebufferANGLETest.cpp
|
||||
@@ -2637,6 +2637,55 @@ TEST_P(BlitFramebufferTest, BlitDepthStencilPixelByPixel)
|
||||
EXPECT_PIXEL_RECT_EQ(64, 0, 128, 1, GLColor::blue);
|
||||
}
|
||||
|
||||
+// Regression test for a bug in the Vulkan backend where vkCmdResolveImage was used with
|
||||
+// out-of-bounds regions.
|
||||
+TEST_P(BlitFramebufferTestES31, OOBResolve)
|
||||
+{
|
||||
+ constexpr GLint kWidth = 16;
|
||||
+ constexpr GLint kHeight = 32;
|
||||
+
|
||||
+ // Read framebuffer is multisampled.
|
||||
+ GLTexture readTexture;
|
||||
+ glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, readTexture);
|
||||
+ glTexStorage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, 4, GL_RGBA8, kWidth, kHeight, GL_TRUE);
|
||||
+
|
||||
+ GLFramebuffer readFbo;
|
||||
+ glBindFramebuffer(GL_FRAMEBUFFER, readFbo);
|
||||
+ glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D_MULTISAMPLE,
|
||||
+ readTexture, 0);
|
||||
+ ASSERT_GL_NO_ERROR();
|
||||
+ ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
|
||||
+
|
||||
+ glClearColor(1, 0, 0, 1);
|
||||
+ glClear(GL_COLOR_BUFFER_BIT);
|
||||
+
|
||||
+ // Draw framebuffer is single sampled.
|
||||
+ GLTexture drawTexture;
|
||||
+ glBindTexture(GL_TEXTURE_2D, drawTexture);
|
||||
+ glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, kWidth, kHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE,
|
||||
+ nullptr);
|
||||
+ glGenerateMipmap(GL_TEXTURE_2D);
|
||||
+
|
||||
+ GLFramebuffer drawFbo;
|
||||
+ glBindFramebuffer(GL_FRAMEBUFFER, drawFbo);
|
||||
+ glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, drawTexture, 0);
|
||||
+ ASSERT_GL_NO_ERROR();
|
||||
+ ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
|
||||
+
|
||||
+ glClearColor(0, 1, 0, 1);
|
||||
+ glClear(GL_COLOR_BUFFER_BIT);
|
||||
+ EXPECT_PIXEL_RECT_EQ(0, 0, kWidth, kHeight, GLColor::green);
|
||||
+
|
||||
+ // Resolve the read framebuffer, using bounds that are outside the size of the image.
|
||||
+ glBindFramebuffer(GL_READ_FRAMEBUFFER, readFbo);
|
||||
+ glBlitFramebuffer(-kWidth * 2, -kHeight * 3, kWidth * 11, kHeight * 8, -kWidth * 2,
|
||||
+ -kHeight * 3, kWidth * 11, kHeight * 8, GL_COLOR_BUFFER_BIT, GL_NEAREST);
|
||||
+ ASSERT_GL_NO_ERROR();
|
||||
+
|
||||
+ glBindFramebuffer(GL_READ_FRAMEBUFFER, drawFbo);
|
||||
+ EXPECT_PIXEL_RECT_EQ(0, 0, kWidth, kHeight, GLColor::red);
|
||||
+}
|
||||
+
|
||||
// Regression test for a bug in the Vulkan backend where vkCmdResolveImage was using the src extents
|
||||
// as the resolve area instead of the area passed to glBlitFramebuffer.
|
||||
TEST_P(BlitFramebufferTestES31, PartialResolve)
|
||||
@@ -0,0 +1,303 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Roman Lavrov <romanl@google.com>
|
||||
Date: Tue, 18 Jan 2022 20:05:55 +0000
|
||||
Subject: M99: Vulkan: Prevent out of bounds read in divisor emulation path.
|
||||
|
||||
Split the replicated part of StreamVertexData out to
|
||||
StreamVertexDataWithDivisor, there is only a partial argument
|
||||
overlap between the two.
|
||||
|
||||
Bug: chromium:1285885
|
||||
Change-Id: Ibf6ab3efc6b12b430b1d391c6ae61bd9668b4407
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/3398816
|
||||
Reviewed-by: Jamie Madill <jmadill@chromium.org>
|
||||
Reviewed-by: Shahbaz Youssefi <syoussefi@chromium.org>
|
||||
Commit-Queue: Roman Lavrov <romanl@google.com>
|
||||
(cherry picked from commit 5f0badf4541ba52659c937cfe9190d3735a76c10)
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/3461414
|
||||
|
||||
diff --git a/src/libANGLE/renderer/vulkan/VertexArrayVk.cpp b/src/libANGLE/renderer/vulkan/VertexArrayVk.cpp
|
||||
index ed416508cab06797a8c4d52e7ab982d538f57e3c..1ca486af3ff004e11aea82c391b4c504b569096c 100644
|
||||
--- a/src/libANGLE/renderer/vulkan/VertexArrayVk.cpp
|
||||
+++ b/src/libANGLE/renderer/vulkan/VertexArrayVk.cpp
|
||||
@@ -81,34 +81,62 @@ angle::Result StreamVertexData(ContextVk *contextVk,
|
||||
size_t destOffset,
|
||||
size_t vertexCount,
|
||||
size_t sourceStride,
|
||||
- size_t destStride,
|
||||
VertexCopyFunction vertexLoadFunction,
|
||||
vk::BufferHelper **bufferOut,
|
||||
- VkDeviceSize *bufferOffsetOut,
|
||||
- uint32_t replicateCount)
|
||||
+ VkDeviceSize *bufferOffsetOut)
|
||||
{
|
||||
uint8_t *dst = nullptr;
|
||||
ANGLE_TRY(dynamicBuffer->allocate(contextVk, bytesToAllocate, &dst, nullptr, bufferOffsetOut,
|
||||
nullptr));
|
||||
*bufferOut = dynamicBuffer->getCurrentBuffer();
|
||||
dst += destOffset;
|
||||
- if (replicateCount == 1)
|
||||
+ vertexLoadFunction(sourceData, sourceStride, vertexCount, dst);
|
||||
+
|
||||
+ ANGLE_TRY(dynamicBuffer->flush(contextVk));
|
||||
+ return angle::Result::Continue;
|
||||
+}
|
||||
+
|
||||
+angle::Result StreamVertexDataWithDivisor(ContextVk *contextVk,
|
||||
+ vk::DynamicBuffer *dynamicBuffer,
|
||||
+ const uint8_t *sourceData,
|
||||
+ size_t bytesToAllocate,
|
||||
+ size_t sourceStride,
|
||||
+ size_t destStride,
|
||||
+ VertexCopyFunction vertexLoadFunction,
|
||||
+ vk::BufferHelper **bufferOut,
|
||||
+ VkDeviceSize *bufferOffsetOut,
|
||||
+ uint32_t divisor,
|
||||
+ size_t numSrcVertices)
|
||||
+{
|
||||
+ uint8_t *dst = nullptr;
|
||||
+ ANGLE_TRY(dynamicBuffer->allocate(contextVk, bytesToAllocate, &dst, nullptr, bufferOffsetOut,
|
||||
+ nullptr));
|
||||
+ *bufferOut = dynamicBuffer->getCurrentBuffer();
|
||||
+
|
||||
+ // Each source vertex is used `divisor` times before advancing. Clamp to avoid OOB reads.
|
||||
+ size_t clampedSize = std::min(numSrcVertices * destStride * divisor, bytesToAllocate);
|
||||
+
|
||||
+ ASSERT(clampedSize % destStride == 0);
|
||||
+ ASSERT(divisor > 0);
|
||||
+
|
||||
+ uint32_t sourceVertexUseCount = 0;
|
||||
+ for (size_t dataCopied = 0; dataCopied < clampedSize; dataCopied += destStride, dst += destStride)
|
||||
{
|
||||
- vertexLoadFunction(sourceData, sourceStride, vertexCount, dst);
|
||||
+ vertexLoadFunction(sourceData, sourceStride, 1, dst);
|
||||
+ sourceVertexUseCount++;
|
||||
+ if (sourceVertexUseCount == divisor)
|
||||
+ {
|
||||
+ sourceData += sourceStride;
|
||||
+ sourceVertexUseCount = 0;
|
||||
+ }
|
||||
}
|
||||
- else
|
||||
+
|
||||
+ // Satisfy robustness constraints (only if extension enabled)
|
||||
+ if (contextVk->getExtensions().robustness)
|
||||
{
|
||||
- ASSERT(replicateCount > 1);
|
||||
- uint32_t sourceRemainingCount = replicateCount - 1;
|
||||
- for (size_t dataCopied = 0; dataCopied < bytesToAllocate;
|
||||
- dataCopied += destStride, dst += destStride, sourceRemainingCount--)
|
||||
+ if (clampedSize < bytesToAllocate)
|
||||
{
|
||||
- vertexLoadFunction(sourceData, sourceStride, 1, dst);
|
||||
- if (sourceRemainingCount == 0)
|
||||
- {
|
||||
- sourceData += sourceStride;
|
||||
- sourceRemainingCount = replicateCount;
|
||||
- }
|
||||
+ memset(dst + clampedSize, 0, bytesToAllocate - clampedSize);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -124,6 +152,7 @@ size_t GetVertexCount(BufferVk *srcBuffer, const gl::VertexBinding &binding, uin
|
||||
return 0;
|
||||
|
||||
// Count the last vertex. It may occupy less than a full stride.
|
||||
+ // This is also correct if stride happens to be less than srcFormatSize.
|
||||
size_t numVertices = 1;
|
||||
bytes -= srcFormatSize;
|
||||
|
||||
@@ -452,8 +481,8 @@ angle::Result VertexArrayVk::convertVertexBufferCPU(ContextVk *contextVk,
|
||||
ASSERT(GetVertexInputAlignment(vertexFormat, compressed) <= vk::kVertexBufferAlignment);
|
||||
ANGLE_TRY(StreamVertexData(
|
||||
contextVk, &conversion->data, srcBytes, numVertices * dstFormatSize, 0, numVertices,
|
||||
- binding.getStride(), srcFormatSize, vertexFormat.getVertexLoadFunction(compressed),
|
||||
- &mCurrentArrayBuffers[attribIndex], &conversion->lastAllocationOffset, 1));
|
||||
+ binding.getStride(), vertexFormat.getVertexLoadFunction(compressed),
|
||||
+ &mCurrentArrayBuffers[attribIndex], &conversion->lastAllocationOffset));
|
||||
ANGLE_TRY(srcBuffer->unmapImpl(contextVk));
|
||||
|
||||
ASSERT(conversion->dirty);
|
||||
@@ -808,28 +837,41 @@ angle::Result VertexArrayVk::updateStreamedAttribs(const gl::Context *context,
|
||||
// Instanced attrib
|
||||
if (divisor > renderer->getMaxVertexAttribDivisor())
|
||||
{
|
||||
- // Emulated attrib
|
||||
- BufferVk *bufferVk = nullptr;
|
||||
+ // Divisor will be set to 1 & so update buffer to have 1 attrib per instance
|
||||
+ size_t bytesToAllocate = instanceCount * stride;
|
||||
+
|
||||
if (binding.getBuffer().get() != nullptr)
|
||||
{
|
||||
// Map buffer to expand attribs for divisor emulation
|
||||
- bufferVk = vk::GetImpl(binding.getBuffer().get());
|
||||
- void *buffSrc = nullptr;
|
||||
+ BufferVk *bufferVk = vk::GetImpl(binding.getBuffer().get());
|
||||
+ void *buffSrc = nullptr;
|
||||
ANGLE_TRY(bufferVk->mapImpl(contextVk, &buffSrc));
|
||||
src = reinterpret_cast<const uint8_t *>(buffSrc) + binding.getOffset();
|
||||
- }
|
||||
- // Divisor will be set to 1 & so update buffer to have 1 attrib per instance
|
||||
- size_t bytesToAllocate = instanceCount * stride;
|
||||
|
||||
- ANGLE_TRY(StreamVertexData(contextVk, &mDynamicVertexData, src, bytesToAllocate, 0,
|
||||
- instanceCount, binding.getStride(), stride,
|
||||
- vertexFormat.vertexLoadFunction,
|
||||
- &mCurrentArrayBuffers[attribIndex],
|
||||
- &mCurrentArrayBufferOffsets[attribIndex], divisor));
|
||||
- if (bufferVk)
|
||||
- {
|
||||
+ uint32_t srcAttributeSize =
|
||||
+ static_cast<uint32_t>(ComputeVertexAttributeTypeSize(attrib));
|
||||
+
|
||||
+ size_t numVertices = GetVertexCount(bufferVk, binding, srcAttributeSize);
|
||||
+
|
||||
+ ANGLE_TRY(StreamVertexDataWithDivisor(
|
||||
+ contextVk, &mDynamicVertexData, src, bytesToAllocate, binding.getStride(),
|
||||
+ stride, vertexFormat.vertexLoadFunction,
|
||||
+ &mCurrentArrayBuffers[attribIndex],
|
||||
+ &mCurrentArrayBufferOffsets[attribIndex], divisor,
|
||||
+ numVertices));
|
||||
+
|
||||
ANGLE_TRY(bufferVk->unmapImpl(contextVk));
|
||||
}
|
||||
+ else
|
||||
+ {
|
||||
+ size_t numVertices = instanceCount;
|
||||
+ ANGLE_TRY(StreamVertexDataWithDivisor(
|
||||
+ contextVk, &mDynamicVertexData, src, bytesToAllocate, binding.getStride(),
|
||||
+ stride, vertexFormat.vertexLoadFunction,
|
||||
+ &mCurrentArrayBuffers[attribIndex],
|
||||
+ &mCurrentArrayBufferOffsets[attribIndex], divisor,
|
||||
+ numVertices));
|
||||
+ }
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -838,10 +880,10 @@ angle::Result VertexArrayVk::updateStreamedAttribs(const gl::Context *context,
|
||||
size_t bytesToAllocate = count * stride;
|
||||
|
||||
ANGLE_TRY(StreamVertexData(contextVk, &mDynamicVertexData, src, bytesToAllocate, 0,
|
||||
- count, binding.getStride(), stride,
|
||||
+ count, binding.getStride(),
|
||||
vertexFormat.vertexLoadFunction,
|
||||
&mCurrentArrayBuffers[attribIndex],
|
||||
- &mCurrentArrayBufferOffsets[attribIndex], 1));
|
||||
+ &mCurrentArrayBufferOffsets[attribIndex]));
|
||||
}
|
||||
}
|
||||
else
|
||||
@@ -856,8 +898,8 @@ angle::Result VertexArrayVk::updateStreamedAttribs(const gl::Context *context,
|
||||
|
||||
ANGLE_TRY(StreamVertexData(
|
||||
contextVk, &mDynamicVertexData, src, bytesToAllocate, destOffset, vertexCount,
|
||||
- binding.getStride(), stride, vertexFormat.vertexLoadFunction,
|
||||
- &mCurrentArrayBuffers[attribIndex], &mCurrentArrayBufferOffsets[attribIndex], 1));
|
||||
+ binding.getStride(), vertexFormat.vertexLoadFunction,
|
||||
+ &mCurrentArrayBuffers[attribIndex], &mCurrentArrayBufferOffsets[attribIndex]));
|
||||
}
|
||||
|
||||
mCurrentArrayBufferHandles[attribIndex] =
|
||||
diff --git a/src/tests/gl_tests/RobustBufferAccessBehaviorTest.cpp b/src/tests/gl_tests/RobustBufferAccessBehaviorTest.cpp
|
||||
index 08917a2de3385eb853bced1dd576aff46f34f709..db708b0a2a3ce90a370b43786af6884b2f992bef 100644
|
||||
--- a/src/tests/gl_tests/RobustBufferAccessBehaviorTest.cpp
|
||||
+++ b/src/tests/gl_tests/RobustBufferAccessBehaviorTest.cpp
|
||||
@@ -564,6 +564,98 @@ TEST_P(RobustBufferAccessBehaviorTest, DynamicBuffer)
|
||||
}
|
||||
}
|
||||
|
||||
+// Tests out of bounds read by divisor emulation due to a user-provided offset.
|
||||
+// Adapted from https://crbug.com/1285885.
|
||||
+TEST_P(RobustBufferAccessBehaviorTest, IndexOutOfBounds)
|
||||
+{
|
||||
+ ANGLE_SKIP_TEST_IF(!initExtension());
|
||||
+
|
||||
+ constexpr char kVS[] = R"(precision highp float;
|
||||
+attribute vec4 a_position;
|
||||
+void main(void) {
|
||||
+ gl_Position = a_position;
|
||||
+})";
|
||||
+
|
||||
+ constexpr char kFS[] = R"(precision highp float;
|
||||
+uniform sampler2D oTexture;
|
||||
+uniform float oColor[3];
|
||||
+void main(void) {
|
||||
+ gl_FragData[0] = texture2DProj(oTexture, vec3(0.1,0.1,0.1));
|
||||
+})";
|
||||
+
|
||||
+ GLfloat singleFloat = 1.0f;
|
||||
+
|
||||
+ GLBuffer buf;
|
||||
+ glBindBuffer(GL_ARRAY_BUFFER, buf);
|
||||
+ glBufferData(GL_ARRAY_BUFFER, 4, &singleFloat, GL_STATIC_DRAW);
|
||||
+
|
||||
+ ANGLE_GL_PROGRAM(program, kVS, kFS);
|
||||
+ glBindAttribLocation(program, 0, "a_position");
|
||||
+ glLinkProgram(program);
|
||||
+ ASSERT_TRUE(CheckLinkStatusAndReturnProgram(program, true));
|
||||
+
|
||||
+ glEnableVertexAttribArray(0);
|
||||
+
|
||||
+ // Trying to exceed renderer->getMaxVertexAttribDivisor()
|
||||
+ GLuint constexpr kDivisor = 4096;
|
||||
+ glVertexAttribDivisor(0, kDivisor);
|
||||
+
|
||||
+ size_t outOfBoundsOffset = 0x50000000;
|
||||
+ glVertexAttribPointer(0, 1, GL_FLOAT, false, 8, reinterpret_cast<void *>(outOfBoundsOffset));
|
||||
+
|
||||
+ glUseProgram(program);
|
||||
+
|
||||
+ glDrawArrays(GL_TRIANGLES, 0, 32);
|
||||
+
|
||||
+ // No assertions, just checking for crashes.
|
||||
+}
|
||||
+
|
||||
+// Similar to the test above but index is first within bounds then goes out of bounds.
|
||||
+TEST_P(RobustBufferAccessBehaviorTest, IndexGoingOutOfBounds)
|
||||
+{
|
||||
+ ANGLE_SKIP_TEST_IF(!initExtension());
|
||||
+
|
||||
+ constexpr char kVS[] = R"(precision highp float;
|
||||
+attribute vec4 a_position;
|
||||
+void main(void) {
|
||||
+ gl_Position = a_position;
|
||||
+})";
|
||||
+
|
||||
+ constexpr char kFS[] = R"(precision highp float;
|
||||
+uniform sampler2D oTexture;
|
||||
+uniform float oColor[3];
|
||||
+void main(void) {
|
||||
+ gl_FragData[0] = texture2DProj(oTexture, vec3(0.1,0.1,0.1));
|
||||
+})";
|
||||
+
|
||||
+ GLBuffer buf;
|
||||
+ glBindBuffer(GL_ARRAY_BUFFER, buf);
|
||||
+ std::array<GLfloat, 2> buffer = {{0.2f, 0.2f}};
|
||||
+ glBufferData(GL_ARRAY_BUFFER, sizeof(GLfloat) * buffer.size(), buffer.data(), GL_STATIC_DRAW);
|
||||
+
|
||||
+ ANGLE_GL_PROGRAM(program, kVS, kFS);
|
||||
+ glBindAttribLocation(program, 0, "a_position");
|
||||
+ glLinkProgram(program);
|
||||
+ ASSERT_TRUE(CheckLinkStatusAndReturnProgram(program, true));
|
||||
+
|
||||
+ glEnableVertexAttribArray(0);
|
||||
+
|
||||
+ // Trying to exceed renderer->getMaxVertexAttribDivisor()
|
||||
+ GLuint constexpr kDivisor = 4096;
|
||||
+ glVertexAttribDivisor(0, kDivisor);
|
||||
+
|
||||
+ // 6 bytes remaining in the buffer from offset so only a single vertex can be read
|
||||
+ glVertexAttribPointer(0, 1, GL_FLOAT, false, 8, reinterpret_cast<void *>(2));
|
||||
+
|
||||
+ glUseProgram(program);
|
||||
+
|
||||
+ // Each vertex is read `kDivisor` times so the last read goes out of bounds
|
||||
+ GLsizei instanceCount = kDivisor + 1;
|
||||
+ glDrawArraysInstanced(GL_TRIANGLES, 0, 32, instanceCount);
|
||||
+
|
||||
+ // No assertions, just checking for crashes.
|
||||
+}
|
||||
+
|
||||
ANGLE_INSTANTIATE_TEST_ES2_AND_ES3_AND_ES31(RobustBufferAccessBehaviorTest);
|
||||
|
||||
} // namespace
|
||||
@@ -0,0 +1,51 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Charlie Lao <cclao@google.com>
|
||||
Date: Mon, 7 Feb 2022 15:08:15 -0800
|
||||
Subject: M99: Vulkan: StreamVertexDataWithDivisor write beyond buffer boundary
|
||||
|
||||
StreamVertexDataWithDivisor() function is advancing dst with dstStride,
|
||||
but then later on it is treating dst as if it never advanced, thus
|
||||
result in write out of buffer boundary. This was hidden by VMA's memory
|
||||
suballocation, which means it may result in some rendering artifacts.
|
||||
|
||||
Bug: angleproject:6990
|
||||
Change-Id: Ic91e917cedd247dfe85b12a69ae26b21b7a4e67a
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/3445528
|
||||
Reviewed-by: Roman Lavrov <romanl@google.com>
|
||||
Reviewed-by: Jamie Madill <jmadill@chromium.org>
|
||||
Commit-Queue: Charlie Lao <cclao@google.com>
|
||||
(cherry picked from commit 5204587698099207ce8ae70779ef44ffae877996)
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/3461417
|
||||
Reviewed-by: Charlie Lao <cclao@google.com>
|
||||
Commit-Queue: Roman Lavrov <romanl@google.com>
|
||||
|
||||
diff --git a/src/libANGLE/renderer/vulkan/VertexArrayVk.cpp b/src/libANGLE/renderer/vulkan/VertexArrayVk.cpp
|
||||
index 1ca486af3ff004e11aea82c391b4c504b569096c..93378c4b24495872405fc06ea01e15254229ab63 100644
|
||||
--- a/src/libANGLE/renderer/vulkan/VertexArrayVk.cpp
|
||||
+++ b/src/libANGLE/renderer/vulkan/VertexArrayVk.cpp
|
||||
@@ -120,7 +120,7 @@ angle::Result StreamVertexDataWithDivisor(ContextVk *contextVk,
|
||||
ASSERT(divisor > 0);
|
||||
|
||||
uint32_t sourceVertexUseCount = 0;
|
||||
- for (size_t dataCopied = 0; dataCopied < clampedSize; dataCopied += destStride, dst += destStride)
|
||||
+ for (size_t dataCopied = 0; dataCopied < clampedSize; dataCopied += destStride)
|
||||
{
|
||||
vertexLoadFunction(sourceData, sourceStride, 1, dst);
|
||||
sourceVertexUseCount++;
|
||||
@@ -129,6 +129,7 @@ angle::Result StreamVertexDataWithDivisor(ContextVk *contextVk,
|
||||
sourceData += sourceStride;
|
||||
sourceVertexUseCount = 0;
|
||||
}
|
||||
+ dst += destStride;
|
||||
}
|
||||
|
||||
// Satisfy robustness constraints (only if extension enabled)
|
||||
@@ -136,7 +137,7 @@ angle::Result StreamVertexDataWithDivisor(ContextVk *contextVk,
|
||||
{
|
||||
if (clampedSize < bytesToAllocate)
|
||||
{
|
||||
- memset(dst + clampedSize, 0, bytesToAllocate - clampedSize);
|
||||
+ memset(dst, 0, bytesToAllocate - clampedSize);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,81 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Peng Huang <penghuang@chromium.org>
|
||||
Date: Mon, 25 Oct 2021 15:45:36 -0400
|
||||
Subject: VANGLE: change the default vulkan device choose logic
|
||||
|
||||
To match the vulkan device choose logic in chrome, ANGLE will choose
|
||||
the default device based on the order of (discret GPU > integrated GPU
|
||||
> other GPU)
|
||||
|
||||
TODO: for long term, ANGLE should provide a way to let chrome specify
|
||||
the physical device.
|
||||
|
||||
Bug: chromium:1260869
|
||||
Change-Id: Id023138485eb65fcc1d2758103d59a4e6cb2a51d
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/3242963
|
||||
Reviewed-by: Geoff Lang <geofflang@chromium.org>
|
||||
Reviewed-by: Shahbaz Youssefi <syoussefi@chromium.org>
|
||||
Commit-Queue: Peng Huang <penghuang@chromium.org>
|
||||
|
||||
diff --git a/src/common/vulkan/vulkan_icd.cpp b/src/common/vulkan/vulkan_icd.cpp
|
||||
index 0ed7ae2aa058792b700503dfdb6fd91b05bf68fb..df14f5f674b37c49332e43ccba8f1782cb13f495 100644
|
||||
--- a/src/common/vulkan/vulkan_icd.cpp
|
||||
+++ b/src/common/vulkan/vulkan_icd.cpp
|
||||
@@ -11,6 +11,7 @@
|
||||
#include <functional>
|
||||
#include <vector>
|
||||
|
||||
+#include "common/Optional.h"
|
||||
#include "common/bitset_utils.h"
|
||||
#include "common/debug.h"
|
||||
#include "common/system_utils.h"
|
||||
@@ -94,8 +95,7 @@ ICDFilterFunc GetFilterForICD(vk::ICD preferredICD)
|
||||
const std::string anglePreferredDevice =
|
||||
angle::GetEnvironmentVar(kANGLEPreferredDeviceEnv);
|
||||
return [anglePreferredDevice](const VkPhysicalDeviceProperties &deviceProperties) {
|
||||
- return (anglePreferredDevice.empty() ||
|
||||
- anglePreferredDevice == deviceProperties.deviceName);
|
||||
+ return (anglePreferredDevice == deviceProperties.deviceName);
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -262,9 +262,37 @@ void ChoosePhysicalDevice(const std::vector<VkPhysicalDevice> &physicalDevices,
|
||||
return;
|
||||
}
|
||||
}
|
||||
- WARN() << "Preferred device ICD not found. Using default physicalDevice instead.";
|
||||
|
||||
- // Fall back to first device.
|
||||
+ Optional<VkPhysicalDevice> integratedDevice;
|
||||
+ VkPhysicalDeviceProperties integratedDeviceProperties;
|
||||
+ for (const VkPhysicalDevice &physicalDevice : physicalDevices)
|
||||
+ {
|
||||
+ vkGetPhysicalDeviceProperties(physicalDevice, physicalDevicePropertiesOut);
|
||||
+ // If discrete GPU exists, uses it by default.
|
||||
+ if (physicalDevicePropertiesOut->deviceType == VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU)
|
||||
+ {
|
||||
+ *physicalDeviceOut = physicalDevice;
|
||||
+ return;
|
||||
+ }
|
||||
+ if (physicalDevicePropertiesOut->deviceType == VK_PHYSICAL_DEVICE_TYPE_INTEGRATED_GPU &&
|
||||
+ !integratedDevice.valid())
|
||||
+ {
|
||||
+ integratedDevice = physicalDevice;
|
||||
+ integratedDeviceProperties = *physicalDevicePropertiesOut;
|
||||
+ continue;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ // If only integrated GPU exists, use it by default.
|
||||
+ if (integratedDevice.valid())
|
||||
+ {
|
||||
+ *physicalDeviceOut = integratedDevice.value();
|
||||
+ *physicalDevicePropertiesOut = integratedDeviceProperties;
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
+ WARN() << "Preferred device ICD not found. Using default physicalDevice instead.";
|
||||
+ // Fallback to the first device.
|
||||
*physicalDeviceOut = physicalDevices[0];
|
||||
vkGetPhysicalDeviceProperties(*physicalDeviceOut, physicalDevicePropertiesOut);
|
||||
}
|
||||
@@ -107,10 +107,70 @@ fix_media_key_usage_with_globalshortcuts.patch
|
||||
cherry-pick-ec42dfd3545f.patch
|
||||
cherry-pick-39090918efac.patch
|
||||
add_ui_scopedcliboardwriter_writeunsaferawdata.patch
|
||||
mas_gate_private_enterprise_APIs
|
||||
mas_gate_private_enterprise_APIs.patch
|
||||
cherry-pick-8af66de55aad.patch
|
||||
cherry-pick-c69dddfe1cde.patch
|
||||
cherry-pick-2e7c9b33453b.patch
|
||||
move_networkstateobserver_from_document_to_window.patch
|
||||
cherry-pick-0894af410c4e.patch
|
||||
cherry-pick-91dd4f79ab5b.patch
|
||||
introduce_crossthreadcopier_skbitmap.patch
|
||||
allow_null_skbitmap_to_be_transferred_across_threads.patch
|
||||
use_weakptrs_for_the_threadediconloader_s_background_tasks.patch
|
||||
cherry-pick-1a8af2da50e4.patch
|
||||
cherry-pick-a5f54612590d.patch
|
||||
cachestorage_store_partial_opaque_responses.patch
|
||||
fix_aspect_ratio_with_max_size.patch
|
||||
cherry-pick-f0a63e1f361f.patch
|
||||
cherry-pick-27eb11a28555.patch
|
||||
sandbox_fix_sandbox_inheritance_m96_merge.patch
|
||||
cherry-pick-da11d71a0227.patch
|
||||
cherry-pick-dbde8795233a.patch
|
||||
cherry-pick-6bb320d134b1.patch
|
||||
cherry-pick-109fde1088be.patch
|
||||
m96_fileapi_move_origin_checks_in_bloburlstore_sooner.patch
|
||||
cherry-pick-f781748dcb3c.patch
|
||||
cherry-pick-c5571653d932.patch
|
||||
fix_crash_when_saving_edited_pdf_files.patch
|
||||
use_axnodeid_rather_than_axnode_in_axeventgenerator_tree_events.patch
|
||||
mojo_reject_addbrokerclient_on_non-broker_nodes.patch
|
||||
cherry-pick-1277917.patch
|
||||
cherry-pick-1281979.patch
|
||||
cherry-pick-1282354.patch
|
||||
cherry-pick-1283198.patch
|
||||
cherry-pick-1283375.patch
|
||||
cherry-pick-1283371.patch
|
||||
cherry-pick-9db9911e1242.patch
|
||||
cherry-pick-1284367.patch
|
||||
m97_webcodecs_various_decodertemplate_shutdown_cleanups.patch
|
||||
96_take_local_copy_of_ump_local_sources_to_iterate.patch
|
||||
pin_scrolltop_to_0_during_autofill_preview.patch
|
||||
fix_preview_state_detection.patch
|
||||
do_not_select_vulkan_device_based_on_the_passed_in_gpu_info_on_linux.patch
|
||||
handle_potentiallydanglingmarkup_for_cssimagevalue.patch
|
||||
fire_iframe_onload_for_cross-origin-initiated_same-document.patch
|
||||
merge_m-97_serial_check_for_detached_buffers_when_writing.patch
|
||||
cleanup_pausablecriptexecutor_usage.patch
|
||||
m98_fs_fix_fileutil_lifetime_issue.patch
|
||||
cherry-pick-be50c60b4225.patch
|
||||
cherry-pick-ebc188ad769e.patch
|
||||
cherry-pick-e3805f29fed7.patch
|
||||
cherry-pick-0081bb347e67.patch
|
||||
cherry-pick-62142d222a80.patch
|
||||
cherry-pick-1887414c016d.patch
|
||||
cherry-pick-6b2643846ae3.patch
|
||||
cherry-pick-905302eb3a2b.patch
|
||||
cherry-pick-246c10dede97.patch
|
||||
fix_imagebitmaprenderingcontext_interaction_with_software_compositor.patch
|
||||
remove_incorrect_width_height_adjustments.patch
|
||||
fix_non-client_mouse_tracking_and_message_bubbling_on_windows.patch
|
||||
fixed_terminate_caused_by_binding_to_wrong_version.patch
|
||||
follow_wayland_specification_regarding_xkb_keymap.patch
|
||||
cherry-pick-4d26949260aa.patch
|
||||
use-after-free_of_id_and_idref_attributes.patch
|
||||
fix_--without-valid_build.patch
|
||||
usb_fix_oob_access_with_non-sequential_interfaces.patch
|
||||
skia_renderer_-_don_t_explicitly_clip_scissor_for_large_transforms.patch
|
||||
skia_renderer_use_rectf_intersect_in_applyscissor.patch
|
||||
cherry-pick-1a31e2110440.patch
|
||||
m100_change_ownership_of_blobbytesprovider.patch
|
||||
|
||||
@@ -0,0 +1,53 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Tony Herre <toprice@chromium.org>
|
||||
Date: Tue, 14 Dec 2021 16:35:05 +0000
|
||||
Subject: Take local copy of UMP::local_sources to iterate
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
|
||||
Take a local copy of UserMediaProcessor::local_sources_ when iterating
|
||||
over it in UserMediaProcessor::DetermineExistingAudioSessionId, as the
|
||||
list can be effectively concurrently modified during destruction of
|
||||
MediaStreamTracks triggered by GC during this loop. Without the copy
|
||||
this leads to a container overflow.
|
||||
|
||||
(cherry picked from commit fb6232ffb1fec14d64ec8815f7dfc2cea0887588)
|
||||
|
||||
Bug: 1238209
|
||||
Change-Id: I048387a51a58eacff87d220e6b67d2d09f610c1d
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3320283
|
||||
Reviewed-by: Henrik Boström <hbos@chromium.org>
|
||||
Commit-Queue: Tony Herre <toprice@chromium.org>
|
||||
Cr-Original-Commit-Position: refs/heads/main@{#950499}
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3337896
|
||||
Reviewed-by: Guido Urdaneta <guidou@chromium.org>
|
||||
Cr-Commit-Position: refs/branch-heads/4664@{#1303}
|
||||
Cr-Branched-From: 24dc4ee75e01a29d390d43c9c264372a169273a7-refs/heads/main@{#929512}
|
||||
|
||||
diff --git a/third_party/blink/renderer/modules/mediastream/user_media_processor.cc b/third_party/blink/renderer/modules/mediastream/user_media_processor.cc
|
||||
index d42b3d7309ce40e74ebf386f4d38eb8cce008ec0..b0b8b15657210174b000a02f711a76fa16e5948d 100644
|
||||
--- a/third_party/blink/renderer/modules/mediastream/user_media_processor.cc
|
||||
+++ b/third_party/blink/renderer/modules/mediastream/user_media_processor.cc
|
||||
@@ -725,6 +725,7 @@ void UserMediaProcessor::SelectAudioSettings(
|
||||
|
||||
absl::optional<base::UnguessableToken>
|
||||
UserMediaProcessor::DetermineExistingAudioSessionId() {
|
||||
+ DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
|
||||
DCHECK(current_request_info_->request()->Audio());
|
||||
|
||||
auto settings = current_request_info_->audio_capture_settings();
|
||||
@@ -733,7 +734,12 @@ UserMediaProcessor::DetermineExistingAudioSessionId() {
|
||||
// Create a copy of the MediaStreamSource objects that are
|
||||
// associated to the same audio device capture based on its device ID.
|
||||
HeapVector<Member<MediaStreamSource>> matching_sources;
|
||||
- for (const auto& source : local_sources_) {
|
||||
+
|
||||
+ // Take a defensive copy, as local_sources_ can be modified during
|
||||
+ // destructions in GC runs triggered by the push_back allocation in this loop.
|
||||
+ // crbug.com/1238209
|
||||
+ HeapVector<Member<MediaStreamSource>> local_sources_copy = local_sources_;
|
||||
+ for (const auto& source : local_sources_copy) {
|
||||
MediaStreamSource* source_copy = source;
|
||||
if (source_copy->GetType() == MediaStreamSource::kTypeAudio &&
|
||||
source_copy->Id().Utf8() == device_id) {
|
||||
@@ -0,0 +1,40 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Yutaka Hirano <yhirano@chromium.org>
|
||||
Date: Tue, 9 Nov 2021 09:03:17 +0000
|
||||
Subject: Allow null SkBitmap to be transferred across threads
|
||||
|
||||
(cherry picked from commit dad0c0e5162bcc49b8f60354d3bca92224d8381b)
|
||||
|
||||
Bug: 1241091
|
||||
Change-Id: Ie96932c14c8884d6d3eafa76dab5043e7aa31888
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3251815
|
||||
Reviewed-by: Florin Malita <fmalita@chromium.org>
|
||||
Commit-Queue: Yutaka Hirano <yhirano@chromium.org>
|
||||
Cr-Original-Commit-Position: refs/heads/main@{#936861}
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3268018
|
||||
Auto-Submit: Yutaka Hirano <yhirano@chromium.org>
|
||||
Reviewed-by: Kentaro Hara <haraken@chromium.org>
|
||||
Commit-Queue: Kentaro Hara <haraken@chromium.org>
|
||||
Cr-Commit-Position: refs/branch-heads/4664@{#893}
|
||||
Cr-Branched-From: 24dc4ee75e01a29d390d43c9c264372a169273a7-refs/heads/main@{#929512}
|
||||
|
||||
diff --git a/third_party/blink/renderer/platform/graphics/skia/skia_utils.h b/third_party/blink/renderer/platform/graphics/skia/skia_utils.h
|
||||
index e4bde78252c90ecd19655e8c552a2a39299dff75..33d6a1f115c606c3f203b37642ad2875bcca1dd7 100644
|
||||
--- a/third_party/blink/renderer/platform/graphics/skia/skia_utils.h
|
||||
+++ b/third_party/blink/renderer/platform/graphics/skia/skia_utils.h
|
||||
@@ -212,11 +212,13 @@ struct CrossThreadCopier<SkBitmap> {
|
||||
|
||||
using Type = SkBitmap;
|
||||
static SkBitmap Copy(const SkBitmap& bitmap) {
|
||||
- CHECK(bitmap.isImmutable()) << "Only immutable bitmaps can be transferred.";
|
||||
+ CHECK(bitmap.isImmutable() || bitmap.isNull())
|
||||
+ << "Only immutable bitmaps can be transferred.";
|
||||
return bitmap;
|
||||
}
|
||||
static SkBitmap Copy(SkBitmap&& bitmap) {
|
||||
- CHECK(bitmap.isImmutable()) << "Only immutable bitmaps can be transferred.";
|
||||
+ CHECK(bitmap.isImmutable() || bitmap.isNull())
|
||||
+ << "Only immutable bitmaps can be transferred.";
|
||||
return std::move(bitmap);
|
||||
}
|
||||
};
|
||||
@@ -0,0 +1,94 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Ben Kelly <wanderview@chromium.org>
|
||||
Date: Fri, 5 Nov 2021 19:47:08 +0000
|
||||
Subject: CacheStorage: Store partial opaque responses.
|
||||
|
||||
(cherry picked from commit 802faa035409ac7cbb58ad1a385bb8507fe99077)
|
||||
|
||||
Fixed: 1260649
|
||||
Change-Id: If83156096e6aecec55490330d03c56c0c26120bc
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3251749
|
||||
Reviewed-by: Marijn Kruisselbrink <mek@chromium.org>
|
||||
Commit-Queue: Ben Kelly <wanderview@chromium.org>
|
||||
Cr-Original-Commit-Position: refs/heads/main@{#937400}
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3264366
|
||||
Bot-Commit: Rubber Stamper <rubber-stamper@appspot.gserviceaccount.com>
|
||||
Cr-Commit-Position: refs/branch-heads/4664@{#774}
|
||||
Cr-Branched-From: 24dc4ee75e01a29d390d43c9c264372a169273a7-refs/heads/main@{#929512}
|
||||
|
||||
diff --git a/content/browser/cache_storage/legacy/legacy_cache_storage_cache.cc b/content/browser/cache_storage/legacy/legacy_cache_storage_cache.cc
|
||||
index 08ed40551e5d66498931271845f345e45ed7272d..f26fcfc4c676d115f2128e843f27154d8a9e03b6 100644
|
||||
--- a/content/browser/cache_storage/legacy/legacy_cache_storage_cache.cc
|
||||
+++ b/content/browser/cache_storage/legacy/legacy_cache_storage_cache.cc
|
||||
@@ -446,10 +446,10 @@ blink::mojom::FetchAPIResponsePtr CreateResponse(
|
||||
? metadata.response().request_include_credentials()
|
||||
: true;
|
||||
|
||||
- // Note that |has_range_requested| can be safely set to false since it only
|
||||
- // affects HTTP 206 (Partial) responses, which are blocked from cache storage.
|
||||
- // See https://fetch.spec.whatwg.org/#main-fetch for usage of
|
||||
- // |has_range_requested|.
|
||||
+ // While we block most partial responses from being stored, we can have
|
||||
+ // partial responses for bgfetch or opaque responses.
|
||||
+ bool has_range_requested = headers.contains(net::HttpRequestHeaders::kRange);
|
||||
+
|
||||
return blink::mojom::FetchAPIResponse::New(
|
||||
url_list, metadata.response().status_code(),
|
||||
metadata.response().status_text(),
|
||||
@@ -467,7 +467,7 @@ blink::mojom::FetchAPIResponsePtr CreateResponse(
|
||||
static_cast<net::HttpResponseInfo::ConnectionInfo>(
|
||||
metadata.response().connection_info()),
|
||||
alpn_negotiated_protocol, metadata.response().was_fetched_via_spdy(),
|
||||
- /*has_range_requested=*/false, /*auth_challenge_info=*/absl::nullopt,
|
||||
+ has_range_requested, /*auth_challenge_info=*/absl::nullopt,
|
||||
request_include_credentials);
|
||||
}
|
||||
|
||||
@@ -1888,7 +1888,13 @@ void LegacyCacheStorageCache::PutDidCreateEntry(
|
||||
}
|
||||
|
||||
proto::CacheResponse* response_metadata = metadata.mutable_response();
|
||||
- DCHECK_NE(put_context->response->status_code, net::HTTP_PARTIAL_CONTENT);
|
||||
+ if (owner_ != storage::mojom::CacheStorageOwner::kBackgroundFetch &&
|
||||
+ put_context->response->response_type !=
|
||||
+ network::mojom::FetchResponseType::kOpaque &&
|
||||
+ put_context->response->response_type !=
|
||||
+ network::mojom::FetchResponseType::kOpaqueRedirect) {
|
||||
+ DCHECK_NE(put_context->response->status_code, net::HTTP_PARTIAL_CONTENT);
|
||||
+ }
|
||||
response_metadata->set_status_code(put_context->response->status_code);
|
||||
response_metadata->set_status_text(put_context->response->status_text);
|
||||
response_metadata->set_response_type(FetchResponseTypeToProtoResponseType(
|
||||
diff --git a/third_party/blink/renderer/modules/cache_storage/cache.cc b/third_party/blink/renderer/modules/cache_storage/cache.cc
|
||||
index c76c7677a17fd58be83d5e9f2bc263b710e528ae..8c267d2f54ae6e83b86d53dd473e2ed1354aa3c4 100644
|
||||
--- a/third_party/blink/renderer/modules/cache_storage/cache.cc
|
||||
+++ b/third_party/blink/renderer/modules/cache_storage/cache.cc
|
||||
@@ -102,7 +102,7 @@ void ValidateResponseForPut(const Response* response,
|
||||
exception_state.ThrowTypeError("Vary header contains *");
|
||||
return;
|
||||
}
|
||||
- if (response->GetResponse()->InternalStatus() == 206) {
|
||||
+ if (response->GetResponse()->Status() == 206) {
|
||||
exception_state.ThrowTypeError(
|
||||
"Partial response (status code 206) is unsupported");
|
||||
return;
|
||||
diff --git a/third_party/blink/web_tests/external/wpt/service-workers/cache-storage/script-tests/cache-put.js b/third_party/blink/web_tests/external/wpt/service-workers/cache-storage/script-tests/cache-put.js
|
||||
index b45910a3b8ba089e1724efa8b9e8a8d679c59320..f60c4b905ebcb61854b83177d59861ef92095624 100644
|
||||
--- a/third_party/blink/web_tests/external/wpt/service-workers/cache-storage/script-tests/cache-put.js
|
||||
+++ b/third_party/blink/web_tests/external/wpt/service-workers/cache-storage/script-tests/cache-put.js
|
||||
@@ -144,7 +144,14 @@ cache_test(function(cache, test) {
|
||||
'Test framework error: The status code should be 0 for an ' +
|
||||
' opaque-filtered response. This is actually HTTP 206.');
|
||||
response = fetch_result.clone();
|
||||
- return promise_rejects_js(test, TypeError, cache.put(request, fetch_result));
|
||||
+ return cache.put(request, fetch_result);
|
||||
+ })
|
||||
+ .then(function() {
|
||||
+ return cache.match(test_url);
|
||||
+ })
|
||||
+ .then(function(result) {
|
||||
+ assert_not_equals(result, undefined,
|
||||
+ 'Cache.put should store an entry for the opaque response');
|
||||
});
|
||||
}, 'Cache.put with opaque-filtered HTTP 206 response');
|
||||
|
||||
26
patches/chromium/cherry-pick-0081bb347e67.patch
Normal file
26
patches/chromium/cherry-pick-0081bb347e67.patch
Normal file
@@ -0,0 +1,26 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Matt Reynolds <mattreynolds@google.com>
|
||||
Date: Wed, 19 Jan 2022 21:03:08 +0000
|
||||
Subject: gamepad: Return an invalid handle after ReportBadMessage
|
||||
|
||||
Bug: 1285449
|
||||
Change-Id: I746c539577f7bdf69cbe4212ac380e0c92a5c771
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3373944
|
||||
Auto-Submit: Matt Reynolds <mattreynolds@chromium.org>
|
||||
Reviewed-by: Reilly Grant <reillyg@chromium.org>
|
||||
Commit-Queue: Reilly Grant <reillyg@chromium.org>
|
||||
Cr-Commit-Position: refs/heads/main@{#961125}
|
||||
|
||||
diff --git a/device/gamepad/gamepad_monitor.cc b/device/gamepad/gamepad_monitor.cc
|
||||
index ce8ba1ef7551e52f8ae4d9a112a08308ab2ce51c..28082924e632a895fc5bc4725bc6de3d6ca120ac 100644
|
||||
--- a/device/gamepad/gamepad_monitor.cc
|
||||
+++ b/device/gamepad/gamepad_monitor.cc
|
||||
@@ -53,6 +53,8 @@ void GamepadMonitor::GamepadStartPolling(GamepadStartPollingCallback callback) {
|
||||
GamepadService* service = GamepadService::GetInstance();
|
||||
if (!service->ConsumerBecameActive(this)) {
|
||||
mojo::ReportBadMessage("GamepadMonitor::GamepadStartPolling failed");
|
||||
+ std::move(callback).Run(base::ReadOnlySharedMemoryRegion());
|
||||
+ return;
|
||||
}
|
||||
std::move(callback).Run(service->DuplicateSharedMemoryRegion());
|
||||
}
|
||||
51
patches/chromium/cherry-pick-109fde1088be.patch
Normal file
51
patches/chromium/cherry-pick-109fde1088be.patch
Normal file
@@ -0,0 +1,51 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Michael Lippautz <mlippautz@chromium.org>
|
||||
Date: Tue, 2 Nov 2021 21:21:27 +0000
|
||||
Subject: MediaStreamSource: Retain observers till callbacks have been executed
|
||||
|
||||
(cherry picked from commit d1055cb23b15e42381bc815eeabb207ce18394d9)
|
||||
|
||||
Bug: chromium:1263620
|
||||
Change-Id: I0655474bd3c5f4f927db1834e95b2724a20ba4e9
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3247159
|
||||
Commit-Queue: Michael Lippautz <mlippautz@chromium.org>
|
||||
Reviewed-by: Guido Urdaneta <guidou@chromium.org>
|
||||
Reviewed-by: Elad Alon <eladalon@chromium.org>
|
||||
Cr-Original-Commit-Position: refs/heads/main@{#935842}
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3257492
|
||||
Auto-Submit: Elad Alon <eladalon@chromium.org>
|
||||
Reviewed-by: Michael Lippautz <mlippautz@chromium.org>
|
||||
Commit-Queue: Guido Urdaneta <guidou@chromium.org>
|
||||
Cr-Commit-Position: refs/branch-heads/4638@{#1004}
|
||||
Cr-Branched-From: 159257cab5585bc8421abf347984bb32fdfe9eb9-refs/heads/main@{#920003}
|
||||
|
||||
diff --git a/third_party/blink/renderer/platform/mediastream/media_stream_source.cc b/third_party/blink/renderer/platform/mediastream/media_stream_source.cc
|
||||
index b37a4b9297b87092233c600953eb01af820b6df1..15ac4cce06d419646979a52a00628b152ec516de 100644
|
||||
--- a/third_party/blink/renderer/platform/mediastream/media_stream_source.cc
|
||||
+++ b/third_party/blink/renderer/platform/mediastream/media_stream_source.cc
|
||||
@@ -32,6 +32,7 @@
|
||||
|
||||
#include "third_party/blink/public/platform/modules/webrtc/webrtc_logging.h"
|
||||
#include "third_party/blink/renderer/platform/audio/audio_bus.h"
|
||||
+#include "third_party/blink/renderer/platform/heap/persistent.h"
|
||||
#include "third_party/blink/renderer/platform/mediastream/media_stream_audio_source.h"
|
||||
#include "third_party/blink/renderer/platform/mediastream/webaudio_destination_consumer.h"
|
||||
|
||||
@@ -171,11 +172,13 @@ void MediaStreamSource::SetReadyState(ReadyState ready_state) {
|
||||
ready_state_ = ready_state;
|
||||
|
||||
// Observers may dispatch events which create and add new Observers;
|
||||
- // take a snapshot so as to safely iterate.
|
||||
+ // take a snapshot so as to safely iterate. Wrap the observers in
|
||||
+ // weak persistents to allow cancelling callbacks in case they are reclaimed
|
||||
+ // until the callback is executed.
|
||||
Vector<base::OnceClosure> observer_callbacks;
|
||||
- for (auto it = observers_.begin(); it != observers_.end(); ++it) {
|
||||
- observer_callbacks.push_back(
|
||||
- base::BindOnce(&Observer::SourceChangedState, *it));
|
||||
+ for (const auto& it : observers_) {
|
||||
+ observer_callbacks.push_back(WTF::Bind(&Observer::SourceChangedState,
|
||||
+ WrapWeakPersistent(it.Get())));
|
||||
}
|
||||
for (auto& observer_callback : observer_callbacks) {
|
||||
std::move(observer_callback).Run();
|
||||
176
patches/chromium/cherry-pick-1277917.patch
Normal file
176
patches/chromium/cherry-pick-1277917.patch
Normal file
@@ -0,0 +1,176 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Simon Pelchat <spelchat@chromium.org>
|
||||
Date: Fri, 7 Jan 2022 20:00:37 +0000
|
||||
Subject: Avoid UAF on StreamingSearchPrefetchURLLoader.
|
||||
|
||||
StreamingSearchPrefetchURLLoader::OnDataAvailable used to "delete this",
|
||||
which results in deleting the DataPipeDrainer, which will then be used
|
||||
once OnDataAvailable returns. Instead, we post a task to delete the
|
||||
URL loader later on.
|
||||
|
||||
Bug: 1277917
|
||||
Change-Id: I8d78c73a01fff0315b96ccb0e7fe605884b99823
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3365387
|
||||
Reviewed-by: Max Curran <curranmax@chromium.org>
|
||||
Reviewed-by: Robert Ogden <robertogden@chromium.org>
|
||||
Commit-Queue: Simon Pelchat <spelchat@chromium.org>
|
||||
Cr-Commit-Position: refs/heads/main@{#956628}
|
||||
|
||||
diff --git a/chrome/browser/prefetch/search_prefetch/streaming_search_prefetch_request.cc b/chrome/browser/prefetch/search_prefetch/streaming_search_prefetch_request.cc
|
||||
index 1d3d1ea93c026d371a6ad5678e8ff37dc58f8423..e3eaad96fbada18211f295988c07d218ab67921f 100644
|
||||
--- a/chrome/browser/prefetch/search_prefetch/streaming_search_prefetch_request.cc
|
||||
+++ b/chrome/browser/prefetch/search_prefetch/streaming_search_prefetch_request.cc
|
||||
@@ -5,6 +5,7 @@
|
||||
#include "chrome/browser/prefetch/search_prefetch/streaming_search_prefetch_request.h"
|
||||
|
||||
#include "chrome/browser/prefetch/search_prefetch/streaming_search_prefetch_url_loader.h"
|
||||
+#include "streaming_search_prefetch_request.h"
|
||||
|
||||
StreamingSearchPrefetchRequest::StreamingSearchPrefetchRequest(
|
||||
const GURL& prefetch_url,
|
||||
@@ -19,7 +20,9 @@ void StreamingSearchPrefetchRequest::StartPrefetchRequestInternal(
|
||||
std::unique_ptr<network::ResourceRequest> resource_request,
|
||||
const net::NetworkTrafficAnnotationTag& network_traffic_annotation) {
|
||||
streaming_url_loader_ = std::make_unique<StreamingSearchPrefetchURLLoader>(
|
||||
- this, profile, std::move(resource_request), network_traffic_annotation);
|
||||
+ this, profile, std::move(resource_request), network_traffic_annotation,
|
||||
+ base::BindOnce(&StreamingSearchPrefetchRequest::StopPrefetch,
|
||||
+ weak_factory_.GetWeakPtr()));
|
||||
}
|
||||
|
||||
std::unique_ptr<SearchPrefetchURLLoader>
|
||||
diff --git a/chrome/browser/prefetch/search_prefetch/streaming_search_prefetch_request.h b/chrome/browser/prefetch/search_prefetch/streaming_search_prefetch_request.h
|
||||
index ff051c61e9cbed67d5cffbcac007d6c12a26cc76..ad75d404abe9e743d079725ffd8b01d3a49ae017 100644
|
||||
--- a/chrome/browser/prefetch/search_prefetch/streaming_search_prefetch_request.h
|
||||
+++ b/chrome/browser/prefetch/search_prefetch/streaming_search_prefetch_request.h
|
||||
@@ -47,6 +47,8 @@ class StreamingSearchPrefetchRequest : public BaseSearchPrefetchRequest {
|
||||
private:
|
||||
// The ongoing prefetch request. Null before and after the fetch.
|
||||
std::unique_ptr<StreamingSearchPrefetchURLLoader> streaming_url_loader_;
|
||||
+
|
||||
+ base::WeakPtrFactory<StreamingSearchPrefetchRequest> weak_factory_{this};
|
||||
};
|
||||
|
||||
#endif // CHROME_BROWSER_PREFETCH_SEARCH_PREFETCH_STREAMING_SEARCH_PREFETCH_REQUEST_H_
|
||||
diff --git a/chrome/browser/prefetch/search_prefetch/streaming_search_prefetch_url_loader.cc b/chrome/browser/prefetch/search_prefetch/streaming_search_prefetch_url_loader.cc
|
||||
index 07f4e5cd7f0adde63861962a78cdac0de43591b0..8d9009c42cdde766e105b02827a539a4477ea58e 100644
|
||||
--- a/chrome/browser/prefetch/search_prefetch/streaming_search_prefetch_url_loader.cc
|
||||
+++ b/chrome/browser/prefetch/search_prefetch/streaming_search_prefetch_url_loader.cc
|
||||
@@ -26,15 +26,18 @@
|
||||
#include "services/network/public/cpp/shared_url_loader_factory.h"
|
||||
#include "services/network/public/mojom/early_hints.mojom.h"
|
||||
#include "services/network/public/mojom/url_response_head.mojom.h"
|
||||
+#include "streaming_search_prefetch_url_loader.h"
|
||||
#include "url/gurl.h"
|
||||
|
||||
StreamingSearchPrefetchURLLoader::StreamingSearchPrefetchURLLoader(
|
||||
StreamingSearchPrefetchRequest* streaming_prefetch_request,
|
||||
Profile* profile,
|
||||
std::unique_ptr<network::ResourceRequest> resource_request,
|
||||
- const net::NetworkTrafficAnnotationTag& network_traffic_annotation)
|
||||
+ const net::NetworkTrafficAnnotationTag& network_traffic_annotation,
|
||||
+ base::OnceClosure stop_prefetch_closure)
|
||||
: resource_request_(std::move(resource_request)),
|
||||
- streaming_prefetch_request_(streaming_prefetch_request) {
|
||||
+ streaming_prefetch_request_(streaming_prefetch_request),
|
||||
+ stop_prefetch_closure_(std::move(stop_prefetch_closure)) {
|
||||
DCHECK(streaming_prefetch_request_);
|
||||
auto url_loader_factory = profile->GetDefaultStoragePartition()
|
||||
->GetURLLoaderFactoryForBrowserProcess();
|
||||
@@ -126,7 +129,7 @@ void StreamingSearchPrefetchURLLoader::OnReceiveRedirect(
|
||||
if (streaming_prefetch_request_) {
|
||||
streaming_prefetch_request_->ErrorEncountered();
|
||||
} else {
|
||||
- delete this;
|
||||
+ PostTaskToStopPrefetchAndDeleteSelf();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -209,7 +212,7 @@ void StreamingSearchPrefetchURLLoader::OnStartLoadingResponseBodyFromData() {
|
||||
mojo::CreateDataPipe(&options, producer_handle_, consumer_handle);
|
||||
|
||||
if (rv != MOJO_RESULT_OK) {
|
||||
- delete this;
|
||||
+ PostTaskToStopPrefetchAndDeleteSelf();
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -231,7 +234,7 @@ void StreamingSearchPrefetchURLLoader::OnHandleReady(
|
||||
MojoResult result,
|
||||
const mojo::HandleSignalsState& state) {
|
||||
if (result != MOJO_RESULT_OK) {
|
||||
- delete this;
|
||||
+ PostTaskToStopPrefetchAndDeleteSelf();
|
||||
return;
|
||||
}
|
||||
PushData();
|
||||
@@ -257,7 +260,7 @@ void StreamingSearchPrefetchURLLoader::PushData() {
|
||||
}
|
||||
|
||||
if (result != MOJO_RESULT_OK) {
|
||||
- delete this;
|
||||
+ PostTaskToStopPrefetchAndDeleteSelf();
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -344,16 +347,24 @@ void StreamingSearchPrefetchURLLoader::OnURLLoaderMojoDisconnect() {
|
||||
DCHECK(streaming_prefetch_request_);
|
||||
streaming_prefetch_request_->ErrorEncountered();
|
||||
} else {
|
||||
- delete this;
|
||||
+ PostTaskToStopPrefetchAndDeleteSelf();
|
||||
}
|
||||
}
|
||||
|
||||
void StreamingSearchPrefetchURLLoader::OnURLLoaderClientMojoDisconnect() {
|
||||
DCHECK(forwarding_client_);
|
||||
DCHECK(!streaming_prefetch_request_);
|
||||
- delete this;
|
||||
+ PostTaskToStopPrefetchAndDeleteSelf();
|
||||
}
|
||||
|
||||
void StreamingSearchPrefetchURLLoader::ClearOwnerPointer() {
|
||||
streaming_prefetch_request_ = nullptr;
|
||||
}
|
||||
+
|
||||
+void StreamingSearchPrefetchURLLoader::PostTaskToStopPrefetchAndDeleteSelf() {
|
||||
+ // To avoid UAF bugs, post a separate task to delete this object.
|
||||
+ if (stop_prefetch_closure_) {
|
||||
+ base::SequencedTaskRunnerHandle::Get()->PostTask(
|
||||
+ FROM_HERE, std::move(stop_prefetch_closure_));
|
||||
+ }
|
||||
+}
|
||||
diff --git a/chrome/browser/prefetch/search_prefetch/streaming_search_prefetch_url_loader.h b/chrome/browser/prefetch/search_prefetch/streaming_search_prefetch_url_loader.h
|
||||
index 2213fb079e3f29566d67030dd2fa399ce11024e2..ed225db0b4d2b0d24aae967f320a7010c1a45044 100644
|
||||
--- a/chrome/browser/prefetch/search_prefetch/streaming_search_prefetch_url_loader.h
|
||||
+++ b/chrome/browser/prefetch/search_prefetch/streaming_search_prefetch_url_loader.h
|
||||
@@ -39,7 +39,8 @@ class StreamingSearchPrefetchURLLoader : public network::mojom::URLLoader,
|
||||
StreamingSearchPrefetchRequest* streaming_prefetch_request,
|
||||
Profile* profile,
|
||||
std::unique_ptr<network::ResourceRequest> resource_request,
|
||||
- const net::NetworkTrafficAnnotationTag& network_traffic_annotation);
|
||||
+ const net::NetworkTrafficAnnotationTag& network_traffic_annotation,
|
||||
+ base::OnceClosure stop_prefetch_closure);
|
||||
|
||||
~StreamingSearchPrefetchURLLoader() override;
|
||||
|
||||
@@ -105,6 +106,9 @@ class StreamingSearchPrefetchURLLoader : public network::mojom::URLLoader,
|
||||
// Clears |producer_handle_| and |handle_watcher_|.
|
||||
void Finish();
|
||||
|
||||
+ // Post a task to delete this object by running stop_prefetch_closure_.
|
||||
+ void PostTaskToStopPrefetchAndDeleteSelf();
|
||||
+
|
||||
// Sets up mojo forwarding to the navigation path. Resumes
|
||||
// |network_url_loader_| calls. Serves the start of the response to the
|
||||
// navigation path. After this method is called, |this| manages its own
|
||||
@@ -164,6 +168,9 @@ class StreamingSearchPrefetchURLLoader : public network::mojom::URLLoader,
|
||||
mojo::ScopedDataPipeProducerHandle producer_handle_;
|
||||
std::unique_ptr<mojo::SimpleWatcher> handle_watcher_;
|
||||
|
||||
+ // Closure to cancel this prefetch. Running this callback will destroy |this|.
|
||||
+ base::OnceClosure stop_prefetch_closure_;
|
||||
+
|
||||
base::WeakPtrFactory<StreamingSearchPrefetchURLLoader> weak_factory_{this};
|
||||
};
|
||||
|
||||
157
patches/chromium/cherry-pick-1281979.patch
Normal file
157
patches/chromium/cherry-pick-1281979.patch
Normal file
@@ -0,0 +1,157 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Etienne Bergeron <etienneb@chromium.org>
|
||||
Date: Wed, 5 Jan 2022 23:37:26 +0000
|
||||
Subject: Fix race condition while initializing GPU Watchdog
|
||||
|
||||
This CL is fixing a race condition detected by TSAN.
|
||||
see: crbug/1281979
|
||||
|
||||
The race condition is between these two functions:
|
||||
base::PowerMonitor::IsInitialized() and
|
||||
base::PowerMonitor::Initialize(...)
|
||||
|
||||
The power monitor doesn't need to be initialized to add
|
||||
observers. In fact, the power monitor initialization
|
||||
is for plugging a power monitor source. Observers can be
|
||||
safely added/removed.
|
||||
|
||||
R=fdoray@chromium.org
|
||||
|
||||
Bug: 1281979
|
||||
Change-Id: Icaecd877d4b0cf5e79d7fe6a096f9d76d932b076
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3367395
|
||||
Reviewed-by: Maggie Chen <magchen@chromium.org>
|
||||
Commit-Queue: Etienne Bergeron <etienneb@chromium.org>
|
||||
Cr-Commit-Position: refs/heads/main@{#955944}
|
||||
|
||||
diff --git a/gpu/ipc/service/gpu_watchdog_thread.cc b/gpu/ipc/service/gpu_watchdog_thread.cc
|
||||
index ecf8e17ce4183bfe2f22a9a6d666a60828f078a2..c518f978e602eda3cfa150bd8e9e07f7f7fc749b 100644
|
||||
--- a/gpu/ipc/service/gpu_watchdog_thread.cc
|
||||
+++ b/gpu/ipc/service/gpu_watchdog_thread.cc
|
||||
@@ -36,9 +36,6 @@
|
||||
#endif
|
||||
|
||||
namespace gpu {
|
||||
-namespace {
|
||||
-constexpr int64_t kDelayForAddPowerObserverInMs = 50;
|
||||
-}
|
||||
|
||||
base::TimeDelta GetGpuWatchdogTimeout() {
|
||||
std::string timeout_str =
|
||||
@@ -176,14 +173,11 @@ void GpuWatchdogThread::OnInitComplete() {
|
||||
base::Unretained(this)));
|
||||
Disarm();
|
||||
|
||||
- // Use a delayed task for AddPowerObserver. The PowerMonitor is initialized in
|
||||
- // ChildThreadImpl::Init right after GpuInit::InitializeAndStartSandbox which
|
||||
- // calls OnInitComplete() at the end if no errors.
|
||||
- task_runner()->PostDelayedTask(
|
||||
- FROM_HERE,
|
||||
- base::BindOnce(&GpuWatchdogThread::AddPowerObserver,
|
||||
- base::Unretained(this)),
|
||||
- base::TimeDelta::FromMilliseconds(kDelayForAddPowerObserverInMs));
|
||||
+ // The PowerMonitorObserver needs to be register on the watchdog thread so the
|
||||
+ // notifications are delivered on that thread.
|
||||
+ task_runner()->PostTask(FROM_HERE,
|
||||
+ base::BindOnce(&GpuWatchdogThread::AddPowerObserver,
|
||||
+ base::Unretained(this)));
|
||||
}
|
||||
|
||||
// Called from the gpu thread in viz::GpuServiceImpl::~GpuServiceImpl().
|
||||
@@ -296,26 +290,12 @@ void GpuWatchdogThread::OnResume() {
|
||||
void GpuWatchdogThread::AddPowerObserver() {
|
||||
DCHECK(watchdog_thread_task_runner_->BelongsToCurrentThread());
|
||||
|
||||
- // The Observer can only be added after the power monitor is initialized.
|
||||
- // When this function is called, PowerMonitor is probably ready.
|
||||
- if (base::PowerMonitor::IsInitialized()) {
|
||||
- bool is_system_suspended =
|
||||
- base::PowerMonitor::AddPowerSuspendObserverAndReturnSuspendedState(
|
||||
- this);
|
||||
- if (is_system_suspended) {
|
||||
- StopWatchdogTimeoutTask(kPowerSuspendResume);
|
||||
- }
|
||||
-
|
||||
- is_power_observer_added_ = true;
|
||||
- } else {
|
||||
- // Just in case PowerMonitor is not ready.
|
||||
- // It usually takes hundreds of milliseconds to finish the whole GPU
|
||||
- // initialization. Try again in 100 ms.
|
||||
- task_runner()->PostDelayedTask(
|
||||
- FROM_HERE,
|
||||
- base::BindOnce(&GpuWatchdogThread::AddPowerObserver, weak_ptr_),
|
||||
- base::TimeDelta::FromMilliseconds(100));
|
||||
- }
|
||||
+ // Adding the Observer to the power monitor is safe even if power monitor is
|
||||
+ // not yet initialized.
|
||||
+ bool is_system_suspended =
|
||||
+ base::PowerMonitor::AddPowerSuspendObserverAndReturnSuspendedState(this);
|
||||
+ if (is_system_suspended)
|
||||
+ StopWatchdogTimeoutTask(kPowerSuspendResume);
|
||||
}
|
||||
|
||||
// Running on the watchdog thread.
|
||||
@@ -638,7 +618,6 @@ void GpuWatchdogThread::DeliberatelyTerminateToRecoverFromHang() {
|
||||
base::debug::Alias(&in_power_suspension_);
|
||||
base::debug::Alias(&in_gpu_process_teardown_);
|
||||
base::debug::Alias(&is_backgrounded_);
|
||||
- base::debug::Alias(&is_power_observer_added_);
|
||||
base::debug::Alias(&last_on_watchdog_timeout_timeticks_);
|
||||
base::TimeDelta timeticks_elapses =
|
||||
function_begin_timeticks - last_on_watchdog_timeout_timeticks_;
|
||||
@@ -843,17 +822,4 @@ bool GpuWatchdogThread::IsGpuHangDetectedForTesting() {
|
||||
return test_result_timeout_and_gpu_hang_.IsSet();
|
||||
}
|
||||
|
||||
-// This should be called on the test main thread only. It will wait until the
|
||||
-// power observer is added on the watchdog thread.
|
||||
-void GpuWatchdogThread::WaitForPowerObserverAddedForTesting() {
|
||||
- DCHECK(watched_gpu_task_runner_->BelongsToCurrentThread());
|
||||
-
|
||||
- base::WaitableEvent event;
|
||||
- task_runner()->PostDelayedTask(
|
||||
- FROM_HERE,
|
||||
- base::BindOnce(&base::WaitableEvent::Signal, base::Unretained(&event)),
|
||||
- base::TimeDelta::FromMilliseconds(kDelayForAddPowerObserverInMs));
|
||||
- event.Wait();
|
||||
-}
|
||||
-
|
||||
} // namespace gpu
|
||||
diff --git a/gpu/ipc/service/gpu_watchdog_thread.h b/gpu/ipc/service/gpu_watchdog_thread.h
|
||||
index d0d20dfc7c9fd7e13896e212673519ec5233c562..622647a68ee2bc2e3d18e58bbcfb3c7f90b3102c 100644
|
||||
--- a/gpu/ipc/service/gpu_watchdog_thread.h
|
||||
+++ b/gpu/ipc/service/gpu_watchdog_thread.h
|
||||
@@ -121,8 +121,6 @@ class GPU_IPC_SERVICE_EXPORT GpuWatchdogThread
|
||||
// For gpu testing only. Return status for the watchdog tests
|
||||
bool IsGpuHangDetectedForTesting();
|
||||
|
||||
- void WaitForPowerObserverAddedForTesting();
|
||||
-
|
||||
// Implements base::Thread.
|
||||
void Init() override;
|
||||
void CleanUp() override;
|
||||
@@ -291,10 +289,6 @@ class GPU_IPC_SERVICE_EXPORT GpuWatchdogThread
|
||||
// The GPU watchdog is paused. The timeout task is temporarily stopped.
|
||||
bool is_paused_ = false;
|
||||
|
||||
- // Whether the watchdog thread has added the power monitor observer.
|
||||
- // Read/Write by the watchdog thread only.
|
||||
- bool is_power_observer_added_ = false;
|
||||
-
|
||||
// whether GpuWatchdogThreadEvent::kGpuWatchdogStart has been recorded.
|
||||
bool is_watchdog_start_histogram_recorded = false;
|
||||
|
||||
diff --git a/gpu/ipc/service/gpu_watchdog_thread_unittest.cc b/gpu/ipc/service/gpu_watchdog_thread_unittest.cc
|
||||
index ca2006a45dd87bad106b0f75bfe8475fa1090038..b44cdd7e22686ab37c57461291676f01512fd623 100644
|
||||
--- a/gpu/ipc/service/gpu_watchdog_thread_unittest.cc
|
||||
+++ b/gpu/ipc/service/gpu_watchdog_thread_unittest.cc
|
||||
@@ -81,9 +81,6 @@ void GpuWatchdogPowerTest::SetUp() {
|
||||
|
||||
// Report GPU init complete.
|
||||
watchdog_thread_->OnInitComplete();
|
||||
-
|
||||
- // Wait until the power observer is added on the watchdog thread
|
||||
- watchdog_thread_->WaitForPowerObserverAddedForTesting();
|
||||
}
|
||||
|
||||
void GpuWatchdogPowerTest::TearDown() {
|
||||
31
patches/chromium/cherry-pick-1282354.patch
Normal file
31
patches/chromium/cherry-pick-1282354.patch
Normal file
@@ -0,0 +1,31 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Chris Bookholt <bookholt@chromium.org>
|
||||
Date: Tue, 11 Jan 2022 00:33:53 +0000
|
||||
Subject: ServiceWorkerContainerHost::EnsureFileAccess: abort request
|
||||
processing if the requesting process lacks file access
|
||||
|
||||
Bug: 1282354
|
||||
Change-Id: Ia37ef5b97eedb0d2ad25ffe2869844a40e5be862
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3379268
|
||||
Reviewed-by: Hiroki Nakagawa <nhiroki@chromium.org>
|
||||
Commit-Queue: Chris Bookholt <bookholt@chromium.org>
|
||||
Cr-Commit-Position: refs/heads/main@{#957344}
|
||||
|
||||
diff --git a/content/browser/service_worker/service_worker_container_host.cc b/content/browser/service_worker/service_worker_container_host.cc
|
||||
index 82498632c53883b5d84fb0a2e5246c98e71ef00d..f13416b0cd611ddcf18053f7a543a9a423635227 100644
|
||||
--- a/content/browser/service_worker/service_worker_container_host.cc
|
||||
+++ b/content/browser/service_worker/service_worker_container_host.cc
|
||||
@@ -379,10 +379,12 @@ void ServiceWorkerContainerHost::EnsureFileAccess(
|
||||
ChildProcessSecurityPolicyImpl* policy =
|
||||
ChildProcessSecurityPolicyImpl::GetInstance();
|
||||
for (const auto& file : file_paths) {
|
||||
- if (!policy->CanReadFile(process_id_, file))
|
||||
+ if (!policy->CanReadFile(process_id_, file)) {
|
||||
mojo::ReportBadMessage(
|
||||
"The renderer doesn't have access to the file "
|
||||
"but it tried to grant access to the controller.");
|
||||
+ return;
|
||||
+ }
|
||||
|
||||
if (!policy->CanReadFile(controller_process_id, file))
|
||||
policy->GrantReadFile(controller_process_id, file);
|
||||
28
patches/chromium/cherry-pick-1283198.patch
Normal file
28
patches/chromium/cherry-pick-1283198.patch
Normal file
@@ -0,0 +1,28 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Daniel Hosseinian <dhoss@chromium.org>
|
||||
Date: Thu, 30 Dec 2021 05:08:29 +0000
|
||||
Subject: CHECK page on thumbnail requests
|
||||
|
||||
Elevate DCHECK to CHECK.
|
||||
|
||||
Fixed: 1283198
|
||||
Change-Id: Iacb3da961cfb44f94f7a377e225270a57809ef9c
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3361538
|
||||
Auto-Submit: Daniel Hosseinian <dhoss@chromium.org>
|
||||
Reviewed-by: K. Moon <kmoon@chromium.org>
|
||||
Commit-Queue: K. Moon <kmoon@chromium.org>
|
||||
Cr-Commit-Position: refs/heads/main@{#954552}
|
||||
|
||||
diff --git a/pdf/pdfium/pdfium_engine.cc b/pdf/pdfium/pdfium_engine.cc
|
||||
index 341b183948b15f72edca6f8620c5039593d16a90..2b128d8fdde8048c1f8b92ec2e38f485feca2bf4 100644
|
||||
--- a/pdf/pdfium/pdfium_engine.cc
|
||||
+++ b/pdf/pdfium/pdfium_engine.cc
|
||||
@@ -4273,7 +4273,7 @@ void PDFiumEngine::SetLinkUnderCursorForAnnotation(FPDF_ANNOTATION annot,
|
||||
void PDFiumEngine::RequestThumbnail(int page_index,
|
||||
float device_pixel_ratio,
|
||||
SendThumbnailCallback send_callback) {
|
||||
- DCHECK(PageIndexInBounds(page_index));
|
||||
+ CHECK(PageIndexInBounds(page_index));
|
||||
|
||||
// Thumbnails cannot be generated in the middle of a progressive paint of a
|
||||
// page. Generate the thumbnail immediately only if the page is not currently
|
||||
138
patches/chromium/cherry-pick-1283371.patch
Normal file
138
patches/chromium/cherry-pick-1283371.patch
Normal file
@@ -0,0 +1,138 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Clark DuVall <cduvall@chromium.org>
|
||||
Date: Thu, 6 Jan 2022 01:21:21 +0000
|
||||
Subject: Fix lifetime bug in PrefetchURLLoader
|
||||
|
||||
PrefetchURLLoader is now owned by PrefetchURLLoaderService, which is no
|
||||
longer refcounted. This makes the lifetime much easier to reason about.
|
||||
|
||||
Bug: 1283371
|
||||
Change-Id: Iaa58c1f44cc9f066459ce344012f57faca533197
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3361198
|
||||
Reviewed-by: John Abd-El-Malek <jam@chromium.org>
|
||||
Reviewed-by: Kunihiko Sakamoto <ksakamoto@chromium.org>
|
||||
Commit-Queue: Clark DuVall <cduvall@chromium.org>
|
||||
Cr-Commit-Position: refs/heads/main@{#955986}
|
||||
|
||||
diff --git a/content/browser/loader/prefetch_url_loader_service.cc b/content/browser/loader/prefetch_url_loader_service.cc
|
||||
index 5211d5552d6b2e1c1967d7dd6c6079001fef6895..345bf021541a121ea183ba16fa7ed76373f0dfd1 100644
|
||||
--- a/content/browser/loader/prefetch_url_loader_service.cc
|
||||
+++ b/content/browser/loader/prefetch_url_loader_service.cc
|
||||
@@ -202,29 +202,25 @@ void PrefetchURLLoaderService::CreateLoaderAndStart(
|
||||
->prefetched_signed_exchange_cache;
|
||||
}
|
||||
|
||||
- // For now we make self owned receiver for the loader to the request, while we
|
||||
- // can also possibly make the new loader owned by the factory so that they can
|
||||
- // live longer than the client (i.e. run in detached mode).
|
||||
- // TODO(kinuko): Revisit this.
|
||||
- mojo::MakeSelfOwnedReceiver(
|
||||
- std::make_unique<PrefetchURLLoader>(
|
||||
- request_id, options, current_context.frame_tree_node_id,
|
||||
- resource_request,
|
||||
- resource_request.trusted_params
|
||||
- ? resource_request.trusted_params->isolation_info
|
||||
- .network_isolation_key()
|
||||
- : current_context.render_frame_host->GetNetworkIsolationKey(),
|
||||
- std::move(client), traffic_annotation,
|
||||
- std::move(network_loader_factory_to_use),
|
||||
- base::BindRepeating(
|
||||
- &PrefetchURLLoaderService::CreateURLLoaderThrottles, this,
|
||||
- resource_request, current_context.frame_tree_node_id),
|
||||
- browser_context_, signed_exchange_prefetch_metric_recorder_,
|
||||
- std::move(prefetched_signed_exchange_cache), accept_langs_,
|
||||
- base::BindOnce(
|
||||
- &PrefetchURLLoaderService::GenerateRecursivePrefetchToken, this,
|
||||
- current_context.weak_ptr_factory.GetWeakPtr())),
|
||||
- std::move(receiver));
|
||||
+ // base::Unretained is safe here since |this| owns the loader.
|
||||
+ auto loader = std::make_unique<PrefetchURLLoader>(
|
||||
+ request_id, options, current_context.frame_tree_node_id, resource_request,
|
||||
+ resource_request.trusted_params
|
||||
+ ? resource_request.trusted_params->isolation_info
|
||||
+ .network_isolation_key()
|
||||
+ : current_context.render_frame_host->GetNetworkIsolationKey(),
|
||||
+ std::move(client), traffic_annotation,
|
||||
+ std::move(network_loader_factory_to_use),
|
||||
+ base::BindRepeating(&PrefetchURLLoaderService::CreateURLLoaderThrottles,
|
||||
+ base::Unretained(this), resource_request,
|
||||
+ current_context.frame_tree_node_id),
|
||||
+ browser_context_, signed_exchange_prefetch_metric_recorder_,
|
||||
+ std::move(prefetched_signed_exchange_cache), accept_langs_,
|
||||
+ base::BindOnce(&PrefetchURLLoaderService::GenerateRecursivePrefetchToken,
|
||||
+ base::Unretained(this),
|
||||
+ current_context.weak_ptr_factory.GetWeakPtr()));
|
||||
+ auto* raw_loader = loader.get();
|
||||
+ prefetch_receivers_.Add(raw_loader, std::move(receiver), std::move(loader));
|
||||
}
|
||||
|
||||
PrefetchURLLoaderService::~PrefetchURLLoaderService() = default;
|
||||
diff --git a/content/browser/loader/prefetch_url_loader_service.h b/content/browser/loader/prefetch_url_loader_service.h
|
||||
index 210794966c8d25947f3e6b490538c1f851d80d52..c5fff844f73deaf2912716de9cf97547c498e4e5 100644
|
||||
--- a/content/browser/loader/prefetch_url_loader_service.h
|
||||
+++ b/content/browser/loader/prefetch_url_loader_service.h
|
||||
@@ -35,13 +35,11 @@ class URLLoaderFactoryGetter;
|
||||
// prefetches. The renderer uses it for prefetch requests including <link
|
||||
// rel="prefetch">.
|
||||
class CONTENT_EXPORT PrefetchURLLoaderService final
|
||||
- : public base::RefCountedThreadSafe<
|
||||
- PrefetchURLLoaderService,
|
||||
- content::BrowserThread::DeleteOnUIThread>,
|
||||
- public blink::mojom::RendererPreferenceWatcher,
|
||||
+ : public blink::mojom::RendererPreferenceWatcher,
|
||||
public network::mojom::URLLoaderFactory {
|
||||
public:
|
||||
explicit PrefetchURLLoaderService(BrowserContext* browser_context);
|
||||
+ ~PrefetchURLLoaderService() override;
|
||||
|
||||
void GetFactory(
|
||||
mojo::PendingReceiver<network::mojom::URLLoaderFactory> receiver,
|
||||
@@ -67,12 +65,8 @@ class CONTENT_EXPORT PrefetchURLLoaderService final
|
||||
}
|
||||
|
||||
private:
|
||||
- friend class base::DeleteHelper<content::PrefetchURLLoaderService>;
|
||||
- friend struct BrowserThread::DeleteOnThread<BrowserThread::UI>;
|
||||
struct BindContext;
|
||||
|
||||
- ~PrefetchURLLoaderService() override;
|
||||
-
|
||||
// network::mojom::URLLoaderFactory:
|
||||
void CreateLoaderAndStart(
|
||||
mojo::PendingReceiver<network::mojom::URLLoader> receiver,
|
||||
@@ -114,6 +108,9 @@ class CONTENT_EXPORT PrefetchURLLoaderService final
|
||||
mojo::ReceiverSet<network::mojom::URLLoaderFactory,
|
||||
std::unique_ptr<BindContext>>
|
||||
loader_factory_receivers_;
|
||||
+ mojo::ReceiverSet<network::mojom::URLLoader,
|
||||
+ std::unique_ptr<network::mojom::URLLoader>>
|
||||
+ prefetch_receivers_;
|
||||
// Used in the IO thread.
|
||||
mojo::Receiver<blink::mojom::RendererPreferenceWatcher>
|
||||
preference_watcher_receiver_{this};
|
||||
diff --git a/content/browser/storage_partition_impl.cc b/content/browser/storage_partition_impl.cc
|
||||
index ae284e031a6e051bda49258d54a2e62332773c70..e9af32dd2dc6ae75ded55b1ffd3fe7881408eefc 100644
|
||||
--- a/content/browser/storage_partition_impl.cc
|
||||
+++ b/content/browser/storage_partition_impl.cc
|
||||
@@ -1321,7 +1321,7 @@ void StoragePartitionImpl::Initialize(
|
||||
blob_context, filesystem_context_, fallback_blob_registry);
|
||||
|
||||
prefetch_url_loader_service_ =
|
||||
- base::MakeRefCounted<PrefetchURLLoaderService>(browser_context_);
|
||||
+ std::make_unique<PrefetchURLLoaderService>(browser_context_);
|
||||
|
||||
cookie_store_manager_ =
|
||||
std::make_unique<CookieStoreManager>(service_worker_context_);
|
||||
diff --git a/content/browser/storage_partition_impl.h b/content/browser/storage_partition_impl.h
|
||||
index 6f3a482ae16e88271768a3f91c633201f435e271..02209f615202a987d83e72895b0782cac8a8fccd 100644
|
||||
--- a/content/browser/storage_partition_impl.h
|
||||
+++ b/content/browser/storage_partition_impl.h
|
||||
@@ -552,7 +552,7 @@ class CONTENT_EXPORT StoragePartitionImpl
|
||||
std::unique_ptr<BroadcastChannelProvider> broadcast_channel_provider_;
|
||||
std::unique_ptr<BluetoothAllowedDevicesMap> bluetooth_allowed_devices_map_;
|
||||
scoped_refptr<BlobRegistryWrapper> blob_registry_;
|
||||
- scoped_refptr<PrefetchURLLoaderService> prefetch_url_loader_service_;
|
||||
+ std::unique_ptr<PrefetchURLLoaderService> prefetch_url_loader_service_;
|
||||
std::unique_ptr<CookieStoreManager> cookie_store_manager_;
|
||||
scoped_refptr<BucketContext> bucket_context_;
|
||||
scoped_refptr<GeneratedCodeCacheContext> generated_code_cache_context_;
|
||||
74
patches/chromium/cherry-pick-1283375.patch
Normal file
74
patches/chromium/cherry-pick-1283375.patch
Normal file
@@ -0,0 +1,74 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Alan Screen <awscreen@chromium.org>
|
||||
Date: Fri, 7 Jan 2022 09:38:01 +0000
|
||||
Subject: Ensure valid print render host before proceeding to print.
|
||||
|
||||
Bug: 1283375
|
||||
Change-Id: I5691fc2a9d09040e777aafd0061b957025643b8a
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3369086
|
||||
Reviewed-by: Lei Zhang <thestig@chromium.org>
|
||||
Commit-Queue: Alan Screen <awscreen@chromium.org>
|
||||
Cr-Commit-Position: refs/heads/main@{#956443}
|
||||
|
||||
diff --git a/chrome/browser/printing/print_view_manager.cc b/chrome/browser/printing/print_view_manager.cc
|
||||
index 4662db344afb08574b7ac7d96cb72c71edc802af..c7535ddd5b54ae33fe6f6aea09b6b313ba38b840 100644
|
||||
--- a/chrome/browser/printing/print_view_manager.cc
|
||||
+++ b/chrome/browser/printing/print_view_manager.cc
|
||||
@@ -111,6 +111,11 @@ bool PrintViewManager::PrintForSystemDialogNow(
|
||||
on_print_dialog_shown_callback_ = std::move(dialog_shown_callback);
|
||||
is_switching_to_system_dialog_ = true;
|
||||
|
||||
+ // Remember the ID for `print_preview_rfh_`, to enable checking that the
|
||||
+ // `RenderFrameHost` is still valid after a possible inner message loop runs
|
||||
+ // in `DisconnectFromCurrentPrintJob()`.
|
||||
+ content::GlobalRenderFrameHostId rfh_id = print_preview_rfh_->GetGlobalId();
|
||||
+
|
||||
auto weak_this = weak_factory_.GetWeakPtr();
|
||||
DisconnectFromCurrentPrintJob();
|
||||
if (!weak_this)
|
||||
@@ -120,6 +125,10 @@ bool PrintViewManager::PrintForSystemDialogNow(
|
||||
if (IsCrashed())
|
||||
return false;
|
||||
|
||||
+ // Don't print if `print_preview_rfh_` is no longer live.
|
||||
+ if (!content::RenderFrameHost::FromID(rfh_id))
|
||||
+ return false;
|
||||
+
|
||||
// TODO(crbug.com/809738) Register with `PrintBackendServiceManager` when
|
||||
// system print is enabled out-of-process.
|
||||
|
||||
diff --git a/chrome/browser/printing/print_view_manager_base.cc b/chrome/browser/printing/print_view_manager_base.cc
|
||||
index 143ee383668965ba04da092e3445fc9f4a33a433..055d97cb63cb5a1b64ee0a113ec27b664113aba9 100644
|
||||
--- a/chrome/browser/printing/print_view_manager_base.cc
|
||||
+++ b/chrome/browser/printing/print_view_manager_base.cc
|
||||
@@ -39,6 +39,7 @@
|
||||
#include "components/services/print_compositor/public/cpp/print_service_mojo_types.h"
|
||||
#include "content/public/browser/browser_task_traits.h"
|
||||
#include "content/public/browser/browser_thread.h"
|
||||
+#include "content/public/browser/global_routing_id.h"
|
||||
#include "content/public/browser/notification_details.h"
|
||||
#include "content/public/browser/notification_service.h"
|
||||
#include "content/public/browser/notification_source.h"
|
||||
@@ -365,6 +366,11 @@ bool PrintViewManagerBase::PrintNow(content::RenderFrameHost* rfh,
|
||||
bool silent,
|
||||
base::Value settings,
|
||||
CompletionCallback callback) {
|
||||
+ // Remember the ID for `rfh`, to enable checking that the `RenderFrameHost`
|
||||
+ // is still valid after a possible inner message loop runs in
|
||||
+ // `DisconnectFromCurrentPrintJob()`.
|
||||
+ content::GlobalRenderFrameHostId rfh_id = rfh->GetGlobalId();
|
||||
+
|
||||
auto weak_this = weak_ptr_factory_.GetWeakPtr();
|
||||
DisconnectFromCurrentPrintJob();
|
||||
if (!weak_this)
|
||||
@@ -374,6 +380,10 @@ bool PrintViewManagerBase::PrintNow(content::RenderFrameHost* rfh,
|
||||
if (IsCrashed())
|
||||
return false;
|
||||
|
||||
+ // Don't print if `rfh` is no longer live.
|
||||
+ if (!content::RenderFrameHost::FromID(rfh_id))
|
||||
+ return false;
|
||||
+
|
||||
// TODO(crbug.com/809738) Register with `PrintBackendServiceManager` when
|
||||
// system print is enabled out-of-process. A corresponding unregister should
|
||||
// go in `ReleasePrintJob()`.
|
||||
188
patches/chromium/cherry-pick-1284367.patch
Normal file
188
patches/chromium/cherry-pick-1284367.patch
Normal file
@@ -0,0 +1,188 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Xinghui Lu <xinghuilu@chromium.org>
|
||||
Date: Thu, 6 Jan 2022 08:36:45 +0000
|
||||
Subject: Use RFH global id to ensure the RFH is valid.
|
||||
|
||||
Observing via RenderFrameDeleted and RenderFrameHostChanged is not
|
||||
sufficient for validating the RFH is still valid, because the frames
|
||||
can belong to inner WebContents. As suggested in
|
||||
https://crrev.com/c/2449389, storing a GlobalFrameRoutingId is the
|
||||
preferred method of keeping a reference to a RFH.
|
||||
|
||||
Bug: 1284367
|
||||
Change-Id: I3afb40e394d6e2e7fd19b2704e0dd68fa23c7bb2
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3367466
|
||||
Reviewed-by: Daniel Rubery <drubery@chromium.org>
|
||||
Commit-Queue: Xinghui Lu <xinghuilu@chromium.org>
|
||||
Cr-Commit-Position: refs/heads/main@{#956061}
|
||||
|
||||
diff --git a/chrome/browser/safe_browsing/threat_details_unittest.cc b/chrome/browser/safe_browsing/threat_details_unittest.cc
|
||||
index ab395a814221a900976fb5f1cdfd79946ea1b742..4bf428b1a7fc8c331d0644c0785f4e57a31c0884 100644
|
||||
--- a/chrome/browser/safe_browsing/threat_details_unittest.cc
|
||||
+++ b/chrome/browser/safe_browsing/threat_details_unittest.cc
|
||||
@@ -601,7 +601,8 @@ TEST_F(ThreatDetailsTest, ThreatDOMDetails) {
|
||||
parent_node->children.push_back(GURL(kDOMChildURL));
|
||||
params.push_back(std::move(parent_node));
|
||||
report->OnReceivedThreatDOMDetails(mojo::Remote<mojom::ThreatReporter>(),
|
||||
- main_rfh(), std::move(params));
|
||||
+ main_rfh()->GetGlobalId(),
|
||||
+ std::move(params));
|
||||
|
||||
std::string serialized = WaitForThreatDetailsDone(
|
||||
report.get(), false /* did_proceed*/, 0 /* num_visit */);
|
||||
@@ -820,10 +821,11 @@ TEST_F(ThreatDetailsTest, ThreatDOMDetails_MultipleFrames) {
|
||||
|
||||
// Send both sets of nodes from different render frames.
|
||||
report->OnReceivedThreatDOMDetails(mojo::Remote<mojom::ThreatReporter>(),
|
||||
- main_rfh(),
|
||||
+ main_rfh()->GetGlobalId(),
|
||||
std::move(outer_params_copy));
|
||||
report->OnReceivedThreatDOMDetails(mojo::Remote<mojom::ThreatReporter>(),
|
||||
- child_rfh, std::move(inner_params_copy));
|
||||
+ child_rfh->GetGlobalId(),
|
||||
+ std::move(inner_params_copy));
|
||||
|
||||
std::string serialized = WaitForThreatDetailsDone(
|
||||
report.get(), false /* did_proceed*/, 0 /* num_visit */);
|
||||
@@ -869,9 +871,11 @@ TEST_F(ThreatDetailsTest, ThreatDOMDetails_MultipleFrames) {
|
||||
|
||||
// Send both sets of nodes from different render frames.
|
||||
report->OnReceivedThreatDOMDetails(mojo::Remote<mojom::ThreatReporter>(),
|
||||
- child_rfh, std::move(inner_params));
|
||||
+ child_rfh->GetGlobalId(),
|
||||
+ std::move(inner_params));
|
||||
report->OnReceivedThreatDOMDetails(mojo::Remote<mojom::ThreatReporter>(),
|
||||
- main_rfh(), std::move(outer_params));
|
||||
+ main_rfh()->GetGlobalId(),
|
||||
+ std::move(outer_params));
|
||||
|
||||
std::string serialized = WaitForThreatDetailsDone(
|
||||
report.get(), false /* did_proceed*/, 0 /* num_visit */);
|
||||
@@ -995,9 +999,11 @@ TEST_F(ThreatDetailsTest, ThreatDOMDetails_AmbiguousDOM) {
|
||||
|
||||
// Send both sets of nodes from different render frames.
|
||||
report->OnReceivedThreatDOMDetails(mojo::Remote<mojom::ThreatReporter>(),
|
||||
- main_rfh(), std::move(outer_params));
|
||||
+ main_rfh()->GetGlobalId(),
|
||||
+ std::move(outer_params));
|
||||
report->OnReceivedThreatDOMDetails(mojo::Remote<mojom::ThreatReporter>(),
|
||||
- child_rfh, std::move(inner_params));
|
||||
+ child_rfh->GetGlobalId(),
|
||||
+ std::move(inner_params));
|
||||
std::string serialized = WaitForThreatDetailsDone(
|
||||
report.get(), false /* did_proceed*/, 0 /* num_visit */);
|
||||
ClientSafeBrowsingReportRequest actual;
|
||||
@@ -1262,10 +1268,10 @@ TEST_F(ThreatDetailsTest, ThreatDOMDetails_TrimToAdTags) {
|
||||
|
||||
// Send both sets of nodes from different render frames.
|
||||
trimmed_report->OnReceivedThreatDOMDetails(
|
||||
- mojo::Remote<mojom::ThreatReporter>(), child_rfh,
|
||||
+ mojo::Remote<mojom::ThreatReporter>(), child_rfh->GetGlobalId(),
|
||||
std::move(inner_params));
|
||||
trimmed_report->OnReceivedThreatDOMDetails(
|
||||
- mojo::Remote<mojom::ThreatReporter>(), main_rfh(),
|
||||
+ mojo::Remote<mojom::ThreatReporter>(), main_rfh()->GetGlobalId(),
|
||||
std::move(outer_params));
|
||||
|
||||
std::string serialized = WaitForThreatDetailsDone(
|
||||
@@ -1338,10 +1344,10 @@ TEST_F(ThreatDetailsTest, ThreatDOMDetails_EmptyReportNotSent) {
|
||||
|
||||
// Send both sets of nodes from different render frames.
|
||||
trimmed_report->OnReceivedThreatDOMDetails(
|
||||
- mojo::Remote<mojom::ThreatReporter>(), child_rfh,
|
||||
+ mojo::Remote<mojom::ThreatReporter>(), child_rfh->GetGlobalId(),
|
||||
std::move(inner_params));
|
||||
trimmed_report->OnReceivedThreatDOMDetails(
|
||||
- mojo::Remote<mojom::ThreatReporter>(), main_rfh(),
|
||||
+ mojo::Remote<mojom::ThreatReporter>(), main_rfh()->GetGlobalId(),
|
||||
std::move(outer_params));
|
||||
|
||||
std::string serialized = WaitForThreatDetailsDone(
|
||||
@@ -1598,7 +1604,8 @@ TEST_F(ThreatDetailsTest, HTTPCache) {
|
||||
// The cache collection starts after the IPC from the DOM is fired.
|
||||
std::vector<mojom::ThreatDOMDetailsNodePtr> params;
|
||||
report->OnReceivedThreatDOMDetails(mojo::Remote<mojom::ThreatReporter>(),
|
||||
- main_rfh(), std::move(params));
|
||||
+ main_rfh()->GetGlobalId(),
|
||||
+ std::move(params));
|
||||
|
||||
// Let the cache callbacks complete.
|
||||
base::RunLoop().RunUntilIdle();
|
||||
@@ -1678,7 +1685,8 @@ TEST_F(ThreatDetailsTest, HttpsResourceSanitization) {
|
||||
// The cache collection starts after the IPC from the DOM is fired.
|
||||
std::vector<mojom::ThreatDOMDetailsNodePtr> params;
|
||||
report->OnReceivedThreatDOMDetails(mojo::Remote<mojom::ThreatReporter>(),
|
||||
- main_rfh(), std::move(params));
|
||||
+ main_rfh()->GetGlobalId(),
|
||||
+ std::move(params));
|
||||
|
||||
// Let the cache callbacks complete.
|
||||
base::RunLoop().RunUntilIdle();
|
||||
@@ -1761,7 +1769,8 @@ TEST_F(ThreatDetailsTest, HTTPCacheNoEntries) {
|
||||
// The cache collection starts after the IPC from the DOM is fired.
|
||||
std::vector<mojom::ThreatDOMDetailsNodePtr> params;
|
||||
report->OnReceivedThreatDOMDetails(mojo::Remote<mojom::ThreatReporter>(),
|
||||
- main_rfh(), std::move(params));
|
||||
+ main_rfh()->GetGlobalId(),
|
||||
+ std::move(params));
|
||||
|
||||
// Let the cache callbacks complete.
|
||||
base::RunLoop().RunUntilIdle();
|
||||
@@ -1820,7 +1829,8 @@ TEST_F(ThreatDetailsTest, HistoryServiceUrls) {
|
||||
// The redirects collection starts after the IPC from the DOM is fired.
|
||||
std::vector<mojom::ThreatDOMDetailsNodePtr> params;
|
||||
report->OnReceivedThreatDOMDetails(mojo::Remote<mojom::ThreatReporter>(),
|
||||
- main_rfh(), std::move(params));
|
||||
+ main_rfh()->GetGlobalId(),
|
||||
+ std::move(params));
|
||||
|
||||
// Let the redirects callbacks complete.
|
||||
base::RunLoop().RunUntilIdle();
|
||||
diff --git a/components/safe_browsing/content/browser/threat_details.cc b/components/safe_browsing/content/browser/threat_details.cc
|
||||
index f3fe647b5d443c2a2f284289ae66d81782c5f6e8..361830189b0ab6324fe87719f36f2fa0bc948224 100644
|
||||
--- a/components/safe_browsing/content/browser/threat_details.cc
|
||||
+++ b/components/safe_browsing/content/browser/threat_details.cc
|
||||
@@ -664,16 +664,20 @@ void ThreatDetails::RequestThreatDOMDetails(content::RenderFrameHost* frame) {
|
||||
pending_render_frame_hosts_.push_back(frame);
|
||||
raw_threat_report->GetThreatDOMDetails(
|
||||
base::BindOnce(&ThreatDetails::OnReceivedThreatDOMDetails, GetWeakPtr(),
|
||||
- std::move(threat_reporter), frame));
|
||||
+ std::move(threat_reporter), frame->GetGlobalId()));
|
||||
}
|
||||
|
||||
// When the renderer is done, this is called.
|
||||
void ThreatDetails::OnReceivedThreatDOMDetails(
|
||||
mojo::Remote<mojom::ThreatReporter> threat_reporter,
|
||||
- content::RenderFrameHost* sender,
|
||||
+ content::GlobalRenderFrameHostId sender_id,
|
||||
std::vector<mojom::ThreatDOMDetailsNodePtr> params) {
|
||||
// If the RenderFrameHost was closed between sending the IPC and this callback
|
||||
// running, |sender| will be invalid.
|
||||
+ auto* sender = content::RenderFrameHost::FromID(sender_id);
|
||||
+ if (!sender) {
|
||||
+ return;
|
||||
+ }
|
||||
const auto sender_it = std::find(pending_render_frame_hosts_.begin(),
|
||||
pending_render_frame_hosts_.end(), sender);
|
||||
if (sender_it == pending_render_frame_hosts_.end()) {
|
||||
diff --git a/components/safe_browsing/content/browser/threat_details.h b/components/safe_browsing/content/browser/threat_details.h
|
||||
index 8cb89700141561aab49edc474799c9e7148b8ae8..61dcb8d9c772d223661236d99aebd1d3ebe01d3a 100644
|
||||
--- a/components/safe_browsing/content/browser/threat_details.h
|
||||
+++ b/components/safe_browsing/content/browser/threat_details.h
|
||||
@@ -24,6 +24,7 @@
|
||||
#include "components/safe_browsing/core/common/proto/csd.pb.h"
|
||||
#include "components/security_interstitials/core/unsafe_resource.h"
|
||||
#include "content/public/browser/browser_thread.h"
|
||||
+#include "content/public/browser/global_routing_id.h"
|
||||
#include "content/public/browser/web_contents_observer.h"
|
||||
#include "mojo/public/cpp/bindings/remote.h"
|
||||
|
||||
@@ -169,7 +170,7 @@ class ThreatDetails : public content::WebContentsObserver {
|
||||
|
||||
void OnReceivedThreatDOMDetails(
|
||||
mojo::Remote<mojom::ThreatReporter> threat_reporter,
|
||||
- content::RenderFrameHost* sender,
|
||||
+ content::GlobalRenderFrameHostId sender_id,
|
||||
std::vector<mojom::ThreatDOMDetailsNodePtr> params);
|
||||
|
||||
void AddRedirectUrlList(const std::vector<GURL>& urls);
|
||||
53
patches/chromium/cherry-pick-1887414c016d.patch
Normal file
53
patches/chromium/cherry-pick-1887414c016d.patch
Normal file
@@ -0,0 +1,53 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Muyao Xu <muyaoxu@google.com>
|
||||
Date: Thu, 17 Feb 2022 16:23:29 +0000
|
||||
Subject: Replace WidgetObserver::OnWidgetClosing() with OnWidgetDestroying()
|
||||
|
||||
In some cases, OnWidgetClosing() is not called when the widget is
|
||||
closed, resulting an invalid pointer |widget_| stored in
|
||||
WebContentsDisplayObserverView.
|
||||
|
||||
This CL replaces OnWidgetClosing() with OnWidgetDestroying(), which
|
||||
is recommended in crbug.com/1240365
|
||||
|
||||
(cherry picked from commit 4535fe2334d0713535adb52b641a8cb34e11333c)
|
||||
|
||||
Bug: 1291728
|
||||
Change-Id: I64fef8b30930f60220008809ee00f4385d6c3520
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3425473
|
||||
Auto-Submit: Muyao Xu <muyaoxu@google.com>
|
||||
Commit-Queue: Takumi Fujimoto <takumif@chromium.org>
|
||||
Cr-Original-Commit-Position: refs/heads/main@{#965431}
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3435985
|
||||
Reviewed-by: Michael Ershov <miersh@google.com>
|
||||
Owners-Override: Michael Ershov <miersh@google.com>
|
||||
Commit-Queue: Roger Felipe Zanoni da Silva <rzanoni@google.com>
|
||||
Cr-Commit-Position: refs/branch-heads/4664@{#1480}
|
||||
Cr-Branched-From: 24dc4ee75e01a29d390d43c9c264372a169273a7-refs/heads/main@{#929512}
|
||||
|
||||
diff --git a/chrome/browser/ui/views/media_router/web_contents_display_observer_view.cc b/chrome/browser/ui/views/media_router/web_contents_display_observer_view.cc
|
||||
index 80d33b238cd7455ec5b44d5fd966f42f690946bf..2061c2ecb476cd33ed999f180c0293641f7ac23a 100644
|
||||
--- a/chrome/browser/ui/views/media_router/web_contents_display_observer_view.cc
|
||||
+++ b/chrome/browser/ui/views/media_router/web_contents_display_observer_view.cc
|
||||
@@ -65,7 +65,7 @@ void WebContentsDisplayObserverView::OnBrowserSetLastActive(Browser* browser) {
|
||||
}
|
||||
}
|
||||
|
||||
-void WebContentsDisplayObserverView::OnWidgetClosing(views::Widget* widget) {
|
||||
+void WebContentsDisplayObserverView::OnWidgetDestroying(views::Widget* widget) {
|
||||
if (widget_)
|
||||
widget_->RemoveObserver(this);
|
||||
widget_ = nullptr;
|
||||
diff --git a/chrome/browser/ui/views/media_router/web_contents_display_observer_view.h b/chrome/browser/ui/views/media_router/web_contents_display_observer_view.h
|
||||
index 17a8ca48b1c836a82e2be5e5c605bc1837150cba..b63cf4505318a44c65585b06ec13960bad5d9e32 100644
|
||||
--- a/chrome/browser/ui/views/media_router/web_contents_display_observer_view.h
|
||||
+++ b/chrome/browser/ui/views/media_router/web_contents_display_observer_view.h
|
||||
@@ -28,7 +28,7 @@ class WebContentsDisplayObserverView : public WebContentsDisplayObserver,
|
||||
void OnBrowserSetLastActive(Browser* browser) override;
|
||||
|
||||
// views::WidgetObserver overrides:
|
||||
- void OnWidgetClosing(views::Widget* widget) override;
|
||||
+ void OnWidgetDestroying(views::Widget* widget) override;
|
||||
void OnWidgetBoundsChanged(views::Widget* widget,
|
||||
const gfx::Rect& new_bounds) override;
|
||||
|
||||
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 87caef2cf5cf56b7bf72752410648ef1d7bb9f9a..59c505707216362d3a3b662a6a531398b8f5009e 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
|
||||
@@ -21,8 +21,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>
|
||||
354
patches/chromium/cherry-pick-1a8af2da50e4.patch
Normal file
354
patches/chromium/cherry-pick-1a8af2da50e4.patch
Normal file
@@ -0,0 +1,354 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Lukasz Anforowicz <lukasza@chromium.org>
|
||||
Date: Mon, 8 Nov 2021 15:05:30 +0000
|
||||
Subject: Deleting unused field: `FetchEventPreloadHandle::url_loader`.
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
|
||||
The `FetchEventPreloadHandle::url_loader` field is not really used - it
|
||||
is only needed to keep the URLLoader alive (and this can be accomplished
|
||||
in a simpler way, by keeping the mojo::PendingRemote in the Browser
|
||||
process).
|
||||
|
||||
This CL removes the `FetchEventPreloadHandle::url_loader` field and the
|
||||
FetchEventPreloadHandle and WebFetchEventPreloadHandle types (collapsing
|
||||
these handle types into their only other remaining field:
|
||||
mojo::PendingReceiver<network::mojom::URLLoaderClient>).
|
||||
|
||||
(cherry picked from commit dbe67ccde52e30acf6a66b1b9cc83768a067fa6a)
|
||||
|
||||
Fixed: 1264477
|
||||
Change-Id: I9c9c54900d79e92ac08eeb43536c938fa84a58f8
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3252914
|
||||
Reviewed-by: Daniel Cheng <dcheng@chromium.org>
|
||||
Reviewed-by: Ben Kelly <wanderview@chromium.org>
|
||||
Reviewed-by: Hiroki Nakagawa <nhiroki@chromium.org>
|
||||
Commit-Queue: Łukasz Anforowicz <lukasza@chromium.org>
|
||||
Cr-Original-Commit-Position: refs/heads/main@{#937895}
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3262600
|
||||
Bot-Commit: Rubber Stamper <rubber-stamper@appspot.gserviceaccount.com>
|
||||
Commit-Queue: Ben Kelly <wanderview@chromium.org>
|
||||
Cr-Commit-Position: refs/branch-heads/4664@{#853}
|
||||
Cr-Branched-From: 24dc4ee75e01a29d390d43c9c264372a169273a7-refs/heads/main@{#929512}
|
||||
|
||||
diff --git a/content/browser/service_worker/service_worker_fetch_dispatcher.cc b/content/browser/service_worker/service_worker_fetch_dispatcher.cc
|
||||
index 0d034293826354f6d1b7910a6604f241ff1c8988..b980c5a0745eaf7a904c1047cbe6c5e86cef0c67 100644
|
||||
--- a/content/browser/service_worker/service_worker_fetch_dispatcher.cc
|
||||
+++ b/content/browser/service_worker/service_worker_fetch_dispatcher.cc
|
||||
@@ -449,8 +449,10 @@ class ServiceWorkerFetchDispatcher::URLLoaderAssets
|
||||
// NetworkService.
|
||||
URLLoaderAssets(
|
||||
scoped_refptr<network::SharedURLLoaderFactory> shared_url_loader_factory,
|
||||
+ mojo::PendingRemote<network::mojom::URLLoader> url_loader,
|
||||
std::unique_ptr<DelegatingURLLoaderClient> url_loader_client)
|
||||
: shared_url_loader_factory_(std::move(shared_url_loader_factory)),
|
||||
+ url_loader_(std::move(url_loader)),
|
||||
url_loader_client_(std::move(url_loader_client)) {}
|
||||
|
||||
void MaybeReportToDevTools(std::pair<int, int> worker_id,
|
||||
@@ -467,6 +469,7 @@ class ServiceWorkerFetchDispatcher::URLLoaderAssets
|
||||
|
||||
// NetworkService:
|
||||
scoped_refptr<network::SharedURLLoaderFactory> shared_url_loader_factory_;
|
||||
+ mojo::PendingRemote<network::mojom::URLLoader> url_loader_;
|
||||
|
||||
// Both:
|
||||
std::unique_ptr<DelegatingURLLoaderClient> url_loader_client_;
|
||||
@@ -633,7 +636,8 @@ void ServiceWorkerFetchDispatcher::DispatchFetchEvent() {
|
||||
auto params = blink::mojom::DispatchFetchEventParams::New();
|
||||
params->request = std::move(request_);
|
||||
params->client_id = client_id_;
|
||||
- params->preload_handle = std::move(preload_handle_);
|
||||
+ params->preload_url_loader_client_receiver =
|
||||
+ std::move(preload_url_loader_client_receiver_);
|
||||
params->is_offline_capability_check = is_offline_capability_check_;
|
||||
|
||||
// TODO(https://crbug.com/900700): Make the remote connected to a receiver
|
||||
@@ -721,13 +725,9 @@ bool ServiceWorkerFetchDispatcher::MaybeStartNavigationPreload(
|
||||
// When the fetch event is for an offline capability check, respond to the
|
||||
// navigation preload with a network disconnected error, to simulate offline.
|
||||
if (is_offline_capability_check_) {
|
||||
- mojo::PendingRemote<network::mojom::URLLoader> url_loader_to_pass;
|
||||
mojo::Remote<network::mojom::URLLoaderClient> url_loader_client;
|
||||
- auto dummy_receiver = url_loader_to_pass.InitWithNewPipeAndPassReceiver();
|
||||
|
||||
- preload_handle_ = blink::mojom::FetchEventPreloadHandle::New();
|
||||
- preload_handle_->url_loader = std::move(url_loader_to_pass);
|
||||
- preload_handle_->url_loader_client_receiver =
|
||||
+ preload_url_loader_client_receiver_ =
|
||||
url_loader_client.BindNewPipeAndPassReceiver();
|
||||
|
||||
url_loader_client->OnComplete(
|
||||
@@ -770,12 +770,10 @@ bool ServiceWorkerFetchDispatcher::MaybeStartNavigationPreload(
|
||||
factory = base::MakeRefCounted<network::WrapperSharedURLLoaderFactory>(
|
||||
std::move(network_factory));
|
||||
|
||||
- preload_handle_ = blink::mojom::FetchEventPreloadHandle::New();
|
||||
-
|
||||
// Create the DelegatingURLLoaderClient, which becomes the
|
||||
// URLLoaderClient for the navigation preload network request.
|
||||
mojo::PendingRemote<network::mojom::URLLoaderClient> inner_url_loader_client;
|
||||
- preload_handle_->url_loader_client_receiver =
|
||||
+ preload_url_loader_client_receiver_ =
|
||||
inner_url_loader_client.InitWithNewPipeAndPassReceiver();
|
||||
auto url_loader_client = std::make_unique<DelegatingURLLoaderClient>(
|
||||
std::move(inner_url_loader_client), resource_request);
|
||||
@@ -810,11 +808,9 @@ bool ServiceWorkerFetchDispatcher::MaybeStartNavigationPreload(
|
||||
net::MutableNetworkTrafficAnnotationTag(
|
||||
kNavigationPreloadTrafficAnnotation));
|
||||
|
||||
- preload_handle_->url_loader = std::move(url_loader);
|
||||
-
|
||||
DCHECK(!url_loader_assets_);
|
||||
url_loader_assets_ = base::MakeRefCounted<URLLoaderAssets>(
|
||||
- std::move(factory), std::move(url_loader_client));
|
||||
+ std::move(factory), std::move(url_loader), std::move(url_loader_client));
|
||||
return true;
|
||||
}
|
||||
|
||||
diff --git a/content/browser/service_worker/service_worker_fetch_dispatcher.h b/content/browser/service_worker/service_worker_fetch_dispatcher.h
|
||||
index 5b2a45bff25b7f2c35e304385f22935c33d60a05..b96b2de068bf9f6a38b4d995cf137ebfd53735ea 100644
|
||||
--- a/content/browser/service_worker/service_worker_fetch_dispatcher.h
|
||||
+++ b/content/browser/service_worker/service_worker_fetch_dispatcher.h
|
||||
@@ -121,10 +121,11 @@ class CONTENT_EXPORT ServiceWorkerFetchDispatcher {
|
||||
|
||||
scoped_refptr<URLLoaderAssets> url_loader_assets_;
|
||||
|
||||
- // |preload_handle_| holds the URLLoader and URLLoaderClient for the service
|
||||
- // worker to receive the navigation preload response. It's passed to the
|
||||
- // service worker along with the fetch event.
|
||||
- blink::mojom::FetchEventPreloadHandlePtr preload_handle_;
|
||||
+ // Holds the URLLoaderClient for the service worker to receive the navigation
|
||||
+ // preload response. It's passed to the service worker along with the fetch
|
||||
+ // event.
|
||||
+ mojo::PendingReceiver<network::mojom::URLLoaderClient>
|
||||
+ preload_url_loader_client_receiver_;
|
||||
|
||||
// Whether to dispatch an offline-capability-check fetch event.
|
||||
const bool is_offline_capability_check_ = false;
|
||||
diff --git a/content/renderer/service_worker/navigation_preload_request.cc b/content/renderer/service_worker/navigation_preload_request.cc
|
||||
index c9e9ffd4c68a583569fd5633ca2369e190e2aed7..92f9d4a7de115cac0502aeb9c777605a756b6175 100644
|
||||
--- a/content/renderer/service_worker/navigation_preload_request.cc
|
||||
+++ b/content/renderer/service_worker/navigation_preload_request.cc
|
||||
@@ -19,12 +19,12 @@ NavigationPreloadRequest::NavigationPreloadRequest(
|
||||
ServiceWorkerContextClient* owner,
|
||||
int fetch_event_id,
|
||||
const GURL& url,
|
||||
- blink::mojom::FetchEventPreloadHandlePtr preload_handle)
|
||||
+ mojo::PendingReceiver<network::mojom::URLLoaderClient>
|
||||
+ preload_url_loader_client_receiver)
|
||||
: owner_(owner),
|
||||
fetch_event_id_(fetch_event_id),
|
||||
url_(url),
|
||||
- url_loader_(std::move(preload_handle->url_loader)),
|
||||
- receiver_(this, std::move(preload_handle->url_loader_client_receiver)) {}
|
||||
+ receiver_(this, std::move(preload_url_loader_client_receiver)) {}
|
||||
|
||||
NavigationPreloadRequest::~NavigationPreloadRequest() = default;
|
||||
|
||||
diff --git a/content/renderer/service_worker/navigation_preload_request.h b/content/renderer/service_worker/navigation_preload_request.h
|
||||
index 08cfc4a0dad5777b88f2388da5d07c864d9953fd..f6d19a3d1383767e1c450be7ec29a47ff245ff5a 100644
|
||||
--- a/content/renderer/service_worker/navigation_preload_request.h
|
||||
+++ b/content/renderer/service_worker/navigation_preload_request.h
|
||||
@@ -35,7 +35,8 @@ class NavigationPreloadRequest final : public network::mojom::URLLoaderClient {
|
||||
ServiceWorkerContextClient* owner,
|
||||
int fetch_event_id,
|
||||
const GURL& url,
|
||||
- blink::mojom::FetchEventPreloadHandlePtr preload_handle);
|
||||
+ mojo::PendingReceiver<network::mojom::URLLoaderClient>
|
||||
+ preload_url_loader_client_receiver);
|
||||
~NavigationPreloadRequest() override;
|
||||
|
||||
// network::mojom::URLLoaderClient:
|
||||
@@ -59,11 +60,10 @@ class NavigationPreloadRequest final : public network::mojom::URLLoaderClient {
|
||||
void ReportErrorToOwner(const std::string& message,
|
||||
blink::WebServiceWorkerError::Mode error_mode);
|
||||
|
||||
- ServiceWorkerContextClient* owner_;
|
||||
+ ServiceWorkerContextClient* owner_ = nullptr;
|
||||
|
||||
- const int fetch_event_id_;
|
||||
+ const int fetch_event_id_ = -1;
|
||||
const GURL url_;
|
||||
- mojo::Remote<network::mojom::URLLoader> url_loader_;
|
||||
mojo::Receiver<network::mojom::URLLoaderClient> receiver_;
|
||||
|
||||
std::unique_ptr<blink::WebURLResponse> response_;
|
||||
diff --git a/content/renderer/service_worker/service_worker_context_client.cc b/content/renderer/service_worker/service_worker_context_client.cc
|
||||
index d569c5362c0c3866b333db714d7dd8e7f3344afc..f65f535b5c228ce881a0b0066b67d9847b6168a4 100644
|
||||
--- a/content/renderer/service_worker/service_worker_context_client.cc
|
||||
+++ b/content/renderer/service_worker/service_worker_context_client.cc
|
||||
@@ -476,14 +476,14 @@ void ServiceWorkerContextClient::SendWorkerStarted(
|
||||
void ServiceWorkerContextClient::SetupNavigationPreload(
|
||||
int fetch_event_id,
|
||||
const blink::WebURL& url,
|
||||
- std::unique_ptr<blink::WebFetchEventPreloadHandle> preload_handle) {
|
||||
+ blink::CrossVariantMojoReceiver<
|
||||
+ network::mojom::URLLoaderClientInterfaceBase>
|
||||
+ preload_url_loader_client_receiver) {
|
||||
DCHECK(worker_task_runner_->RunsTasksInCurrentSequence());
|
||||
DCHECK(context_);
|
||||
auto preload_request = std::make_unique<NavigationPreloadRequest>(
|
||||
this, fetch_event_id, GURL(url),
|
||||
- blink::mojom::FetchEventPreloadHandle::New(
|
||||
- std::move(preload_handle->url_loader),
|
||||
- std::move(preload_handle->url_loader_client_receiver)));
|
||||
+ std::move(preload_url_loader_client_receiver));
|
||||
context_->preload_requests.AddWithID(std::move(preload_request),
|
||||
fetch_event_id);
|
||||
}
|
||||
diff --git a/content/renderer/service_worker/service_worker_context_client.h b/content/renderer/service_worker/service_worker_context_client.h
|
||||
index 8191aaec6ed37c6a64bcbd9beac720777de3075e..5abd533c6c3b1926efa6b8fc158562468cc96e19 100644
|
||||
--- a/content/renderer/service_worker/service_worker_context_client.h
|
||||
+++ b/content/renderer/service_worker/service_worker_context_client.h
|
||||
@@ -159,8 +159,9 @@ class CONTENT_EXPORT ServiceWorkerContextClient
|
||||
const blink::WebString& source_url) override;
|
||||
void SetupNavigationPreload(int fetch_event_id,
|
||||
const blink::WebURL& url,
|
||||
- std::unique_ptr<blink::WebFetchEventPreloadHandle>
|
||||
- preload_handle) override;
|
||||
+ blink::CrossVariantMojoReceiver<
|
||||
+ network::mojom::URLLoaderClientInterfaceBase>
|
||||
+ preload_url_loader_client_receiver) override;
|
||||
void RequestTermination(RequestTerminationCallback callback) override;
|
||||
scoped_refptr<blink::WebServiceWorkerFetchContext>
|
||||
CreateWorkerFetchContextOnInitiatorThread() override;
|
||||
diff --git a/mojo/public/cpp/bindings/README.md b/mojo/public/cpp/bindings/README.md
|
||||
index b950df5a7733b26ae3a9dbc1bacc208e584fa9e6..334ba1c8fd92aed36dec6993afe38ca91ffcc49a 100644
|
||||
--- a/mojo/public/cpp/bindings/README.md
|
||||
+++ b/mojo/public/cpp/bindings/README.md
|
||||
@@ -1709,6 +1709,9 @@ C++ sources can depend on shared sources only, by referencing the
|
||||
`"${target_name}_shared"` target, e.g. `"//foo/mojom:mojom_shared"` in the
|
||||
example above.
|
||||
|
||||
+For converting between Blink and non-Blink variants, please see
|
||||
+`//third_party/blink/public/platform/cross_variant_mojo_util.h`.
|
||||
+
|
||||
## Versioning Considerations
|
||||
|
||||
For general documentation of versioning in the Mojom IDL see
|
||||
diff --git a/third_party/blink/public/mojom/service_worker/dispatch_fetch_event_params.mojom b/third_party/blink/public/mojom/service_worker/dispatch_fetch_event_params.mojom
|
||||
index 382be0b3dd042ceadb73e4d514f93ac7c8624b43..c95a2e255166871ff45b6a4c3a8b206e1dace776 100644
|
||||
--- a/third_party/blink/public/mojom/service_worker/dispatch_fetch_event_params.mojom
|
||||
+++ b/third_party/blink/public/mojom/service_worker/dispatch_fetch_event_params.mojom
|
||||
@@ -9,13 +9,6 @@ import "third_party/blink/public/mojom/blob/blob.mojom";
|
||||
import "third_party/blink/public/mojom/fetch/fetch_api_request.mojom";
|
||||
import "third_party/blink/public/mojom/timing/worker_timing_container.mojom";
|
||||
|
||||
-// Used for service worker navigation preload, to create
|
||||
-// FetchEvent#preloadResponse.
|
||||
-struct FetchEventPreloadHandle {
|
||||
- pending_remote<network.mojom.URLLoader> url_loader;
|
||||
- pending_receiver<network.mojom.URLLoaderClient> url_loader_client_receiver;
|
||||
-};
|
||||
-
|
||||
// Parameters used for dispatching a FetchEvent.
|
||||
struct DispatchFetchEventParams {
|
||||
// FetchEvent#request.
|
||||
@@ -23,8 +16,9 @@ struct DispatchFetchEventParams {
|
||||
|
||||
// FetchEvent#clientId.
|
||||
string client_id;
|
||||
+
|
||||
// FetchEvent#preloadResponse.
|
||||
- FetchEventPreloadHandle? preload_handle;
|
||||
+ pending_receiver<network.mojom.URLLoaderClient>? preload_url_loader_client_receiver;
|
||||
|
||||
// This is currently null for navigation because it's still being implemented.
|
||||
// TODO(https://crbug.com/900700): Make this non-nullable when implementation
|
||||
diff --git a/third_party/blink/public/web/modules/service_worker/web_service_worker_context_client.h b/third_party/blink/public/web/modules/service_worker/web_service_worker_context_client.h
|
||||
index 67c0c9d3cb10478755422b489c97afe8adce1a24..0a8cde9a7f6bab9de2c43f13c1bc0d35375bc2b5 100644
|
||||
--- a/third_party/blink/public/web/modules/service_worker/web_service_worker_context_client.h
|
||||
+++ b/third_party/blink/public/web/modules/service_worker/web_service_worker_context_client.h
|
||||
@@ -31,8 +31,6 @@
|
||||
#ifndef THIRD_PARTY_BLINK_PUBLIC_WEB_MODULES_SERVICE_WORKER_WEB_SERVICE_WORKER_CONTEXT_CLIENT_H_
|
||||
#define THIRD_PARTY_BLINK_PUBLIC_WEB_MODULES_SERVICE_WORKER_WEB_SERVICE_WORKER_CONTEXT_CLIENT_H_
|
||||
|
||||
-#include <memory>
|
||||
-
|
||||
#include "base/memory/scoped_refptr.h"
|
||||
#include "services/network/public/mojom/url_loader.mojom-shared.h"
|
||||
#include "third_party/blink/public/mojom/devtools/console_message.mojom-shared.h"
|
||||
@@ -53,14 +51,6 @@ namespace blink {
|
||||
class WebServiceWorkerContextProxy;
|
||||
class WebString;
|
||||
|
||||
-// Used to pass the mojom struct blink.mojom.FetchEventPreloadHandle across the
|
||||
-// boundary between //content and Blink.
|
||||
-struct WebFetchEventPreloadHandle {
|
||||
- CrossVariantMojoRemote<network::mojom::URLLoaderInterfaceBase> url_loader;
|
||||
- CrossVariantMojoReceiver<network::mojom::URLLoaderClientInterfaceBase>
|
||||
- url_loader_client_receiver;
|
||||
-};
|
||||
-
|
||||
// WebServiceWorkerContextClient is a "client" of a service worker execution
|
||||
// context. This interface is implemented by the embedder and allows the
|
||||
// embedder to communicate with the service worker execution context. It is
|
||||
@@ -166,7 +156,8 @@ class WebServiceWorkerContextClient {
|
||||
virtual void SetupNavigationPreload(
|
||||
int fetch_event_id,
|
||||
const WebURL& url,
|
||||
- std::unique_ptr<WebFetchEventPreloadHandle> preload_handle) {}
|
||||
+ CrossVariantMojoReceiver<network::mojom::URLLoaderClientInterfaceBase>
|
||||
+ preload_url_loader_client_receiver) {}
|
||||
|
||||
// Called when we need to request to terminate this worker due to idle
|
||||
// timeout.
|
||||
diff --git a/third_party/blink/renderer/modules/service_worker/service_worker_global_scope.cc b/third_party/blink/renderer/modules/service_worker/service_worker_global_scope.cc
|
||||
index 9c2cff1d0433d55c4b08fd4eef83544bd120425b..3e84a0200950a33c93f6e473a2cace4609389aea 100644
|
||||
--- a/third_party/blink/renderer/modules/service_worker/service_worker_global_scope.cc
|
||||
+++ b/third_party/blink/renderer/modules/service_worker/service_worker_global_scope.cc
|
||||
@@ -1514,11 +1514,12 @@ void ServiceWorkerGlobalScope::StartFetchEvent(
|
||||
params->request->url.ElidedString().Utf8());
|
||||
|
||||
// Set up for navigation preload (FetchEvent#preloadResponse) if needed.
|
||||
- const bool navigation_preload_sent = !!params->preload_handle;
|
||||
+ bool navigation_preload_sent = !!params->preload_url_loader_client_receiver;
|
||||
if (navigation_preload_sent) {
|
||||
To<ServiceWorkerGlobalScopeProxy>(ReportingProxy())
|
||||
- .SetupNavigationPreload(event_id, params->request->url,
|
||||
- std::move(params->preload_handle));
|
||||
+ .SetupNavigationPreload(
|
||||
+ event_id, params->request->url,
|
||||
+ std::move(params->preload_url_loader_client_receiver));
|
||||
}
|
||||
|
||||
ScriptState::Scope scope(ScriptController()->GetScriptState());
|
||||
diff --git a/third_party/blink/renderer/modules/service_worker/service_worker_global_scope_proxy.cc b/third_party/blink/renderer/modules/service_worker/service_worker_global_scope_proxy.cc
|
||||
index b2efbea7c370b7f641cad9c5db75f9826ec705ed..33d11a19b350e1dd12c105403ed513e9a62a76ec 100644
|
||||
--- a/third_party/blink/renderer/modules/service_worker/service_worker_global_scope_proxy.cc
|
||||
+++ b/third_party/blink/renderer/modules/service_worker/service_worker_global_scope_proxy.cc
|
||||
@@ -257,14 +257,11 @@ bool ServiceWorkerGlobalScopeProxy::IsServiceWorkerGlobalScopeProxy() const {
|
||||
void ServiceWorkerGlobalScopeProxy::SetupNavigationPreload(
|
||||
int fetch_event_id,
|
||||
const KURL& url,
|
||||
- mojom::blink::FetchEventPreloadHandlePtr preload_handle) {
|
||||
+ mojo::PendingReceiver<network::mojom::blink::URLLoaderClient>
|
||||
+ preload_url_loader_client_receiver) {
|
||||
DCHECK_CALLED_ON_VALID_THREAD(worker_thread_checker_);
|
||||
- auto web_preload_handle = std::make_unique<WebFetchEventPreloadHandle>();
|
||||
- web_preload_handle->url_loader = std::move(preload_handle->url_loader);
|
||||
- web_preload_handle->url_loader_client_receiver =
|
||||
- std::move(preload_handle->url_loader_client_receiver);
|
||||
- Client().SetupNavigationPreload(fetch_event_id, url,
|
||||
- std::move(web_preload_handle));
|
||||
+ Client().SetupNavigationPreload(
|
||||
+ fetch_event_id, url, std::move(preload_url_loader_client_receiver));
|
||||
}
|
||||
|
||||
void ServiceWorkerGlobalScopeProxy::RequestTermination(
|
||||
diff --git a/third_party/blink/renderer/modules/service_worker/service_worker_global_scope_proxy.h b/third_party/blink/renderer/modules/service_worker/service_worker_global_scope_proxy.h
|
||||
index 783dbe1919d1282f40117aea22b75a8e54e82d89..d54a2449da63f67930cb3d85cfbb27c35c45a8d3 100644
|
||||
--- a/third_party/blink/renderer/modules/service_worker/service_worker_global_scope_proxy.h
|
||||
+++ b/third_party/blink/renderer/modules/service_worker/service_worker_global_scope_proxy.h
|
||||
@@ -129,7 +129,8 @@ class ServiceWorkerGlobalScopeProxy final : public WebServiceWorkerContextProxy,
|
||||
void SetupNavigationPreload(
|
||||
int fetch_event_id,
|
||||
const KURL& url,
|
||||
- mojom::blink::FetchEventPreloadHandlePtr preload_handle);
|
||||
+ mojo::PendingReceiver<network::mojom::blink::URLLoaderClient>
|
||||
+ preload_url_loader_client_receiver);
|
||||
void RequestTermination(WTF::CrossThreadOnceFunction<void(bool)> callback);
|
||||
|
||||
// Detaches this proxy object entirely from the outside world, clearing out
|
||||
36
patches/chromium/cherry-pick-246c10dede97.patch
Normal file
36
patches/chromium/cherry-pick-246c10dede97.patch
Normal file
@@ -0,0 +1,36 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Tony Herre <toprice@chromium.org>
|
||||
Date: Fri, 18 Feb 2022 13:52:01 +0000
|
||||
Subject: Switch to new RequestPermissionsFromCurrentDocument API method for
|
||||
Media Stream Devices
|
||||
|
||||
Switch away from the deprecated RequestPermissions() API, as a part of removing a bug where the previously provided request.security_origin param might get destroyed during the method execution.
|
||||
|
||||
(cherry picked from commit cb6778fb965e2b010922f157c68480de863c252e)
|
||||
|
||||
Bug: 1283402
|
||||
Change-Id: I512ce910146ec60d4d35fa1a86a71a3b0983a5d1
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3417436
|
||||
Reviewed-by: Florent Castelli <orphis@chromium.org>
|
||||
Commit-Queue: Tony Herre <toprice@chromium.org>
|
||||
Cr-Original-Commit-Position: refs/heads/main@{#964535}
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3473365
|
||||
Cr-Commit-Position: refs/branch-heads/4844@{#655}
|
||||
Cr-Branched-From: 007241ce2e6c8e5a7b306cc36c730cd07cd38825-refs/heads/main@{#961656}
|
||||
|
||||
diff --git a/components/webrtc/media_stream_devices_controller.cc b/components/webrtc/media_stream_devices_controller.cc
|
||||
index 8eb0e01815f6a5f2f0241554b3e5b93017564242..33468f9f2b1bcc2cda8d98748902984ae82e147d 100644
|
||||
--- a/components/webrtc/media_stream_devices_controller.cc
|
||||
+++ b/components/webrtc/media_stream_devices_controller.cc
|
||||
@@ -139,9 +139,8 @@ void MediaStreamDevicesController::RequestPermissions(
|
||||
}
|
||||
}
|
||||
|
||||
- permission_manager->RequestPermissions(
|
||||
- content_settings_types, rfh, request.security_origin,
|
||||
- request.user_gesture,
|
||||
+ permission_manager->RequestPermissionsFromCurrentDocument(
|
||||
+ content_settings_types, rfh, request.user_gesture,
|
||||
base::BindOnce(
|
||||
&MediaStreamDevicesController::RequestAndroidPermissionsIfNeeded,
|
||||
web_contents, std::move(controller), will_prompt_for_audio,
|
||||
71
patches/chromium/cherry-pick-27eb11a28555.patch
Normal file
71
patches/chromium/cherry-pick-27eb11a28555.patch
Normal file
@@ -0,0 +1,71 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Yutaka Hirano <yhirano@chromium.org>
|
||||
Date: Wed, 29 Sep 2021 07:58:26 +0000
|
||||
Subject: Run CORS check for manual redirects
|
||||
|
||||
...to prevent status code leak.
|
||||
|
||||
Bug: 1251179
|
||||
Change-Id: I7fcab0daf49e16305ed53702f42d1d1eacc933e5
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3193481
|
||||
Reviewed-by: Yoav Weiss <yoavweiss@chromium.org>
|
||||
Commit-Queue: Yutaka Hirano <yhirano@chromium.org>
|
||||
Cr-Commit-Position: refs/heads/main@{#926166}
|
||||
|
||||
diff --git a/services/network/cors/cors_url_loader.cc b/services/network/cors/cors_url_loader.cc
|
||||
index 89813366845757aaa31a37ba155ad2e50a2f5010..88f9236a91c3b32cd1daabca4d42e47c4a959746 100644
|
||||
--- a/services/network/cors/cors_url_loader.cc
|
||||
+++ b/services/network/cors/cors_url_loader.cc
|
||||
@@ -304,13 +304,6 @@ void CorsURLLoader::OnReceiveRedirect(const net::RedirectInfo& redirect_info,
|
||||
DCHECK(forwarding_client_);
|
||||
DCHECK(!deferred_redirect_url_);
|
||||
|
||||
- if (request_.redirect_mode == mojom::RedirectMode::kManual) {
|
||||
- deferred_redirect_url_ = std::make_unique<GURL>(redirect_info.new_url);
|
||||
- forwarding_client_->OnReceiveRedirect(redirect_info,
|
||||
- std::move(response_head));
|
||||
- return;
|
||||
- }
|
||||
-
|
||||
// If |CORS flag| is set and a CORS check for |request| and |response| returns
|
||||
// failure, then return a network error.
|
||||
if (fetch_cors_flag_ && IsCorsEnabledRequestMode(request_.mode)) {
|
||||
@@ -328,6 +321,13 @@ void CorsURLLoader::OnReceiveRedirect(const net::RedirectInfo& redirect_info,
|
||||
}
|
||||
}
|
||||
|
||||
+ if (request_.redirect_mode == mojom::RedirectMode::kManual) {
|
||||
+ deferred_redirect_url_ = std::make_unique<GURL>(redirect_info.new_url);
|
||||
+ forwarding_client_->OnReceiveRedirect(redirect_info,
|
||||
+ std::move(response_head));
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
timing_allow_failed_flag_ = !PassesTimingAllowOriginCheck(*response_head);
|
||||
|
||||
// Because we initiate a new request on redirect in some cases, we cannot
|
||||
diff --git a/third_party/blink/web_tests/external/wpt/fetch/api/redirect/redirect-mode.any.js b/third_party/blink/web_tests/external/wpt/fetch/api/redirect/redirect-mode.any.js
|
||||
index eed44e0414cb8947c9b7c21df6ef288f733f8994..9f1ff98c65af97bcf185867ac6c6e128dbd77715 100644
|
||||
--- a/third_party/blink/web_tests/external/wpt/fetch/api/redirect/redirect-mode.any.js
|
||||
+++ b/third_party/blink/web_tests/external/wpt/fetch/api/redirect/redirect-mode.any.js
|
||||
@@ -1,6 +1,7 @@
|
||||
// META: script=/common/get-host-info.sub.js
|
||||
|
||||
var redirectLocation = "cors-top.txt";
|
||||
+const { ORIGIN, REMOTE_ORIGIN } = get_host_info();
|
||||
|
||||
function testRedirect(origin, redirectStatus, redirectMode, corsMode) {
|
||||
var url = new URL("../resources/redirect.py", self.location);
|
||||
@@ -47,4 +48,12 @@ for (var origin of ["same-origin", "cross-origin"]) {
|
||||
}
|
||||
}
|
||||
|
||||
+promise_test(async (t) => {
|
||||
+ const destination = `${ORIGIN}/common/blank.html`;
|
||||
+ // We use /common/redirect.py intentionally, as we want a CORS error.
|
||||
+ const url =
|
||||
+ `${REMOTE_ORIGIN}/common/redirect.py?location=${destination}`;
|
||||
+ await promise_rejects_js(t, TypeError, fetch(url, { redirect: "manual" }));
|
||||
+}, "manual redirect with a CORS error should be rejected");
|
||||
+
|
||||
done();
|
||||
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 8fe9a4e507aa5b081af4b48fe80ee38275dee84e..8ec7bbc1ed065b84afd22a4223e2359344876c47 100644
|
||||
--- a/net/http/http_stream_parser.cc
|
||||
+++ b/net/http/http_stream_parser.cc
|
||||
@@ -1013,15 +1013,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 0a415338f3396e1fce75b691911aa77c28d8bdf9..ff0e1508326c92ecd46546755c030a906c6eac28 100644
|
||||
--- a/net/http/http_stream_parser.h
|
||||
+++ b/net/http/http_stream_parser.h
|
||||
@@ -271,6 +271,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 545b9f11b43b37456ccab54a63eeb76034c934ef..07f94e6bb6aefe3777a71afed80b22eedea2999e 100644
|
||||
--- a/net/http/http_stream_parser_unittest.cc
|
||||
+++ b/net/http/http_stream_parser_unittest.cc
|
||||
@@ -1395,6 +1395,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.
|
||||
+
|
||||
151
patches/chromium/cherry-pick-62142d222a80.patch
Normal file
151
patches/chromium/cherry-pick-62142d222a80.patch
Normal file
@@ -0,0 +1,151 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Ken Rockot <rockot@google.com>
|
||||
Date: Thu, 24 Feb 2022 15:13:13 +0000
|
||||
Subject: Validate message headers sooner
|
||||
|
||||
M96 merge issues:
|
||||
- multiplex_router.h: conflict in removed lines because of
|
||||
differences in comments above header_validator_
|
||||
- connector.h: conflicting includes
|
||||
|
||||
Message header validation has been tied to interface message dispatch,
|
||||
but not all mojo::Message consumers are interface bindings.
|
||||
|
||||
mojo::Connector is a more general-purpose entry point through which
|
||||
incoming messages are received and transformed into mojo::Message
|
||||
objects. Blink's MessagePort implementation uses Connector directly to
|
||||
transmit and receive raw serialized object data.
|
||||
|
||||
This change moves MessageHeaderValidator ownership into Connector and
|
||||
always applies its validation immediately after reading a message from
|
||||
the pipe, thereby ensuring that all mojo::Message objects used in
|
||||
production have validated headers before use.
|
||||
|
||||
(cherry picked from commit 8d5bc69146505785ce299c490e35e3f3ef19f69c)
|
||||
|
||||
Fixed: 1281908
|
||||
Change-Id: Ie0e251ab04681a4fd4b849d82c247e0ed800dc04
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3462461
|
||||
Commit-Queue: Ken Rockot <rockot@google.com>
|
||||
Cr-Original-Commit-Position: refs/heads/main@{#971263}
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3483815
|
||||
Reviewed-by: Victor-Gabriel Savu <vsavu@google.com>
|
||||
Owners-Override: Victor-Gabriel Savu <vsavu@google.com>
|
||||
Commit-Queue: Roger Felipe Zanoni da Silva <rzanoni@google.com>
|
||||
Cr-Commit-Position: refs/branch-heads/4664@{#1505}
|
||||
Cr-Branched-From: 24dc4ee75e01a29d390d43c9c264372a169273a7-refs/heads/main@{#929512}
|
||||
|
||||
diff --git a/mojo/public/cpp/bindings/connector.h b/mojo/public/cpp/bindings/connector.h
|
||||
index 3975d01a434d6caf229c6d8eaedfe5e2acf684f8..ff17af9b378a1992dbd681e80e957826ebfd83dd 100644
|
||||
--- a/mojo/public/cpp/bindings/connector.h
|
||||
+++ b/mojo/public/cpp/bindings/connector.h
|
||||
@@ -18,6 +18,7 @@
|
||||
#include "base/sequenced_task_runner.h"
|
||||
#include "mojo/public/cpp/bindings/connection_group.h"
|
||||
#include "mojo/public/cpp/bindings/message.h"
|
||||
+#include "mojo/public/cpp/bindings/message_header_validator.h"
|
||||
#include "mojo/public/cpp/bindings/sync_handle_watcher.h"
|
||||
#include "mojo/public/cpp/system/core.h"
|
||||
#include "mojo/public/cpp/system/handle_signal_tracker.h"
|
||||
@@ -345,6 +346,8 @@ class COMPONENT_EXPORT(MOJO_CPP_BINDINGS) Connector : public MessageReceiver {
|
||||
// The number of pending tasks for |CallDispatchNextMessageFromPipe|.
|
||||
size_t num_pending_dispatch_tasks_ = 0;
|
||||
|
||||
+ MessageHeaderValidator header_validator_;
|
||||
+
|
||||
#if defined(ENABLE_IPC_FUZZER)
|
||||
std::unique_ptr<MessageReceiver> message_dumper_;
|
||||
#endif
|
||||
diff --git a/mojo/public/cpp/bindings/lib/connector.cc b/mojo/public/cpp/bindings/lib/connector.cc
|
||||
index 92a9756cbaebe12377e9c9b81467260c73528311..cb08f13b1bfa13a1a79f7f39005f826e51c12a69 100644
|
||||
--- a/mojo/public/cpp/bindings/lib/connector.cc
|
||||
+++ b/mojo/public/cpp/bindings/lib/connector.cc
|
||||
@@ -19,6 +19,7 @@
|
||||
#include "base/rand_util.h"
|
||||
#include "base/run_loop.h"
|
||||
#include "base/strings/strcat.h"
|
||||
+#include "base/strings/string_util.h"
|
||||
#include "base/synchronization/lock.h"
|
||||
#include "base/task/current_thread.h"
|
||||
#include "base/threading/sequence_local_storage_slot.h"
|
||||
@@ -152,7 +153,11 @@ Connector::Connector(ScopedMessagePipeHandle message_pipe,
|
||||
force_immediate_dispatch_(!EnableTaskPerMessage()),
|
||||
outgoing_serialization_mode_(g_default_outgoing_serialization_mode),
|
||||
incoming_serialization_mode_(g_default_incoming_serialization_mode),
|
||||
- interface_name_(interface_name) {
|
||||
+ interface_name_(interface_name),
|
||||
+ header_validator_(
|
||||
+ base::JoinString({interface_name ? interface_name : "Generic",
|
||||
+ "MessageHeaderValidator"},
|
||||
+ "")) {
|
||||
if (config == MULTI_THREADED_SEND)
|
||||
lock_.emplace();
|
||||
|
||||
@@ -492,6 +497,7 @@ MojoResult Connector::ReadMessage(Message* message) {
|
||||
return result;
|
||||
|
||||
*message = Message::CreateFromMessageHandle(&handle);
|
||||
+
|
||||
if (message->IsNull()) {
|
||||
// Even if the read was successful, the Message may still be null if there
|
||||
// was a problem extracting handles from it. We treat this essentially as
|
||||
@@ -507,6 +513,10 @@ MojoResult Connector::ReadMessage(Message* message) {
|
||||
return MOJO_RESULT_ABORTED;
|
||||
}
|
||||
|
||||
+ if (!header_validator_.Accept(message)) {
|
||||
+ return MOJO_RESULT_ABORTED;
|
||||
+ }
|
||||
+
|
||||
return MOJO_RESULT_OK;
|
||||
}
|
||||
|
||||
diff --git a/mojo/public/cpp/bindings/lib/multiplex_router.cc b/mojo/public/cpp/bindings/lib/multiplex_router.cc
|
||||
index 605e51344d64eb5ede3ab475bc8833b37a458535..23e3970089e33d07b18d734d4f599c9c9f9e4bc8 100644
|
||||
--- a/mojo/public/cpp/bindings/lib/multiplex_router.cc
|
||||
+++ b/mojo/public/cpp/bindings/lib/multiplex_router.cc
|
||||
@@ -23,7 +23,6 @@
|
||||
#include "mojo/public/cpp/bindings/interface_endpoint_controller.h"
|
||||
#include "mojo/public/cpp/bindings/lib/may_auto_lock.h"
|
||||
#include "mojo/public/cpp/bindings/lib/message_quota_checker.h"
|
||||
-#include "mojo/public/cpp/bindings/message_header_validator.h"
|
||||
#include "mojo/public/cpp/bindings/sequence_local_sync_event_watcher.h"
|
||||
|
||||
namespace mojo {
|
||||
@@ -389,14 +388,7 @@ MultiplexRouter::MultiplexRouter(
|
||||
if (quota_checker)
|
||||
connector_.SetMessageQuotaChecker(std::move(quota_checker));
|
||||
|
||||
- std::unique_ptr<MessageHeaderValidator> header_validator =
|
||||
- std::make_unique<MessageHeaderValidator>();
|
||||
- header_validator_ = header_validator.get();
|
||||
- dispatcher_.SetValidator(std::move(header_validator));
|
||||
-
|
||||
if (primary_interface_name) {
|
||||
- header_validator_->SetDescription(base::JoinString(
|
||||
- {primary_interface_name, "[primary] MessageHeaderValidator"}, " "));
|
||||
control_message_handler_.SetDescription(base::JoinString(
|
||||
{primary_interface_name, "[primary] PipeControlMessageHandler"}, " "));
|
||||
}
|
||||
diff --git a/mojo/public/cpp/bindings/lib/multiplex_router.h b/mojo/public/cpp/bindings/lib/multiplex_router.h
|
||||
index 3d3bbb16e25b1adc678e536bd977fa22fc478920..3a9f76a57e301aa89d1bdc5aa1000f815793e238 100644
|
||||
--- a/mojo/public/cpp/bindings/lib/multiplex_router.h
|
||||
+++ b/mojo/public/cpp/bindings/lib/multiplex_router.h
|
||||
@@ -38,7 +38,6 @@ class SequencedTaskRunner;
|
||||
namespace mojo {
|
||||
|
||||
class AsyncFlusher;
|
||||
-class MessageHeaderValidator;
|
||||
class PendingFlush;
|
||||
|
||||
namespace internal {
|
||||
@@ -301,9 +300,6 @@ class COMPONENT_EXPORT(MOJO_CPP_BINDINGS) MultiplexRouter
|
||||
|
||||
scoped_refptr<base::SequencedTaskRunner> task_runner_;
|
||||
|
||||
- // Owned by |dispatcher_| below.
|
||||
- MessageHeaderValidator* header_validator_ = nullptr;
|
||||
-
|
||||
MessageDispatcher dispatcher_;
|
||||
Connector connector_;
|
||||
|
||||
150
patches/chromium/cherry-pick-6b2643846ae3.patch
Normal file
150
patches/chromium/cherry-pick-6b2643846ae3.patch
Normal file
@@ -0,0 +1,150 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Ted Meyer <tmathmeyer@chromium.org>
|
||||
Date: Thu, 24 Feb 2022 17:39:53 +0000
|
||||
Subject: Guard BatchingMediaLog::event_handlers_ with lock
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
|
||||
It seems that despite MediaLog::OnWebMediaPlayerDestroyed and
|
||||
MediaLog::AddLogRecord both grabbing a lock,
|
||||
BatchingMediaLog::AddLogRecordLocked can escape the lock handle by
|
||||
posting BatchingMediaLog::SendQueuedMediaEvents, causing a race.
|
||||
|
||||
When the addition of an event is interrupted by the deletion of a player
|
||||
due to player culling in MediaInspectorContextImpl, a UAF can occur.
|
||||
|
||||
R=dalecurtis
|
||||
|
||||
(cherry picked from commit 34526c3d0a857a22618e4d77c7f63b5ca6f8d3d2)
|
||||
|
||||
Bug: 1295786
|
||||
Change-Id: I77df94988f806e4d98924669d27860e50455299d
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3451494
|
||||
Commit-Queue: Ted (Chromium) Meyer <tmathmeyer@chromium.org>
|
||||
Cr-Original-Commit-Position: refs/heads/main@{#970815}
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3483655
|
||||
Reviewed-by: Victor-Gabriel Savu <vsavu@google.com>
|
||||
Owners-Override: Victor-Gabriel Savu <vsavu@google.com>
|
||||
Commit-Queue: Roger Felipe Zanoni da Silva <rzanoni@google.com>
|
||||
Cr-Commit-Position: refs/branch-heads/4664@{#1508}
|
||||
Cr-Branched-From: 24dc4ee75e01a29d390d43c9c264372a169273a7-refs/heads/main@{#929512}
|
||||
|
||||
diff --git a/content/renderer/media/batching_media_log.cc b/content/renderer/media/batching_media_log.cc
|
||||
index 8d8c5cb28b9bb0fcebcceb9e56db98fdace13c88..2d12a5eb42b930acac74a5ea2b2961e6c7e32fcf 100644
|
||||
--- a/content/renderer/media/batching_media_log.cc
|
||||
+++ b/content/renderer/media/batching_media_log.cc
|
||||
@@ -52,9 +52,9 @@ BatchingMediaLog::BatchingMediaLog(
|
||||
scoped_refptr<base::SingleThreadTaskRunner> task_runner,
|
||||
std::vector<std::unique_ptr<EventHandler>> event_handlers)
|
||||
: task_runner_(std::move(task_runner)),
|
||||
- event_handlers_(std::move(event_handlers)),
|
||||
tick_clock_(base::DefaultTickClock::GetInstance()),
|
||||
last_ipc_send_time_(tick_clock_->NowTicks()),
|
||||
+ event_handlers_(std::move(event_handlers)),
|
||||
ipc_send_pending_(false),
|
||||
logged_rate_limit_warning_(false) {
|
||||
// Pre-bind the WeakPtr on the right thread since we'll receive calls from
|
||||
@@ -76,6 +76,7 @@ BatchingMediaLog::~BatchingMediaLog() {
|
||||
}
|
||||
|
||||
void BatchingMediaLog::OnWebMediaPlayerDestroyedLocked() {
|
||||
+ base::AutoLock lock(lock_);
|
||||
for (const auto& handler : event_handlers_)
|
||||
handler->OnWebMediaPlayerDestroyed();
|
||||
}
|
||||
@@ -198,32 +199,30 @@ std::string BatchingMediaLog::MediaEventToMessageString(
|
||||
|
||||
void BatchingMediaLog::SendQueuedMediaEvents() {
|
||||
DCHECK(task_runner_->BelongsToCurrentThread());
|
||||
+ base::AutoLock auto_lock(lock_);
|
||||
|
||||
- std::vector<media::MediaLogRecord> events_to_send;
|
||||
- {
|
||||
- base::AutoLock auto_lock(lock_);
|
||||
- DCHECK(ipc_send_pending_);
|
||||
- ipc_send_pending_ = false;
|
||||
-
|
||||
- if (last_duration_changed_event_) {
|
||||
- queued_media_events_.push_back(*last_duration_changed_event_);
|
||||
- last_duration_changed_event_.reset();
|
||||
- }
|
||||
+ DCHECK(ipc_send_pending_);
|
||||
+ ipc_send_pending_ = false;
|
||||
|
||||
- if (last_buffering_state_event_) {
|
||||
- queued_media_events_.push_back(*last_buffering_state_event_);
|
||||
- last_buffering_state_event_.reset();
|
||||
- }
|
||||
+ if (last_duration_changed_event_) {
|
||||
+ queued_media_events_.push_back(*last_duration_changed_event_);
|
||||
+ last_duration_changed_event_.reset();
|
||||
+ }
|
||||
|
||||
- queued_media_events_.swap(events_to_send);
|
||||
- last_ipc_send_time_ = tick_clock_->NowTicks();
|
||||
+ if (last_buffering_state_event_) {
|
||||
+ queued_media_events_.push_back(*last_buffering_state_event_);
|
||||
+ last_buffering_state_event_.reset();
|
||||
}
|
||||
|
||||
- if (events_to_send.empty())
|
||||
+ last_ipc_send_time_ = tick_clock_->NowTicks();
|
||||
+
|
||||
+ if (queued_media_events_.empty())
|
||||
return;
|
||||
|
||||
for (const auto& handler : event_handlers_)
|
||||
- handler->SendQueuedMediaEvents(events_to_send);
|
||||
+ handler->SendQueuedMediaEvents(queued_media_events_);
|
||||
+
|
||||
+ queued_media_events_.clear();
|
||||
}
|
||||
|
||||
void BatchingMediaLog::SetTickClockForTesting(
|
||||
diff --git a/content/renderer/media/batching_media_log.h b/content/renderer/media/batching_media_log.h
|
||||
index 5810efdf0a75b809b94fb5abcd5f3dfbde7b019d..c59dbf2a2b980a89b41c45818476c77e9096339b 100644
|
||||
--- a/content/renderer/media/batching_media_log.h
|
||||
+++ b/content/renderer/media/batching_media_log.h
|
||||
@@ -63,9 +63,6 @@ class CONTENT_EXPORT BatchingMediaLog : public media::MediaLog {
|
||||
|
||||
scoped_refptr<base::SingleThreadTaskRunner> task_runner_;
|
||||
|
||||
- // impl for sending queued events.
|
||||
- std::vector<std::unique_ptr<EventHandler>> event_handlers_;
|
||||
-
|
||||
// |lock_| protects access to all of the following member variables. It
|
||||
// allows any render process thread to AddEvent(), while preserving their
|
||||
// sequence for throttled send on |task_runner_| and coherent retrieval by
|
||||
@@ -73,19 +70,24 @@ class CONTENT_EXPORT BatchingMediaLog : public media::MediaLog {
|
||||
// guarantees provided by MediaLog, since SendQueuedMediaEvents must also
|
||||
// be synchronized with respect to AddEvent.
|
||||
mutable base::Lock lock_;
|
||||
- const base::TickClock* tick_clock_;
|
||||
- base::TimeTicks last_ipc_send_time_;
|
||||
- std::vector<media::MediaLogRecord> queued_media_events_;
|
||||
+ const base::TickClock* tick_clock_ GUARDED_BY(lock_);
|
||||
+ base::TimeTicks last_ipc_send_time_ GUARDED_BY(lock_);
|
||||
+ std::vector<media::MediaLogRecord> queued_media_events_ GUARDED_BY(lock_);
|
||||
+
|
||||
+ // impl for sending queued events.
|
||||
+ std::vector<std::unique_ptr<EventHandler>> event_handlers_ GUARDED_BY(lock_);
|
||||
|
||||
// For enforcing max 1 pending send.
|
||||
- bool ipc_send_pending_;
|
||||
+ bool ipc_send_pending_ GUARDED_BY(lock_);
|
||||
|
||||
// True if we've logged a warning message about exceeding rate limits.
|
||||
- bool logged_rate_limit_warning_;
|
||||
+ bool logged_rate_limit_warning_ GUARDED_BY(lock_);
|
||||
|
||||
// Limits the number of events we send over IPC to one.
|
||||
- absl::optional<media::MediaLogRecord> last_duration_changed_event_;
|
||||
- absl::optional<media::MediaLogRecord> last_buffering_state_event_;
|
||||
+ absl::optional<media::MediaLogRecord> last_duration_changed_event_
|
||||
+ GUARDED_BY(lock_);
|
||||
+ absl::optional<media::MediaLogRecord> last_buffering_state_event_
|
||||
+ GUARDED_BY(lock_);
|
||||
|
||||
// Holds the earliest MEDIA_ERROR_LOG_ENTRY event added to this log. This is
|
||||
// most likely to contain the most specific information available describing
|
||||
765
patches/chromium/cherry-pick-6bb320d134b1.patch
Normal file
765
patches/chromium/cherry-pick-6bb320d134b1.patch
Normal file
@@ -0,0 +1,765 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Victor Costan <pwnall@chromium.org>
|
||||
Date: Thu, 11 Nov 2021 00:22:30 +0000
|
||||
Subject: M96: Storage Foundation: Share FileState ownership with I/O threads.
|
||||
|
||||
blink::NativeIOFile methods implementing the Storage Foundation
|
||||
JavaScript API pass raw pointers to NativeIOFile::FileState instances to
|
||||
their corresponding blink::NativeIOFile::Do*() methods, which rely on
|
||||
that CrossThreadPersistent<NativeIOFile> arguments to keep the
|
||||
underlying NativeIOFile::FileState instances alive.
|
||||
|
||||
CrossThreadPersistent can be used across threads to keep a garbage
|
||||
collected object alive, together with any non-garbage-collected objects
|
||||
that it owns. However, relying on CrossThreadPersistent existence to
|
||||
access the owned objects on a different thread is not safe.
|
||||
cppgc::subtle::CrossThreadPersistent (blink::CrossThreadPersistent is an
|
||||
alias to that) has comments explaining that the garbage collected heap
|
||||
can go away while the CrossThreadPersistent instance exists.
|
||||
|
||||
This CL fixes the problem by having the ownership of
|
||||
NativeIOFile::FileState be shared between the corresponding NativeIOFile
|
||||
instance and any threads doing I/O on the FileState.
|
||||
|
||||
(cherry picked from commit 7dc02206707362f3f92cea93f8eb2fa4af0d375f)
|
||||
|
||||
Bug: 1240593
|
||||
Change-Id: I5c9c818bcb23316fe1fd5afa57ed9c3fdb034377
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3269947
|
||||
Commit-Queue: Victor Costan <pwnall@chromium.org>
|
||||
Reviewed-by: Austin Sullivan <asully@chromium.org>
|
||||
Reviewed-by: Marijn Kruisselbrink <mek@chromium.org>
|
||||
Reviewed-by: enne <enne@chromium.org>
|
||||
Cr-Original-Commit-Position: refs/heads/main@{#940130}
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3272672
|
||||
Bot-Commit: Rubber Stamper <rubber-stamper@appspot.gserviceaccount.com>
|
||||
Cr-Commit-Position: refs/branch-heads/4664@{#945}
|
||||
Cr-Branched-From: 24dc4ee75e01a29d390d43c9c264372a169273a7-refs/heads/main@{#929512}
|
||||
|
||||
diff --git a/third_party/blink/renderer/modules/native_io/native_io_file.cc b/third_party/blink/renderer/modules/native_io/native_io_file.cc
|
||||
index 4d5aa4efa13930aea4886bac0fd8ba892ce8b5a5..615c1d3a20cba732a3d981bf6b2df181e56d2727 100644
|
||||
--- a/third_party/blink/renderer/modules/native_io/native_io_file.cc
|
||||
+++ b/third_party/blink/renderer/modules/native_io/native_io_file.cc
|
||||
@@ -9,6 +9,7 @@
|
||||
#include "base/check.h"
|
||||
#include "base/files/file.h"
|
||||
#include "base/location.h"
|
||||
+#include "base/memory/scoped_refptr.h"
|
||||
#include "base/numerics/checked_math.h"
|
||||
#include "base/sequenced_task_runner.h"
|
||||
#include "base/task/thread_pool.h"
|
||||
@@ -47,31 +48,167 @@
|
||||
|
||||
namespace blink {
|
||||
|
||||
-struct NativeIOFile::FileState {
|
||||
- explicit FileState(base::File file) : file(std::move(file)) {}
|
||||
+// State and logic for performing file I/O off the JavaScript thread.
|
||||
+//
|
||||
+// Instances are allocated on the PartitionAlloc heap. Instances cannot be
|
||||
+// garbage-collected, because garbage collected heaps get deallocated when the
|
||||
+// underlying threads are terminated, and we need a guarantee that each
|
||||
+// instance remains alive while it is used by a thread performing file I/O.
|
||||
+//
|
||||
+// Instances are initially constructed on a Blink thread that executes
|
||||
+// JavaScript, which can be Blink's main thread, or a worker thread. Afterwards,
|
||||
+// instances are (mostly*) only accessed on dedicated threads that do blocking
|
||||
+// file I/O.
|
||||
+//
|
||||
+// Mostly*: On macOS < 10.15, SetLength() synchronously accesses FileState on
|
||||
+// the JavaScript thread. This could be fixed with extra thread hopping. We're
|
||||
+// not currently planning to invest in the fix.
|
||||
+class NativeIOFile::FileState
|
||||
+ : public base::RefCountedThreadSafe<NativeIOFile::FileState> {
|
||||
+ public:
|
||||
+ explicit FileState(base::File file) : file_(std::move(file)) {
|
||||
+ DCHECK(file_.IsValid());
|
||||
+ }
|
||||
|
||||
FileState(const FileState&) = delete;
|
||||
FileState& operator=(const FileState&) = delete;
|
||||
|
||||
~FileState() = default;
|
||||
|
||||
+ // Returns true until Close() is called. Returns false afterwards.
|
||||
+ //
|
||||
+ // On macOS < 10.15, returns false between a TakeFile() call and the
|
||||
+ // corresponding SetFile() call.
|
||||
+ bool IsValid() {
|
||||
+ DCHECK(!IsMainThread());
|
||||
+
|
||||
+ WTF::MutexLocker locker(mutex_);
|
||||
+ return file_.IsValid();
|
||||
+ }
|
||||
+
|
||||
+ void Close() {
|
||||
+ DCHECK(!IsMainThread());
|
||||
+
|
||||
+ WTF::MutexLocker locker(mutex_);
|
||||
+ DCHECK(file_.IsValid()) << __func__ << " called on invalid file";
|
||||
+
|
||||
+ file_.Close();
|
||||
+ }
|
||||
+
|
||||
+ // Returns {length, base::File::FILE_OK} in case of success.
|
||||
+ // Returns {invalid number, error} in case of failure.
|
||||
+ std::pair<int64_t, base::File::Error> GetLength() {
|
||||
+ DCHECK(!IsMainThread());
|
||||
+
|
||||
+ WTF::MutexLocker mutex_locker(mutex_);
|
||||
+ DCHECK(file_.IsValid()) << __func__ << " called on invalid file";
|
||||
+
|
||||
+ int64_t length = file_.GetLength();
|
||||
+ base::File::Error error =
|
||||
+ (length < 0) ? file_.GetLastFileError() : base::File::FILE_OK;
|
||||
+
|
||||
+ return {length, error};
|
||||
+ }
|
||||
+
|
||||
+ // Returns {expected_length, base::File::FILE_OK} in case of success.
|
||||
+ // Returns {actual file length, error} in case of failure.
|
||||
+ std::pair<int64_t, base::File::Error> SetLength(int64_t expected_length) {
|
||||
+ DCHECK(!IsMainThread());
|
||||
+ DCHECK_GE(expected_length, 0);
|
||||
+
|
||||
+ WTF::MutexLocker mutex_locker(mutex_);
|
||||
+ DCHECK(file_.IsValid()) << __func__ << " called on invalid file";
|
||||
+
|
||||
+ bool success = file_.SetLength(expected_length);
|
||||
+ base::File::Error error =
|
||||
+ success ? base::File::FILE_OK : file_.GetLastFileError();
|
||||
+ int64_t actual_length = success ? expected_length : file_.GetLength();
|
||||
+
|
||||
+ return {actual_length, error};
|
||||
+ }
|
||||
+
|
||||
+#if defined(OS_MAC)
|
||||
+ // Used to implement browser-side SetLength() on macOS < 10.15.
|
||||
+ base::File TakeFile() {
|
||||
+ WTF::MutexLocker mutex_locker(mutex_);
|
||||
+ DCHECK(file_.IsValid()) << __func__ << " called on invalid file";
|
||||
+
|
||||
+ return std::move(file_);
|
||||
+ }
|
||||
+
|
||||
+ // Used to implement browser-side SetLength() on macOS < 10.15.
|
||||
+ void SetFile(base::File file) {
|
||||
+ WTF::MutexLocker locker(mutex_);
|
||||
+ DCHECK(!file_.IsValid()) << __func__ << " called on valid file";
|
||||
+
|
||||
+ file_ = std::move(file);
|
||||
+ }
|
||||
+#endif // defined(OS_MAC)
|
||||
+
|
||||
+ // Returns {read byte count, base::File::FILE_OK} in case of success.
|
||||
+ // Returns {invalid number, error} in case of failure.
|
||||
+ std::pair<int, base::File::Error> Read(NativeIODataBuffer* buffer,
|
||||
+ int64_t file_offset,
|
||||
+ int read_size) {
|
||||
+ DCHECK(!IsMainThread());
|
||||
+ DCHECK(buffer);
|
||||
+ DCHECK_GE(file_offset, 0);
|
||||
+ DCHECK_GE(read_size, 0);
|
||||
+
|
||||
+ WTF::MutexLocker mutex_locker(mutex_);
|
||||
+ DCHECK(file_.IsValid()) << __func__ << " called on invalid file";
|
||||
+
|
||||
+ int read_bytes = file_.Read(file_offset, buffer->Data(), read_size);
|
||||
+ base::File::Error error =
|
||||
+ (read_bytes < 0) ? file_.GetLastFileError() : base::File::FILE_OK;
|
||||
+
|
||||
+ return {read_bytes, error};
|
||||
+ }
|
||||
+
|
||||
+ // Returns {0, write_size, base::File::FILE_OK} in case of success.
|
||||
+ // Returns {actual file length, written bytes, base::File::OK} in case of a
|
||||
+ // short write.
|
||||
+ // Returns {actual file length, invalid number, error} in case of failure.
|
||||
+ std::tuple<int64_t, int, base::File::Error> Write(NativeIODataBuffer* buffer,
|
||||
+ int64_t file_offset,
|
||||
+ int write_size) {
|
||||
+ DCHECK(!IsMainThread());
|
||||
+ DCHECK(buffer);
|
||||
+ DCHECK_GE(file_offset, 0);
|
||||
+ DCHECK_GE(write_size, 0);
|
||||
+
|
||||
+ WTF::MutexLocker mutex_locker(mutex_);
|
||||
+ DCHECK(file_.IsValid()) << __func__ << " called on invalid file";
|
||||
+
|
||||
+ int written_bytes = file_.Write(file_offset, buffer->Data(), write_size);
|
||||
+ base::File::Error error =
|
||||
+ (written_bytes < 0) ? file_.GetLastFileError() : base::File::FILE_OK;
|
||||
+ int64_t actual_file_length_on_failure = 0;
|
||||
+ if (written_bytes < write_size || error != base::File::FILE_OK) {
|
||||
+ actual_file_length_on_failure = file_.GetLength();
|
||||
+ if (actual_file_length_on_failure < 0 && error != base::File::FILE_OK)
|
||||
+ error = file_.GetLastFileError();
|
||||
+ }
|
||||
+
|
||||
+ return {actual_file_length_on_failure, written_bytes, error};
|
||||
+ }
|
||||
+
|
||||
+ base::File::Error Flush() {
|
||||
+ DCHECK(!IsMainThread());
|
||||
+
|
||||
+ WTF::MutexLocker mutex_locker(mutex_);
|
||||
+ DCHECK(file_.IsValid()) << __func__ << " called on invalid file";
|
||||
+
|
||||
+ bool success = file_.Flush();
|
||||
+ return success ? base::File::FILE_OK : file_.GetLastFileError();
|
||||
+ }
|
||||
+
|
||||
+ private:
|
||||
// Lock coordinating cross-thread access to the state.
|
||||
- WTF::Mutex mutex;
|
||||
+ WTF::Mutex mutex_;
|
||||
+
|
||||
// The file on disk backing this NativeIOFile.
|
||||
- //
|
||||
- // The mutex is there to protect us against using the file after it was
|
||||
- // closed, and against OS-specific behavior around concurrent file access. It
|
||||
- // should never cause the main (JS) thread to block. This is because the mutex
|
||||
- // is only taken on the main thread in CloseBackingFile(), which is called
|
||||
- // when the NativeIOFile is destroyed (which implies there's no pending I/O
|
||||
- // operation, because all I/O operations hold onto a Persistent<NativeIOFile>)
|
||||
- // and when the mojo pipe is closed, which currently only happens when the JS
|
||||
- // context is being torn down.
|
||||
- //
|
||||
- // TODO(rstz): Is it possible and worthwhile to remove the mutex and rely
|
||||
- // exclusively on |NativeIOFile::io_pending_|, or remove
|
||||
- // |NativeIOFile::io_pending_| in favor of the mutex (might be harder)?
|
||||
- base::File file GUARDED_BY(mutex);
|
||||
+ base::File file_ GUARDED_BY(mutex_);
|
||||
};
|
||||
|
||||
NativeIOFile::NativeIOFile(
|
||||
@@ -81,7 +218,7 @@ NativeIOFile::NativeIOFile(
|
||||
NativeIOCapacityTracker* capacity_tracker,
|
||||
ExecutionContext* execution_context)
|
||||
: file_length_(backing_file_length),
|
||||
- file_state_(std::make_unique<FileState>(std::move(backing_file))),
|
||||
+ file_state_(base::MakeRefCounted<FileState>(std::move(backing_file))),
|
||||
// TODO(pwnall): Get a dedicated queue when the specification matures.
|
||||
resolver_task_runner_(
|
||||
execution_context->GetTaskRunner(TaskType::kMiscPlatformAPI)),
|
||||
@@ -94,7 +231,7 @@ NativeIOFile::NativeIOFile(
|
||||
}
|
||||
|
||||
NativeIOFile::~NativeIOFile() {
|
||||
- // Needed to avoid having the base::File destructor close the file descriptor
|
||||
+ // Needed to avoid having the FileState destructor close the file descriptor
|
||||
// synchronously on the main thread.
|
||||
CloseBackingFile();
|
||||
}
|
||||
@@ -114,6 +251,9 @@ ScriptPromise NativeIOFile::close(ScriptState* script_state) {
|
||||
queued_close_resolver_ = resolver;
|
||||
|
||||
if (!io_pending_) {
|
||||
+ DCHECK(file_state_)
|
||||
+ << "file_state_ nulled out without setting closed_ or io_pending_";
|
||||
+
|
||||
// Pretend that a close() promise was queued behind an I/O operation, and
|
||||
// the operation just finished. This is less logic than handling the
|
||||
// non-queued case separately.
|
||||
@@ -138,18 +278,15 @@ ScriptPromise NativeIOFile::getLength(ScriptState* script_state,
|
||||
"The file was already closed"));
|
||||
return ScriptPromise();
|
||||
}
|
||||
- io_pending_ = true;
|
||||
+ DCHECK(file_state_)
|
||||
+ << "file_state_ nulled out without setting closed_ or io_pending_";
|
||||
|
||||
+ io_pending_ = true;
|
||||
auto* resolver = MakeGarbageCollected<ScriptPromiseResolver>(script_state);
|
||||
- // CrossThreadUnretained() is safe here because the NativeIOFile::FileState
|
||||
- // instance is owned by this NativeIOFile, which is also passed to the task
|
||||
- // via WrapCrossThreadPersistent. Therefore, the FileState instance is
|
||||
- // guaranteed to remain alive during the task's execution.
|
||||
worker_pool::PostTask(
|
||||
FROM_HERE, {base::MayBlock()},
|
||||
CrossThreadBindOnce(&DoGetLength, WrapCrossThreadPersistent(this),
|
||||
- WrapCrossThreadPersistent(resolver),
|
||||
- CrossThreadUnretained(file_state_.get()),
|
||||
+ WrapCrossThreadPersistent(resolver), file_state_,
|
||||
resolver_task_runner_));
|
||||
return resolver->Promise();
|
||||
}
|
||||
@@ -175,6 +312,9 @@ ScriptPromise NativeIOFile::setLength(ScriptState* script_state,
|
||||
"The file was already closed"));
|
||||
return ScriptPromise();
|
||||
}
|
||||
+ DCHECK(file_state_)
|
||||
+ << "file_state_ nulled out without setting closed_ or io_pending_";
|
||||
+
|
||||
int64_t expected_length = base::as_signed(new_length);
|
||||
|
||||
DCHECK_GE(expected_length, 0);
|
||||
@@ -201,8 +341,8 @@ ScriptPromise NativeIOFile::setLength(ScriptState* script_state,
|
||||
}
|
||||
file_length_ = expected_length;
|
||||
}
|
||||
- io_pending_ = true;
|
||||
|
||||
+ io_pending_ = true;
|
||||
auto* resolver = MakeGarbageCollected<ScriptPromiseResolver>(script_state);
|
||||
|
||||
#if defined(OS_MAC)
|
||||
@@ -217,26 +357,19 @@ ScriptPromise NativeIOFile::setLength(ScriptState* script_state,
|
||||
// To preserve this invariant, we pass this file's handle to the browser
|
||||
// process during the SetLength() mojo call, and the browser passes it back
|
||||
// when the call completes.
|
||||
- {
|
||||
- WTF::MutexLocker locker(file_state_->mutex);
|
||||
- backend_file_->SetLength(
|
||||
- expected_length, std::move(file_state_->file),
|
||||
- WTF::Bind(&NativeIOFile::DidSetLengthIpc, WrapPersistent(this),
|
||||
- WrapPersistent(resolver)));
|
||||
- }
|
||||
+ base::File file = file_state_->TakeFile();
|
||||
+ backend_file_->SetLength(
|
||||
+ expected_length, std::move(file),
|
||||
+ WTF::Bind(&NativeIOFile::DidSetLengthIpc, WrapPersistent(this),
|
||||
+ WrapPersistent(resolver)));
|
||||
return resolver->Promise();
|
||||
}
|
||||
#endif // defined(OS_MAC)
|
||||
|
||||
- // CrossThreadUnretained() is safe here because the NativeIOFile::FileState
|
||||
- // instance is owned by this NativeIOFile, which is also passed to the task
|
||||
- // via WrapCrossThreadPersistent. Therefore, the FileState instance is
|
||||
- // guaranteed to remain alive during the task's execution.
|
||||
worker_pool::PostTask(
|
||||
FROM_HERE, {base::MayBlock()},
|
||||
CrossThreadBindOnce(&DoSetLength, WrapCrossThreadPersistent(this),
|
||||
- WrapCrossThreadPersistent(resolver),
|
||||
- CrossThreadUnretained(file_state_.get()),
|
||||
+ WrapCrossThreadPersistent(resolver), file_state_,
|
||||
resolver_task_runner_, expected_length));
|
||||
return resolver->Promise();
|
||||
}
|
||||
@@ -258,6 +391,8 @@ ScriptPromise NativeIOFile::read(ScriptState* script_state,
|
||||
"The file was already closed"));
|
||||
return ScriptPromise();
|
||||
}
|
||||
+ DCHECK(file_state_)
|
||||
+ << "file_state_ nulled out without setting closed_ or io_pending_";
|
||||
|
||||
// TODO(pwnall): This assignment should move right before the
|
||||
// worker_pool::PostTask() call.
|
||||
@@ -281,16 +416,10 @@ ScriptPromise NativeIOFile::read(ScriptState* script_state,
|
||||
DCHECK(buffer->IsDetached());
|
||||
|
||||
auto* resolver = MakeGarbageCollected<ScriptPromiseResolver>(script_state);
|
||||
- // The first CrossThreadUnretained() is safe here because the
|
||||
- // NativeIOFile::FileState instance is owned by this NativeIOFile, which is
|
||||
- // also passed to the task via WrapCrossThreadPersistent. Therefore, the
|
||||
- // FileState instance is guaranteed to remain alive during the task's
|
||||
- // execution.
|
||||
worker_pool::PostTask(
|
||||
FROM_HERE, {base::MayBlock()},
|
||||
CrossThreadBindOnce(&DoRead, WrapCrossThreadPersistent(this),
|
||||
- WrapCrossThreadPersistent(resolver),
|
||||
- CrossThreadUnretained(file_state_.get()),
|
||||
+ WrapCrossThreadPersistent(resolver), file_state_,
|
||||
resolver_task_runner_, std::move(result_buffer_data),
|
||||
file_offset, read_size));
|
||||
return resolver->Promise();
|
||||
@@ -313,6 +442,8 @@ ScriptPromise NativeIOFile::write(ScriptState* script_state,
|
||||
"The file was already closed"));
|
||||
return ScriptPromise();
|
||||
}
|
||||
+ DCHECK(file_state_)
|
||||
+ << "file_state_ nulled out without setting closed_ or io_pending_";
|
||||
|
||||
int write_size = NativeIOOperationSize(*buffer);
|
||||
int64_t write_end_offset;
|
||||
@@ -346,6 +477,14 @@ ScriptPromise NativeIOFile::write(ScriptState* script_state,
|
||||
file_length_ = write_end_offset;
|
||||
}
|
||||
|
||||
+ // TODO(pwnall): This assignment should move right before the
|
||||
+ // worker_pool::PostTask() call.
|
||||
+ //
|
||||
+ // `io_pending_` should only be set to true when we know for sure we'll post a
|
||||
+ // task that eventually results in getting `io_pending_` set back to false.
|
||||
+ // Having `io_pending_` set to true in an early return case (rejecting with an
|
||||
+ // exception) leaves the NativeIOFile "stuck" in a state where all future I/O
|
||||
+ // method calls will reject.
|
||||
io_pending_ = true;
|
||||
|
||||
std::unique_ptr<NativeIODataBuffer> result_buffer_data =
|
||||
@@ -358,16 +497,10 @@ ScriptPromise NativeIOFile::write(ScriptState* script_state,
|
||||
DCHECK(buffer->IsDetached());
|
||||
|
||||
auto* resolver = MakeGarbageCollected<ScriptPromiseResolver>(script_state);
|
||||
- // The first CrossThreadUnretained() is safe here because the
|
||||
- // NativeIOFile::FileState instance is owned by this NativeIOFile, which is
|
||||
- // also passed to the task via WrapCrossThreadPersistent. Therefore, the
|
||||
- // FileState instance is guaranteed to remain alive during the task's
|
||||
- // execution.
|
||||
worker_pool::PostTask(
|
||||
FROM_HERE, {base::MayBlock()},
|
||||
CrossThreadBindOnce(&DoWrite, WrapCrossThreadPersistent(this),
|
||||
- WrapCrossThreadPersistent(resolver),
|
||||
- CrossThreadUnretained(file_state_.get()),
|
||||
+ WrapCrossThreadPersistent(resolver), file_state_,
|
||||
resolver_task_runner_, std::move(result_buffer_data),
|
||||
file_offset, write_size));
|
||||
return resolver->Promise();
|
||||
@@ -391,18 +524,15 @@ ScriptPromise NativeIOFile::flush(ScriptState* script_state,
|
||||
"The file was already closed"));
|
||||
return ScriptPromise();
|
||||
}
|
||||
- io_pending_ = true;
|
||||
+ DCHECK(file_state_)
|
||||
+ << "file_state_ nulled out without setting closed_ or io_pending_";
|
||||
|
||||
+ io_pending_ = true;
|
||||
auto* resolver = MakeGarbageCollected<ScriptPromiseResolver>(script_state);
|
||||
- // CrossThreadUnretained() is safe here because the NativeIOFile::FileState
|
||||
- // instance is owned by this NativeIOFile, which is also passed to the task
|
||||
- // via WrapCrossThreadPersistent. Therefore, the FileState instance is
|
||||
- // guaranteed to remain alive during the task's execution.
|
||||
worker_pool::PostTask(
|
||||
FROM_HERE, {base::MayBlock()},
|
||||
CrossThreadBindOnce(&DoFlush, WrapCrossThreadPersistent(this),
|
||||
- WrapCrossThreadPersistent(resolver),
|
||||
- CrossThreadUnretained(file_state_.get()),
|
||||
+ WrapCrossThreadPersistent(resolver), file_state_,
|
||||
resolver_task_runner_));
|
||||
return resolver->Promise();
|
||||
}
|
||||
@@ -430,28 +560,29 @@ void NativeIOFile::DispatchQueuedClose() {
|
||||
ScriptPromiseResolver* resolver = queued_close_resolver_;
|
||||
queued_close_resolver_ = nullptr;
|
||||
|
||||
+ scoped_refptr<FileState> file_state = std::move(file_state_);
|
||||
+ DCHECK(!file_state_);
|
||||
+
|
||||
worker_pool::PostTask(
|
||||
FROM_HERE, {base::MayBlock()},
|
||||
CrossThreadBindOnce(&DoClose, WrapCrossThreadPersistent(this),
|
||||
WrapCrossThreadPersistent(resolver),
|
||||
- CrossThreadUnretained(file_state_.get()),
|
||||
- resolver_task_runner_));
|
||||
+ std::move(file_state), resolver_task_runner_));
|
||||
}
|
||||
|
||||
// static
|
||||
void NativeIOFile::DoClose(
|
||||
CrossThreadPersistent<NativeIOFile> native_io_file,
|
||||
CrossThreadPersistent<ScriptPromiseResolver> resolver,
|
||||
- NativeIOFile::FileState* file_state,
|
||||
+ scoped_refptr<NativeIOFile::FileState> file_state,
|
||||
scoped_refptr<base::SequencedTaskRunner> resolver_task_runner) {
|
||||
DCHECK(!IsMainThread()) << "File I/O should not happen on the main thread";
|
||||
+ DCHECK(file_state);
|
||||
+ DCHECK(file_state->IsValid())
|
||||
+ << "File I/O operation queued after file closed";
|
||||
+ DCHECK(resolver_task_runner);
|
||||
|
||||
- {
|
||||
- WTF::MutexLocker locker(file_state->mutex);
|
||||
- DCHECK(file_state->file.IsValid())
|
||||
- << "file I/O operation queued after file closed";
|
||||
- file_state->file.Close();
|
||||
- }
|
||||
+ file_state->Close();
|
||||
|
||||
PostCrossThreadTask(
|
||||
*resolver_task_runner, FROM_HERE,
|
||||
@@ -482,19 +613,17 @@ void NativeIOFile::DidClose(
|
||||
void NativeIOFile::DoGetLength(
|
||||
CrossThreadPersistent<NativeIOFile> native_io_file,
|
||||
CrossThreadPersistent<ScriptPromiseResolver> resolver,
|
||||
- NativeIOFile::FileState* file_state,
|
||||
+ scoped_refptr<NativeIOFile::FileState> file_state,
|
||||
scoped_refptr<base::SequencedTaskRunner> resolver_task_runner) {
|
||||
DCHECK(!IsMainThread()) << "File I/O should not happen on the main thread";
|
||||
+ DCHECK(file_state);
|
||||
+ DCHECK(file_state->IsValid())
|
||||
+ << "File I/O operation queued after file closed";
|
||||
+ DCHECK(resolver_task_runner);
|
||||
+
|
||||
+ int64_t length;
|
||||
base::File::Error get_length_error;
|
||||
- int64_t length = -1;
|
||||
- {
|
||||
- WTF::MutexLocker mutex_locker(file_state->mutex);
|
||||
- DCHECK(file_state->file.IsValid())
|
||||
- << "file I/O operation queued after file closed";
|
||||
- length = file_state->file.GetLength();
|
||||
- get_length_error = (length < 0) ? file_state->file.GetLastFileError()
|
||||
- : base::File::FILE_OK;
|
||||
- }
|
||||
+ std::tie(length, get_length_error) = file_state->GetLength();
|
||||
|
||||
PostCrossThreadTask(
|
||||
*resolver_task_runner, FROM_HERE,
|
||||
@@ -541,22 +670,20 @@ void NativeIOFile::DidGetLength(
|
||||
void NativeIOFile::DoSetLength(
|
||||
CrossThreadPersistent<NativeIOFile> native_io_file,
|
||||
CrossThreadPersistent<ScriptPromiseResolver> resolver,
|
||||
- NativeIOFile::FileState* file_state,
|
||||
+ scoped_refptr<NativeIOFile::FileState> file_state,
|
||||
scoped_refptr<base::SequencedTaskRunner> resolver_task_runner,
|
||||
int64_t expected_length) {
|
||||
DCHECK(!IsMainThread()) << "File I/O should not happen on the main thread";
|
||||
+ DCHECK(file_state);
|
||||
+ DCHECK(file_state->IsValid())
|
||||
+ << "File I/O operation queued after file closed";
|
||||
+ DCHECK(resolver_task_runner);
|
||||
+ DCHECK_GE(expected_length, 0);
|
||||
|
||||
- base::File::Error set_length_error;
|
||||
int64_t actual_length;
|
||||
- {
|
||||
- WTF::MutexLocker mutex_locker(file_state->mutex);
|
||||
- DCHECK(file_state->file.IsValid())
|
||||
- << "file I/O operation queued after file closed";
|
||||
- bool success = file_state->file.SetLength(expected_length);
|
||||
- set_length_error =
|
||||
- success ? base::File::FILE_OK : file_state->file.GetLastFileError();
|
||||
- actual_length = success ? expected_length : file_state->file.GetLength();
|
||||
- }
|
||||
+ base::File::Error set_length_error;
|
||||
+ std::tie(actual_length, set_length_error) =
|
||||
+ file_state->SetLength(expected_length);
|
||||
|
||||
PostCrossThreadTask(
|
||||
*resolver_task_runner, FROM_HERE,
|
||||
@@ -619,10 +746,7 @@ void NativeIOFile::DidSetLengthIpc(
|
||||
int64_t actual_length,
|
||||
mojom::blink::NativeIOErrorPtr set_length_error) {
|
||||
DCHECK(backing_file.IsValid()) << "browser returned closed file";
|
||||
- {
|
||||
- WTF::MutexLocker locker(file_state_->mutex);
|
||||
- file_state_->file = std::move(backing_file);
|
||||
- }
|
||||
+ file_state_->SetFile(std::move(backing_file));
|
||||
ScriptState* script_state = resolver->GetScriptState();
|
||||
|
||||
DCHECK(io_pending_) << "I/O operation performed without io_pending_ set";
|
||||
@@ -673,13 +797,15 @@ void NativeIOFile::DidSetLengthIpc(
|
||||
void NativeIOFile::DoRead(
|
||||
CrossThreadPersistent<NativeIOFile> native_io_file,
|
||||
CrossThreadPersistent<ScriptPromiseResolver> resolver,
|
||||
- NativeIOFile::FileState* file_state,
|
||||
+ scoped_refptr<NativeIOFile::FileState> file_state,
|
||||
scoped_refptr<base::SequencedTaskRunner> resolver_task_runner,
|
||||
std::unique_ptr<NativeIODataBuffer> result_buffer_data,
|
||||
uint64_t file_offset,
|
||||
int read_size) {
|
||||
DCHECK(!IsMainThread()) << "File I/O should not happen on the main thread";
|
||||
-
|
||||
+ DCHECK(file_state);
|
||||
+ DCHECK(file_state->IsValid())
|
||||
+ << "File I/O operation queued after file closed";
|
||||
DCHECK(resolver_task_runner);
|
||||
DCHECK(result_buffer_data);
|
||||
DCHECK(result_buffer_data->IsValid());
|
||||
@@ -690,15 +816,8 @@ void NativeIOFile::DoRead(
|
||||
|
||||
int read_bytes;
|
||||
base::File::Error read_error;
|
||||
- {
|
||||
- WTF::MutexLocker mutex_locker(file_state->mutex);
|
||||
- DCHECK(file_state->file.IsValid())
|
||||
- << "file I/O operation queued after file closed";
|
||||
- read_bytes = file_state->file.Read(file_offset, result_buffer_data->Data(),
|
||||
- read_size);
|
||||
- read_error = (read_bytes < 0) ? file_state->file.GetLastFileError()
|
||||
- : base::File::FILE_OK;
|
||||
- }
|
||||
+ std::tie(read_bytes, read_error) =
|
||||
+ file_state->Read(result_buffer_data.get(), file_offset, read_size);
|
||||
|
||||
PostCrossThreadTask(
|
||||
*resolver_task_runner, FROM_HERE,
|
||||
@@ -743,12 +862,15 @@ void NativeIOFile::DidRead(
|
||||
void NativeIOFile::DoWrite(
|
||||
CrossThreadPersistent<NativeIOFile> native_io_file,
|
||||
CrossThreadPersistent<ScriptPromiseResolver> resolver,
|
||||
- NativeIOFile::FileState* file_state,
|
||||
+ scoped_refptr<NativeIOFile::FileState> file_state,
|
||||
scoped_refptr<base::SequencedTaskRunner> resolver_task_runner,
|
||||
std::unique_ptr<NativeIODataBuffer> result_buffer_data,
|
||||
uint64_t file_offset,
|
||||
int write_size) {
|
||||
DCHECK(!IsMainThread()) << "File I/O should not happen on the main thread";
|
||||
+ DCHECK(file_state);
|
||||
+ DCHECK(file_state->IsValid())
|
||||
+ << "File I/O operation queued after file closed";
|
||||
DCHECK(resolver_task_runner);
|
||||
DCHECK(result_buffer_data);
|
||||
DCHECK(result_buffer_data->IsValid());
|
||||
@@ -760,22 +882,8 @@ void NativeIOFile::DoWrite(
|
||||
int written_bytes;
|
||||
int64_t actual_file_length_on_failure = 0;
|
||||
base::File::Error write_error;
|
||||
- {
|
||||
- WTF::MutexLocker mutex_locker(file_state->mutex);
|
||||
- DCHECK(file_state->file.IsValid())
|
||||
- << "file I/O operation queued after file closed";
|
||||
- written_bytes = file_state->file.Write(
|
||||
- file_offset, result_buffer_data->Data(), write_size);
|
||||
- write_error = (written_bytes < 0) ? file_state->file.GetLastFileError()
|
||||
- : base::File::FILE_OK;
|
||||
- if (written_bytes < write_size || write_error != base::File::FILE_OK) {
|
||||
- actual_file_length_on_failure = file_state->file.GetLength();
|
||||
- if (actual_file_length_on_failure < 0 &&
|
||||
- write_error != base::File::FILE_OK) {
|
||||
- write_error = file_state->file.GetLastFileError();
|
||||
- }
|
||||
- }
|
||||
- }
|
||||
+ std::tie(actual_file_length_on_failure, written_bytes, write_error) =
|
||||
+ file_state->Write(result_buffer_data.get(), file_offset, write_size);
|
||||
|
||||
PostCrossThreadTask(
|
||||
*resolver_task_runner, FROM_HERE,
|
||||
@@ -846,18 +954,14 @@ void NativeIOFile::DidWrite(
|
||||
void NativeIOFile::DoFlush(
|
||||
CrossThreadPersistent<NativeIOFile> native_io_file,
|
||||
CrossThreadPersistent<ScriptPromiseResolver> resolver,
|
||||
- NativeIOFile::FileState* file_state,
|
||||
+ scoped_refptr<NativeIOFile::FileState> file_state,
|
||||
scoped_refptr<base::SequencedTaskRunner> resolver_task_runner) {
|
||||
DCHECK(!IsMainThread()) << "File I/O should not happen on the main thread";
|
||||
- base::File::Error flush_error;
|
||||
- {
|
||||
- WTF::MutexLocker mutex_locker(file_state->mutex);
|
||||
- DCHECK(file_state->file.IsValid())
|
||||
- << "file I/O operation queued after file closed";
|
||||
- bool success = file_state->file.Flush();
|
||||
- flush_error =
|
||||
- success ? base::File::FILE_OK : file_state->file.GetLastFileError();
|
||||
- }
|
||||
+ DCHECK(file_state);
|
||||
+ DCHECK(file_state->IsValid())
|
||||
+ << "File I/O operation queued after file closed";
|
||||
+
|
||||
+ base::File::Error flush_error = file_state->Flush();
|
||||
|
||||
PostCrossThreadTask(
|
||||
*resolver_task_runner, FROM_HERE,
|
||||
@@ -887,20 +991,23 @@ void NativeIOFile::DidFlush(
|
||||
|
||||
void NativeIOFile::CloseBackingFile() {
|
||||
closed_ = true;
|
||||
- file_state_->mutex.lock();
|
||||
- base::File backing_file = std::move(file_state_->file);
|
||||
- file_state_->mutex.unlock();
|
||||
|
||||
- if (!backing_file.IsValid()) {
|
||||
+ if (!file_state_) {
|
||||
// Avoid posting a cross-thread task if the file is already closed. This is
|
||||
// the expected path.
|
||||
return;
|
||||
}
|
||||
|
||||
- worker_pool::PostTask(
|
||||
- FROM_HERE, {base::MayBlock()},
|
||||
- CrossThreadBindOnce([](base::File file) { file.Close(); },
|
||||
- std::move(backing_file)));
|
||||
+ scoped_refptr<FileState> file_state = std::move(file_state_);
|
||||
+ DCHECK(!file_state_);
|
||||
+
|
||||
+ worker_pool::PostTask(FROM_HERE, {base::MayBlock()},
|
||||
+ CrossThreadBindOnce(
|
||||
+ [](scoped_refptr<FileState> file_state) {
|
||||
+ DCHECK(file_state);
|
||||
+ file_state->Close();
|
||||
+ },
|
||||
+ std::move(file_state)));
|
||||
}
|
||||
|
||||
} // namespace blink
|
||||
diff --git a/third_party/blink/renderer/modules/native_io/native_io_file.h b/third_party/blink/renderer/modules/native_io/native_io_file.h
|
||||
index 8ae49ebc2d36d547d152d4e56192e30f8cacd641..95d2da4ac3e1859a0abc21ea15d269758eed1681 100644
|
||||
--- a/third_party/blink/renderer/modules/native_io/native_io_file.h
|
||||
+++ b/third_party/blink/renderer/modules/native_io/native_io_file.h
|
||||
@@ -67,12 +67,7 @@ class NativeIOFile final : public ScriptWrappable {
|
||||
void Trace(Visitor* visitor) const override;
|
||||
|
||||
private:
|
||||
- // Data accessed on the threads that do file I/O.
|
||||
- //
|
||||
- // Instances are allocated on the PartitionAlloc heap. Instances are initially
|
||||
- // constructed on Blink's main thread, or on a worker thread. Afterwards,
|
||||
- // instances are only accessed on dedicated threads that do blocking file I/O.
|
||||
- struct FileState;
|
||||
+ class FileState;
|
||||
|
||||
// Called when the mojo backend disconnects.
|
||||
void OnBackendDisconnect();
|
||||
@@ -84,7 +79,7 @@ class NativeIOFile final : public ScriptWrappable {
|
||||
static void DoClose(
|
||||
CrossThreadPersistent<NativeIOFile> native_io_file,
|
||||
CrossThreadPersistent<ScriptPromiseResolver> resolver,
|
||||
- NativeIOFile::FileState* file_state,
|
||||
+ scoped_refptr<NativeIOFile::FileState> file_state,
|
||||
scoped_refptr<base::SequencedTaskRunner> file_task_runner);
|
||||
// Performs the post file I/O part of close(), on the main thread.
|
||||
void DidClose(CrossThreadPersistent<ScriptPromiseResolver> resolver);
|
||||
@@ -93,7 +88,7 @@ class NativeIOFile final : public ScriptWrappable {
|
||||
static void DoGetLength(
|
||||
CrossThreadPersistent<NativeIOFile> native_io_file,
|
||||
CrossThreadPersistent<ScriptPromiseResolver> resolver,
|
||||
- NativeIOFile::FileState* file_state,
|
||||
+ scoped_refptr<NativeIOFile::FileState> file_state,
|
||||
scoped_refptr<base::SequencedTaskRunner> file_task_runner);
|
||||
// Performs the post file I/O part of getLength(), on the main thread.
|
||||
void DidGetLength(CrossThreadPersistent<ScriptPromiseResolver> resolver,
|
||||
@@ -104,7 +99,7 @@ class NativeIOFile final : public ScriptWrappable {
|
||||
static void DoSetLength(
|
||||
CrossThreadPersistent<NativeIOFile> native_io_file,
|
||||
CrossThreadPersistent<ScriptPromiseResolver> resolver,
|
||||
- NativeIOFile::FileState* file_state,
|
||||
+ scoped_refptr<NativeIOFile::FileState> file_state,
|
||||
scoped_refptr<base::SequencedTaskRunner> file_task_runner,
|
||||
int64_t expected_length);
|
||||
// Performs the post file I/O part of setLength(), on the main thread.
|
||||
@@ -128,7 +123,7 @@ class NativeIOFile final : public ScriptWrappable {
|
||||
// Performs the file I/O part of read(), off the main thread.
|
||||
static void DoRead(CrossThreadPersistent<NativeIOFile> native_io_file,
|
||||
CrossThreadPersistent<ScriptPromiseResolver> resolver,
|
||||
- NativeIOFile::FileState* file_state,
|
||||
+ scoped_refptr<NativeIOFile::FileState> file_state,
|
||||
scoped_refptr<base::SequencedTaskRunner> file_task_runner,
|
||||
std::unique_ptr<NativeIODataBuffer> result_buffer_data,
|
||||
uint64_t file_offset,
|
||||
@@ -143,7 +138,7 @@ class NativeIOFile final : public ScriptWrappable {
|
||||
static void DoWrite(
|
||||
CrossThreadPersistent<NativeIOFile> native_io_file,
|
||||
CrossThreadPersistent<ScriptPromiseResolver> resolver,
|
||||
- NativeIOFile::FileState* file_state,
|
||||
+ scoped_refptr<NativeIOFile::FileState> file_state,
|
||||
scoped_refptr<base::SequencedTaskRunner> resolver_task_runner,
|
||||
std::unique_ptr<NativeIODataBuffer> result_buffer_data,
|
||||
uint64_t file_offset,
|
||||
@@ -163,7 +158,7 @@ class NativeIOFile final : public ScriptWrappable {
|
||||
static void DoFlush(
|
||||
CrossThreadPersistent<NativeIOFile> native_io_file,
|
||||
CrossThreadPersistent<ScriptPromiseResolver> resolver,
|
||||
- NativeIOFile::FileState* file_state,
|
||||
+ scoped_refptr<NativeIOFile::FileState> file_state,
|
||||
scoped_refptr<base::SequencedTaskRunner> file_task_runner);
|
||||
// Performs the post file-I/O part of flush(), on the main thread.
|
||||
void DidFlush(CrossThreadPersistent<ScriptPromiseResolver> resolver,
|
||||
@@ -210,8 +205,13 @@ class NativeIOFile final : public ScriptWrappable {
|
||||
// TODO(rstz): Consider moving this variable into `file_state_`
|
||||
int64_t file_length_ = 0;
|
||||
|
||||
- // See NativeIOFile::FileState, declared above.
|
||||
- const std::unique_ptr<FileState> file_state_;
|
||||
+ // Points to a NativeIOFile::FileState while the underlying file is open.
|
||||
+ //
|
||||
+ // When the underlying file is closed, this pointer is nulled out, and the
|
||||
+ // FileState instance is passed to a different thread, where the closing
|
||||
+ // happens. This avoids having any I/O performed by the base::File::Close()
|
||||
+ // jank the JavaScript thread that owns this NativeIOFile instance.
|
||||
+ scoped_refptr<FileState> file_state_;
|
||||
|
||||
// Schedules resolving Promises with file I/O results.
|
||||
const scoped_refptr<base::SequencedTaskRunner> resolver_task_runner_;
|
||||
1863
patches/chromium/cherry-pick-905302eb3a2b.patch
Normal file
1863
patches/chromium/cherry-pick-905302eb3a2b.patch
Normal file
File diff suppressed because it is too large
Load Diff
151
patches/chromium/cherry-pick-9db9911e1242.patch
Normal file
151
patches/chromium/cherry-pick-9db9911e1242.patch
Normal file
@@ -0,0 +1,151 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Stephen Roettger <sroettger@google.com>
|
||||
Date: Fri, 7 Jan 2022 09:36:31 +0000
|
||||
Subject: Keep a set of previously dropped peers
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
|
||||
Test that a given node name hasn't been seen before.
|
||||
A side effect of this fix is that re-invitation will not work anymore.
|
||||
|
||||
BUG=chromium:1274113
|
||||
|
||||
Change-Id: Ibdc50291efa1f6298614b163b544ad980615a981
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3341553
|
||||
Reviewed-by: Ken Rockot <rockot@google.com>
|
||||
Commit-Queue: Stephen Röttger <sroettger@google.com>
|
||||
Cr-Commit-Position: refs/heads/main@{#956441}
|
||||
|
||||
diff --git a/mojo/core/invitation_unittest.cc b/mojo/core/invitation_unittest.cc
|
||||
index 2c8eeef9feefc6be689f1ca2052af316b4b7db68..0687a58ee2b294580d1165e872ec5855e5de2b53 100644
|
||||
--- a/mojo/core/invitation_unittest.cc
|
||||
+++ b/mojo/core/invitation_unittest.cc
|
||||
@@ -693,7 +693,8 @@ DEFINE_TEST_CLIENT(ProcessErrorsClient) {
|
||||
EXPECT_EQ(kDisconnectMessage, ReadMessage(pipe));
|
||||
}
|
||||
|
||||
-TEST_F(InvitationTest, Reinvitation) {
|
||||
+// Temporary removed support for reinvitation for non-isolated connections.
|
||||
+TEST_F(InvitationTest, DISABLED_Reinvitation) {
|
||||
// The gist of this test is that a process should be able to accept an
|
||||
// invitation, lose its connection to the process network, and then accept a
|
||||
// new invitation to re-establish communication.
|
||||
diff --git a/mojo/core/node_controller.cc b/mojo/core/node_controller.cc
|
||||
index b34753b2dc0c58e5a80e1d0678ee178e2589e8e3..1a343929127e748b78fdb2107ec7a91f71c846a7 100644
|
||||
--- a/mojo/core/node_controller.cc
|
||||
+++ b/mojo/core/node_controller.cc
|
||||
@@ -543,7 +543,8 @@ scoped_refptr<NodeChannel> NodeController::GetBrokerChannel() {
|
||||
|
||||
void NodeController::AddPeer(const ports::NodeName& name,
|
||||
scoped_refptr<NodeChannel> channel,
|
||||
- bool start_channel) {
|
||||
+ bool start_channel,
|
||||
+ bool allow_name_reuse) {
|
||||
DCHECK(io_task_runner_->RunsTasksInCurrentSequence());
|
||||
|
||||
DCHECK(name != ports::kInvalidNodeName);
|
||||
@@ -562,6 +563,11 @@ void NodeController::AddPeer(const ports::NodeName& name,
|
||||
return;
|
||||
}
|
||||
|
||||
+ if (dropped_peers_.Contains(name) && !allow_name_reuse) {
|
||||
+ LOG(ERROR) << "Trying to re-add dropped peer " << name;
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
auto result = peers_.insert(std::make_pair(name, channel));
|
||||
DCHECK(result.second);
|
||||
|
||||
@@ -602,6 +608,7 @@ void NodeController::DropPeer(const ports::NodeName& node_name,
|
||||
if (it != peers_.end()) {
|
||||
ports::NodeName peer = it->first;
|
||||
peers_.erase(it);
|
||||
+ dropped_peers_.Insert(peer);
|
||||
DVLOG(1) << "Dropped peer " << peer;
|
||||
}
|
||||
|
||||
@@ -1270,7 +1277,8 @@ void NodeController::OnAcceptPeer(const ports::NodeName& from_node,
|
||||
// Note that we explicitly drop any prior connection to the same peer so
|
||||
// that new isolated connections can replace old ones.
|
||||
DropPeer(peer_name, nullptr);
|
||||
- AddPeer(peer_name, channel, false /* start_channel */);
|
||||
+ AddPeer(peer_name, channel, false /* start_channel */,
|
||||
+ true /* allow_name_reuse */);
|
||||
DVLOG(1) << "Node " << name_ << " accepted peer " << peer_name;
|
||||
}
|
||||
|
||||
@@ -1386,5 +1394,24 @@ NodeController::IsolatedConnection&
|
||||
NodeController::IsolatedConnection::operator=(IsolatedConnection&& other) =
|
||||
default;
|
||||
|
||||
+BoundedPeerSet::BoundedPeerSet() = default;
|
||||
+BoundedPeerSet::~BoundedPeerSet() = default;
|
||||
+
|
||||
+void BoundedPeerSet::Insert(const ports::NodeName& name) {
|
||||
+ if (new_set_.size() == kHalfSize) {
|
||||
+ old_set_.clear();
|
||||
+ std::swap(old_set_, new_set_);
|
||||
+ }
|
||||
+ new_set_.insert(name);
|
||||
+}
|
||||
+
|
||||
+bool BoundedPeerSet::Contains(const ports::NodeName& name) {
|
||||
+ if (old_set_.find(name) != old_set_.end())
|
||||
+ return true;
|
||||
+ if (new_set_.find(name) != new_set_.end())
|
||||
+ return true;
|
||||
+ return false;
|
||||
+}
|
||||
+
|
||||
} // namespace core
|
||||
} // namespace mojo
|
||||
diff --git a/mojo/core/node_controller.h b/mojo/core/node_controller.h
|
||||
index 040eeab79f72efcdb2823cf62e7dbaefa8b9233f..571e578da4950135456bb97c8ea7a30ceabca7cc 100644
|
||||
--- a/mojo/core/node_controller.h
|
||||
+++ b/mojo/core/node_controller.h
|
||||
@@ -38,6 +38,26 @@ namespace core {
|
||||
class Broker;
|
||||
class Core;
|
||||
|
||||
+// A set of NodeNames that is bounded by a maximum size.
|
||||
+// If the max size is reached, it will delete the older half of stored names.
|
||||
+class BoundedPeerSet {
|
||||
+ public:
|
||||
+ BoundedPeerSet();
|
||||
+ BoundedPeerSet(const BoundedPeerSet&) = delete;
|
||||
+ BoundedPeerSet& operator=(const BoundedPeerSet&) = delete;
|
||||
+
|
||||
+ ~BoundedPeerSet();
|
||||
+
|
||||
+ void Insert(const ports::NodeName& name);
|
||||
+ bool Contains(const ports::NodeName& name);
|
||||
+
|
||||
+ private:
|
||||
+ static constexpr int kHalfSize = 50000;
|
||||
+
|
||||
+ std::unordered_set<ports::NodeName> old_set_;
|
||||
+ std::unordered_set<ports::NodeName> new_set_;
|
||||
+};
|
||||
+
|
||||
// The owner of ports::Node which facilitates core EDK implementation. All
|
||||
// public interface methods are safe to call from any thread.
|
||||
class MOJO_SYSTEM_IMPL_EXPORT NodeController : public ports::NodeDelegate,
|
||||
@@ -180,7 +200,8 @@ class MOJO_SYSTEM_IMPL_EXPORT NodeController : public ports::NodeDelegate,
|
||||
|
||||
void AddPeer(const ports::NodeName& name,
|
||||
scoped_refptr<NodeChannel> channel,
|
||||
- bool start_channel);
|
||||
+ bool start_channel,
|
||||
+ bool allow_name_reuse = false);
|
||||
void DropPeer(const ports::NodeName& name, NodeChannel* channel);
|
||||
void SendPeerEvent(const ports::NodeName& name, ports::ScopedEvent event);
|
||||
void DropAllPeers();
|
||||
@@ -265,6 +286,7 @@ class MOJO_SYSTEM_IMPL_EXPORT NodeController : public ports::NodeDelegate,
|
||||
|
||||
// Channels to known peers, including inviter and invitees, if any.
|
||||
NodeMap peers_;
|
||||
+ BoundedPeerSet dropped_peers_;
|
||||
|
||||
// Outgoing message queues for peers we've heard of but can't yet talk to.
|
||||
std::unordered_map<ports::NodeName, OutgoingMessageQueue>
|
||||
649
patches/chromium/cherry-pick-a5f54612590d.patch
Normal file
649
patches/chromium/cherry-pick-a5f54612590d.patch
Normal file
@@ -0,0 +1,649 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Victor Costan <pwnall@chromium.org>
|
||||
Date: Wed, 10 Nov 2021 21:14:03 +0000
|
||||
Subject: M96: Storage Foundation: Avoid cross-thread access of
|
||||
DOMArrayBufferView.
|
||||
|
||||
blink::NativeIOFile::{read, write}() (in the Storage Foundation API
|
||||
implementation) pass DOMArrayBufferView instances to
|
||||
blink::NativeIOFile::Do{Read,Write}() via CrossThreadPersistent.
|
||||
blink::NativeIOFile::Do{Read,Write}() accesses these instances.
|
||||
|
||||
CrossThreadPersistent can be used across threads to keep a garbage
|
||||
collected object alive. However, accessing the object on a different
|
||||
thread is not safe. cppgc::subtle::CrossThreadPersistent
|
||||
(blink::CrossThreadPersistent is an alias to that) has comments
|
||||
explaining that the garbage collected heap can go away while the
|
||||
CrossThreadPersistent instance exists.
|
||||
|
||||
This CL bypasses the problem by having Do{Read,Write}() receive a
|
||||
ArrayBufferContents that has the DOMArrayBufferView's backing buffer.
|
||||
ArrayBufferContents is not garbage-collected, so it can be safely used
|
||||
across threads.
|
||||
|
||||
This CL introduces a NativeIODataBuffer class that contains the logic
|
||||
and state for tearing a DOMArrayBufferView apart into its components
|
||||
(backing buffer, view type, view offset, view length) and putting it
|
||||
back together into a new DOMArrayBufferView, after it doesn't need to be
|
||||
accessed cross-thread anymore.
|
||||
|
||||
(cherry picked from commit 5200793c2aea5979cc79f3350a4e3d6c0795d6f2)
|
||||
|
||||
Bug: 1268274
|
||||
Change-Id: I51588f5bfe963de96ce426e0f480e8c5b4902688
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3269366
|
||||
Commit-Queue: Victor Costan <pwnall@chromium.org>
|
||||
Reviewed-by: enne <enne@chromium.org>
|
||||
Reviewed-by: Joshua Bell <jsbell@chromium.org>
|
||||
Cr-Original-Commit-Position: refs/heads/main@{#940070}
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3272377
|
||||
Bot-Commit: Rubber Stamper <rubber-stamper@appspot.gserviceaccount.com>
|
||||
Cr-Commit-Position: refs/branch-heads/4664@{#941}
|
||||
Cr-Branched-From: 24dc4ee75e01a29d390d43c9c264372a169273a7-refs/heads/main@{#929512}
|
||||
|
||||
diff --git a/third_party/blink/renderer/modules/native_io/native_io_file.cc b/third_party/blink/renderer/modules/native_io/native_io_file.cc
|
||||
index b25cf909f05be73f690fabee7942ee1fa83c1e04..4d5aa4efa13930aea4886bac0fd8ba892ce8b5a5 100644
|
||||
--- a/third_party/blink/renderer/modules/native_io/native_io_file.cc
|
||||
+++ b/third_party/blink/renderer/modules/native_io/native_io_file.cc
|
||||
@@ -24,7 +24,9 @@
|
||||
#include "third_party/blink/renderer/core/execution_context/execution_context.h"
|
||||
#include "third_party/blink/renderer/core/execution_context/execution_context_lifecycle_observer.h"
|
||||
#include "third_party/blink/renderer/core/execution_context/execution_context_lifecycle_state_observer.h"
|
||||
+#include "third_party/blink/renderer/core/typed_arrays/array_buffer/array_buffer_contents.h"
|
||||
#include "third_party/blink/renderer/core/typed_arrays/dom_array_buffer.h"
|
||||
+#include "third_party/blink/renderer/core/typed_arrays/dom_array_buffer_view.h"
|
||||
#include "third_party/blink/renderer/modules/native_io/native_io_error.h"
|
||||
#include "third_party/blink/renderer/modules/native_io/native_io_file_utils.h"
|
||||
#include "third_party/blink/renderer/platform/bindings/exception_code.h"
|
||||
@@ -256,39 +258,41 @@ ScriptPromise NativeIOFile::read(ScriptState* script_state,
|
||||
"The file was already closed"));
|
||||
return ScriptPromise();
|
||||
}
|
||||
+
|
||||
+ // TODO(pwnall): This assignment should move right before the
|
||||
+ // worker_pool::PostTask() call.
|
||||
+ //
|
||||
+ // `io_pending_` should only be set to true when we know for sure we'll post a
|
||||
+ // task that eventually results in getting `io_pending_` set back to false.
|
||||
+ // Having `io_pending_` set to true in an early return case (rejecting with an
|
||||
+ // exception) leaves the NativeIOFile "stuck" in a state where all future I/O
|
||||
+ // method calls will reject.
|
||||
io_pending_ = true;
|
||||
|
||||
int read_size = NativeIOOperationSize(*buffer);
|
||||
|
||||
- DOMArrayBufferView* result_buffer =
|
||||
- TransferToNewArrayBufferView(script_state->GetIsolate(), buffer);
|
||||
- if (!result_buffer) {
|
||||
+ std::unique_ptr<NativeIODataBuffer> result_buffer_data =
|
||||
+ NativeIODataBuffer::Create(script_state, buffer);
|
||||
+ if (!result_buffer_data) {
|
||||
exception_state.ThrowTypeError("Could not transfer buffer");
|
||||
return ScriptPromise();
|
||||
}
|
||||
+ DCHECK(result_buffer_data->IsValid());
|
||||
DCHECK(buffer->IsDetached());
|
||||
|
||||
- char* result_buffer_data = static_cast<char*>(result_buffer->BaseAddress());
|
||||
-
|
||||
auto* resolver = MakeGarbageCollected<ScriptPromiseResolver>(script_state);
|
||||
// The first CrossThreadUnretained() is safe here because the
|
||||
// NativeIOFile::FileState instance is owned by this NativeIOFile, which is
|
||||
// also passed to the task via WrapCrossThreadPersistent. Therefore, the
|
||||
// FileState instance is guaranteed to remain alive during the task's
|
||||
// execution.
|
||||
- //
|
||||
- // The second CrossThreadUnretained() is safe here because result_buffer_data
|
||||
- // is backed by a DOMArrayBufferView that is also passed to the task via
|
||||
- // WrapCrossThreadPersistent. Therefore, the buffer is guaranteed to remain
|
||||
- // alive during the task's execution.
|
||||
worker_pool::PostTask(
|
||||
FROM_HERE, {base::MayBlock()},
|
||||
- CrossThreadBindOnce(
|
||||
- &DoRead, WrapCrossThreadPersistent(this),
|
||||
- WrapCrossThreadPersistent(resolver),
|
||||
- WrapCrossThreadPersistent(result_buffer),
|
||||
- CrossThreadUnretained(file_state_.get()), resolver_task_runner_,
|
||||
- CrossThreadUnretained(result_buffer_data), file_offset, read_size));
|
||||
+ CrossThreadBindOnce(&DoRead, WrapCrossThreadPersistent(this),
|
||||
+ WrapCrossThreadPersistent(resolver),
|
||||
+ CrossThreadUnretained(file_state_.get()),
|
||||
+ resolver_task_runner_, std::move(result_buffer_data),
|
||||
+ file_offset, read_size));
|
||||
return resolver->Promise();
|
||||
}
|
||||
|
||||
@@ -344,35 +348,28 @@ ScriptPromise NativeIOFile::write(ScriptState* script_state,
|
||||
|
||||
io_pending_ = true;
|
||||
|
||||
- DOMArrayBufferView* result_buffer =
|
||||
- TransferToNewArrayBufferView(script_state->GetIsolate(), buffer);
|
||||
- if (!result_buffer) {
|
||||
+ std::unique_ptr<NativeIODataBuffer> result_buffer_data =
|
||||
+ NativeIODataBuffer::Create(script_state, buffer);
|
||||
+ if (!result_buffer_data) {
|
||||
exception_state.ThrowTypeError("Could not transfer buffer");
|
||||
return ScriptPromise();
|
||||
}
|
||||
+ DCHECK(result_buffer_data->IsValid());
|
||||
DCHECK(buffer->IsDetached());
|
||||
|
||||
- char* result_buffer_data = static_cast<char*>(result_buffer->BaseAddress());
|
||||
-
|
||||
auto* resolver = MakeGarbageCollected<ScriptPromiseResolver>(script_state);
|
||||
// The first CrossThreadUnretained() is safe here because the
|
||||
// NativeIOFile::FileState instance is owned by this NativeIOFile, which is
|
||||
// also passed to the task via WrapCrossThreadPersistent. Therefore, the
|
||||
// FileState instance is guaranteed to remain alive during the task's
|
||||
// execution.
|
||||
- //
|
||||
- // The second CrossThreadUnretained() is safe here because result_buffer_data
|
||||
- // is backed by a DOMArrayBufferView that is also passed to the task via
|
||||
- // WrapCrossThreadPersistent. Therefore, the data is guaranteed to remain
|
||||
- // alive during the task's execution.
|
||||
worker_pool::PostTask(
|
||||
FROM_HERE, {base::MayBlock()},
|
||||
- CrossThreadBindOnce(
|
||||
- &DoWrite, WrapCrossThreadPersistent(this),
|
||||
- WrapCrossThreadPersistent(resolver),
|
||||
- WrapCrossThreadPersistent(result_buffer),
|
||||
- CrossThreadUnretained(file_state_.get()), resolver_task_runner_,
|
||||
- CrossThreadUnretained(result_buffer_data), file_offset, write_size));
|
||||
+ CrossThreadBindOnce(&DoWrite, WrapCrossThreadPersistent(this),
|
||||
+ WrapCrossThreadPersistent(resolver),
|
||||
+ CrossThreadUnretained(file_state_.get()),
|
||||
+ resolver_task_runner_, std::move(result_buffer_data),
|
||||
+ file_offset, write_size));
|
||||
return resolver->Promise();
|
||||
}
|
||||
|
||||
@@ -676,22 +673,29 @@ void NativeIOFile::DidSetLengthIpc(
|
||||
void NativeIOFile::DoRead(
|
||||
CrossThreadPersistent<NativeIOFile> native_io_file,
|
||||
CrossThreadPersistent<ScriptPromiseResolver> resolver,
|
||||
- CrossThreadPersistent<DOMArrayBufferView> result_buffer,
|
||||
NativeIOFile::FileState* file_state,
|
||||
scoped_refptr<base::SequencedTaskRunner> resolver_task_runner,
|
||||
- char* result_buffer_data,
|
||||
+ std::unique_ptr<NativeIODataBuffer> result_buffer_data,
|
||||
uint64_t file_offset,
|
||||
int read_size) {
|
||||
DCHECK(!IsMainThread()) << "File I/O should not happen on the main thread";
|
||||
|
||||
+ DCHECK(resolver_task_runner);
|
||||
+ DCHECK(result_buffer_data);
|
||||
+ DCHECK(result_buffer_data->IsValid());
|
||||
+ DCHECK_GE(read_size, 0);
|
||||
+#if DCHECK_IS_ON()
|
||||
+ DCHECK_LE(static_cast<size_t>(read_size), result_buffer_data->DataLength());
|
||||
+#endif // DCHECK_IS_ON()
|
||||
+
|
||||
int read_bytes;
|
||||
base::File::Error read_error;
|
||||
{
|
||||
WTF::MutexLocker mutex_locker(file_state->mutex);
|
||||
DCHECK(file_state->file.IsValid())
|
||||
<< "file I/O operation queued after file closed";
|
||||
- read_bytes =
|
||||
- file_state->file.Read(file_offset, result_buffer_data, read_size);
|
||||
+ read_bytes = file_state->file.Read(file_offset, result_buffer_data->Data(),
|
||||
+ read_size);
|
||||
read_error = (read_bytes < 0) ? file_state->file.GetLastFileError()
|
||||
: base::File::FILE_OK;
|
||||
}
|
||||
@@ -699,15 +703,18 @@ void NativeIOFile::DoRead(
|
||||
PostCrossThreadTask(
|
||||
*resolver_task_runner, FROM_HERE,
|
||||
CrossThreadBindOnce(&NativeIOFile::DidRead, std::move(native_io_file),
|
||||
- std::move(resolver), std::move(result_buffer),
|
||||
+ std::move(resolver), std::move(result_buffer_data),
|
||||
read_bytes, read_error));
|
||||
}
|
||||
|
||||
void NativeIOFile::DidRead(
|
||||
CrossThreadPersistent<ScriptPromiseResolver> resolver,
|
||||
- CrossThreadPersistent<DOMArrayBufferView> result_buffer,
|
||||
+ std::unique_ptr<NativeIODataBuffer> result_buffer_data,
|
||||
int read_bytes,
|
||||
base::File::Error read_error) {
|
||||
+ DCHECK(result_buffer_data);
|
||||
+ DCHECK(result_buffer_data->IsValid());
|
||||
+
|
||||
ScriptState* script_state = resolver->GetScriptState();
|
||||
if (!script_state->ContextIsValid())
|
||||
return;
|
||||
@@ -727,7 +734,7 @@ void NativeIOFile::DidRead(
|
||||
DCHECK_EQ(read_error, base::File::FILE_OK)
|
||||
<< "Error set but positive number of bytes read.";
|
||||
NativeIOReadResult* read_result = MakeGarbageCollected<NativeIOReadResult>();
|
||||
- read_result->setBuffer(NotShared<DOMArrayBufferView>(result_buffer));
|
||||
+ read_result->setBuffer(result_buffer_data->Take());
|
||||
read_result->setReadBytes(read_bytes);
|
||||
resolver->Resolve(read_result);
|
||||
}
|
||||
@@ -736,13 +743,19 @@ void NativeIOFile::DidRead(
|
||||
void NativeIOFile::DoWrite(
|
||||
CrossThreadPersistent<NativeIOFile> native_io_file,
|
||||
CrossThreadPersistent<ScriptPromiseResolver> resolver,
|
||||
- CrossThreadPersistent<DOMArrayBufferView> result_buffer,
|
||||
NativeIOFile::FileState* file_state,
|
||||
scoped_refptr<base::SequencedTaskRunner> resolver_task_runner,
|
||||
- const char* result_buffer_data,
|
||||
+ std::unique_ptr<NativeIODataBuffer> result_buffer_data,
|
||||
uint64_t file_offset,
|
||||
int write_size) {
|
||||
DCHECK(!IsMainThread()) << "File I/O should not happen on the main thread";
|
||||
+ DCHECK(resolver_task_runner);
|
||||
+ DCHECK(result_buffer_data);
|
||||
+ DCHECK(result_buffer_data->IsValid());
|
||||
+ DCHECK_GE(write_size, 0);
|
||||
+#if DCHECK_IS_ON()
|
||||
+ DCHECK_LE(static_cast<size_t>(write_size), result_buffer_data->DataLength());
|
||||
+#endif // DCHECK_IS_ON()
|
||||
|
||||
int written_bytes;
|
||||
int64_t actual_file_length_on_failure = 0;
|
||||
@@ -751,8 +764,8 @@ void NativeIOFile::DoWrite(
|
||||
WTF::MutexLocker mutex_locker(file_state->mutex);
|
||||
DCHECK(file_state->file.IsValid())
|
||||
<< "file I/O operation queued after file closed";
|
||||
- written_bytes =
|
||||
- file_state->file.Write(file_offset, result_buffer_data, write_size);
|
||||
+ written_bytes = file_state->file.Write(
|
||||
+ file_offset, result_buffer_data->Data(), write_size);
|
||||
write_error = (written_bytes < 0) ? file_state->file.GetLastFileError()
|
||||
: base::File::FILE_OK;
|
||||
if (written_bytes < write_size || write_error != base::File::FILE_OK) {
|
||||
@@ -767,18 +780,21 @@ void NativeIOFile::DoWrite(
|
||||
PostCrossThreadTask(
|
||||
*resolver_task_runner, FROM_HERE,
|
||||
CrossThreadBindOnce(&NativeIOFile::DidWrite, std::move(native_io_file),
|
||||
- std::move(resolver), std::move(result_buffer),
|
||||
+ std::move(resolver), std::move(result_buffer_data),
|
||||
written_bytes, write_error, write_size,
|
||||
actual_file_length_on_failure));
|
||||
}
|
||||
|
||||
void NativeIOFile::DidWrite(
|
||||
CrossThreadPersistent<ScriptPromiseResolver> resolver,
|
||||
- CrossThreadPersistent<DOMArrayBufferView> result_buffer,
|
||||
+ std::unique_ptr<NativeIODataBuffer> result_buffer_data,
|
||||
int written_bytes,
|
||||
base::File::Error write_error,
|
||||
int write_size,
|
||||
int64_t actual_file_length_on_failure) {
|
||||
+ DCHECK(result_buffer_data);
|
||||
+ DCHECK(result_buffer_data->IsValid());
|
||||
+
|
||||
ScriptState* script_state = resolver->GetScriptState();
|
||||
if (!script_state->ContextIsValid())
|
||||
return;
|
||||
@@ -821,7 +837,7 @@ void NativeIOFile::DidWrite(
|
||||
DCHECK_EQ(write_error, base::File::FILE_OK);
|
||||
NativeIOWriteResult* write_result =
|
||||
MakeGarbageCollected<NativeIOWriteResult>();
|
||||
- write_result->setBuffer(NotShared<DOMArrayBufferView>(result_buffer));
|
||||
+ write_result->setBuffer(result_buffer_data->Take());
|
||||
write_result->setWrittenBytes(written_bytes);
|
||||
resolver->Resolve(write_result);
|
||||
}
|
||||
diff --git a/third_party/blink/renderer/modules/native_io/native_io_file.h b/third_party/blink/renderer/modules/native_io/native_io_file.h
|
||||
index 2e41efeefbcf9805ec2b2ed70d018c717c5c75d1..8ae49ebc2d36d547d152d4e56192e30f8cacd641 100644
|
||||
--- a/third_party/blink/renderer/modules/native_io/native_io_file.h
|
||||
+++ b/third_party/blink/renderer/modules/native_io/native_io_file.h
|
||||
@@ -16,6 +16,7 @@
|
||||
#include "third_party/blink/renderer/core/typed_arrays/array_buffer_view_helpers.h"
|
||||
#include "third_party/blink/renderer/core/typed_arrays/dom_array_buffer_view.h"
|
||||
#include "third_party/blink/renderer/modules/native_io/native_io_capacity_tracker.h"
|
||||
+#include "third_party/blink/renderer/modules/native_io/native_io_file_utils.h"
|
||||
#include "third_party/blink/renderer/platform/bindings/script_wrappable.h"
|
||||
#include "third_party/blink/renderer/platform/heap/handle.h"
|
||||
#include "third_party/blink/renderer/platform/heap/persistent.h"
|
||||
@@ -127,15 +128,14 @@ class NativeIOFile final : public ScriptWrappable {
|
||||
// Performs the file I/O part of read(), off the main thread.
|
||||
static void DoRead(CrossThreadPersistent<NativeIOFile> native_io_file,
|
||||
CrossThreadPersistent<ScriptPromiseResolver> resolver,
|
||||
- CrossThreadPersistent<DOMArrayBufferView> result_buffer,
|
||||
NativeIOFile::FileState* file_state,
|
||||
scoped_refptr<base::SequencedTaskRunner> file_task_runner,
|
||||
- char* result_buffer_data,
|
||||
+ std::unique_ptr<NativeIODataBuffer> result_buffer_data,
|
||||
uint64_t file_offset,
|
||||
int read_size);
|
||||
// Performs the post file I/O part of read(), on the main thread.
|
||||
void DidRead(CrossThreadPersistent<ScriptPromiseResolver> resolver,
|
||||
- CrossThreadPersistent<DOMArrayBufferView> result_buffer,
|
||||
+ std::unique_ptr<NativeIODataBuffer> result_buffer_data,
|
||||
int read_bytes,
|
||||
base::File::Error read_error);
|
||||
|
||||
@@ -143,10 +143,9 @@ class NativeIOFile final : public ScriptWrappable {
|
||||
static void DoWrite(
|
||||
CrossThreadPersistent<NativeIOFile> native_io_file,
|
||||
CrossThreadPersistent<ScriptPromiseResolver> resolver,
|
||||
- CrossThreadPersistent<DOMArrayBufferView> result_buffer,
|
||||
NativeIOFile::FileState* file_state,
|
||||
scoped_refptr<base::SequencedTaskRunner> resolver_task_runner,
|
||||
- const char* result_buffer_data,
|
||||
+ std::unique_ptr<NativeIODataBuffer> result_buffer_data,
|
||||
uint64_t file_offset,
|
||||
int write_size);
|
||||
// Performs the post file I/O part of write(), on the main thread.
|
||||
@@ -154,7 +153,7 @@ class NativeIOFile final : public ScriptWrappable {
|
||||
// `actual_file_length_on_failure` is negative if the I/O operation was
|
||||
// unsuccessful and the correct length of the file could not be determined.
|
||||
void DidWrite(CrossThreadPersistent<ScriptPromiseResolver> resolver,
|
||||
- CrossThreadPersistent<DOMArrayBufferView> result_buffer,
|
||||
+ std::unique_ptr<NativeIODataBuffer> result_buffer_data,
|
||||
int written_bytes,
|
||||
base::File::Error write_error,
|
||||
int write_size,
|
||||
diff --git a/third_party/blink/renderer/modules/native_io/native_io_file_utils.cc b/third_party/blink/renderer/modules/native_io/native_io_file_utils.cc
|
||||
index c50a0a94d111d9ea4eb1eac8a7da920936e0d1a3..3e98a12059374d41b22c8d5c706c31e81581aeae 100644
|
||||
--- a/third_party/blink/renderer/modules/native_io/native_io_file_utils.cc
|
||||
+++ b/third_party/blink/renderer/modules/native_io/native_io_file_utils.cc
|
||||
@@ -3,9 +3,16 @@
|
||||
// found in the LICENSE file.
|
||||
|
||||
#include "third_party/blink/renderer/modules/native_io/native_io_file_utils.h"
|
||||
+
|
||||
#include "base/numerics/safe_conversions.h"
|
||||
+#include "base/sequence_checker.h"
|
||||
+#include "base/types/pass_key.h"
|
||||
+#include "third_party/blink/renderer/core/typed_arrays/dom_array_buffer.h"
|
||||
+#include "third_party/blink/renderer/core/typed_arrays/dom_array_buffer_view.h"
|
||||
#include "third_party/blink/renderer/core/typed_arrays/dom_data_view.h"
|
||||
#include "third_party/blink/renderer/core/typed_arrays/dom_typed_array.h"
|
||||
+#include "third_party/blink/renderer/platform/bindings/script_state.h"
|
||||
+#include "v8/include/v8.h"
|
||||
|
||||
namespace blink {
|
||||
|
||||
@@ -72,4 +79,140 @@ DOMArrayBufferView* TransferToNewArrayBufferView(
|
||||
return target;
|
||||
}
|
||||
|
||||
+// static
|
||||
+std::unique_ptr<NativeIODataBuffer> NativeIODataBuffer::Create(
|
||||
+ ScriptState* script_state,
|
||||
+ NotShared<DOMArrayBufferView> source) {
|
||||
+ DCHECK(script_state);
|
||||
+ DCHECK(source);
|
||||
+
|
||||
+ DOMArrayBufferView::ViewType type = source->GetType();
|
||||
+ size_t offset = source->byteOffset();
|
||||
+ size_t byte_length = source->byteLength();
|
||||
+ size_t length = byte_length / source->TypeSize();
|
||||
+
|
||||
+ // Explicitly fail if the source buffer is not detachable. On its own,
|
||||
+ // Transfer() copies non-detachable input buffers.
|
||||
+ DOMArrayBuffer* buffer = source->buffer();
|
||||
+ v8::Isolate* isolate = script_state->GetIsolate();
|
||||
+ if (!buffer->IsDetachable(isolate))
|
||||
+ return nullptr;
|
||||
+
|
||||
+ ArrayBufferContents contents;
|
||||
+ if (!buffer->Transfer(isolate, contents))
|
||||
+ return nullptr;
|
||||
+ DCHECK(source->IsDetached());
|
||||
+
|
||||
+ return std::make_unique<NativeIODataBuffer>(
|
||||
+ std::move(contents), type, offset,
|
||||
+#if DCHECK_IS_ON()
|
||||
+ byte_length,
|
||||
+#endif // DCHECK_IS_ON()
|
||||
+ length, base::PassKey<NativeIODataBuffer>());
|
||||
+}
|
||||
+
|
||||
+NativeIODataBuffer::NativeIODataBuffer(ArrayBufferContents contents,
|
||||
+ DOMArrayBufferView::ViewType type,
|
||||
+ size_t offset,
|
||||
+#if DCHECK_IS_ON()
|
||||
+ size_t byte_length,
|
||||
+#endif // DCHECK_IS_ON()
|
||||
+ size_t length,
|
||||
+ base::PassKey<NativeIODataBuffer>)
|
||||
+ : contents_(std::move(contents)),
|
||||
+ type_(type),
|
||||
+ offset_(offset),
|
||||
+#if DCHECK_IS_ON()
|
||||
+ byte_length_(byte_length),
|
||||
+#endif // DCHECK_IS_ON()
|
||||
+ length_(length) {
|
||||
+ DCHECK(IsValid());
|
||||
+ DCHECK(!contents_.IsShared());
|
||||
+
|
||||
+ // DataLength() returns 0 when called on an invalid ArrayBufferContents
|
||||
+ // (backing an empty array). This works as expected.
|
||||
+ DCHECK_LE(offset, contents_.DataLength());
|
||||
+#if DCHECK_IS_ON()
|
||||
+ DCHECK_LE(length, byte_length);
|
||||
+ DCHECK_LE(byte_length, contents_.DataLength() - offset);
|
||||
+#endif // DCHECK_IS_ON()
|
||||
+}
|
||||
+
|
||||
+NativeIODataBuffer::~NativeIODataBuffer() {
|
||||
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
|
||||
+}
|
||||
+
|
||||
+bool NativeIODataBuffer::IsValid() const {
|
||||
+ // The ArrayBufferContents is not shared when this instance is constructed. It
|
||||
+ // should not become shared while the instance is valid, because no other code
|
||||
+ // can gain access and make it shared.
|
||||
+ //
|
||||
+ // ArrayBufferContents::IsShared() returns false for invalid instances, which
|
||||
+ // works out well for this check.
|
||||
+ DCHECK(!contents_.IsShared());
|
||||
+
|
||||
+ // Transferring the data out of an empty ArrayBuffer yields an invalid
|
||||
+ // ArrayBufferContents.
|
||||
+ return length_ == 0 || contents_.IsValid();
|
||||
+}
|
||||
+
|
||||
+NotShared<DOMArrayBufferView> NativeIODataBuffer::Take() {
|
||||
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
|
||||
+ DCHECK(IsValid());
|
||||
+
|
||||
+ DOMArrayBuffer* array_buffer = DOMArrayBuffer::Create(std::move(contents_));
|
||||
+
|
||||
+ DOMArrayBufferView* view = nullptr;
|
||||
+ switch (type_) {
|
||||
+ case DOMArrayBufferView::kTypeInt8:
|
||||
+ view = DOMInt8Array::Create(array_buffer, offset_, length_);
|
||||
+ break;
|
||||
+
|
||||
+ case DOMArrayBufferView::kTypeUint8:
|
||||
+ view = DOMUint8Array::Create(array_buffer, offset_, length_);
|
||||
+ break;
|
||||
+
|
||||
+ case DOMArrayBufferView::kTypeUint8Clamped:
|
||||
+ view = DOMUint8ClampedArray::Create(array_buffer, offset_, length_);
|
||||
+ break;
|
||||
+
|
||||
+ case DOMArrayBufferView::kTypeInt16:
|
||||
+ view = DOMInt16Array::Create(array_buffer, offset_, length_);
|
||||
+ break;
|
||||
+
|
||||
+ case DOMArrayBufferView::kTypeUint16:
|
||||
+ view = DOMUint16Array::Create(array_buffer, offset_, length_);
|
||||
+ break;
|
||||
+
|
||||
+ case DOMArrayBufferView::kTypeInt32:
|
||||
+ view = DOMInt32Array::Create(array_buffer, offset_, length_);
|
||||
+ break;
|
||||
+
|
||||
+ case DOMArrayBufferView::kTypeUint32:
|
||||
+ view = DOMUint32Array::Create(array_buffer, offset_, length_);
|
||||
+ break;
|
||||
+
|
||||
+ case DOMArrayBufferView::kTypeFloat32:
|
||||
+ view = DOMFloat32Array::Create(array_buffer, offset_, length_);
|
||||
+ break;
|
||||
+
|
||||
+ case DOMArrayBufferView::kTypeFloat64:
|
||||
+ view = DOMFloat64Array::Create(array_buffer, offset_, length_);
|
||||
+ break;
|
||||
+
|
||||
+ case DOMArrayBufferView::kTypeBigInt64:
|
||||
+ view = DOMBigInt64Array::Create(array_buffer, offset_, length_);
|
||||
+ break;
|
||||
+
|
||||
+ case DOMArrayBufferView::kTypeBigUint64:
|
||||
+ view = DOMBigUint64Array::Create(array_buffer, offset_, length_);
|
||||
+ break;
|
||||
+
|
||||
+ case DOMArrayBufferView::kTypeDataView:
|
||||
+ view = DOMDataView::Create(array_buffer, offset_, length_);
|
||||
+ break;
|
||||
+ }
|
||||
+ return NotShared<DOMArrayBufferView>(view);
|
||||
+}
|
||||
+
|
||||
} // namespace blink
|
||||
diff --git a/third_party/blink/renderer/modules/native_io/native_io_file_utils.h b/third_party/blink/renderer/modules/native_io/native_io_file_utils.h
|
||||
index 355a67a8125ea11158dfe435a71c1c01b1ece361..a500d38bcdf8340e7c747cbde949db8f980ea272 100644
|
||||
--- a/third_party/blink/renderer/modules/native_io/native_io_file_utils.h
|
||||
+++ b/third_party/blink/renderer/modules/native_io/native_io_file_utils.h
|
||||
@@ -5,11 +5,19 @@
|
||||
#ifndef THIRD_PARTY_BLINK_RENDERER_MODULES_NATIVE_IO_NATIVE_IO_FILE_UTILS_H_
|
||||
#define THIRD_PARTY_BLINK_RENDERER_MODULES_NATIVE_IO_NATIVE_IO_FILE_UTILS_H_
|
||||
|
||||
+#include <cstddef>
|
||||
+#include <memory>
|
||||
+
|
||||
+#include "base/sequence_checker.h"
|
||||
+#include "base/types/pass_key.h"
|
||||
+#include "third_party/blink/renderer/core/typed_arrays/array_buffer/array_buffer_contents.h"
|
||||
#include "third_party/blink/renderer/core/typed_arrays/array_buffer_view_helpers.h"
|
||||
#include "third_party/blink/renderer/core/typed_arrays/dom_array_buffer_view.h"
|
||||
|
||||
namespace blink {
|
||||
|
||||
+class ScriptState;
|
||||
+
|
||||
// Extracts the read/write operation size from the buffer size.
|
||||
int NativeIOOperationSize(const DOMArrayBufferView& buffer);
|
||||
|
||||
@@ -20,6 +28,121 @@ DOMArrayBufferView* TransferToNewArrayBufferView(
|
||||
v8::Isolate* isolate,
|
||||
NotShared<DOMArrayBufferView> source);
|
||||
|
||||
+// Provides cross-thread access to the buffer backing a DOMArrayBufferView.
|
||||
+//
|
||||
+// This class is necessary because DOMArrayBufferView is garbage-collected,
|
||||
+// which entails that each DOMArrayBufferView instance can only be safely
|
||||
+// accessed on the thread where it was created. Note that CrossThreadPersistent
|
||||
+// can be used to keep a DOMArrayBufferView alive across threads, but the
|
||||
+// instance cannot be safely accessed on a different thread. See the comments on
|
||||
+// cppgc::subtle::CrossThreadPersistent for details.
|
||||
+//
|
||||
+// An instance takes over a DOMArrayBufferView's backing buffer at construction.
|
||||
+// The instance exposes the backing buffer via the Data() and DataLength()
|
||||
+// methods. At some point, the backing buffer is turned back into a
|
||||
+// DOMArrayBufferView via the Take() method. Once Take() is called, the instance
|
||||
+// is invalid, and Data() / DataLength() must not be called anymore.
|
||||
+//
|
||||
+// An instance should be owned by a single sequence at a time. Changing the
|
||||
+// owning sequence should be accomplished by PostTask-ing an owning pointer to
|
||||
+// the instance.
|
||||
+//
|
||||
+// Each instance must be destroyed on the same sequence where it was created.
|
||||
+// Take() must be called on the same sequence where the instance was created.
|
||||
+class NativeIODataBuffer {
|
||||
+ public:
|
||||
+ // Detaches the buffer backing `source`.
|
||||
+ //
|
||||
+ // Returns nullptr if detaching failed.
|
||||
+ static std::unique_ptr<NativeIODataBuffer> Create(
|
||||
+ ScriptState* script_state,
|
||||
+ NotShared<DOMArrayBufferView> source);
|
||||
+
|
||||
+ // Exposed for std::make_unique. Instances should be obtained from Create().
|
||||
+ NativeIODataBuffer(ArrayBufferContents contents,
|
||||
+ DOMArrayBufferView::ViewType type,
|
||||
+ size_t offset,
|
||||
+#if DCHECK_IS_ON()
|
||||
+ size_t byte_length,
|
||||
+#endif // DCHECK_IS_ON()
|
||||
+ size_t length,
|
||||
+ base::PassKey<NativeIODataBuffer>);
|
||||
+
|
||||
+ NativeIODataBuffer(const NativeIODataBuffer&) = delete;
|
||||
+ NativeIODataBuffer& operator=(const NativeIODataBuffer&) = delete;
|
||||
+
|
||||
+ ~NativeIODataBuffer();
|
||||
+
|
||||
+ // Re-creates the DOMArrayBufferView.
|
||||
+ //
|
||||
+ // Must only be called while this instance is onwed by the same sequence where
|
||||
+ // Create() was called. Must only be called if IsValid() is true.
|
||||
+ // After the call, IsValid() will return false.
|
||||
+ NotShared<DOMArrayBufferView> Take();
|
||||
+
|
||||
+ // Exposed for DCHECKs.
|
||||
+ //
|
||||
+ // Can be called while this instance is owned by any sequence.
|
||||
+ bool IsValid() const;
|
||||
+
|
||||
+ // Returns a raw pointer to the DOMArrayBufferView's view.
|
||||
+ //
|
||||
+ // The return type was chosen so that the raw pointer can be conveniently
|
||||
+ // passed to base::File methods.
|
||||
+ //
|
||||
+ // Can be called while this instance is owned by any sequence. Must only be
|
||||
+ // called if IsValid() is true.
|
||||
+ char* Data() {
|
||||
+ DCHECK(IsValid());
|
||||
+
|
||||
+ // An invalid ArrayBufferContents (backing an empty array) returns nullptr
|
||||
+ // when Data() is called. However, in that case, the offset must be zero.
|
||||
+ DCHECK(contents_.Data() || contents_.DataLength() == 0);
|
||||
+ DCHECK(contents_.Data() || offset_ == 0);
|
||||
+
|
||||
+ // According to the DCHECKs above, this branch isn't strictly needed. The
|
||||
+ // return statement below the branch will never do pointer arithmetic on
|
||||
+ // nullptr, because `offset_` is guaranteed to be zero when
|
||||
+ // the ArrayBufferContents is not valid but this instance is.
|
||||
+ char* data = static_cast<char*>(contents_.Data());
|
||||
+ if (!data) {
|
||||
+ DCHECK_EQ(offset_, 0u);
|
||||
+ return data;
|
||||
+ }
|
||||
+
|
||||
+ return data + offset_;
|
||||
+ }
|
||||
+
|
||||
+#if DCHECK_IS_ON()
|
||||
+ // Returns the size of the DOMArrayBufferView's view, in bytes.
|
||||
+ //
|
||||
+ // Exposed for DCHECKs around base::File calls.
|
||||
+ //
|
||||
+ // Can be called while this instance is owned by any sequence. Must only be
|
||||
+ // called if IsValid() is true.
|
||||
+ size_t DataLength() const {
|
||||
+ DCHECK(IsValid());
|
||||
+ return byte_length_;
|
||||
+ }
|
||||
+#endif // DCHECK_IS_ON()
|
||||
+
|
||||
+ private:
|
||||
+ SEQUENCE_CHECKER(sequence_checker_);
|
||||
+
|
||||
+ // May not be valid, as reported by ArrayBufferContents::IsValid().
|
||||
+ //
|
||||
+ // If valid, guaranteed not to be shared, as reported by
|
||||
+ // ArrayBufferContents::IsShared().
|
||||
+ ArrayBufferContents contents_;
|
||||
+
|
||||
+ DOMArrayBufferView::ViewType type_;
|
||||
+ const size_t offset_;
|
||||
+#if DCHECK_IS_ON()
|
||||
+ const size_t byte_length_;
|
||||
+#endif // DCHECK_IS_ON()
|
||||
+ const size_t length_;
|
||||
+};
|
||||
+
|
||||
} // namespace blink
|
||||
|
||||
#endif // THIRD_PARTY_BLINK_RENDERER_MODULES_NATIVE_IO_NATIVE_IO_FILE_UTILS_H_
|
||||
41
patches/chromium/cherry-pick-be50c60b4225.patch
Normal file
41
patches/chromium/cherry-pick-be50c60b4225.patch
Normal file
@@ -0,0 +1,41 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Ken Rockot <rockot@google.com>
|
||||
Date: Wed, 2 Feb 2022 05:45:44 +0000
|
||||
Subject: Viz: Fix UAF on context loss
|
||||
|
||||
(cherry picked from commit 98d246cabe677e1d8287e4d42ce02825417be9e2)
|
||||
|
||||
Fixed: 1250655
|
||||
Change-Id: I2898316635d370fa36b94e0ae2564ed357745b2c
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3413372
|
||||
Auto-Submit: Ken Rockot <rockot@google.com>
|
||||
Reviewed-by: Kyle Charbonneau <kylechar@chromium.org>
|
||||
Commit-Queue: Kyle Charbonneau <kylechar@chromium.org>
|
||||
Cr-Original-Commit-Position: refs/heads/main@{#963012}
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3430523
|
||||
Bot-Commit: Rubber Stamper <rubber-stamper@appspot.gserviceaccount.com>
|
||||
Commit-Queue: Ken Rockot <rockot@google.com>
|
||||
Cr-Commit-Position: refs/branch-heads/4758@{#1050}
|
||||
Cr-Branched-From: 4a2cf4baf90326df19c3ee70ff987960d59a386e-refs/heads/main@{#950365}
|
||||
|
||||
diff --git a/services/viz/public/cpp/gpu/context_provider_command_buffer.cc b/services/viz/public/cpp/gpu/context_provider_command_buffer.cc
|
||||
index a31c10c610000415b5a88a0824eea63b45a435cc..1b323f142d934afea0215dea190efaa197cec554 100644
|
||||
--- a/services/viz/public/cpp/gpu/context_provider_command_buffer.cc
|
||||
+++ b/services/viz/public/cpp/gpu/context_provider_command_buffer.cc
|
||||
@@ -478,9 +478,13 @@ const gpu::GpuFeatureInfo& ContextProviderCommandBuffer::GetGpuFeatureInfo()
|
||||
void ContextProviderCommandBuffer::OnLostContext() {
|
||||
CheckValidThreadOrLockAcquired();
|
||||
|
||||
- // Ensure |this| isn't destroyed in the middle of OnLostContext() if observers
|
||||
- // drop all references to it.
|
||||
- scoped_refptr<ContextProviderCommandBuffer> ref(this);
|
||||
+ // Observers may drop the last persistent references to `this`, but there may
|
||||
+ // be weak references in use further up the stack. This task is posted to
|
||||
+ // ensure that destruction is deferred until it's safe.
|
||||
+ base::SequencedTaskRunnerHandle::Get()->PostTask(
|
||||
+ FROM_HERE,
|
||||
+ base::BindOnce([](scoped_refptr<ContextProviderCommandBuffer>) {},
|
||||
+ base::WrapRefCounted(this)));
|
||||
|
||||
for (auto& observer : observers_)
|
||||
observer.OnContextLost();
|
||||
183
patches/chromium/cherry-pick-c5571653d932.patch
Normal file
183
patches/chromium/cherry-pick-c5571653d932.patch
Normal file
@@ -0,0 +1,183 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Jarryd <jarrydg@chromium.org>
|
||||
Date: Wed, 29 Dec 2021 19:49:22 +0000
|
||||
Subject: Quota: Use Threadsafe Pressure Callback.
|
||||
|
||||
Fixes UAF by removing use of raw ptr to StorageNotificationService.
|
||||
Instead, the service's interface exposes a method to create a
|
||||
thread-safe callback to pass to the quota manager instead.
|
||||
|
||||
This change also changes the parameter type for the call chain from
|
||||
url::Origin to blink::StorageKey to match the type Quota is keyed on.
|
||||
|
||||
Bug:1275020
|
||||
|
||||
(cherry picked from commit e304c0373f9cc4a65d39d7094e4897627e83390e)
|
||||
|
||||
Change-Id: Icc696d22fa41324e7a6c056599db635bb5de6291
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3347939
|
||||
Reviewed-by: Joshua Bell <jsbell@chromium.org>
|
||||
Reviewed-by: Nasko Oskov <nasko@chromium.org>
|
||||
Commit-Queue: Jarryd Goodman <jarrydg@chromium.org>
|
||||
Cr-Original-Commit-Position: refs/heads/main@{#953375}
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3360203
|
||||
Bot-Commit: Rubber Stamper <rubber-stamper@appspot.gserviceaccount.com>
|
||||
Owners-Override: Krishna Govind <govind@chromium.org>
|
||||
Commit-Queue: Krishna Govind <govind@chromium.org>
|
||||
Cr-Commit-Position: refs/branch-heads/4664@{#1352}
|
||||
Cr-Branched-From: 24dc4ee75e01a29d390d43c9c264372a169273a7-refs/heads/main@{#929512}
|
||||
|
||||
diff --git a/chrome/browser/storage/storage_notification_service_impl.cc b/chrome/browser/storage/storage_notification_service_impl.cc
|
||||
index f8b38745827b25e46bfd1b4225bb3c55f2836d02..ceeafe0ad40e69574ccf885e4230ce042ecbaaaa 100644
|
||||
--- a/chrome/browser/storage/storage_notification_service_impl.cc
|
||||
+++ b/chrome/browser/storage/storage_notification_service_impl.cc
|
||||
@@ -10,6 +10,8 @@
|
||||
#include "build/build_config.h"
|
||||
#include "chrome/browser/profiles/profile.h"
|
||||
#include "chrome/common/chrome_switches.h"
|
||||
+#include "content/public/browser/browser_task_traits.h"
|
||||
+#include "content/public/browser/browser_thread.h"
|
||||
|
||||
#if !defined(OS_ANDROID)
|
||||
#include "chrome/browser/ui/storage_pressure_bubble.h"
|
||||
@@ -36,8 +38,26 @@ const base::TimeDelta GetThrottlingInterval() {
|
||||
|
||||
} // namespace
|
||||
|
||||
+StoragePressureNotificationCallback
|
||||
+StorageNotificationServiceImpl::CreateThreadSafePressureNotificationCallback() {
|
||||
+ DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
|
||||
+ auto thread_unsafe_callback = base::BindRepeating(
|
||||
+ &StorageNotificationServiceImpl::MaybeShowStoragePressureNotification,
|
||||
+ weak_ptr_factory_.GetWeakPtr());
|
||||
+ return base::BindRepeating(
|
||||
+ [](StoragePressureNotificationCallback cb, blink::StorageKey key) {
|
||||
+ content::GetUIThreadTaskRunner({})->PostTask(
|
||||
+ FROM_HERE,
|
||||
+ base::BindOnce([](StoragePressureNotificationCallback callback,
|
||||
+ blink::StorageKey key) { callback.Run(key); },
|
||||
+ std::move(cb), key));
|
||||
+ },
|
||||
+ std::move(thread_unsafe_callback));
|
||||
+}
|
||||
+
|
||||
void StorageNotificationServiceImpl::MaybeShowStoragePressureNotification(
|
||||
- const url::Origin origin) {
|
||||
+ const blink::StorageKey storage_key) {
|
||||
+ auto origin = storage_key.origin();
|
||||
if (!disk_pressure_notification_last_sent_at_.is_null() &&
|
||||
base::TimeTicks::Now() - disk_pressure_notification_last_sent_at_ <
|
||||
GetThrottlingInterval()) {
|
||||
diff --git a/chrome/browser/storage/storage_notification_service_impl.h b/chrome/browser/storage/storage_notification_service_impl.h
|
||||
index 497a3063c835a37fe9141052263cf70c863235fa..44fe169b82ced5e328060f191d608aaa57d3af71 100644
|
||||
--- a/chrome/browser/storage/storage_notification_service_impl.h
|
||||
+++ b/chrome/browser/storage/storage_notification_service_impl.h
|
||||
@@ -5,10 +5,12 @@
|
||||
#ifndef CHROME_BROWSER_STORAGE_STORAGE_NOTIFICATION_SERVICE_IMPL_H_
|
||||
#define CHROME_BROWSER_STORAGE_STORAGE_NOTIFICATION_SERVICE_IMPL_H_
|
||||
|
||||
+#include "base/memory/weak_ptr.h"
|
||||
#include "base/time/time.h"
|
||||
#include "chrome/browser/profiles/profile.h"
|
||||
#include "components/keyed_service/core/keyed_service.h"
|
||||
#include "content/public/browser/storage_notification_service.h"
|
||||
+#include "third_party/blink/public/common/storage_key/storage_key.h"
|
||||
|
||||
class StorageNotificationServiceImpl
|
||||
: public content::StorageNotificationService,
|
||||
@@ -16,13 +18,20 @@ class StorageNotificationServiceImpl
|
||||
public:
|
||||
StorageNotificationServiceImpl();
|
||||
~StorageNotificationServiceImpl() override;
|
||||
- void MaybeShowStoragePressureNotification(const url::Origin) override;
|
||||
+ // Called from the UI thread, this method returns a callback that can passed
|
||||
+ // to any thread, and proxies calls to
|
||||
+ // `MaybeShowStoragePressureNotification()` back to the UI thread. It wraps a
|
||||
+ // weak pointer to `this`.
|
||||
+ StoragePressureNotificationCallback
|
||||
+ CreateThreadSafePressureNotificationCallback() override;
|
||||
+ void MaybeShowStoragePressureNotification(const blink::StorageKey) override;
|
||||
base::TimeTicks GetLastSentAtForTesting() {
|
||||
return disk_pressure_notification_last_sent_at_;
|
||||
}
|
||||
|
||||
private:
|
||||
base::TimeTicks disk_pressure_notification_last_sent_at_;
|
||||
+ base::WeakPtrFactory<StorageNotificationServiceImpl> weak_ptr_factory_{this};
|
||||
};
|
||||
|
||||
#endif // CHROME_BROWSER_STORAGE_STORAGE_NOTIFICATION_SERVICE_IMPL_H_
|
||||
diff --git a/content/browser/storage_partition_impl.cc b/content/browser/storage_partition_impl.cc
|
||||
index ba015b7c6439dfb4a0b9e21f580dbb2581483dcb..ae284e031a6e051bda49258d54a2e62332773c70 100644
|
||||
--- a/content/browser/storage_partition_impl.cc
|
||||
+++ b/content/browser/storage_partition_impl.cc
|
||||
@@ -1205,23 +1205,14 @@ void StoragePartitionImpl::Initialize(
|
||||
StorageNotificationService* storage_notification_service =
|
||||
browser_context_->GetStorageNotificationService();
|
||||
if (storage_notification_service) {
|
||||
- // base::Unretained is safe to use because the BrowserContext is guaranteed
|
||||
- // to outlive QuotaManager. This is because BrowserContext outlives this
|
||||
- // StoragePartitionImpl, which destroys the QuotaManager on teardown.
|
||||
- base::RepeatingCallback<void(const blink::StorageKey)>
|
||||
- send_notification_function = base::BindRepeating(
|
||||
- [](StorageNotificationService* service,
|
||||
- const blink::StorageKey storage_key) {
|
||||
- GetUIThreadTaskRunner({})->PostTask(
|
||||
- FROM_HERE,
|
||||
- base::BindOnce(&StorageNotificationService::
|
||||
- MaybeShowStoragePressureNotification,
|
||||
- base::Unretained(service),
|
||||
- std::move(storage_key.origin())));
|
||||
- },
|
||||
- base::Unretained(storage_notification_service));
|
||||
-
|
||||
- quota_manager_->SetStoragePressureCallback(send_notification_function);
|
||||
+ // The weak ptr associated with the pressure notification callback will be
|
||||
+ // created and evaluated by a task runner on the UI thread, as confirmed by
|
||||
+ // the DCHECK's above, ensuring that the task runner does not attempt to run
|
||||
+ // the callback in the case that the storage notification service is already
|
||||
+ // destructed.
|
||||
+ quota_manager_->SetStoragePressureCallback(
|
||||
+ storage_notification_service
|
||||
+ ->CreateThreadSafePressureNotificationCallback());
|
||||
}
|
||||
|
||||
// Each consumer is responsible for registering its QuotaClient during
|
||||
diff --git a/content/public/browser/storage_notification_service.h b/content/public/browser/storage_notification_service.h
|
||||
index 3eec5ef29051008041695bcf7ebbf63787f5bd89..e72adada318f1cb998e2a9e7468a6f2e54742760 100644
|
||||
--- a/content/public/browser/storage_notification_service.h
|
||||
+++ b/content/public/browser/storage_notification_service.h
|
||||
@@ -8,6 +8,15 @@
|
||||
#include "base/bind.h"
|
||||
#include "url/origin.h"
|
||||
|
||||
+namespace blink {
|
||||
+class StorageKey;
|
||||
+}
|
||||
+
|
||||
+namespace {
|
||||
+using StoragePressureNotificationCallback =
|
||||
+ base::RepeatingCallback<void(const blink::StorageKey)>;
|
||||
+}
|
||||
+
|
||||
namespace content {
|
||||
|
||||
// This interface is used to create a connection between the storage layer and
|
||||
@@ -19,12 +28,15 @@ class StorageNotificationService {
|
||||
StorageNotificationService() = default;
|
||||
~StorageNotificationService() = default;
|
||||
|
||||
- // This pure virtual function should be implemented in the embedder layer
|
||||
+ // These pure virtual functions should be implemented in the embedder layer
|
||||
// where calls to UI and notification code can be implemented. This closure
|
||||
// is passed to QuotaManager in StoragePartitionImpl, where it is called
|
||||
// when QuotaManager determines appropriate to alert the user that the device
|
||||
// is in a state of storage pressure.
|
||||
- virtual void MaybeShowStoragePressureNotification(const url::Origin) = 0;
|
||||
+ virtual void MaybeShowStoragePressureNotification(
|
||||
+ const blink::StorageKey) = 0;
|
||||
+ virtual StoragePressureNotificationCallback
|
||||
+ CreateThreadSafePressureNotificationCallback() = 0;
|
||||
|
||||
private:
|
||||
DISALLOW_COPY_AND_ASSIGN(StorageNotificationService);
|
||||
62
patches/chromium/cherry-pick-da11d71a0227.patch
Normal file
62
patches/chromium/cherry-pick-da11d71a0227.patch
Normal file
@@ -0,0 +1,62 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Ken Rockot <rockot@google.com>
|
||||
Date: Fri, 10 Dec 2021 01:03:53 +0000
|
||||
Subject: mojo/ipc: Drop messages targeting invalid task runner
|
||||
|
||||
If the endpoint's task runner does not match the current task runner (or
|
||||
an equivalent main-thread task runner for the ChannelProxy) when a
|
||||
executing a message dispatch task for that endpoint, this ignores the
|
||||
message instead of dispatching it on the wrong sequence.
|
||||
|
||||
(cherry picked from commit 0747c9405e1098c0bbbc5593183696eafb45b72c)
|
||||
|
||||
Fixed: 1263457
|
||||
Change-Id: I4f6ba22de3ff8cf3994b748e1ffd0f0aabb17b70
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3318601
|
||||
Reviewed-by: Daniel Cheng <dcheng@chromium.org>
|
||||
Commit-Queue: Ken Rockot <rockot@google.com>
|
||||
Cr-Original-Commit-Position: refs/heads/main@{#949140}
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3328403
|
||||
Auto-Submit: Ken Rockot <rockot@google.com>
|
||||
Commit-Queue: Daniel Cheng <dcheng@chromium.org>
|
||||
Cr-Commit-Position: refs/branch-heads/4664@{#1269}
|
||||
Cr-Branched-From: 24dc4ee75e01a29d390d43c9c264372a169273a7-refs/heads/main@{#929512}
|
||||
|
||||
diff --git a/ipc/ipc_mojo_bootstrap.cc b/ipc/ipc_mojo_bootstrap.cc
|
||||
index 18b4dc9be5bf54e6f5443d53739bc06ba3f98767..07e522337090494e278395ac4e7ead73c472ef72 100644
|
||||
--- a/ipc/ipc_mojo_bootstrap.cc
|
||||
+++ b/ipc/ipc_mojo_bootstrap.cc
|
||||
@@ -966,11 +966,14 @@ class ChannelAssociatedGroupController
|
||||
if (!client)
|
||||
return;
|
||||
|
||||
+ if (!endpoint->task_runner()->RunsTasksInCurrentSequence() &&
|
||||
+ !proxy_task_runner_->RunsTasksInCurrentSequence()) {
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
// Using client->interface_name() is safe here because this is a static
|
||||
// string defined for each mojo interface.
|
||||
TRACE_EVENT0("mojom", client->interface_name());
|
||||
- DCHECK(endpoint->task_runner()->RunsTasksInCurrentSequence() ||
|
||||
- proxy_task_runner_->RunsTasksInCurrentSequence());
|
||||
|
||||
// Sync messages should never make their way to this method.
|
||||
DCHECK(!message.has_flag(mojo::Message::kFlagIsSync));
|
||||
@@ -1000,11 +1003,14 @@ class ChannelAssociatedGroupController
|
||||
if (!client)
|
||||
return;
|
||||
|
||||
+ if (!endpoint->task_runner()->RunsTasksInCurrentSequence() &&
|
||||
+ !proxy_task_runner_->RunsTasksInCurrentSequence()) {
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
// Using client->interface_name() is safe here because this is a static
|
||||
// string defined for each mojo interface.
|
||||
TRACE_EVENT0("mojom", client->interface_name());
|
||||
- DCHECK(endpoint->task_runner()->RunsTasksInCurrentSequence() ||
|
||||
- proxy_task_runner_->RunsTasksInCurrentSequence());
|
||||
MessageWrapper message_wrapper = endpoint->PopSyncMessage(message_id);
|
||||
|
||||
// The message must have already been dequeued by the endpoint waking up
|
||||
308
patches/chromium/cherry-pick-dbde8795233a.patch
Normal file
308
patches/chromium/cherry-pick-dbde8795233a.patch
Normal file
@@ -0,0 +1,308 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Patrick Meenan <pmeenan@chromium.org>
|
||||
Date: Fri, 3 Dec 2021 18:15:17 +0000
|
||||
Subject: Prevent opaque range request responses from entering the preload
|
||||
cache
|
||||
|
||||
ResourceLoader cancels range request responses that were not initiated
|
||||
with range request headers causing them to error out and be cleared from
|
||||
the preload cache. Other responses (200, 416, error, etc) complete
|
||||
successfully and would otherwise enter the preload cache, making them
|
||||
observable.
|
||||
|
||||
This prevents opaque range responses of any kind from persisting in the
|
||||
preload cache (which would not naturally have any anyway).
|
||||
|
||||
(cherry picked from commit a5f630e5f94da28a926d60da7dde194acd8697f0)
|
||||
|
||||
Bug: 1270990
|
||||
Change-Id: Ife9922fe0b88e39722f3664ddd091a1516892157
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3294001
|
||||
Reviewed-by: Ben Kelly <wanderview@chromium.org>
|
||||
Reviewed-by: Yoav Weiss <yoavweiss@chromium.org>
|
||||
Commit-Queue: Patrick Meenan <pmeenan@chromium.org>
|
||||
Cr-Original-Commit-Position: refs/heads/main@{#946055}
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3313416
|
||||
Auto-Submit: Patrick Meenan <pmeenan@chromium.org>
|
||||
Bot-Commit: Rubber Stamper <rubber-stamper@appspot.gserviceaccount.com>
|
||||
Cr-Commit-Position: refs/branch-heads/4664@{#1222}
|
||||
Cr-Branched-From: 24dc4ee75e01a29d390d43c9c264372a169273a7-refs/heads/main@{#929512}
|
||||
|
||||
diff --git a/third_party/blink/renderer/platform/loader/fetch/resource_fetcher.cc b/third_party/blink/renderer/platform/loader/fetch/resource_fetcher.cc
|
||||
index c7ae11a459051edab1fcaf1cc5feb5d9f19ff52d..29d34ddc211350a834ca94466cce1dcfea0db1ff 100644
|
||||
--- a/third_party/blink/renderer/platform/loader/fetch/resource_fetcher.cc
|
||||
+++ b/third_party/blink/renderer/platform/loader/fetch/resource_fetcher.cc
|
||||
@@ -1866,6 +1866,19 @@ void ResourceFetcher::HandleLoaderFinish(Resource* resource,
|
||||
}
|
||||
|
||||
resource->VirtualTimePauser().UnpauseVirtualTime();
|
||||
+
|
||||
+ // A response should not serve partial content if it was not requested via a
|
||||
+ // Range header: https://fetch.spec.whatwg.org/#main-fetch so keep it out
|
||||
+ // of the preload cache in case of a non-206 response (which generates an
|
||||
+ // error).
|
||||
+ if (resource->GetResponse().GetType() ==
|
||||
+ network::mojom::FetchResponseType::kOpaque &&
|
||||
+ resource->GetResponse().HasRangeRequested() &&
|
||||
+ !resource->GetResourceRequest().HttpHeaderFields().Contains(
|
||||
+ net::HttpRequestHeaders::kRange)) {
|
||||
+ RemovePreload(resource);
|
||||
+ }
|
||||
+
|
||||
if (type == kDidFinishLoading) {
|
||||
resource->Finish(response_end, freezable_task_runner_.get());
|
||||
|
||||
diff --git a/third_party/blink/web_tests/external/wpt/fetch/range/resources/partial-text.py b/third_party/blink/web_tests/external/wpt/fetch/range/resources/partial-text.py
|
||||
new file mode 100644
|
||||
index 0000000000000000000000000000000000000000..a0058551d52d45b3c16882014be740d75e51ddd1
|
||||
--- /dev/null
|
||||
+++ b/third_party/blink/web_tests/external/wpt/fetch/range/resources/partial-text.py
|
||||
@@ -0,0 +1,47 @@
|
||||
+"""
|
||||
+This generates a partial response for a 100-byte text file.
|
||||
+"""
|
||||
+import re
|
||||
+
|
||||
+from wptserve.utils import isomorphic_decode
|
||||
+
|
||||
+def main(request, response):
|
||||
+ total_length = int(request.GET.first(b'length', b'100'))
|
||||
+ partial_code = int(request.GET.first(b'partial', b'206'))
|
||||
+ range_header = request.headers.get(b'Range', b'')
|
||||
+
|
||||
+ # Send a 200 if there is no range request
|
||||
+ if not range_header:
|
||||
+ to_send = ''.zfill(total_length)
|
||||
+ response.headers.set(b"Content-Type", b"text/plain")
|
||||
+ response.headers.set(b"Cache-Control", b"no-cache")
|
||||
+ response.headers.set(b"Content-Length", total_length)
|
||||
+ response.content = to_send
|
||||
+ return
|
||||
+
|
||||
+ # Simple range parsing, requires specifically "bytes=xxx-xxxx"
|
||||
+ range_header_match = re.search(r'^bytes=(\d*)-(\d*)$', isomorphic_decode(range_header))
|
||||
+ start, end = range_header_match.groups()
|
||||
+ start = int(start)
|
||||
+ end = int(end) if end else total_length
|
||||
+ length = end - start
|
||||
+
|
||||
+ # Error the request if the range goes beyond the length
|
||||
+ if length <= 0 or end > total_length:
|
||||
+ response.set_error(416, u"Range Not Satisfiable")
|
||||
+ response.write()
|
||||
+ return
|
||||
+
|
||||
+ # Generate a partial response of the requested length
|
||||
+ to_send = ''.zfill(length)
|
||||
+ response.headers.set(b"Content-Type", b"text/plain")
|
||||
+ response.headers.set(b"Accept-Ranges", b"bytes")
|
||||
+ response.headers.set(b"Cache-Control", b"no-cache")
|
||||
+ response.status = partial_code
|
||||
+
|
||||
+ content_range = b"bytes %d-%d/%d" % (start, end, total_length)
|
||||
+
|
||||
+ response.headers.set(b"Content-Range", content_range)
|
||||
+ response.headers.set(b"Content-Length", length)
|
||||
+
|
||||
+ response.content = to_send
|
||||
diff --git a/third_party/blink/web_tests/external/wpt/fetch/range/resources/range-sw.js b/third_party/blink/web_tests/external/wpt/fetch/range/resources/range-sw.js
|
||||
index 3680c0c471d3d5f36c4aba4cc58dcd52c38a08df..b47823f03b4ef3749e622fbf7dd3b515a216b5be 100644
|
||||
--- a/third_party/blink/web_tests/external/wpt/fetch/range/resources/range-sw.js
|
||||
+++ b/third_party/blink/web_tests/external/wpt/fetch/range/resources/range-sw.js
|
||||
@@ -12,7 +12,7 @@ async function broadcast(msg) {
|
||||
}
|
||||
}
|
||||
|
||||
-addEventListener('fetch', event => {
|
||||
+addEventListener('fetch', async event => {
|
||||
/** @type Request */
|
||||
const request = event.request;
|
||||
const url = new URL(request.url);
|
||||
@@ -34,6 +34,11 @@ addEventListener('fetch', event => {
|
||||
case 'broadcast-accept-encoding':
|
||||
broadcastAcceptEncoding(event);
|
||||
return;
|
||||
+ case 'record-media-range-request':
|
||||
+ return recordMediaRangeRequest(event);
|
||||
+ case 'use-media-range-request':
|
||||
+ useMediaRangeRequest(event);
|
||||
+ return;
|
||||
}
|
||||
});
|
||||
|
||||
@@ -157,3 +162,57 @@ function broadcastAcceptEncoding(event) {
|
||||
// Just send back any response, it isn't important for the test.
|
||||
event.respondWith(new Response(''));
|
||||
}
|
||||
+
|
||||
+let rangeResponse = {};
|
||||
+
|
||||
+async function recordMediaRangeRequest(event) {
|
||||
+ /** @type Request */
|
||||
+ const request = event.request;
|
||||
+ const url = new URL(request.url);
|
||||
+ const urlParams = new URLSearchParams(url.search);
|
||||
+ const size = urlParams.get("size");
|
||||
+ const id = urlParams.get('id');
|
||||
+ const key = 'size' + size;
|
||||
+
|
||||
+ if (key in rangeResponse) {
|
||||
+ // Don't re-fetch ranges we already have.
|
||||
+ const clonedResponse = rangeResponse[key].clone();
|
||||
+ event.respondWith(clonedResponse);
|
||||
+ } else if (event.request.headers.get("range") === "bytes=0-") {
|
||||
+ // Generate a bogus 206 response to trigger subsequent range requests
|
||||
+ // of the desired size.
|
||||
+ const length = urlParams.get("length") + 100;
|
||||
+ const body = "A".repeat(Number(size));
|
||||
+ event.respondWith(new Response(body, {status: 206, headers: {
|
||||
+ "Content-Type": "audio/mp4",
|
||||
+ "Content-Range": `bytes 0-1/${length}`
|
||||
+ }}));
|
||||
+ } else if (event.request.headers.get("range") === `bytes=${Number(size)}-`) {
|
||||
+ // Pass through actual range requests which will attempt to fetch up to the
|
||||
+ // length in the original response which is bigger than the actual resource
|
||||
+ // to make sure 206 and 416 responses are treated the same.
|
||||
+ rangeResponse[key] = await fetch(event.request);
|
||||
+
|
||||
+ // Let the client know we have the range response for the given ID
|
||||
+ broadcast({id});
|
||||
+ } else {
|
||||
+ event.respondWith(Promise.reject(Error("Invalid Request")));
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+function useMediaRangeRequest(event) {
|
||||
+ /** @type Request */
|
||||
+ const request = event.request;
|
||||
+ const url = new URL(request.url);
|
||||
+ const urlParams = new URLSearchParams(url.search);
|
||||
+ const size = urlParams.get("size");
|
||||
+ const key = 'size' + size;
|
||||
+
|
||||
+ // Send a clone of the range response to preload.
|
||||
+ if (key in rangeResponse) {
|
||||
+ const clonedResponse = rangeResponse[key].clone();
|
||||
+ event.respondWith(clonedResponse);
|
||||
+ } else {
|
||||
+ event.respondWith(Promise.reject(Error("Invalid Request")));
|
||||
+ }
|
||||
+}
|
||||
diff --git a/third_party/blink/web_tests/external/wpt/fetch/range/resources/utils.js b/third_party/blink/web_tests/external/wpt/fetch/range/resources/utils.js
|
||||
index 16ed737f63e8eee26a306c70acb0589e424db35d..ad2853b33dc7474293df1423dd8af459571736b9 100644
|
||||
--- a/third_party/blink/web_tests/external/wpt/fetch/range/resources/utils.js
|
||||
+++ b/third_party/blink/web_tests/external/wpt/fetch/range/resources/utils.js
|
||||
@@ -8,6 +8,18 @@ function loadScript(url, { doc = document }={}) {
|
||||
})
|
||||
}
|
||||
|
||||
+function preloadImage(url, { doc = document }={}) {
|
||||
+ return new Promise((resolve, reject) => {
|
||||
+ const preload = doc.createElement('link');
|
||||
+ preload.rel = 'preload';
|
||||
+ preload.as = 'image';
|
||||
+ preload.onload = () => resolve();
|
||||
+ preload.onerror = () => resolve();
|
||||
+ preload.href = url;
|
||||
+ doc.body.appendChild(preload);
|
||||
+ })
|
||||
+}
|
||||
+
|
||||
/**
|
||||
*
|
||||
* @param {Document} document
|
||||
diff --git a/third_party/blink/web_tests/external/wpt/fetch/range/sw.https.window-expected.txt b/third_party/blink/web_tests/external/wpt/fetch/range/sw.https.window-expected.txt
|
||||
index 134b0a7abd817599921d4fb430e8247a2cb40f82..a9577f01727678cd7a76bcc65e132fd6fcb230ac 100644
|
||||
--- a/third_party/blink/web_tests/external/wpt/fetch/range/sw.https.window-expected.txt
|
||||
+++ b/third_party/blink/web_tests/external/wpt/fetch/range/sw.https.window-expected.txt
|
||||
@@ -4,6 +4,7 @@ PASS Defer range header passthrough tests to service worker
|
||||
PASS Ranged response not allowed following no-cors ranged request
|
||||
PASS Non-opaque ranged response executed
|
||||
FAIL Accept-Encoding should not appear in a service worker assert_equals: Accept-Encoding should not be set for media expected (object) null but got (string) "identity;q=1, *;q=0"
|
||||
+PASS Opaque range preload successes and failures should be indistinguishable
|
||||
PASS Range headers correctly preserved
|
||||
PASS Range headers correctly removed
|
||||
PASS Headers correctly filtered
|
||||
diff --git a/third_party/blink/web_tests/external/wpt/fetch/range/sw.https.window.js b/third_party/blink/web_tests/external/wpt/fetch/range/sw.https.window.js
|
||||
index 76f80e9416c615417ad2a9fbaa565641ff5b8a12..42e4ac6d75afdcbb2ad1e9d3e4069d9cbfd10dbd 100644
|
||||
--- a/third_party/blink/web_tests/external/wpt/fetch/range/sw.https.window.js
|
||||
+++ b/third_party/blink/web_tests/external/wpt/fetch/range/sw.https.window.js
|
||||
@@ -149,3 +149,78 @@ promise_test(async t => {
|
||||
|
||||
assert_equals((await audioBroadcast).acceptEncoding, null, "Accept-Encoding should not be set for media");
|
||||
}, `Accept-Encoding should not appear in a service worker`);
|
||||
+
|
||||
+promise_test(async t => {
|
||||
+ const scope = BASE_SCOPE + Math.random();
|
||||
+ await setupRegistration(t, scope);
|
||||
+ const iframe = await with_iframe(scope);
|
||||
+ const w = iframe.contentWindow;
|
||||
+ const length = 100;
|
||||
+ const count = 3;
|
||||
+ const counts = {};
|
||||
+
|
||||
+ // test a single range request size
|
||||
+ async function testSizedRange(size, partialResponseCode) {
|
||||
+ const rangeId = Math.random() + '';
|
||||
+ const rangeBroadcast = awaitMessage(w.navigator.serviceWorker, rangeId);
|
||||
+
|
||||
+ // Create a bogus audo element to trick the browser into sending
|
||||
+ // cross-origin range requests that can be manipulated by the service worker.
|
||||
+ const sound_url = new URL('partial-text.py', w.location);
|
||||
+ sound_url.hostname = REMOTE_HOST;
|
||||
+ sound_url.searchParams.set('action', 'record-media-range-request');
|
||||
+ sound_url.searchParams.set('length', length);
|
||||
+ sound_url.searchParams.set('size', size);
|
||||
+ sound_url.searchParams.set('partial', partialResponseCode);
|
||||
+ sound_url.searchParams.set('id', rangeId);
|
||||
+ appendAudio(w.document, sound_url);
|
||||
+
|
||||
+ // wait for the range requests to happen
|
||||
+ await rangeBroadcast;
|
||||
+
|
||||
+ // Create multiple preload requests and count the number of resource timing
|
||||
+ // entries that get created to make sure 206 and 416 range responses are treated
|
||||
+ // the same.
|
||||
+ const url = new URL('partial-text.py', w.location);
|
||||
+ url.searchParams.set('action', 'use-media-range-request');
|
||||
+ url.searchParams.set('size', size);
|
||||
+ counts['size' + size] = 0;
|
||||
+ for (let i = 0; i < count; i++) {
|
||||
+ await preloadImage(url, { doc: w.document });
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ // Test range requests from 1 smaller than the correct size to 1 larger than
|
||||
+ // the correct size to exercise the various permutations using the default 206
|
||||
+ // response code for successful range requests.
|
||||
+ for (let size = length - 1; size <= length + 1; size++) {
|
||||
+ await testSizedRange(size, '206');
|
||||
+ }
|
||||
+
|
||||
+ // Test a successful range request using a 200 response.
|
||||
+ await testSizedRange(length - 2, '200');
|
||||
+
|
||||
+ // Check the resource timing entries and count the reported number of fetches of each type
|
||||
+ const resources = w.performance.getEntriesByType("resource");
|
||||
+ for (const entry of resources) {
|
||||
+ const url = new URL(entry.name);
|
||||
+ if (url.searchParams.has('action') &&
|
||||
+ url.searchParams.get('action') == 'use-media-range-request' &&
|
||||
+ url.searchParams.has('size')) {
|
||||
+ counts['size' + url.searchParams.get('size')]++;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ // Make sure there are a non-zero number of preload requests and they are all the same
|
||||
+ let counts_valid = true;
|
||||
+ const first = 'size' + (length - 2);
|
||||
+ for (let size = length - 2; size <= length + 1; size++) {
|
||||
+ let key = 'size' + size;
|
||||
+ if (!(key in counts) || counts[key] <= 0 || counts[key] != counts[first]) {
|
||||
+ counts_valid = false;
|
||||
+ break;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ assert_true(counts_valid, `Opaque range request preloads were different for error and success`);
|
||||
+}, `Opaque range preload successes and failures should be indistinguishable`);
|
||||
72
patches/chromium/cherry-pick-e3805f29fed7.patch
Normal file
72
patches/chromium/cherry-pick-e3805f29fed7.patch
Normal file
@@ -0,0 +1,72 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Kevin Ellis <kevers@google.com>
|
||||
Date: Fri, 11 Feb 2022 01:36:04 +0000
|
||||
Subject: Code health cleanup: replacing animations.
|
||||
|
||||
Animation::Update performed a synchronous processing of the finish
|
||||
microtask to ensure that finished events where dispatched ahead of
|
||||
replace events. This step does not align with the spec. Instead we
|
||||
should be queuing the replace event. Microtasks will be processed in
|
||||
the correct order.
|
||||
|
||||
Spec link: https://www.w3.org/TR/web-animations-1/#timelines
|
||||
|
||||
Change-Id: Ibe7753e792fb6cf905bbe6815a080a8cc51c2803
|
||||
|
||||
(cherry picked from commit d4fb69ff0fe343fe8a171014785a88eabfe2b1c2)
|
||||
|
||||
Bug: 1290858
|
||||
Change-Id: Ibe7753e792fb6cf905bbe6815a080a8cc51c2803
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3414765
|
||||
Reviewed-by: Mustaq Ahmed <mustaq@chromium.org>
|
||||
Commit-Queue: Kevin Ellis <kevers@chromium.org>
|
||||
Cr-Original-Commit-Position: refs/heads/main@{#964223}
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3453925
|
||||
Reviewed-by: Adrian Taylor <adetaylor@google.com>
|
||||
Commit-Queue: Krishna Govind <govind@chromium.org>
|
||||
Cr-Commit-Position: refs/branch-heads/4758@{#1134}
|
||||
Cr-Branched-From: 4a2cf4baf90326df19c3ee70ff987960d59a386e-refs/heads/main@{#950365}
|
||||
|
||||
diff --git a/third_party/blink/renderer/core/animation/animation.cc b/third_party/blink/renderer/core/animation/animation.cc
|
||||
index f11b55b34cdaa57f4ccfbe44c40c4d03d485210d..acb59f356d43e368e6e5cfe2f649ae60483ab978 100644
|
||||
--- a/third_party/blink/renderer/core/animation/animation.cc
|
||||
+++ b/third_party/blink/renderer/core/animation/animation.cc
|
||||
@@ -2275,10 +2275,6 @@ bool Animation::Update(TimingUpdateReason reason) {
|
||||
|
||||
if (reason == kTimingUpdateForAnimationFrame) {
|
||||
if (idle || CalculateAnimationPlayState() == kFinished) {
|
||||
- // TODO(crbug.com/1029348): Per spec, we should have a microtask
|
||||
- // checkpoint right after the update cycle. Once this is fixed we should
|
||||
- // no longer need to force a synchronous resolution here.
|
||||
- AsyncFinishMicrotask();
|
||||
finished_ = true;
|
||||
}
|
||||
}
|
||||
diff --git a/third_party/blink/renderer/core/animation/document_animations.cc b/third_party/blink/renderer/core/animation/document_animations.cc
|
||||
index 6e5b4f970387929b6b940b18e14e997d2baa339c..f8090e41f8b0aa2e138738f5a3ba7c434d85535b 100644
|
||||
--- a/third_party/blink/renderer/core/animation/document_animations.cc
|
||||
+++ b/third_party/blink/renderer/core/animation/document_animations.cc
|
||||
@@ -45,6 +45,7 @@
|
||||
#include "third_party/blink/renderer/core/page/page.h"
|
||||
#include "third_party/blink/renderer/core/page/page_animator.h"
|
||||
#include "third_party/blink/renderer/platform/bindings/microtask.h"
|
||||
+#include "third_party/blink/renderer/platform/heap/persistent.h"
|
||||
|
||||
namespace blink {
|
||||
|
||||
@@ -286,10 +287,13 @@ void DocumentAnimations::RemoveReplacedAnimations(
|
||||
|
||||
// The list of animations for removal is constructed in reverse composite
|
||||
// ordering for efficiency. Flip the ordering to ensure that events are
|
||||
- // dispatched in composite order.
|
||||
+ // dispatched in composite order. Queue as a microtask so that the finished
|
||||
+ // event is dispatched ahead of the remove event.
|
||||
for (auto it = animations_to_remove.rbegin();
|
||||
it != animations_to_remove.rend(); it++) {
|
||||
- (*it)->RemoveReplacedAnimation();
|
||||
+ Animation* animation = *it;
|
||||
+ Microtask::EnqueueMicrotask(WTF::Bind(&Animation::RemoveReplacedAnimation,
|
||||
+ WrapWeakPersistent(animation)));
|
||||
}
|
||||
}
|
||||
|
||||
55
patches/chromium/cherry-pick-ebc188ad769e.patch
Normal file
55
patches/chromium/cherry-pick-ebc188ad769e.patch
Normal file
@@ -0,0 +1,55 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Ken Rockot <rockot@google.com>
|
||||
Date: Sat, 5 Feb 2022 13:41:47 +0000
|
||||
Subject: Fix potential handle reuse in Mojo
|
||||
|
||||
(cherry picked from commit 76eca90d0e9c09bfbb8c3e8999f36e6da6842a39)
|
||||
|
||||
(cherry picked from commit e1432faf5e101b3a516037a26818c03c759d2fdd)
|
||||
|
||||
Fixed: 1270333
|
||||
Change-Id: Ife188d519092e4e634355fd53d97c85009771b76
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3414063
|
||||
Auto-Submit: Ken Rockot <rockot@google.com>
|
||||
Commit-Queue: Daniel Cheng <dcheng@chromium.org>
|
||||
Cr-Original-Original-Commit-Position: refs/heads/main@{#962946}
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3421488
|
||||
Commit-Queue: Ken Rockot <rockot@google.com>
|
||||
Commit-Queue: Rubber Stamper <rubber-stamper@appspot.gserviceaccount.com>
|
||||
Bot-Commit: Rubber Stamper <rubber-stamper@appspot.gserviceaccount.com>
|
||||
Cr-Original-Commit-Position: refs/branch-heads/4844@{#87}
|
||||
Cr-Original-Branched-From: 007241ce2e6c8e5a7b306cc36c730cd07cd38825-refs/heads/main@{#961656}
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3427544
|
||||
Reviewed-by: Jana Grill <janagrill@google.com>
|
||||
Owners-Override: Jana Grill <janagrill@google.com>
|
||||
Commit-Queue: Zakhar Voit <voit@google.com>
|
||||
Cr-Commit-Position: refs/branch-heads/4664@{#1455}
|
||||
Cr-Branched-From: 24dc4ee75e01a29d390d43c9c264372a169273a7-refs/heads/main@{#929512}
|
||||
|
||||
diff --git a/mojo/core/handle_table.cc b/mojo/core/handle_table.cc
|
||||
index 9426281d73f050598bd5f88b38aac39c4b994ff3..a044f1c8e38f0affe269a87a10c70b49fe6d353c 100644
|
||||
--- a/mojo/core/handle_table.cc
|
||||
+++ b/mojo/core/handle_table.cc
|
||||
@@ -65,13 +65,19 @@ bool HandleTable::AddDispatchersFromTransit(
|
||||
const std::vector<Dispatcher::DispatcherInTransit>& dispatchers,
|
||||
MojoHandle* handles) {
|
||||
// Oops, we're out of handles.
|
||||
- if (next_available_handle_ == MOJO_HANDLE_INVALID)
|
||||
+ if (next_available_handle_ == MOJO_HANDLE_INVALID) {
|
||||
return false;
|
||||
+ }
|
||||
+
|
||||
+ // MOJO_HANDLE_INVALID is zero.
|
||||
+ DCHECK_GE(next_available_handle_, 1u);
|
||||
|
||||
- DCHECK_LE(dispatchers.size(), std::numeric_limits<uint32_t>::max());
|
||||
// If this insertion would cause handle overflow, we're out of handles.
|
||||
- if (next_available_handle_ + dispatchers.size() < next_available_handle_)
|
||||
+ const uint32_t num_handles_available =
|
||||
+ std::numeric_limits<uint32_t>::max() - next_available_handle_ + 1;
|
||||
+ if (num_handles_available < dispatchers.size()) {
|
||||
return false;
|
||||
+ }
|
||||
|
||||
for (size_t i = 0; i < dispatchers.size(); ++i) {
|
||||
MojoHandle handle = MOJO_HANDLE_INVALID;
|
||||
245
patches/chromium/cherry-pick-f0a63e1f361f.patch
Normal file
245
patches/chromium/cherry-pick-f0a63e1f361f.patch
Normal file
@@ -0,0 +1,245 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Adam Rice <ricea@chromium.org>
|
||||
Date: Sat, 6 Nov 2021 18:52:26 +0000
|
||||
Subject: Return undefined from UnderlyingSinkBase "type" getter
|
||||
|
||||
The "type" attribute of an object passed to the WritableStream
|
||||
constructor is supposed to return undefined. Add a getter to
|
||||
UnderlyingSinkBase to ensure it always does.
|
||||
|
||||
Add tests to verify that "type" is not inherited from
|
||||
Object.prototype.type.
|
||||
|
||||
Move some methods out-of-line into a new underlying_sink_base.cc file.
|
||||
|
||||
Make WritableStreamDefaultController::From() more robust.
|
||||
|
||||
BUG=1262791
|
||||
|
||||
(cherry picked from commit 26564c88bc9e034cc512afd857cf303193647b9a)
|
||||
|
||||
Change-Id: I97f43233eef0e473fb1a22a3ea8afafe92e16266
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3252171
|
||||
Reviewed-by: Yutaka Hirano <yhirano@chromium.org>
|
||||
Commit-Queue: Adam Rice <ricea@chromium.org>
|
||||
Cr-Original-Commit-Position: refs/heads/main@{#936834}
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3266824
|
||||
Bot-Commit: Rubber Stamper <rubber-stamper@appspot.gserviceaccount.com>
|
||||
Cr-Commit-Position: refs/branch-heads/4664@{#806}
|
||||
Cr-Branched-From: 24dc4ee75e01a29d390d43c9c264372a169273a7-refs/heads/main@{#929512}
|
||||
|
||||
diff --git a/third_party/blink/renderer/core/streams/build.gni b/third_party/blink/renderer/core/streams/build.gni
|
||||
index 57a106353bd6720bc7da88f96dce66e4332aea2a..744d47f1a1e9352cc4df56ce89635b3d6f8b5425 100644
|
||||
--- a/third_party/blink/renderer/core/streams/build.gni
|
||||
+++ b/third_party/blink/renderer/core/streams/build.gni
|
||||
@@ -43,6 +43,7 @@ blink_core_sources_streams = [
|
||||
"transform_stream_default_controller.cc",
|
||||
"transform_stream_default_controller.h",
|
||||
"transform_stream_transformer.h",
|
||||
+ "underlying_sink_base.cc",
|
||||
"underlying_sink_base.h",
|
||||
"underlying_source_base.cc",
|
||||
"underlying_source_base.h",
|
||||
diff --git a/third_party/blink/renderer/core/streams/underlying_sink_base.cc b/third_party/blink/renderer/core/streams/underlying_sink_base.cc
|
||||
new file mode 100644
|
||||
index 0000000000000000000000000000000000000000..a10d4f1865fc4e11c90f463b64ff666cce0fba69
|
||||
--- /dev/null
|
||||
+++ b/third_party/blink/renderer/core/streams/underlying_sink_base.cc
|
||||
@@ -0,0 +1,29 @@
|
||||
+// Copyright 2021 The Chromium Authors. All rights reserved.
|
||||
+// Use of this source code is governed by a BSD-style license that can be
|
||||
+// found in the LICENSE file.
|
||||
+
|
||||
+#include "third_party/blink/renderer/core/streams/underlying_sink_base.h"
|
||||
+
|
||||
+#include "third_party/blink/renderer/core/streams/writable_stream_default_controller.h"
|
||||
+#include "v8/include/v8.h"
|
||||
+
|
||||
+namespace blink {
|
||||
+
|
||||
+ScriptPromise UnderlyingSinkBase::start(ScriptState* script_state,
|
||||
+ ScriptValue controller,
|
||||
+ ExceptionState& exception_state) {
|
||||
+ controller_ = WritableStreamDefaultController::From(script_state, controller);
|
||||
+ return start(script_state, controller_, exception_state);
|
||||
+}
|
||||
+
|
||||
+ScriptValue UnderlyingSinkBase::type(ScriptState* script_state) const {
|
||||
+ auto* isolate = script_state->GetIsolate();
|
||||
+ return ScriptValue(isolate, v8::Undefined(isolate));
|
||||
+}
|
||||
+
|
||||
+void UnderlyingSinkBase::Trace(Visitor* visitor) const {
|
||||
+ visitor->Trace(controller_);
|
||||
+ ScriptWrappable::Trace(visitor);
|
||||
+}
|
||||
+
|
||||
+} // namespace blink
|
||||
diff --git a/third_party/blink/renderer/core/streams/underlying_sink_base.h b/third_party/blink/renderer/core/streams/underlying_sink_base.h
|
||||
index 3b07d87f064a26e01c4ee827d78fca005049c90a..07ba729fc3a78cf2102e2d64e527048af8be9c71 100644
|
||||
--- a/third_party/blink/renderer/core/streams/underlying_sink_base.h
|
||||
+++ b/third_party/blink/renderer/core/streams/underlying_sink_base.h
|
||||
@@ -6,16 +6,20 @@
|
||||
#define THIRD_PARTY_BLINK_RENDERER_CORE_STREAMS_UNDERLYING_SINK_BASE_H_
|
||||
|
||||
#include "third_party/blink/renderer/bindings/core/v8/script_promise.h"
|
||||
+#include "third_party/blink/renderer/bindings/core/v8/script_value.h"
|
||||
#include "third_party/blink/renderer/core/core_export.h"
|
||||
-#include "third_party/blink/renderer/core/streams/writable_stream_default_controller.h"
|
||||
#include "third_party/blink/renderer/platform/bindings/script_wrappable.h"
|
||||
#include "third_party/blink/renderer/platform/heap/visitor.h"
|
||||
|
||||
+// Various files depend on us exporting this header.
|
||||
+// TODO(ricea): Clean up the dependencies and remove this include.
|
||||
+#include "third_party/blink/renderer/core/streams/writable_stream_default_controller.h"
|
||||
+
|
||||
namespace blink {
|
||||
|
||||
class ExceptionState;
|
||||
-class ScriptValue;
|
||||
class ScriptState;
|
||||
+class WritableStreamDefaultController;
|
||||
|
||||
class CORE_EXPORT UnderlyingSinkBase : public ScriptWrappable {
|
||||
DEFINE_WRAPPERTYPEINFO();
|
||||
@@ -38,12 +42,8 @@ class CORE_EXPORT UnderlyingSinkBase : public ScriptWrappable {
|
||||
ScriptValue reason,
|
||||
ExceptionState&) = 0;
|
||||
|
||||
- ScriptPromise start(ScriptState* script_state,
|
||||
- ScriptValue controller,
|
||||
- ExceptionState& exception_state) {
|
||||
- controller_ = WritableStreamDefaultController::From(controller);
|
||||
- return start(script_state, controller_, exception_state);
|
||||
- }
|
||||
+ ScriptPromise start(ScriptState*, ScriptValue controller, ExceptionState&);
|
||||
+
|
||||
ScriptPromise write(ScriptState* script_state,
|
||||
ScriptValue chunk,
|
||||
ScriptValue controller,
|
||||
@@ -52,10 +52,11 @@ class CORE_EXPORT UnderlyingSinkBase : public ScriptWrappable {
|
||||
return write(script_state, chunk, controller_, exception_state);
|
||||
}
|
||||
|
||||
- void Trace(Visitor* visitor) const override {
|
||||
- visitor->Trace(controller_);
|
||||
- ScriptWrappable::Trace(visitor);
|
||||
- }
|
||||
+ // Returns a JavaScript "undefined" value. This is required by the
|
||||
+ // WritableStream Create() method.
|
||||
+ ScriptValue type(ScriptState*) const;
|
||||
+
|
||||
+ void Trace(Visitor*) const override;
|
||||
|
||||
protected:
|
||||
WritableStreamDefaultController* Controller() const { return controller_; }
|
||||
diff --git a/third_party/blink/renderer/core/streams/underlying_sink_base.idl b/third_party/blink/renderer/core/streams/underlying_sink_base.idl
|
||||
index 8351141cbc07ed32566a0006f998aab61e8fd6b5..470eb527b11e3dce355d724eaa63ec981b7788e4 100644
|
||||
--- a/third_party/blink/renderer/core/streams/underlying_sink_base.idl
|
||||
+++ b/third_party/blink/renderer/core/streams/underlying_sink_base.idl
|
||||
@@ -14,4 +14,7 @@ interface UnderlyingSinkBase {
|
||||
[CallWith=ScriptState, RaisesException] Promise<void> write(any chunk, any controller);
|
||||
[CallWith=ScriptState, RaisesException] Promise<void> close();
|
||||
[CallWith=ScriptState, RaisesException] Promise<void> abort(any reason);
|
||||
+
|
||||
+ // This only exists to prevent Object.prototype.type being accessed.
|
||||
+ [CallWith=ScriptState] readonly attribute any type;
|
||||
};
|
||||
diff --git a/third_party/blink/renderer/core/streams/writable_stream_default_controller.cc b/third_party/blink/renderer/core/streams/writable_stream_default_controller.cc
|
||||
index 0b22eedcddc87b0ac695389a76ed5e353dd5f92c..bc959b6c33dbba6a367b4d247d56b67698299635 100644
|
||||
--- a/third_party/blink/renderer/core/streams/writable_stream_default_controller.cc
|
||||
+++ b/third_party/blink/renderer/core/streams/writable_stream_default_controller.cc
|
||||
@@ -20,10 +20,14 @@
|
||||
namespace blink {
|
||||
|
||||
WritableStreamDefaultController* WritableStreamDefaultController::From(
|
||||
+ ScriptState* script_state,
|
||||
ScriptValue controller) {
|
||||
- DCHECK(controller.IsObject());
|
||||
- return V8WritableStreamDefaultController::ToImpl(
|
||||
- controller.V8Value().As<v8::Object>());
|
||||
+ CHECK(controller.IsObject());
|
||||
+ auto* controller_impl =
|
||||
+ V8WritableStreamDefaultController::ToImplWithTypeCheck(
|
||||
+ script_state->GetIsolate(), controller.V8Value().As<v8::Object>());
|
||||
+ CHECK(controller_impl);
|
||||
+ return controller_impl;
|
||||
}
|
||||
|
||||
// Only used internally. Not reachable from JavaScript.
|
||||
diff --git a/third_party/blink/renderer/core/streams/writable_stream_default_controller.h b/third_party/blink/renderer/core/streams/writable_stream_default_controller.h
|
||||
index 3351dcd6941360fc9fecaa8c03080da813a5b6a2..8be676421763caa911b8d003c869856675e28713 100644
|
||||
--- a/third_party/blink/renderer/core/streams/writable_stream_default_controller.h
|
||||
+++ b/third_party/blink/renderer/core/streams/writable_stream_default_controller.h
|
||||
@@ -27,7 +27,7 @@ class CORE_EXPORT WritableStreamDefaultController final
|
||||
DEFINE_WRAPPERTYPEINFO();
|
||||
|
||||
public:
|
||||
- static WritableStreamDefaultController* From(ScriptValue);
|
||||
+ static WritableStreamDefaultController* From(ScriptState*, ScriptValue);
|
||||
|
||||
// The JavaScript-exposed constructor throws automatically as no constructor
|
||||
// is specified in the IDL. This constructor is used internally during
|
||||
diff --git a/third_party/blink/web_tests/http/tests/streams/chromium/underlying-sink-base-type-getter.html b/third_party/blink/web_tests/http/tests/streams/chromium/underlying-sink-base-type-getter.html
|
||||
new file mode 100644
|
||||
index 0000000000000000000000000000000000000000..fbbc26b08ea4e310ed99b7a02e1a7952e8f60921
|
||||
--- /dev/null
|
||||
+++ b/third_party/blink/web_tests/http/tests/streams/chromium/underlying-sink-base-type-getter.html
|
||||
@@ -0,0 +1,57 @@
|
||||
+<!DOCTYPE html>
|
||||
+<meta charset="utf-8">
|
||||
+<script src="/resources/testharness.js"></script>
|
||||
+<script src="/resources/testharnessreport.js"></script>
|
||||
+<script>
|
||||
+'use strict';
|
||||
+
|
||||
+test(t => {
|
||||
+ Object.defineProperty(Object.prototype, 'type',
|
||||
+ {
|
||||
+ configurable: true,
|
||||
+ get() {
|
||||
+ throw Error();
|
||||
+ }
|
||||
+ });
|
||||
+ t.add_cleanup(() => {
|
||||
+ delete Object.prototype.type;
|
||||
+ });
|
||||
+ const generator = new MediaStreamTrackGenerator('video');
|
||||
+ // The WritableStream is created lazily, so access it to trigger creation.
|
||||
+ generator.writable.getWriter();
|
||||
+}, 'a throwing getter on Object.prototype.type should not interfere with ' +
|
||||
+ 'native writable stream creation');
|
||||
+
|
||||
+test(t => {
|
||||
+ Object.defineProperty(Object.prototype, 'type',
|
||||
+ {
|
||||
+ configurable: true,
|
||||
+ get() {
|
||||
+ this.start(0x414141);
|
||||
+ }
|
||||
+ });
|
||||
+ t.add_cleanup(() => {
|
||||
+ delete Object.prototype.type;
|
||||
+ });
|
||||
+ const generator = new MediaStreamTrackGenerator('video');
|
||||
+ generator.writable.getWriter();
|
||||
+}, 'a getter that calls start() with a number on Object.prototype.type ' +
|
||||
+ 'should not interfere with native writable stream creation');
|
||||
+
|
||||
+test(t => {
|
||||
+ Object.defineProperty(Object.prototype, 'type',
|
||||
+ {
|
||||
+ configurable: true,
|
||||
+ get() {
|
||||
+ this.start({});
|
||||
+ }
|
||||
+ });
|
||||
+ t.add_cleanup(() => {
|
||||
+ delete Object.prototype.type;
|
||||
+ });
|
||||
+ const generator = new MediaStreamTrackGenerator('video');
|
||||
+ generator.writable.getWriter();
|
||||
+}, 'a getter that calls start() with an object on Object.prototype.type ' +
|
||||
+ 'should not interfere with native writable stream creation');
|
||||
+
|
||||
+</script>
|
||||
195
patches/chromium/cherry-pick-f781748dcb3c.patch
Normal file
195
patches/chromium/cherry-pick-f781748dcb3c.patch
Normal file
@@ -0,0 +1,195 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Ravjit <ravjit@chromium.org>
|
||||
Date: Thu, 16 Sep 2021 12:29:55 +0000
|
||||
Subject: Show the origin of the last redirecting server in external protocol
|
||||
handler dialogs
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
|
||||
External protocol handlers always show the initiating url's origin. This can be misleading if there are server side redirects.
|
||||
Now we will show the origin of the last redirecting server (falling back to the request_initiator if there were no redirects / if the request goes straight to an external protocol).
|
||||
|
||||
Bug: 1197889
|
||||
Change-Id: I3cf7ccf3a8bd79d161364680a1871d1c88bec813
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3113931
|
||||
Commit-Queue: Ravjit Singh Uppal <ravjit@chromium.org>
|
||||
Reviewed-by: Arthur Sonzogni <arthursonzogni@chromium.org>
|
||||
Reviewed-by: Collin Baker <collinbaker@chromium.org>
|
||||
Reviewed-by: Takashi Toyoshima <toyoshim@chromium.org>
|
||||
Reviewed-by: Łukasz Anforowicz <lukasza@chromium.org>
|
||||
Cr-Commit-Position: refs/heads/main@{#922096}
|
||||
|
||||
diff --git a/chrome/browser/ui/views/external_protocol_dialog_browsertest.cc b/chrome/browser/ui/views/external_protocol_dialog_browsertest.cc
|
||||
index 7e953fe89ff8dadf4da9578c0fdc6c3aada11aca..5c7e331ea4fbbcf36ac6463b37884cc9c6ca7e41 100644
|
||||
--- a/chrome/browser/ui/views/external_protocol_dialog_browsertest.cc
|
||||
+++ b/chrome/browser/ui/views/external_protocol_dialog_browsertest.cc
|
||||
@@ -14,11 +14,15 @@
|
||||
#include "chrome/browser/ui/test/test_browser_dialog.h"
|
||||
#include "chrome/browser/ui/views/external_protocol_dialog.h"
|
||||
#include "chrome/test/base/in_process_browser_test.h"
|
||||
+#include "chrome/test/base/ui_test_utils.h"
|
||||
#include "content/public/browser/render_frame_host.h"
|
||||
#include "content/public/browser/render_process_host.h"
|
||||
#include "content/public/browser/render_view_host.h"
|
||||
#include "content/public/browser/web_contents.h"
|
||||
#include "content/public/test/browser_test.h"
|
||||
+#include "net/dns/mock_host_resolver.h"
|
||||
+#include "net/test/embedded_test_server/http_request.h"
|
||||
+#include "net/test/embedded_test_server/http_response.h"
|
||||
#include "ui/views/controls/button/checkbox.h"
|
||||
#include "url/gurl.h"
|
||||
|
||||
@@ -41,6 +45,33 @@ class ExternalProtocolDialogTestApi {
|
||||
|
||||
} // namespace test
|
||||
|
||||
+namespace {
|
||||
+constexpr char kInitiatingOrigin[] = "a.test";
|
||||
+constexpr char kRedirectingOrigin[] = "b.test";
|
||||
+
|
||||
+class FakeDefaultProtocolClientWorker
|
||||
+ : public shell_integration::DefaultProtocolClientWorker {
|
||||
+ public:
|
||||
+ explicit FakeDefaultProtocolClientWorker(const std::string& protocol)
|
||||
+ : DefaultProtocolClientWorker(protocol) {}
|
||||
+ FakeDefaultProtocolClientWorker(const FakeDefaultProtocolClientWorker&) =
|
||||
+ delete;
|
||||
+ FakeDefaultProtocolClientWorker& operator=(
|
||||
+ const FakeDefaultProtocolClientWorker&) = delete;
|
||||
+
|
||||
+ private:
|
||||
+ ~FakeDefaultProtocolClientWorker() override = default;
|
||||
+ shell_integration::DefaultWebClientState CheckIsDefaultImpl() override {
|
||||
+ return shell_integration::DefaultWebClientState::NOT_DEFAULT;
|
||||
+ }
|
||||
+
|
||||
+ void SetAsDefaultImpl(base::OnceClosure on_finished_callback) override {
|
||||
+ base::SequencedTaskRunnerHandle::Get()->PostTask(
|
||||
+ FROM_HERE, std::move(on_finished_callback));
|
||||
+ }
|
||||
+};
|
||||
+} // namespace
|
||||
+
|
||||
class ExternalProtocolDialogBrowserTest
|
||||
: public DialogBrowserTest,
|
||||
public ExternalProtocolHandler::Delegate {
|
||||
@@ -71,11 +102,11 @@ class ExternalProtocolDialogBrowserTest
|
||||
// ExternalProtocolHander::Delegate:
|
||||
scoped_refptr<shell_integration::DefaultProtocolClientWorker>
|
||||
CreateShellWorker(const std::string& protocol) override {
|
||||
- return nullptr;
|
||||
+ return base::MakeRefCounted<FakeDefaultProtocolClientWorker>(protocol);
|
||||
}
|
||||
ExternalProtocolHandler::BlockState GetBlockState(const std::string& scheme,
|
||||
Profile* profile) override {
|
||||
- return ExternalProtocolHandler::DONT_BLOCK;
|
||||
+ return ExternalProtocolHandler::UNKNOWN;
|
||||
}
|
||||
void BlockRequest() override {}
|
||||
void RunExternalProtocolDialog(
|
||||
@@ -83,7 +114,10 @@ class ExternalProtocolDialogBrowserTest
|
||||
content::WebContents* web_contents,
|
||||
ui::PageTransition page_transition,
|
||||
bool has_user_gesture,
|
||||
- const absl::optional<url::Origin>& initiating_origin) override {}
|
||||
+ const absl::optional<url::Origin>& initiating_origin) override {
|
||||
+ url_did_launch_ = true;
|
||||
+ launch_url_ = initiating_origin->host();
|
||||
+ }
|
||||
void LaunchUrlWithoutSecurityCheck(
|
||||
const GURL& url,
|
||||
content::WebContents* web_contents) override {
|
||||
@@ -98,6 +132,12 @@ class ExternalProtocolDialogBrowserTest
|
||||
blocked_state_ = state;
|
||||
}
|
||||
|
||||
+ void SetUpOnMainThread() override {
|
||||
+ DialogBrowserTest::SetUpOnMainThread();
|
||||
+ host_resolver()->AddRule(kInitiatingOrigin, "127.0.0.1");
|
||||
+ host_resolver()->AddRule(kRedirectingOrigin, "127.0.0.1");
|
||||
+ }
|
||||
+
|
||||
base::HistogramTester histogram_tester_;
|
||||
|
||||
protected:
|
||||
@@ -106,6 +146,7 @@ class ExternalProtocolDialogBrowserTest
|
||||
url::Origin blocked_origin_;
|
||||
BlockState blocked_state_ = BlockState::UNKNOWN;
|
||||
bool url_did_launch_ = false;
|
||||
+ std::string launch_url_;
|
||||
|
||||
private:
|
||||
DISALLOW_COPY_AND_ASSIGN(ExternalProtocolDialogBrowserTest);
|
||||
@@ -231,3 +272,21 @@ IN_PROC_BROWSER_TEST_F(ExternalProtocolDialogBrowserTest, TestFocus) {
|
||||
const views::View* focused_view = focus_manager->GetFocusedView();
|
||||
EXPECT_TRUE(focused_view);
|
||||
}
|
||||
+
|
||||
+IN_PROC_BROWSER_TEST_F(ExternalProtocolDialogBrowserTest, OriginNameTest) {
|
||||
+ ASSERT_TRUE(embedded_test_server()->Start());
|
||||
+ content::WebContents* web_contents =
|
||||
+ browser()->tab_strip_model()->GetActiveWebContents();
|
||||
+ EXPECT_TRUE(ui_test_utils::NavigateToURL(
|
||||
+ browser(), embedded_test_server()->GetURL("a.test", "/empty.html")));
|
||||
+ EXPECT_TRUE(content::ExecJs(
|
||||
+ web_contents,
|
||||
+ content::JsReplace("location.href = $1",
|
||||
+ embedded_test_server()->GetURL(
|
||||
+ "b.test", "/server-redirect?ms-calc:"))));
|
||||
+ content::WaitForLoadStop(web_contents);
|
||||
+ EXPECT_TRUE(url_did_launch_);
|
||||
+ // The url should be the url of the last redirecting server and not of the
|
||||
+ // request initiator
|
||||
+ EXPECT_EQ(launch_url_, "b.test");
|
||||
+}
|
||||
diff --git a/content/browser/loader/navigation_url_loader_impl.cc b/content/browser/loader/navigation_url_loader_impl.cc
|
||||
index 42f62ccb3830bf718806f2361d9fb8a4abd53c6a..3d91eadbed7fc9cfd9a70805415eb660b15398d4 100644
|
||||
--- a/content/browser/loader/navigation_url_loader_impl.cc
|
||||
+++ b/content/browser/loader/navigation_url_loader_impl.cc
|
||||
@@ -626,6 +626,13 @@ NavigationURLLoaderImpl::PrepareForNonInterceptedRequest(
|
||||
if (known_schemes_.find(resource_request_->url.scheme()) ==
|
||||
known_schemes_.end()) {
|
||||
mojo::PendingRemote<network::mojom::URLLoaderFactory> loader_factory;
|
||||
+ absl::optional<url::Origin> initiating_origin;
|
||||
+ if (url_chain_.size() > 1) {
|
||||
+ initiating_origin =
|
||||
+ url::Origin::Create(url_chain_[url_chain_.size() - 2]);
|
||||
+ } else {
|
||||
+ initiating_origin = resource_request_->request_initiator;
|
||||
+ }
|
||||
bool handled = GetContentClient()->browser()->HandleExternalProtocol(
|
||||
resource_request_->url, web_contents_getter_,
|
||||
ChildProcessHost::kInvalidUniqueID, frame_tree_node_id_,
|
||||
@@ -633,8 +640,8 @@ NavigationURLLoaderImpl::PrepareForNonInterceptedRequest(
|
||||
resource_request_->resource_type ==
|
||||
static_cast<int>(blink::mojom::ResourceType::kMainFrame),
|
||||
static_cast<ui::PageTransition>(resource_request_->transition_type),
|
||||
- resource_request_->has_user_gesture,
|
||||
- resource_request_->request_initiator, &loader_factory);
|
||||
+ resource_request_->has_user_gesture, initiating_origin,
|
||||
+ &loader_factory);
|
||||
|
||||
if (loader_factory) {
|
||||
factory = base::MakeRefCounted<network::WrapperSharedURLLoaderFactory>(
|
||||
diff --git a/content/public/browser/content_browser_client.h b/content/public/browser/content_browser_client.h
|
||||
index 86b630ca2fa26150d71451a1ffe77552cdd589a9..c8981fea3bf8596797d68a3a164309444bb6e1ec 100644
|
||||
--- a/content/public/browser/content_browser_client.h
|
||||
+++ b/content/public/browser/content_browser_client.h
|
||||
@@ -1758,10 +1758,12 @@ class CONTENT_EXPORT ContentBrowserClient {
|
||||
// Otherwise child_id will be the process id and |navigation_ui_data| will be
|
||||
// nullptr.
|
||||
//
|
||||
- // |initiating_origin| is the origin that initiated the navigation to the
|
||||
- // external protocol, and may be null, e.g. in the case of browser-initiated
|
||||
- // navigations. The initiating origin is intended to help users make security
|
||||
- // decisions about whether to allow an external application to launch.
|
||||
+ // |initiating_origin| is the origin of the last redirecting server (falling
|
||||
+ // back to the request initiator if there were no redirects / if the request
|
||||
+ // goes straight to an external protocol, or null, e.g. in the case of
|
||||
+ // browser-initiated navigations. The initiating origin is intended to help
|
||||
+ // users make security decisions about whether to allow an external
|
||||
+ // application to launch.
|
||||
virtual bool HandleExternalProtocol(
|
||||
const GURL& url,
|
||||
base::RepeatingCallback<WebContents*()> web_contents_getter,
|
||||
@@ -7,7 +7,7 @@ Pending upstream patch, this gives us fuller access to the window.open params
|
||||
so that we will be able to decide whether to cancel it or not.
|
||||
|
||||
diff --git a/chrome/browser/android/document/document_web_contents_delegate.cc b/chrome/browser/android/document/document_web_contents_delegate.cc
|
||||
index 0e90487923c57c0570e73ef0f0e8c5acc2576932..fcdc88233b2277f3b37a2a2b0bdee7d71b721bf8 100644
|
||||
index 0e90487923c57c0570e73ef0f0e8c5acc2576932..20fece7e761c28d8d13f53de5b5b521a73f4f168 100644
|
||||
--- a/chrome/browser/android/document/document_web_contents_delegate.cc
|
||||
+++ b/chrome/browser/android/document/document_web_contents_delegate.cc
|
||||
@@ -46,8 +46,7 @@ bool DocumentWebContentsDelegate::IsWebContentsCreationOverridden(
|
||||
@@ -16,12 +16,12 @@ index 0e90487923c57c0570e73ef0f0e8c5acc2576932..fcdc88233b2277f3b37a2a2b0bdee7d7
|
||||
const GURL& opener_url,
|
||||
- const std::string& frame_name,
|
||||
- const GURL& target_url) {
|
||||
+ const mojom::CreateNewWindowParams& params) {
|
||||
+ const content::mojom::CreateNewWindowParams& params) {
|
||||
NOTREACHED();
|
||||
return true;
|
||||
}
|
||||
diff --git a/chrome/browser/android/document/document_web_contents_delegate.h b/chrome/browser/android/document/document_web_contents_delegate.h
|
||||
index 5b4d70991e19edcdfee731c56251932bf43e535f..fe1977c5e6ce0f5b30e8be529b9efa51785db57f 100644
|
||||
index 5b4d70991e19edcdfee731c56251932bf43e535f..4d996e3821410b2325ef85499f8c307c6e043b2a 100644
|
||||
--- a/chrome/browser/android/document/document_web_contents_delegate.h
|
||||
+++ b/chrome/browser/android/document/document_web_contents_delegate.h
|
||||
@@ -41,8 +41,7 @@ class DocumentWebContentsDelegate
|
||||
@@ -30,12 +30,12 @@ index 5b4d70991e19edcdfee731c56251932bf43e535f..fe1977c5e6ce0f5b30e8be529b9efa51
|
||||
const GURL& opener_url,
|
||||
- const std::string& frame_name,
|
||||
- const GURL& target_url) override;
|
||||
+ const mojom::CreateNewWindowParams& params) override;
|
||||
+ const content::mojom::CreateNewWindowParams& params) override;
|
||||
};
|
||||
|
||||
#endif // CHROME_BROWSER_ANDROID_DOCUMENT_DOCUMENT_WEB_CONTENTS_DELEGATE_H_
|
||||
diff --git a/chrome/browser/media/offscreen_tab.cc b/chrome/browser/media/offscreen_tab.cc
|
||||
index d6295d809381f4f4a86a9948762079232ba6c93c..ad429250984cf367e1194bda67bc56a886f650ae 100644
|
||||
index d6295d809381f4f4a86a9948762079232ba6c93c..c320f1d304a1e327f2454c4cd4302fc6003090e8 100644
|
||||
--- a/chrome/browser/media/offscreen_tab.cc
|
||||
+++ b/chrome/browser/media/offscreen_tab.cc
|
||||
@@ -283,8 +283,7 @@ bool OffscreenTab::IsWebContentsCreationOverridden(
|
||||
@@ -44,12 +44,12 @@ index d6295d809381f4f4a86a9948762079232ba6c93c..ad429250984cf367e1194bda67bc56a8
|
||||
const GURL& opener_url,
|
||||
- const std::string& frame_name,
|
||||
- const GURL& target_url) {
|
||||
+ const mojom::CreateNewWindowParams& params) {
|
||||
+ const content::mojom::CreateNewWindowParams& params) {
|
||||
// Disallow creating separate WebContentses. The WebContents implementation
|
||||
// uses this to spawn new windows/tabs, which is also not allowed for
|
||||
// offscreen tabs.
|
||||
diff --git a/chrome/browser/media/offscreen_tab.h b/chrome/browser/media/offscreen_tab.h
|
||||
index 3fd38bcb861174f99369d0e53b9946c632baf21a..de1a4df623538cc2857f8bb85b05e17d411c45a0 100644
|
||||
index 3fd38bcb861174f99369d0e53b9946c632baf21a..e758275588b027ec877d4afb1072891f0c6995ec 100644
|
||||
--- a/chrome/browser/media/offscreen_tab.h
|
||||
+++ b/chrome/browser/media/offscreen_tab.h
|
||||
@@ -103,8 +103,7 @@ class OffscreenTab final : public ProfileObserver,
|
||||
@@ -58,12 +58,12 @@ index 3fd38bcb861174f99369d0e53b9946c632baf21a..de1a4df623538cc2857f8bb85b05e17d
|
||||
const GURL& opener_url,
|
||||
- const std::string& frame_name,
|
||||
- const GURL& target_url) final;
|
||||
+ const mojom::CreateNewWindowParams& params) override;
|
||||
+ const content::mojom::CreateNewWindowParams& params) override;
|
||||
void EnterFullscreenModeForTab(
|
||||
content::RenderFrameHost* requesting_frame,
|
||||
const blink::mojom::FullscreenOptions& options) final;
|
||||
diff --git a/chrome/browser/ui/ash/assistant/assistant_web_view_impl.cc b/chrome/browser/ui/ash/assistant/assistant_web_view_impl.cc
|
||||
index e4f3632c84ebe4dcbbc3deb2f49e351c75ec93fd..58902fdaf316ad371ddb3e79e6ebc74cbbafc138 100644
|
||||
index e4f3632c84ebe4dcbbc3deb2f49e351c75ec93fd..08227615c2370bf55edfc373a40d9b488d775ba7 100644
|
||||
--- a/chrome/browser/ui/ash/assistant/assistant_web_view_impl.cc
|
||||
+++ b/chrome/browser/ui/ash/assistant/assistant_web_view_impl.cc
|
||||
@@ -77,10 +77,9 @@ bool AssistantWebViewImpl::IsWebContentsCreationOverridden(
|
||||
@@ -72,7 +72,7 @@ index e4f3632c84ebe4dcbbc3deb2f49e351c75ec93fd..58902fdaf316ad371ddb3e79e6ebc74c
|
||||
const GURL& opener_url,
|
||||
- const std::string& frame_name,
|
||||
- const GURL& target_url) {
|
||||
+ const mojom::CreateNewWindowParams& params) {
|
||||
+ const content::mojom::CreateNewWindowParams& params) {
|
||||
if (params_.suppress_navigation) {
|
||||
- NotifyDidSuppressNavigation(target_url,
|
||||
+ NotifyDidSuppressNavigation(params.target_url,
|
||||
@@ -80,7 +80,7 @@ index e4f3632c84ebe4dcbbc3deb2f49e351c75ec93fd..58902fdaf316ad371ddb3e79e6ebc74c
|
||||
/*from_user_gesture=*/true);
|
||||
return true;
|
||||
diff --git a/chrome/browser/ui/ash/assistant/assistant_web_view_impl.h b/chrome/browser/ui/ash/assistant/assistant_web_view_impl.h
|
||||
index 07014765f33bdddebcc5bc32a2713d6523faf394..f866f69f9c810d89f1a0e9e4952293f66804602a 100644
|
||||
index 07014765f33bdddebcc5bc32a2713d6523faf394..b76a6e4f5d79ad53caba3044c1d9d6e6b9e066f8 100644
|
||||
--- a/chrome/browser/ui/ash/assistant/assistant_web_view_impl.h
|
||||
+++ b/chrome/browser/ui/ash/assistant/assistant_web_view_impl.h
|
||||
@@ -48,8 +48,7 @@ class AssistantWebViewImpl : public ash::AssistantWebView,
|
||||
@@ -89,12 +89,12 @@ index 07014765f33bdddebcc5bc32a2713d6523faf394..f866f69f9c810d89f1a0e9e4952293f6
|
||||
const GURL& opener_url,
|
||||
- const std::string& frame_name,
|
||||
- const GURL& target_url) override;
|
||||
+ const mojom::CreateNewWindowParams& params) override;
|
||||
+ const content::mojom::CreateNewWindowParams& params) override;
|
||||
content::WebContents* OpenURLFromTab(
|
||||
content::WebContents* source,
|
||||
const content::OpenURLParams& params) override;
|
||||
diff --git a/chrome/browser/ui/ash/keyboard/chrome_keyboard_web_contents.cc b/chrome/browser/ui/ash/keyboard/chrome_keyboard_web_contents.cc
|
||||
index ef84e04d628fb5cdbaf8fbbf84af3bf23e00c522..f1ee0bee5bfd08227a29498f8410d5d3582e02c3 100644
|
||||
index ef84e04d628fb5cdbaf8fbbf84af3bf23e00c522..b6fde0d5f289d352670e03e0ffc8c0d234c0a7d3 100644
|
||||
--- a/chrome/browser/ui/ash/keyboard/chrome_keyboard_web_contents.cc
|
||||
+++ b/chrome/browser/ui/ash/keyboard/chrome_keyboard_web_contents.cc
|
||||
@@ -66,8 +66,7 @@ class ChromeKeyboardContentsDelegate : public content::WebContentsDelegate,
|
||||
@@ -103,12 +103,12 @@ index ef84e04d628fb5cdbaf8fbbf84af3bf23e00c522..f1ee0bee5bfd08227a29498f8410d5d3
|
||||
const GURL& opener_url,
|
||||
- const std::string& frame_name,
|
||||
- const GURL& target_url) override {
|
||||
+ const mojom::CreateNewWindowParams& params) override {
|
||||
+ const content::mojom::CreateNewWindowParams& params) override {
|
||||
return true;
|
||||
}
|
||||
|
||||
diff --git a/chrome/browser/ui/browser.cc b/chrome/browser/ui/browser.cc
|
||||
index 7e29403699d56081424643bd143d0f255c8e8e73..ad9f02f84ce5954d3a2ca9b7c26eab7f2c90c162 100644
|
||||
index 7e29403699d56081424643bd143d0f255c8e8e73..57a47dcea9dc57581bf60a30ef4ae165daff55a4 100644
|
||||
--- a/chrome/browser/ui/browser.cc
|
||||
+++ b/chrome/browser/ui/browser.cc
|
||||
@@ -1787,12 +1787,11 @@ bool Browser::IsWebContentsCreationOverridden(
|
||||
@@ -117,7 +117,7 @@ index 7e29403699d56081424643bd143d0f255c8e8e73..ad9f02f84ce5954d3a2ca9b7c26eab7f
|
||||
const GURL& opener_url,
|
||||
- const std::string& frame_name,
|
||||
- const GURL& target_url) {
|
||||
+ const mojom::CreateNewWindowParams& params) {
|
||||
+ const content::mojom::CreateNewWindowParams& params) {
|
||||
return window_container_type ==
|
||||
content::mojom::WindowContainerType::BACKGROUND &&
|
||||
ShouldCreateBackgroundContents(source_site_instance, opener_url,
|
||||
@@ -127,7 +127,7 @@ index 7e29403699d56081424643bd143d0f255c8e8e73..ad9f02f84ce5954d3a2ca9b7c26eab7f
|
||||
|
||||
WebContents* Browser::CreateCustomWebContents(
|
||||
diff --git a/chrome/browser/ui/browser.h b/chrome/browser/ui/browser.h
|
||||
index 7649c59dde3f58b5ec153eb6146b159cfc190975..c1cc53b89d805f63fe4dcda12e02cd0a2687f926 100644
|
||||
index 7649c59dde3f58b5ec153eb6146b159cfc190975..ce3f5e56b4e02a0e566e1a01ca2003a3bc21a947 100644
|
||||
--- a/chrome/browser/ui/browser.h
|
||||
+++ b/chrome/browser/ui/browser.h
|
||||
@@ -807,8 +807,7 @@ class Browser : public TabStripModelObserver,
|
||||
@@ -136,12 +136,12 @@ index 7649c59dde3f58b5ec153eb6146b159cfc190975..c1cc53b89d805f63fe4dcda12e02cd0a
|
||||
const GURL& opener_url,
|
||||
- const std::string& frame_name,
|
||||
- const GURL& target_url) override;
|
||||
+ const mojom::CreateNewWindowParams& params) override;
|
||||
+ const content::mojom::CreateNewWindowParams& params) override;
|
||||
content::WebContents* CreateCustomWebContents(
|
||||
content::RenderFrameHost* opener,
|
||||
content::SiteInstance* source_site_instance,
|
||||
diff --git a/chrome/browser/ui/media_router/presentation_receiver_window_controller.cc b/chrome/browser/ui/media_router/presentation_receiver_window_controller.cc
|
||||
index ff97ac6e97c688d677053a5f01546a4c2d91ff1d..1da6a9c32b883a17975e61d60363918251c78ffd 100644
|
||||
index ff97ac6e97c688d677053a5f01546a4c2d91ff1d..c095be21525d85e3d6c1f4a0c1dda5c8579e1ec3 100644
|
||||
--- a/chrome/browser/ui/media_router/presentation_receiver_window_controller.cc
|
||||
+++ b/chrome/browser/ui/media_router/presentation_receiver_window_controller.cc
|
||||
@@ -201,8 +201,7 @@ bool PresentationReceiverWindowController::IsWebContentsCreationOverridden(
|
||||
@@ -150,12 +150,12 @@ index ff97ac6e97c688d677053a5f01546a4c2d91ff1d..1da6a9c32b883a17975e61d603639182
|
||||
const GURL& opener_url,
|
||||
- const std::string& frame_name,
|
||||
- const GURL& target_url) {
|
||||
+ const mojom::CreateNewWindowParams& params) {
|
||||
+ const content::mojom::CreateNewWindowParams& params) {
|
||||
// Disallow creating separate WebContentses. The WebContents implementation
|
||||
// uses this to spawn new windows/tabs, which is also not allowed for
|
||||
// local presentations.
|
||||
diff --git a/chrome/browser/ui/media_router/presentation_receiver_window_controller.h b/chrome/browser/ui/media_router/presentation_receiver_window_controller.h
|
||||
index 058ec72442d59989c4d6df4a7c791ecfeff0ef99..f7c8c2139382cb2e290c561624291afe647383cf 100644
|
||||
index 058ec72442d59989c4d6df4a7c791ecfeff0ef99..136b835e9a044aad4a1b3c0582a56f7cf56d2691 100644
|
||||
--- a/chrome/browser/ui/media_router/presentation_receiver_window_controller.h
|
||||
+++ b/chrome/browser/ui/media_router/presentation_receiver_window_controller.h
|
||||
@@ -99,8 +99,7 @@ class PresentationReceiverWindowController final
|
||||
@@ -164,12 +164,12 @@ index 058ec72442d59989c4d6df4a7c791ecfeff0ef99..f7c8c2139382cb2e290c561624291afe
|
||||
const GURL& opener_url,
|
||||
- const std::string& frame_name,
|
||||
- const GURL& target_url) override;
|
||||
+ const mojom::CreateNewWindowParams& params) override;
|
||||
+ const content::mojom::CreateNewWindowParams& params) override;
|
||||
|
||||
// The profile used for the presentation.
|
||||
Profile* otr_profile_;
|
||||
diff --git a/components/embedder_support/android/delegate/web_contents_delegate_android.cc b/components/embedder_support/android/delegate/web_contents_delegate_android.cc
|
||||
index 9364a722de5183c077a9c50b8c8a48ffa3a0fea6..ddde17de38bc5ca904046702a28a88d7c00f18c4 100644
|
||||
index 9364a722de5183c077a9c50b8c8a48ffa3a0fea6..58d9e6c24d70dbedeb41f0b29ed1cb03a1bdcde3 100644
|
||||
--- a/components/embedder_support/android/delegate/web_contents_delegate_android.cc
|
||||
+++ b/components/embedder_support/android/delegate/web_contents_delegate_android.cc
|
||||
@@ -170,14 +170,13 @@ bool WebContentsDelegateAndroid::IsWebContentsCreationOverridden(
|
||||
@@ -178,7 +178,7 @@ index 9364a722de5183c077a9c50b8c8a48ffa3a0fea6..ddde17de38bc5ca904046702a28a88d7
|
||||
const GURL& opener_url,
|
||||
- const std::string& frame_name,
|
||||
- const GURL& target_url) {
|
||||
+ const mojom::CreateNewWindowParams& params) {
|
||||
+ const content::mojom::CreateNewWindowParams& params) {
|
||||
JNIEnv* env = AttachCurrentThread();
|
||||
ScopedJavaLocalRef<jobject> obj = GetJavaDelegate(env);
|
||||
if (obj.is_null())
|
||||
@@ -190,7 +190,7 @@ index 9364a722de5183c077a9c50b8c8a48ffa3a0fea6..ddde17de38bc5ca904046702a28a88d7
|
||||
java_gurl);
|
||||
}
|
||||
diff --git a/components/embedder_support/android/delegate/web_contents_delegate_android.h b/components/embedder_support/android/delegate/web_contents_delegate_android.h
|
||||
index 4b832f4c3a051eefca57909958334631335e03e1..8aed42112d8fad7df813524cf700d8082ad75c47 100644
|
||||
index 4b832f4c3a051eefca57909958334631335e03e1..b665a3cac289409280e61f75eb7d7eb83517f603 100644
|
||||
--- a/components/embedder_support/android/delegate/web_contents_delegate_android.h
|
||||
+++ b/components/embedder_support/android/delegate/web_contents_delegate_android.h
|
||||
@@ -78,8 +78,7 @@ class WebContentsDelegateAndroid : public content::WebContentsDelegate {
|
||||
@@ -199,12 +199,12 @@ index 4b832f4c3a051eefca57909958334631335e03e1..8aed42112d8fad7df813524cf700d808
|
||||
const GURL& opener_url,
|
||||
- const std::string& frame_name,
|
||||
- const GURL& target_url) override;
|
||||
+ const mojom::CreateNewWindowParams& params) override;
|
||||
+ const content::mojom::CreateNewWindowParams& params) override;
|
||||
void CloseContents(content::WebContents* source) override;
|
||||
void SetContentsBounds(content::WebContents* source,
|
||||
const gfx::Rect& bounds) override;
|
||||
diff --git a/components/offline_pages/content/background_loader/background_loader_contents.cc b/components/offline_pages/content/background_loader/background_loader_contents.cc
|
||||
index 53fad64f87a952fd0d7398958288ecde259b57bf..0b8359b6179bf16e58978e5f3e51a911ad3d0a3f 100644
|
||||
index 53fad64f87a952fd0d7398958288ecde259b57bf..26f64dabcbee575034e97ada29c7de48b315080f 100644
|
||||
--- a/components/offline_pages/content/background_loader/background_loader_contents.cc
|
||||
+++ b/components/offline_pages/content/background_loader/background_loader_contents.cc
|
||||
@@ -80,8 +80,7 @@ bool BackgroundLoaderContents::IsWebContentsCreationOverridden(
|
||||
@@ -213,12 +213,12 @@ index 53fad64f87a952fd0d7398958288ecde259b57bf..0b8359b6179bf16e58978e5f3e51a911
|
||||
const GURL& opener_url,
|
||||
- const std::string& frame_name,
|
||||
- const GURL& target_url) {
|
||||
+ const mojom::CreateNewWindowParams& params) {
|
||||
+ const content::mojom::CreateNewWindowParams& params) {
|
||||
// Background pages should not create other webcontents/tabs.
|
||||
return true;
|
||||
}
|
||||
diff --git a/components/offline_pages/content/background_loader/background_loader_contents.h b/components/offline_pages/content/background_loader/background_loader_contents.h
|
||||
index c5c5a7b63b5b3b62a9517cbef3ae23ce57a3c89c..4f1b7e88d6d2ae89a60311c8aeb1fceea87f2b02 100644
|
||||
index c5c5a7b63b5b3b62a9517cbef3ae23ce57a3c89c..1002ce845c0372b99293917e41dab0bee701b49f 100644
|
||||
--- a/components/offline_pages/content/background_loader/background_loader_contents.h
|
||||
+++ b/components/offline_pages/content/background_loader/background_loader_contents.h
|
||||
@@ -60,8 +60,7 @@ class BackgroundLoaderContents : public content::WebContentsDelegate {
|
||||
@@ -227,7 +227,7 @@ index c5c5a7b63b5b3b62a9517cbef3ae23ce57a3c89c..4f1b7e88d6d2ae89a60311c8aeb1fcee
|
||||
const GURL& opener_url,
|
||||
- const std::string& frame_name,
|
||||
- const GURL& target_url) override;
|
||||
+ const mojom::CreateNewWindowParams& params) override;
|
||||
+ const content::mojom::CreateNewWindowParams& params) override;
|
||||
|
||||
void AddNewContents(content::WebContents* source,
|
||||
std::unique_ptr<content::WebContents> new_contents,
|
||||
@@ -246,7 +246,7 @@ index a5aca663101e206156528adaf299d4d97a9ee59e..50bee6111f723932ad2164f42c71ad95
|
||||
static_cast<WebContentsImpl*>(delegate_->CreateCustomWebContents(
|
||||
opener, source_site_instance, is_new_browsing_instance,
|
||||
diff --git a/content/public/browser/web_contents_delegate.cc b/content/public/browser/web_contents_delegate.cc
|
||||
index 31c73efb73bb69076abd6b9c4f139072a9f7f603..3867f45d32c409ce6a738519ba539b51685c7d3e 100644
|
||||
index 31c73efb73bb69076abd6b9c4f139072a9f7f603..d1d6720377043af43f71b2ed8f35f71ee168e0ea 100644
|
||||
--- a/content/public/browser/web_contents_delegate.cc
|
||||
+++ b/content/public/browser/web_contents_delegate.cc
|
||||
@@ -136,8 +136,7 @@ bool WebContentsDelegate::IsWebContentsCreationOverridden(
|
||||
@@ -255,12 +255,12 @@ index 31c73efb73bb69076abd6b9c4f139072a9f7f603..3867f45d32c409ce6a738519ba539b51
|
||||
const GURL& opener_url,
|
||||
- const std::string& frame_name,
|
||||
- const GURL& target_url) {
|
||||
+ const mojom::CreateNewWindowParams& params) {
|
||||
+ const content::mojom::CreateNewWindowParams& params) {
|
||||
return false;
|
||||
}
|
||||
|
||||
diff --git a/content/public/browser/web_contents_delegate.h b/content/public/browser/web_contents_delegate.h
|
||||
index 5936fa4bce09895595ccb294504f5b89c967d8c0..7186e17271d727c2df1d58e9cb300d22dd4e52e5 100644
|
||||
index 5936fa4bce09895595ccb294504f5b89c967d8c0..09a39bb7a3bea1c7215273b2946bd3bea7cb30b3 100644
|
||||
--- a/content/public/browser/web_contents_delegate.h
|
||||
+++ b/content/public/browser/web_contents_delegate.h
|
||||
@@ -314,8 +314,7 @@ class CONTENT_EXPORT WebContentsDelegate {
|
||||
@@ -269,7 +269,7 @@ index 5936fa4bce09895595ccb294504f5b89c967d8c0..7186e17271d727c2df1d58e9cb300d22
|
||||
const GURL& opener_url,
|
||||
- const std::string& frame_name,
|
||||
- const GURL& target_url);
|
||||
+ const mojom::CreateNewWindowParams& params);
|
||||
+ const content::mojom::CreateNewWindowParams& params);
|
||||
|
||||
// Allow delegate to creates a custom WebContents when
|
||||
// WebContents::CreateNewWindow() is called. This function is only called
|
||||
@@ -330,7 +330,7 @@ index bb90319f768ed2f3a3e530d64bf622de585ce163..d84de1d218267887f6b8624f913438eb
|
||||
content::RenderFrameHost* opener,
|
||||
content::SiteInstance* source_site_instance,
|
||||
diff --git a/fuchsia/engine/browser/frame_impl.cc b/fuchsia/engine/browser/frame_impl.cc
|
||||
index 2863abb239a77b96e638c83f47ae7219cf0ccec8..5675ad386efa99383067eb404b385cf2ec46142e 100644
|
||||
index 2863abb239a77b96e638c83f47ae7219cf0ccec8..b7bbdd2077d193be711ef9ec787e66bdcb7de301 100644
|
||||
--- a/fuchsia/engine/browser/frame_impl.cc
|
||||
+++ b/fuchsia/engine/browser/frame_impl.cc
|
||||
@@ -388,8 +388,7 @@ bool FrameImpl::IsWebContentsCreationOverridden(
|
||||
@@ -339,12 +339,12 @@ index 2863abb239a77b96e638c83f47ae7219cf0ccec8..5675ad386efa99383067eb404b385cf2
|
||||
const GURL& opener_url,
|
||||
- const std::string& frame_name,
|
||||
- const GURL& target_url) {
|
||||
+ const mojom::CreateNewWindowParams& params) {
|
||||
+ const content::mojom::CreateNewWindowParams& params) {
|
||||
// Specify a generous upper bound for unacknowledged popup windows, so that we
|
||||
// can catch bad client behavior while not interfering with normal operation.
|
||||
constexpr size_t kMaxPendingWebContentsCount = 10;
|
||||
diff --git a/fuchsia/engine/browser/frame_impl.h b/fuchsia/engine/browser/frame_impl.h
|
||||
index e2736c5329d9516fdd417df4dff8039f991e800e..11081373e0d70e7ec366c6917c21db61c4e18cca 100644
|
||||
index e2736c5329d9516fdd417df4dff8039f991e800e..ac50e41768c8f05a757cd32339ca622b608feaf9 100644
|
||||
--- a/fuchsia/engine/browser/frame_impl.h
|
||||
+++ b/fuchsia/engine/browser/frame_impl.h
|
||||
@@ -245,8 +245,7 @@ class FrameImpl : public fuchsia::web::Frame,
|
||||
@@ -353,12 +353,12 @@ index e2736c5329d9516fdd417df4dff8039f991e800e..11081373e0d70e7ec366c6917c21db61
|
||||
const GURL& opener_url,
|
||||
- const std::string& frame_name,
|
||||
- const GURL& target_url) override;
|
||||
+ const mojom::CreateNewWindowParams& params) override;
|
||||
+ const content::mojom::CreateNewWindowParams& params) override;
|
||||
void WebContentsCreated(content::WebContents* source_contents,
|
||||
int opener_render_process_id,
|
||||
int opener_render_frame_id,
|
||||
diff --git a/headless/lib/browser/headless_web_contents_impl.cc b/headless/lib/browser/headless_web_contents_impl.cc
|
||||
index dd1f6129173a0e19023f4ec9b66c44486b080456..d10468c06f84b59387af0a8fd5bc1c06108865eb 100644
|
||||
index dd1f6129173a0e19023f4ec9b66c44486b080456..0b6d3cddd71a222db32e555630c0b00c2dfe215c 100644
|
||||
--- a/headless/lib/browser/headless_web_contents_impl.cc
|
||||
+++ b/headless/lib/browser/headless_web_contents_impl.cc
|
||||
@@ -192,8 +192,7 @@ class HeadlessWebContentsImpl::Delegate : public content::WebContentsDelegate {
|
||||
@@ -367,7 +367,7 @@ index dd1f6129173a0e19023f4ec9b66c44486b080456..d10468c06f84b59387af0a8fd5bc1c06
|
||||
const GURL& opener_url,
|
||||
- const std::string& frame_name,
|
||||
- const GURL& target_url) override {
|
||||
+ const mojom::CreateNewWindowParams& params) override {
|
||||
+ const content::mojom::CreateNewWindowParams& params) override {
|
||||
return headless_web_contents_->browser_context()
|
||||
->options()
|
||||
->block_new_web_contents();
|
||||
|
||||
138
patches/chromium/cleanup_pausablecriptexecutor_usage.patch
Normal file
138
patches/chromium/cleanup_pausablecriptexecutor_usage.patch
Normal file
@@ -0,0 +1,138 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Dave Tapuska <dtapuska@chromium.org>
|
||||
Date: Tue, 8 Feb 2022 15:58:40 +0000
|
||||
Subject: Cleanup PausablecriptExecutor usage.
|
||||
|
||||
Improve performance of API so we don't have to go from
|
||||
WTF::String->WebString->WTF::String for execution.
|
||||
|
||||
Ensure the Executor is traced via the PausableScriptExecutor.
|
||||
|
||||
BUG=1289384
|
||||
|
||||
(cherry picked from commit c8231f9a89460fd8336e6c0d8e10347f52f540ec)
|
||||
|
||||
Change-Id: If9badab91222c49c08a983c60132ce71b183e951
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3407654
|
||||
Reviewed-by: Michael Lippautz <mlippautz@chromium.org>
|
||||
Reviewed-by: Daniel Cheng <dcheng@chromium.org>
|
||||
Commit-Queue: Dave Tapuska <dtapuska@chromium.org>
|
||||
Cr-Original-Commit-Position: refs/heads/main@{#963010}
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3443262
|
||||
Bot-Commit: Rubber Stamper <rubber-stamper@appspot.gserviceaccount.com>
|
||||
Cr-Commit-Position: refs/branch-heads/4758@{#1109}
|
||||
Cr-Branched-From: 4a2cf4baf90326df19c3ee70ff987960d59a386e-refs/heads/main@{#950365}
|
||||
|
||||
diff --git a/third_party/blink/renderer/core/frame/local_frame_mojo_handler.cc b/third_party/blink/renderer/core/frame/local_frame_mojo_handler.cc
|
||||
index 71653584749ef80143f3312a85a9537edd35f014..60377e12f05d298aa512a2eda5358c8bea49d114 100644
|
||||
--- a/third_party/blink/renderer/core/frame/local_frame_mojo_handler.cc
|
||||
+++ b/third_party/blink/renderer/core/frame/local_frame_mojo_handler.cc
|
||||
@@ -211,15 +211,16 @@ v8::MaybeLocal<v8::Value> CallMethodOnFrame(LocalFrame* local_frame,
|
||||
|
||||
// A wrapper class used as the callback for JavaScript executed
|
||||
// in an isolated world.
|
||||
-class JavaScriptIsolatedWorldRequest
|
||||
- : public GarbageCollected<JavaScriptIsolatedWorldRequest>,
|
||||
- public WebScriptExecutionCallback {
|
||||
+class JavaScriptIsolatedWorldRequest : public PausableScriptExecutor::Executor,
|
||||
+ public WebScriptExecutionCallback {
|
||||
using JavaScriptExecuteRequestInIsolatedWorldCallback =
|
||||
mojom::blink::LocalFrame::JavaScriptExecuteRequestInIsolatedWorldCallback;
|
||||
|
||||
public:
|
||||
JavaScriptIsolatedWorldRequest(
|
||||
LocalFrame* local_frame,
|
||||
+ int32_t world_id,
|
||||
+ const String& script,
|
||||
bool wants_result,
|
||||
mojom::blink::LocalFrame::JavaScriptExecuteRequestInIsolatedWorldCallback
|
||||
callback);
|
||||
@@ -229,27 +230,53 @@ class JavaScriptIsolatedWorldRequest
|
||||
const JavaScriptIsolatedWorldRequest&) = delete;
|
||||
~JavaScriptIsolatedWorldRequest() override;
|
||||
|
||||
- // WebScriptExecutionCallback:
|
||||
- void Completed(const WebVector<v8::Local<v8::Value>>& result) override;
|
||||
+ // PausableScriptExecutor::Executor overrides.
|
||||
+ Vector<v8::Local<v8::Value>> Execute(LocalDOMWindow*) override;
|
||||
+
|
||||
+ void Trace(Visitor* visitor) const override;
|
||||
|
||||
- void Trace(Visitor* visitor) const { visitor->Trace(local_frame_); }
|
||||
+ // WebScriptExecutionCallback overrides.
|
||||
+ void Completed(const WebVector<v8::Local<v8::Value>>& result) override;
|
||||
|
||||
private:
|
||||
Member<LocalFrame> local_frame_;
|
||||
+ int32_t world_id_;
|
||||
+ String script_;
|
||||
bool wants_result_;
|
||||
JavaScriptExecuteRequestInIsolatedWorldCallback callback_;
|
||||
};
|
||||
|
||||
JavaScriptIsolatedWorldRequest::JavaScriptIsolatedWorldRequest(
|
||||
LocalFrame* local_frame,
|
||||
+ int32_t world_id,
|
||||
+ const String& script,
|
||||
bool wants_result,
|
||||
JavaScriptExecuteRequestInIsolatedWorldCallback callback)
|
||||
: local_frame_(local_frame),
|
||||
+ world_id_(world_id),
|
||||
+ script_(script),
|
||||
wants_result_(wants_result),
|
||||
- callback_(std::move(callback)) {}
|
||||
+ callback_(std::move(callback)) {
|
||||
+ DCHECK_GT(world_id, DOMWrapperWorld::kMainWorldId);
|
||||
+}
|
||||
|
||||
JavaScriptIsolatedWorldRequest::~JavaScriptIsolatedWorldRequest() = default;
|
||||
|
||||
+void JavaScriptIsolatedWorldRequest::Trace(Visitor* visitor) const {
|
||||
+ PausableScriptExecutor::Executor::Trace(visitor);
|
||||
+ visitor->Trace(local_frame_);
|
||||
+}
|
||||
+
|
||||
+Vector<v8::Local<v8::Value>> JavaScriptIsolatedWorldRequest::Execute(
|
||||
+ LocalDOMWindow* window) {
|
||||
+ // Note: An error event in an isolated world will never be dispatched to
|
||||
+ // a foreign world.
|
||||
+ ClassicScript* classic_script = ClassicScript::CreateUnspecifiedScript(
|
||||
+ script_, SanitizeScriptErrors::kDoNotSanitize);
|
||||
+ return {classic_script->RunScriptInIsolatedWorldAndReturnValue(window,
|
||||
+ world_id_)};
|
||||
+}
|
||||
+
|
||||
void JavaScriptIsolatedWorldRequest::Completed(
|
||||
const WebVector<v8::Local<v8::Value>>& result) {
|
||||
base::Value value;
|
||||
@@ -269,7 +296,6 @@ void JavaScriptIsolatedWorldRequest::Completed(
|
||||
if (new_value)
|
||||
value = base::Value::FromUniquePtrValue(std::move(new_value));
|
||||
}
|
||||
-
|
||||
std::move(callback_).Run(std::move(value));
|
||||
}
|
||||
|
||||
@@ -927,13 +953,16 @@ void LocalFrameMojoHandler::JavaScriptExecuteRequestInIsolatedWorld(
|
||||
v8::HandleScope handle_scope(v8::Isolate::GetCurrent());
|
||||
scoped_refptr<DOMWrapperWorld> isolated_world =
|
||||
DOMWrapperWorld::EnsureIsolatedWorld(ToIsolate(frame_), world_id);
|
||||
- ScriptSourceCode source_code = ScriptSourceCode(javascript);
|
||||
- HeapVector<ScriptSourceCode> sources;
|
||||
- sources.Append(&source_code, 1);
|
||||
- auto* executor = MakeGarbageCollected<PausableScriptExecutor>(
|
||||
- DomWindow(), std::move(isolated_world), sources, false /* user_gesture */,
|
||||
+
|
||||
+ // This member will be traced as the |executor| on the PausableScriptExector.
|
||||
+ auto* execution_request =
|
||||
MakeGarbageCollected<JavaScriptIsolatedWorldRequest>(
|
||||
- frame_, wants_result, std::move(callback)));
|
||||
+ frame_, world_id, javascript, wants_result, std::move(callback));
|
||||
+
|
||||
+ auto* executor = MakeGarbageCollected<PausableScriptExecutor>(
|
||||
+ DomWindow(), ToScriptState(frame_, *isolated_world),
|
||||
+ /*callback=*/execution_request,
|
||||
+ /*executor=*/execution_request);
|
||||
executor->Run();
|
||||
}
|
||||
|
||||
@@ -0,0 +1,60 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Peng Huang <penghuang@chromium.org>
|
||||
Date: Mon, 25 Oct 2021 21:10:55 +0000
|
||||
Subject: Do not select vulkan device based on the passed in gpu_info on Linux
|
||||
|
||||
On linux dual GPU setup, we cannot detect the active GPU correctly.
|
||||
It causes problems for GL and Vulkan interop. So we would to use
|
||||
ANGLE vulkan backend when vulkan is enabled. So we can choose the same
|
||||
GPU for both vulkan and GL. So for this CL, we will not create vulkan
|
||||
device based on passed in gpu_info anymore, instead GPU device will be
|
||||
selected by the order of
|
||||
(discrete GPU > integrated GPU > virtual GPU > CPU simulated GPU).
|
||||
And we will use the same logic in ANGLE vulkan backend as well.
|
||||
|
||||
Bug: 1260869
|
||||
Change-Id: I6fb79a4e6ce1710e4809cd63a0f7738955a8e2d2
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3242785
|
||||
Commit-Queue: Peng Huang <penghuang@chromium.org>
|
||||
Commit-Queue: Vasiliy Telezhnikov <vasilyt@chromium.org>
|
||||
Auto-Submit: Peng Huang <penghuang@chromium.org>
|
||||
Reviewed-by: Vasiliy Telezhnikov <vasilyt@chromium.org>
|
||||
Cr-Commit-Position: refs/heads/main@{#934696}
|
||||
|
||||
diff --git a/gpu/vulkan/vulkan_device_queue.cc b/gpu/vulkan/vulkan_device_queue.cc
|
||||
index e4fe73f613dfe27b2ac6ccd7d31448e0f16ff459..22abed4db134647699d5622c4b92c3a861274f7c 100644
|
||||
--- a/gpu/vulkan/vulkan_device_queue.cc
|
||||
+++ b/gpu/vulkan/vulkan_device_queue.cc
|
||||
@@ -11,6 +11,7 @@
|
||||
|
||||
#include "base/logging.h"
|
||||
#include "base/strings/stringprintf.h"
|
||||
+#include "build/build_config.h"
|
||||
#include "gpu/config/gpu_info.h" // nogncheck
|
||||
#include "gpu/config/vulkan_info.h"
|
||||
#include "gpu/vulkan/vulkan_command_pool.h"
|
||||
@@ -77,11 +78,15 @@ bool VulkanDeviceQueue::Initialize(
|
||||
if (device_properties.apiVersion < info.used_api_version)
|
||||
continue;
|
||||
|
||||
+ // In dual-CPU cases, we cannot detect the active GPU correctly on Linux,
|
||||
+ // so don't select GPU device based on the |gpu_info|.
|
||||
+#if !defined(OS_LINUX)
|
||||
// If gpu_info is provided, the device should match it.
|
||||
if (gpu_info && (device_properties.vendorID != gpu_info->gpu.vendor_id ||
|
||||
device_properties.deviceID != gpu_info->gpu.device_id)) {
|
||||
continue;
|
||||
}
|
||||
+#endif
|
||||
|
||||
if (device_properties.deviceType < 0 ||
|
||||
device_properties.deviceType > VK_PHYSICAL_DEVICE_TYPE_CPU) {
|
||||
@@ -112,7 +117,7 @@ bool VulkanDeviceQueue::Initialize(
|
||||
break;
|
||||
}
|
||||
}
|
||||
-
|
||||
+
|
||||
if (!found)
|
||||
continue;
|
||||
|
||||
@@ -33,10 +33,10 @@ index 0ccfe130f00ec3b6c75cd8ee04d5a2777e1fd00c..653829457d58bf92057cc36aa8a28970
|
||||
DISALLOW_COPY_AND_ASSIGN(StaticHttpUserAgentSettings);
|
||||
};
|
||||
diff --git a/services/network/network_context.cc b/services/network/network_context.cc
|
||||
index 00af87f13c9f819e4d56a3c2ecbac9337be88dec..b48f88f20f54bdd5521528882158fe1864becbbe 100644
|
||||
index 24298fa4c35fec195e0e1b15422b97e2cf89daa8..8f20984763357a95c3d86be228e9bbf5e17bc9e9 100644
|
||||
--- a/services/network/network_context.cc
|
||||
+++ b/services/network/network_context.cc
|
||||
@@ -1195,6 +1195,13 @@ void NetworkContext::SetNetworkConditions(
|
||||
@@ -1207,6 +1207,13 @@ void NetworkContext::SetNetworkConditions(
|
||||
std::move(network_conditions));
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,191 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Nate Chapin <japhet@chromium.org>
|
||||
Date: Thu, 14 Oct 2021 20:24:32 +0000
|
||||
Subject: Fire iframe onload for cross-origin-initiated same-document
|
||||
navigations
|
||||
|
||||
A cross-origin initiator can check whether or not onload fired to
|
||||
guess the url of a target frame. Always firing onload makes it
|
||||
appear to be a cross-document navigation, even when it wasn't.
|
||||
|
||||
Bug: 1248444
|
||||
Change-Id: I79249cb441f61ac6cab65ab9e5dd4a44b291bc4a
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3193885
|
||||
Commit-Queue: Nate Chapin <japhet@chromium.org>
|
||||
Reviewed-by: Rakina Zata Amni <rakina@chromium.org>
|
||||
Cr-Commit-Position: refs/heads/main@{#931681}
|
||||
|
||||
diff --git a/third_party/blink/renderer/core/loader/document_loader.cc b/third_party/blink/renderer/core/loader/document_loader.cc
|
||||
index 5f0be38667a04a3a47f190099b81778cc8b02757..ae8baa6ab44f83e114646247f99bd0b95710f249 100644
|
||||
--- a/third_party/blink/renderer/core/loader/document_loader.cc
|
||||
+++ b/third_party/blink/renderer/core/loader/document_loader.cc
|
||||
@@ -1429,7 +1429,25 @@ void DocumentLoader::CommitSameDocumentNavigationInternal(
|
||||
|
||||
initial_scroll_state_.was_scrolled_by_user = false;
|
||||
|
||||
- frame_->GetDocument()->CheckCompleted();
|
||||
+ if (frame_->GetDocument()->LoadEventStillNeeded()) {
|
||||
+ frame_->GetDocument()->CheckCompleted();
|
||||
+ } else if (frame_->Owner() && initiator_origin &&
|
||||
+ !initiator_origin->CanAccess(
|
||||
+ frame_->DomWindow()->GetSecurityOrigin()) &&
|
||||
+ frame_->Tree()
|
||||
+ .Parent()
|
||||
+ ->GetSecurityContext()
|
||||
+ ->GetSecurityOrigin()) {
|
||||
+ // If this same-document navigation was initiated by a cross-origin iframe
|
||||
+ // and is cross-origin to its parent, fire onload on the owner iframe.
|
||||
+ // Normally, the owner iframe's onload fires if and only if the window's
|
||||
+ // onload fires (i.e., when a navigation to a different document completes).
|
||||
+ // However, a cross-origin initiator can use the presence or absence of a
|
||||
+ // load event to detect whether the navigation was same- or cross-document,
|
||||
+ // and can therefore try to guess the url of a cross-origin iframe. Fire the
|
||||
+ // iframe's onload to prevent this technique. https://crbug.com/1251790
|
||||
+ frame_->Owner()->DispatchLoad();
|
||||
+ }
|
||||
|
||||
// If the item sequence number didn't change, there's no need to trigger
|
||||
// popstate, restore scroll positions, or scroll to fragments for this
|
||||
diff --git a/third_party/blink/web_tests/http/tests/navigation/cross-origin-fragment-navigation-is-async-expected.txt b/third_party/blink/web_tests/http/tests/navigation/cross-origin-fragment-navigation-is-async-expected.txt
|
||||
index 850c54970953c62eae282e177949f9082f22a03c..09122d9c3f39f042116d197276420cc1841c5ea8 100644
|
||||
--- a/third_party/blink/web_tests/http/tests/navigation/cross-origin-fragment-navigation-is-async-expected.txt
|
||||
+++ b/third_party/blink/web_tests/http/tests/navigation/cross-origin-fragment-navigation-is-async-expected.txt
|
||||
@@ -1,4 +1,6 @@
|
||||
+ALERT: iframe onload fired
|
||||
ALERT: PASS: url fragment is changing asynchronously
|
||||
ALERT: PASS: scheduled postMessage() before hashchange triggered.
|
||||
+ALERT: iframe onload fired
|
||||
ALERT: PASS: hashchange triggered after postMessage().
|
||||
-This tests that cross-origin fragment navigations are asynchronous. It does so by scheduling a postMessage before scheduling the navigation. If the navigation is synchronous, the internals API will be able to report the presence of an url fragment immediately.
|
||||
+This tests that cross-origin-initiated fragment navigations are asynchronous and always fire the load event at their embedding iframe element if it's cross-origin. It does so by scheduling a postMessage before scheduling the navigation. If the navigation is synchronous, the internals API will be able to report the presence of an url fragment immediately.
|
||||
diff --git a/third_party/blink/web_tests/http/tests/navigation/cross-origin-fragment-navigation-is-async.html b/third_party/blink/web_tests/http/tests/navigation/cross-origin-fragment-navigation-is-async.html
|
||||
index 3d74de086c1a7f8a5fedff72d7c6bb970fca57ed..a1fc3bc87ccd2319f2dff3c5d8729a1a62875ec8 100644
|
||||
--- a/third_party/blink/web_tests/http/tests/navigation/cross-origin-fragment-navigation-is-async.html
|
||||
+++ b/third_party/blink/web_tests/http/tests/navigation/cross-origin-fragment-navigation-is-async.html
|
||||
@@ -1,48 +1,51 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
-<head>
|
||||
- <script>
|
||||
- if (window.testRunner) {
|
||||
- testRunner.dumpAsText();
|
||||
- testRunner.waitUntilDone();
|
||||
- }
|
||||
+<body>
|
||||
+<script>
|
||||
+if (window.testRunner) {
|
||||
+ testRunner.dumpAsText();
|
||||
+ testRunner.waitUntilDone();
|
||||
+}
|
||||
|
||||
- function testFragmentNavigation() {
|
||||
- window.postMessage("postmessage", "*");
|
||||
- document.querySelector('iframe').src = "http://localhost:8000/navigation/resources/postmessage-on-hashchange.html#anchor1";
|
||||
- if (window.internals) {
|
||||
- if (internals.doesWindowHaveUrlFragment(document.querySelector('iframe').contentWindow))
|
||||
- alert("FAIL: url fragment should change asynchronously");
|
||||
- else
|
||||
- alert("PASS: url fragment is changing asynchronously");
|
||||
- }
|
||||
- }
|
||||
+window.onload = function() {
|
||||
+ window.postMessage("postmessage", "*");
|
||||
+ document.querySelector('iframe').src = "http://localhost:8000/navigation/resources/postmessage-on-hashchange.html#anchor1";
|
||||
+ if (window.internals) {
|
||||
+ if (internals.doesWindowHaveUrlFragment(document.querySelector('iframe').contentWindow))
|
||||
+ alert("FAIL: url fragment should change asynchronously");
|
||||
+ else
|
||||
+ alert("PASS: url fragment is changing asynchronously");
|
||||
+ }
|
||||
+}
|
||||
|
||||
- var receivedScheduledPostMessage = false;
|
||||
- var receivedHashchangeMessage = false;
|
||||
- window.addEventListener('message', function (e) {
|
||||
- if (e.data === 'postmessage') {
|
||||
- receivedScheduledPostMessage = true;
|
||||
- if (receivedHashchangeMessage)
|
||||
- alert('FAIL: hashchange already triggered!');
|
||||
- else
|
||||
- alert('PASS: scheduled postMessage() before hashchange triggered.');
|
||||
- } else {
|
||||
- receivedHashchangeMessage = true;
|
||||
- if (receivedScheduledPostMessage)
|
||||
- alert('PASS: hashchange triggered after postMessage().');
|
||||
- else
|
||||
- alert('FAIL: hashchange triggered before postMessage().');
|
||||
- testRunner.notifyDone();
|
||||
- }
|
||||
- });
|
||||
- </script>
|
||||
-</head>
|
||||
-<body>
|
||||
- <p>This tests that cross-origin fragment navigations are asynchronous. It does
|
||||
- so by scheduling a postMessage before scheduling the navigation. If the
|
||||
- navigation is synchronous, the internals API will be able to report the presence
|
||||
- of an url fragment immediately.</p>
|
||||
- <iframe src="http://localhost:8000/navigation/resources/postmessage-on-hashchange.html" onload='testFragmentNavigation()'></iframe>
|
||||
+var receivedScheduledPostMessage = false;
|
||||
+var receivedHashchangeMessage = false;
|
||||
+window.addEventListener('message', function (e) {
|
||||
+ if (e.data === 'postmessage') {
|
||||
+ receivedScheduledPostMessage = true;
|
||||
+ if (receivedHashchangeMessage)
|
||||
+ alert('FAIL: hashchange already triggered!');
|
||||
+ else
|
||||
+ alert('PASS: scheduled postMessage() before hashchange triggered.');
|
||||
+ } else {
|
||||
+ receivedHashchangeMessage = true;
|
||||
+ if (receivedScheduledPostMessage)
|
||||
+ alert('PASS: hashchange triggered after postMessage().');
|
||||
+ else
|
||||
+ alert('FAIL: hashchange triggered before postMessage().');
|
||||
+ testRunner.notifyDone();
|
||||
+ }
|
||||
+});
|
||||
+
|
||||
+function onloadFired() {
|
||||
+ alert("iframe onload fired");
|
||||
+}
|
||||
+</script>
|
||||
+<p>This tests that cross-origin-initiated fragment navigations are asynchronous
|
||||
+and always fire the load event at their embedding iframe element if it's cross-origin. It does
|
||||
+so by scheduling a postMessage before scheduling the navigation. If the
|
||||
+navigation is synchronous, the internals API will be able to report the presence
|
||||
+of an url fragment immediately.</p>
|
||||
+<iframe src="http://localhost:8000/navigation/resources/postmessage-on-hashchange.html" onload="onloadFired()"></iframe>
|
||||
</body>
|
||||
</html>
|
||||
diff --git a/third_party/blink/web_tests/http/tests/navigation/same-origin-fragment-navigation-is-sync-expected.txt b/third_party/blink/web_tests/http/tests/navigation/same-origin-fragment-navigation-is-sync-expected.txt
|
||||
index c1c1143026cad5cfe51829a8c34d61c01a63ffbf..5a6ccc855e14417df8039f18dba7aa0474ff552d 100644
|
||||
--- a/third_party/blink/web_tests/http/tests/navigation/same-origin-fragment-navigation-is-sync-expected.txt
|
||||
+++ b/third_party/blink/web_tests/http/tests/navigation/same-origin-fragment-navigation-is-sync-expected.txt
|
||||
@@ -1,3 +1,4 @@
|
||||
+ALERT: iframe onload fired
|
||||
ALERT: PASS: url fragment has changed synchronously
|
||||
ALERT: PASS: scheduled postMessage() before hashchange triggered.
|
||||
ALERT: PASS: hashchange triggered after postMessage().
|
||||
diff --git a/third_party/blink/web_tests/http/tests/navigation/same-origin-fragment-navigation-is-sync.html b/third_party/blink/web_tests/http/tests/navigation/same-origin-fragment-navigation-is-sync.html
|
||||
index 0ffe3cc8759e8e0ff4df7cad66c93cd5e2cbbe69..2cb9143bfce9a28d8803b49cf6afa7403554cdf4 100644
|
||||
--- a/third_party/blink/web_tests/http/tests/navigation/same-origin-fragment-navigation-is-sync.html
|
||||
+++ b/third_party/blink/web_tests/http/tests/navigation/same-origin-fragment-navigation-is-sync.html
|
||||
@@ -36,6 +36,11 @@
|
||||
testRunner.notifyDone();
|
||||
}
|
||||
});
|
||||
+
|
||||
+ function onloadFired() {
|
||||
+ alert("iframe onload fired");
|
||||
+ testFragmentNavigation();
|
||||
+ }
|
||||
</script>
|
||||
</head>
|
||||
<body>
|
||||
@@ -43,6 +48,6 @@
|
||||
so by scheduling a postMessage before scheduling the navigation. If the
|
||||
navigation is synchronous, the internals API will be able to report the presence
|
||||
of an url fragment immediately.</p>
|
||||
- <iframe src="http://127.0.0.1:8000/navigation/resources/postmessage-on-hashchange.html" onload='testFragmentNavigation()'></iframe>
|
||||
+ <iframe src="http://127.0.0.1:8000/navigation/resources/postmessage-on-hashchange.html" onload='onloadFired()'></iframe>
|
||||
</body>
|
||||
</html>
|
||||
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;
|
||||
38
patches/chromium/fix_aspect_ratio_with_max_size.patch
Normal file
38
patches/chromium/fix_aspect_ratio_with_max_size.patch
Normal file
@@ -0,0 +1,38 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Cezary Kulakowski <cezary@openfin.co>
|
||||
Date: Tue, 11 May 2021 11:14:06 +0200
|
||||
Subject: fix: fix aspect ratio when max width/height is set
|
||||
|
||||
Add the native frame border size to the minimum and maximum size if
|
||||
the view reports its size as the client size. It allows to enlarge
|
||||
window to proper values when aspect ratio and max width/height are
|
||||
set. It also fixes DCHECK which was triggered when user tried to
|
||||
enlarge window above dimensions set during creation of the
|
||||
BrowserWindow.
|
||||
|
||||
diff --git a/ui/views/win/hwnd_message_handler.cc b/ui/views/win/hwnd_message_handler.cc
|
||||
index 18acd3724d486f7acdaa6aeedcd8ff3681729746..dc4e4755116935c527c34e98a27ce19de0e7b7bc 100644
|
||||
--- a/ui/views/win/hwnd_message_handler.cc
|
||||
+++ b/ui/views/win/hwnd_message_handler.cc
|
||||
@@ -3565,6 +3565,21 @@ void HWNDMessageHandler::SizeWindowToAspectRatio(UINT param,
|
||||
delegate_->GetMinMaxSize(&min_window_size, &max_window_size);
|
||||
min_window_size = delegate_->DIPToScreenSize(min_window_size);
|
||||
max_window_size = delegate_->DIPToScreenSize(max_window_size);
|
||||
+ // Add the native frame border size to the minimum and maximum size if the
|
||||
+ // view reports its size as the client size.
|
||||
+ if (delegate_->WidgetSizeIsClientSize()) {
|
||||
+ RECT client_rect, rect;
|
||||
+ GetClientRect(hwnd(), &client_rect);
|
||||
+ GetWindowRect(hwnd(), &rect);
|
||||
+ CR_DEFLATE_RECT(&rect, &client_rect);
|
||||
+ min_window_size.Enlarge(rect.right - rect.left,
|
||||
+ rect.bottom - rect.top);
|
||||
+ // Either axis may be zero, so enlarge them independently.
|
||||
+ if (max_window_size.width())
|
||||
+ max_window_size.Enlarge(rect.right - rect.left, 0);
|
||||
+ if (max_window_size.height())
|
||||
+ max_window_size.Enlarge(0, rect.bottom - rect.top);
|
||||
+ }
|
||||
gfx::SizeRectToAspectRatio(GetWindowResizeEdge(param), aspect_ratio_.value(),
|
||||
min_window_size, max_window_size, window_rect);
|
||||
}
|
||||
@@ -0,0 +1,85 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Shelley Vohr <shelley.vohr@gmail.com>
|
||||
Date: Mon, 17 Jan 2022 23:47:54 +0100
|
||||
Subject: fix: crash when saving edited PDF files
|
||||
|
||||
This commit fixes a crash that persists any time a user attempts to
|
||||
download an edited PDF. This was happening because the logic flow for
|
||||
downloading of any edited PDF triggers a call to
|
||||
chrome.fileSystem.chooseEntry, which we do not support and which
|
||||
therefore causes unmapped page access crashes.
|
||||
|
||||
This patch can be removed should we choose to support chrome.fileSystem
|
||||
or support it enough to fix the crash.
|
||||
|
||||
diff --git a/chrome/browser/resources/pdf/pdf_viewer.js b/chrome/browser/resources/pdf/pdf_viewer.js
|
||||
index 7b1e50624df15f4d77cbe5d014e4f57c7499a999..f3b8dcd32369e9f954a0791588ba4955c6cdae7e 100644
|
||||
--- a/chrome/browser/resources/pdf/pdf_viewer.js
|
||||
+++ b/chrome/browser/resources/pdf/pdf_viewer.js
|
||||
@@ -974,25 +974,12 @@ export class PDFViewerElement extends PDFViewerBaseElement {
|
||||
dataArray = [result.dataToSave];
|
||||
}
|
||||
|
||||
+ const a = document.createElement('a');
|
||||
+ a.download = this.attachments_[index].name;
|
||||
const blob = new Blob(dataArray);
|
||||
- const fileName = this.attachments_[index].name;
|
||||
- chrome.fileSystem.chooseEntry(
|
||||
- {type: 'saveFile', suggestedName: fileName}, entry => {
|
||||
- if (chrome.runtime.lastError) {
|
||||
- if (chrome.runtime.lastError.message !== 'User cancelled') {
|
||||
- console.error(
|
||||
- 'chrome.fileSystem.chooseEntry failed: ' +
|
||||
- chrome.runtime.lastError.message);
|
||||
- }
|
||||
- return;
|
||||
- }
|
||||
- entry.createWriter(writer => {
|
||||
- writer.write(blob);
|
||||
- // Unblock closing the window now that the user has saved
|
||||
- // successfully.
|
||||
- chrome.mimeHandlerPrivate.setShowBeforeUnloadDialog(false);
|
||||
- });
|
||||
- });
|
||||
+ a.href = URL.createObjectURL(blob);
|
||||
+ a.click();
|
||||
+ URL.revokeObjectURL(a.href);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1120,29 +1107,12 @@ export class PDFViewerElement extends PDFViewerBaseElement {
|
||||
fileName = fileName + '.pdf';
|
||||
}
|
||||
|
||||
- chrome.fileSystem.chooseEntry(
|
||||
- {
|
||||
- type: 'saveFile',
|
||||
- accepts: [{description: '*.pdf', extensions: ['pdf']}],
|
||||
- suggestedName: fileName
|
||||
- },
|
||||
- entry => {
|
||||
- if (chrome.runtime.lastError) {
|
||||
- if (chrome.runtime.lastError.message !== 'User cancelled') {
|
||||
- console.error(
|
||||
- 'chrome.fileSystem.chooseEntry failed: ' +
|
||||
- chrome.runtime.lastError.message);
|
||||
- }
|
||||
- return;
|
||||
- }
|
||||
- entry.createWriter(writer => {
|
||||
- writer.write(
|
||||
- new Blob([result.dataToSave], {type: 'application/pdf'}));
|
||||
- // Unblock closing the window now that the user has saved
|
||||
- // successfully.
|
||||
- chrome.mimeHandlerPrivate.setShowBeforeUnloadDialog(false);
|
||||
- });
|
||||
- });
|
||||
+ const a = document.createElement('a');
|
||||
+ a.download = fileName;
|
||||
+ const blob = new Blob([result.dataToSave], {type: 'application/pdf'});
|
||||
+ a.href = URL.createObjectURL(blob);
|
||||
+ a.click();
|
||||
+ URL.revokeObjectURL(a.href);
|
||||
|
||||
// <if expr="enable_ink">
|
||||
// Saving in Annotation mode is destructive: crbug.com/919364
|
||||
@@ -0,0 +1,127 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Justin Novosad <junov@chromium.org>
|
||||
Date: Fri, 14 Jan 2022 15:26:55 +0000
|
||||
Subject: Fix ImageBitmapRenderingContext interaction with software compositor.
|
||||
|
||||
Before this CL, there was an early exit condition that prevented
|
||||
texture-backed resources from being presented to the software compositor
|
||||
even when the texture backing is swiftshader. This meant that in some
|
||||
cases, ImageBitmaps that were created by webGL contexts would fail to
|
||||
render. Once the early exit removed, there were other bugs due to the
|
||||
fact that bitmaps were not being converted to N32 format before being
|
||||
dispatched to the software compositor. This could cause several types
|
||||
of rendering artifacts, including leaking bitmap data between contexts.
|
||||
|
||||
BUG=1283434
|
||||
|
||||
Change-Id: I6f353bc6301b79d7a4124445c85956125135f539
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3387268
|
||||
Reviewed-by: Juanmi Huertas <juanmihd@chromium.org>
|
||||
Commit-Queue: Justin Novosad <junov@chromium.org>
|
||||
Cr-Commit-Position: refs/heads/main@{#959192}
|
||||
|
||||
diff --git a/third_party/blink/renderer/platform/graphics/gpu/image_layer_bridge.cc b/third_party/blink/renderer/platform/graphics/gpu/image_layer_bridge.cc
|
||||
index 722c88e5704fc21fb711ffdd3c4179449de9303b..2b126c41c5e231b6b88f058eef564b9388c67267 100644
|
||||
--- a/third_party/blink/renderer/platform/graphics/gpu/image_layer_bridge.cc
|
||||
+++ b/third_party/blink/renderer/platform/graphics/gpu/image_layer_bridge.cc
|
||||
@@ -137,13 +137,9 @@ bool ImageLayerBridge::PrepareTransferableResource(
|
||||
|
||||
has_presented_since_last_set_image_ = true;
|
||||
|
||||
- bool gpu_compositing = SharedGpuContext::IsGpuCompositingEnabled();
|
||||
+ const bool gpu_compositing = SharedGpuContext::IsGpuCompositingEnabled();
|
||||
bool gpu_image = image_->IsTextureBacked();
|
||||
|
||||
- // Expect software images for software compositing.
|
||||
- if (!gpu_compositing && gpu_image)
|
||||
- return false;
|
||||
-
|
||||
// If the texture comes from a software image then it does not need to be
|
||||
// flipped.
|
||||
layer_->SetFlipped(gpu_image);
|
||||
@@ -210,14 +206,17 @@ bool ImageLayerBridge::PrepareTransferableResource(
|
||||
return false;
|
||||
|
||||
const gfx::Size size(image_->width(), image_->height());
|
||||
- viz::ResourceFormat resource_format = viz::RGBA_8888;
|
||||
- if (sk_image->colorType() == SkColorType::kRGBA_F16_SkColorType)
|
||||
- resource_format = viz::RGBA_F16;
|
||||
+
|
||||
+ // Always convert to N32 format. This is a constraint of the software
|
||||
+ // compositor.
|
||||
+ constexpr SkColorType dst_color_type = kN32_SkColorType;
|
||||
+ viz::ResourceFormat resource_format =
|
||||
+ viz::SkColorTypeToResourceFormat(dst_color_type);
|
||||
RegisteredBitmap registered =
|
||||
CreateOrRecycleBitmap(size, resource_format, bitmap_registrar);
|
||||
|
||||
SkImageInfo dst_info =
|
||||
- SkImageInfo::Make(size.width(), size.height(), sk_image->colorType(),
|
||||
+ SkImageInfo::Make(size.width(), size.height(), dst_color_type,
|
||||
kPremul_SkAlphaType, sk_image->refColorSpace());
|
||||
void* pixels = registered.bitmap->memory();
|
||||
|
||||
@@ -246,8 +245,8 @@ ImageLayerBridge::RegisteredBitmap ImageLayerBridge::CreateOrRecycleBitmap(
|
||||
recycled_bitmaps_.begin(), recycled_bitmaps_.end(),
|
||||
[&size, &format](const RegisteredBitmap& registered) {
|
||||
unsigned src_bytes_per_pixel =
|
||||
- (registered.bitmap->format() == viz::RGBA_8888) ? 4 : 8;
|
||||
- unsigned target_bytes_per_pixel = (format == viz::RGBA_8888) ? 4 : 8;
|
||||
+ viz::BitsPerPixel(registered.bitmap->format()) / 8;
|
||||
+ unsigned target_bytes_per_pixel = viz::BitsPerPixel(format) / 8;
|
||||
return (registered.bitmap->size().GetArea() * src_bytes_per_pixel !=
|
||||
size.GetArea() * target_bytes_per_pixel);
|
||||
});
|
||||
diff --git a/third_party/blink/web_tests/fast/canvas/bug1283434-expected.html b/third_party/blink/web_tests/fast/canvas/bug1283434-expected.html
|
||||
new file mode 100644
|
||||
index 0000000000000000000000000000000000000000..d0046a6c5ede6804497107318650f5f452b0d5e2
|
||||
--- /dev/null
|
||||
+++ b/third_party/blink/web_tests/fast/canvas/bug1283434-expected.html
|
||||
@@ -0,0 +1,11 @@
|
||||
+
|
||||
+<!doctype html>
|
||||
+<html>
|
||||
+<head>
|
||||
+</head>
|
||||
+<body>
|
||||
+<p>The two squares below should be filled in blue.</p>
|
||||
+<canvas id="c" width="100" height="100" style="background-color: #00f;"></canvas>
|
||||
+<canvas id="c2" width="100" height="100" style="background-color: #00f;"></canvas>
|
||||
+</body>
|
||||
+</html>
|
||||
\ No newline at end of file
|
||||
diff --git a/third_party/blink/web_tests/fast/canvas/bug1283434.html b/third_party/blink/web_tests/fast/canvas/bug1283434.html
|
||||
new file mode 100644
|
||||
index 0000000000000000000000000000000000000000..b07298cbcb356b7fb34e3923259c3365e3a976fb
|
||||
--- /dev/null
|
||||
+++ b/third_party/blink/web_tests/fast/canvas/bug1283434.html
|
||||
@@ -0,0 +1,28 @@
|
||||
+
|
||||
+<!doctype html>
|
||||
+<html>
|
||||
+<head>
|
||||
+</head>
|
||||
+<body>
|
||||
+<p>The two squares below should be filled in blue.</p>
|
||||
+<canvas id="c" width="100" height="100" style="background-color: red;"></canvas>
|
||||
+<canvas id="c2" width="100" height="100" style="background-color: red;"></canvas>
|
||||
+<script>
|
||||
+ const canvas = document.getElementById('c');
|
||||
+ const canvas2 = document.getElementById('c2');
|
||||
+ const renderer = canvas.getContext('bitmaprenderer');
|
||||
+ const renderer2 = canvas2.getContext('2d');
|
||||
+
|
||||
+ const temp_canvas = new OffscreenCanvas(640, 480);
|
||||
+ const gl = temp_canvas.getContext('webgl');
|
||||
+
|
||||
+ gl.clearColor(0.0, 0.0, 1.0, 1.0);
|
||||
+ gl.clear(gl.COLOR_BUFFER_BIT);
|
||||
+
|
||||
+ const bitmap = temp_canvas.transferToImageBitmap();
|
||||
+
|
||||
+ renderer2.drawImage(bitmap, 0, 0);
|
||||
+ renderer.transferFromImageBitmap(bitmap);
|
||||
+</script>
|
||||
+</body>
|
||||
+</html>
|
||||
\ No newline at end of file
|
||||
@@ -59,7 +59,7 @@ index 9aec54a3263d24491d24013a80b719dfc834ecd4..001a6cb2a5eb701351fa924109b43fab
|
||||
// true if register successfully, or false if 1) the specificied |accelerator|
|
||||
// has been registered by another caller or other native applications, or
|
||||
diff --git a/content/browser/media/media_keys_listener_manager_impl.cc b/content/browser/media/media_keys_listener_manager_impl.cc
|
||||
index 5938f75742b793868638e693a9a8c8dc686dfc46..1137ea6c6b2b14f912b400e3cc43dc6fd0243407 100644
|
||||
index 5938f75742b793868638e693a9a8c8dc686dfc46..7f30f3fdd2c63612232e31c331b26b17ad729efb 100644
|
||||
--- a/content/browser/media/media_keys_listener_manager_impl.cc
|
||||
+++ b/content/browser/media/media_keys_listener_manager_impl.cc
|
||||
@@ -55,7 +55,12 @@ bool MediaKeysListenerManagerImpl::StartWatchingMediaKey(
|
||||
@@ -76,32 +76,28 @@ index 5938f75742b793868638e693a9a8c8dc686dfc46..1137ea6c6b2b14f912b400e3cc43dc6f
|
||||
!media_keys_listener_->StartWatchingMediaKey(key_code)) {
|
||||
return false;
|
||||
}
|
||||
@@ -231,18 +236,16 @@ void MediaKeysListenerManagerImpl::StartListeningForMediaKeysIfNecessary() {
|
||||
media::AudioManager::GetGlobalAppName());
|
||||
@@ -232,18 +237,18 @@ void MediaKeysListenerManagerImpl::StartListeningForMediaKeysIfNecessary() {
|
||||
#endif
|
||||
|
||||
- if (system_media_controls_) {
|
||||
- system_media_controls_->AddObserver(this);
|
||||
- system_media_controls_notifier_ =
|
||||
- std::make_unique<SystemMediaControlsNotifier>(
|
||||
- system_media_controls_.get());
|
||||
if (system_media_controls_) {
|
||||
+ // This is required for proper functioning of MediaMetadata.
|
||||
system_media_controls_->AddObserver(this);
|
||||
system_media_controls_notifier_ =
|
||||
std::make_unique<SystemMediaControlsNotifier>(
|
||||
system_media_controls_.get());
|
||||
- } else {
|
||||
- // If we can't access system media controls, then directly listen for media
|
||||
- // key keypresses instead.
|
||||
- media_keys_listener_ = ui::MediaKeysListener::Create(
|
||||
- this, ui::MediaKeysListener::Scope::kGlobal);
|
||||
- DCHECK(media_keys_listener_);
|
||||
- }
|
||||
+ // This is required for proper functioning of MediaMetadata.
|
||||
+ system_media_controls_->AddObserver(this);
|
||||
+ system_media_controls_notifier_ =
|
||||
+ std::make_unique<SystemMediaControlsNotifier>(
|
||||
+ system_media_controls_.get());
|
||||
+
|
||||
}
|
||||
|
||||
+ // Directly listen for media key keypresses when using GlobalShortcuts.
|
||||
+ media_keys_listener_ = ui::MediaKeysListener::Create(
|
||||
+ this, ui::MediaKeysListener::Scope::kGlobal);
|
||||
+ DCHECK(media_keys_listener_);
|
||||
|
||||
+
|
||||
EnsureAuxiliaryServices();
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,57 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: clavin <cwatford@slack-corp.com>
|
||||
Date: Fri, 11 Feb 2022 15:05:42 -0700
|
||||
Subject: fix: non-client mouse tracking and message bubbling on windows
|
||||
|
||||
It is not known why, but for some reason calling |DefWindowProc| on the parent
|
||||
window handle causes a WM_NCMOUSELEAVE (non-client mouse exit) message to be
|
||||
sent to the parent window, even though |TrackMouseEvent| is never called on it.
|
||||
|
||||
This patch also adds some boilerplate for properly tracking non-client mouse
|
||||
messages in the legacy window handle layer.
|
||||
|
||||
These conditions are regularly hit with WCO-enabled windows on Windows.
|
||||
|
||||
diff --git a/content/browser/renderer_host/legacy_render_widget_host_win.cc b/content/browser/renderer_host/legacy_render_widget_host_win.cc
|
||||
index 8b196e1a10c96443a912eaaeb9327982618efa41..2f6939a6af34b901a8d1743a8559d5c3bfdb2d04 100644
|
||||
--- a/content/browser/renderer_host/legacy_render_widget_host_win.cc
|
||||
+++ b/content/browser/renderer_host/legacy_render_widget_host_win.cc
|
||||
@@ -288,12 +288,12 @@ LRESULT LegacyRenderWidgetHostHWND::OnMouseRange(UINT message,
|
||||
WPARAM w_param,
|
||||
LPARAM l_param,
|
||||
BOOL& handled) {
|
||||
- if (message == WM_MOUSEMOVE) {
|
||||
+ if (message == WM_MOUSEMOVE || message == WM_NCMOUSEMOVE) {
|
||||
if (!mouse_tracking_enabled_) {
|
||||
mouse_tracking_enabled_ = true;
|
||||
TRACKMOUSEEVENT tme;
|
||||
tme.cbSize = sizeof(tme);
|
||||
- tme.dwFlags = TME_LEAVE;
|
||||
+ tme.dwFlags = message == WM_NCMOUSEMOVE ? TME_NONCLIENT | TME_LEAVE : TME_LEAVE;
|
||||
tme.hwndTrack = hwnd();
|
||||
tme.dwHoverTime = 0;
|
||||
TrackMouseEvent(&tme);
|
||||
@@ -324,7 +324,10 @@ LRESULT LegacyRenderWidgetHostHWND::OnMouseRange(UINT message,
|
||||
// out of the picture.
|
||||
if (!handled &&
|
||||
(message >= WM_NCMOUSEMOVE && message <= WM_NCXBUTTONDBLCLK)) {
|
||||
- ret = ::DefWindowProc(GetParent(), message, w_param, l_param);
|
||||
+ // Send WM_NCMOUSEMOVE messages using the LegacyRenderWidgetHostHWND's
|
||||
+ // handle so mouse tracking on non-client areas doesn't break.
|
||||
+ HWND target = message == WM_NCMOUSEMOVE ? hwnd() : GetParent();
|
||||
+ ret = ::DefWindowProc(target, message, w_param, l_param);
|
||||
handled = TRUE;
|
||||
}
|
||||
}
|
||||
diff --git a/content/browser/renderer_host/legacy_render_widget_host_win.h b/content/browser/renderer_host/legacy_render_widget_host_win.h
|
||||
index 026e8b93602766e8d8e4a04f467b68ce3cea92de..83ca674adb6c6bf5e16d38b12aa33dddbf685bd8 100644
|
||||
--- a/content/browser/renderer_host/legacy_render_widget_host_win.h
|
||||
+++ b/content/browser/renderer_host/legacy_render_widget_host_win.h
|
||||
@@ -100,6 +100,7 @@ class CONTENT_EXPORT LegacyRenderWidgetHostHWND
|
||||
MESSAGE_HANDLER_EX(WM_NCHITTEST, OnNCHitTest)
|
||||
MESSAGE_RANGE_HANDLER(WM_NCMOUSEMOVE, WM_NCXBUTTONDBLCLK,
|
||||
OnMouseRange)
|
||||
+ MESSAGE_HANDLER_EX(WM_NCMOUSELEAVE, OnMouseLeave)
|
||||
MESSAGE_HANDLER_EX(WM_NCCALCSIZE, OnNCCalcSize)
|
||||
MESSAGE_HANDLER_EX(WM_SIZE, OnSize)
|
||||
MESSAGE_HANDLER_EX(WM_DESTROY, OnDestroy)
|
||||
47
patches/chromium/fix_preview_state_detection.patch
Normal file
47
patches/chromium/fix_preview_state_detection.patch
Normal file
@@ -0,0 +1,47 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Dominic Battre <battre@chromium.org>
|
||||
Date: Wed, 22 Dec 2021 16:25:16 +0000
|
||||
Subject: Fix preview state detection
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
|
||||
This CL fixes the preview state detection in some edge cases. See
|
||||
crbug.com/1261689#c23.
|
||||
|
||||
(cherry picked from commit e3aeadcf584ebb5d7f61cd141f9af317cb60cf21)
|
||||
|
||||
Fixed: 1261689
|
||||
Change-Id: Iefe27e2748acb4b524e8a0811973bdceda46089a
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3335637
|
||||
Reviewed-by: Mason Freed <masonf@chromium.org>
|
||||
Commit-Queue: Dominic Battré <battre@chromium.org>
|
||||
Cr-Original-Commit-Position: refs/heads/main@{#951313}
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3348406
|
||||
Auto-Submit: Dominic Battré <battre@chromium.org>
|
||||
Reviewed-by: Joey Arhar <jarhar@chromium.org>
|
||||
Commit-Queue: Joey Arhar <jarhar@chromium.org>
|
||||
Cr-Commit-Position: refs/branch-heads/4758@{#186}
|
||||
Cr-Branched-From: 4a2cf4baf90326df19c3ee70ff987960d59a386e-refs/heads/main@{#950365}
|
||||
|
||||
diff --git a/third_party/blink/renderer/core/dom/element.cc b/third_party/blink/renderer/core/dom/element.cc
|
||||
index daa9e25f645f9d554dd85ed4199bc80bf3a7e049..4bf8054f5b6382bbef85b83996dbb6b48dfc2f74 100644
|
||||
--- a/third_party/blink/renderer/core/dom/element.cc
|
||||
+++ b/third_party/blink/renderer/core/dom/element.cc
|
||||
@@ -36,6 +36,7 @@
|
||||
#include "third_party/blink/public/common/privacy_budget/identifiability_metric_builder.h"
|
||||
#include "third_party/blink/public/common/privacy_budget/identifiability_study_settings.h"
|
||||
#include "third_party/blink/public/mojom/scroll/scroll_into_view_params.mojom-blink.h"
|
||||
+#include "third_party/blink/public/web/web_autofill_state.h"
|
||||
#include "third_party/blink/renderer/bindings/core/v8/dictionary.h"
|
||||
#include "third_party/blink/renderer/bindings/core/v8/script_promise_resolver.h"
|
||||
#include "third_party/blink/renderer/bindings/core/v8/v8_get_inner_html_options.h"
|
||||
@@ -1560,7 +1561,7 @@ double Element::scrollTop() {
|
||||
// Don't disclose scroll position in preview state. See crbug.com/1261689.
|
||||
auto* select_element = DynamicTo<HTMLSelectElement>(this);
|
||||
if (select_element && !select_element->UsesMenuList() &&
|
||||
- !select_element->SuggestedValue().IsEmpty()) {
|
||||
+ select_element->GetAutofillState() == WebAutofillState::kPreviewed) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,553 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Robin Ebert <ebertrobin2002@gmail.com>
|
||||
Date: Tue, 22 Feb 2022 12:49:55 +0100
|
||||
Subject: Fixed terminate caused by binding to wrong version.
|
||||
|
||||
The Ozone/Wayland implementation had a few places where the Wayland
|
||||
objects were bound without proper checking for their versions. That was
|
||||
part of the technical debt not addressed before, and ended up causing
|
||||
the issue explained in the linked crbug: the compositor terminates the
|
||||
client that binds to the protocol that it does not actually support.
|
||||
|
||||
This patch fixes the issue by adding the necessary checks in all places
|
||||
where they were missing. Also a convenience macro for validating the
|
||||
version is proposed.
|
||||
|
||||
Backport of dd4c3ddadbb9869f59cee201a38e9ca3b9154f4d from chromium
|
||||
|
||||
diff --git a/ui/ozone/platform/wayland/common/wayland_object.cc b/ui/ozone/platform/wayland/common/wayland_object.cc
|
||||
index 0f21da447e43125c85b15a4254d7e047409e2e57..109fea03294a9bcbcc335d4c7d3250179f13f9bd 100644
|
||||
--- a/ui/ozone/platform/wayland/common/wayland_object.cc
|
||||
+++ b/ui/ozone/platform/wayland/common/wayland_object.cc
|
||||
@@ -29,6 +29,8 @@
|
||||
#include <xdg-shell-client-protocol.h>
|
||||
#include <xdg-shell-unstable-v6-client-protocol.h>
|
||||
|
||||
+#include "base/logging.h"
|
||||
+
|
||||
namespace wl {
|
||||
namespace {
|
||||
|
||||
@@ -71,6 +73,19 @@ void delete_touch(wl_touch* touch) {
|
||||
|
||||
} // namespace
|
||||
|
||||
+bool CanBind(uint32_t available_version,
|
||||
+ uint32_t min_version,
|
||||
+ uint32_t max_version) {
|
||||
+ if (available_version < min_version) {
|
||||
+ LOG(WARNING) << "Error in binding wayland interface."
|
||||
+ << available_version << ". The minimum supported version is "
|
||||
+ << min_version << ".";
|
||||
+ return false;
|
||||
+ }
|
||||
+
|
||||
+ return true;
|
||||
+}
|
||||
+
|
||||
void (*ObjectTraits<wl_cursor_theme>::deleter)(wl_cursor_theme*) =
|
||||
&wl_cursor_theme_destroy;
|
||||
|
||||
diff --git a/ui/ozone/platform/wayland/common/wayland_object.h b/ui/ozone/platform/wayland/common/wayland_object.h
|
||||
index 88a5c0551402131357168c788787a0fddb24d747..465ac9633841b297ecdfe31df4b569773fdf2918 100644
|
||||
--- a/ui/ozone/platform/wayland/common/wayland_object.h
|
||||
+++ b/ui/ozone/platform/wayland/common/wayland_object.h
|
||||
@@ -86,6 +86,16 @@ struct ObjectTraits<wl_proxy> {
|
||||
static void (*deleter)(void*);
|
||||
};
|
||||
|
||||
+// Checks the given |available_version| exposed by the server against
|
||||
+// |min_version| and |max_version| supported by the client.
|
||||
+// Returns false (with rendering a warning) if |available_version| is less than
|
||||
+// the minimum supported version.
|
||||
+// Returns true otherwise, renders an info message if |available_version| is
|
||||
+// greater than the maximum supported one.
|
||||
+bool CanBind(uint32_t available_version,
|
||||
+ uint32_t min_version,
|
||||
+ uint32_t max_version);
|
||||
+
|
||||
} // namespace wl
|
||||
|
||||
// Puts the forward declaration for struct TYPE and declares the template
|
||||
diff --git a/ui/ozone/platform/wayland/host/gtk_primary_selection_device_manager.cc b/ui/ozone/platform/wayland/host/gtk_primary_selection_device_manager.cc
|
||||
index 8822c0a57ebd5cdc5044c3746e6b17abd6898621..3dcb157031df12e36109bda1048cd0c57de23a41 100644
|
||||
--- a/ui/ozone/platform/wayland/host/gtk_primary_selection_device_manager.cc
|
||||
+++ b/ui/ozone/platform/wayland/host/gtk_primary_selection_device_manager.cc
|
||||
@@ -16,7 +16,7 @@
|
||||
namespace ui {
|
||||
|
||||
namespace {
|
||||
-constexpr uint32_t kMaxGtkPrimarySelectionDeviceManagerVersion = 1;
|
||||
+constexpr uint32_t kMinVersion = 1;
|
||||
}
|
||||
|
||||
// static
|
||||
@@ -32,12 +32,13 @@ void GtkPrimarySelectionDeviceManager::Instantiate(
|
||||
wl_registry* registry,
|
||||
uint32_t name,
|
||||
uint32_t version) {
|
||||
- if (connection->gtk_primary_selection_device_manager())
|
||||
- return;
|
||||
+ if (connection->gtk_primary_selection_device_manager() ||
|
||||
+ !wl::CanBind(version, kMinVersion, kMinVersion)) {
|
||||
+ return;
|
||||
+ }
|
||||
|
||||
- auto manager = wl::Bind<gtk_primary_selection_device_manager>(
|
||||
- registry, name,
|
||||
- std::min(version, kMaxGtkPrimarySelectionDeviceManagerVersion));
|
||||
+ auto manager = wl::Bind<gtk_primary_selection_device_manager>(registry, name,
|
||||
+ kMinVersion);
|
||||
if (!manager) {
|
||||
LOG(ERROR) << "Failed to bind gtk_primary_selection_device_manager";
|
||||
return;
|
||||
diff --git a/ui/ozone/platform/wayland/host/gtk_shell1.cc b/ui/ozone/platform/wayland/host/gtk_shell1.cc
|
||||
index 88126d9dd6e6770747059b77fb68f96b051176a7..20afad639e26d63c1e4c039f25a833deb9595425 100644
|
||||
--- a/ui/ozone/platform/wayland/host/gtk_shell1.cc
|
||||
+++ b/ui/ozone/platform/wayland/host/gtk_shell1.cc
|
||||
@@ -17,8 +17,8 @@ namespace {
|
||||
// gtk_shell1 exposes request_focus() since version 3. Below that, it is not
|
||||
// interesting for us, although it provides some shell integration that might be
|
||||
// useful.
|
||||
-constexpr uint32_t kMinGtkShell1Version = 3;
|
||||
-constexpr uint32_t kMaxGtkShell1Version = 4;
|
||||
+constexpr uint32_t kMinVersion = 3;
|
||||
+constexpr uint32_t kMaxVersion = 4;
|
||||
} // namespace
|
||||
|
||||
// static
|
||||
@@ -32,11 +32,13 @@ void GtkShell1::Instantiate(WaylandConnection* connection,
|
||||
wl_registry* registry,
|
||||
uint32_t name,
|
||||
uint32_t version) {
|
||||
- if (connection->gtk_shell1_ || version < kMinGtkShell1Version)
|
||||
- return;
|
||||
+ if (connection->gtk_shell1_ ||
|
||||
+ !wl::CanBind(version, kMinVersion, kMaxVersion)) {
|
||||
+ return;
|
||||
+ }
|
||||
|
||||
auto gtk_shell1 = wl::Bind<::gtk_shell1>(
|
||||
- registry, name, std::min(version, kMaxGtkShell1Version));
|
||||
+ registry, name, std::min(version, kMaxVersion));
|
||||
if (!gtk_shell1) {
|
||||
LOG(ERROR) << "Failed to bind gtk_shell1";
|
||||
return;
|
||||
diff --git a/ui/ozone/platform/wayland/host/org_kde_kwin_idle.cc b/ui/ozone/platform/wayland/host/org_kde_kwin_idle.cc
|
||||
index d990c810be430462cfe1a66460350fe1c548fbb8..ec225d49ecfbf0c349f15663d5acd3bc0620584f 100644
|
||||
--- a/ui/ozone/platform/wayland/host/org_kde_kwin_idle.cc
|
||||
+++ b/ui/ozone/platform/wayland/host/org_kde_kwin_idle.cc
|
||||
@@ -13,7 +13,7 @@ namespace ui {
|
||||
|
||||
namespace {
|
||||
|
||||
-constexpr uint32_t kMaxOrgKdeKwinIdleVersion = 1;
|
||||
+constexpr uint32_t kMinVersion = 1;
|
||||
|
||||
// After the system has gone idle, it will wait for this time before notifying
|
||||
// us. This reduces "jitter" of the idle/active state, but also adds some lag
|
||||
@@ -58,11 +58,13 @@ void OrgKdeKwinIdle::Instantiate(WaylandConnection* connection,
|
||||
wl_registry* registry,
|
||||
uint32_t name,
|
||||
uint32_t version) {
|
||||
- if (connection->org_kde_kwin_idle_)
|
||||
- return;
|
||||
+ if (connection->org_kde_kwin_idle_ ||
|
||||
+ !wl::CanBind(version, kMinVersion, kMinVersion)) {
|
||||
+ return;
|
||||
+ }
|
||||
|
||||
auto idle = wl::Bind<struct org_kde_kwin_idle>(
|
||||
- registry, name, std::min(version, kMaxOrgKdeKwinIdleVersion));
|
||||
+ registry, name, kMinVersion);
|
||||
if (!idle) {
|
||||
LOG(ERROR) << "Failed to bind to org_kde_kwin_idle global";
|
||||
return;
|
||||
diff --git a/ui/ozone/platform/wayland/host/wayland_data_device_manager.cc b/ui/ozone/platform/wayland/host/wayland_data_device_manager.cc
|
||||
index 036512a39fa776d3c76c8dc6e29163224838c30b..6acc02f8348e5aaf1b20c1064bb10d31c32da26d 100644
|
||||
--- a/ui/ozone/platform/wayland/host/wayland_data_device_manager.cc
|
||||
+++ b/ui/ozone/platform/wayland/host/wayland_data_device_manager.cc
|
||||
@@ -14,7 +14,8 @@
|
||||
namespace ui {
|
||||
|
||||
namespace {
|
||||
-constexpr uint32_t kMaxDeviceManagerVersion = 3;
|
||||
+constexpr uint32_t kMinVersion = 1;
|
||||
+constexpr uint32_t kMaxVersion = 3;
|
||||
}
|
||||
|
||||
// static
|
||||
@@ -28,11 +29,13 @@ void WaylandDataDeviceManager::Instantiate(WaylandConnection* connection,
|
||||
wl_registry* registry,
|
||||
uint32_t name,
|
||||
uint32_t version) {
|
||||
- if (connection->data_device_manager_)
|
||||
- return;
|
||||
+ if (connection->data_device_manager_ ||
|
||||
+ !wl::CanBind(version, kMinVersion, kMaxVersion)) {
|
||||
+ return;
|
||||
+ }
|
||||
|
||||
auto data_device_manager = wl::Bind<wl_data_device_manager>(
|
||||
- registry, name, std::min(version, kMaxDeviceManagerVersion));
|
||||
+ registry, name, std::min(version, kMaxVersion));
|
||||
if (!data_device_manager) {
|
||||
LOG(ERROR) << "Failed to bind to wl_data_device_manager global";
|
||||
return;
|
||||
diff --git a/ui/ozone/platform/wayland/host/wayland_drm.cc b/ui/ozone/platform/wayland/host/wayland_drm.cc
|
||||
index cb1062d47d035672e1b730fc7011185daaa162c2..852b516e1b8f86ef4e741d1a70f67541cba7def3 100644
|
||||
--- a/ui/ozone/platform/wayland/host/wayland_drm.cc
|
||||
+++ b/ui/ozone/platform/wayland/host/wayland_drm.cc
|
||||
@@ -17,7 +17,7 @@
|
||||
namespace ui {
|
||||
|
||||
namespace {
|
||||
-constexpr uint32_t kMinWlDrmVersion = 2;
|
||||
+constexpr uint32_t kMinVersion = 2;
|
||||
}
|
||||
|
||||
// static
|
||||
@@ -30,10 +30,12 @@ void WaylandDrm::Instantiate(WaylandConnection* connection,
|
||||
wl_registry* registry,
|
||||
uint32_t name,
|
||||
uint32_t version) {
|
||||
- if (connection->drm_ || version < kMinWlDrmVersion)
|
||||
- return;
|
||||
+ if (connection->drm_ ||
|
||||
+ !wl::CanBind(version, kMinVersion, kMinVersion)) {
|
||||
+ return;
|
||||
+ }
|
||||
|
||||
- auto wl_drm = wl::Bind<struct wl_drm>(registry, name, version);
|
||||
+ auto wl_drm = wl::Bind<struct wl_drm>(registry, name, kMinVersion);
|
||||
if (!wl_drm) {
|
||||
LOG(ERROR) << "Failed to bind wl_drm";
|
||||
return;
|
||||
diff --git a/ui/ozone/platform/wayland/host/wayland_output.cc b/ui/ozone/platform/wayland/host/wayland_output.cc
|
||||
index 0316abe49f9f6c289cfbac2ed94e47b93a7b1f1f..344974d33af6b97120e8143b1931ee59a08111f5 100644
|
||||
--- a/ui/ozone/platform/wayland/host/wayland_output.cc
|
||||
+++ b/ui/ozone/platform/wayland/host/wayland_output.cc
|
||||
@@ -13,7 +13,8 @@
|
||||
namespace ui {
|
||||
|
||||
namespace {
|
||||
-constexpr uint32_t kMinWlOutputVersion = 2;
|
||||
+// TODO(crbug.com/1279681): support newer versions.
|
||||
+constexpr uint32_t kMinVersion = 2;
|
||||
}
|
||||
|
||||
// static
|
||||
@@ -27,14 +28,11 @@ void WaylandOutput::Instantiate(WaylandConnection* connection,
|
||||
wl_registry* registry,
|
||||
uint32_t name,
|
||||
uint32_t version) {
|
||||
- if (version < kMinWlOutputVersion) {
|
||||
- LOG(ERROR)
|
||||
- << "Unable to bind to the unsupported wl_output object with version= "
|
||||
- << version << ". Minimum supported version is " << kMinWlOutputVersion;
|
||||
+ if (!wl::CanBind(version, kMinVersion, kMinVersion)) {
|
||||
return;
|
||||
}
|
||||
|
||||
- auto output = wl::Bind<wl_output>(registry, name, version);
|
||||
+ auto output = wl::Bind<wl_output>(registry, name, kMinVersion);
|
||||
if (!output) {
|
||||
LOG(ERROR) << "Failed to bind to wl_output global";
|
||||
return;
|
||||
diff --git a/ui/ozone/platform/wayland/host/wayland_shm.cc b/ui/ozone/platform/wayland/host/wayland_shm.cc
|
||||
index 27afbcfb25d9c73d4d832bd4ac9e57629451e35a..8f05786d7beb6a8f7458bf37cf0417d6a76b682a 100644
|
||||
--- a/ui/ozone/platform/wayland/host/wayland_shm.cc
|
||||
+++ b/ui/ozone/platform/wayland/host/wayland_shm.cc
|
||||
@@ -10,7 +10,7 @@
|
||||
namespace ui {
|
||||
|
||||
namespace {
|
||||
-constexpr uint32_t kMaxShmVersion = 1;
|
||||
+constexpr uint32_t kMinVersion = 1;
|
||||
constexpr uint32_t kShmFormat = WL_SHM_FORMAT_ARGB8888;
|
||||
} // namespace
|
||||
|
||||
@@ -24,11 +24,13 @@ void WaylandShm::Instantiate(WaylandConnection* connection,
|
||||
wl_registry* registry,
|
||||
uint32_t name,
|
||||
uint32_t version) {
|
||||
- if (connection->shm_)
|
||||
+ if (connection->shm_ ||
|
||||
+ !wl::CanBind(version, kMinVersion, kMinVersion)) {
|
||||
return;
|
||||
+ }
|
||||
|
||||
auto shm =
|
||||
- wl::Bind<wl_shm>(registry, name, std::min(version, kMaxShmVersion));
|
||||
+ wl::Bind<wl_shm>(registry, name, kMinVersion);
|
||||
if (!shm) {
|
||||
LOG(ERROR) << "Failed to bind to wl_shm global";
|
||||
return;
|
||||
diff --git a/ui/ozone/platform/wayland/host/wayland_zaura_shell.cc b/ui/ozone/platform/wayland/host/wayland_zaura_shell.cc
|
||||
index 9bc924f6baaf41288bfd616bb4f3eb4d37492c5f..29e32ed739233a91d57838e33f2fe3a7f5ecdaed 100644
|
||||
--- a/ui/ozone/platform/wayland/host/wayland_zaura_shell.cc
|
||||
+++ b/ui/ozone/platform/wayland/host/wayland_zaura_shell.cc
|
||||
@@ -18,7 +18,8 @@
|
||||
namespace ui {
|
||||
|
||||
namespace {
|
||||
-constexpr uint32_t kMaxAuraShellVersion = 22;
|
||||
+constexpr uint32_t kMinVersion = 1;
|
||||
+constexpr uint32_t kMaxVersion = 22;
|
||||
}
|
||||
|
||||
// static
|
||||
@@ -32,11 +33,13 @@ void WaylandZAuraShell::Instantiate(WaylandConnection* connection,
|
||||
wl_registry* registry,
|
||||
uint32_t name,
|
||||
uint32_t version) {
|
||||
- if (connection->zaura_shell_)
|
||||
- return;
|
||||
+ if (connection->zaura_shell_ ||
|
||||
+ !wl::CanBind(version, kMinVersion, kMaxVersion)) {
|
||||
+ return;
|
||||
+ }
|
||||
|
||||
auto zaura_shell = wl::Bind<struct zaura_shell>(
|
||||
- registry, name, std::min(version, kMaxAuraShellVersion));
|
||||
+ registry, name, std::min(version, kMaxVersion));
|
||||
if (!zaura_shell) {
|
||||
LOG(ERROR) << "Failed to bind zaura_shell";
|
||||
return;
|
||||
diff --git a/ui/ozone/platform/wayland/host/wayland_zcr_cursor_shapes.cc b/ui/ozone/platform/wayland/host/wayland_zcr_cursor_shapes.cc
|
||||
index 651e4f8154e47aeaac8860bf8ec58583cdb64862..28c43f2fc43be89b92496c5a5d084455c80c0cbd 100644
|
||||
--- a/ui/ozone/platform/wayland/host/wayland_zcr_cursor_shapes.cc
|
||||
+++ b/ui/ozone/platform/wayland/host/wayland_zcr_cursor_shapes.cc
|
||||
@@ -16,7 +16,7 @@
|
||||
namespace ui {
|
||||
|
||||
namespace {
|
||||
-constexpr uint32_t kMaxCursorShapesVersion = 1;
|
||||
+constexpr uint32_t kMinVersion = 1;
|
||||
}
|
||||
|
||||
using mojom::CursorType;
|
||||
@@ -32,11 +32,13 @@ void WaylandZcrCursorShapes::Instantiate(WaylandConnection* connection,
|
||||
wl_registry* registry,
|
||||
uint32_t name,
|
||||
uint32_t version) {
|
||||
- if (connection->zcr_cursor_shapes_)
|
||||
- return;
|
||||
+ if (connection->zcr_cursor_shapes_ ||
|
||||
+ !wl::CanBind(version, kMinVersion, kMinVersion)) {
|
||||
+ return;
|
||||
+ }
|
||||
|
||||
auto zcr_cursor_shapes = wl::Bind<zcr_cursor_shapes_v1>(
|
||||
- registry, name, std::min(version, kMaxCursorShapesVersion));
|
||||
+ registry, name, kMinVersion);
|
||||
if (!zcr_cursor_shapes) {
|
||||
LOG(ERROR) << "Failed to bind zcr_cursor_shapes_v1";
|
||||
return;
|
||||
diff --git a/ui/ozone/platform/wayland/host/wayland_zwp_linux_dmabuf.cc b/ui/ozone/platform/wayland/host/wayland_zwp_linux_dmabuf.cc
|
||||
index edc00fc587f1c6011171460e0c055191e642befb..34f93335267ba082a013e694e870bfe03e698fc1 100644
|
||||
--- a/ui/ozone/platform/wayland/host/wayland_zwp_linux_dmabuf.cc
|
||||
+++ b/ui/ozone/platform/wayland/host/wayland_zwp_linux_dmabuf.cc
|
||||
@@ -14,7 +14,8 @@
|
||||
namespace ui {
|
||||
|
||||
namespace {
|
||||
-constexpr uint32_t kMaxLinuxDmabufVersion = 3;
|
||||
+constexpr uint32_t kMinVersion = 1;
|
||||
+constexpr uint32_t kMaxVersion = 3;
|
||||
}
|
||||
|
||||
// static
|
||||
@@ -28,11 +29,13 @@ void WaylandZwpLinuxDmabuf::Instantiate(WaylandConnection* connection,
|
||||
wl_registry* registry,
|
||||
uint32_t name,
|
||||
uint32_t version) {
|
||||
- if (connection->zwp_dmabuf())
|
||||
- return;
|
||||
+ if (connection->zwp_dmabuf() ||
|
||||
+ !wl::CanBind(version, kMinVersion, kMaxVersion)) {
|
||||
+ return;
|
||||
+ }
|
||||
|
||||
auto zwp_linux_dmabuf = wl::Bind<zwp_linux_dmabuf_v1>(
|
||||
- registry, name, std::min(version, kMaxLinuxDmabufVersion));
|
||||
+ registry, name, std::min(version, kMaxVersion));
|
||||
if (!zwp_linux_dmabuf) {
|
||||
LOG(ERROR) << "Failed to bind zwp_linux_dmabuf_v1";
|
||||
return;
|
||||
diff --git a/ui/ozone/platform/wayland/host/wayland_zwp_pointer_constraints.cc b/ui/ozone/platform/wayland/host/wayland_zwp_pointer_constraints.cc
|
||||
index b0c35447917eea2c9031e24e7e03efd0999afba7..25f497db50fe1161e8bb7d162b711f583e6c482e 100644
|
||||
--- a/ui/ozone/platform/wayland/host/wayland_zwp_pointer_constraints.cc
|
||||
+++ b/ui/ozone/platform/wayland/host/wayland_zwp_pointer_constraints.cc
|
||||
@@ -15,7 +15,7 @@
|
||||
namespace ui {
|
||||
|
||||
namespace {
|
||||
-constexpr uint32_t kMinZwpPointerConstraintsVersion = 1;
|
||||
+constexpr uint32_t kMinVersion = 1;
|
||||
}
|
||||
|
||||
// static
|
||||
@@ -30,12 +30,12 @@ void WaylandZwpPointerConstraints::Instantiate(WaylandConnection* connection,
|
||||
uint32_t name,
|
||||
uint32_t version) {
|
||||
if (connection->wayland_zwp_pointer_constraints_ ||
|
||||
- version < kMinZwpPointerConstraintsVersion) {
|
||||
+ !wl::CanBind(version, kMinVersion, kMinVersion)) {
|
||||
return;
|
||||
}
|
||||
|
||||
auto zwp_pointer_constraints_v1 =
|
||||
- wl::Bind<struct zwp_pointer_constraints_v1>(registry, name, version);
|
||||
+ wl::Bind<struct zwp_pointer_constraints_v1>(registry, name, kMinVersion);
|
||||
if (!zwp_pointer_constraints_v1) {
|
||||
LOG(ERROR) << "Failed to bind wp_pointer_constraints_v1";
|
||||
return;
|
||||
diff --git a/ui/ozone/platform/wayland/host/wayland_zwp_pointer_gestures.cc b/ui/ozone/platform/wayland/host/wayland_zwp_pointer_gestures.cc
|
||||
index 86a0d3aabdf23f43463c5cc2c72b31fc31da8f04..ceac0b99d4534b64a67eff04c2ab10611656a0e8 100644
|
||||
--- a/ui/ozone/platform/wayland/host/wayland_zwp_pointer_gestures.cc
|
||||
+++ b/ui/ozone/platform/wayland/host/wayland_zwp_pointer_gestures.cc
|
||||
@@ -19,7 +19,7 @@
|
||||
namespace ui {
|
||||
|
||||
namespace {
|
||||
-constexpr uint32_t kMinZwpPointerGesturesVersion = 1;
|
||||
+constexpr uint32_t kMinVersion = 1;
|
||||
}
|
||||
|
||||
// static
|
||||
@@ -34,11 +34,12 @@ void WaylandZwpPointerGestures::Instantiate(WaylandConnection* connection,
|
||||
uint32_t name,
|
||||
uint32_t version) {
|
||||
if (connection->wayland_zwp_pointer_gestures_ ||
|
||||
- version < kMinZwpPointerGesturesVersion)
|
||||
+ !wl::CanBind(version, kMinVersion, kMinVersion)) {
|
||||
return;
|
||||
+ }
|
||||
|
||||
auto zwp_pointer_gestures_v1 =
|
||||
- wl::Bind<struct zwp_pointer_gestures_v1>(registry, name, version);
|
||||
+ wl::Bind<struct zwp_pointer_gestures_v1>(registry, name, kMinVersion);
|
||||
if (!zwp_pointer_gestures_v1) {
|
||||
LOG(ERROR) << "Failed to bind wp_pointer_gestures_v1";
|
||||
return;
|
||||
diff --git a/ui/ozone/platform/wayland/host/wayland_zwp_relative_pointer_manager.cc b/ui/ozone/platform/wayland/host/wayland_zwp_relative_pointer_manager.cc
|
||||
index 26c9cc387ae085d1bee35baab7a53e82be499799..0283b3630866fc4f32e16dc47a16fee5ac93e5a7 100644
|
||||
--- a/ui/ozone/platform/wayland/host/wayland_zwp_relative_pointer_manager.cc
|
||||
+++ b/ui/ozone/platform/wayland/host/wayland_zwp_relative_pointer_manager.cc
|
||||
@@ -14,7 +14,7 @@
|
||||
namespace ui {
|
||||
|
||||
namespace {
|
||||
-constexpr uint32_t kMinZwpRelativePointerManagerVersion = 1;
|
||||
+constexpr uint32_t kMinVersion = 1;
|
||||
}
|
||||
|
||||
// static
|
||||
@@ -31,11 +31,13 @@ void WaylandZwpRelativePointerManager::Instantiate(
|
||||
uint32_t name,
|
||||
uint32_t version) {
|
||||
if (connection->wayland_zwp_relative_pointer_manager_ ||
|
||||
- version < kMinZwpRelativePointerManagerVersion)
|
||||
+ !wl::CanBind(version, kMinVersion, kMinVersion)) {
|
||||
return;
|
||||
+ }
|
||||
|
||||
auto zwp_relative_pointer_manager_v1 =
|
||||
- wl::Bind<struct zwp_relative_pointer_manager_v1>(registry, name, version);
|
||||
+ wl::Bind<struct zwp_relative_pointer_manager_v1>(registry, name,
|
||||
+ kMinVersion);
|
||||
if (!zwp_relative_pointer_manager_v1) {
|
||||
LOG(ERROR) << "Failed to bind zwp_relative_pointer_manager_v1";
|
||||
return;
|
||||
diff --git a/ui/ozone/platform/wayland/host/xdg_foreign_wrapper.cc b/ui/ozone/platform/wayland/host/xdg_foreign_wrapper.cc
|
||||
index 43a419c125f13a749bd5769eba66fa052a5b300c..188ff4a61685a53705b2da2773cd583a1127fe22 100644
|
||||
--- a/ui/ozone/platform/wayland/host/xdg_foreign_wrapper.cc
|
||||
+++ b/ui/ozone/platform/wayland/host/xdg_foreign_wrapper.cc
|
||||
@@ -11,6 +11,8 @@
|
||||
#include "ui/ozone/platform/wayland/host/wayland_window.h"
|
||||
#include "ui/platform_window/platform_window_init_properties.h"
|
||||
|
||||
+constexpr uint32_t kMinVersion = 1;
|
||||
+
|
||||
namespace ui {
|
||||
|
||||
// static
|
||||
@@ -24,10 +26,12 @@ void XdgForeignWrapper::Instantiate(WaylandConnection* connection,
|
||||
wl_registry* registry,
|
||||
uint32_t name,
|
||||
uint32_t version) {
|
||||
- if (connection->xdg_foreign_)
|
||||
- return;
|
||||
+ if (connection->xdg_foreign_ ||
|
||||
+ !wl::CanBind(version, kMinVersion, kMinVersion)) {
|
||||
+ return;
|
||||
+ }
|
||||
|
||||
- auto zxdg_exporter = wl::Bind<zxdg_exporter_v1>(registry, name, version);
|
||||
+ auto zxdg_exporter = wl::Bind<zxdg_exporter_v1>(registry, name, kMinVersion);
|
||||
if (!zxdg_exporter) {
|
||||
LOG(ERROR) << "Failed to bind zxdg_exporter";
|
||||
return;
|
||||
diff --git a/ui/ozone/platform/wayland/host/zwp_idle_inhibit_manager.cc b/ui/ozone/platform/wayland/host/zwp_idle_inhibit_manager.cc
|
||||
index ef9cf6fd6934ffd20c7d8f80bcb3f08c9e2e43d9..678f08e63d29b2388292729c6b77dbf163a6d007 100644
|
||||
--- a/ui/ozone/platform/wayland/host/zwp_idle_inhibit_manager.cc
|
||||
+++ b/ui/ozone/platform/wayland/host/zwp_idle_inhibit_manager.cc
|
||||
@@ -12,7 +12,7 @@
|
||||
namespace ui {
|
||||
|
||||
namespace {
|
||||
-constexpr uint32_t kMaxZwpIdleInhibitManagerVersion = 1;
|
||||
+constexpr uint32_t kMinVersion = 1;
|
||||
}
|
||||
|
||||
// static
|
||||
@@ -26,11 +26,13 @@ void ZwpIdleInhibitManager::Instantiate(WaylandConnection* connection,
|
||||
wl_registry* registry,
|
||||
uint32_t name,
|
||||
uint32_t version) {
|
||||
- if (connection->zwp_idle_inhibit_manager_)
|
||||
- return;
|
||||
+ if (connection->zwp_idle_inhibit_manager_ ||
|
||||
+ !wl::CanBind(version, kMinVersion, kMinVersion)) {
|
||||
+ return;
|
||||
+ }
|
||||
|
||||
- auto manager = wl::Bind<zwp_idle_inhibit_manager_v1>(
|
||||
- registry, name, std::min(version, kMaxZwpIdleInhibitManagerVersion));
|
||||
+ auto manager =
|
||||
+ wl::Bind<zwp_idle_inhibit_manager_v1>(registry, name, kMinVersion);
|
||||
if (!manager) {
|
||||
LOG(ERROR) << "Failed to bind zwp_idle_inhibit_manager_v1";
|
||||
return;
|
||||
diff --git a/ui/ozone/platform/wayland/host/zwp_primary_selection_device_manager.cc b/ui/ozone/platform/wayland/host/zwp_primary_selection_device_manager.cc
|
||||
index 0bae8670c33bc2998e29613e7647c167b4a3b957..e7a138942c955ce432e75d155b6a80b455d3243e 100644
|
||||
--- a/ui/ozone/platform/wayland/host/zwp_primary_selection_device_manager.cc
|
||||
+++ b/ui/ozone/platform/wayland/host/zwp_primary_selection_device_manager.cc
|
||||
@@ -16,7 +16,7 @@
|
||||
namespace ui {
|
||||
|
||||
namespace {
|
||||
-constexpr uint32_t kMaxGtkPrimarySelectionDeviceManagerVersion = 1;
|
||||
+constexpr uint32_t kMinVersion = 1;
|
||||
} // namespace
|
||||
|
||||
// static
|
||||
@@ -32,12 +32,12 @@ void ZwpPrimarySelectionDeviceManager::Instantiate(
|
||||
wl_registry* registry,
|
||||
uint32_t name,
|
||||
uint32_t version) {
|
||||
- if (connection->zwp_primary_selection_device_manager_)
|
||||
- return;
|
||||
-
|
||||
+ if (connection->zwp_primary_selection_device_manager_ ||
|
||||
+ !wl::CanBind(version, kMinVersion, kMinVersion)) {
|
||||
+ return;
|
||||
+ }
|
||||
auto manager = wl::Bind<zwp_primary_selection_device_manager_v1>(
|
||||
- registry, name,
|
||||
- std::min(version, kMaxGtkPrimarySelectionDeviceManagerVersion));
|
||||
+ registry, name, kMinVersion);
|
||||
if (!manager) {
|
||||
LOG(ERROR) << "Failed to bind zwp_primary_selection_device_manager_v1";
|
||||
return;
|
||||
@@ -0,0 +1,68 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Robin Ebert <ebertrobin2002@gmail.com>
|
||||
Date: Tue, 22 Feb 2022 18:12:22 +0100
|
||||
Subject: Follow wayland specification regarding xkb keymap.
|
||||
|
||||
The wayland specification expects client to mmap the xkb keymap file descriptor with MAP_PRIVATE.
|
||||
This fixes mapping issues regarding file descriptor permissions.
|
||||
|
||||
diff --git a/ui/ozone/platform/wayland/host/wayland_keyboard.cc b/ui/ozone/platform/wayland/host/wayland_keyboard.cc
|
||||
index 272322210b59228e5faa606101957c48c6371249..1c661e1ed92428f7c810fe4c041e91a08a0901e5 100644
|
||||
--- a/ui/ozone/platform/wayland/host/wayland_keyboard.cc
|
||||
+++ b/ui/ozone/platform/wayland/host/wayland_keyboard.cc
|
||||
@@ -4,11 +4,12 @@
|
||||
|
||||
#include "ui/ozone/platform/wayland/host/wayland_keyboard.h"
|
||||
|
||||
+#include <sys/mman.h>
|
||||
+
|
||||
#include <utility>
|
||||
|
||||
#include "base/files/scoped_file.h"
|
||||
#include "base/logging.h"
|
||||
-#include "base/memory/unsafe_shared_memory_region.h"
|
||||
#include "base/unguessable_token.h"
|
||||
#include "ui/base/buildflags.h"
|
||||
#include "ui/events/base_event_utils.h"
|
||||
@@ -111,26 +112,28 @@ WaylandKeyboard::~WaylandKeyboard() {
|
||||
void WaylandKeyboard::Keymap(void* data,
|
||||
wl_keyboard* obj,
|
||||
uint32_t format,
|
||||
- int32_t keymap_fd,
|
||||
+ int32_t fd,
|
||||
uint32_t size) {
|
||||
WaylandKeyboard* keyboard = static_cast<WaylandKeyboard*>(data);
|
||||
DCHECK(keyboard);
|
||||
|
||||
- base::ScopedFD fd(keymap_fd);
|
||||
- auto length = size - 1;
|
||||
- auto shmen = base::subtle::PlatformSharedMemoryRegion::Take(
|
||||
- std::move(fd), base::subtle::PlatformSharedMemoryRegion::Mode::kUnsafe,
|
||||
- length, base::UnguessableToken::Create());
|
||||
- auto mapped_memory =
|
||||
- base::UnsafeSharedMemoryRegion::Deserialize(std::move(shmen)).Map();
|
||||
- const char* keymap = mapped_memory.GetMemoryAs<char>();
|
||||
+ if (!data || format != WL_KEYBOARD_KEYMAP_FORMAT_XKB_V1) {
|
||||
+ return;
|
||||
+ }
|
||||
|
||||
- if (!keymap || format != WL_KEYBOARD_KEYMAP_FORMAT_XKB_V1)
|
||||
+ void* keymap = mmap(nullptr, size, PROT_READ, MAP_PRIVATE, fd, 0);
|
||||
+ if (keymap == MAP_FAILED) {
|
||||
+ DPLOG(ERROR) << "Failed to map XKB keymap.";
|
||||
return;
|
||||
+ }
|
||||
|
||||
- bool success = keyboard->layout_engine_->SetCurrentLayoutFromBuffer(
|
||||
- keymap, mapped_memory.size());
|
||||
- DCHECK(success) << "Failed to set the XKB keyboard mapping.";
|
||||
+ const char* keymap_string = static_cast<const char*>(keymap);
|
||||
+ if (!keyboard->layout_engine_->SetCurrentLayoutFromBuffer(
|
||||
+ keymap_string, strnlen(keymap_string, size))) {
|
||||
+ DLOG(ERROR) << "Failed to set XKB keymap.";
|
||||
+ }
|
||||
+ munmap(keymap, size);
|
||||
+ close(fd);
|
||||
}
|
||||
|
||||
void WaylandKeyboard::Enter(void* data,
|
||||
@@ -0,0 +1,135 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Rune Lillesveen <futhark@chromium.org>
|
||||
Date: Fri, 15 Oct 2021 14:33:17 +0000
|
||||
Subject: Handle PotentiallyDanglingMarkup() for CSSImageValue
|
||||
|
||||
The flag was lost in the KURL -> String -> KURL conversions. Store the
|
||||
flag on CSSImageValue and always re-resolve from the original relative
|
||||
url before fetching when that flag is set. The blocking happens in
|
||||
BaseFetchContext::CanRequestInternal().
|
||||
|
||||
Bug: 1039885
|
||||
Change-Id: Ia5777739a0ee0bee591163873926d19e0ea014bf
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3226142
|
||||
Reviewed-by: Anders Hartvoll Ruud <andruud@chromium.org>
|
||||
Reviewed-by: Mike West <mkwst@chromium.org>
|
||||
Commit-Queue: Rune Lillesveen <futhark@chromium.org>
|
||||
Cr-Commit-Position: refs/heads/main@{#932004}
|
||||
|
||||
diff --git a/third_party/blink/renderer/core/css/build.gni b/third_party/blink/renderer/core/css/build.gni
|
||||
index d170dc0a9cdb6e7cfcd0979b8a4832e4fc8059f8..363301d60de1d206669a29dc27b9c58ec3d68c7a 100644
|
||||
--- a/third_party/blink/renderer/core/css/build.gni
|
||||
+++ b/third_party/blink/renderer/core/css/build.gni
|
||||
@@ -638,6 +638,7 @@ blink_core_tests_css = [
|
||||
"css_font_face_source_test.cc",
|
||||
"css_gradient_value_test.cc",
|
||||
"css_id_selector_value_test.cc",
|
||||
+ "css_image_value_test.cc",
|
||||
"css_invalid_variable_value_test.cc",
|
||||
"css_light_dark_value_pair_test.cc",
|
||||
"css_math_expression_node_test.cc",
|
||||
diff --git a/third_party/blink/renderer/core/css/css_image_value.cc b/third_party/blink/renderer/core/css/css_image_value.cc
|
||||
index 81fe3aa1175a31d5c6f3611ec6bd2a27f71e900d..732b48f787d782779e5fea8bf60a55ca3f7fe95d 100644
|
||||
--- a/third_party/blink/renderer/core/css/css_image_value.cc
|
||||
+++ b/third_party/blink/renderer/core/css/css_image_value.cc
|
||||
@@ -51,7 +51,8 @@ CSSImageValue::CSSImageValue(const AtomicString& raw_value,
|
||||
absolute_url_(url.GetString()),
|
||||
cached_image_(image),
|
||||
origin_clean_(origin_clean),
|
||||
- is_ad_related_(is_ad_related) {}
|
||||
+ is_ad_related_(is_ad_related),
|
||||
+ potentially_dangling_markup_(url.PotentiallyDanglingMarkup()) {}
|
||||
|
||||
CSSImageValue::~CSSImageValue() = default;
|
||||
|
||||
@@ -59,7 +60,17 @@ FetchParameters CSSImageValue::PrepareFetch(
|
||||
const Document& document,
|
||||
FetchParameters::ImageRequestBehavior image_request_behavior,
|
||||
CrossOriginAttributeValue cross_origin) const {
|
||||
- ResourceRequest resource_request(absolute_url_);
|
||||
+ // The PotentiallyDanglingMarkup() flag is lost when storing the absolute url
|
||||
+ // as a string from which the KURL is constructed here.
|
||||
+ // The url passed into the constructor had the PotentiallyDanglingMarkup flag
|
||||
+ // set. That information needs to be passed on to the fetch code to block such
|
||||
+ // resources from loading.
|
||||
+ KURL request_url = potentially_dangling_markup_
|
||||
+ ? document.CompleteURL(relative_url_)
|
||||
+ : KURL(absolute_url_);
|
||||
+ SECURITY_CHECK(request_url.PotentiallyDanglingMarkup() ==
|
||||
+ potentially_dangling_markup_);
|
||||
+ ResourceRequest resource_request(request_url);
|
||||
resource_request.SetReferrerPolicy(
|
||||
ReferrerUtils::MojoReferrerPolicyResolveDefault(
|
||||
referrer_.referrer_policy));
|
||||
diff --git a/third_party/blink/renderer/core/css/css_image_value.h b/third_party/blink/renderer/core/css/css_image_value.h
|
||||
index fca1d73c764412d2014bfd1fe4775937794c9e2d..f414195f4a543fb3f47c1fef3799161d13495507 100644
|
||||
--- a/third_party/blink/renderer/core/css/css_image_value.h
|
||||
+++ b/third_party/blink/renderer/core/css/css_image_value.h
|
||||
@@ -102,6 +102,11 @@ class CORE_EXPORT CSSImageValue : public CSSValue {
|
||||
|
||||
// Whether this was created by an ad-related CSSParserContext.
|
||||
const bool is_ad_related_;
|
||||
+
|
||||
+ // The url passed into the constructor had the PotentiallyDanglingMarkup flag
|
||||
+ // set. That information needs to be passed on to the fetch code to block such
|
||||
+ // resources from loading.
|
||||
+ const bool potentially_dangling_markup_;
|
||||
};
|
||||
|
||||
template <>
|
||||
diff --git a/third_party/blink/renderer/core/css/css_image_value_test.cc b/third_party/blink/renderer/core/css/css_image_value_test.cc
|
||||
new file mode 100644
|
||||
index 0000000000000000000000000000000000000000..83415bd586e3187287dcb020ddafe4c7f8671a61
|
||||
--- /dev/null
|
||||
+++ b/third_party/blink/renderer/core/css/css_image_value_test.cc
|
||||
@@ -0,0 +1,50 @@
|
||||
+// Copyright 2021 The Chromium Authors. All rights reserved.
|
||||
+// Use of this source code is governed by a BSD-style license that can be
|
||||
+// found in the LICENSE file.
|
||||
+
|
||||
+#include "third_party/blink/renderer/core/css/css_image_value.h"
|
||||
+
|
||||
+#include "testing/gtest/include/gtest/gtest.h"
|
||||
+#include "third_party/blink/renderer/core/dom/document.h"
|
||||
+#include "third_party/blink/renderer/core/dom/element.h"
|
||||
+#include "third_party/blink/renderer/core/dom/node_computed_style.h"
|
||||
+#include "third_party/blink/renderer/core/loader/resource/image_resource_content.h"
|
||||
+#include "third_party/blink/renderer/core/style/computed_style.h"
|
||||
+#include "third_party/blink/renderer/core/testing/sim/sim_request.h"
|
||||
+#include "third_party/blink/renderer/core/testing/sim/sim_test.h"
|
||||
+#include "third_party/blink/renderer/platform/testing/unit_test_helpers.h"
|
||||
+
|
||||
+namespace blink {
|
||||
+
|
||||
+class CSSImageValueTest : public SimTest {};
|
||||
+
|
||||
+TEST_F(CSSImageValueTest, BlockPotentiallyDanglingMarkup) {
|
||||
+ SimRequest main_resource("https://example.com", "text/html");
|
||||
+
|
||||
+ LoadURL("https://example.com");
|
||||
+
|
||||
+ main_resource.Complete(R"HTML(
|
||||
+ <!doctype html>
|
||||
+ <table id="t1" background="ht
|
||||
+ tps://example.com/y<ay?foo"><td>XXX</td></table>
|
||||
+ <table id="t2" background="ht
|
||||
+ tps://example.com/y<ay?bar#boo"><td>XXX</td></table>
|
||||
+ )HTML");
|
||||
+
|
||||
+ test::RunPendingTasks();
|
||||
+ Compositor().BeginFrame();
|
||||
+
|
||||
+ auto* t1 = GetDocument().getElementById("t1");
|
||||
+ ImageResourceContent* content1 =
|
||||
+ t1->ComputedStyleRef().BackgroundLayers().GetImage()->CachedImage();
|
||||
+ ASSERT_TRUE(content1);
|
||||
+ EXPECT_TRUE(content1->ErrorOccurred());
|
||||
+
|
||||
+ auto* t2 = GetDocument().getElementById("t2");
|
||||
+ ImageResourceContent* content2 =
|
||||
+ t2->ComputedStyleRef().BackgroundLayers().GetImage()->CachedImage();
|
||||
+ ASSERT_TRUE(content2);
|
||||
+ EXPECT_TRUE(content2->ErrorOccurred());
|
||||
+}
|
||||
+
|
||||
+} // namespace blink
|
||||
62
patches/chromium/introduce_crossthreadcopier_skbitmap.patch
Normal file
62
patches/chromium/introduce_crossthreadcopier_skbitmap.patch
Normal file
@@ -0,0 +1,62 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Yutaka Hirano <yhirano@chromium.org>
|
||||
Date: Tue, 9 Nov 2021 05:02:50 +0000
|
||||
Subject: Introduce CrossThreadCopier<SkBitmap>
|
||||
|
||||
Allow immutable SkBitmap to be transferred across threads.
|
||||
|
||||
(cherry picked from commit fd794ad56432870e462aab9d62e4f059169c1a5f)
|
||||
|
||||
Bug: 1241091
|
||||
Change-Id: Ia771893245ef2fc1acb05cd4906d64bf2dd406fe
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3244824
|
||||
Reviewed-by: danakj <danakj@chromium.org>
|
||||
Reviewed-by: Florin Malita <fmalita@chromium.org>
|
||||
Commit-Queue: Yutaka Hirano <yhirano@chromium.org>
|
||||
Cr-Original-Commit-Position: refs/heads/main@{#936435}
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3267808
|
||||
Bot-Commit: Rubber Stamper <rubber-stamper@appspot.gserviceaccount.com>
|
||||
Reviewed-by: Kentaro Hara <haraken@chromium.org>
|
||||
Cr-Commit-Position: refs/branch-heads/4664@{#887}
|
||||
Cr-Branched-From: 24dc4ee75e01a29d390d43c9c264372a169273a7-refs/heads/main@{#929512}
|
||||
|
||||
diff --git a/third_party/blink/renderer/platform/graphics/skia/skia_utils.h b/third_party/blink/renderer/platform/graphics/skia/skia_utils.h
|
||||
index 0b3efb14964b44ef0929fe33d37cec154d7410b2..e4bde78252c90ecd19655e8c552a2a39299dff75 100644
|
||||
--- a/third_party/blink/renderer/platform/graphics/skia/skia_utils.h
|
||||
+++ b/third_party/blink/renderer/platform/graphics/skia/skia_utils.h
|
||||
@@ -39,7 +39,9 @@
|
||||
#include "third_party/blink/renderer/platform/graphics/image.h"
|
||||
#include "third_party/blink/renderer/platform/platform_export.h"
|
||||
#include "third_party/blink/renderer/platform/transforms/affine_transform.h"
|
||||
+#include "third_party/blink/renderer/platform/wtf/cross_thread_copier.h"
|
||||
#include "third_party/blink/renderer/platform/wtf/math_extras.h"
|
||||
+#include "third_party/skia/include/core/SkBitmap.h"
|
||||
#include "third_party/skia/include/core/SkCanvas.h"
|
||||
#include "third_party/skia/include/core/SkColor.h"
|
||||
#include "third_party/skia/include/core/SkData.h"
|
||||
@@ -200,4 +202,25 @@ PLATFORM_EXPORT sk_sp<SkData> TryAllocateSkData(size_t size);
|
||||
|
||||
} // namespace blink
|
||||
|
||||
+namespace WTF {
|
||||
+
|
||||
+// We define CrossThreadCopier<SKBitMap> here because we cannot include skia
|
||||
+// headers in platform/wtf.
|
||||
+template <>
|
||||
+struct CrossThreadCopier<SkBitmap> {
|
||||
+ STATIC_ONLY(CrossThreadCopier);
|
||||
+
|
||||
+ using Type = SkBitmap;
|
||||
+ static SkBitmap Copy(const SkBitmap& bitmap) {
|
||||
+ CHECK(bitmap.isImmutable()) << "Only immutable bitmaps can be transferred.";
|
||||
+ return bitmap;
|
||||
+ }
|
||||
+ static SkBitmap Copy(SkBitmap&& bitmap) {
|
||||
+ CHECK(bitmap.isImmutable()) << "Only immutable bitmaps can be transferred.";
|
||||
+ return std::move(bitmap);
|
||||
+ }
|
||||
+};
|
||||
+
|
||||
+} // namespace WTF
|
||||
+
|
||||
#endif // THIRD_PARTY_BLINK_RENDERER_PLATFORM_GRAPHICS_SKIA_SKIA_UTILS_H_
|
||||
@@ -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 fc723d2dd83aae8f2b1abdf9d5a00990bbee5293..04f2b584d20a37c0b7bd2fb6a0d3a7095f7d8a38 100644
|
||||
--- a/third_party/blink/renderer/platform/blob/blob_bytes_provider.cc
|
||||
+++ b/third_party/blink/renderer/platform/blob/blob_bytes_provider.cc
|
||||
@@ -31,13 +31,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,
|
||||
@@ -45,6 +42,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;
|
||||
@@ -84,15 +83,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.
|
||||
@@ -118,31 +120,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() {
|
||||
@@ -150,6 +129,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());
|
||||
@@ -158,6 +139,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());
|
||||
@@ -166,8 +149,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;
|
||||
@@ -178,9 +185,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,
|
||||
@@ -188,7 +196,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);
|
||||
@@ -256,10 +264,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 59b019a6ce9c6db896ab20f4684e8db117c289f8..eb4f778e72dcc32043628d5f03da17d27f34d062 100644
|
||||
--- a/third_party/blink/renderer/platform/blob/blob_bytes_provider.h
|
||||
+++ b/third_party/blink/renderer/platform/blob/blob_bytes_provider.h
|
||||
@@ -5,6 +5,7 @@
|
||||
#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_BLOB_BLOB_BYTES_PROVIDER_H_
|
||||
#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_BLOB_BLOB_BYTES_PROVIDER_H_
|
||||
|
||||
+#include "base/sequence_checker.h"
|
||||
#include "base/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"
|
||||
@@ -16,8 +17,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:
|
||||
@@ -25,19 +26,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;
|
||||
@@ -50,17 +49,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 b62dca5e303898fbdbc4c931dfcbc7361504194a..75c769665148d8530742586f4cdd6eb98cf96e50 100644
|
||||
--- a/third_party/blink/renderer/platform/blob/blob_data.cc
|
||||
+++ b/third_party/blink/renderer/platform/blob/blob_data.cc
|
||||
@@ -106,6 +106,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_);
|
||||
}
|
||||
|
||||
@@ -140,16 +146,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;
|
||||
@@ -273,6 +269,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) {
|
||||
@@ -284,9 +281,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 fa905f87ed4cee14909827e8f078f51bb91cfa61..805da754eb510224f67f719bb43ab281d702f5fb 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 8f1d08efa8e505fdb098742bd5b778a8b2b82213..9b8927b18bbe261afa2990ef7695cc33bdea53c5 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_);
|
||||
@@ -0,0 +1,420 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Marijn Kruisselbrink <mek@chromium.org>
|
||||
Date: Tue, 16 Nov 2021 22:16:15 +0000
|
||||
Subject: M96: [FileAPI] Move origin checks in BlobURLStore sooner.
|
||||
|
||||
Rather than waiting to verify if a valid origin was passed in until
|
||||
register/revoke time, check if the origin is valid at the time the
|
||||
mojo interface is requested. This avoids the need to pass the
|
||||
delegate on to BlobURLStoreImpl, further decoupling this from
|
||||
BlobRegistryImpl.
|
||||
|
||||
(cherry picked from commit 15cfa2bed3ce9dcdd0a06d3cd3b8330e3591acdc)
|
||||
|
||||
Bug: 1262183
|
||||
Change-Id: I4889685d03501158abfe4f87c647dc468d005f78
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3264353
|
||||
Commit-Queue: Marijn Kruisselbrink <mek@chromium.org>
|
||||
Reviewed-by: Alex Moshchuk <alexmos@chromium.org>
|
||||
Cr-Original-Commit-Position: refs/heads/main@{#940015}
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3285385
|
||||
Bot-Commit: Rubber Stamper <rubber-stamper@appspot.gserviceaccount.com>
|
||||
Cr-Commit-Position: refs/branch-heads/4664@{#1078}
|
||||
Cr-Branched-From: 24dc4ee75e01a29d390d43c9c264372a169273a7-refs/heads/main@{#929512}
|
||||
|
||||
diff --git a/chrome/browser/chrome_security_exploit_browsertest.cc b/chrome/browser/chrome_security_exploit_browsertest.cc
|
||||
index 29bccb2da2c4e49029ad06c73f82d77e8863cb76..b6acbfe9f5a07632992f9506debaf4338852413c 100644
|
||||
--- a/chrome/browser/chrome_security_exploit_browsertest.cc
|
||||
+++ b/chrome/browser/chrome_security_exploit_browsertest.cc
|
||||
@@ -488,8 +488,8 @@ IN_PROC_BROWSER_TEST_F(ChromeSecurityExploitBrowserTestMojoBlobURLs,
|
||||
|
||||
// If the process is killed, this test passes.
|
||||
EXPECT_EQ(
|
||||
- "Received bad user message: Non committable URL passed to "
|
||||
- "BlobURLStore::Register",
|
||||
+ "Received bad user message: "
|
||||
+ "URL with invalid origin passed to BlobURLStore::Register",
|
||||
crash_observer.Wait());
|
||||
}
|
||||
|
||||
@@ -531,7 +531,7 @@ IN_PROC_BROWSER_TEST_F(ChromeSecurityExploitBrowserTestMojoBlobURLs,
|
||||
|
||||
// If the process is killed, this test passes.
|
||||
EXPECT_EQ(
|
||||
- "Received bad user message: Non committable URL passed to "
|
||||
- "BlobURLStore::Register",
|
||||
+ "Received bad user message: "
|
||||
+ "URL with invalid origin passed to BlobURLStore::Register",
|
||||
crash_observer.Wait());
|
||||
}
|
||||
diff --git a/content/browser/blob_storage/blob_url_unittest.cc b/content/browser/blob_storage/blob_url_unittest.cc
|
||||
index 727721091b78fd0e8478f372a55e78bfb993e691..dc5068e3f65ff58f9b00d50efd003649e4167430 100644
|
||||
--- a/content/browser/blob_storage/blob_url_unittest.cc
|
||||
+++ b/content/browser/blob_storage/blob_url_unittest.cc
|
||||
@@ -187,15 +187,14 @@ class BlobURLTest : public testing::Test {
|
||||
|
||||
void TestRequest(const std::string& method,
|
||||
const net::HttpRequestHeaders& extra_headers) {
|
||||
- GURL url("blob:blah");
|
||||
+ auto origin = url::Origin::Create(GURL("https://example.com"));
|
||||
+ auto url = GURL("blob:" + origin.Serialize() + "/id1");
|
||||
network::ResourceRequest request;
|
||||
request.url = url;
|
||||
request.method = method;
|
||||
request.headers = extra_headers;
|
||||
|
||||
- storage::MockBlobRegistryDelegate delegate;
|
||||
- storage::BlobURLStoreImpl url_store(blob_url_registry_.AsWeakPtr(),
|
||||
- &delegate);
|
||||
+ storage::BlobURLStoreImpl url_store(origin, blob_url_registry_.AsWeakPtr());
|
||||
|
||||
mojo::PendingRemote<blink::mojom::Blob> blob_remote;
|
||||
storage::BlobImpl::Create(
|
||||
diff --git a/content/browser/security_exploit_browsertest.cc b/content/browser/security_exploit_browsertest.cc
|
||||
index 0b6943a877874f37b10b5cfe5b7252c272e9dfee..cc99e6a8f55591bab724ef9181d594b43bb5d699 100644
|
||||
--- a/content/browser/security_exploit_browsertest.cc
|
||||
+++ b/content/browser/security_exploit_browsertest.cc
|
||||
@@ -787,7 +787,7 @@ IN_PROC_BROWSER_TEST_F(SecurityExploitBrowserTestMojoBlobURLs,
|
||||
// If the process is killed, this test passes.
|
||||
EXPECT_EQ(
|
||||
"Received bad user message: "
|
||||
- "Non committable URL passed to BlobURLStore::Register",
|
||||
+ "URL with invalid origin passed to BlobURLStore::Register",
|
||||
crash_observer.Wait());
|
||||
}
|
||||
|
||||
diff --git a/storage/browser/blob/blob_registry_impl.cc b/storage/browser/blob/blob_registry_impl.cc
|
||||
index ac131afb5e5ecc8ac77af86d9ddcb9658de1b868..c40b3e334e4327a2828756ec5700fb9a89e4aff0 100644
|
||||
--- a/storage/browser/blob/blob_registry_impl.cc
|
||||
+++ b/storage/browser/blob/blob_registry_impl.cc
|
||||
@@ -640,13 +640,14 @@ void BlobRegistryImpl::GetBlobFromUUID(
|
||||
void BlobRegistryImpl::URLStoreForOrigin(
|
||||
const url::Origin& origin,
|
||||
mojo::PendingAssociatedReceiver<blink::mojom::BlobURLStore> receiver) {
|
||||
- // TODO(mek): Pass origin on to BlobURLStoreImpl so it can use it to generate
|
||||
- // Blob URLs, and verify at this point that the renderer can create URLs for
|
||||
- // that origin.
|
||||
Delegate* delegate = receivers_.current_context().get();
|
||||
DCHECK(delegate);
|
||||
+ if (!origin.opaque() && !delegate->CanCommitURL(origin.GetURL())) {
|
||||
+ mojo::ReportBadMessage(
|
||||
+ "Non committable origin passed to BlobRegistryImpl::URLStoreForOrigin");
|
||||
+ }
|
||||
auto self_owned_associated_receiver = mojo::MakeSelfOwnedAssociatedReceiver(
|
||||
- std::make_unique<BlobURLStoreImpl>(url_registry_, delegate),
|
||||
+ std::make_unique<BlobURLStoreImpl>(origin, url_registry_),
|
||||
std::move(receiver));
|
||||
if (g_url_store_creation_hook)
|
||||
g_url_store_creation_hook->Run(self_owned_associated_receiver);
|
||||
diff --git a/storage/browser/blob/blob_url_store_impl.cc b/storage/browser/blob/blob_url_store_impl.cc
|
||||
index 09a93bcf4e1e0c1a2282d99b75b66b6ae0770611..de637458878c04999c348b4df08938f8807fa090 100644
|
||||
--- a/storage/browser/blob/blob_url_store_impl.cc
|
||||
+++ b/storage/browser/blob/blob_url_store_impl.cc
|
||||
@@ -5,6 +5,7 @@
|
||||
#include "storage/browser/blob/blob_url_store_impl.h"
|
||||
|
||||
#include "base/bind.h"
|
||||
+#include "base/strings/strcat.h"
|
||||
#include "mojo/public/cpp/bindings/receiver_set.h"
|
||||
#include "storage/browser/blob/blob_impl.h"
|
||||
#include "storage/browser/blob/blob_url_loader_factory.h"
|
||||
@@ -58,9 +59,9 @@ class BlobURLTokenImpl : public blink::mojom::BlobURLToken {
|
||||
const base::UnguessableToken token_;
|
||||
};
|
||||
|
||||
-BlobURLStoreImpl::BlobURLStoreImpl(base::WeakPtr<BlobUrlRegistry> registry,
|
||||
- BlobRegistryImpl::Delegate* delegate)
|
||||
- : registry_(std::move(registry)), delegate_(delegate) {}
|
||||
+BlobURLStoreImpl::BlobURLStoreImpl(const url::Origin& origin,
|
||||
+ base::WeakPtr<BlobUrlRegistry> registry)
|
||||
+ : origin_(origin), registry_(std::move(registry)) {}
|
||||
|
||||
BlobURLStoreImpl::~BlobURLStoreImpl() {
|
||||
if (registry_) {
|
||||
@@ -75,20 +76,9 @@ void BlobURLStoreImpl::Register(
|
||||
// TODO(https://crbug.com/1224926): Remove this once experiment is over.
|
||||
const base::UnguessableToken& unsafe_agent_cluster_id,
|
||||
RegisterCallback callback) {
|
||||
- if (!url.SchemeIsBlob()) {
|
||||
- mojo::ReportBadMessage("Invalid scheme passed to BlobURLStore::Register");
|
||||
- std::move(callback).Run();
|
||||
- return;
|
||||
- }
|
||||
- if (!delegate_->CanCommitURL(url)) {
|
||||
- mojo::ReportBadMessage(
|
||||
- "Non committable URL passed to BlobURLStore::Register");
|
||||
- std::move(callback).Run();
|
||||
- return;
|
||||
- }
|
||||
- if (BlobUrlUtils::UrlHasFragment(url)) {
|
||||
- mojo::ReportBadMessage(
|
||||
- "URL with fragment passed to BlobURLStore::Register");
|
||||
+ // TODO(mek): Generate blob URLs here, rather than validating the URLs the
|
||||
+ // renderer process generated.
|
||||
+ if (!BlobUrlIsValid(url, "Register")) {
|
||||
std::move(callback).Run();
|
||||
return;
|
||||
}
|
||||
@@ -100,19 +90,8 @@ void BlobURLStoreImpl::Register(
|
||||
}
|
||||
|
||||
void BlobURLStoreImpl::Revoke(const GURL& url) {
|
||||
- if (!url.SchemeIsBlob()) {
|
||||
- mojo::ReportBadMessage("Invalid scheme passed to BlobURLStore::Revoke");
|
||||
- return;
|
||||
- }
|
||||
- if (!delegate_->CanCommitURL(url)) {
|
||||
- mojo::ReportBadMessage(
|
||||
- "Non committable URL passed to BlobURLStore::Revoke");
|
||||
+ if (!BlobUrlIsValid(url, "Revoke"))
|
||||
return;
|
||||
- }
|
||||
- if (BlobUrlUtils::UrlHasFragment(url)) {
|
||||
- mojo::ReportBadMessage("URL with fragment passed to BlobURLStore::Revoke");
|
||||
- return;
|
||||
- }
|
||||
|
||||
if (registry_)
|
||||
registry_->RemoveUrlMapping(url);
|
||||
@@ -156,4 +135,38 @@ void BlobURLStoreImpl::ResolveForNavigation(
|
||||
std::move(callback).Run(registry_->GetUnsafeAgentClusterID(url));
|
||||
}
|
||||
|
||||
+bool BlobURLStoreImpl::BlobUrlIsValid(const GURL& url,
|
||||
+ const char* method) const {
|
||||
+ if (!url.SchemeIsBlob()) {
|
||||
+ mojo::ReportBadMessage(
|
||||
+ base::StrCat({"Invalid scheme passed to BlobURLStore::", method}));
|
||||
+ return false;
|
||||
+ }
|
||||
+ url::Origin url_origin = url::Origin::Create(url);
|
||||
+ // For file:// origins blink sometimes creates blob URLs with "null" as origin
|
||||
+ // and other times "file://" (based on a runtime setting). On the other hand,
|
||||
+ // `origin_` will always be a non-opaque file: origin for pages loaded from
|
||||
+ // file:// URLs. To deal with this, we treat file:// origins and
|
||||
+ // opaque origins separately from non-opaque origins.
|
||||
+ bool valid_origin = true;
|
||||
+ if (url_origin.scheme() == url::kFileScheme) {
|
||||
+ valid_origin = origin_.scheme() == url::kFileScheme;
|
||||
+ } else if (url_origin.opaque()) {
|
||||
+ valid_origin = origin_.opaque() || origin_.scheme() == url::kFileScheme;
|
||||
+ } else {
|
||||
+ valid_origin = origin_ == url_origin;
|
||||
+ }
|
||||
+ if (!valid_origin) {
|
||||
+ mojo::ReportBadMessage(base::StrCat(
|
||||
+ {"URL with invalid origin passed to BlobURLStore::", method}));
|
||||
+ return false;
|
||||
+ }
|
||||
+ if (BlobUrlUtils::UrlHasFragment(url)) {
|
||||
+ mojo::ReportBadMessage(
|
||||
+ base::StrCat({"URL with fragment passed to BlobURLStore::", method}));
|
||||
+ return false;
|
||||
+ }
|
||||
+ return true;
|
||||
+}
|
||||
+
|
||||
} // namespace storage
|
||||
diff --git a/storage/browser/blob/blob_url_store_impl.h b/storage/browser/blob/blob_url_store_impl.h
|
||||
index 9c6d3bfdc6aca4814323b145aa6cd6bbe1224f6f..f4cd9a96bc6ac92f3d85c679c3538a42accbe1e4 100644
|
||||
--- a/storage/browser/blob/blob_url_store_impl.h
|
||||
+++ b/storage/browser/blob/blob_url_store_impl.h
|
||||
@@ -12,8 +12,9 @@
|
||||
#include "mojo/public/cpp/bindings/pending_receiver.h"
|
||||
#include "mojo/public/cpp/bindings/pending_remote.h"
|
||||
#include "mojo/public/cpp/bindings/remote.h"
|
||||
-#include "storage/browser/blob/blob_registry_impl.h"
|
||||
+#include "storage/browser/blob/blob_url_registry.h"
|
||||
#include "third_party/blink/public/mojom/blob/blob_url_store.mojom.h"
|
||||
+#include "url/origin.h"
|
||||
|
||||
namespace storage {
|
||||
|
||||
@@ -22,8 +23,9 @@ class BlobUrlRegistry;
|
||||
class COMPONENT_EXPORT(STORAGE_BROWSER) BlobURLStoreImpl
|
||||
: public blink::mojom::BlobURLStore {
|
||||
public:
|
||||
- BlobURLStoreImpl(base::WeakPtr<BlobUrlRegistry> registry,
|
||||
- BlobRegistryImpl::Delegate* delegate);
|
||||
+ BlobURLStoreImpl(const url::Origin& origin,
|
||||
+ base::WeakPtr<BlobUrlRegistry> registry);
|
||||
+
|
||||
~BlobURLStoreImpl() override;
|
||||
|
||||
void Register(
|
||||
@@ -44,8 +46,12 @@ class COMPONENT_EXPORT(STORAGE_BROWSER) BlobURLStoreImpl
|
||||
ResolveForNavigationCallback callback) override;
|
||||
|
||||
private:
|
||||
+ // Checks if the passed in url is a valid blob url for this blob url store.
|
||||
+ // Returns false and reports a bad mojo message if not.
|
||||
+ bool BlobUrlIsValid(const GURL& url, const char* method) const;
|
||||
+
|
||||
+ const url::Origin origin_;
|
||||
base::WeakPtr<BlobUrlRegistry> registry_;
|
||||
- BlobRegistryImpl::Delegate* delegate_;
|
||||
|
||||
std::set<GURL> urls_;
|
||||
|
||||
diff --git a/storage/browser/blob/blob_url_store_impl_unittest.cc b/storage/browser/blob/blob_url_store_impl_unittest.cc
|
||||
index daf2ea331acc014ca4658eaab0ba93dcd47fe9a0..04c44794d55e3b3c1c2b9ec7eae2201fabd9f796 100644
|
||||
--- a/storage/browser/blob/blob_url_store_impl_unittest.cc
|
||||
+++ b/storage/browser/blob/blob_url_store_impl_unittest.cc
|
||||
@@ -19,7 +19,6 @@
|
||||
#include "storage/browser/blob/blob_impl.h"
|
||||
#include "storage/browser/blob/blob_storage_context.h"
|
||||
#include "storage/browser/blob/blob_url_registry.h"
|
||||
-#include "storage/browser/test/mock_blob_registry_delegate.h"
|
||||
#include "testing/gtest/include/gtest/gtest.h"
|
||||
|
||||
using blink::mojom::BlobURLStore;
|
||||
@@ -72,9 +71,9 @@ class BlobURLStoreImplTest : public testing::Test {
|
||||
|
||||
mojo::PendingRemote<BlobURLStore> CreateURLStore() {
|
||||
mojo::PendingRemote<BlobURLStore> result;
|
||||
- mojo::MakeSelfOwnedReceiver(std::make_unique<BlobURLStoreImpl>(
|
||||
- url_registry_.AsWeakPtr(), &delegate_),
|
||||
- result.InitWithNewPipeAndPassReceiver());
|
||||
+ mojo::MakeSelfOwnedReceiver(
|
||||
+ std::make_unique<BlobURLStoreImpl>(kOrigin, url_registry_.AsWeakPtr()),
|
||||
+ result.InitWithNewPipeAndPassReceiver());
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -110,15 +109,19 @@ class BlobURLStoreImplTest : public testing::Test {
|
||||
}
|
||||
|
||||
const std::string kId = "id";
|
||||
- const GURL kValidUrl = GURL("blob:id");
|
||||
+ const url::Origin kOrigin = url::Origin::Create(GURL("https://example.com"));
|
||||
+ const GURL kValidUrl = GURL("blob:" + kOrigin.Serialize() + "/id1");
|
||||
+ const GURL kValidUrl2 = GURL("blob:" + kOrigin.Serialize() + "/id2");
|
||||
const GURL kInvalidUrl = GURL("bolb:id");
|
||||
- const GURL kFragmentUrl = GURL("blob:id#fragment");
|
||||
+ const GURL kFragmentUrl = GURL(kValidUrl.spec() + "#fragment");
|
||||
+ const url::Origin kWrongOrigin =
|
||||
+ url::Origin::Create(GURL("https://test.com"));
|
||||
+ const GURL kWrongOriginUrl = GURL("blob:" + kWrongOrigin.Serialize() + "/id");
|
||||
|
||||
protected:
|
||||
base::test::TaskEnvironment task_environment_;
|
||||
std::unique_ptr<BlobStorageContext> context_;
|
||||
BlobUrlRegistry url_registry_;
|
||||
- MockBlobRegistryDelegate delegate_;
|
||||
std::vector<std::string> bad_messages_;
|
||||
base::UnguessableToken agent_cluster_id_;
|
||||
};
|
||||
@@ -128,7 +131,7 @@ TEST_F(BlobURLStoreImplTest, BasicRegisterRevoke) {
|
||||
CreateBlobFromString(kId, "hello world");
|
||||
|
||||
// Register a URL and make sure the URL keeps the blob alive.
|
||||
- BlobURLStoreImpl url_store(url_registry_.AsWeakPtr(), &delegate_);
|
||||
+ BlobURLStoreImpl url_store(kOrigin, url_registry_.AsWeakPtr());
|
||||
RegisterURL(&url_store, std::move(blob), kValidUrl);
|
||||
|
||||
blob = url_registry_.GetBlobFromUrl(kValidUrl);
|
||||
@@ -156,15 +159,13 @@ TEST_F(BlobURLStoreImplTest, RegisterInvalidScheme) {
|
||||
EXPECT_EQ(1u, bad_messages_.size());
|
||||
}
|
||||
|
||||
-TEST_F(BlobURLStoreImplTest, RegisterCantCommit) {
|
||||
+TEST_F(BlobURLStoreImplTest, RegisterWrongOrigin) {
|
||||
mojo::PendingRemote<blink::mojom::Blob> blob =
|
||||
CreateBlobFromString(kId, "hello world");
|
||||
|
||||
- delegate_.can_commit_url_result = false;
|
||||
-
|
||||
mojo::Remote<BlobURLStore> url_store(CreateURLStore());
|
||||
- RegisterURL(url_store.get(), std::move(blob), kValidUrl);
|
||||
- EXPECT_FALSE(url_registry_.GetBlobFromUrl(kValidUrl));
|
||||
+ RegisterURL(url_store.get(), std::move(blob), kWrongOriginUrl);
|
||||
+ EXPECT_FALSE(url_registry_.GetBlobFromUrl(kWrongOriginUrl));
|
||||
EXPECT_EQ(1u, bad_messages_.size());
|
||||
}
|
||||
|
||||
@@ -179,14 +180,13 @@ TEST_F(BlobURLStoreImplTest, RegisterUrlFragment) {
|
||||
}
|
||||
|
||||
TEST_F(BlobURLStoreImplTest, ImplicitRevoke) {
|
||||
- const GURL kValidUrl2("blob:id2");
|
||||
mojo::Remote<blink::mojom::Blob> blob(
|
||||
CreateBlobFromString(kId, "hello world"));
|
||||
mojo::PendingRemote<blink::mojom::Blob> blob2;
|
||||
blob->Clone(blob2.InitWithNewPipeAndPassReceiver());
|
||||
|
||||
auto url_store =
|
||||
- std::make_unique<BlobURLStoreImpl>(url_registry_.AsWeakPtr(), &delegate_);
|
||||
+ std::make_unique<BlobURLStoreImpl>(kOrigin, url_registry_.AsWeakPtr());
|
||||
RegisterURL(url_store.get(), blob.Unbind(), kValidUrl);
|
||||
EXPECT_TRUE(url_registry_.GetBlobFromUrl(kValidUrl));
|
||||
RegisterURL(url_store.get(), std::move(blob2), kValidUrl2);
|
||||
@@ -202,8 +202,8 @@ TEST_F(BlobURLStoreImplTest, RevokeThroughDifferentURLStore) {
|
||||
mojo::PendingRemote<blink::mojom::Blob> blob =
|
||||
CreateBlobFromString(kId, "hello world");
|
||||
|
||||
- BlobURLStoreImpl url_store1(url_registry_.AsWeakPtr(), &delegate_);
|
||||
- BlobURLStoreImpl url_store2(url_registry_.AsWeakPtr(), &delegate_);
|
||||
+ BlobURLStoreImpl url_store1(kOrigin, url_registry_.AsWeakPtr());
|
||||
+ BlobURLStoreImpl url_store2(kOrigin, url_registry_.AsWeakPtr());
|
||||
|
||||
RegisterURL(&url_store1, std::move(blob), kValidUrl);
|
||||
EXPECT_TRUE(url_registry_.GetBlobFromUrl(kValidUrl));
|
||||
@@ -219,11 +219,9 @@ TEST_F(BlobURLStoreImplTest, RevokeInvalidScheme) {
|
||||
EXPECT_EQ(1u, bad_messages_.size());
|
||||
}
|
||||
|
||||
-TEST_F(BlobURLStoreImplTest, RevokeCantCommit) {
|
||||
- delegate_.can_commit_url_result = false;
|
||||
-
|
||||
+TEST_F(BlobURLStoreImplTest, RevokeWrongOrigin) {
|
||||
mojo::Remote<BlobURLStore> url_store(CreateURLStore());
|
||||
- url_store->Revoke(kValidUrl);
|
||||
+ url_store->Revoke(kWrongOriginUrl);
|
||||
url_store.FlushForTesting();
|
||||
EXPECT_EQ(1u, bad_messages_.size());
|
||||
}
|
||||
@@ -239,7 +237,7 @@ TEST_F(BlobURLStoreImplTest, Resolve) {
|
||||
mojo::PendingRemote<blink::mojom::Blob> blob =
|
||||
CreateBlobFromString(kId, "hello world");
|
||||
|
||||
- BlobURLStoreImpl url_store(url_registry_.AsWeakPtr(), &delegate_);
|
||||
+ BlobURLStoreImpl url_store(kOrigin, url_registry_.AsWeakPtr());
|
||||
RegisterURL(&url_store, std::move(blob), kValidUrl);
|
||||
|
||||
blob = ResolveURL(&url_store, kValidUrl);
|
||||
@@ -254,7 +252,7 @@ TEST_F(BlobURLStoreImplTest, Resolve) {
|
||||
}
|
||||
|
||||
TEST_F(BlobURLStoreImplTest, ResolveNonExistentURL) {
|
||||
- BlobURLStoreImpl url_store(url_registry_.AsWeakPtr(), &delegate_);
|
||||
+ BlobURLStoreImpl url_store(kOrigin, url_registry_.AsWeakPtr());
|
||||
|
||||
mojo::PendingRemote<blink::mojom::Blob> blob =
|
||||
ResolveURL(&url_store, kValidUrl);
|
||||
@@ -264,7 +262,7 @@ TEST_F(BlobURLStoreImplTest, ResolveNonExistentURL) {
|
||||
}
|
||||
|
||||
TEST_F(BlobURLStoreImplTest, ResolveInvalidURL) {
|
||||
- BlobURLStoreImpl url_store(url_registry_.AsWeakPtr(), &delegate_);
|
||||
+ BlobURLStoreImpl url_store(kOrigin, url_registry_.AsWeakPtr());
|
||||
|
||||
mojo::PendingRemote<blink::mojom::Blob> blob =
|
||||
ResolveURL(&url_store, kInvalidUrl);
|
||||
@@ -275,7 +273,7 @@ TEST_F(BlobURLStoreImplTest, ResolveAsURLLoaderFactory) {
|
||||
mojo::PendingRemote<blink::mojom::Blob> blob =
|
||||
CreateBlobFromString(kId, "hello world");
|
||||
|
||||
- BlobURLStoreImpl url_store(url_registry_.AsWeakPtr(), &delegate_);
|
||||
+ BlobURLStoreImpl url_store(kOrigin, url_registry_.AsWeakPtr());
|
||||
RegisterURL(&url_store, std::move(blob), kValidUrl);
|
||||
|
||||
mojo::Remote<network::mojom::URLLoaderFactory> factory;
|
||||
@@ -312,7 +310,7 @@ TEST_F(BlobURLStoreImplTest, ResolveForNavigation) {
|
||||
mojo::PendingRemote<blink::mojom::Blob> blob =
|
||||
CreateBlobFromString(kId, "hello world");
|
||||
|
||||
- BlobURLStoreImpl url_store(url_registry_.AsWeakPtr(), &delegate_);
|
||||
+ BlobURLStoreImpl url_store(kOrigin, url_registry_.AsWeakPtr());
|
||||
RegisterURL(&url_store, std::move(blob), kValidUrl);
|
||||
|
||||
base::RunLoop loop0;
|
||||
@@ -0,0 +1,93 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Chris Cunningham <chcunningham@chromium.org>
|
||||
Date: Tue, 30 Nov 2021 20:53:26 +0000
|
||||
Subject: Various DecoderTemplate shutdown cleanups
|
||||
|
||||
1. Use DeleteSoon() when destroying the |decoder_| to avoid destructing
|
||||
in error conditions where it's callback (OnDecodeDone()) is actively
|
||||
executing.
|
||||
|
||||
2. Call Shutdown() from ContextDestroyed() to invoke full reset
|
||||
algorithm and tidily clean up all state.
|
||||
|
||||
(cherry picked from commit b5e609d4e7a296fa8c2d50f1373e9f3a50003995)
|
||||
|
||||
Bug: 1267426
|
||||
Change-Id: I927d8a3bd245b3f833e73c74103cbaacf6d73406
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3277273
|
||||
Commit-Queue: Chrome Cunningham <chcunningham@chromium.org>
|
||||
Auto-Submit: Chrome Cunningham <chcunningham@chromium.org>
|
||||
Reviewed-by: Dan Sanders <sandersd@chromium.org>
|
||||
Cr-Original-Commit-Position: refs/heads/main@{#941390}
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3308537
|
||||
Commit-Queue: Dan Sanders <sandersd@chromium.org>
|
||||
Cr-Commit-Position: refs/branch-heads/4692@{#599}
|
||||
Cr-Branched-From: 038cd96142d384c0d2238973f1cb277725a62eba-refs/heads/main@{#938553}
|
||||
|
||||
diff --git a/third_party/blink/renderer/modules/webcodecs/decoder_template.cc b/third_party/blink/renderer/modules/webcodecs/decoder_template.cc
|
||||
index fbb40f4a6a245706abcab1cc34595168f444528d..18e6d5f9f5675591dfcfa557f28bec72e41c276a 100644
|
||||
--- a/third_party/blink/renderer/modules/webcodecs/decoder_template.cc
|
||||
+++ b/third_party/blink/renderer/modules/webcodecs/decoder_template.cc
|
||||
@@ -79,8 +79,10 @@ DecoderTemplate<Traits>::DecoderTemplate(ScriptState* script_state,
|
||||
ExecutionContext* context = GetExecutionContext();
|
||||
DCHECK(context);
|
||||
|
||||
- logger_ = std::make_unique<CodecLogger>(
|
||||
- context, context->GetTaskRunner(TaskType::kInternalMedia));
|
||||
+ main_thread_task_runner_ =
|
||||
+ context->GetTaskRunner(TaskType::kInternalMediaRealTime);
|
||||
+
|
||||
+ logger_ = std::make_unique<CodecLogger>(context, main_thread_task_runner_);
|
||||
|
||||
logger_->log()->SetProperty<media::MediaLogProperty::kFrameUrl>(
|
||||
context->Url().GetString().Ascii());
|
||||
@@ -504,8 +506,10 @@ void DecoderTemplate<Traits>::Shutdown(DOMException* exception) {
|
||||
// Prevent any further logging from being reported.
|
||||
logger_->Neuter();
|
||||
|
||||
- // Clear decoding and JS-visible queue state.
|
||||
- decoder_.reset();
|
||||
+ // Clear decoding and JS-visible queue state. Use DeleteSoon() to avoid
|
||||
+ // deleting decoder_ when its callback (e.g. OnDecodeDone()) may be below us
|
||||
+ // in the stack.
|
||||
+ main_thread_task_runner_->DeleteSoon(FROM_HERE, std::move(decoder_));
|
||||
|
||||
if (pending_request_) {
|
||||
// This request was added as part of calling ResetAlgorithm above. However,
|
||||
@@ -722,9 +726,8 @@ void DecoderTemplate<Traits>::TraceQueueSizes() const {
|
||||
|
||||
template <typename Traits>
|
||||
void DecoderTemplate<Traits>::ContextDestroyed() {
|
||||
- state_ = V8CodecState(V8CodecState::Enum::kClosed);
|
||||
- logger_->Neuter();
|
||||
- decoder_.reset();
|
||||
+ // Deallocate resources and supress late callbacks from media thread.
|
||||
+ Shutdown();
|
||||
}
|
||||
|
||||
template <typename Traits>
|
||||
diff --git a/third_party/blink/renderer/modules/webcodecs/decoder_template.h b/third_party/blink/renderer/modules/webcodecs/decoder_template.h
|
||||
index bc186b60c84e2b4b76468f21a9305c5792796e7e..c16dbeee58048644291fe856e33573068da3c69f 100644
|
||||
--- a/third_party/blink/renderer/modules/webcodecs/decoder_template.h
|
||||
+++ b/third_party/blink/renderer/modules/webcodecs/decoder_template.h
|
||||
@@ -29,6 +29,10 @@
|
||||
#include "third_party/blink/renderer/platform/heap/heap_allocator.h"
|
||||
#include "third_party/blink/renderer/platform/heap/member.h"
|
||||
|
||||
+namespace base {
|
||||
+class SingleThreadTaskRunner;
|
||||
+}
|
||||
+
|
||||
namespace media {
|
||||
class GpuVideoAcceleratorFactories;
|
||||
class ScopedDecodeTrace;
|
||||
@@ -227,6 +231,9 @@ class MODULES_EXPORT DecoderTemplate
|
||||
|
||||
// Keyframes are required after configure(), flush(), and reset().
|
||||
bool require_key_frame_ = true;
|
||||
+
|
||||
+ // Task runner for main thread.
|
||||
+ scoped_refptr<base::SingleThreadTaskRunner> main_thread_task_runner_;
|
||||
};
|
||||
|
||||
} // namespace blink
|
||||
67
patches/chromium/m98_fs_fix_fileutil_lifetime_issue.patch
Normal file
67
patches/chromium/m98_fs_fix_fileutil_lifetime_issue.patch
Normal file
@@ -0,0 +1,67 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Austin Sullivan <asully@chromium.org>
|
||||
Date: Thu, 10 Feb 2022 22:18:54 +0000
|
||||
Subject: M98: FS: Fix FileUtil lifetime issue
|
||||
|
||||
Keeps FileSystemContext alive while while resolving a URL on an open
|
||||
file system, removing the possibility of the file system being
|
||||
destroyed while a URL is being resolved on it.
|
||||
|
||||
(cherry picked from commit 3fdf2adf11b3c716c9015597d30b59bffc7ac91b)
|
||||
|
||||
Bug: 1275622, 1289394
|
||||
Change-Id: Ic1b97552f9d41a61163d72ff8c605699f673f55f
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3373583
|
||||
Reviewed-by: Marijn Kruisselbrink <mek@chromium.org>
|
||||
Commit-Queue: Austin Sullivan <asully@chromium.org>
|
||||
Cr-Original-Commit-Position: refs/heads/main@{#968470}
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3451059
|
||||
Auto-Submit: Austin Sullivan <asully@chromium.org>
|
||||
Commit-Queue: Marijn Kruisselbrink <mek@chromium.org>
|
||||
Cr-Commit-Position: refs/branch-heads/4758@{#1131}
|
||||
Cr-Branched-From: 4a2cf4baf90326df19c3ee70ff987960d59a386e-refs/heads/main@{#950365}
|
||||
|
||||
diff --git a/storage/browser/file_system/file_system_context.cc b/storage/browser/file_system/file_system_context.cc
|
||||
index a9dff4886dc2697a5e146d3dae14dfd7137c8942..54dc48d097f37e62db188157bd928f85e2666fa9 100644
|
||||
--- a/storage/browser/file_system/file_system_context.cc
|
||||
+++ b/storage/browser/file_system/file_system_context.cc
|
||||
@@ -430,9 +430,22 @@ void FileSystemContext::OpenFileSystem(const blink::StorageKey& storage_key,
|
||||
return;
|
||||
}
|
||||
|
||||
+ // Bind `this` to the callback to ensure this instance stays alive while the
|
||||
+ // URL is resolving.
|
||||
backend->ResolveURL(
|
||||
CreateCrackedFileSystemURL(storage_key, type, base::FilePath()), mode,
|
||||
- std::move(callback));
|
||||
+ base::BindOnce(&FileSystemContext::DidResolveURLOnOpenFileSystem, this,
|
||||
+ std::move(callback)));
|
||||
+}
|
||||
+
|
||||
+void FileSystemContext::DidResolveURLOnOpenFileSystem(
|
||||
+ OpenFileSystemCallback callback,
|
||||
+ const GURL& filesystem_root,
|
||||
+ const std::string& filesystem_name,
|
||||
+ base::File::Error error) {
|
||||
+ DCHECK(io_task_runner_->RunsTasksInCurrentSequence());
|
||||
+
|
||||
+ std::move(callback).Run(filesystem_root, filesystem_name, error);
|
||||
}
|
||||
|
||||
void FileSystemContext::ResolveURL(const FileSystemURL& url,
|
||||
diff --git a/storage/browser/file_system/file_system_context.h b/storage/browser/file_system/file_system_context.h
|
||||
index 49d34aaf8a4f5226a26232cf6d29567fa75616ec..22e55b190c95fbdba247526deaa030b50bb45e42 100644
|
||||
--- a/storage/browser/file_system/file_system_context.h
|
||||
+++ b/storage/browser/file_system/file_system_context.h
|
||||
@@ -396,6 +396,11 @@ class COMPONENT_EXPORT(STORAGE_BROWSER) FileSystemContext
|
||||
const std::string& filesystem_name,
|
||||
base::File::Error error);
|
||||
|
||||
+ void DidResolveURLOnOpenFileSystem(OpenFileSystemCallback callback,
|
||||
+ const GURL& filesystem_root,
|
||||
+ const std::string& filesystem_name,
|
||||
+ base::File::Error error);
|
||||
+
|
||||
// Returns a FileSystemBackend, used only by test code.
|
||||
SandboxFileSystemBackend* sandbox_backend() const {
|
||||
return sandbox_backend_.get();
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user