mirror of
https://github.com/electron/electron.git
synced 2026-02-26 03:01:17 -05:00
Compare commits
79 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
f887fa45df | ||
|
|
de3776f580 | ||
|
|
165d5a2547 | ||
|
|
bd67fd8814 | ||
|
|
0eef6897cd | ||
|
|
4450b7bc23 | ||
|
|
bd5166a85d | ||
|
|
23c0c7af5b | ||
|
|
eda34ceb2e | ||
|
|
d4a9ee7e43 | ||
|
|
bac4d3469d | ||
|
|
9b2d260c12 | ||
|
|
7ede4aeaf1 | ||
|
|
3d8827fb9d | ||
|
|
2331e9192c | ||
|
|
87b0a0d984 | ||
|
|
aab45e6ed5 | ||
|
|
9e58c1bff8 | ||
|
|
7e5adf5e56 | ||
|
|
726839761f | ||
|
|
21e1f6398e | ||
|
|
6b75a958c2 | ||
|
|
7842c6d075 | ||
|
|
f2e2fc34f2 | ||
|
|
b4d98668cf | ||
|
|
7ce8eaf7f3 | ||
|
|
9fe4c52219 | ||
|
|
7a40212cc8 | ||
|
|
5ce7d5f81d | ||
|
|
0ab4aa8519 | ||
|
|
2c457e3cb5 | ||
|
|
d3fe374952 | ||
|
|
83077e9b97 | ||
|
|
4c1bab160e | ||
|
|
3085f29451 | ||
|
|
5e7d79baa3 | ||
|
|
87da7ebd6e | ||
|
|
4748751005 | ||
|
|
033c3eded3 | ||
|
|
a58099974c | ||
|
|
8517c72503 | ||
|
|
5dfff3a70a | ||
|
|
ddee4efb07 | ||
|
|
d961b39ed7 | ||
|
|
bb5c7430db | ||
|
|
17b7b78993 | ||
|
|
dbecf7f3c4 | ||
|
|
92ebdb4766 | ||
|
|
b077402f2c | ||
|
|
7f89857058 | ||
|
|
8d545255c9 | ||
|
|
b999fd31f2 | ||
|
|
73923c862e | ||
|
|
4817e82e89 | ||
|
|
7d84b3bc87 | ||
|
|
13445df1fb | ||
|
|
e75e4420eb | ||
|
|
9947b55cc2 | ||
|
|
a79258f77e | ||
|
|
09cf05df5c | ||
|
|
2dfd69ea90 | ||
|
|
51d097662e | ||
|
|
08c02d2013 | ||
|
|
58f7ab8a5c | ||
|
|
770a38e21c | ||
|
|
1289823c67 | ||
|
|
3ade6e1b08 | ||
|
|
c2d73ae79c | ||
|
|
14c64ed2e0 | ||
|
|
0e0b638e5f | ||
|
|
0e6da36264 | ||
|
|
3160e0d7fd | ||
|
|
d0293c81c0 | ||
|
|
178db41204 | ||
|
|
d3976e68c8 | ||
|
|
9e3039775e | ||
|
|
820e0ca3b5 | ||
|
|
397a5c6194 | ||
|
|
4d62f9648f |
@@ -216,6 +216,7 @@ step-maybe-cleanup-arm64-mac: &step-maybe-cleanup-arm64-mac
|
||||
rm -rf ~/Library/Application\ Support/electron*
|
||||
security delete-generic-password -l "Chromium Safe Storage" || echo "✓ Keychain does not contain password from tests"
|
||||
security delete-generic-password -l "Electron Test Main Safe Storage" || echo "✓ Keychain does not contain password from tests"
|
||||
security delete-generic-password -a "electron-safe-storage" || echo "✓ Keychain does not contain password from tests"
|
||||
elif [ "$TARGET_ARCH" == "arm" ] || [ "$TARGET_ARCH" == "arm64" ]; then
|
||||
XVFB=/usr/bin/Xvfb
|
||||
/sbin/start-stop-daemon --stop --exec $XVFB || echo "Xvfb not running"
|
||||
@@ -454,7 +455,7 @@ step-delete-git-directories: &step-delete-git-directories
|
||||
command: |
|
||||
if [ "`uname`" == "Darwin" ]; then
|
||||
cd src
|
||||
( find . -type d -name ".git" -not -path "./third_party/angle/*" -not -path "./third_party/dawn/*" ) | xargs rm -rf
|
||||
( find . -type d -name ".git" -not -path "./third_party/angle/*" -not -path "./third_party/dawn/*" -not -path "./electron/*" ) | xargs rm -rf
|
||||
fi
|
||||
|
||||
# On macOS the yarn install command during gclient sync was run on a linux
|
||||
@@ -825,7 +826,7 @@ step-maybe-zip-symbols: &step-maybe-zip-symbols
|
||||
cd src
|
||||
export BUILD_PATH="$PWD/out/Default"
|
||||
ninja -C out/Default electron:licenses
|
||||
ninja -C out/Default electron:electron_version
|
||||
ninja -C out/Default electron:electron_version_file
|
||||
DELETE_DSYMS_AFTER_ZIP=1 electron/script/zip-symbols.py -b $BUILD_PATH
|
||||
|
||||
step-maybe-cross-arch-snapshot: &step-maybe-cross-arch-snapshot
|
||||
@@ -885,12 +886,12 @@ step-touch-sync-done: &step-touch-sync-done
|
||||
step-maybe-restore-src-cache: &step-maybe-restore-src-cache
|
||||
restore_cache:
|
||||
keys:
|
||||
- v14-src-cache-{{ checksum "src/electron/.depshash" }}
|
||||
- v16-src-cache-{{ checksum "src/electron/.depshash" }}
|
||||
name: Restoring src cache
|
||||
step-maybe-restore-src-cache-marker: &step-maybe-restore-src-cache-marker
|
||||
restore_cache:
|
||||
keys:
|
||||
- v14-src-cache-marker-{{ checksum "src/electron/.depshash" }}
|
||||
- v16-src-cache-marker-{{ checksum "src/electron/.depshash" }}
|
||||
name: Restoring src cache marker
|
||||
|
||||
# Restore exact or closest git cache based on the hash of DEPS and .circle-sync-done
|
||||
@@ -905,14 +906,6 @@ step-maybe-restore-git-cache: &step-maybe-restore-git-cache
|
||||
- v1-git-cache-{{ checksum "src/electron/.circle-sync-done" }}
|
||||
name: Conditionally restoring git cache
|
||||
|
||||
step-restore-out-cache: &step-restore-out-cache
|
||||
restore_cache:
|
||||
paths:
|
||||
- ./src/out/Default
|
||||
keys:
|
||||
- v10-out-cache-{{ checksum "src/electron/.depshash" }}-{{ checksum "src/electron/.depshash-target" }}
|
||||
name: Restoring out cache
|
||||
|
||||
step-set-git-cache-path: &step-set-git-cache-path
|
||||
run:
|
||||
name: Set GIT_CACHE_PATH to make gclient to use the cache
|
||||
@@ -930,13 +923,6 @@ step-save-git-cache: &step-save-git-cache
|
||||
key: v1-git-cache-{{ checksum "src/electron/.circle-sync-done" }}-{{ checksum "src/electron/DEPS" }}
|
||||
name: Persisting git cache
|
||||
|
||||
step-save-out-cache: &step-save-out-cache
|
||||
save_cache:
|
||||
paths:
|
||||
- ./src/out/Default
|
||||
key: v10-out-cache-{{ checksum "src/electron/.depshash" }}-{{ checksum "src/electron/.depshash-target" }}
|
||||
name: Persisting out cache
|
||||
|
||||
step-run-electron-only-hooks: &step-run-electron-only-hooks
|
||||
run:
|
||||
name: Run Electron Only Hooks
|
||||
@@ -966,13 +952,16 @@ step-minimize-workspace-size-from-checkout: &step-minimize-workspace-size-from-c
|
||||
rm -rf third_party/electron_node/deps/openssl
|
||||
rm -rf third_party/electron_node/deps/v8
|
||||
rm -rf chrome/test/data/xr/webvr_info
|
||||
rm -rf src/third_party/angle/third_party/VK-GL-CTS/src
|
||||
rm -rf src/third_party/swift-toolchain
|
||||
rm -rf src/third_party/swiftshader/tests/regres/testlists
|
||||
|
||||
# Save the src cache based on the deps hash
|
||||
step-save-src-cache: &step-save-src-cache
|
||||
save_cache:
|
||||
paths:
|
||||
- /var/portal
|
||||
key: v14-src-cache-{{ checksum "/var/portal/src/electron/.depshash" }}
|
||||
key: v16-src-cache-{{ checksum "/var/portal/src/electron/.depshash" }}
|
||||
name: Persisting src cache
|
||||
step-make-src-cache-marker: &step-make-src-cache-marker
|
||||
run:
|
||||
@@ -982,7 +971,7 @@ step-save-src-cache-marker: &step-save-src-cache-marker
|
||||
save_cache:
|
||||
paths:
|
||||
- .src-cache-marker
|
||||
key: v14-src-cache-marker-{{ checksum "/var/portal/src/electron/.depshash" }}
|
||||
key: v16-src-cache-marker-{{ checksum "/var/portal/src/electron/.depshash" }}
|
||||
|
||||
step-maybe-early-exit-no-doc-change: &step-maybe-early-exit-no-doc-change
|
||||
run:
|
||||
@@ -1353,9 +1342,6 @@ commands:
|
||||
build:
|
||||
type: boolean
|
||||
default: true
|
||||
use-out-cache:
|
||||
type: boolean
|
||||
default: true
|
||||
restore-src-cache:
|
||||
type: boolean
|
||||
default: true
|
||||
@@ -1478,10 +1464,6 @@ commands:
|
||||
- *step-delete-git-directories
|
||||
|
||||
# Electron app
|
||||
- when:
|
||||
condition: << parameters.use-out-cache >>
|
||||
steps:
|
||||
- *step-restore-out-cache
|
||||
- *step-gn-gen-default
|
||||
- *step-electron-build
|
||||
- *step-maybe-electron-dist-strip
|
||||
@@ -1524,22 +1506,6 @@ commands:
|
||||
condition: << parameters.build >>
|
||||
steps:
|
||||
- move_and_store_all_artifacts
|
||||
- run:
|
||||
name: Remove the big things on macOS, this seems to be better on average
|
||||
command: |
|
||||
if [ "`uname`" == "Darwin" ]; then
|
||||
mkdir -p src/out/Default
|
||||
cd src/out/Default
|
||||
find . -type f -size +50M -delete
|
||||
mkdir -p gen/electron
|
||||
cd gen/electron
|
||||
# These files do not seem to like being in a cache, let us remove them
|
||||
find . -type f -name '*_pkg_info' -delete
|
||||
fi
|
||||
- when:
|
||||
condition: << parameters.use-out-cache >>
|
||||
steps:
|
||||
- *step-save-out-cache
|
||||
|
||||
- *step-maybe-notify-slack-failure
|
||||
|
||||
@@ -1693,7 +1659,6 @@ jobs:
|
||||
persist: true
|
||||
checkout: false
|
||||
checkout-and-assume-cache: true
|
||||
use-out-cache: false
|
||||
|
||||
linux-x64-testing-asan:
|
||||
executor:
|
||||
@@ -1710,7 +1675,6 @@ jobs:
|
||||
- electron-build:
|
||||
persist: true
|
||||
checkout: true
|
||||
use-out-cache: false
|
||||
build-nonproprietary-ffmpeg: false
|
||||
|
||||
linux-x64-testing-no-run-as-node:
|
||||
@@ -1727,7 +1691,6 @@ jobs:
|
||||
- electron-build:
|
||||
persist: false
|
||||
checkout: true
|
||||
use-out-cache: false
|
||||
|
||||
linux-x64-testing-gn-check:
|
||||
executor:
|
||||
@@ -1778,7 +1741,6 @@ jobs:
|
||||
persist: true
|
||||
checkout: false
|
||||
checkout-and-assume-cache: true
|
||||
use-out-cache: false
|
||||
|
||||
linux-arm-publish:
|
||||
executor:
|
||||
@@ -1821,7 +1783,6 @@ jobs:
|
||||
persist: true
|
||||
checkout: false
|
||||
checkout-and-assume-cache: true
|
||||
use-out-cache: false
|
||||
|
||||
linux-arm64-testing-gn-check:
|
||||
executor:
|
||||
|
||||
2
.github/semantic.yml
vendored
2
.github/semantic.yml
vendored
@@ -1,2 +0,0 @@
|
||||
# Always validate the PR title, and ignore the commits
|
||||
titleOnly: true
|
||||
60
BUILD.gn
60
BUILD.gn
@@ -100,6 +100,14 @@ branding = read_file("shell/app/BRANDING.json", "json")
|
||||
electron_project_name = branding.project_name
|
||||
electron_product_name = branding.product_name
|
||||
electron_mac_bundle_id = branding.mac_bundle_id
|
||||
electron_version = exec_script("script/print-version.py",
|
||||
[],
|
||||
"trim string",
|
||||
[
|
||||
".git/packed-refs",
|
||||
".git/HEAD",
|
||||
"script/lib/get-version.js",
|
||||
])
|
||||
|
||||
if (is_mas_build) {
|
||||
assert(is_mac,
|
||||
@@ -294,12 +302,9 @@ npm_action("electron_version_args") {
|
||||
|
||||
outputs = [ "$target_gen_dir/electron_version.args" ]
|
||||
|
||||
args = rebase_path(outputs)
|
||||
args = rebase_path(outputs) + [ "$electron_version" ]
|
||||
|
||||
inputs = [
|
||||
"ELECTRON_VERSION",
|
||||
"script/generate-version-json.js",
|
||||
]
|
||||
inputs = [ "script/generate-version-json.js" ]
|
||||
}
|
||||
|
||||
templated_file("electron_version_header") {
|
||||
@@ -311,6 +316,39 @@ templated_file("electron_version_header") {
|
||||
args_files = get_target_outputs(":electron_version_args")
|
||||
}
|
||||
|
||||
templated_file("electron_win_rc") {
|
||||
deps = [ ":electron_version_args" ]
|
||||
|
||||
template = "build/templates/electron_rc.tmpl"
|
||||
output = "$target_gen_dir/win-resources/electron.rc"
|
||||
|
||||
args_files = get_target_outputs(":electron_version_args")
|
||||
}
|
||||
|
||||
copy("electron_win_resource_files") {
|
||||
sources = [
|
||||
"shell/browser/resources/win/electron.ico",
|
||||
"shell/browser/resources/win/resource.h",
|
||||
]
|
||||
outputs = [ "$target_gen_dir/win-resources/{{source_file_part}}" ]
|
||||
}
|
||||
|
||||
templated_file("electron_version_file") {
|
||||
deps = [ ":electron_version_args" ]
|
||||
|
||||
template = "build/templates/version_string.tmpl"
|
||||
output = "$root_build_dir/version"
|
||||
|
||||
args_files = get_target_outputs(":electron_version_args")
|
||||
}
|
||||
|
||||
group("electron_win32_resources") {
|
||||
public_deps = [
|
||||
":electron_win_rc",
|
||||
":electron_win_resource_files",
|
||||
]
|
||||
}
|
||||
|
||||
action("electron_fuses") {
|
||||
script = "build/fuses/build.py"
|
||||
|
||||
@@ -749,7 +787,6 @@ if (is_mac) {
|
||||
electron_helper_name = "$electron_product_name Helper"
|
||||
electron_login_helper_name = "$electron_product_name Login Helper"
|
||||
electron_framework_version = "A"
|
||||
electron_version = read_file("ELECTRON_VERSION", "trim string")
|
||||
|
||||
mac_xib_bundle_data("electron_xibs") {
|
||||
sources = [ "shell/common/resources/mac/MainMenu.xib" ]
|
||||
@@ -1179,6 +1216,7 @@ if (is_mac) {
|
||||
":default_app_asar",
|
||||
":electron_app_manifest",
|
||||
":electron_lib",
|
||||
":electron_win32_resources",
|
||||
":packed_resources",
|
||||
"//components/crash/core/app",
|
||||
"//content:sandbox_helper_win",
|
||||
@@ -1212,8 +1250,7 @@ if (is_mac) {
|
||||
|
||||
if (is_win) {
|
||||
sources += [
|
||||
# TODO: we should be generating our .rc files more like how chrome does
|
||||
"shell/browser/resources/win/electron.rc",
|
||||
"$target_gen_dir/win-resources/electron.rc",
|
||||
"shell/browser/resources/win/resource.h",
|
||||
]
|
||||
|
||||
@@ -1395,15 +1432,10 @@ group("licenses") {
|
||||
]
|
||||
}
|
||||
|
||||
copy("electron_version") {
|
||||
sources = [ "ELECTRON_VERSION" ]
|
||||
outputs = [ "$root_build_dir/version" ]
|
||||
}
|
||||
|
||||
dist_zip("electron_dist_zip") {
|
||||
data_deps = [
|
||||
":electron_app",
|
||||
":electron_version",
|
||||
":electron_version_file",
|
||||
":licenses",
|
||||
]
|
||||
if (is_linux) {
|
||||
|
||||
@@ -1 +0,0 @@
|
||||
19.0.16
|
||||
14
appveyor.yml
14
appveyor.yml
@@ -182,14 +182,14 @@ build_script:
|
||||
}
|
||||
- ps: >-
|
||||
if ($env:GN_CONFIG -eq 'release') {
|
||||
python electron\script\zip-symbols.py
|
||||
python3 electron\script\zip-symbols.py
|
||||
appveyor-retry appveyor PushArtifact out/Default/symbols.zip
|
||||
} else {
|
||||
# It's useful to have pdb files when debugging testing builds that are
|
||||
# built on CI.
|
||||
7z a pdb.zip out\Default\*.pdb
|
||||
}
|
||||
- python electron/script/zip_manifests/check-zip-manifest.py out/Default/dist.zip electron/script/zip_manifests/dist_zip.win.%TARGET_ARCH%.manifest
|
||||
- python3 electron/script/zip_manifests/check-zip-manifest.py out/Default/dist.zip electron/script/zip_manifests/dist_zip.win.%TARGET_ARCH%.manifest
|
||||
test_script:
|
||||
# Workaround for https://github.com/appveyor/ci/issues/2420
|
||||
- set "PATH=%PATH%;C:\Program Files\Git\mingw64\libexec\git-core"
|
||||
@@ -210,11 +210,11 @@ test_script:
|
||||
- if "%RUN_TESTS%"=="true" ( echo Running remote test suite & node script/yarn test -- --trace-uncaught --runners=remote --runTestFilesSeperately --enable-logging=file --log-file=%cd%\electron.log --disable-features=CalculateNativeWinOcclusion )
|
||||
- if "%RUN_TESTS%"=="true" ( echo Running native test suite & node script/yarn test -- --trace-uncaught --runners=native --enable-logging=file --log-file=%cd%\electron.log --disable-features=CalculateNativeWinOcclusion )
|
||||
- cd ..
|
||||
- if "%RUN_TESTS%"=="true" ( echo Verifying non proprietary ffmpeg & python electron\script\verify-ffmpeg.py --build-dir out\Default --source-root %cd% --ffmpeg-path out\ffmpeg )
|
||||
- if "%RUN_TESTS%"=="true" ( echo Verifying non proprietary ffmpeg & python3 electron\script\verify-ffmpeg.py --build-dir out\Default --source-root %cd% --ffmpeg-path out\ffmpeg )
|
||||
- echo "About to verify mksnapshot"
|
||||
- if "%RUN_TESTS%"=="true" ( echo Verifying mksnapshot & python electron\script\verify-mksnapshot.py --build-dir out\Default --source-root %cd% )
|
||||
- if "%RUN_TESTS%"=="true" ( echo Verifying mksnapshot & python3 electron\script\verify-mksnapshot.py --build-dir out\Default --source-root %cd% )
|
||||
- echo "Done verifying mksnapshot"
|
||||
- if "%RUN_TESTS%"=="true" ( echo Verifying chromedriver & python electron\script\verify-chromedriver.py --build-dir out\Default --source-root %cd% )
|
||||
- if "%RUN_TESTS%"=="true" ( echo Verifying chromedriver & python3 electron\script\verify-chromedriver.py --build-dir out\Default --source-root %cd% )
|
||||
- echo "Done verifying chromedriver"
|
||||
deploy_script:
|
||||
- cd electron
|
||||
@@ -222,10 +222,10 @@ deploy_script:
|
||||
if (Test-Path Env:\ELECTRON_RELEASE) {
|
||||
if (Test-Path Env:\UPLOAD_TO_STORAGE) {
|
||||
Write-Output "Uploading Electron release distribution to azure"
|
||||
& python script\release\uploaders\upload.py --verbose --upload_to_storage
|
||||
& python3 script\release\uploaders\upload.py --verbose --upload_to_storage
|
||||
} else {
|
||||
Write-Output "Uploading Electron release distribution to github releases"
|
||||
& python script\release\uploaders\upload.py --verbose
|
||||
& python3 script\release\uploaders\upload.py --verbose
|
||||
}
|
||||
} elseif (Test-Path Env:\TEST_WOA) {
|
||||
node script/release/ci-release-build.js --job=electron-woa-testing --ci=GHA --appveyorJobId=$env:APPVEYOR_JOB_ID $env:APPVEYOR_REPO_BRANCH
|
||||
|
||||
@@ -50,8 +50,8 @@ END
|
||||
//
|
||||
|
||||
VS_VERSION_INFO VERSIONINFO
|
||||
FILEVERSION 19,0,16,0
|
||||
PRODUCTVERSION 19,0,16,0
|
||||
FILEVERSION $major,$minor,$patch,$prerelease_number
|
||||
PRODUCTVERSION $major,$minor,$patch,$prerelease_number
|
||||
FILEFLAGSMASK 0x3fL
|
||||
#ifdef _DEBUG
|
||||
FILEFLAGS 0x1L
|
||||
@@ -68,12 +68,12 @@ BEGIN
|
||||
BEGIN
|
||||
VALUE "CompanyName", "GitHub, Inc."
|
||||
VALUE "FileDescription", "Electron"
|
||||
VALUE "FileVersion", "19.0.16"
|
||||
VALUE "FileVersion", "$major.$minor.$patch"
|
||||
VALUE "InternalName", "electron.exe"
|
||||
VALUE "LegalCopyright", "Copyright (C) 2015 GitHub, Inc. All rights reserved."
|
||||
VALUE "OriginalFilename", "electron.exe"
|
||||
VALUE "ProductName", "Electron"
|
||||
VALUE "ProductVersion", "19.0.16"
|
||||
VALUE "ProductVersion", "$major.$minor.$patch"
|
||||
VALUE "SquirrelAwareVersion", "1"
|
||||
END
|
||||
END
|
||||
1
build/templates/version_string.tmpl
Normal file
1
build/templates/version_string.tmpl
Normal file
@@ -0,0 +1 @@
|
||||
$full_version
|
||||
@@ -610,7 +610,7 @@ win.webContents.session.setCertificateVerifyProc((request, callback) => {
|
||||
* `notifications` - Request notification creation and the ability to display them in the user's system tray.
|
||||
* `midi` - Request MIDI access in the `webmidi` API.
|
||||
* `midiSysex` - Request the use of system exclusive messages in the `webmidi` API.
|
||||
* `pointerLock` - Request to directly interpret mouse movements as an input method. Click [here](https://developer.mozilla.org/en-US/docs/Web/API/Pointer_Lock_API) to know more.
|
||||
* `pointerLock` - Request to directly interpret mouse movements as an input method. Click [here](https://developer.mozilla.org/en-US/docs/Web/API/Pointer_Lock_API) to know more. These requests always appear to originate from the main frame.
|
||||
* `fullscreen` - Request for the app to enter fullscreen mode.
|
||||
* `openExternal` - Request to open links in external applications.
|
||||
* `unknown` - An unrecognized permission request
|
||||
|
||||
@@ -144,6 +144,16 @@ ipcRenderer.on('port', (e, msg) => {
|
||||
|
||||
A `string` representing the current URL of the frame.
|
||||
|
||||
#### `frame.origin` _Readonly_
|
||||
|
||||
A `string` representing the current origin of the frame, serialized according
|
||||
to [RFC 6454](https://www.rfc-editor.org/rfc/rfc6454). This may be different
|
||||
from the URL. For instance, if the frame is a child window opened to
|
||||
`about:blank`, then `frame.origin` will return the parent frame's origin, while
|
||||
`frame.url` will return the empty string. Pages without a scheme/host/port
|
||||
triple origin will have the serialized origin of `"null"` (that is, the string
|
||||
containing the letters n, u, l, l).
|
||||
|
||||
#### `frame.top` _Readonly_
|
||||
|
||||
A `WebFrameMain | null` representing top frame in the frame hierarchy to which `frame`
|
||||
|
||||
@@ -135,7 +135,7 @@ is only available in renderer processes.
|
||||
|
||||
If [sub-pixel anti-aliasing](https://alienryderflex.com/sub_pixel/) is deactivated, then fonts on LCD screens can look blurry. Example:
|
||||
|
||||
![subpixel rendering example]
|
||||

|
||||
|
||||
Sub-pixel anti-aliasing needs a non-transparent background of the layer containing the font glyphs. (See [this issue](https://github.com/electron/electron/issues/6344#issuecomment-420371918) for more info).
|
||||
|
||||
@@ -161,4 +161,3 @@ Notice that just setting the background in the CSS does not have the desired eff
|
||||
[indexed-db]: https://developer.mozilla.org/en-US/docs/Web/API/IndexedDB_API
|
||||
[message-port]: https://developer.mozilla.org/en-US/docs/Web/API/MessagePort
|
||||
[browser-window]: api/browser-window.md
|
||||
[subpixel rendering example]: images/subpixel-rendering-screenshot.gif
|
||||
|
||||
@@ -28,12 +28,16 @@ function createWindow () {
|
||||
if (permission === 'serial' && details.securityOrigin === 'file:///') {
|
||||
return true
|
||||
}
|
||||
|
||||
return false
|
||||
})
|
||||
|
||||
mainWindow.webContents.session.setDevicePermissionHandler((details) => {
|
||||
if (details.deviceType === 'serial' && details.origin === 'file://') {
|
||||
return true
|
||||
}
|
||||
|
||||
return false
|
||||
})
|
||||
|
||||
mainWindow.loadFile('index.html')
|
||||
|
||||
@@ -18,4 +18,4 @@
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -72,9 +72,8 @@ BrowserWindow.getAllWindows = () => {
|
||||
|
||||
BrowserWindow.getFocusedWindow = () => {
|
||||
for (const window of BrowserWindow.getAllWindows()) {
|
||||
const hasWC = window.webContents && !window.webContents.isDestroyed();
|
||||
if (!window.isDestroyed() && hasWC) {
|
||||
if (window.isFocused() || window.isDevToolsFocused()) return window;
|
||||
if (!window.isDestroyed() && window.webContents && !window.webContents.isDestroyed()) {
|
||||
if (window.isFocused() || window.webContents.isDevToolsFocused()) return window;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
const { nativeTheme } = process._linkedBinding('electron_common_native_theme');
|
||||
const { nativeTheme } = process._linkedBinding('electron_browser_native_theme');
|
||||
|
||||
module.exports = nativeTheme;
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
const {
|
||||
Notification: ElectronNotification,
|
||||
isSupported
|
||||
} = process._linkedBinding('electron_common_notification');
|
||||
} = process._linkedBinding('electron_browser_notification');
|
||||
|
||||
ElectronNotification.isSupported = isSupported;
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { EventEmitter } from 'events';
|
||||
|
||||
const { createScreen } = process._linkedBinding('electron_common_screen');
|
||||
const { createScreen } = process._linkedBinding('electron_browser_screen');
|
||||
|
||||
let _screen: Electron.Screen;
|
||||
|
||||
|
||||
23
lib/common/.eslintrc.json
Normal file
23
lib/common/.eslintrc.json
Normal file
@@ -0,0 +1,23 @@
|
||||
{
|
||||
"rules": {
|
||||
"no-restricted-imports": [
|
||||
"error",
|
||||
{
|
||||
"paths": [
|
||||
"electron",
|
||||
"electron/main",
|
||||
"electron/renderer"
|
||||
],
|
||||
"patterns": [
|
||||
"./*",
|
||||
"../*",
|
||||
"@electron/internal/browser/*",
|
||||
"@electron/internal/isolated_renderer/*",
|
||||
"@electron/internal/renderer/*",
|
||||
"@electron/internal/sandboxed_worker/*",
|
||||
"@electron/internal/worker/*"
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,6 @@
|
||||
import { IPC_MESSAGES } from '@electron/internal/common/ipc-messages';
|
||||
|
||||
// eslint-disable-next-line no-restricted-imports
|
||||
import type * as ipcRendererUtilsModule from '@electron/internal/renderer/ipc-renderer-internal-utils';
|
||||
|
||||
const clipboard = process._linkedBinding('electron_common_clipboard');
|
||||
|
||||
18
lib/isolated_renderer/.eslintrc.json
Normal file
18
lib/isolated_renderer/.eslintrc.json
Normal file
@@ -0,0 +1,18 @@
|
||||
{
|
||||
"rules": {
|
||||
"no-restricted-imports": [
|
||||
"error",
|
||||
{
|
||||
"paths": [
|
||||
"electron",
|
||||
"electron/main"
|
||||
],
|
||||
"patterns": [
|
||||
"./*",
|
||||
"../*",
|
||||
"@electron/internal/browser/*"
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
18
lib/renderer/.eslintrc.json
Normal file
18
lib/renderer/.eslintrc.json
Normal file
@@ -0,0 +1,18 @@
|
||||
{
|
||||
"rules": {
|
||||
"no-restricted-imports": [
|
||||
"error",
|
||||
{
|
||||
"paths": [
|
||||
"electron",
|
||||
"electron/main"
|
||||
],
|
||||
"patterns": [
|
||||
"./*",
|
||||
"../*",
|
||||
"@electron/internal/browser/*"
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
import { ipcRenderer } from 'electron';
|
||||
import { ipcRenderer } from 'electron/renderer';
|
||||
import { ipcRendererInternal } from '@electron/internal/renderer/ipc-renderer-internal';
|
||||
|
||||
import type * as webViewInitModule from '@electron/internal/renderer/web-view/web-view-init';
|
||||
|
||||
@@ -2,7 +2,7 @@ import { internalContextBridge } from '@electron/internal/renderer/api/context-b
|
||||
import { ipcRendererInternal } from '@electron/internal/renderer/ipc-renderer-internal';
|
||||
import * as ipcRendererUtils from '@electron/internal/renderer/ipc-renderer-internal-utils';
|
||||
import { webFrame } from 'electron/renderer';
|
||||
import { IPC_MESSAGES } from '../common/ipc-messages';
|
||||
import { IPC_MESSAGES } from '@electron/internal/common/ipc-messages';
|
||||
|
||||
const { contextIsolationEnabled } = internalContextBridge;
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { webFrame, WebFrame } from 'electron';
|
||||
import { webFrame, WebFrame } from 'electron/renderer';
|
||||
import * as ipcRendererUtils from '@electron/internal/renderer/ipc-renderer-internal-utils';
|
||||
import { IPC_MESSAGES } from '@electron/internal/common/ipc-messages';
|
||||
|
||||
|
||||
18
lib/sandboxed_renderer/.eslintrc.json
Normal file
18
lib/sandboxed_renderer/.eslintrc.json
Normal file
@@ -0,0 +1,18 @@
|
||||
{
|
||||
"rules": {
|
||||
"no-restricted-imports": [
|
||||
"error",
|
||||
{
|
||||
"paths": [
|
||||
"electron",
|
||||
"electron/main"
|
||||
],
|
||||
"patterns": [
|
||||
"./*",
|
||||
"../*",
|
||||
"@electron/internal/browser/*"
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
18
lib/worker/.eslintrc.json
Normal file
18
lib/worker/.eslintrc.json
Normal file
@@ -0,0 +1,18 @@
|
||||
{
|
||||
"rules": {
|
||||
"no-restricted-imports": [
|
||||
"error",
|
||||
{
|
||||
"paths": [
|
||||
"electron",
|
||||
"electron/main"
|
||||
],
|
||||
"patterns": [
|
||||
"./*",
|
||||
"../*",
|
||||
"@electron/internal/browser/*"
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
12
package.json
12
package.json
@@ -1,12 +1,13 @@
|
||||
{
|
||||
"name": "electron",
|
||||
"version": "19.0.16",
|
||||
"version": "0.0.0-development",
|
||||
"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.4",
|
||||
"@electron/typescript-definitions": "^8.9.5",
|
||||
"@electron/asar": "^3.2.1",
|
||||
"@electron/docs-parser": "^1.0.0",
|
||||
"@electron/typescript-definitions": "^8.10.0",
|
||||
"@octokit/auth-app": "^2.10.0",
|
||||
"@octokit/rest": "^18.0.3",
|
||||
"@primer/octicons": "^10.0.0",
|
||||
@@ -31,7 +32,6 @@
|
||||
"@types/webpack-env": "^1.16.3",
|
||||
"@typescript-eslint/eslint-plugin": "^4.4.1",
|
||||
"@typescript-eslint/parser": "^4.4.1",
|
||||
"asar": "^3.1.0",
|
||||
"aws-sdk": "^2.814.0",
|
||||
"check-for-leaks": "^1.2.1",
|
||||
"colors": "1.4.0",
|
||||
@@ -89,7 +89,7 @@
|
||||
"lint:docs-relative-links": "python3 ./script/check-relative-doc-links.py",
|
||||
"lint:markdownlint": "markdownlint \"*.md\" \"docs/**/*.md\"",
|
||||
"lint:js-in-markdown": "standard-markdown docs",
|
||||
"create-api-json": "electron-docs-parser --dir=./",
|
||||
"create-api-json": "node script/create-api-json.js",
|
||||
"create-typescript-definitions": "npm run create-api-json && electron-typescript-definitions --api=electron-api.json && node spec/ts-smoke/runner.js",
|
||||
"gn-typescript-definitions": "npm run create-typescript-definitions && shx cp electron.d.ts",
|
||||
"pre-flight": "pre-flight",
|
||||
@@ -143,4 +143,4 @@
|
||||
"node script/gen-hunspell-filenames.js"
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,2 +1,3 @@
|
||||
m104_vulkan_fix_garbage_collection_vs_outside-rp-only_flush.patch
|
||||
m104_vulkan_fix_xfb_buffer_redefine_to_smaller_size.patch
|
||||
cherry-pick-b8636b57b8f2.patch
|
||||
|
||||
45
patches/angle/cherry-pick-b8636b57b8f2.patch
Normal file
45
patches/angle/cherry-pick-b8636b57b8f2.patch
Normal file
@@ -0,0 +1,45 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Jamie Madill <jmadill@chromium.org>
|
||||
Date: Mon, 29 Aug 2022 16:25:46 -0400
|
||||
Subject: Vulkan: Ensure we sync the draw FB before beingQuery.
|
||||
|
||||
Bug: chromium:1354271
|
||||
(cherry picked from commit 4ebdac790c76b65abf5703bcef9482c638076195)
|
||||
Change-Id: I7b715a9c28badfe58a0ae1a478d2b4e8bbd23c47
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/3956939
|
||||
Reviewed-by: Shahbaz Youssefi <syoussefi@chromium.org>
|
||||
|
||||
diff --git a/src/libANGLE/State.h b/src/libANGLE/State.h
|
||||
index f8c1d9daaf31b5edb98edf3ca0a5c1983d6039cb..79403b13a94447c07bf0bfa6f9e6567e43346505 100644
|
||||
--- a/src/libANGLE/State.h
|
||||
+++ b/src/libANGLE/State.h
|
||||
@@ -600,6 +600,11 @@ class State : angle::NonCopyable
|
||||
|
||||
bool isRobustResourceInitEnabled() const { return mRobustResourceInit; }
|
||||
|
||||
+ bool isDrawFramebufferBindingDirty() const
|
||||
+ {
|
||||
+ return mDirtyBits.test(DIRTY_BIT_DRAW_FRAMEBUFFER_BINDING);
|
||||
+ }
|
||||
+
|
||||
// Sets the dirty bit for the program executable.
|
||||
angle::Result onProgramExecutableChange(const Context *context, Program *program);
|
||||
// Sets the dirty bit for the program pipeline executable.
|
||||
diff --git a/src/libANGLE/renderer/vulkan/QueryVk.cpp b/src/libANGLE/renderer/vulkan/QueryVk.cpp
|
||||
index 921adfc6e02984cb9b0ded70065df16f9241e4e7..f806326113d0804862481ac5508f07eab4d5ebe1 100644
|
||||
--- a/src/libANGLE/renderer/vulkan/QueryVk.cpp
|
||||
+++ b/src/libANGLE/renderer/vulkan/QueryVk.cpp
|
||||
@@ -302,6 +302,13 @@ angle::Result QueryVk::begin(const gl::Context *context)
|
||||
{
|
||||
ContextVk *contextVk = vk::GetImpl(context);
|
||||
|
||||
+ // Ensure that we start with the right RenderPass when we begin a new query.
|
||||
+ if (contextVk->getState().isDrawFramebufferBindingDirty())
|
||||
+ {
|
||||
+ ANGLE_TRY(contextVk->flushCommandsAndEndRenderPass(
|
||||
+ RenderPassClosureReason::FramebufferBindingChange));
|
||||
+ }
|
||||
+
|
||||
mCachedResultValid = false;
|
||||
|
||||
// Transform feedback query is handled by a CPU-calculated value when emulated.
|
||||
@@ -119,6 +119,7 @@ build_disable_print_content_analysis.patch
|
||||
feat_move_firstpartysets_to_content_browser_client.patch
|
||||
custom_protocols_plzserviceworker.patch
|
||||
posix_replace_doubleforkandexec_with_forkandspawn.patch
|
||||
cherry-pick-ecad352cd614.patch
|
||||
cherry-pick-22c61cfae5d1.patch
|
||||
remove_default_window_title.patch
|
||||
keep_handling_scroll_update_if_you_can.patch
|
||||
@@ -137,3 +138,26 @@ cherry-pick-c643d18a078d.patch
|
||||
feat_add_set_can_resize_mutator.patch
|
||||
cherry-pick-2083e894852c.patch
|
||||
cherry-pick-079105b7ebba.patch
|
||||
cherry-pick-51daffbf5cd8.patch
|
||||
cherry-pick-9b5207569882.patch
|
||||
dpwa_enable_window_controls_overlay_by_default.patch
|
||||
cherry-pick-eb4d31309df7.patch
|
||||
add_electron_deps_to_license_credits_file.patch
|
||||
cherry-pick-fefd6198da31.patch
|
||||
cherry-pick-1eb1e18ad41d.patch
|
||||
cherry-pick-9bebe8549a36.patch
|
||||
cherry-pick-05a0d99c9715.patch
|
||||
cherry-pick-cb9dff93f3d4.patch
|
||||
build_allow_electron_to_use_exec_script.patch
|
||||
cherry-pick-933cc81c6bad.patch
|
||||
cherry-pick-67c9cbc784d6.patch
|
||||
cherry-pick-d5ffb4dd4112.patch
|
||||
cherry-pick-06c87f9f42ff.patch
|
||||
refresh_cached_attributes_before_name_computation_traversal.patch
|
||||
review_add_clear_children_checks_during_accname_traversal.patch
|
||||
cherry-pick-1894458e04a2.patch
|
||||
cherry-pick-a1cbf05b4163.patch
|
||||
cherry-pick-ac4785387fff.patch
|
||||
cherry-pick-81cb17c24788.patch
|
||||
fix_crash-on-close_for_mac_udp_sockets.patch
|
||||
cherry-pick-6b4af5d82083.patch
|
||||
|
||||
@@ -0,0 +1,45 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Charles Kerr <charles@charleskerr.com>
|
||||
Date: Tue, 9 Aug 2022 12:35:36 -0500
|
||||
Subject: add electron deps to license credits file
|
||||
|
||||
Ensure that licenses for the dependencies introduced by Electron
|
||||
are included in `LICENSES.chromium.html`
|
||||
|
||||
diff --git a/tools/licenses.py b/tools/licenses.py
|
||||
index b083d3509433aa97aa85c59a4269def5ef5a5359..c032e1f9dc058ff2c76b54ac5da6805163d1eadf 100755
|
||||
--- a/tools/licenses.py
|
||||
+++ b/tools/licenses.py
|
||||
@@ -340,6 +340,32 @@ SPECIAL_CASES = {
|
||||
"License File":
|
||||
"/third_party/swiftshader/third_party/SPIRV-Tools/LICENSE",
|
||||
},
|
||||
+
|
||||
+ os.path.join('third_party', 'electron_node'): {
|
||||
+ "Name": "Node.js",
|
||||
+ "URL": "https://github.com/nodejs/node",
|
||||
+ "License": "MIT",
|
||||
+ "License File": "/third_party/electron_node/LICENSE",
|
||||
+ },
|
||||
+ os.path.join('third_party', 'squirrel.mac'): {
|
||||
+ "Name": "Squirrel",
|
||||
+ "URL": "https://github.com/Squirrel/Squirrel.Mac",
|
||||
+ "License": "MIT",
|
||||
+ "License File": "/third_party/squirrel.mac/LICENSE",
|
||||
+ },
|
||||
+ os.path.join('third_party', 'squirrel.mac', 'vendor', 'mantle'): {
|
||||
+ "Name": "Mantle",
|
||||
+ "URL": "https://github.com/Mantle/Mantle",
|
||||
+ "License": "MIT",
|
||||
+ "License File": "/third_party/squirrel.mac/vendor/mantle/LICENSE.md",
|
||||
+ },
|
||||
+ os.path.join('third_party', 'squirrel.mac', 'vendor', 'ReactiveObjC'): {
|
||||
+ "Name": "ReactiveObjC",
|
||||
+ "URL": "https://github.com/ReactiveCocoa/ReactiveObjC",
|
||||
+ "License": "MIT",
|
||||
+ "License File":
|
||||
+ "/third_party/squirrel.mac/vendor/ReactiveObjC/LICENSE.md",
|
||||
+ },
|
||||
}
|
||||
|
||||
# Special value for 'License File' field used to indicate that the license file
|
||||
@@ -0,0 +1,18 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Samuel Attard <sattard@salesforce.com>
|
||||
Date: Fri, 21 Oct 2022 16:29:06 -0700
|
||||
Subject: build: allow electron to use exec_script
|
||||
|
||||
This is similar to the //build usecase so we're OK adding ourselves here
|
||||
|
||||
diff --git a/.gn b/.gn
|
||||
index 5a11496a47ae7cd2b74992c58760ce1786f7b7df..210463041fa2e46bb368f515afdd4f25e1ca6616 100644
|
||||
--- a/.gn
|
||||
+++ b/.gn
|
||||
@@ -171,4 +171,6 @@ exec_script_whitelist =
|
||||
|
||||
"//tools/grit/grit_rule.gni",
|
||||
"//tools/gritsettings/BUILD.gn",
|
||||
+
|
||||
+ "//electron/BUILD.gn"
|
||||
]
|
||||
34
patches/chromium/cherry-pick-05a0d99c9715.patch
Normal file
34
patches/chromium/cherry-pick-05a0d99c9715.patch
Normal file
@@ -0,0 +1,34 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: David Bokan <bokan@chromium.org>
|
||||
Date: Thu, 28 Jul 2022 18:09:13 +0000
|
||||
Subject: Prevent handling input for provisional frames
|
||||
|
||||
Bug: 1347644,1322812
|
||||
Change-Id: Ifd60f6aa593ce23ca6cbb65552fc9fb8f8690035
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3791883
|
||||
Commit-Queue: David Bokan <bokan@chromium.org>
|
||||
Reviewed-by: Dave Tapuska <dtapuska@chromium.org>
|
||||
Cr-Commit-Position: refs/heads/main@{#1029361}
|
||||
|
||||
diff --git a/third_party/blink/renderer/core/frame/web_frame_widget_impl.cc b/third_party/blink/renderer/core/frame/web_frame_widget_impl.cc
|
||||
index c7d6c63a3c3b640436835e986d2e03ee232b65f0..6106168562e5300b5d15666e1278b207358c63b8 100644
|
||||
--- a/third_party/blink/renderer/core/frame/web_frame_widget_impl.cc
|
||||
+++ b/third_party/blink/renderer/core/frame/web_frame_widget_impl.cc
|
||||
@@ -2448,10 +2448,15 @@ WebInputEventResult WebFrameWidgetImpl::HandleInputEvent(
|
||||
DCHECK(!WebInputEvent::IsTouchEventType(input_event.GetType()));
|
||||
CHECK(LocalRootImpl());
|
||||
|
||||
+ // Clients shouldn't be dispatching events to a provisional frame but this
|
||||
+ // can happen. Ensure that event handling can assume we're in a committed
|
||||
+ // frame.
|
||||
+ if (IsProvisional())
|
||||
+ return WebInputEventResult::kHandledSuppressed;
|
||||
+
|
||||
// Only record metrics for the root frame.
|
||||
- if (ForTopMostMainFrame()) {
|
||||
+ if (ForTopMostMainFrame())
|
||||
GetPage()->GetVisualViewport().StartTrackingPinchStats();
|
||||
- }
|
||||
|
||||
// If a drag-and-drop operation is in progress, ignore input events except
|
||||
// PointerCancel and GestureLongPress.
|
||||
153
patches/chromium/cherry-pick-06c87f9f42ff.patch
Normal file
153
patches/chromium/cherry-pick-06c87f9f42ff.patch
Normal file
@@ -0,0 +1,153 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Rune Lillesveen <futhark@chromium.org>
|
||||
Date: Fri, 14 Oct 2022 09:52:34 +0000
|
||||
Subject: Avoid layout roots in subtrees skipped for style recalc
|
||||
|
||||
Layout roots are laid out from inner to outer in LocalFrameView. DOM
|
||||
mutations may have added layout roots inside size container subtrees
|
||||
before style recalc. If we decide to postpone style recalc until layout
|
||||
of the size container, it means we may try to layout a root inside a
|
||||
subtree skipped for style recalc. That causes a DCHECK and possibly
|
||||
other issues.
|
||||
|
||||
This also fixes the use-after-poison issue 1365330.
|
||||
|
||||
(cherry picked from commit 0f0f1e99201fadb3c68518350e1cd6af1b665346)
|
||||
|
||||
Bug: 1371820, 1365330
|
||||
Change-Id: Ia48890c08aacfe7b9a3e660817702abce0570564
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3934847
|
||||
Reviewed-by: Ian Kilpatrick <ikilpatrick@chromium.org>
|
||||
Commit-Queue: Rune Lillesveen <futhark@chromium.org>
|
||||
Cr-Original-Commit-Position: refs/heads/main@{#1055853}
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3953455
|
||||
Auto-Submit: Rune Lillesveen <futhark@chromium.org>
|
||||
Commit-Queue: Anders Hartvoll Ruud <andruud@chromium.org>
|
||||
Reviewed-by: Anders Hartvoll Ruud <andruud@chromium.org>
|
||||
Cr-Commit-Position: refs/branch-heads/5249@{#836}
|
||||
Cr-Branched-From: 4f7bea5de862aaa52e6bde5920755a9ef9db120b-refs/heads/main@{#1036826}
|
||||
|
||||
diff --git a/third_party/blink/renderer/core/css/style_engine.cc b/third_party/blink/renderer/core/css/style_engine.cc
|
||||
index 80a400738536e80683ec6e7eba78f891966d4e9c..c06274949131f17253c614984402fe13eee66809 100644
|
||||
--- a/third_party/blink/renderer/core/css/style_engine.cc
|
||||
+++ b/third_party/blink/renderer/core/css/style_engine.cc
|
||||
@@ -2643,6 +2643,7 @@ void StyleEngine::RecalcStyle(StyleRecalcChange change,
|
||||
DCHECK(GetDocument().documentElement());
|
||||
ScriptForbiddenScope forbid_script;
|
||||
HasMatchedCacheScope has_matched_cache_scope(&GetDocument());
|
||||
+ SkipStyleRecalcScope skip_scope(*this);
|
||||
Element& root_element = style_recalc_root_.RootElement();
|
||||
Element* parent = FlatTreeTraversal::ParentElement(root_element);
|
||||
|
||||
@@ -3231,4 +3232,17 @@ void StyleEngine::MarkForLayoutTreeChangesAfterDetach() {
|
||||
parent_for_detached_subtree_ = nullptr;
|
||||
}
|
||||
|
||||
+bool StyleEngine::AllowSkipStyleRecalcForScope() const {
|
||||
+ if (InContainerQueryStyleRecalc())
|
||||
+ return true;
|
||||
+ if (LocalFrameView* view = GetDocument().View()) {
|
||||
+ // Existing layout roots before starting style recalc may end up being
|
||||
+ // inside skipped subtrees if we allowed skipping. If we start out with an
|
||||
+ // empty list, any added ones will be a result of an element style recalc,
|
||||
+ // which means the will not be inside a skipped subtree.
|
||||
+ return !view->IsSubtreeLayout();
|
||||
+ }
|
||||
+ return true;
|
||||
+}
|
||||
+
|
||||
} // namespace blink
|
||||
diff --git a/third_party/blink/renderer/core/css/style_engine.h b/third_party/blink/renderer/core/css/style_engine.h
|
||||
index cb18cdff2e2b782a486dcebdda75761a68428a2b..512010d021ae8e726efb02206af6f739fa610346 100644
|
||||
--- a/third_party/blink/renderer/core/css/style_engine.h
|
||||
+++ b/third_party/blink/renderer/core/css/style_engine.h
|
||||
@@ -177,6 +177,20 @@ class CORE_EXPORT StyleEngine final : public GarbageCollected<StyleEngine>,
|
||||
base::AutoReset<bool> allow_marking_;
|
||||
};
|
||||
|
||||
+ // Set up the condition for allowing to skip style recalc before starting
|
||||
+ // RecalcStyle().
|
||||
+ class SkipStyleRecalcScope {
|
||||
+ STACK_ALLOCATED();
|
||||
+
|
||||
+ public:
|
||||
+ explicit SkipStyleRecalcScope(StyleEngine& engine)
|
||||
+ : allow_skip_(&engine.allow_skip_style_recalc_,
|
||||
+ engine.AllowSkipStyleRecalcForScope()) {}
|
||||
+
|
||||
+ private:
|
||||
+ base::AutoReset<bool> allow_skip_;
|
||||
+ };
|
||||
+
|
||||
explicit StyleEngine(Document&);
|
||||
~StyleEngine() override;
|
||||
|
||||
@@ -337,6 +351,10 @@ class CORE_EXPORT StyleEngine final : public GarbageCollected<StyleEngine>,
|
||||
void UpdateStyleRecalcRoot(ContainerNode* ancestor, Node* dirty_node);
|
||||
void UpdateLayoutTreeRebuildRoot(ContainerNode* ancestor, Node* dirty_node);
|
||||
|
||||
+ // Returns true if we can skip style recalc for a size container subtree and
|
||||
+ // resume it during layout.
|
||||
+ bool SkipStyleRecalcAllowed() const { return allow_skip_style_recalc_; }
|
||||
+
|
||||
CSSFontSelector* GetFontSelector() { return font_selector_; }
|
||||
|
||||
void RemoveFontFaceRules(const HeapVector<Member<const StyleRuleFontFace>>&);
|
||||
@@ -719,6 +737,9 @@ class CORE_EXPORT StyleEngine final : public GarbageCollected<StyleEngine>,
|
||||
Element* parent,
|
||||
Element* previous_sibling);
|
||||
|
||||
+ // Initialization value for SkipStyleRecalcScope.
|
||||
+ bool AllowSkipStyleRecalcForScope() const;
|
||||
+
|
||||
Member<Document> document_;
|
||||
|
||||
// Tracks the number of currently loading top-level stylesheets. Sheets loaded
|
||||
@@ -788,6 +809,9 @@ class CORE_EXPORT StyleEngine final : public GarbageCollected<StyleEngine>,
|
||||
// AllowMarkStyleDirtyFromRecalcScope.
|
||||
bool allow_mark_for_reattach_from_rebuild_layout_tree_{false};
|
||||
|
||||
+ // Set to true if we are allowed to skip recalc for a size container subtree.
|
||||
+ bool allow_skip_style_recalc_{false};
|
||||
+
|
||||
// See enum ViewportUnitFlag.
|
||||
unsigned viewport_unit_dirty_flags_{0};
|
||||
|
||||
diff --git a/third_party/blink/renderer/core/dom/element.cc b/third_party/blink/renderer/core/dom/element.cc
|
||||
index 8f60e1e6e2c929e5f58682c924478a62725f73b3..bfbf6b3c103f0b5d79570c9372bfc0f81166a2d7 100644
|
||||
--- a/third_party/blink/renderer/core/dom/element.cc
|
||||
+++ b/third_party/blink/renderer/core/dom/element.cc
|
||||
@@ -3334,6 +3334,10 @@ bool Element::SkipStyleRecalcForContainer(
|
||||
const ComputedStyle& style,
|
||||
const StyleRecalcChange& child_change) {
|
||||
DCHECK(RuntimeEnabledFeatures::CSSContainerSkipStyleRecalcEnabled());
|
||||
+
|
||||
+ if (!GetDocument().GetStyleEngine().SkipStyleRecalcAllowed())
|
||||
+ return false;
|
||||
+
|
||||
if (!child_change.TraversePseudoElements(*this)) {
|
||||
// If none of the children or pseudo elements need to be traversed for style
|
||||
// recalc, there is no point in marking the subtree as skipped.
|
||||
diff --git a/third_party/blink/web_tests/external/wpt/css/css-contain/container-queries/crashtests/chrome-layout-root-crash.html b/third_party/blink/web_tests/external/wpt/css/css-contain/container-queries/crashtests/chrome-layout-root-crash.html
|
||||
new file mode 100644
|
||||
index 0000000000000000000000000000000000000000..e3e709a240bd870250b2747c94fe96880bdf52e3
|
||||
--- /dev/null
|
||||
+++ b/third_party/blink/web_tests/external/wpt/css/css-contain/container-queries/crashtests/chrome-layout-root-crash.html
|
||||
@@ -0,0 +1,17 @@
|
||||
+<!doctype html>
|
||||
+<html class="reftest-wait">
|
||||
+<link rel="help" href="https://crbug.com/1371820">
|
||||
+<style>
|
||||
+ body, div, img { container-type: size; }
|
||||
+</style>
|
||||
+<p>Pass if no crash.</p>
|
||||
+<div id="div"><img id="img" alt="a"></div>
|
||||
+<script>
|
||||
+ requestAnimationFrame(() => requestAnimationFrame(() => {
|
||||
+ // Adds a layout root inside the div size container.
|
||||
+ img.alt = img.src = "b";
|
||||
+ // Marks div size container for layout which skips style recalc for the sub-tree.
|
||||
+ div.style.width = "500px";
|
||||
+ document.documentElement.classList.remove("reftest-wait");
|
||||
+ }));
|
||||
+</script>
|
||||
37
patches/chromium/cherry-pick-1894458e04a2.patch
Normal file
37
patches/chromium/cherry-pick-1894458e04a2.patch
Normal file
@@ -0,0 +1,37 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Joshua Peraza <jperaza@chromium.org>
|
||||
Date: Thu, 3 Nov 2022 21:18:35 +0000
|
||||
Subject: Validate number of bytes read
|
||||
|
||||
Original commit:
|
||||
https://chromium-review.googlesource.com/c/crashpad/crashpad/+/3994208
|
||||
|
||||
(cherry picked from commit 7585111a6c1dfa502f3ca1e3d27aed066e479fd9)
|
||||
|
||||
Bug: chromium:1380083
|
||||
Change-Id: If9708ccdbf6957ef169b35f8f89e2b0744d066d7
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/4000305
|
||||
Reviewed-by: Mark Mentovai <mark@chromium.org>
|
||||
Commit-Queue: Joshua Peraza <jperaza@chromium.org>
|
||||
Cr-Original-Commit-Position: refs/branch-heads/5359@{#529}
|
||||
Cr-Original-Branched-From: 27d3765d341b09369006d030f83f582a29eb57ae-refs/heads/main@{#1058933}
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/4004067
|
||||
Cr-Commit-Position: refs/branch-heads/5249@{#905}
|
||||
Cr-Branched-From: 4f7bea5de862aaa52e6bde5920755a9ef9db120b-refs/heads/main@{#1036826}
|
||||
|
||||
diff --git a/third_party/crashpad/crashpad/util/linux/ptrace_client.cc b/third_party/crashpad/crashpad/util/linux/ptrace_client.cc
|
||||
index 1863841f73f64d89391646f5c3e5fc2e2766a6cc..32cc35d9567117fe0eb6f1ec4736ac4a15ddfd83 100644
|
||||
--- a/third_party/crashpad/crashpad/util/linux/ptrace_client.cc
|
||||
+++ b/third_party/crashpad/crashpad/util/linux/ptrace_client.cc
|
||||
@@ -331,6 +331,11 @@ ssize_t PtraceClient::ReadUpTo(VMAddress address, size_t size, void* buffer) {
|
||||
return total_read;
|
||||
}
|
||||
|
||||
+ if (static_cast<size_t>(bytes_read) > size) {
|
||||
+ LOG(ERROR) << "invalid size " << bytes_read;
|
||||
+ return -1;
|
||||
+ }
|
||||
+
|
||||
if (!LoggingReadFileExactly(sock_, buffer_c, bytes_read)) {
|
||||
return -1;
|
||||
}
|
||||
184
patches/chromium/cherry-pick-1eb1e18ad41d.patch
Normal file
184
patches/chromium/cherry-pick-1eb1e18ad41d.patch
Normal file
@@ -0,0 +1,184 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Anders Hartvoll Ruud <andruud@chromium.org>
|
||||
Date: Tue, 20 Sep 2022 17:43:47 +0000
|
||||
Subject: Add CSSTokenizer-created strings to CSSVariableData's backing strings
|
||||
|
||||
When computing the value of a registered custom property, we create
|
||||
a CSSVariableData object equivalent to the computed CSSValue by
|
||||
serializing that CSSValue to a String, then tokenizing that value.
|
||||
|
||||
The problem is that CSSTokenizer can create *new* string objects
|
||||
during the tokenization process (see calls to CSSTokenizer::
|
||||
RegisterString), without communicating that fact to the call-site.
|
||||
|
||||
Therefore, this CL adds a way to access those strings so they can
|
||||
be added to the backing strings of the CSSVariableData.
|
||||
|
||||
Also added a DCHECK to verify that we don't have any tokens with
|
||||
non-backed string pointers.
|
||||
|
||||
Fixed: 1358907
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3892782
|
||||
Reviewed-by: Steinar H Gunderson <sesse@chromium.org>
|
||||
Commit-Queue: Anders Hartvoll Ruud <andruud@chromium.org>
|
||||
Cr-Original-Commit-Position: refs/heads/main@{#1046868}
|
||||
Change-Id: Ifb6d194508e99030a5a3ed5fbad5496b7263bdc1
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3905727
|
||||
Auto-Submit: Anders Hartvoll Ruud <andruud@chromium.org>
|
||||
Cr-Commit-Position: refs/branch-heads/5249@{#518}
|
||||
Cr-Branched-From: 4f7bea5de862aaa52e6bde5920755a9ef9db120b-refs/heads/main@{#1036826}
|
||||
|
||||
diff --git a/third_party/blink/renderer/core/css/css_variable_data.cc b/third_party/blink/renderer/core/css/css_variable_data.cc
|
||||
index a2294cc70c59ac0357dddf0f7719cc3c09d23554..b3a61b312eb5f0360e8aa4cb706c60f0085fead9 100644
|
||||
--- a/third_party/blink/renderer/core/css/css_variable_data.cc
|
||||
+++ b/third_party/blink/renderer/core/css/css_variable_data.cc
|
||||
@@ -4,6 +4,7 @@
|
||||
|
||||
#include "third_party/blink/renderer/core/css/css_variable_data.h"
|
||||
|
||||
+#include "base/containers/span.h"
|
||||
#include "third_party/blink/renderer/core/css/css_syntax_definition.h"
|
||||
#include "third_party/blink/renderer/core/css/parser/css_parser_context.h"
|
||||
#include "third_party/blink/renderer/platform/wtf/text/character_names.h"
|
||||
@@ -109,6 +110,51 @@ void CSSVariableData::ConsumeAndUpdateTokens(const CSSParserTokenRange& range) {
|
||||
UpdateTokens<UChar>(range, backing_string, tokens_);
|
||||
}
|
||||
|
||||
+#if EXPENSIVE_DCHECKS_ARE_ON()
|
||||
+
|
||||
+namespace {
|
||||
+
|
||||
+template <typename CharacterType>
|
||||
+bool IsSubspan(base::span<const CharacterType> inner,
|
||||
+ base::span<const CharacterType> outer) {
|
||||
+ // Note that base::span uses CheckedContiguousIterator, which restricts
|
||||
+ // which comparisons are allowed. Therefore we must avoid begin()/end() here.
|
||||
+ return inner.data() >= outer.data() &&
|
||||
+ (inner.data() + inner.size()) <= (outer.data() + outer.size());
|
||||
+}
|
||||
+
|
||||
+bool TokenValueIsBacked(const CSSParserToken& token,
|
||||
+ const String& backing_string) {
|
||||
+ StringView value = token.Value();
|
||||
+ if (value.Is8Bit() != backing_string.Is8Bit())
|
||||
+ return false;
|
||||
+ return value.Is8Bit() ? IsSubspan(value.Span8(), backing_string.Span8())
|
||||
+ : IsSubspan(value.Span16(), backing_string.Span16());
|
||||
+}
|
||||
+
|
||||
+bool TokenValueIsBacked(const CSSParserToken& token,
|
||||
+ const Vector<String>& backing_strings) {
|
||||
+ DCHECK(token.HasStringBacking());
|
||||
+ for (const String& backing_string : backing_strings) {
|
||||
+ if (TokenValueIsBacked(token, backing_string)) {
|
||||
+ return true;
|
||||
+ }
|
||||
+ }
|
||||
+ return false;
|
||||
+}
|
||||
+
|
||||
+} // namespace
|
||||
+
|
||||
+void CSSVariableData::VerifyStringBacking() const {
|
||||
+ for (const CSSParserToken& token : tokens_) {
|
||||
+ DCHECK(!token.HasStringBacking() ||
|
||||
+ TokenValueIsBacked(token, backing_strings_))
|
||||
+ << "Token value is not backed: " << token.Value().ToString();
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+#endif // EXPENSIVE_DCHECKS_ARE_ON()
|
||||
+
|
||||
CSSVariableData::CSSVariableData(const CSSTokenizedValue& tokenized_value,
|
||||
bool is_animation_tainted,
|
||||
bool needs_variable_resolution,
|
||||
@@ -120,6 +166,9 @@ CSSVariableData::CSSVariableData(const CSSTokenizedValue& tokenized_value,
|
||||
base_url_(base_url.IsValid() ? base_url.GetString() : String()),
|
||||
charset_(charset) {
|
||||
ConsumeAndUpdateTokens(tokenized_value.range);
|
||||
+#if EXPENSIVE_DCHECKS_ARE_ON()
|
||||
+ VerifyStringBacking();
|
||||
+#endif // EXPENSIVE_DCHECKS_ARE_ON()
|
||||
}
|
||||
|
||||
const CSSValue* CSSVariableData::ParseForSyntax(
|
||||
diff --git a/third_party/blink/renderer/core/css/css_variable_data.h b/third_party/blink/renderer/core/css/css_variable_data.h
|
||||
index f042f85736c2c49f8337c29cb742976c5e97a14b..7be7d201313ec3e591e2c45c9fd5bda327856645 100644
|
||||
--- a/third_party/blink/renderer/core/css/css_variable_data.h
|
||||
+++ b/third_party/blink/renderer/core/css/css_variable_data.h
|
||||
@@ -100,11 +100,18 @@ class CORE_EXPORT CSSVariableData : public RefCounted<CSSVariableData> {
|
||||
has_font_units_(has_font_units),
|
||||
has_root_font_units_(has_root_font_units),
|
||||
base_url_(base_url),
|
||||
- charset_(charset) {}
|
||||
+ charset_(charset) {
|
||||
+#if EXPENSIVE_DCHECKS_ARE_ON()
|
||||
+ VerifyStringBacking();
|
||||
+#endif // EXPENSIVE_DCHECKS_ARE_ON()
|
||||
+ }
|
||||
CSSVariableData(const CSSVariableData&) = delete;
|
||||
CSSVariableData& operator=(const CSSVariableData&) = delete;
|
||||
|
||||
void ConsumeAndUpdateTokens(const CSSParserTokenRange&);
|
||||
+#if EXPENSIVE_DCHECKS_ARE_ON()
|
||||
+ void VerifyStringBacking() const;
|
||||
+#endif // EXPENSIVE_DCHECKS_ARE_ON()
|
||||
|
||||
// tokens_ may have raw pointers to string data, we store the String objects
|
||||
// owning that data in backing_strings_ to keep it alive alongside the
|
||||
diff --git a/third_party/blink/renderer/core/css/parser/css_tokenizer.h b/third_party/blink/renderer/core/css/parser/css_tokenizer.h
|
||||
index 817bcbd4b6b9a9a5519bb92d6870c5b16a19278f..682a44a478bcd0ee3aa1638601650fd420033625 100644
|
||||
--- a/third_party/blink/renderer/core/css/parser/css_tokenizer.h
|
||||
+++ b/third_party/blink/renderer/core/css/parser/css_tokenizer.h
|
||||
@@ -33,6 +33,7 @@ class CORE_EXPORT CSSTokenizer {
|
||||
wtf_size_t Offset() const { return input_.Offset(); }
|
||||
wtf_size_t PreviousOffset() const { return prev_offset_; }
|
||||
StringView StringRangeAt(wtf_size_t start, wtf_size_t length) const;
|
||||
+ const Vector<String>& StringPool() const { return string_pool_; }
|
||||
|
||||
private:
|
||||
CSSParserToken TokenizeSingle();
|
||||
diff --git a/third_party/blink/renderer/core/css/resolver/style_builder_converter.cc b/third_party/blink/renderer/core/css/resolver/style_builder_converter.cc
|
||||
index ae863c8df923f55b116ed1c70557e5d5916794d3..dbc654e9079f4f79fe6883a6ea34e8fa00e1a26f 100644
|
||||
--- a/third_party/blink/renderer/core/css/resolver/style_builder_converter.cc
|
||||
+++ b/third_party/blink/renderer/core/css/resolver/style_builder_converter.cc
|
||||
@@ -2170,6 +2170,10 @@ StyleBuilderConverter::ConvertRegisteredPropertyVariableData(
|
||||
|
||||
Vector<String> backing_strings;
|
||||
backing_strings.push_back(text);
|
||||
+ // CSSTokenizer may allocate new strings for some tokens (e.g. for escapes)
|
||||
+ // and produce tokens that point to those strings. We need to retain those
|
||||
+ // strings (if any) as well.
|
||||
+ backing_strings.AppendVector(tokenizer.StringPool());
|
||||
|
||||
const bool has_font_units = false;
|
||||
const bool has_root_font_units = false;
|
||||
diff --git a/third_party/blink/web_tests/external/wpt/css/css-properties-values-api/registered-property-computation-expected.txt b/third_party/blink/web_tests/external/wpt/css/css-properties-values-api/registered-property-computation-expected.txt
|
||||
index 3823a752b99f506d11c50aee36474c6c51c849cd..eeed0dfc0def17b1ba636f7f6a076caf770e1327 100644
|
||||
--- a/third_party/blink/web_tests/external/wpt/css/css-properties-values-api/registered-property-computation-expected.txt
|
||||
+++ b/third_party/blink/web_tests/external/wpt/css/css-properties-values-api/registered-property-computation-expected.txt
|
||||
@@ -1,5 +1,5 @@
|
||||
This is a testharness.js-based test.
|
||||
-Found 60 tests; 59 PASS, 1 FAIL, 0 TIMEOUT, 0 NOTRUN.
|
||||
+Found 61 tests; 60 PASS, 1 FAIL, 0 TIMEOUT, 0 NOTRUN.
|
||||
PASS <length> values computed are correctly via var()-reference
|
||||
PASS <length> values computed are correctly via var()-reference when font-size is inherited
|
||||
PASS <length> values are computed correctly when font-size is inherited [14em]
|
||||
@@ -60,5 +60,6 @@ PASS * values are computed correctly [50dpi]
|
||||
PASS <resolution> values are computed correctly [1dppx]
|
||||
PASS <resolution> values are computed correctly [96dpi]
|
||||
FAIL <resolution> values are computed correctly [calc(1dppx + 96dpi)] assert_equals: expected "2dppx" but got "0dppx"
|
||||
+PASS * values are computed correctly [url(why)]
|
||||
Harness: the test ran to completion.
|
||||
|
||||
diff --git a/third_party/blink/web_tests/external/wpt/css/css-properties-values-api/registered-property-computation.html b/third_party/blink/web_tests/external/wpt/css/css-properties-values-api/registered-property-computation.html
|
||||
index f03b257246e520bd93055203a5cb27188babc8ca..168495247a3b16a2203fb361f662b6db83044d09 100644
|
||||
--- a/third_party/blink/web_tests/external/wpt/css/css-properties-values-api/registered-property-computation.html
|
||||
+++ b/third_party/blink/web_tests/external/wpt/css/css-properties-values-api/registered-property-computation.html
|
||||
@@ -167,4 +167,6 @@ test_computed_value('<resolution>', '1dppx', '1dppx');
|
||||
test_computed_value('<resolution>', '96dpi', '1dppx');
|
||||
test_computed_value('<resolution>', 'calc(1dppx + 96dpi)', '2dppx');
|
||||
|
||||
+test_computed_value('*', 'url(why)', 'url(why)');
|
||||
+
|
||||
</script>
|
||||
45
patches/chromium/cherry-pick-51daffbf5cd8.patch
Normal file
45
patches/chromium/cherry-pick-51daffbf5cd8.patch
Normal file
@@ -0,0 +1,45 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Yutaka Hirano <yhirano@chromium.org>
|
||||
Date: Mon, 4 Jul 2022 11:48:20 +0000
|
||||
Subject: Fix UAF on network::URLLoader
|
||||
|
||||
network::URLLoader::SetUpUpload calls NotifyCompleted asynchronously,
|
||||
as it can be called in the constructor and we don't want to run
|
||||
NotifyCompleted in the constructor.
|
||||
|
||||
The problem is that it attaches a raw pointer to the method, which leads to a use-after-free problem if the URLLoader is destructed before
|
||||
NotifyCompleted is called.
|
||||
|
||||
Use weak pointers instead of raw pointers to avoid the problem.
|
||||
|
||||
Bug: 1340253
|
||||
Change-Id: Iacb1e772bf7a8e3de4a7bb9de342fea9ba0f3f3c
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3740150
|
||||
Reviewed-by: Kenichi Ishibashi <bashi@chromium.org>
|
||||
Commit-Queue: Yutaka Hirano <yhirano@chromium.org>
|
||||
Cr-Commit-Position: refs/heads/main@{#1020539}
|
||||
|
||||
diff --git a/services/network/url_loader.cc b/services/network/url_loader.cc
|
||||
index dbe9e809898ee720c0670e9c6db73c38658613b2..666e82ee2f14a77592b52159ee81a2029de28172 100644
|
||||
--- a/services/network/url_loader.cc
|
||||
+++ b/services/network/url_loader.cc
|
||||
@@ -793,8 +793,8 @@ void URLLoader::OpenFilesForUpload(const ResourceRequest& request) {
|
||||
// initializing before getting deleted.
|
||||
base::SequencedTaskRunnerHandle::Get()->PostTask(
|
||||
FROM_HERE,
|
||||
- base::BindOnce(&URLLoader::NotifyCompleted, base::Unretained(this),
|
||||
- net::ERR_ACCESS_DENIED));
|
||||
+ base::BindOnce(&URLLoader::NotifyCompleted,
|
||||
+ weak_ptr_factory_.GetWeakPtr(), net::ERR_ACCESS_DENIED));
|
||||
return;
|
||||
}
|
||||
url_request_->LogBlockedBy("Opening Files");
|
||||
@@ -813,7 +813,7 @@ void URLLoader::SetUpUpload(const ResourceRequest& request,
|
||||
// initializing before getting deleted.
|
||||
base::SequencedTaskRunnerHandle::Get()->PostTask(
|
||||
FROM_HERE, base::BindOnce(&URLLoader::NotifyCompleted,
|
||||
- base::Unretained(this), error_code));
|
||||
+ weak_ptr_factory_.GetWeakPtr(), error_code));
|
||||
return;
|
||||
}
|
||||
scoped_refptr<base::SequencedTaskRunner> task_runner =
|
||||
675
patches/chromium/cherry-pick-67c9cbc784d6.patch
Normal file
675
patches/chromium/cherry-pick-67c9cbc784d6.patch
Normal file
@@ -0,0 +1,675 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Lukasz Anforowicz <lukasza@chromium.org>
|
||||
Date: Tue, 30 Aug 2022 19:18:15 +0000
|
||||
Subject: Validate `source_context` in ExtensionHostMsg_OpenChannelToNativeApp.
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
|
||||
After this CL, the Browser process will verify `source_context` in the
|
||||
IPC payload of the ExtensionHostMsg_OpenChannelToNativeApp message and
|
||||
avoid processing malformed or spoofed IPCs.
|
||||
|
||||
Change-Id: I9466dc076c4d07dbb4bec38973000dc0418565f6
|
||||
Bug: 1356234
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3854987
|
||||
Commit-Queue: Łukasz Anforowicz <lukasza@chromium.org>
|
||||
Reviewed-by: Devlin Cronin <rdevlin.cronin@chromium.org>
|
||||
Cr-Commit-Position: refs/heads/main@{#1041118}
|
||||
|
||||
diff --git a/chrome/browser/extensions/extension_security_exploit_browsertest.cc b/chrome/browser/extensions/extension_security_exploit_browsertest.cc
|
||||
index d4c4c8fc301940bbeba31bc49ba63961db92a7ed..2ef2f61da9ae3ed7736575424dd5cbb50eca6a3b 100644
|
||||
--- a/chrome/browser/extensions/extension_security_exploit_browsertest.cc
|
||||
+++ b/chrome/browser/extensions/extension_security_exploit_browsertest.cc
|
||||
@@ -10,6 +10,7 @@
|
||||
#include "base/memory/scoped_refptr.h"
|
||||
#include "base/memory/weak_ptr.h"
|
||||
#include "base/test/bind.h"
|
||||
+#include "build/build_config.h"
|
||||
#include "chrome/browser/chrome_content_browser_client.h"
|
||||
#include "chrome/browser/extensions/extension_browsertest.h"
|
||||
#include "chrome/browser/extensions/extension_tab_util.h"
|
||||
@@ -40,6 +41,10 @@
|
||||
#include "third_party/blink/public/mojom/service_worker/service_worker_database.mojom-forward.h"
|
||||
#include "url/gurl.h"
|
||||
|
||||
+#if !(BUILDFLAG(IS_FUCHSIA))
|
||||
+#include "chrome/browser/extensions/api/messaging/native_messaging_test_util.h"
|
||||
+#endif
|
||||
+
|
||||
namespace extensions {
|
||||
|
||||
// Waits for a kill of the given RenderProcessHost and returns the
|
||||
@@ -233,6 +238,10 @@ class OpenChannelToExtensionExploitTest : public ExtensionBrowserTest {
|
||||
return ipc_message_waiter_->WaitForMessage();
|
||||
}
|
||||
|
||||
+ content::WebContents* active_web_contents() {
|
||||
+ return browser()->tab_strip_model()->GetActiveWebContents();
|
||||
+ }
|
||||
+
|
||||
// Asks the `extension_id` to inject `content_script` into `web_contents`.
|
||||
// Returns true if the content script execution started successfully.
|
||||
bool ExecuteProgrammaticContentScript(content::WebContents* web_contents,
|
||||
@@ -246,61 +255,88 @@ class OpenChannelToExtensionExploitTest : public ExtensionBrowserTest {
|
||||
browser()->profile(), extension_id, background_script);
|
||||
}
|
||||
|
||||
+ const Extension& active_extension() { return *active_extension_; }
|
||||
const ExtensionId& active_extension_id() { return active_extension_->id(); }
|
||||
|
||||
const ExtensionId& spoofed_extension_id() { return spoofed_extension_->id(); }
|
||||
|
||||
private:
|
||||
+ // Installs an `active_extension` and a separate, but otherwise identical
|
||||
+ // `spoofed_extension` (the only difference will be the extension id).
|
||||
void InstallTestExtensions() {
|
||||
- // Install an `active_extension` and a separate, but otherwise identical
|
||||
- // `spoofed_extension` (the only difference will be the extension id).
|
||||
- auto install_extension = [this](TestExtensionDir& dir) -> const Extension* {
|
||||
+ auto install_extension =
|
||||
+ [this](TestExtensionDir& dir,
|
||||
+ const char* extra_manifest_bits) -> const Extension* {
|
||||
const char kManifestTemplate[] = R"(
|
||||
{
|
||||
+ %s
|
||||
"name": "ContentScriptTrackerBrowserTest - Programmatic",
|
||||
"version": "1.0",
|
||||
"manifest_version": 2,
|
||||
+ "permissions": [ "tabs", "<all_urls>", "storage" ],
|
||||
+ "permissions": [
|
||||
+ "tabs",
|
||||
+ "<all_urls>",
|
||||
+ "nativeMessaging"
|
||||
+ ],
|
||||
"permissions": [ "tabs", "<all_urls>" ],
|
||||
"background": {"scripts": ["background_script.js"]}
|
||||
} )";
|
||||
- dir.WriteManifest(kManifestTemplate);
|
||||
+ dir.WriteManifest(
|
||||
+ base::StringPrintf(kManifestTemplate, extra_manifest_bits));
|
||||
dir.WriteFile(FILE_PATH_LITERAL("background_script.js"), "");
|
||||
+ dir.WriteFile(FILE_PATH_LITERAL("page.html"), "<p>page</p>");
|
||||
return LoadExtension(dir.UnpackedPath());
|
||||
};
|
||||
- TestExtensionDir active_dir;
|
||||
- TestExtensionDir spoofed_dir;
|
||||
- active_extension_ = install_extension(active_dir);
|
||||
- spoofed_extension_ = install_extension(spoofed_dir);
|
||||
+#if !(BUILDFLAG(IS_FUCHSIA))
|
||||
+ // The key below corresponds to the extension ID used by
|
||||
+ // ScopedTestNativeMessagingHost::kExtensionId.
|
||||
+ const char kActiveExtensionKey[] = R"(
|
||||
+ "key": "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDcBHwzDvyBQ6bDppkIs9MP4ksKqCMyXQ/A52JivHZKh4YO/9vJsT3oaYhSpDCE9RPocOEQvwsHsFReW2nUEc6OLLyoCFFxIb7KkLGsmfakkut/fFdNJYh0xOTbSN8YvLWcqph09XAY2Y/f0AL7vfO1cuCqtkMt8hFrBGWxDdf9CQIDAQAB",
|
||||
+ )";
|
||||
+#else
|
||||
+ // Native messaging is not available on Fuchsia (i.e.
|
||||
+ // //chrome/browser/extensions/BUILD.gn excludes
|
||||
+ // api/messaging/native_messaging_test_util.h on Fuchsia).
|
||||
+ const char kActiveExtensionKey[] = "";
|
||||
+#endif
|
||||
+ active_extension_ = install_extension(active_dir_, kActiveExtensionKey);
|
||||
+ spoofed_extension_ = install_extension(spoofed_dir_, "");
|
||||
ASSERT_TRUE(active_extension_);
|
||||
ASSERT_TRUE(spoofed_extension_);
|
||||
+#if !(BUILDFLAG(IS_FUCHSIA))
|
||||
+ ASSERT_EQ(active_extension_id(),
|
||||
+ ScopedTestNativeMessagingHost::kExtensionId);
|
||||
+#endif
|
||||
ASSERT_NE(active_extension_id(), spoofed_extension_id());
|
||||
}
|
||||
|
||||
using OpenChannelMessageWaiter =
|
||||
ExtensionMessageWaiter<ExtensionHostMsg_OpenChannelToExtension>;
|
||||
- std::unique_ptr<OpenChannelMessageWaiter> StartInterceptingIpcs(
|
||||
- const GURL& test_page_url) {
|
||||
// Start capturing IPC messages in all future/new RenderProcessHosts.
|
||||
- auto ipc_message_waiter = std::make_unique<OpenChannelMessageWaiter>();
|
||||
+ ipc_message_waiter_ = std::make_unique<OpenChannelMessageWaiter>();
|
||||
|
||||
// Navigate to an arbitrary, mostly empty test page. Make sure that a new
|
||||
// RenderProcessHost is created to make sure it is covered by the
|
||||
- // `ipc_message_waiter`. (A WebUI -> http navigation should swap the
|
||||
+ // `ipc_message_waiter_`. (A WebUI -> http navigation should swap the
|
||||
// RenderProcessHost on all platforms.)
|
||||
- content::WebContents* web_contents =
|
||||
- browser()->tab_strip_model()->GetActiveWebContents();
|
||||
- int old_process_id = web_contents->GetMainFrame()->GetProcess()->GetID();
|
||||
+ GURL test_page_url =
|
||||
+ embedded_test_server()->GetURL("foo.com", "/title1.html");
|
||||
+ int old_process_id =
|
||||
+ active_web_contents()->GetMainFrame()->GetProcess()->GetID();
|
||||
EXPECT_TRUE(
|
||||
ui_test_utils::NavigateToURL(browser(), GURL("chrome://version")));
|
||||
EXPECT_TRUE(ui_test_utils::NavigateToURL(browser(), test_page_url));
|
||||
- int new_process_id = web_contents->GetMainFrame()->GetProcess()->GetID();
|
||||
+ int new_process_id =
|
||||
+ active_web_contents()->GetMainFrame()->GetProcess()->GetID();
|
||||
EXPECT_NE(old_process_id, new_process_id);
|
||||
|
||||
// Only intercept messages from `active_extension`'s content script running
|
||||
// in the main frame's process.
|
||||
std::string matching_extension_id = active_extension_id();
|
||||
- int matching_process_id = new_process_id;
|
||||
- ipc_message_waiter->SetIpcMatcher(base::BindLambdaForTesting(
|
||||
+ int matching_process_id =
|
||||
+ active_web_contents()->GetPrimaryMainFrame()->GetProcess()->GetID();
|
||||
+ ipc_message_waiter_->SetIpcMatcher(base::BindLambdaForTesting(
|
||||
[matching_extension_id, matching_process_id](
|
||||
int captured_render_process_id,
|
||||
const ExtensionHostMsg_OpenChannelToExtension::Param& param) {
|
||||
@@ -317,14 +353,21 @@ class OpenChannelToExtensionExploitTest : public ExtensionBrowserTest {
|
||||
|
||||
return true;
|
||||
}));
|
||||
+ }
|
||||
|
||||
- return ipc_message_waiter;
|
||||
+ // Waits for ExtensionHostMsg_OpenChannelToExtension IPC and returns its
|
||||
+ // payload.
|
||||
+ ExtensionHostMsg_OpenChannelToExtension::Param WaitForMessage() {
|
||||
+ return ipc_message_waiter_->WaitForMessage();
|
||||
}
|
||||
|
||||
+ private:
|
||||
std::unique_ptr<OpenChannelMessageWaiter> ipc_message_waiter_;
|
||||
|
||||
raw_ptr<const Extension> active_extension_ = nullptr;
|
||||
raw_ptr<const Extension> spoofed_extension_ = nullptr;
|
||||
+ TestExtensionDir active_dir_;
|
||||
+ TestExtensionDir spoofed_dir_;
|
||||
};
|
||||
|
||||
IN_PROC_BROWSER_TEST_F(OpenChannelToExtensionExploitTest,
|
||||
@@ -338,24 +381,22 @@ IN_PROC_BROWSER_TEST_F(OpenChannelToExtensionExploitTest,
|
||||
|
||||
// Trigger sending of a valid ExtensionHostMsg_OpenChannelToExtension IPC
|
||||
// from a content script of an `active_extension_id`.
|
||||
- content::WebContents* web_contents =
|
||||
- browser()->tab_strip_model()->GetActiveWebContents();
|
||||
ASSERT_TRUE(ExecuteProgrammaticContentScript(
|
||||
- web_contents, active_extension_id(),
|
||||
+ active_web_contents(), active_extension_id(),
|
||||
"chrome.runtime.sendMessage({greeting: 'hello'}, (response) => {});"));
|
||||
|
||||
// Capture the IPC.
|
||||
auto [source_context, info, channel_name, port_id] = WaitForMessage();
|
||||
-
|
||||
- // Mutate the IPC payload.
|
||||
EXPECT_EQ(MessagingEndpoint::Type::kTab, info.source_endpoint.type);
|
||||
EXPECT_EQ(active_extension_id(), info.source_endpoint.extension_id);
|
||||
+
|
||||
+ // Mutate the IPC payload.
|
||||
info.source_endpoint.extension_id = spoofed_extension_id();
|
||||
|
||||
// Inject the malformed/mutated IPC and verify that the renderer is terminated
|
||||
// as expected.
|
||||
content::RenderProcessHost* main_frame_process =
|
||||
- web_contents->GetMainFrame()->GetProcess();
|
||||
+ active_web_contents()->GetMainFrame()->GetProcess();
|
||||
RenderProcessHostBadIpcMessageWaiter kill_waiter(main_frame_process);
|
||||
IPC::IpcSecurityTestUtil::PwnMessageReceived(
|
||||
main_frame_process->GetChannel(),
|
||||
@@ -369,24 +410,22 @@ IN_PROC_BROWSER_TEST_F(OpenChannelToExtensionExploitTest,
|
||||
FromContentScript_UnexpectedNativeAppType) {
|
||||
// Trigger sending of a valid ExtensionHostMsg_OpenChannelToExtension IPC
|
||||
// from a content script of an `active_extension_id`.
|
||||
- content::WebContents* web_contents =
|
||||
- browser()->tab_strip_model()->GetActiveWebContents();
|
||||
ASSERT_TRUE(ExecuteProgrammaticContentScript(
|
||||
- web_contents, active_extension_id(),
|
||||
+ active_web_contents(), active_extension_id(),
|
||||
"chrome.runtime.sendMessage({greeting: 'hello'}, (response) => {});"));
|
||||
|
||||
// Capture the IPC.
|
||||
auto [source_context, info, channel_name, port_id] = WaitForMessage();
|
||||
-
|
||||
- // Mutate the IPC payload.
|
||||
EXPECT_EQ(MessagingEndpoint::Type::kTab, info.source_endpoint.type);
|
||||
EXPECT_EQ(active_extension_id(), info.source_endpoint.extension_id);
|
||||
+
|
||||
+ // Mutate the IPC payload.
|
||||
info.source_endpoint.type = MessagingEndpoint::Type::kNativeApp;
|
||||
|
||||
// Inject the malformed/mutated IPC and verify that the renderer is terminated
|
||||
// as expected.
|
||||
content::RenderProcessHost* main_frame_process =
|
||||
- web_contents->GetMainFrame()->GetProcess();
|
||||
+ active_web_contents()->GetMainFrame()->GetProcess();
|
||||
RenderProcessHostBadIpcMessageWaiter kill_waiter(main_frame_process);
|
||||
IPC::IpcSecurityTestUtil::PwnMessageReceived(
|
||||
main_frame_process->GetChannel(),
|
||||
@@ -399,24 +438,22 @@ IN_PROC_BROWSER_TEST_F(OpenChannelToExtensionExploitTest,
|
||||
FromContentScript_UnexpectedExtensionType) {
|
||||
// Trigger sending of a valid ExtensionHostMsg_OpenChannelToExtension IPC
|
||||
// from a content script of an `active_extension_id`.
|
||||
- content::WebContents* web_contents =
|
||||
- browser()->tab_strip_model()->GetActiveWebContents();
|
||||
ASSERT_TRUE(ExecuteProgrammaticContentScript(
|
||||
- web_contents, active_extension_id(),
|
||||
+ active_web_contents(), active_extension_id(),
|
||||
"chrome.runtime.sendMessage({greeting: 'hello'}, (response) => {});"));
|
||||
|
||||
// Capture the IPC.
|
||||
auto [source_context, info, channel_name, port_id] = WaitForMessage();
|
||||
-
|
||||
- // Mutate the IPC payload.
|
||||
EXPECT_EQ(MessagingEndpoint::Type::kTab, info.source_endpoint.type);
|
||||
EXPECT_EQ(active_extension_id(), info.source_endpoint.extension_id);
|
||||
+
|
||||
+ // Mutate the IPC payload.
|
||||
info.source_endpoint.type = MessagingEndpoint::Type::kExtension;
|
||||
|
||||
// Inject the malformed/mutated IPC and verify that the renderer is terminated
|
||||
// as expected.
|
||||
content::RenderProcessHost* main_frame_process =
|
||||
- web_contents->GetMainFrame()->GetProcess();
|
||||
+ active_web_contents()->GetMainFrame()->GetProcess();
|
||||
RenderProcessHostBadIpcMessageWaiter kill_waiter(main_frame_process);
|
||||
IPC::IpcSecurityTestUtil::PwnMessageReceived(
|
||||
main_frame_process->GetChannel(),
|
||||
@@ -430,25 +467,23 @@ IN_PROC_BROWSER_TEST_F(OpenChannelToExtensionExploitTest,
|
||||
FromContentScript_NoExtensionIdForExtensionType) {
|
||||
// Trigger sending of a valid ExtensionHostMsg_OpenChannelToExtension IPC
|
||||
// from a content script of an `active_extension_id`.
|
||||
- content::WebContents* web_contents =
|
||||
- browser()->tab_strip_model()->GetActiveWebContents();
|
||||
ASSERT_TRUE(ExecuteProgrammaticContentScript(
|
||||
- web_contents, active_extension_id(),
|
||||
+ active_web_contents(), active_extension_id(),
|
||||
"chrome.runtime.sendMessage({greeting: 'hello'}, (response) => {});"));
|
||||
|
||||
// Capture the IPC.
|
||||
auto [source_context, info, channel_name, port_id] = WaitForMessage();
|
||||
-
|
||||
- // Mutate the IPC payload.
|
||||
EXPECT_EQ(MessagingEndpoint::Type::kTab, info.source_endpoint.type);
|
||||
EXPECT_EQ(active_extension_id(), info.source_endpoint.extension_id);
|
||||
+
|
||||
+ // Mutate the IPC payload.
|
||||
info.source_endpoint.type = MessagingEndpoint::Type::kExtension;
|
||||
info.source_endpoint.extension_id = absl::nullopt;
|
||||
|
||||
// Inject the malformed/mutated IPC and verify that the renderer is terminated
|
||||
// as expected.
|
||||
content::RenderProcessHost* main_frame_process =
|
||||
- web_contents->GetMainFrame()->GetProcess();
|
||||
+ active_web_contents()->GetMainFrame()->GetProcess();
|
||||
RenderProcessHostBadIpcMessageWaiter kill_waiter(main_frame_process);
|
||||
IPC::IpcSecurityTestUtil::PwnMessageReceived(
|
||||
main_frame_process->GetChannel(),
|
||||
@@ -462,18 +497,16 @@ IN_PROC_BROWSER_TEST_F(OpenChannelToExtensionExploitTest,
|
||||
FromContentScript_UnexpectedWorkerContext) {
|
||||
// Trigger sending of a valid ExtensionHostMsg_OpenChannelToExtension IPC
|
||||
// from a content script of an `active_extension_id`.
|
||||
- content::WebContents* web_contents =
|
||||
- browser()->tab_strip_model()->GetActiveWebContents();
|
||||
ASSERT_TRUE(ExecuteProgrammaticContentScript(
|
||||
- web_contents, active_extension_id(),
|
||||
+ active_web_contents(), active_extension_id(),
|
||||
"chrome.runtime.sendMessage({greeting: 'hello'}, (response) => {});"));
|
||||
|
||||
// Capture the IPC.
|
||||
auto [source_context, info, channel_name, port_id] = WaitForMessage();
|
||||
-
|
||||
- // Mutate the IPC payload.
|
||||
EXPECT_TRUE(source_context.is_for_render_frame());
|
||||
EXPECT_FALSE(source_context.is_for_service_worker());
|
||||
+
|
||||
+ // Mutate the IPC payload.
|
||||
source_context.frame = absl::nullopt;
|
||||
source_context.worker = PortContext::WorkerContext(
|
||||
/* thread_id = */ 123, /* version_id = */ 456,
|
||||
@@ -482,7 +515,7 @@ IN_PROC_BROWSER_TEST_F(OpenChannelToExtensionExploitTest,
|
||||
// Inject the malformed/mutated IPC and verify that the renderer is terminated
|
||||
// as expected.
|
||||
content::RenderProcessHost* main_frame_process =
|
||||
- web_contents->GetMainFrame()->GetProcess();
|
||||
+ active_web_contents()->GetMainFrame()->GetProcess();
|
||||
RenderProcessHostBadIpcMessageWaiter kill_waiter(main_frame_process);
|
||||
IPC::IpcSecurityTestUtil::PwnMessageReceived(
|
||||
main_frame_process->GetChannel(),
|
||||
@@ -492,4 +525,148 @@ IN_PROC_BROWSER_TEST_F(OpenChannelToExtensionExploitTest,
|
||||
kill_waiter.Wait());
|
||||
}
|
||||
|
||||
+// Native messaging is not available on Fuchsia (i.e.
|
||||
+// //chrome/browser/extensions/BUILD.gn excludes
|
||||
+// api/messaging/native_messaging_test_util.h on Fuchsia).
|
||||
+#if !(BUILDFLAG(IS_FUCHSIA))
|
||||
+
|
||||
+// Test suite for covering ExtensionHostMsg_OpenChannelToNativeApp IPC.
|
||||
+class OpenChannelToNativeAppExploitTest
|
||||
+ : public ExtensionSecurityExploitBrowserTest {
|
||||
+ public:
|
||||
+ OpenChannelToNativeAppExploitTest() = default;
|
||||
+
|
||||
+ using OpenChannelMessageWaiter =
|
||||
+ ExtensionMessageWaiter<ExtensionHostMsg_OpenChannelToNativeApp>;
|
||||
+ void SetUpOnMainThread() override {
|
||||
+ // Set up ExtensionMessageWaiter *before* installing the extensions (i.e.
|
||||
+ // *before* the corresponding RenderProcessHost objects are created).
|
||||
+ ipc_message_waiter_ = std::make_unique<OpenChannelMessageWaiter>();
|
||||
+
|
||||
+ // SetUpOnMainThread in the base class will install the test extensions.
|
||||
+ ExtensionSecurityExploitBrowserTest::SetUpOnMainThread();
|
||||
+
|
||||
+ // Register a (fake, test-only) native messaging host.
|
||||
+ test_native_messaging_host_.RegisterTestHost(/* user_level= */ false);
|
||||
+
|
||||
+ // Navigate the test tab to an extension page.
|
||||
+ GURL test_page_url = active_extension().GetResourceURL("page.html");
|
||||
+ EXPECT_TRUE(ui_test_utils::NavigateToURL(browser(), test_page_url));
|
||||
+
|
||||
+ // Only intercept messages from the test process.
|
||||
+ int matching_process_id =
|
||||
+ active_web_contents()->GetPrimaryMainFrame()->GetProcess()->GetID();
|
||||
+ ipc_message_waiter_->SetIpcMatcher(base::BindLambdaForTesting(
|
||||
+ [matching_process_id](
|
||||
+ int captured_render_process_id,
|
||||
+ const ExtensionHostMsg_OpenChannelToNativeApp::Param& param) {
|
||||
+ if (captured_render_process_id != matching_process_id)
|
||||
+ return false;
|
||||
+
|
||||
+ return true;
|
||||
+ }));
|
||||
+ }
|
||||
+
|
||||
+ // Waits for ExtensionHostMsg_OpenChannelToNativeApp IPC and returns its
|
||||
+ // payload.
|
||||
+ ExtensionHostMsg_OpenChannelToNativeApp::Param WaitForMessage() {
|
||||
+ return ipc_message_waiter_->WaitForMessage();
|
||||
+ }
|
||||
+
|
||||
+ private:
|
||||
+ ScopedTestNativeMessagingHost test_native_messaging_host_;
|
||||
+ std::unique_ptr<OpenChannelMessageWaiter> ipc_message_waiter_;
|
||||
+};
|
||||
+
|
||||
+IN_PROC_BROWSER_TEST_F(OpenChannelToNativeAppExploitTest,
|
||||
+ SourceContextWithSpoofedExtensionId) {
|
||||
+ // Trigger sending of a valid ExtensionHostMsg_OpenChannelToNativeApp IPC
|
||||
+ // from a frame of an `active_extension`.
|
||||
+ const char kScript[] = R"(
|
||||
+ var message = {text: 'Hello!'};
|
||||
+ var host = $1;
|
||||
+ chrome.runtime.sendNativeMessage(host, message);
|
||||
+ )";
|
||||
+ ASSERT_EQ(
|
||||
+ active_extension().origin(),
|
||||
+ active_web_contents()->GetPrimaryMainFrame()->GetLastCommittedOrigin());
|
||||
+ ASSERT_TRUE(content::ExecuteScript(
|
||||
+ active_web_contents(),
|
||||
+ content::JsReplace(kScript, ScopedTestNativeMessagingHost::kHostName)));
|
||||
+
|
||||
+ // Capture the IPC.
|
||||
+ auto [source_context, native_app_name, port_id] = WaitForMessage();
|
||||
+ EXPECT_EQ(native_app_name, ScopedTestNativeMessagingHost::kHostName);
|
||||
+ EXPECT_TRUE(source_context.is_for_render_frame());
|
||||
+
|
||||
+ // Mutate the IPC payload.
|
||||
+ source_context = PortContext::ForWorker(123, // thread_id
|
||||
+ 456, // version_id
|
||||
+ spoofed_extension_id());
|
||||
+
|
||||
+ // Inject the malformed/mutated IPC and verify that the renderer is terminated
|
||||
+ // as expected.
|
||||
+ content::RenderProcessHost* main_frame_process =
|
||||
+ active_web_contents()->GetPrimaryMainFrame()->GetProcess();
|
||||
+ RenderProcessHostBadIpcMessageWaiter kill_waiter(main_frame_process);
|
||||
+ IPC::IpcSecurityTestUtil::PwnMessageReceived(
|
||||
+ main_frame_process->GetChannel(),
|
||||
+ ExtensionHostMsg_OpenChannelToNativeApp(source_context, native_app_name,
|
||||
+ port_id));
|
||||
+ EXPECT_EQ(bad_message::EMF_INVALID_EXTENSION_ID_FOR_WORKER_CONTEXT,
|
||||
+ kill_waiter.Wait());
|
||||
+}
|
||||
+
|
||||
+#endif // !(BUILDFLAG(IS_FUCHSIA)) - native messaging is available
|
||||
+
|
||||
+IN_PROC_BROWSER_TEST_F(ExtensionSecurityExploitBrowserTest,
|
||||
+ SpoofedExtensionId_ExtensionFunctionDispatcher) {
|
||||
+ // Navigate to a test page.
|
||||
+ GURL test_page_url =
|
||||
+ embedded_test_server()->GetURL("foo.com", "/title1.html");
|
||||
+ ASSERT_TRUE(ui_test_utils::NavigateToURL(browser(), test_page_url));
|
||||
+ content::RenderFrameHost* main_frame =
|
||||
+ active_web_contents()->GetPrimaryMainFrame();
|
||||
+
|
||||
+ // Verify the test setup by checking if the non-intercepted `chrome.storage`
|
||||
+ // API call will succeed.
|
||||
+ {
|
||||
+ ExtensionTestMessageListener listener("Got chrome.storage response");
|
||||
+ ExecuteProgrammaticContentScript(active_web_contents(),
|
||||
+ active_extension_id(), R"(
|
||||
+ chrome.storage.local.set(
|
||||
+ { test_key: 'test value'},
|
||||
+ () => {
|
||||
+ chrome.test.sendMessage('Got chrome.storage response');
|
||||
+ }
|
||||
+ ); )");
|
||||
+ ASSERT_TRUE(listener.WaitUntilSatisfied());
|
||||
+ }
|
||||
+
|
||||
+ // Prepare to mutate the extension id in the IPC associated with the
|
||||
+ // `chrome.storage.local.set`.
|
||||
+ auto interceptor = std::make_unique<ExtensionFrameHostInterceptor>(
|
||||
+ main_frame,
|
||||
+ base::BindLambdaForTesting([this](mojom::RequestParams& request_params) {
|
||||
+ if (request_params.name != "storage.set")
|
||||
+ return;
|
||||
+
|
||||
+ EXPECT_EQ(active_extension_id(), request_params.extension_id);
|
||||
+ request_params.extension_id = spoofed_extension_id();
|
||||
+ }));
|
||||
+
|
||||
+ // Trigger an IPC associated with the `chrome.storage.local.set` API and
|
||||
+ // verify that the mutated/spoofed extension id is detected and leads to
|
||||
+ // terminating the misbehaving renderer process.
|
||||
+ content::RenderProcessHostBadMojoMessageWaiter kill_waiter(
|
||||
+ main_frame->GetProcess());
|
||||
+ ExecuteProgrammaticContentScript(active_web_contents(), active_extension_id(),
|
||||
+ R"(
|
||||
+ chrome.storage.local.set({ test_key: 'test value2'}, () => {}); )");
|
||||
+ EXPECT_EQ(
|
||||
+ "Received bad user message: LocalFrameHost::Request: renderer never "
|
||||
+ "hosted such extension",
|
||||
+ kill_waiter.Wait());
|
||||
+}
|
||||
+
|
||||
} // namespace extensions
|
||||
diff --git a/docs/security/compromised-renderers.md b/docs/security/compromised-renderers.md
|
||||
index b7e56be454f2d42dc4ae4ac875586a01f2354d9a..2155a399e0e432fedc2792b6893440efd7fca572 100644
|
||||
--- a/docs/security/compromised-renderers.md
|
||||
+++ b/docs/security/compromised-renderers.md
|
||||
@@ -213,14 +213,21 @@ Compromised renderers shouldn’t be able to:
|
||||
- Spoof the `MessageEvent.origin` seen by a recipient of a `postMessage`.
|
||||
- Bypass enforcement of the `targetOrigin` argument of `postMessage`.
|
||||
- Send or receive `BroadcastChannel` messages for another origin.
|
||||
-- Spoof the `MessageSender.origin` seen by a recipient of a
|
||||
- `chrome.runtime.sendMessage`
|
||||
- (see also [MessageSender documentation](https://developers.chrome.com/extensions/runtime#type-MessageSender) and [content script security guidance](https://groups.google.com/a/chromium.org/forum/#!topic/chromium-extensions/0ei-UCHNm34)).
|
||||
+- Spoof the `MessageSender.origin`, nor `MessageSender.id` (i.e. an
|
||||
+ extension id which can differ from the origin when the message is sent
|
||||
+ from a content script), as seen by a recipient of a
|
||||
+ `chrome.runtime.sendMessage`.
|
||||
+ See also [MessageSender documentation](https://developers.chrome.com/extensions/runtime#type-MessageSender) and [content script security guidance](https://groups.google.com/a/chromium.org/forum/#!topic/chromium-extensions/0ei-UCHNm34).
|
||||
+- Spoof the id of a Chrome extension initiating
|
||||
+ [native messaging](https://developer.chrome.com/docs/apps/nativeMessaging/)
|
||||
+ communication.
|
||||
|
||||
Protection techniques:
|
||||
- Using `CanAccessDataForOrigin` to verify IPCs sent by a renderer process
|
||||
(e.g. in `RenderFrameProxyHost::OnRouteMessageEvent` or
|
||||
`BroadcastChannelProvider::ConnectToChannel`).
|
||||
+- Using `ContentScriptTracker` to check if IPCs from a given renderer process
|
||||
+ can legitimately claim to act on behalf content scripts of a given extension.
|
||||
|
||||
**Known gaps in protection**:
|
||||
- Spoofing of `MessageSender.id` object
|
||||
diff --git a/extensions/browser/api/messaging/messaging_api_message_filter.cc b/extensions/browser/api/messaging/messaging_api_message_filter.cc
|
||||
index 5469f5e91bfbb98aece208e9fffa8139dc9dacdf..e57cffb46d74229fff2534f7bb9f9fa3ddbc3d26 100644
|
||||
--- a/extensions/browser/api/messaging/messaging_api_message_filter.cc
|
||||
+++ b/extensions/browser/api/messaging/messaging_api_message_filter.cc
|
||||
@@ -156,6 +156,16 @@ bool IsValidSourceContext(RenderProcessHost& process,
|
||||
}
|
||||
}
|
||||
|
||||
+ // This function doesn't validate frame-flavoured `source_context`s, because
|
||||
+ // PortContext::FrameContext only contains frame's `routing_id` and therefore
|
||||
+ // inherently cannot spoof frames in another process (a frame is identified
|
||||
+ // by its `routing_id` *and* the `process_id` of the Renderer process hosting
|
||||
+ // the frame; the latter is trustworthy / doesn't come from an IPC payload).
|
||||
+
|
||||
+ // This function doesn't validate native app `source_context`s, because
|
||||
+ // `PortContext::ForNativeHost()` is called with trustoworthy inputs (e.g. it
|
||||
+ // doesn't take input from IPCs sent by a Renderer process).
|
||||
+
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -227,6 +237,18 @@ void MessagingAPIMessageFilter::Shutdown() {
|
||||
shutdown_notifier_subscription_ = {};
|
||||
}
|
||||
|
||||
+content::RenderProcessHost* MessagingAPIMessageFilter::GetRenderProcessHost() {
|
||||
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
|
||||
+ if (!browser_context_)
|
||||
+ return nullptr;
|
||||
+
|
||||
+ // The IPC might race with RenderProcessHost destruction. This may only
|
||||
+ // happen in scenarios that are already inherently racey, so returning nullptr
|
||||
+ // (and dropping the IPC) is okay and won't lead to any additional risk of
|
||||
+ // data loss.
|
||||
+ return content::RenderProcessHost::FromID(render_process_id_);
|
||||
+}
|
||||
+
|
||||
void MessagingAPIMessageFilter::OverrideThreadForMessage(
|
||||
const IPC::Message& message,
|
||||
BrowserThread::ID* thread) {
|
||||
@@ -272,19 +294,14 @@ void MessagingAPIMessageFilter::OnOpenChannelToExtension(
|
||||
const std::string& channel_name,
|
||||
const PortId& port_id) {
|
||||
DCHECK_CURRENTLY_ON(BrowserThread::UI);
|
||||
- if (!browser_context_)
|
||||
- return;
|
||||
-
|
||||
- // The IPC might race with RenderProcessHost destruction. This may only
|
||||
- // happen in scenarios that are already inherently racey, so dropping the IPC
|
||||
- // is okay and won't lead to any additional risk of data loss.
|
||||
- auto* process = content::RenderProcessHost::FromID(render_process_id_);
|
||||
+ auto* process = GetRenderProcessHost();
|
||||
if (!process)
|
||||
return;
|
||||
TRACE_EVENT("extensions", "MessageFilter::OnOpenChannelToExtension",
|
||||
ChromeTrackEvent::kRenderProcessHost, *process);
|
||||
|
||||
ScopedExternalConnectionInfoCrashKeys info_crash_keys(info);
|
||||
+ debug::ScopedPortContextCrashKeys port_context_crash_keys(source_context);
|
||||
if (!IsValidMessagingSource(*process, info.source_endpoint) ||
|
||||
!IsValidSourceContext(*process, source_context)) {
|
||||
return;
|
||||
@@ -303,7 +320,14 @@ void MessagingAPIMessageFilter::OnOpenChannelToNativeApp(
|
||||
const std::string& native_app_name,
|
||||
const PortId& port_id) {
|
||||
DCHECK_CURRENTLY_ON(BrowserThread::UI);
|
||||
- if (!browser_context_)
|
||||
+ auto* process = GetRenderProcessHost();
|
||||
+ if (!process)
|
||||
+ return;
|
||||
+ TRACE_EVENT("extensions", "MessageFilter::OnOpenChannelToNativeApp",
|
||||
+ ChromeTrackEvent::kRenderProcessHost, *process);
|
||||
+
|
||||
+ debug::ScopedPortContextCrashKeys port_context_crash_keys(source_context);
|
||||
+ if (!IsValidSourceContext(*process, source_context))
|
||||
return;
|
||||
|
||||
ChannelEndpoint source_endpoint(browser_context_, render_process_id_,
|
||||
diff --git a/extensions/browser/api/messaging/messaging_api_message_filter.h b/extensions/browser/api/messaging/messaging_api_message_filter.h
|
||||
index 6a0ccd698629f650d68f2b4ee168aa2b3b3a116c..3358187387cd9a5765a7bd4e522aeecfd787e06b 100644
|
||||
--- a/extensions/browser/api/messaging/messaging_api_message_filter.h
|
||||
+++ b/extensions/browser/api/messaging/messaging_api_message_filter.h
|
||||
@@ -14,6 +14,7 @@ struct ExtensionMsg_TabTargetConnectionInfo;
|
||||
|
||||
namespace content {
|
||||
class BrowserContext;
|
||||
+class RenderProcessHost;
|
||||
}
|
||||
|
||||
namespace extensions {
|
||||
@@ -40,6 +41,11 @@ class MessagingAPIMessageFilter : public content::BrowserMessageFilter {
|
||||
|
||||
void Shutdown();
|
||||
|
||||
+ // Returns the process that the IPC came from, or `nullptr` if the IPC should
|
||||
+ // be dropped (in case the IPC arrived racily after the process or its
|
||||
+ // BrowserContext already got destructed).
|
||||
+ content::RenderProcessHost* GetRenderProcessHost();
|
||||
+
|
||||
// content::BrowserMessageFilter implementation:
|
||||
void OverrideThreadForMessage(const IPC::Message& message,
|
||||
content::BrowserThread::ID* thread) override;
|
||||
diff --git a/extensions/common/api/messaging/port_context.cc b/extensions/common/api/messaging/port_context.cc
|
||||
index 6872179450d8295de7f15dc1437e9d6edefe4fde..319e2f34eca730c5eb7cf94ef8cdede0ddc3f8e1 100644
|
||||
--- a/extensions/common/api/messaging/port_context.cc
|
||||
+++ b/extensions/common/api/messaging/port_context.cc
|
||||
@@ -40,4 +40,27 @@ PortContext PortContext::ForNativeHost() {
|
||||
return PortContext();
|
||||
}
|
||||
|
||||
+namespace debug {
|
||||
+
|
||||
+namespace {
|
||||
+
|
||||
+base::debug::CrashKeyString* GetServiceWorkerExtensionIdCrashKey() {
|
||||
+ static auto* crash_key = base::debug::AllocateCrashKeyString(
|
||||
+ "PortContext-worker-extension_id", base::debug::CrashKeySize::Size64);
|
||||
+ return crash_key;
|
||||
+}
|
||||
+
|
||||
+} // namespace
|
||||
+
|
||||
+ScopedPortContextCrashKeys::ScopedPortContextCrashKeys(
|
||||
+ const PortContext& port_context) {
|
||||
+ if (port_context.is_for_service_worker()) {
|
||||
+ extension_id_.emplace(GetServiceWorkerExtensionIdCrashKey(),
|
||||
+ port_context.worker->extension_id);
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+ScopedPortContextCrashKeys::~ScopedPortContextCrashKeys() = default;
|
||||
+
|
||||
+} // namespace debug
|
||||
} // namespace extensions
|
||||
diff --git a/extensions/common/api/messaging/port_context.h b/extensions/common/api/messaging/port_context.h
|
||||
index b2e9f057b531d90dc256773959cd586953e4915c..53d94c2ad73c58d45b186a32989e2f4864e67d79 100644
|
||||
--- a/extensions/common/api/messaging/port_context.h
|
||||
+++ b/extensions/common/api/messaging/port_context.h
|
||||
@@ -9,6 +9,7 @@
|
||||
|
||||
#include <string>
|
||||
|
||||
+#include "base/debug/crash_logging.h"
|
||||
#include "third_party/abseil-cpp/absl/types/optional.h"
|
||||
|
||||
namespace extensions {
|
||||
@@ -59,6 +60,19 @@ struct PortContext {
|
||||
absl::optional<WorkerContext> worker;
|
||||
};
|
||||
|
||||
+namespace debug {
|
||||
+
|
||||
+class ScopedPortContextCrashKeys {
|
||||
+ public:
|
||||
+ explicit ScopedPortContextCrashKeys(const PortContext& port_context);
|
||||
+ ~ScopedPortContextCrashKeys();
|
||||
+
|
||||
+ private:
|
||||
+ absl::optional<base::debug::ScopedCrashKeyString> extension_id_;
|
||||
+};
|
||||
+
|
||||
+} // namespace debug
|
||||
+
|
||||
} // namespace extensions
|
||||
|
||||
#endif // EXTENSIONS_COMMON_API_MESSAGING_PORT_CONTEXT_H_
|
||||
292
patches/chromium/cherry-pick-6b4af5d82083.patch
Normal file
292
patches/chromium/cherry-pick-6b4af5d82083.patch
Normal file
@@ -0,0 +1,292 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Peng Huang <penghuang@chromium.org>
|
||||
Date: Wed, 23 Nov 2022 00:16:49 +0000
|
||||
Subject: Fix potential OOB problem with validating command decoder
|
||||
|
||||
Bug: 1392715
|
||||
Change-Id: If51b10cc08e5b3ca4b6012b97261347a5e4c134e
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/4048203
|
||||
Auto-Submit: Peng Huang <penghuang@chromium.org>
|
||||
Commit-Queue: Peng Huang <penghuang@chromium.org>
|
||||
Reviewed-by: Geoff Lang <geofflang@chromium.org>
|
||||
Cr-Commit-Position: refs/heads/main@{#1074966}
|
||||
|
||||
diff --git a/gpu/command_buffer/service/gles2_cmd_decoder.cc b/gpu/command_buffer/service/gles2_cmd_decoder.cc
|
||||
index 4847ff3403f318d66b70eaa4444a90e5de8689f2..83055ae687e85fafb6c498aee471d58ecc47880a 100644
|
||||
--- a/gpu/command_buffer/service/gles2_cmd_decoder.cc
|
||||
+++ b/gpu/command_buffer/service/gles2_cmd_decoder.cc
|
||||
@@ -8655,10 +8655,18 @@ void GLES2DecoderImpl::DoFramebufferTexture2DCommon(
|
||||
service_id = texture_ref->service_id();
|
||||
}
|
||||
|
||||
+ bool valid_target = false;
|
||||
+ if (texture_ref) {
|
||||
+ valid_target = texture_manager()->ValidForTextureTarget(
|
||||
+ texture_ref->texture(), level, 0, 0, 1);
|
||||
+ } else {
|
||||
+ valid_target = texture_manager()->ValidForTarget(textarget, level, 0, 0, 1);
|
||||
+ }
|
||||
+
|
||||
if ((level > 0 && !feature_info_->IsWebGL2OrES3Context() &&
|
||||
!(fbo_render_mipmap_explicitly_enabled_ &&
|
||||
feature_info_->feature_flags().oes_fbo_render_mipmap)) ||
|
||||
- !texture_manager()->ValidForTarget(textarget, level, 0, 0, 1)) {
|
||||
+ !valid_target) {
|
||||
LOCAL_SET_GL_ERROR(
|
||||
GL_INVALID_VALUE,
|
||||
name, "level out of range");
|
||||
@@ -8730,8 +8738,8 @@ void GLES2DecoderImpl::DoFramebufferTextureLayer(
|
||||
"texture is neither TEXTURE_3D nor TEXTURE_2D_ARRAY");
|
||||
return;
|
||||
}
|
||||
- if (!texture_manager()->ValidForTarget(texture_target, level,
|
||||
- 0, 0, layer)) {
|
||||
+ if (!texture_manager()->ValidForTextureTarget(texture_ref->texture(), level,
|
||||
+ 0, 0, layer)) {
|
||||
LOCAL_SET_GL_ERROR(
|
||||
GL_INVALID_VALUE, function_name, "invalid level or layer");
|
||||
return;
|
||||
@@ -15112,11 +15120,6 @@ error::Error GLES2DecoderImpl::DoCompressedTexImage(
|
||||
LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, func_name, "imageSize < 0");
|
||||
return error::kNoError;
|
||||
}
|
||||
- if (!texture_manager()->ValidForTarget(target, level, width, height, depth) ||
|
||||
- border != 0) {
|
||||
- LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, func_name, "dimensions out of range");
|
||||
- return error::kNoError;
|
||||
- }
|
||||
TextureRef* texture_ref = texture_manager()->GetTextureInfoForTarget(
|
||||
&state_, target);
|
||||
if (!texture_ref) {
|
||||
@@ -15125,6 +15128,12 @@ error::Error GLES2DecoderImpl::DoCompressedTexImage(
|
||||
return error::kNoError;
|
||||
}
|
||||
Texture* texture = texture_ref->texture();
|
||||
+ if (!texture_manager()->ValidForTextureTarget(texture, level, width, height,
|
||||
+ depth) ||
|
||||
+ border != 0) {
|
||||
+ LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, func_name, "dimensions out of range");
|
||||
+ return error::kNoError;
|
||||
+ }
|
||||
if (texture->IsImmutable()) {
|
||||
LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, func_name, "texture is immutable");
|
||||
return error::kNoError;
|
||||
@@ -15494,10 +15503,6 @@ error::Error GLES2DecoderImpl::DoCompressedTexSubImage(
|
||||
LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, func_name, "imageSize < 0");
|
||||
return error::kNoError;
|
||||
}
|
||||
- if (!texture_manager()->ValidForTarget(target, level, width, height, depth)) {
|
||||
- LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, func_name, "dimensions out of range");
|
||||
- return error::kNoError;
|
||||
- }
|
||||
TextureRef* texture_ref = texture_manager()->GetTextureInfoForTarget(
|
||||
&state_, target);
|
||||
if (!texture_ref) {
|
||||
@@ -15505,7 +15510,14 @@ error::Error GLES2DecoderImpl::DoCompressedTexSubImage(
|
||||
GL_INVALID_OPERATION, func_name, "no texture bound at target");
|
||||
return error::kNoError;
|
||||
}
|
||||
+
|
||||
Texture* texture = texture_ref->texture();
|
||||
+ if (!texture_manager()->ValidForTextureTarget(texture, level, width, height,
|
||||
+ depth)) {
|
||||
+ LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, func_name, "dimensions out of range");
|
||||
+ return error::kNoError;
|
||||
+ }
|
||||
+
|
||||
GLenum type = 0;
|
||||
GLenum internal_format = 0;
|
||||
if (!texture->GetLevelType(target, level, &type, &internal_format)) {
|
||||
@@ -15630,7 +15642,8 @@ void GLES2DecoderImpl::DoCopyTexImage2D(
|
||||
GL_INVALID_OPERATION, func_name, "texture is immutable");
|
||||
return;
|
||||
}
|
||||
- if (!texture_manager()->ValidForTarget(target, level, width, height, 1) ||
|
||||
+ if (!texture_manager()->ValidForTextureTarget(texture, level, width, height,
|
||||
+ 1) ||
|
||||
border != 0) {
|
||||
LOCAL_SET_GL_ERROR(
|
||||
GL_INVALID_VALUE, func_name, "dimensions out of range");
|
||||
@@ -18227,8 +18240,8 @@ void GLES2DecoderImpl::DoCopyTextureCHROMIUM(
|
||||
}
|
||||
|
||||
// Check that this type of texture is allowed.
|
||||
- if (!texture_manager()->ValidForTarget(source_target, source_level,
|
||||
- source_width, source_height, 1)) {
|
||||
+ if (!texture_manager()->ValidForTextureTarget(
|
||||
+ source_texture, source_level, source_width, source_height, 1)) {
|
||||
LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, kFunctionName, "Bad dimensions");
|
||||
return;
|
||||
}
|
||||
@@ -18395,8 +18408,8 @@ void GLES2DecoderImpl::CopySubTextureHelper(const char* function_name,
|
||||
}
|
||||
|
||||
// Check that this type of texture is allowed.
|
||||
- if (!texture_manager()->ValidForTarget(source_target, source_level,
|
||||
- source_width, source_height, 1)) {
|
||||
+ if (!texture_manager()->ValidForTextureTarget(
|
||||
+ source_texture, source_level, source_width, source_height, 1)) {
|
||||
LOCAL_SET_GL_ERROR(GL_INVALID_VALUE, function_name,
|
||||
"source texture bad dimensions");
|
||||
return;
|
||||
@@ -18636,11 +18649,20 @@ void GLES2DecoderImpl::TexStorageImpl(GLenum target,
|
||||
return;
|
||||
}
|
||||
}
|
||||
+ TextureRef* texture_ref =
|
||||
+ texture_manager()->GetTextureInfoForTarget(&state_, target);
|
||||
+ if (!texture_ref) {
|
||||
+ LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, function_name,
|
||||
+ "unknown texture for target");
|
||||
+ return;
|
||||
+ }
|
||||
+ Texture* texture = texture_ref->texture();
|
||||
// The glTexStorage entry points require width, height, and depth to be
|
||||
// at least 1, but the other texture entry points (those which use
|
||||
- // ValidForTarget) do not. So we have to add an extra check here.
|
||||
+ // ValidForTextureTarget) do not. So we have to add an extra check here.
|
||||
bool is_invalid_texstorage_size = width < 1 || height < 1 || depth < 1;
|
||||
- if (!texture_manager()->ValidForTarget(target, 0, width, height, depth) ||
|
||||
+ if (!texture_manager()->ValidForTextureTarget(texture, 0, width, height,
|
||||
+ depth) ||
|
||||
is_invalid_texstorage_size) {
|
||||
LOCAL_SET_GL_ERROR(
|
||||
GL_INVALID_VALUE, function_name, "dimensions out of range");
|
||||
@@ -18653,14 +18675,6 @@ void GLES2DecoderImpl::TexStorageImpl(GLenum target,
|
||||
LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, function_name, "too many levels");
|
||||
return;
|
||||
}
|
||||
- TextureRef* texture_ref = texture_manager()->GetTextureInfoForTarget(
|
||||
- &state_, target);
|
||||
- if (!texture_ref) {
|
||||
- LOCAL_SET_GL_ERROR(
|
||||
- GL_INVALID_OPERATION, function_name, "unknown texture for target");
|
||||
- return;
|
||||
- }
|
||||
- Texture* texture = texture_ref->texture();
|
||||
if (texture->IsAttachedToFramebuffer()) {
|
||||
framebuffer_state_.clear_state_dirty = true;
|
||||
}
|
||||
diff --git a/gpu/command_buffer/service/texture_manager.cc b/gpu/command_buffer/service/texture_manager.cc
|
||||
index b20b875b6b37c36623b41e648e393ded96bae93b..f5df8270a8192d36b95e619248c128167455ef46 100644
|
||||
--- a/gpu/command_buffer/service/texture_manager.cc
|
||||
+++ b/gpu/command_buffer/service/texture_manager.cc
|
||||
@@ -1641,7 +1641,7 @@ void Texture::Update() {
|
||||
return;
|
||||
|
||||
if (face_infos_.empty() ||
|
||||
- static_cast<size_t>(base_level_) >= face_infos_[0].level_infos.size()) {
|
||||
+ static_cast<size_t>(base_level_) >= MaxValidMipLevel()) {
|
||||
texture_complete_ = false;
|
||||
cube_complete_ = false;
|
||||
return;
|
||||
@@ -2028,8 +2028,7 @@ bool Texture::CanRenderTo(const FeatureInfo* feature_info, GLint level) const {
|
||||
// the time.
|
||||
if (face_infos_.size() == 6 && !cube_complete())
|
||||
return false;
|
||||
- DCHECK(level >= 0 &&
|
||||
- level < static_cast<GLint>(face_infos_[0].level_infos.size()));
|
||||
+ DCHECK(level >= 0 && level < static_cast<GLint>(MaxValidMipLevel()));
|
||||
if (level > base_level_ && !texture_complete()) {
|
||||
return false;
|
||||
}
|
||||
@@ -2064,7 +2063,7 @@ void Texture::SetCompatibilitySwizzle(const CompatibilitySwizzle* swizzle) {
|
||||
|
||||
void Texture::ApplyFormatWorkarounds(const FeatureInfo* feature_info) {
|
||||
if (feature_info->gl_version_info().NeedsLuminanceAlphaEmulation()) {
|
||||
- if (static_cast<size_t>(base_level_) >= face_infos_[0].level_infos.size())
|
||||
+ if (static_cast<size_t>(base_level_) >= MaxValidMipLevel())
|
||||
return;
|
||||
const Texture::LevelInfo& info = face_infos_[0].level_infos[base_level_];
|
||||
SetCompatibilitySwizzle(GetCompatibilitySwizzleInternal(info.format));
|
||||
@@ -2298,8 +2297,11 @@ scoped_refptr<TextureRef>
|
||||
return default_texture;
|
||||
}
|
||||
|
||||
-bool TextureManager::ValidForTarget(
|
||||
- GLenum target, GLint level, GLsizei width, GLsizei height, GLsizei depth) {
|
||||
+bool TextureManager::ValidForTarget(GLenum target,
|
||||
+ GLint level,
|
||||
+ GLsizei width,
|
||||
+ GLsizei height,
|
||||
+ GLsizei depth) {
|
||||
if (level < 0 || level >= MaxLevelsForTarget(target))
|
||||
return false;
|
||||
GLsizei max_size = MaxSizeForTarget(target) >> level;
|
||||
@@ -2319,6 +2321,18 @@ bool TextureManager::ValidForTarget(
|
||||
(target != GL_TEXTURE_2D || (depth == 1));
|
||||
}
|
||||
|
||||
+bool TextureManager::ValidForTextureTarget(const Texture* texture,
|
||||
+ GLint level,
|
||||
+ GLsizei width,
|
||||
+ GLsizei height,
|
||||
+ GLsizei depth) {
|
||||
+ if (texture->target() == 0)
|
||||
+ return false;
|
||||
+ if (level < 0 || static_cast<size_t>(level) >= texture->MaxValidMipLevel())
|
||||
+ return false;
|
||||
+ return ValidForTarget(texture->target(), level, width, height, depth);
|
||||
+}
|
||||
+
|
||||
void TextureManager::SetTarget(TextureRef* ref, GLenum target) {
|
||||
DCHECK(ref);
|
||||
ref->texture()->SetTarget(target, MaxLevelsForTarget(target));
|
||||
@@ -2802,14 +2816,6 @@ bool TextureManager::ValidateTexImage(ContextState* state,
|
||||
args.internal_format, args.level)) {
|
||||
return false;
|
||||
}
|
||||
- if (!ValidForTarget(args.target, args.level,
|
||||
- args.width, args.height, args.depth) ||
|
||||
- args.border != 0) {
|
||||
- ERRORSTATE_SET_GL_ERROR(
|
||||
- error_state, GL_INVALID_VALUE, function_name,
|
||||
- "dimensions out of range");
|
||||
- return false;
|
||||
- }
|
||||
if ((GLES2Util::GetChannelsForFormat(args.format) &
|
||||
(GLES2Util::kDepth | GLES2Util::kStencil)) != 0 && args.pixels
|
||||
&& !feature_info_->IsWebGL2OrES3Context()) {
|
||||
@@ -2832,7 +2838,13 @@ bool TextureManager::ValidateTexImage(ContextState* state,
|
||||
"texture is immutable");
|
||||
return false;
|
||||
}
|
||||
-
|
||||
+ if (!ValidForTextureTarget(local_texture_ref->texture(), args.level,
|
||||
+ args.width, args.height, args.depth) ||
|
||||
+ args.border != 0) {
|
||||
+ ERRORSTATE_SET_GL_ERROR(error_state, GL_INVALID_VALUE, function_name,
|
||||
+ "dimensions out of range");
|
||||
+ return false;
|
||||
+ }
|
||||
Buffer* buffer = state->bound_pixel_unpack_buffer.get();
|
||||
if (buffer) {
|
||||
if (buffer->GetMappedRange()) {
|
||||
diff --git a/gpu/command_buffer/service/texture_manager.h b/gpu/command_buffer/service/texture_manager.h
|
||||
index c78c914cbad58abb17439354eeb9f77a9891f21d..8f68e70e6d1c9a4b75f6bec0df7179320bc167c0 100644
|
||||
--- a/gpu/command_buffer/service/texture_manager.h
|
||||
+++ b/gpu/command_buffer/service/texture_manager.h
|
||||
@@ -470,6 +470,11 @@ class GPU_GLES2_EXPORT Texture final : public TextureBase {
|
||||
sampler_state_.min_filter != GL_LINEAR;
|
||||
}
|
||||
|
||||
+ size_t MaxValidMipLevel() const {
|
||||
+ DCHECK(!face_infos_.empty());
|
||||
+ return face_infos_[0].level_infos.size();
|
||||
+ }
|
||||
+
|
||||
private:
|
||||
friend class MailboxManagerTest;
|
||||
friend class TextureManager;
|
||||
@@ -932,6 +937,11 @@ class GPU_GLES2_EXPORT TextureManager
|
||||
bool ValidForTarget(
|
||||
GLenum target, GLint level,
|
||||
GLsizei width, GLsizei height, GLsizei depth);
|
||||
+ bool ValidForTextureTarget(const Texture* texture,
|
||||
+ GLint level,
|
||||
+ GLsizei width,
|
||||
+ GLsizei height,
|
||||
+ GLsizei depth);
|
||||
|
||||
// True if this texture meets all the GLES2 criteria for rendering.
|
||||
// See section 3.8.2 of the GLES2 spec.
|
||||
115
patches/chromium/cherry-pick-81cb17c24788.patch
Normal file
115
patches/chromium/cherry-pick-81cb17c24788.patch
Normal file
@@ -0,0 +1,115 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Christoph Schwering <schwering@google.com>
|
||||
Date: Fri, 4 Nov 2022 00:56:32 +0000
|
||||
Subject: Handle misaligned FormData, FormStructure.
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
|
||||
This CL handles the case where the fields of the cached FormStructure
|
||||
and the FormData are misaligned in
|
||||
BrowserAutofillManager::WillFillCreditCardNumber.
|
||||
|
||||
(cherry picked from commit 1ad751f7dfa30a12a85824c291394b73c5c47eff)
|
||||
|
||||
Bug: 1376637, 1376639
|
||||
Change-Id: Id7c3357a274b4d6624009ecf52b95a24cf3bfa1d
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3965141
|
||||
Commit-Queue: Christoph Schwering <schwering@google.com>
|
||||
Quick-Run: Christoph Schwering <schwering@google.com>
|
||||
Reviewed-by: Dominic Battré <battre@chromium.org>
|
||||
Auto-Submit: Christoph Schwering <schwering@google.com>
|
||||
Cr-Original-Commit-Position: refs/heads/main@{#1061790}
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/4003032
|
||||
Commit-Queue: Dominic Battré <battre@chromium.org>
|
||||
Cr-Commit-Position: refs/branch-heads/5249@{#907}
|
||||
Cr-Branched-From: 4f7bea5de862aaa52e6bde5920755a9ef9db120b-refs/heads/main@{#1036826}
|
||||
|
||||
diff --git a/chrome/test/data/autofill/captured_sites/testcases.json b/chrome/test/data/autofill/captured_sites/testcases.json
|
||||
index bb7ac2a638a410b3e83b9871314eae27aa8ef229..2e69d8f8532760103b9cccd5efc4ca7a4ad016a1 100644
|
||||
--- a/chrome/test/data/autofill/captured_sites/testcases.json
|
||||
+++ b/chrome/test/data/autofill/captured_sites/testcases.json
|
||||
@@ -17,7 +17,7 @@
|
||||
{ "site_name": "bath_and_body_works" },
|
||||
{ "site_name": "beachbody" },
|
||||
{ "site_name": "bed_bath_beyond" },
|
||||
- { "site_name": "belk" },
|
||||
+ { "site_name": "belk", "bug_number": 1376637 },
|
||||
{ "site_name": "bestbuy" },
|
||||
{ "site_name": "bhphotovideo", "bug_number":1173033 },
|
||||
{ "site_name": "bloomingdales" },
|
||||
diff --git a/components/autofill/core/browser/browser_autofill_manager.cc b/components/autofill/core/browser/browser_autofill_manager.cc
|
||||
index bc16e80e580b0c800391501e022c2ea011e65ef1..b3ca85044a094e639f492a12d10ca0ed4cce11e9 100644
|
||||
--- a/components/autofill/core/browser/browser_autofill_manager.cc
|
||||
+++ b/components/autofill/core/browser/browser_autofill_manager.cc
|
||||
@@ -1056,26 +1056,36 @@ void BrowserAutofillManager::OnAskForValuesToFillImpl(
|
||||
|
||||
bool BrowserAutofillManager::WillFillCreditCardNumber(
|
||||
const FormData& form,
|
||||
- const FormFieldData& field) {
|
||||
+ const FormFieldData& triggered_field_data) {
|
||||
FormStructure* form_structure = nullptr;
|
||||
- AutofillField* autofill_field = nullptr;
|
||||
- if (!GetCachedFormAndField(form, field, &form_structure, &autofill_field))
|
||||
+ AutofillField* triggered_field = nullptr;
|
||||
+ if (!GetCachedFormAndField(form, triggered_field_data, &form_structure,
|
||||
+ &triggered_field)) {
|
||||
return false;
|
||||
+ }
|
||||
|
||||
- if (autofill_field->Type().GetStorableType() == CREDIT_CARD_NUMBER)
|
||||
+ if (triggered_field->Type().GetStorableType() == CREDIT_CARD_NUMBER)
|
||||
return true;
|
||||
|
||||
- DCHECK_EQ(form_structure->field_count(), form.fields.size());
|
||||
- for (size_t i = 0; i < form_structure->field_count(); ++i) {
|
||||
- if (form_structure->field(i)->section == autofill_field->section &&
|
||||
- form_structure->field(i)->Type().GetStorableType() ==
|
||||
- CREDIT_CARD_NUMBER &&
|
||||
- form.fields[i].value.empty() && !form.fields[i].is_autofilled) {
|
||||
- return true;
|
||||
- }
|
||||
- }
|
||||
+ // `form` is the latest version of the form received from the renderer and may
|
||||
+ // be more up to date than the `form_structure` in the cache. Therefore, we
|
||||
+ // need to validate for each `field` in the cache we try to fill whether
|
||||
+ // it still exists in the renderer and whether it is fillable.
|
||||
+ auto IsFillableField = [&form](FieldGlobalId id) {
|
||||
+ auto it = base::ranges::find(form.fields, id, &FormFieldData::global_id);
|
||||
+ return it != form.fields.end() && it->value.empty() && !it->is_autofilled;
|
||||
+ };
|
||||
|
||||
- return false;
|
||||
+ auto IsFillableCreditCardNumberField = [&triggered_field,
|
||||
+ &IsFillableField](const auto& field) {
|
||||
+ return field->Type().GetStorableType() == CREDIT_CARD_NUMBER &&
|
||||
+ field->section == triggered_field->section &&
|
||||
+ IsFillableField(field->global_id());
|
||||
+ };
|
||||
+
|
||||
+ // This runs O(N^2) in the worst case, but usually there aren't too many
|
||||
+ // credit card number fields in a form.
|
||||
+ return base::ranges::any_of(*form_structure, IsFillableCreditCardNumberField);
|
||||
}
|
||||
|
||||
void BrowserAutofillManager::FillOrPreviewCreditCardForm(
|
||||
diff --git a/components/autofill/core/browser/browser_autofill_manager.h b/components/autofill/core/browser/browser_autofill_manager.h
|
||||
index 0040d007eea8e69f7cccb069afe1103cfdd84d75..2d5aa6171bc4634bc98a5c123a25979675de4f10 100644
|
||||
--- a/components/autofill/core/browser/browser_autofill_manager.h
|
||||
+++ b/components/autofill/core/browser/browser_autofill_manager.h
|
||||
@@ -503,11 +503,11 @@ class BrowserAutofillManager : public AutofillManager,
|
||||
// profile does not exist.
|
||||
AutofillProfile* GetProfile(int unique_id);
|
||||
|
||||
- // Determines whether a fill on |form| initiated from |field| will wind up
|
||||
- // filling a credit card number. This is useful to determine if we will need
|
||||
- // to unmask a card.
|
||||
+ // Determines whether a fill on |form| initiated from |triggered_field| will
|
||||
+ // wind up filling a credit card number. This is useful to determine if we
|
||||
+ // will need to unmask a card.
|
||||
bool WillFillCreditCardNumber(const FormData& form,
|
||||
- const FormFieldData& field);
|
||||
+ const FormFieldData& triggered_field);
|
||||
|
||||
// Fills or previews the credit card form.
|
||||
// Assumes the form and field are valid.
|
||||
323
patches/chromium/cherry-pick-933cc81c6bad.patch
Normal file
323
patches/chromium/cherry-pick-933cc81c6bad.patch
Normal file
@@ -0,0 +1,323 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Xiaocheng Hu <xiaochengh@chromium.org>
|
||||
Date: Sat, 10 Sep 2022 05:53:49 +0000
|
||||
Subject: Remove symlinks from FileChooserImpl folder upload result
|
||||
|
||||
FileChooserImpl is the browser-side implementation of
|
||||
<input type=file>. When uploading a whole folder, it
|
||||
currently uses DirectoryLister to list all the files in a
|
||||
directory. The result also includes resolved symbolic links
|
||||
(which may even hide deep in some subfolder), which is not a
|
||||
desired behavior.
|
||||
|
||||
Therefore, this patch removes all symbolic links from the
|
||||
result by checking each file against `base::IsLink()`. Since
|
||||
the function needs blocking calls to access file data, the
|
||||
job is sent to a worker pool thread.
|
||||
|
||||
Fixed: 1345275
|
||||
Change-Id: I8ab58214c87944408c64b177e915247a7485925b
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3866767
|
||||
Reviewed-by: Austin Sullivan <asully@chromium.org>
|
||||
Commit-Queue: Xiaocheng Hu <xiaochengh@chromium.org>
|
||||
Reviewed-by: Mason Freed <masonf@chromium.org>
|
||||
Reviewed-by: Alex Moshchuk <alexmos@chromium.org>
|
||||
Cr-Commit-Position: refs/heads/main@{#1045491}
|
||||
|
||||
diff --git a/content/browser/web_contents/file_chooser_impl.cc b/content/browser/web_contents/file_chooser_impl.cc
|
||||
index 7a3ea45d32c97980c141662f6a071cc517a15ad8..1aa19f7a735b444f2c33d5084edcdd14e3c2f5c5 100644
|
||||
--- a/content/browser/web_contents/file_chooser_impl.cc
|
||||
+++ b/content/browser/web_contents/file_chooser_impl.cc
|
||||
@@ -4,8 +4,11 @@
|
||||
|
||||
#include "content/browser/web_contents/file_chooser_impl.h"
|
||||
|
||||
+#include "base/files/file_util.h"
|
||||
#include "base/logging.h"
|
||||
#include "base/memory/ptr_util.h"
|
||||
+#include "base/ranges/algorithm.h"
|
||||
+#include "base/task/thread_pool.h"
|
||||
#include "content/browser/child_process_security_policy_impl.h"
|
||||
#include "content/browser/renderer_host/back_forward_cache_disable.h"
|
||||
#include "content/browser/renderer_host/render_frame_host_delegate.h"
|
||||
@@ -18,6 +21,19 @@
|
||||
|
||||
namespace content {
|
||||
|
||||
+namespace {
|
||||
+
|
||||
+std::vector<blink::mojom::FileChooserFileInfoPtr> RemoveSymlinks(
|
||||
+ std::vector<blink::mojom::FileChooserFileInfoPtr> files) {
|
||||
+ auto new_end = base::ranges::remove_if(
|
||||
+ files, &base::IsLink,
|
||||
+ [](const auto& file) { return file->get_native_file()->file_path; });
|
||||
+ files.erase(new_end, files.end());
|
||||
+ return files;
|
||||
+}
|
||||
+
|
||||
+} // namespace
|
||||
+
|
||||
FileChooserImpl::FileSelectListenerImpl::~FileSelectListenerImpl() {
|
||||
#if DCHECK_IS_ON()
|
||||
if (!was_file_select_listener_function_called_) {
|
||||
@@ -51,8 +67,20 @@ void FileChooserImpl::FileSelectListenerImpl::FileSelected(
|
||||
"FileSelectListener::FileSelectionCanceled()";
|
||||
was_file_select_listener_function_called_ = true;
|
||||
#endif
|
||||
- if (owner_)
|
||||
- owner_->FileSelected(std::move(files), base_dir, mode);
|
||||
+ if (!owner_)
|
||||
+ return;
|
||||
+
|
||||
+ if (mode != blink::mojom::FileChooserParams::Mode::kUploadFolder) {
|
||||
+ owner_->FileSelected(base_dir, mode, std::move(files));
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
+ base::ThreadPool::PostTaskAndReplyWithResult(
|
||||
+ FROM_HERE,
|
||||
+ {base::MayBlock(), base::TaskShutdownBehavior::CONTINUE_ON_SHUTDOWN},
|
||||
+ base::BindOnce(&RemoveSymlinks, std::move(files)),
|
||||
+ base::BindOnce(&FileChooserImpl::FileSelected, owner_->GetWeakPtr(),
|
||||
+ base_dir, mode));
|
||||
}
|
||||
|
||||
void FileChooserImpl::FileSelectListenerImpl::FileSelectionCanceled() {
|
||||
@@ -162,9 +190,9 @@ void FileChooserImpl::EnumerateChosenDirectory(
|
||||
}
|
||||
|
||||
void FileChooserImpl::FileSelected(
|
||||
- std::vector<blink::mojom::FileChooserFileInfoPtr> files,
|
||||
const base::FilePath& base_dir,
|
||||
- blink::mojom::FileChooserParams::Mode mode) {
|
||||
+ blink::mojom::FileChooserParams::Mode mode,
|
||||
+ std::vector<blink::mojom::FileChooserFileInfoPtr> files) {
|
||||
listener_impl_ = nullptr;
|
||||
if (!render_frame_host_) {
|
||||
std::move(callback_).Run(nullptr);
|
||||
diff --git a/content/browser/web_contents/file_chooser_impl.h b/content/browser/web_contents/file_chooser_impl.h
|
||||
index b9f11f9e6a0b548cb5ab8ca721ae823e079ce6fa..b628b29a5f84264e62bb3fa9e92550787b8342de 100644
|
||||
--- a/content/browser/web_contents/file_chooser_impl.h
|
||||
+++ b/content/browser/web_contents/file_chooser_impl.h
|
||||
@@ -37,6 +37,8 @@ class CONTENT_EXPORT FileChooserImpl : public blink::mojom::FileChooser,
|
||||
|
||||
// FileSelectListener overrides:
|
||||
|
||||
+ // TODO(xiaochengh): Move |file| to the end of the argument list to match
|
||||
+ // the argument ordering of FileChooserImpl::FileSelected().
|
||||
void FileSelected(std::vector<blink::mojom::FileChooserFileInfoPtr> files,
|
||||
const base::FilePath& base_dir,
|
||||
blink::mojom::FileChooserParams::Mode mode) override;
|
||||
@@ -68,9 +70,9 @@ class CONTENT_EXPORT FileChooserImpl : public blink::mojom::FileChooser,
|
||||
|
||||
~FileChooserImpl() override;
|
||||
|
||||
- void FileSelected(std::vector<blink::mojom::FileChooserFileInfoPtr> files,
|
||||
- const base::FilePath& base_dir,
|
||||
- blink::mojom::FileChooserParams::Mode mode);
|
||||
+ void FileSelected(const base::FilePath& base_dir,
|
||||
+ blink::mojom::FileChooserParams::Mode mode,
|
||||
+ std::vector<blink::mojom::FileChooserFileInfoPtr> files);
|
||||
|
||||
void FileSelectionCanceled();
|
||||
|
||||
@@ -82,6 +84,10 @@ class CONTENT_EXPORT FileChooserImpl : public blink::mojom::FileChooser,
|
||||
const base::FilePath& directory_path,
|
||||
EnumerateChosenDirectoryCallback callback) override;
|
||||
|
||||
+ base::WeakPtr<FileChooserImpl> GetWeakPtr() {
|
||||
+ return weak_factory_.GetWeakPtr();
|
||||
+ }
|
||||
+
|
||||
private:
|
||||
explicit FileChooserImpl(RenderFrameHostImpl* render_frame_host);
|
||||
|
||||
@@ -95,6 +101,8 @@ class CONTENT_EXPORT FileChooserImpl : public blink::mojom::FileChooser,
|
||||
raw_ptr<RenderFrameHostImpl> render_frame_host_;
|
||||
scoped_refptr<FileSelectListenerImpl> listener_impl_;
|
||||
base::OnceCallback<void(blink::mojom::FileChooserResultPtr)> callback_;
|
||||
+
|
||||
+ base::WeakPtrFactory<FileChooserImpl> weak_factory_{this};
|
||||
};
|
||||
|
||||
} // namespace content
|
||||
diff --git a/content/browser/web_contents/file_chooser_impl_browsertest.cc b/content/browser/web_contents/file_chooser_impl_browsertest.cc
|
||||
index ced9bfd8fe905acbb6ab5c3e52a9882fc23a7303..f7519189638ece437c4285ddd490be3ea59e638d 100644
|
||||
--- a/content/browser/web_contents/file_chooser_impl_browsertest.cc
|
||||
+++ b/content/browser/web_contents/file_chooser_impl_browsertest.cc
|
||||
@@ -5,14 +5,18 @@
|
||||
#include "content/browser/web_contents/file_chooser_impl.h"
|
||||
|
||||
#include "base/bind.h"
|
||||
+#include "base/files/file_util.h"
|
||||
+#include "base/path_service.h"
|
||||
#include "base/run_loop.h"
|
||||
#include "content/browser/renderer_host/render_frame_host_impl.h"
|
||||
#include "content/public/browser/web_contents_delegate.h"
|
||||
+#include "content/public/common/content_paths.h"
|
||||
#include "content/public/test/browser_test.h"
|
||||
#include "content/public/test/browser_test_utils.h"
|
||||
#include "content/public/test/content_browser_test.h"
|
||||
#include "content/public/test/content_browser_test_utils.h"
|
||||
#include "content/shell/browser/shell.h"
|
||||
+#include "content/test/content_browser_test_utils_internal.h"
|
||||
#include "url/gurl.h"
|
||||
#include "url/url_constants.h"
|
||||
|
||||
@@ -143,11 +147,52 @@ IN_PROC_BROWSER_TEST_F(FileChooserImplBrowserTest,
|
||||
->SetListenerFunctionCalledTrueForTesting();
|
||||
std::vector<blink::mojom::FileChooserFileInfoPtr> files;
|
||||
files.emplace_back(blink::mojom::FileChooserFileInfoPtr(nullptr));
|
||||
- chooser->FileSelected(std::move(files), base::FilePath(),
|
||||
- blink::mojom::FileChooserParams::Mode::kOpen);
|
||||
+ chooser->FileSelected(base::FilePath(),
|
||||
+ blink::mojom::FileChooserParams::Mode::kOpen,
|
||||
+ std::move(files));
|
||||
|
||||
// Test passes if this run_loop.Run() returns instead of timing out.
|
||||
run_loop.Run();
|
||||
}
|
||||
|
||||
+// https://crbug.com/1345275
|
||||
+IN_PROC_BROWSER_TEST_F(FileChooserImplBrowserTest, UploadFolderWithSymlink) {
|
||||
+ EXPECT_TRUE(NavigateToURL(
|
||||
+ shell(), GetTestUrl(".", "file_input_webkitdirectory.html")));
|
||||
+
|
||||
+ // The folder contains a regular file and a symbolic link.
|
||||
+ // When uploading the folder, the symbolic link should be excluded.
|
||||
+ base::FilePath dir_test_data;
|
||||
+ ASSERT_TRUE(base::PathService::Get(DIR_TEST_DATA, &dir_test_data));
|
||||
+ base::FilePath folder_to_upload =
|
||||
+ dir_test_data.AppendASCII("file_chooser").AppendASCII("dir_with_symlink");
|
||||
+
|
||||
+ base::FilePath text_file = folder_to_upload.AppendASCII("text_file.txt");
|
||||
+ base::FilePath symlink_file = folder_to_upload.AppendASCII("symlink");
|
||||
+
|
||||
+ // Skip the test if symbolic links are not supported.
|
||||
+ {
|
||||
+ base::ScopedAllowBlockingForTesting allow_blocking;
|
||||
+ if (!base::IsLink(symlink_file))
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
+ std::unique_ptr<FileChooserDelegate> delegate(
|
||||
+ new FileChooserDelegate({text_file, symlink_file}, base::OnceClosure()));
|
||||
+ shell()->web_contents()->SetDelegate(delegate.get());
|
||||
+ EXPECT_TRUE(ExecJs(shell(),
|
||||
+ "(async () => {"
|
||||
+ " let listener = new Promise("
|
||||
+ " resolve => fileinput.onchange = resolve);"
|
||||
+ " fileinput.click();"
|
||||
+ " await listener;"
|
||||
+ "})()"));
|
||||
+
|
||||
+ EXPECT_EQ(
|
||||
+ 1, EvalJs(shell(), "document.getElementById('fileinput').files.length;"));
|
||||
+ EXPECT_EQ(
|
||||
+ "text_file.txt",
|
||||
+ EvalJs(shell(), "document.getElementById('fileinput').files[0].name;"));
|
||||
+}
|
||||
+
|
||||
} // namespace content
|
||||
diff --git a/content/test/content_browser_test_utils_internal.cc b/content/test/content_browser_test_utils_internal.cc
|
||||
index d8e63b56c8ac89a08cd7c40cabb156eb4d1923aa..c70d088bfd007e9a6cd9cfcb6f92b07b99653048 100644
|
||||
--- a/content/test/content_browser_test_utils_internal.cc
|
||||
+++ b/content/test/content_browser_test_utils_internal.cc
|
||||
@@ -446,9 +446,14 @@ Shell* OpenPopup(const ToRenderFrameHost& opener,
|
||||
return new_shell_observer.GetShell();
|
||||
}
|
||||
|
||||
+FileChooserDelegate::FileChooserDelegate(std::vector<base::FilePath> files,
|
||||
+ base::OnceClosure callback)
|
||||
+ : files_(std::move(files)), callback_(std::move(callback)) {}
|
||||
+
|
||||
FileChooserDelegate::FileChooserDelegate(const base::FilePath& file,
|
||||
base::OnceClosure callback)
|
||||
- : file_(file), callback_(std::move(callback)) {}
|
||||
+ : FileChooserDelegate(std::vector<base::FilePath>(1, file),
|
||||
+ std::move(callback)) {}
|
||||
|
||||
FileChooserDelegate::~FileChooserDelegate() = default;
|
||||
|
||||
@@ -456,16 +461,18 @@ void FileChooserDelegate::RunFileChooser(
|
||||
RenderFrameHost* render_frame_host,
|
||||
scoped_refptr<content::FileSelectListener> listener,
|
||||
const blink::mojom::FileChooserParams& params) {
|
||||
- // Send the selected file to the renderer process.
|
||||
- auto file_info = blink::mojom::FileChooserFileInfo::NewNativeFile(
|
||||
- blink::mojom::NativeFileInfo::New(file_, std::u16string()));
|
||||
+ // Send the selected files to the renderer process.
|
||||
std::vector<blink::mojom::FileChooserFileInfoPtr> files;
|
||||
- files.push_back(std::move(file_info));
|
||||
- listener->FileSelected(std::move(files), base::FilePath(),
|
||||
- blink::mojom::FileChooserParams::Mode::kOpen);
|
||||
+ for (const auto& file : files_) {
|
||||
+ auto file_info = blink::mojom::FileChooserFileInfo::NewNativeFile(
|
||||
+ blink::mojom::NativeFileInfo::New(file, std::u16string()));
|
||||
+ files.push_back(std::move(file_info));
|
||||
+ }
|
||||
+ listener->FileSelected(std::move(files), base::FilePath(), params.mode);
|
||||
|
||||
params_ = params.Clone();
|
||||
- std::move(callback_).Run();
|
||||
+ if (callback_)
|
||||
+ std::move(callback_).Run();
|
||||
}
|
||||
|
||||
FrameTestNavigationManager::FrameTestNavigationManager(
|
||||
diff --git a/content/test/content_browser_test_utils_internal.h b/content/test/content_browser_test_utils_internal.h
|
||||
index 73be6e8a2f458128b08aae34d951c7a80139997d..43c6aabc5414d0cc12fb5a03142e8b20e2a7fab3 100644
|
||||
--- a/content/test/content_browser_test_utils_internal.h
|
||||
+++ b/content/test/content_browser_test_utils_internal.h
|
||||
@@ -176,9 +176,11 @@ Shell* OpenPopup(const ToRenderFrameHost& opener,
|
||||
class FileChooserDelegate : public WebContentsDelegate {
|
||||
public:
|
||||
// Constructs a WebContentsDelegate that mocks a file dialog.
|
||||
- // The mocked file dialog will always reply that the user selected |file|.
|
||||
- // |callback| is invoked when RunFileChooser() is called.
|
||||
+ // The mocked file dialog will always reply that the user selected |file| or
|
||||
+ // |files|. |callback| is invoked when RunFileChooser() is called.
|
||||
FileChooserDelegate(const base::FilePath& file, base::OnceClosure callback);
|
||||
+ FileChooserDelegate(std::vector<base::FilePath> files,
|
||||
+ base::OnceClosure callback);
|
||||
~FileChooserDelegate() override;
|
||||
|
||||
// Implementation of WebContentsDelegate::RunFileChooser.
|
||||
@@ -190,7 +192,7 @@ class FileChooserDelegate : public WebContentsDelegate {
|
||||
const blink::mojom::FileChooserParams& params() const { return *params_; }
|
||||
|
||||
private:
|
||||
- base::FilePath file_;
|
||||
+ std::vector<base::FilePath> files_;
|
||||
base::OnceClosure callback_;
|
||||
blink::mojom::FileChooserParamsPtr params_;
|
||||
};
|
||||
diff --git a/content/test/data/file_chooser/dir_with_symlink/symlink b/content/test/data/file_chooser/dir_with_symlink/symlink
|
||||
new file mode 120000
|
||||
index 0000000000000000000000000000000000000000..7857c689f7043265b4e6d4dcdf6d40d0be2d3d60
|
||||
--- /dev/null
|
||||
+++ b/content/test/data/file_chooser/dir_with_symlink/symlink
|
||||
@@ -0,0 +1 @@
|
||||
+../linked_text_file.txt
|
||||
\ No newline at end of file
|
||||
diff --git a/content/test/data/file_chooser/dir_with_symlink/text_file.txt b/content/test/data/file_chooser/dir_with_symlink/text_file.txt
|
||||
new file mode 100644
|
||||
index 0000000000000000000000000000000000000000..8e27be7d6154a1f68ea9160ef0e18691d20560dc
|
||||
--- /dev/null
|
||||
+++ b/content/test/data/file_chooser/dir_with_symlink/text_file.txt
|
||||
@@ -0,0 +1 @@
|
||||
+text
|
||||
diff --git a/content/test/data/file_chooser/linked_text_file.txt b/content/test/data/file_chooser/linked_text_file.txt
|
||||
new file mode 100644
|
||||
index 0000000000000000000000000000000000000000..9a1f4bc60917c014eac1464ad664a0271c288b84
|
||||
--- /dev/null
|
||||
+++ b/content/test/data/file_chooser/linked_text_file.txt
|
||||
@@ -0,0 +1 @@
|
||||
+linked text file
|
||||
diff --git a/content/test/data/file_input_webkitdirectory.html b/content/test/data/file_input_webkitdirectory.html
|
||||
new file mode 100644
|
||||
index 0000000000000000000000000000000000000000..5b7bb501f7eb5d9f28751f36380e4ad01d2da0c7
|
||||
--- /dev/null
|
||||
+++ b/content/test/data/file_input_webkitdirectory.html
|
||||
@@ -0,0 +1 @@
|
||||
+<input type="file" id="fileinput" webkitdirectory />
|
||||
179
patches/chromium/cherry-pick-9b5207569882.patch
Normal file
179
patches/chromium/cherry-pick-9b5207569882.patch
Normal file
@@ -0,0 +1,179 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Ken Rockot <rockot@google.com>
|
||||
Date: Wed, 31 Aug 2022 15:39:45 +0000
|
||||
Subject: Mojo: Validate response message type
|
||||
|
||||
Ensures that a response message is actually the type expected by the
|
||||
original request.
|
||||
|
||||
Fixed: 1358134
|
||||
Change-Id: I8f8f58168764477fbf7a6d2e8aeb040f07793d45
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3864274
|
||||
Reviewed-by: Robert Sesek <rsesek@chromium.org>
|
||||
Commit-Queue: Ken Rockot <rockot@google.com>
|
||||
Cr-Commit-Position: refs/heads/main@{#1041553}
|
||||
|
||||
diff --git a/mojo/public/cpp/bindings/interface_endpoint_client.h b/mojo/public/cpp/bindings/interface_endpoint_client.h
|
||||
index 01cba995429b0accc21986aba0e3de17d013ee95..d3a1ab3a13a6662239ec28f99e5865afa54356b3 100644
|
||||
--- a/mojo/public/cpp/bindings/interface_endpoint_client.h
|
||||
+++ b/mojo/public/cpp/bindings/interface_endpoint_client.h
|
||||
@@ -222,20 +222,32 @@ class COMPONENT_EXPORT(MOJO_CPP_BINDINGS) InterfaceEndpointClient
|
||||
void ForgetAsyncRequest(uint64_t request_id);
|
||||
|
||||
private:
|
||||
- // Maps from the id of a response to the MessageReceiver that handles the
|
||||
- // response.
|
||||
- using AsyncResponderMap =
|
||||
- std::map<uint64_t, std::unique_ptr<MessageReceiver>>;
|
||||
+ struct PendingAsyncResponse {
|
||||
+ public:
|
||||
+ PendingAsyncResponse(uint32_t request_message_name,
|
||||
+ std::unique_ptr<MessageReceiver> responder);
|
||||
+ PendingAsyncResponse(PendingAsyncResponse&&);
|
||||
+ PendingAsyncResponse(const PendingAsyncResponse&) = delete;
|
||||
+ PendingAsyncResponse& operator=(PendingAsyncResponse&&);
|
||||
+ PendingAsyncResponse& operator=(const PendingAsyncResponse&) = delete;
|
||||
+ ~PendingAsyncResponse();
|
||||
+
|
||||
+ uint32_t request_message_name;
|
||||
+ std::unique_ptr<MessageReceiver> responder;
|
||||
+ };
|
||||
+
|
||||
+ using AsyncResponderMap = std::map<uint64_t, PendingAsyncResponse>;
|
||||
|
||||
struct SyncResponseInfo {
|
||||
public:
|
||||
- explicit SyncResponseInfo(bool* in_response_received);
|
||||
+ SyncResponseInfo(uint32_t request_message_name, bool* in_response_received);
|
||||
|
||||
SyncResponseInfo(const SyncResponseInfo&) = delete;
|
||||
SyncResponseInfo& operator=(const SyncResponseInfo&) = delete;
|
||||
|
||||
~SyncResponseInfo();
|
||||
|
||||
+ uint32_t request_message_name;
|
||||
Message response;
|
||||
|
||||
// Points to a stack-allocated variable.
|
||||
diff --git a/mojo/public/cpp/bindings/lib/interface_endpoint_client.cc b/mojo/public/cpp/bindings/lib/interface_endpoint_client.cc
|
||||
index b9db8f31a42b956c6125852cf162dc524d5308e6..6e87db197c603d8ac44b591f2cd70023217dcbe2 100644
|
||||
--- a/mojo/public/cpp/bindings/lib/interface_endpoint_client.cc
|
||||
+++ b/mojo/public/cpp/bindings/lib/interface_endpoint_client.cc
|
||||
@@ -28,6 +28,7 @@
|
||||
#include "mojo/public/cpp/bindings/sync_call_restrictions.h"
|
||||
#include "mojo/public/cpp/bindings/sync_event_watcher.h"
|
||||
#include "mojo/public/cpp/bindings/thread_safe_proxy.h"
|
||||
+#include "third_party/abseil-cpp/absl/types/optional.h"
|
||||
#include "third_party/perfetto/protos/perfetto/trace/track_event/chrome_mojo_event_info.pbzero.h"
|
||||
|
||||
namespace mojo {
|
||||
@@ -314,9 +315,27 @@ class ResponderThunk : public MessageReceiverWithStatus {
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
+InterfaceEndpointClient::PendingAsyncResponse::PendingAsyncResponse(
|
||||
+ uint32_t request_message_name,
|
||||
+ std::unique_ptr<MessageReceiver> responder)
|
||||
+ : request_message_name(request_message_name),
|
||||
+ responder(std::move(responder)) {}
|
||||
+
|
||||
+InterfaceEndpointClient::PendingAsyncResponse::PendingAsyncResponse(
|
||||
+ PendingAsyncResponse&&) = default;
|
||||
+
|
||||
+InterfaceEndpointClient::PendingAsyncResponse&
|
||||
+InterfaceEndpointClient::PendingAsyncResponse::operator=(
|
||||
+ PendingAsyncResponse&&) = default;
|
||||
+
|
||||
+InterfaceEndpointClient::PendingAsyncResponse::~PendingAsyncResponse() =
|
||||
+ default;
|
||||
+
|
||||
InterfaceEndpointClient::SyncResponseInfo::SyncResponseInfo(
|
||||
+ uint32_t request_message_name,
|
||||
bool* in_response_received)
|
||||
- : response_received(in_response_received) {}
|
||||
+ : request_message_name(request_message_name),
|
||||
+ response_received(in_response_received) {}
|
||||
|
||||
InterfaceEndpointClient::SyncResponseInfo::~SyncResponseInfo() {}
|
||||
|
||||
@@ -604,6 +623,7 @@ bool InterfaceEndpointClient::SendMessageWithResponder(
|
||||
// message before calling |SendMessage()| below.
|
||||
#endif
|
||||
|
||||
+ const uint32_t message_name = message->name();
|
||||
const bool is_sync = message->has_flag(Message::kFlagIsSync);
|
||||
const bool exclusive_wait = message->has_flag(Message::kFlagNoInterrupt);
|
||||
if (!controller_->SendMessage(message))
|
||||
@@ -620,7 +640,8 @@ bool InterfaceEndpointClient::SendMessageWithResponder(
|
||||
controller_->RegisterExternalSyncWaiter(request_id);
|
||||
}
|
||||
base::AutoLock lock(async_responders_lock_);
|
||||
- async_responders_[request_id] = std::move(responder);
|
||||
+ async_responders_.emplace(
|
||||
+ request_id, PendingAsyncResponse{message_name, std::move(responder)});
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -628,7 +649,8 @@ bool InterfaceEndpointClient::SendMessageWithResponder(
|
||||
|
||||
bool response_received = false;
|
||||
sync_responses_.insert(std::make_pair(
|
||||
- request_id, std::make_unique<SyncResponseInfo>(&response_received)));
|
||||
+ request_id,
|
||||
+ std::make_unique<SyncResponseInfo>(message_name, &response_received)));
|
||||
|
||||
base::WeakPtr<InterfaceEndpointClient> weak_self =
|
||||
weak_ptr_factory_.GetWeakPtr();
|
||||
@@ -806,13 +828,13 @@ void InterfaceEndpointClient::ResetFromAnotherSequenceUnsafe() {
|
||||
}
|
||||
|
||||
void InterfaceEndpointClient::ForgetAsyncRequest(uint64_t request_id) {
|
||||
- std::unique_ptr<MessageReceiver> responder;
|
||||
+ absl::optional<PendingAsyncResponse> response;
|
||||
{
|
||||
base::AutoLock lock(async_responders_lock_);
|
||||
auto it = async_responders_.find(request_id);
|
||||
if (it == async_responders_.end())
|
||||
return;
|
||||
- responder = std::move(it->second);
|
||||
+ response = std::move(it->second);
|
||||
async_responders_.erase(it);
|
||||
}
|
||||
}
|
||||
@@ -893,6 +915,10 @@ bool InterfaceEndpointClient::HandleValidatedMessage(Message* message) {
|
||||
return false;
|
||||
|
||||
if (it->second) {
|
||||
+ if (message->name() != it->second->request_message_name) {
|
||||
+ return false;
|
||||
+ }
|
||||
+
|
||||
it->second->response = std::move(*message);
|
||||
*it->second->response_received = true;
|
||||
return true;
|
||||
@@ -903,18 +929,22 @@ bool InterfaceEndpointClient::HandleValidatedMessage(Message* message) {
|
||||
sync_responses_.erase(it);
|
||||
}
|
||||
|
||||
- std::unique_ptr<MessageReceiver> responder;
|
||||
+ absl::optional<PendingAsyncResponse> pending_response;
|
||||
{
|
||||
base::AutoLock lock(async_responders_lock_);
|
||||
auto it = async_responders_.find(request_id);
|
||||
if (it == async_responders_.end())
|
||||
return false;
|
||||
- responder = std::move(it->second);
|
||||
+ pending_response = std::move(it->second);
|
||||
async_responders_.erase(it);
|
||||
}
|
||||
|
||||
+ if (message->name() != pending_response->request_message_name) {
|
||||
+ return false;
|
||||
+ }
|
||||
+
|
||||
internal::MessageDispatchContext dispatch_context(message);
|
||||
- return responder->Accept(message);
|
||||
+ return pending_response->responder->Accept(message);
|
||||
} else {
|
||||
if (mojo::internal::ControlMessageHandler::IsControlMessage(message))
|
||||
return control_message_handler_.Accept(message);
|
||||
79
patches/chromium/cherry-pick-9bebe8549a36.patch
Normal file
79
patches/chromium/cherry-pick-9bebe8549a36.patch
Normal file
@@ -0,0 +1,79 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Xiaocheng Hu <xiaochengh@chromium.org>
|
||||
Date: Wed, 28 Sep 2022 19:09:02 +0000
|
||||
Subject: Ensure iterator validity in CustomElementRegistry::DefineInternal()
|
||||
|
||||
Currently, this function first resolves a promise, and then erases an
|
||||
iterator from a hash map, but the promise resolving may run synchronous
|
||||
JavaScript that invalidates the iterator.
|
||||
|
||||
This patch switches the ordering so that we always use the iterator when
|
||||
it's valid.
|
||||
|
||||
(cherry picked from commit ed87ab54b29898a96a87e8fd497425db32539350)
|
||||
|
||||
(cherry picked from commit b0bfc4334369bd1d44bc6507dfefc012afb7e12d)
|
||||
|
||||
Fixed: 1366813
|
||||
Change-Id: Iaa6631db5f3ad47049f46ddf909f18a49e5880c0
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3915346
|
||||
Commit-Queue: Xiaocheng Hu <xiaochengh@chromium.org>
|
||||
Reviewed-by: Joey Arhar <jarhar@chromium.org>
|
||||
Cr-Original-Original-Commit-Position: refs/heads/main@{#1050816}
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3922738
|
||||
Commit-Queue: Joey Arhar <jarhar@chromium.org>
|
||||
Auto-Submit: Xiaocheng Hu <xiaochengh@chromium.org>
|
||||
Cr-Original-Commit-Position: refs/branch-heads/5304@{#203}
|
||||
Cr-Original-Branched-From: 5d7b1fc9cb7103d9c82eed647cf4be38cf09738b-refs/heads/main@{#1047731}
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3924290
|
||||
Cr-Commit-Position: refs/branch-heads/5249@{#686}
|
||||
Cr-Branched-From: 4f7bea5de862aaa52e6bde5920755a9ef9db120b-refs/heads/main@{#1036826}
|
||||
|
||||
diff --git a/third_party/blink/renderer/core/html/custom/custom_element_registry.cc b/third_party/blink/renderer/core/html/custom/custom_element_registry.cc
|
||||
index 5a63b6f0fd74d8c836c805e4d03e7be0b0205f15..6e37fba2cd627d69e602381e79f64c8ba72128b6 100644
|
||||
--- a/third_party/blink/renderer/core/html/custom/custom_element_registry.cc
|
||||
+++ b/third_party/blink/renderer/core/html/custom/custom_element_registry.cc
|
||||
@@ -217,8 +217,11 @@ CustomElementDefinition* CustomElementRegistry::DefineInternal(
|
||||
// 16: when-defined promise processing
|
||||
const auto& entry = when_defined_promise_map_.find(name);
|
||||
if (entry != when_defined_promise_map_.end()) {
|
||||
- entry->value->Resolve();
|
||||
+ ScriptPromiseResolver* resolver = entry->value;
|
||||
when_defined_promise_map_.erase(entry);
|
||||
+ // Resolve() may run synchronous JavaScript that invalidates iterators of
|
||||
+ // |when_defined_promise_map_|, so it must be called after erasing |entry|.
|
||||
+ resolver->Resolve();
|
||||
}
|
||||
|
||||
return definition;
|
||||
diff --git a/third_party/blink/web_tests/external/wpt/custom-elements/when-defined-reentry-crash.html b/third_party/blink/web_tests/external/wpt/custom-elements/when-defined-reentry-crash.html
|
||||
new file mode 100644
|
||||
index 0000000000000000000000000000000000000000..38614cbbd7836a955c40ea64165a22bcb44f7e63
|
||||
--- /dev/null
|
||||
+++ b/third_party/blink/web_tests/external/wpt/custom-elements/when-defined-reentry-crash.html
|
||||
@@ -0,0 +1,25 @@
|
||||
+<!DOCTYPE html>
|
||||
+<meta charset="utf-8">
|
||||
+<title>Check for crashes when a whenDefined promise resolving re-entries</title>
|
||||
+<meta name="author" href="mailto:xiaochengh@chromium.org">
|
||||
+<link rel="help" href="https://html.spec.whatwg.org/multipage/custom-elements.html#custom-elements-api">
|
||||
+<link rel="help" href="https://bugs.chromium.org/p/chromium/issues/detail?id=1366813">
|
||||
+<script>
|
||||
+class CustomElement extends HTMLElement {}
|
||||
+
|
||||
+Object.prototype.__defineGetter__("then", main);
|
||||
+
|
||||
+let depth = 0;
|
||||
+function main() {
|
||||
+ if (depth > 1) return;
|
||||
+ ++depth;
|
||||
+ customElements.whenDefined("custom-a"); // Causes re-entry of main()
|
||||
+ try { customElements.define("custom-a", CustomElement) } catch (e) {}
|
||||
+ customElements.whenDefined("custom-b");
|
||||
+ --depth;
|
||||
+}
|
||||
+
|
||||
+main();
|
||||
+</script>
|
||||
+
|
||||
+Test passes if it does not crash.
|
||||
102
patches/chromium/cherry-pick-a1cbf05b4163.patch
Normal file
102
patches/chromium/cherry-pick-a1cbf05b4163.patch
Normal file
@@ -0,0 +1,102 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Matt Wolenetz <wolenetz@chromium.org>
|
||||
Date: Fri, 4 Nov 2022 22:06:47 +0000
|
||||
Subject: webcodecs: Fix race in VE.isConfigSupported() promise resolution
|
||||
|
||||
If the context is destroyed before VideoEncoder calls `done_callback`, bad
|
||||
things can happen. That's why we extract a callback runner before doing
|
||||
anything asynchronous. Since we hold a ref-counted pointer to the
|
||||
runner it should be safe now.
|
||||
|
||||
(cherry picked from commit 2acf28478008315f302fd52b571623e784be707b)
|
||||
|
||||
Bug: 1375059
|
||||
Change-Id: I984ab27e03e50bd5ae4bf0eb13431834b14f89b7
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3965544
|
||||
Commit-Queue: Eugene Zemtsov <eugene@chromium.org>
|
||||
Reviewed-by: Dale Curtis <dalecurtis@chromium.org>
|
||||
Cr-Original-Commit-Position: refs/heads/main@{#1061737}
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/4005574
|
||||
Reviewed-by: Matthew Wolenetz <wolenetz@chromium.org>
|
||||
Cr-Commit-Position: refs/branch-heads/5249@{#911}
|
||||
Cr-Branched-From: 4f7bea5de862aaa52e6bde5920755a9ef9db120b-refs/heads/main@{#1036826}
|
||||
|
||||
diff --git a/third_party/blink/renderer/modules/webcodecs/video_encoder.cc b/third_party/blink/renderer/modules/webcodecs/video_encoder.cc
|
||||
index 291c18fc9b8f4fbb869e580843403818b44f2d43..ed7b3551fc9ddb5768fec46833363806129bd505 100644
|
||||
--- a/third_party/blink/renderer/modules/webcodecs/video_encoder.cc
|
||||
+++ b/third_party/blink/renderer/modules/webcodecs/video_encoder.cc
|
||||
@@ -68,6 +68,7 @@
|
||||
#include "third_party/blink/renderer/platform/instrumentation/use_counter.h"
|
||||
#include "third_party/blink/renderer/platform/scheduler/public/post_cross_thread_task.h"
|
||||
#include "third_party/blink/renderer/platform/scheduler/public/thread.h"
|
||||
+#include "third_party/blink/renderer/platform/wtf/cross_thread_copier_base.h"
|
||||
#include "third_party/blink/renderer/platform/wtf/cross_thread_copier_std.h"
|
||||
#include "third_party/blink/renderer/platform/wtf/cross_thread_functional.h"
|
||||
|
||||
@@ -100,16 +101,6 @@ namespace {
|
||||
constexpr const char kCategory[] = "media";
|
||||
constexpr int kMaxActiveEncodes = 5;
|
||||
|
||||
-// Use this function in cases when we can't immediately delete |ptr| because
|
||||
-// there might be its methods on the call stack.
|
||||
-template <typename T>
|
||||
-void DeleteLater(ScriptState* state, std::unique_ptr<T> ptr) {
|
||||
- DCHECK(state->ContextIsValid());
|
||||
- auto* context = ExecutionContext::From(state);
|
||||
- auto runner = context->GetTaskRunner(TaskType::kInternalDefault);
|
||||
- runner->DeleteSoon(FROM_HERE, std::move(ptr));
|
||||
-}
|
||||
-
|
||||
bool IsAcceleratedConfigurationSupported(
|
||||
media::VideoCodecProfile profile,
|
||||
const media::VideoEncoder::Options& options,
|
||||
@@ -988,6 +979,7 @@ void VideoEncoder::ResetInternal() {
|
||||
}
|
||||
|
||||
static void isConfigSupportedWithSoftwareOnly(
|
||||
+ ScriptState* script_state,
|
||||
ScriptPromiseResolver* resolver,
|
||||
VideoEncoderSupport* support,
|
||||
VideoEncoderTraits::ParsedConfig* config) {
|
||||
@@ -1012,22 +1004,25 @@ static void isConfigSupportedWithSoftwareOnly(
|
||||
return;
|
||||
}
|
||||
|
||||
- auto done_callback = [](std::unique_ptr<media::VideoEncoder> sw_encoder,
|
||||
+ auto done_callback = [](std::unique_ptr<media::VideoEncoder> encoder,
|
||||
ScriptPromiseResolver* resolver,
|
||||
+ scoped_refptr<base::SingleThreadTaskRunner> runner,
|
||||
VideoEncoderSupport* support,
|
||||
media::EncoderStatus status) {
|
||||
support->setSupported(status.is_ok());
|
||||
resolver->Resolve(support);
|
||||
- DeleteLater(resolver->GetScriptState(), std::move(sw_encoder));
|
||||
+ runner->DeleteSoon(FROM_HERE, std::move(encoder));
|
||||
};
|
||||
|
||||
+ auto* context = ExecutionContext::From(script_state);
|
||||
+ auto runner = context->GetTaskRunner(TaskType::kInternalDefault);
|
||||
auto* software_encoder_raw = software_encoder.get();
|
||||
software_encoder_raw->Initialize(
|
||||
config->profile, config->options, base::DoNothing(),
|
||||
- ConvertToBaseOnceCallback(
|
||||
- CrossThreadBindOnce(done_callback, std::move(software_encoder),
|
||||
- WrapCrossThreadPersistent(resolver),
|
||||
- WrapCrossThreadPersistent(support))));
|
||||
+ ConvertToBaseOnceCallback(CrossThreadBindOnce(
|
||||
+ done_callback, std::move(software_encoder),
|
||||
+ WrapCrossThreadPersistent(resolver), std::move(runner),
|
||||
+ WrapCrossThreadPersistent(support))));
|
||||
}
|
||||
|
||||
static void isConfigSupportedWithHardwareOnly(
|
||||
@@ -1114,7 +1109,8 @@ ScriptPromise VideoEncoder::isConfigSupported(ScriptState* script_state,
|
||||
promises.push_back(resolver->Promise());
|
||||
auto* support = VideoEncoderSupport::Create();
|
||||
support->setConfig(config_copy);
|
||||
- isConfigSupportedWithSoftwareOnly(resolver, support, parsed_config);
|
||||
+ isConfigSupportedWithSoftwareOnly(script_state, resolver, support,
|
||||
+ parsed_config);
|
||||
}
|
||||
|
||||
// Wait for all |promises| to resolve and check if any of them have
|
||||
285
patches/chromium/cherry-pick-ac4785387fff.patch
Normal file
285
patches/chromium/cherry-pick-ac4785387fff.patch
Normal file
@@ -0,0 +1,285 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Dave Tapuska <dtapuska@chromium.org>
|
||||
Date: Thu, 3 Nov 2022 23:16:16 +0000
|
||||
Subject: Fix PauseOrFreezeOnWorkerThread with nested Worklets.
|
||||
|
||||
Worklets can use the same backing thread which means we can have
|
||||
nested WorkerThreads paused. If a parent WorkerThread gets deallocated
|
||||
make sure we don't access anything after it is deallocated once the
|
||||
nested event queue is released.
|
||||
|
||||
BUG=1372695
|
||||
|
||||
(cherry picked from commit ff5696ba4bc0f8782e3de40e04685507d9f17fd2)
|
||||
|
||||
Change-Id: I176b8f750da5a41d19d1b3a623944d9a2ed4a441
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3953152
|
||||
Commit-Queue: Dave Tapuska <dtapuska@chromium.org>
|
||||
Reviewed-by: Daniel Cheng <dcheng@chromium.org>
|
||||
Cr-Original-Commit-Position: refs/heads/main@{#1059485}
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/4004562
|
||||
Cr-Commit-Position: refs/branch-heads/5249@{#906}
|
||||
Cr-Branched-From: 4f7bea5de862aaa52e6bde5920755a9ef9db120b-refs/heads/main@{#1036826}
|
||||
|
||||
diff --git a/third_party/blink/renderer/core/workers/threaded_worklet_test.cc b/third_party/blink/renderer/core/workers/threaded_worklet_test.cc
|
||||
index 80fc6e758afbfebedfbb0303854366d2c13d6bc0..5cc0138609f1944f03500b75d40634d1a7e946fa 100644
|
||||
--- a/third_party/blink/renderer/core/workers/threaded_worklet_test.cc
|
||||
+++ b/third_party/blink/renderer/core/workers/threaded_worklet_test.cc
|
||||
@@ -235,6 +235,7 @@ class ThreadedWorkletMessagingProxyForTest
|
||||
|
||||
private:
|
||||
friend class ThreadedWorkletTest;
|
||||
+ FRIEND_TEST_ALL_PREFIXES(ThreadedWorkletTest, NestedRunLoopTermination);
|
||||
|
||||
std::unique_ptr<WorkerThread> CreateWorkerThread() final {
|
||||
return std::make_unique<ThreadedWorkletThreadForTest>(WorkletObjectProxy());
|
||||
@@ -281,6 +282,16 @@ class ThreadedWorkletTest : public testing::Test {
|
||||
}
|
||||
Document& GetDocument() { return page_->GetDocument(); }
|
||||
|
||||
+ void WaitForReady(WorkerThread* worker_thread) {
|
||||
+ base::WaitableEvent child_waitable;
|
||||
+ PostCrossThreadTask(
|
||||
+ *worker_thread->GetTaskRunner(TaskType::kInternalTest), FROM_HERE,
|
||||
+ CrossThreadBindOnce(&base::WaitableEvent::Signal,
|
||||
+ CrossThreadUnretained(&child_waitable)));
|
||||
+
|
||||
+ child_waitable.Wait();
|
||||
+ }
|
||||
+
|
||||
private:
|
||||
std::unique_ptr<DummyPageHolder> page_;
|
||||
Persistent<ThreadedWorkletMessagingProxyForTest> messaging_proxy_;
|
||||
@@ -404,4 +415,40 @@ TEST_F(ThreadedWorkletTest, TaskRunner) {
|
||||
test::EnterRunLoop();
|
||||
}
|
||||
|
||||
+TEST_F(ThreadedWorkletTest, NestedRunLoopTermination) {
|
||||
+ MessagingProxy()->Start();
|
||||
+
|
||||
+ ThreadedWorkletMessagingProxyForTest* second_messaging_proxy =
|
||||
+ MakeGarbageCollected<ThreadedWorkletMessagingProxyForTest>(
|
||||
+ GetExecutionContext());
|
||||
+
|
||||
+ // Get a nested event loop where the first one is on the stack
|
||||
+ // and the second is still alive.
|
||||
+ second_messaging_proxy->Start();
|
||||
+
|
||||
+ // Wait until the workers are setup and ready to accept work before we
|
||||
+ // pause them.
|
||||
+ WaitForReady(GetWorkerThread());
|
||||
+ WaitForReady(second_messaging_proxy->GetWorkerThread());
|
||||
+
|
||||
+ // Pause the second worker, then the first.
|
||||
+ second_messaging_proxy->GetWorkerThread()->Pause();
|
||||
+ GetWorkerThread()->Pause();
|
||||
+
|
||||
+ // Resume then terminate the second worker.
|
||||
+ second_messaging_proxy->GetWorkerThread()->Resume();
|
||||
+ second_messaging_proxy->GetWorkerThread()->Terminate();
|
||||
+ second_messaging_proxy = nullptr;
|
||||
+
|
||||
+ // Now resume the first worker.
|
||||
+ GetWorkerThread()->Resume();
|
||||
+
|
||||
+ // Make sure execution still works without crashing.
|
||||
+ PostCrossThreadTask(
|
||||
+ *GetWorkerThread()->GetTaskRunner(TaskType::kInternalTest), FROM_HERE,
|
||||
+ CrossThreadBindOnce(&ThreadedWorkletThreadForTest::TestTaskRunner,
|
||||
+ CrossThreadUnretained(GetWorkerThread())));
|
||||
+ test::EnterRunLoop();
|
||||
+}
|
||||
+
|
||||
} // namespace blink
|
||||
diff --git a/third_party/blink/renderer/core/workers/worker_thread.cc b/third_party/blink/renderer/core/workers/worker_thread.cc
|
||||
index 892b3e58443f1a82a6a41c6d52df7d2d701b377d..3a98c2d192e1e47d1586d1dab1fc9e9dc9daf83b 100644
|
||||
--- a/third_party/blink/renderer/core/workers/worker_thread.cc
|
||||
+++ b/third_party/blink/renderer/core/workers/worker_thread.cc
|
||||
@@ -30,7 +30,6 @@
|
||||
#include <memory>
|
||||
#include <utility>
|
||||
|
||||
-#include "base/auto_reset.h"
|
||||
#include "base/metrics/histogram_functions.h"
|
||||
#include "base/synchronization/waitable_event.h"
|
||||
#include "base/threading/thread_restrictions.h"
|
||||
@@ -593,6 +592,7 @@ void WorkerThread::InitializeOnWorkerThread(
|
||||
const absl::optional<WorkerBackingThreadStartupData>& thread_startup_data,
|
||||
std::unique_ptr<WorkerDevToolsParams> devtools_params) {
|
||||
DCHECK(IsCurrentThread());
|
||||
+ backing_thread_weak_factory_.emplace(this);
|
||||
worker_reporting_proxy_.WillInitializeWorkerContext();
|
||||
{
|
||||
TRACE_EVENT0("blink.worker", "WorkerThread::InitializeWorkerContext");
|
||||
@@ -728,11 +728,13 @@ void WorkerThread::PrepareForShutdownOnWorkerThread() {
|
||||
SetThreadState(ThreadState::kReadyToShutdown);
|
||||
}
|
||||
|
||||
+ backing_thread_weak_factory_ = absl::nullopt;
|
||||
if (pause_or_freeze_count_ > 0) {
|
||||
DCHECK(nested_runner_);
|
||||
pause_or_freeze_count_ = 0;
|
||||
nested_runner_->QuitNow();
|
||||
}
|
||||
+ pause_handle_.reset();
|
||||
|
||||
{
|
||||
v8::HandleScope handle_scope(GetIsolate());
|
||||
@@ -883,8 +885,7 @@ void WorkerThread::PauseOrFreezeOnWorkerThread(
|
||||
if (pause_or_freeze_count_ > 1)
|
||||
return;
|
||||
|
||||
- std::unique_ptr<scheduler::WorkerScheduler::PauseHandle> pause_handle =
|
||||
- GetScheduler()->Pause();
|
||||
+ pause_handle_ = GetScheduler()->Pause();
|
||||
{
|
||||
// Since the nested message loop runner needs to be created and destroyed on
|
||||
// the same thread we allocate and destroy a new message loop runner each
|
||||
@@ -892,13 +893,20 @@ void WorkerThread::PauseOrFreezeOnWorkerThread(
|
||||
// the worker thread such that the resume/terminate can quit this runner.
|
||||
std::unique_ptr<Platform::NestedMessageLoopRunner> nested_runner =
|
||||
Platform::Current()->CreateNestedMessageLoopRunner();
|
||||
- base::AutoReset<Platform::NestedMessageLoopRunner*> nested_runner_autoreset(
|
||||
- &nested_runner_, nested_runner.get());
|
||||
+ auto weak_this = backing_thread_weak_factory_->GetWeakPtr();
|
||||
+ nested_runner_ = nested_runner.get();
|
||||
nested_runner->Run();
|
||||
+
|
||||
+ // Careful `this` may be destroyed.
|
||||
+ if (!weak_this) {
|
||||
+ return;
|
||||
+ }
|
||||
+ nested_runner_ = nullptr;
|
||||
}
|
||||
GlobalScope()->SetDefersLoadingForResourceFetchers(LoaderFreezeMode::kNone);
|
||||
GlobalScope()->SetIsInBackForwardCache(false);
|
||||
GlobalScope()->SetLifecycleState(mojom::blink::FrameLifecycleState::kRunning);
|
||||
+ pause_handle_.reset();
|
||||
}
|
||||
|
||||
void WorkerThread::ResumeOnWorkerThread() {
|
||||
diff --git a/third_party/blink/renderer/core/workers/worker_thread.h b/third_party/blink/renderer/core/workers/worker_thread.h
|
||||
index 89f75cbfba55c2760a018e99c4746c2e09b83c1b..b8b93f827d1892886fde662bf660d43f7bd646e3 100644
|
||||
--- a/third_party/blink/renderer/core/workers/worker_thread.h
|
||||
+++ b/third_party/blink/renderer/core/workers/worker_thread.h
|
||||
@@ -31,6 +31,7 @@
|
||||
|
||||
#include "base/gtest_prod_util.h"
|
||||
#include "base/memory/scoped_refptr.h"
|
||||
+#include "base/memory/weak_ptr.h"
|
||||
#include "base/synchronization/waitable_event.h"
|
||||
#include "base/task/single_thread_task_runner.h"
|
||||
#include "base/thread_annotations.h"
|
||||
@@ -78,7 +79,7 @@ struct WorkerMainScriptLoadParameters;
|
||||
// abstract class. Multiple WorkerThreads may share one WorkerBackingThread for
|
||||
// worklets.
|
||||
//
|
||||
-// WorkerThread start and termination must be initiated on the main thread and
|
||||
+// WorkerThread start and termination must be initiated on the parent thread and
|
||||
// an actual task is executed on the worker thread.
|
||||
//
|
||||
// When termination starts, (debugger) tasks on WorkerThread are handled as
|
||||
@@ -101,7 +102,7 @@ class CORE_EXPORT WorkerThread : public Thread::TaskObserver {
|
||||
~WorkerThread() override;
|
||||
|
||||
// Starts the underlying thread and creates the global scope. Called on the
|
||||
- // main thread.
|
||||
+ // parent thread.
|
||||
// Startup data for WorkerBackingThread is absl::nullopt if |this| doesn't own
|
||||
// the underlying WorkerBackingThread.
|
||||
// TODO(nhiroki): We could separate WorkerBackingThread initialization from
|
||||
@@ -113,14 +114,14 @@ class CORE_EXPORT WorkerThread : public Thread::TaskObserver {
|
||||
std::unique_ptr<WorkerDevToolsParams>);
|
||||
|
||||
// Posts a task to evaluate a top-level classic script on the worker thread.
|
||||
- // Called on the main thread after Start().
|
||||
+ // Called on the parent thread after Start().
|
||||
void EvaluateClassicScript(const KURL& script_url,
|
||||
const String& source_code,
|
||||
std::unique_ptr<Vector<uint8_t>> cached_meta_data,
|
||||
const v8_inspector::V8StackTraceId& stack_id);
|
||||
|
||||
// Posts a task to fetch and run a top-level classic script on the worker
|
||||
- // thread. Called on the main thread after Start().
|
||||
+ // thread. Called on the parent thread after Start().
|
||||
void FetchAndRunClassicScript(
|
||||
const KURL& script_url,
|
||||
std::unique_ptr<WorkerMainScriptLoadParameters>
|
||||
@@ -131,7 +132,7 @@ class CORE_EXPORT WorkerThread : public Thread::TaskObserver {
|
||||
const v8_inspector::V8StackTraceId& stack_id);
|
||||
|
||||
// Posts a task to fetch and run a top-level module script on the worker
|
||||
- // thread. Called on the main thread after Start().
|
||||
+ // thread. Called on the parent thread after Start().
|
||||
void FetchAndRunModuleScript(
|
||||
const KURL& script_url,
|
||||
std::unique_ptr<WorkerMainScriptLoadParameters>
|
||||
@@ -152,7 +153,7 @@ class CORE_EXPORT WorkerThread : public Thread::TaskObserver {
|
||||
// Terminates the worker thread. Subclasses of WorkerThread can override this
|
||||
// to do cleanup. The default behavior is to call Terminate() and
|
||||
// synchronously call EnsureScriptExecutionTerminates() to ensure the thread
|
||||
- // is quickly terminated. Called on the main thread.
|
||||
+ // is quickly terminated. Called on the parent thread.
|
||||
virtual void TerminateForTesting();
|
||||
|
||||
// Thread::TaskObserver.
|
||||
@@ -179,7 +180,7 @@ class CORE_EXPORT WorkerThread : public Thread::TaskObserver {
|
||||
void DebuggerTaskStarted();
|
||||
void DebuggerTaskFinished();
|
||||
|
||||
- // Callable on both the main thread and the worker thread.
|
||||
+ // Callable on both the parent thread and the worker thread.
|
||||
const base::UnguessableToken& GetDevToolsWorkerToken() const {
|
||||
return devtools_worker_token_;
|
||||
}
|
||||
@@ -323,7 +324,7 @@ class CORE_EXPORT WorkerThread : public Thread::TaskObserver {
|
||||
// already shutting down. Does not terminate if a debugger task is running,
|
||||
// because the debugger task is guaranteed to finish and it heavily uses V8
|
||||
// API calls which would crash after forcible script termination. Called on
|
||||
- // the main thread.
|
||||
+ // the parent thread.
|
||||
void EnsureScriptExecutionTerminates(ExitCode) LOCKS_EXCLUDED(mutex_);
|
||||
|
||||
// These are called in this order during worker thread startup.
|
||||
@@ -408,7 +409,7 @@ class CORE_EXPORT WorkerThread : public Thread::TaskObserver {
|
||||
// A unique identifier among all WorkerThreads.
|
||||
const int worker_thread_id_;
|
||||
|
||||
- // Set on the main thread.
|
||||
+ // Set on the parent thread.
|
||||
bool requested_to_terminate_ GUARDED_BY(mutex_) = false;
|
||||
|
||||
ThreadState thread_state_ GUARDED_BY(mutex_) = ThreadState::kNotStarted;
|
||||
@@ -442,7 +443,7 @@ class CORE_EXPORT WorkerThread : public Thread::TaskObserver {
|
||||
TaskTypeTraits>;
|
||||
TaskRunnerHashMap worker_task_runners_;
|
||||
|
||||
- // This lock protects shared states between the main thread and the worker
|
||||
+ // This lock protects shared states between the parent thread and the worker
|
||||
// thread. See thread-safety annotations (e.g., GUARDED_BY) in this header
|
||||
// file.
|
||||
Mutex mutex_;
|
||||
@@ -451,6 +452,10 @@ class CORE_EXPORT WorkerThread : public Thread::TaskObserver {
|
||||
// only on the worker thread.
|
||||
int pause_or_freeze_count_ = 0;
|
||||
|
||||
+ // The `PauseHandle` needs to be destroyed before the scheduler is destroyed
|
||||
+ // otherwise we will hit a DCHECK.
|
||||
+ std::unique_ptr<scheduler::WorkerScheduler::PauseHandle> pause_handle_;
|
||||
+
|
||||
// A nested message loop for handling pausing. Pointer is not owned. Used only
|
||||
// on the worker thread.
|
||||
Platform::NestedMessageLoopRunner* nested_runner_ = nullptr;
|
||||
@@ -477,6 +482,12 @@ class CORE_EXPORT WorkerThread : public Thread::TaskObserver {
|
||||
HashSet<std::unique_ptr<InterruptData>> pending_interrupts_
|
||||
GUARDED_BY(mutex_);
|
||||
|
||||
+ // Since the WorkerThread is allocated and deallocated on the parent thread,
|
||||
+ // we need a WeakPtrFactory that is allocated and cleared on the backing
|
||||
+ // thread.
|
||||
+ absl::optional<base::WeakPtrFactory<WorkerThread>>
|
||||
+ backing_thread_weak_factory_;
|
||||
+
|
||||
THREAD_CHECKER(parent_thread_checker_);
|
||||
};
|
||||
|
||||
86
patches/chromium/cherry-pick-cb9dff93f3d4.patch
Normal file
86
patches/chromium/cherry-pick-cb9dff93f3d4.patch
Normal file
@@ -0,0 +1,86 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Harald Alvestrand <hta@chromium.org>
|
||||
Date: Mon, 10 Oct 2022 08:37:15 +0000
|
||||
Subject: Use HeapMojoReceiver rather than mojo::Receiver for
|
||||
PeerConnectionTracker
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
|
||||
HeapMojoReceiver is recommended for garbage collected objects, avoiding
|
||||
problems with conflicting lifetimes.
|
||||
|
||||
(cherry picked from commit e3437317c4cd8401f0f0d599b61751bbe0e1ec70)
|
||||
|
||||
Bug: chromium:1369882
|
||||
Change-Id: Ic38e761cf4275e6d7b30a6d7e2daa5d1596e67a4
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3936144
|
||||
Reviewed-by: Henrik Boström <hbos@chromium.org>
|
||||
Commit-Queue: Harald Alvestrand <hta@chromium.org>
|
||||
Cr-Original-Commit-Position: refs/heads/main@{#1055630}
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3934344
|
||||
Commit-Queue: Henrik Boström <hbos@chromium.org>
|
||||
Auto-Submit: Harald Alvestrand <hta@chromium.org>
|
||||
Cr-Commit-Position: refs/branch-heads/5249@{#790}
|
||||
Cr-Branched-From: 4f7bea5de862aaa52e6bde5920755a9ef9db120b-refs/heads/main@{#1036826}
|
||||
|
||||
diff --git a/third_party/blink/renderer/modules/peerconnection/peer_connection_tracker.cc b/third_party/blink/renderer/modules/peerconnection/peer_connection_tracker.cc
|
||||
index 7789929aafbb596d22c0af46e67bc4a1c9970fe9..1b068312ef9bea8f54dfbabee1a3bafc0c34801b 100644
|
||||
--- a/third_party/blink/renderer/modules/peerconnection/peer_connection_tracker.cc
|
||||
+++ b/third_party/blink/renderer/modules/peerconnection/peer_connection_tracker.cc
|
||||
@@ -648,16 +648,20 @@ PeerConnectionTracker::PeerConnectionTracker(
|
||||
scoped_refptr<base::SingleThreadTaskRunner> main_thread_task_runner,
|
||||
base::PassKey<PeerConnectionTracker>)
|
||||
: Supplement<LocalDOMWindow>(window),
|
||||
+ receiver_(this, &window),
|
||||
main_thread_task_runner_(std::move(main_thread_task_runner)) {
|
||||
window.GetBrowserInterfaceBroker().GetInterface(
|
||||
peer_connection_tracker_host_.BindNewPipeAndPassReceiver());
|
||||
}
|
||||
|
||||
+// Constructor used for testing. Note that receiver_ doesn't have a context
|
||||
+// notifier in this case.
|
||||
PeerConnectionTracker::PeerConnectionTracker(
|
||||
mojo::Remote<blink::mojom::blink::PeerConnectionTrackerHost> host,
|
||||
scoped_refptr<base::SingleThreadTaskRunner> main_thread_task_runner)
|
||||
: Supplement(nullptr),
|
||||
peer_connection_tracker_host_(std::move(host)),
|
||||
+ receiver_(this, nullptr),
|
||||
main_thread_task_runner_(std::move(main_thread_task_runner)) {}
|
||||
|
||||
PeerConnectionTracker::~PeerConnectionTracker() {}
|
||||
diff --git a/third_party/blink/renderer/modules/peerconnection/peer_connection_tracker.h b/third_party/blink/renderer/modules/peerconnection/peer_connection_tracker.h
|
||||
index 101670d8a31154047762a060fcd13ce342dd758c..fc8ee4bc429d4abb637b121b6969880cb07f186d 100644
|
||||
--- a/third_party/blink/renderer/modules/peerconnection/peer_connection_tracker.h
|
||||
+++ b/third_party/blink/renderer/modules/peerconnection/peer_connection_tracker.h
|
||||
@@ -15,6 +15,7 @@
|
||||
#include "third_party/blink/renderer/core/frame/local_dom_window.h"
|
||||
#include "third_party/blink/renderer/modules/mediastream/media_stream.h"
|
||||
#include "third_party/blink/renderer/modules/modules_export.h"
|
||||
+#include "third_party/blink/renderer/platform/mojo/heap_mojo_receiver.h"
|
||||
#include "third_party/blink/renderer/platform/peerconnection/rtc_peer_connection_handler_client.h"
|
||||
#include "third_party/blink/renderer/platform/peerconnection/rtc_rtp_transceiver_platform.h"
|
||||
#include "third_party/blink/renderer/platform/peerconnection/rtc_session_description_platform.h"
|
||||
@@ -257,6 +258,11 @@ class MODULES_EXPORT PeerConnectionTracker
|
||||
virtual void TrackRtcEventLogWrite(RTCPeerConnectionHandler* pc_handler,
|
||||
const WTF::Vector<uint8_t>& output);
|
||||
|
||||
+ void Trace(Visitor* visitor) const override {
|
||||
+ visitor->Trace(receiver_);
|
||||
+ Supplement<LocalDOMWindow>::Trace(visitor);
|
||||
+ }
|
||||
+
|
||||
private:
|
||||
FRIEND_TEST_ALL_PREFIXES(PeerConnectionTrackerTest, OnSuspend);
|
||||
FRIEND_TEST_ALL_PREFIXES(PeerConnectionTrackerTest, OnThermalStateChange);
|
||||
@@ -325,7 +331,9 @@ class MODULES_EXPORT PeerConnectionTracker
|
||||
THREAD_CHECKER(main_thread_);
|
||||
mojo::Remote<blink::mojom::blink::PeerConnectionTrackerHost>
|
||||
peer_connection_tracker_host_;
|
||||
- mojo::Receiver<blink::mojom::blink::PeerConnectionManager> receiver_{this};
|
||||
+ HeapMojoReceiver<blink::mojom::blink::PeerConnectionManager,
|
||||
+ PeerConnectionTracker>
|
||||
+ receiver_;
|
||||
|
||||
scoped_refptr<base::SingleThreadTaskRunner> main_thread_task_runner_;
|
||||
};
|
||||
70
patches/chromium/cherry-pick-d5ffb4dd4112.patch
Normal file
70
patches/chromium/cherry-pick-d5ffb4dd4112.patch
Normal file
@@ -0,0 +1,70 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Shrek Shao <shrekshao@google.com>
|
||||
Date: Tue, 18 Oct 2022 01:30:12 +0000
|
||||
Subject: WebGPU: use CHECK instead of DCHECK to crash out of bounds write in
|
||||
SerializeDataUpdate
|
||||
|
||||
A comprised renderer could have a shared memory size not large enough
|
||||
to fit the GPU buffer contents. Instead of DCHECK, do a CHECK here to
|
||||
crash the release build. The crash is fine since it is not reachable
|
||||
from normal behavior. WebGPU post-V1 will have a refactored API.
|
||||
|
||||
(cherry picked from commit 9bcbce75d5feaa1ba48a5d0d8036b5c77500bb67)
|
||||
|
||||
Fixed: 1373314
|
||||
Change-Id: I8d8e1a469c2b10ff16e7363f9b6f7b63587cb007
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3946246
|
||||
Reviewed-by: Austin Eng <enga@chromium.org>
|
||||
Commit-Queue: Shrek Shao <shrekshao@google.com>
|
||||
Cr-Original-Commit-Position: refs/heads/main@{#1058233}
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3956286
|
||||
Owners-Override: Prudhvikumar Bommana <pbommana@google.com>
|
||||
Reviewed-by: Prudhvikumar Bommana <pbommana@google.com>
|
||||
Commit-Queue: Prudhvikumar Bommana <pbommana@google.com>
|
||||
Cr-Commit-Position: refs/branch-heads/5249@{#850}
|
||||
Cr-Branched-From: 4f7bea5de862aaa52e6bde5920755a9ef9db120b-refs/heads/main@{#1036826}
|
||||
|
||||
diff --git a/gpu/command_buffer/service/dawn_service_memory_transfer_service.cc b/gpu/command_buffer/service/dawn_service_memory_transfer_service.cc
|
||||
index 579cd3cbdfcd5990db02960413bcac86e41c69b2..a15b6f9b3b345079d8cf8251ca5f77b6e7ef647a 100644
|
||||
--- a/gpu/command_buffer/service/dawn_service_memory_transfer_service.cc
|
||||
+++ b/gpu/command_buffer/service/dawn_service_memory_transfer_service.cc
|
||||
@@ -30,8 +30,13 @@ class ReadHandleImpl
|
||||
size_t offset,
|
||||
size_t size,
|
||||
void* serializePointer) override {
|
||||
- DCHECK_LE(offset, size_);
|
||||
- DCHECK_LE(size, size_ - offset);
|
||||
+ // TODO(crbug.com/1373314): A compromised renderer could have a shared
|
||||
+ // memory size not large enough to fit the GPU buffer contents. Instead of
|
||||
+ // DCHECK, do a CHECK here to crash the release build. The crash is fine
|
||||
+ // since it is not reachable from normal behavior. WebGPU post-V1 will have
|
||||
+ // a refactored API.
|
||||
+ CHECK_LE(offset, size_);
|
||||
+ CHECK_LE(size, size_ - offset);
|
||||
// Copy the data into the shared memory allocation.
|
||||
// In the case of buffer mapping, this is the mapped GPU memory which we
|
||||
// copy into client-visible shared memory.
|
||||
@@ -94,7 +99,10 @@ bool DawnServiceMemoryTransferService::DeserializeReadHandle(
|
||||
size_t deserialize_size,
|
||||
ReadHandle** read_handle) {
|
||||
DCHECK(deserialize_pointer);
|
||||
- DCHECK_EQ(deserialize_size, sizeof(MemoryTransferHandle));
|
||||
+ // Use CHECK instead of DCHECK because the cast of the memory to
|
||||
+ // MemoryTransferHandle and subsequent reads won't be safe if deserialize_size
|
||||
+ // is too small.
|
||||
+ CHECK_EQ(deserialize_size, sizeof(MemoryTransferHandle));
|
||||
const volatile MemoryTransferHandle* handle =
|
||||
reinterpret_cast<const volatile MemoryTransferHandle*>(
|
||||
deserialize_pointer);
|
||||
@@ -119,7 +127,10 @@ bool DawnServiceMemoryTransferService::DeserializeWriteHandle(
|
||||
size_t deserialize_size,
|
||||
WriteHandle** write_handle) {
|
||||
DCHECK(deserialize_pointer);
|
||||
- DCHECK_EQ(deserialize_size, sizeof(MemoryTransferHandle));
|
||||
+ // Use CHECK instead of DCHECK because the cast of the memory to
|
||||
+ // MemoryTransferHandle and subsequent reads won't be safe if deserialize_size
|
||||
+ // is too small.
|
||||
+ CHECK_EQ(deserialize_size, sizeof(MemoryTransferHandle));
|
||||
const volatile MemoryTransferHandle* handle =
|
||||
reinterpret_cast<const volatile MemoryTransferHandle*>(
|
||||
deserialize_pointer);
|
||||
46
patches/chromium/cherry-pick-eb4d31309df7.patch
Normal file
46
patches/chromium/cherry-pick-eb4d31309df7.patch
Normal file
@@ -0,0 +1,46 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Stefan Zager <szager@chromium.org>
|
||||
Date: Fri, 9 Sep 2022 01:56:46 +0000
|
||||
Subject: Fix for reference to invalid iterator
|
||||
|
||||
Evidently, LocalFrameView::layout_subtree_root_list_ can be modified
|
||||
during LayoutFromRootObject, leaving the loop variable in an invalid
|
||||
state. I don't know the exact sequence, but the test case crashes for
|
||||
me without this patch, and doesn't crash with the patch.
|
||||
|
||||
(cherry picked from commit 815aa5ca03ab4ecc619b2d2ad7650531bd3892a8)
|
||||
|
||||
Bug: 1355237
|
||||
Change-Id: Ib17b1fac5b2ec060eda39be76305db18075802fa
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3864877
|
||||
Reviewed-by: Ian Kilpatrick <ikilpatrick@chromium.org>
|
||||
Commit-Queue: Stefan Zager <szager@chromium.org>
|
||||
Cr-Original-Commit-Position: refs/heads/main@{#1041903}
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3884238
|
||||
Owners-Override: Srinivas Sista <srinivassista@chromium.org>
|
||||
Auto-Submit: Srinivas Sista <srinivassista@chromium.org>
|
||||
Reviewed-by: Stefan Zager <szager@chromium.org>
|
||||
Cr-Commit-Position: refs/branch-heads/5112@{#1566}
|
||||
Cr-Branched-From: b13d3fe7b3c47a56354ef54b221008afa754412e-refs/heads/main@{#1012729}
|
||||
|
||||
diff --git a/third_party/blink/renderer/core/frame/local_frame_view.cc b/third_party/blink/renderer/core/frame/local_frame_view.cc
|
||||
index 8a9dabd602b54b4801406bffb26723b4105c5fdc..82963b7edb85da99f4bbf345b22e70d50ac1573c 100644
|
||||
--- a/third_party/blink/renderer/core/frame/local_frame_view.cc
|
||||
+++ b/third_party/blink/renderer/core/frame/local_frame_view.cc
|
||||
@@ -821,6 +821,7 @@ void LocalFrameView::PerformLayout() {
|
||||
}
|
||||
for (auto& root : layout_subtree_root_list_.Ordered()) {
|
||||
bool should_rebuild_fragments = false;
|
||||
+ LayoutObject& root_layout_object = *root;
|
||||
LayoutBlock* cb = root->ContainingNGBlock();
|
||||
if (cb) {
|
||||
auto it = fragment_tree_spines.find(cb);
|
||||
@@ -840,7 +841,7 @@ void LocalFrameView::PerformLayout() {
|
||||
// We need to ensure that we mark up all layoutObjects up to the
|
||||
// LayoutView for paint invalidation. This simplifies our code as we
|
||||
// just always do a full tree walk.
|
||||
- if (LayoutObject* container = root->Container())
|
||||
+ if (LayoutObject* container = root_layout_object.Container())
|
||||
container->SetShouldCheckForPaintInvalidation();
|
||||
}
|
||||
layout_subtree_root_list_.Clear();
|
||||
128
patches/chromium/cherry-pick-ecad352cd614.patch
Normal file
128
patches/chromium/cherry-pick-ecad352cd614.patch
Normal file
@@ -0,0 +1,128 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Ted Meyer <tmathmeyer@chromium.org>
|
||||
Date: Wed, 8 Jun 2022 04:33:20 +0000
|
||||
Subject: Add Stop method to BatchingMediaLog
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
|
||||
Now that ~MediaLog is posted for a later destruction due to garbage
|
||||
collector ownership of CodecLogger, it's possible for the
|
||||
SendQueuedMediaEvents call from ~BatchingMediaLog to reference
|
||||
InspectorMediaEventHandler::inspector_context_ after it has been freed.
|
||||
|
||||
This fix forces BatchingMediaLog to shut down it's logging capabilities
|
||||
when the destruction call is caused by the garbage collector deletion
|
||||
phase
|
||||
|
||||
R=liberato
|
||||
|
||||
(cherry picked from commit 1bbfaf23cd8a1e977cb445a82a4caae107632a59)
|
||||
|
||||
Bug: 1333333
|
||||
Change-Id: I0bdca72a71177c4c5a6a9dc692aad3de4c25f4e2
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3689639
|
||||
Commit-Queue: Ted (Chromium) Meyer <tmathmeyer@chromium.org>
|
||||
Reviewed-by: Eugene Zemtsov <eugene@chromium.org>
|
||||
Cr-Original-Commit-Position: refs/heads/main@{#1011247}
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3694435
|
||||
Auto-Submit: Ted (Chromium) Meyer <tmathmeyer@chromium.org>
|
||||
Reviewed-by: Eugene Zemtsov <ezemtsov@google.com>
|
||||
Commit-Queue: Eugene Zemtsov <eugene@chromium.org>
|
||||
Cr-Commit-Position: refs/branch-heads/5060@{#672}
|
||||
Cr-Branched-From: b83393d0f4038aeaf67f970a024d8101df7348d1-refs/heads/main@{#1002911}
|
||||
|
||||
diff --git a/content/renderer/media/batching_media_log.cc b/content/renderer/media/batching_media_log.cc
|
||||
index 42b6fb68c294b9834f0b123ed18688482de460bc..efd56d9a0cf70cd502901d47d3639663445527e8 100644
|
||||
--- a/content/renderer/media/batching_media_log.cc
|
||||
+++ b/content/renderer/media/batching_media_log.cc
|
||||
@@ -76,6 +76,11 @@ BatchingMediaLog::~BatchingMediaLog() {
|
||||
SendQueuedMediaEvents();
|
||||
}
|
||||
|
||||
+void BatchingMediaLog::Stop() {
|
||||
+ base::AutoLock lock(lock_);
|
||||
+ event_handlers_.clear();
|
||||
+}
|
||||
+
|
||||
void BatchingMediaLog::OnWebMediaPlayerDestroyedLocked() {
|
||||
base::AutoLock lock(lock_);
|
||||
for (const auto& handler : event_handlers_)
|
||||
diff --git a/content/renderer/media/batching_media_log.h b/content/renderer/media/batching_media_log.h
|
||||
index eb757a4ca922bd5456d0e436d10cc540ee9134ae..6c2df688caee4d2fc17e973cdad12f20342e56fe 100644
|
||||
--- a/content/renderer/media/batching_media_log.h
|
||||
+++ b/content/renderer/media/batching_media_log.h
|
||||
@@ -45,6 +45,8 @@ class CONTENT_EXPORT BatchingMediaLog : public media::MediaLog {
|
||||
|
||||
~BatchingMediaLog() override;
|
||||
|
||||
+ void Stop() override;
|
||||
+
|
||||
// Will reset |last_ipc_send_time_| with the value of NowTicks().
|
||||
void SetTickClockForTesting(const base::TickClock* tick_clock);
|
||||
|
||||
diff --git a/media/base/media_log.cc b/media/base/media_log.cc
|
||||
index 3728433c5eb473cc9c82b6cf33b22bbf89471eea..46887da3dc21c504b26d6ff174eb14d68298c6b1 100644
|
||||
--- a/media/base/media_log.cc
|
||||
+++ b/media/base/media_log.cc
|
||||
@@ -49,6 +49,9 @@ std::string MediaLog::GetErrorMessageLocked() {
|
||||
return "";
|
||||
}
|
||||
|
||||
+// Default implementation.
|
||||
+void MediaLog::Stop() {}
|
||||
+
|
||||
void MediaLog::AddMessage(MediaLogMessageLevel level, std::string message) {
|
||||
std::unique_ptr<MediaLogRecord> record(
|
||||
CreateRecord(MediaLogRecord::Type::kMessage));
|
||||
diff --git a/media/base/media_log.h b/media/base/media_log.h
|
||||
index e70a95b72f75f9bbfb114a94396c048bce2a3647..cce6a266327b43837d7a6ccaca7f2969c06fef4b 100644
|
||||
--- a/media/base/media_log.h
|
||||
+++ b/media/base/media_log.h
|
||||
@@ -131,6 +131,10 @@ class MEDIA_EXPORT MediaLog {
|
||||
// even if this occurs, in the "won't crash" sense.
|
||||
virtual std::unique_ptr<MediaLog> Clone();
|
||||
|
||||
+ // Can be used for stopping a MediaLog during a garbage-collected destruction
|
||||
+ // sequence.
|
||||
+ virtual void Stop();
|
||||
+
|
||||
protected:
|
||||
// Ensures only subclasses and factories (e.g. Clone()) can create MediaLog.
|
||||
MediaLog();
|
||||
diff --git a/third_party/blink/renderer/modules/webcodecs/codec_logger.h b/third_party/blink/renderer/modules/webcodecs/codec_logger.h
|
||||
index 5d3f9fd53bcea8cf6220e862b095d5e109ff9857..44bbb6675e600145971339672a6eb9dc2f794daf 100644
|
||||
--- a/third_party/blink/renderer/modules/webcodecs/codec_logger.h
|
||||
+++ b/third_party/blink/renderer/modules/webcodecs/codec_logger.h
|
||||
@@ -72,9 +72,20 @@ class MODULES_EXPORT CodecLogger final {
|
||||
// This allows us to destroy |parent_media_log_| and stop logging,
|
||||
// without causing problems to |media_log_| users.
|
||||
media_log_ = parent_media_log_->Clone();
|
||||
+
|
||||
+ task_runner_ = task_runner;
|
||||
}
|
||||
|
||||
- ~CodecLogger() { DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); }
|
||||
+ ~CodecLogger() {
|
||||
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
|
||||
+ // media logs must be posted for destruction, since they can cause the
|
||||
+ // garbage collector to trigger an immediate cleanup and delete the owning
|
||||
+ // instance of |CodecLogger|.
|
||||
+ if (parent_media_log_) {
|
||||
+ parent_media_log_->Stop();
|
||||
+ task_runner_->DeleteSoon(FROM_HERE, std::move(parent_media_log_));
|
||||
+ }
|
||||
+ }
|
||||
|
||||
void SendPlayerNameInformation(const ExecutionContext& context,
|
||||
std::string loadedAs) {
|
||||
@@ -135,6 +146,9 @@ class MODULES_EXPORT CodecLogger final {
|
||||
// can be safely accessed, and whose raw pointer can be given callbacks.
|
||||
std::unique_ptr<media::MediaLog> media_log_;
|
||||
|
||||
+ // Keep task runner around for posting the media log to upon destruction.
|
||||
+ scoped_refptr<base::SingleThreadTaskRunner> task_runner_;
|
||||
+
|
||||
SEQUENCE_CHECKER(sequence_checker_);
|
||||
};
|
||||
|
||||
305
patches/chromium/cherry-pick-fefd6198da31.patch
Normal file
305
patches/chromium/cherry-pick-fefd6198da31.patch
Normal file
@@ -0,0 +1,305 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Ben Wagner <benjaminwagner@google.com>
|
||||
Date: Tue, 20 Sep 2022 18:38:53 +0000
|
||||
Subject: Fix races in FrameQueueUnderlyingSource related to
|
||||
CrossThreadPersistent
|
||||
|
||||
The repro in bug 1323488 unfortunately does not reliably reproduce
|
||||
the races when run as a web test. I was also not able to repro the
|
||||
races in a unit test.
|
||||
|
||||
There are actually three fixes in this CL; it was easiest to fix them
|
||||
all together so that I can run the repro locally for an extended period
|
||||
without it being stopped by a crash.
|
||||
|
||||
The underlying cause for all three races is that CrossThreadPersistent
|
||||
can refer to an object whose heap has already been destroyed. When
|
||||
accessed on the thread corresponding to that heap, there is no race,
|
||||
but when accessed from a different thread, there is a period of time
|
||||
after the heap is destroyed before the CrossThreadPersistent is
|
||||
cleared.
|
||||
|
||||
1. The FrameQueueUnderlyingSource::transferred_source_ member's pointer
|
||||
is accessed in FrameQueueUnderlyingSource::Close. This CL adds a
|
||||
callback to clear the pointer in
|
||||
TransferredFrameQueueUnderlyingSource::ContextDestroyed.
|
||||
|
||||
2. The TransferredFrameQueueUnderlyingSource constructor takes a raw
|
||||
pointer to the original FrameQueueUnderlyingSource, which is
|
||||
associated with a different thread. GC won't be able to update this
|
||||
raw pointer since it's on the wrong stack. This CL changes the raw
|
||||
pointer to a CrossThreadPersistent which is visible to GC.
|
||||
|
||||
3. Same as 2, but for the callstack ConnectHostCallback,
|
||||
MediaStream(Audio|Video)TrackUnderlyingSource::OnSourceTransferStarted
|
||||
and FrameQueueUnderlyingSource::TransferSource.
|
||||
|
||||
(cherry picked from commit 63ce9c40e1a67395278dfc70ecfb545a818747bb)
|
||||
|
||||
Bug: 1323488
|
||||
Change-Id: Id63484eebefd2e003959b25bd752ac8263caab4f
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3865452
|
||||
Commit-Queue: Ben Wagner <benjaminwagner@google.com>
|
||||
Reviewed-by: Thomas Guilbert <tguilbert@chromium.org>
|
||||
Auto-Submit: Ben Wagner <benjaminwagner@google.com>
|
||||
Cr-Original-Commit-Position: refs/heads/main@{#1041434}
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3908010
|
||||
Commit-Queue: Srinivas Sista <srinivassista@chromium.org>
|
||||
Reviewed-by: Srinivas Sista <srinivassista@chromium.org>
|
||||
Cr-Commit-Position: refs/branch-heads/5249@{#521}
|
||||
Cr-Branched-From: 4f7bea5de862aaa52e6bde5920755a9ef9db120b-refs/heads/main@{#1036826}
|
||||
|
||||
diff --git a/third_party/blink/renderer/modules/breakout_box/frame_queue_transferring_optimizer.cc b/third_party/blink/renderer/modules/breakout_box/frame_queue_transferring_optimizer.cc
|
||||
index 2cc89e8cd32421bf80b262bac2e4a7cb685db62f..ab41fa086ad9eb8c1cd66db74ea1f05a66ac56a4 100644
|
||||
--- a/third_party/blink/renderer/modules/breakout_box/frame_queue_transferring_optimizer.cc
|
||||
+++ b/third_party/blink/renderer/modules/breakout_box/frame_queue_transferring_optimizer.cc
|
||||
@@ -19,10 +19,13 @@ FrameQueueTransferringOptimizer<NativeFrameType>::
|
||||
FrameQueueHost* host,
|
||||
scoped_refptr<base::SequencedTaskRunner> host_runner,
|
||||
wtf_size_t max_queue_size,
|
||||
- ConnectHostCallback connect_host_callback)
|
||||
+ ConnectHostCallback connect_host_callback,
|
||||
+ CrossThreadOnceClosure transferred_source_destroyed_callback)
|
||||
: host_(host),
|
||||
host_runner_(std::move(host_runner)),
|
||||
connect_host_callback_(std::move(connect_host_callback)),
|
||||
+ transferred_source_destroyed_callback_(
|
||||
+ std::move(transferred_source_destroyed_callback)),
|
||||
max_queue_size_(max_queue_size) {}
|
||||
|
||||
template <typename NativeFrameType>
|
||||
@@ -40,7 +43,8 @@ FrameQueueTransferringOptimizer<NativeFrameType>::PerformInProcessOptimization(
|
||||
|
||||
auto* source = MakeGarbageCollected<
|
||||
TransferredFrameQueueUnderlyingSource<NativeFrameType>>(
|
||||
- script_state, host, host_runner_);
|
||||
+ script_state, host, host_runner_,
|
||||
+ std::move(transferred_source_destroyed_callback_));
|
||||
|
||||
PostCrossThreadTask(
|
||||
*host_runner_, FROM_HERE,
|
||||
diff --git a/third_party/blink/renderer/modules/breakout_box/frame_queue_transferring_optimizer.h b/third_party/blink/renderer/modules/breakout_box/frame_queue_transferring_optimizer.h
|
||||
index 6d33945b7c840e55ae73a1efd1f1cf33ccfaaa71..336073235ba7f6c05cf2cf19fccbfac0be9597c9 100644
|
||||
--- a/third_party/blink/renderer/modules/breakout_box/frame_queue_transferring_optimizer.h
|
||||
+++ b/third_party/blink/renderer/modules/breakout_box/frame_queue_transferring_optimizer.h
|
||||
@@ -25,13 +25,15 @@ class FrameQueueTransferringOptimizer final
|
||||
|
||||
using ConnectHostCallback = CrossThreadOnceFunction<void(
|
||||
scoped_refptr<base::SequencedTaskRunner>,
|
||||
- TransferredFrameQueueUnderlyingSource<NativeFrameType>*)>;
|
||||
+ CrossThreadPersistent<
|
||||
+ TransferredFrameQueueUnderlyingSource<NativeFrameType>>)>;
|
||||
|
||||
FrameQueueTransferringOptimizer(
|
||||
FrameQueueHost*,
|
||||
scoped_refptr<base::SequencedTaskRunner> host_runner,
|
||||
wtf_size_t max_queue_size,
|
||||
- ConnectHostCallback callback);
|
||||
+ ConnectHostCallback connect_host_callback,
|
||||
+ CrossThreadOnceFunction<void()> transferred_source_destroyed_callback);
|
||||
~FrameQueueTransferringOptimizer() override = default;
|
||||
|
||||
UnderlyingSourceBase* PerformInProcessOptimization(
|
||||
@@ -41,6 +43,7 @@ class FrameQueueTransferringOptimizer final
|
||||
CrossThreadWeakPersistent<FrameQueueHost> host_;
|
||||
scoped_refptr<base::SequencedTaskRunner> host_runner_;
|
||||
ConnectHostCallback connect_host_callback_;
|
||||
+ CrossThreadOnceFunction<void()> transferred_source_destroyed_callback_;
|
||||
wtf_size_t max_queue_size_;
|
||||
};
|
||||
|
||||
diff --git a/third_party/blink/renderer/modules/breakout_box/frame_queue_underlying_source.cc b/third_party/blink/renderer/modules/breakout_box/frame_queue_underlying_source.cc
|
||||
index b93b67f131e1e58118e32d2c9b29e472a28d4664..fcd676b3035e19c6e0b28ee1c44109c6737a1c35 100644
|
||||
--- a/third_party/blink/renderer/modules/breakout_box/frame_queue_underlying_source.cc
|
||||
+++ b/third_party/blink/renderer/modules/breakout_box/frame_queue_underlying_source.cc
|
||||
@@ -266,15 +266,22 @@ double FrameQueueUnderlyingSource<NativeFrameType>::DesiredSizeForTesting()
|
||||
|
||||
template <typename NativeFrameType>
|
||||
void FrameQueueUnderlyingSource<NativeFrameType>::TransferSource(
|
||||
- FrameQueueUnderlyingSource<NativeFrameType>* transferred_source) {
|
||||
+ CrossThreadPersistent<FrameQueueUnderlyingSource<NativeFrameType>>
|
||||
+ transferred_source) {
|
||||
DCHECK(realm_task_runner_->RunsTasksInCurrentSequence());
|
||||
MutexLocker locker(mutex_);
|
||||
DCHECK(!transferred_source_);
|
||||
- transferred_source_ = transferred_source;
|
||||
+ transferred_source_ = std::move(transferred_source);
|
||||
CloseController();
|
||||
frame_queue_handle_.Invalidate();
|
||||
}
|
||||
|
||||
+template <typename NativeFrameType>
|
||||
+void FrameQueueUnderlyingSource<NativeFrameType>::ClearTransferredSource() {
|
||||
+ MutexLocker locker(mutex_);
|
||||
+ transferred_source_.Clear();
|
||||
+}
|
||||
+
|
||||
template <typename NativeFrameType>
|
||||
void FrameQueueUnderlyingSource<NativeFrameType>::CloseController() {
|
||||
DCHECK(realm_task_runner_->RunsTasksInCurrentSequence());
|
||||
diff --git a/third_party/blink/renderer/modules/breakout_box/frame_queue_underlying_source.h b/third_party/blink/renderer/modules/breakout_box/frame_queue_underlying_source.h
|
||||
index a5d529a4231a8951e95adb6804ea45d82ccb4673..f7457b15002b244490b286f596e6e227d940ca52 100644
|
||||
--- a/third_party/blink/renderer/modules/breakout_box/frame_queue_underlying_source.h
|
||||
+++ b/third_party/blink/renderer/modules/breakout_box/frame_queue_underlying_source.h
|
||||
@@ -84,7 +84,13 @@ class FrameQueueUnderlyingSource
|
||||
// QueueFrame(). |transferred_source| will pull frames from the same circular
|
||||
// queue. Must be called on |realm_task_runner_|.
|
||||
void TransferSource(
|
||||
- FrameQueueUnderlyingSource<NativeFrameType>* transferred_source);
|
||||
+ CrossThreadPersistent<FrameQueueUnderlyingSource<NativeFrameType>>
|
||||
+ transferred_source);
|
||||
+
|
||||
+ // Due to a potential race condition between |transferred_source_|'s heap
|
||||
+ // being destroyed and the Close() method being called, we need to explicitly
|
||||
+ // clear |transferred_source_| when its context is being destroyed.
|
||||
+ void ClearTransferredSource();
|
||||
|
||||
protected:
|
||||
bool MustUseMonitor() const;
|
||||
diff --git a/third_party/blink/renderer/modules/breakout_box/media_stream_audio_track_underlying_source.cc b/third_party/blink/renderer/modules/breakout_box/media_stream_audio_track_underlying_source.cc
|
||||
index bfc966452e4134e5133d559698497ce82f89aad4..da9a4bffc3a8c9ec5a1595a7cd78110bfadbfb5e 100644
|
||||
--- a/third_party/blink/renderer/modules/breakout_box/media_stream_audio_track_underlying_source.cc
|
||||
+++ b/third_party/blink/renderer/modules/breakout_box/media_stream_audio_track_underlying_source.cc
|
||||
@@ -93,14 +93,17 @@ MediaStreamAudioTrackUnderlyingSource::GetTransferringOptimizer() {
|
||||
this, GetRealmRunner(), MaxQueueSize(),
|
||||
CrossThreadBindOnce(
|
||||
&MediaStreamAudioTrackUnderlyingSource::OnSourceTransferStarted,
|
||||
+ WrapCrossThreadWeakPersistent(this)),
|
||||
+ CrossThreadBindOnce(
|
||||
+ &MediaStreamAudioTrackUnderlyingSource::ClearTransferredSource,
|
||||
WrapCrossThreadWeakPersistent(this)));
|
||||
}
|
||||
|
||||
void MediaStreamAudioTrackUnderlyingSource::OnSourceTransferStarted(
|
||||
scoped_refptr<base::SequencedTaskRunner> transferred_runner,
|
||||
- TransferredAudioDataQueueUnderlyingSource* source) {
|
||||
+ CrossThreadPersistent<TransferredAudioDataQueueUnderlyingSource> source) {
|
||||
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
|
||||
- TransferSource(source);
|
||||
+ TransferSource(std::move(source));
|
||||
RecordBreakoutBoxUsage(BreakoutBoxUsage::kReadableAudioWorker);
|
||||
}
|
||||
|
||||
diff --git a/third_party/blink/renderer/modules/breakout_box/media_stream_audio_track_underlying_source.h b/third_party/blink/renderer/modules/breakout_box/media_stream_audio_track_underlying_source.h
|
||||
index 19a290ea6b83e4b56b8d96cb7632fca55bd65fd0..73c16dc5ff3855e258e1e70397def478485f1481 100644
|
||||
--- a/third_party/blink/renderer/modules/breakout_box/media_stream_audio_track_underlying_source.h
|
||||
+++ b/third_party/blink/renderer/modules/breakout_box/media_stream_audio_track_underlying_source.h
|
||||
@@ -56,7 +56,7 @@ class MODULES_EXPORT MediaStreamAudioTrackUnderlyingSource
|
||||
void DisconnectFromTrack();
|
||||
void OnSourceTransferStarted(
|
||||
scoped_refptr<base::SequencedTaskRunner> transferred_runner,
|
||||
- TransferredAudioDataQueueUnderlyingSource* source);
|
||||
+ CrossThreadPersistent<TransferredAudioDataQueueUnderlyingSource> source);
|
||||
|
||||
// Only used to prevent the gargabe collector from reclaiming the media
|
||||
// stream track processor that created |this|.
|
||||
diff --git a/third_party/blink/renderer/modules/breakout_box/media_stream_video_track_underlying_source.cc b/third_party/blink/renderer/modules/breakout_box/media_stream_video_track_underlying_source.cc
|
||||
index bcb941aca4e4d0729dc1253e01ef477fdaae1877..e748bf6eaf8f9d1acf8519c38a5a8cb53b031d0e 100644
|
||||
--- a/third_party/blink/renderer/modules/breakout_box/media_stream_video_track_underlying_source.cc
|
||||
+++ b/third_party/blink/renderer/modules/breakout_box/media_stream_video_track_underlying_source.cc
|
||||
@@ -66,6 +66,9 @@ MediaStreamVideoTrackUnderlyingSource::GetStreamTransferOptimizer() {
|
||||
this, GetRealmRunner(), MaxQueueSize(),
|
||||
CrossThreadBindOnce(
|
||||
&MediaStreamVideoTrackUnderlyingSource::OnSourceTransferStarted,
|
||||
+ WrapCrossThreadWeakPersistent(this)),
|
||||
+ CrossThreadBindOnce(
|
||||
+ &MediaStreamVideoTrackUnderlyingSource::ClearTransferredSource,
|
||||
WrapCrossThreadWeakPersistent(this)));
|
||||
}
|
||||
|
||||
@@ -76,9 +79,9 @@ MediaStreamVideoTrackUnderlyingSource::GetIOTaskRunner() {
|
||||
|
||||
void MediaStreamVideoTrackUnderlyingSource::OnSourceTransferStarted(
|
||||
scoped_refptr<base::SequencedTaskRunner> transferred_runner,
|
||||
- TransferredVideoFrameQueueUnderlyingSource* source) {
|
||||
+ CrossThreadPersistent<TransferredVideoFrameQueueUnderlyingSource> source) {
|
||||
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
|
||||
- TransferSource(source);
|
||||
+ TransferSource(std::move(source));
|
||||
RecordBreakoutBoxUsage(BreakoutBoxUsage::kReadableVideoWorker);
|
||||
}
|
||||
|
||||
diff --git a/third_party/blink/renderer/modules/breakout_box/media_stream_video_track_underlying_source.h b/third_party/blink/renderer/modules/breakout_box/media_stream_video_track_underlying_source.h
|
||||
index 1bbd4f6bbf20eaf168bf1319f1b35819dabe3cce..8964eb5eb83964c4bb2633092a12cb144da4e9b0 100644
|
||||
--- a/third_party/blink/renderer/modules/breakout_box/media_stream_video_track_underlying_source.h
|
||||
+++ b/third_party/blink/renderer/modules/breakout_box/media_stream_video_track_underlying_source.h
|
||||
@@ -59,8 +59,9 @@ class MODULES_EXPORT MediaStreamVideoTrackUnderlyingSource
|
||||
bool StartFrameDelivery() override;
|
||||
void StopFrameDelivery() override;
|
||||
|
||||
- void OnSourceTransferStarted(scoped_refptr<base::SequencedTaskRunner>,
|
||||
- TransferredVideoFrameQueueUnderlyingSource*);
|
||||
+ void OnSourceTransferStarted(
|
||||
+ scoped_refptr<base::SequencedTaskRunner>,
|
||||
+ CrossThreadPersistent<TransferredVideoFrameQueueUnderlyingSource>);
|
||||
|
||||
void OnFrameFromTrack(
|
||||
scoped_refptr<media::VideoFrame> media_frame,
|
||||
diff --git a/third_party/blink/renderer/modules/breakout_box/transferred_frame_queue_underlying_source.cc b/third_party/blink/renderer/modules/breakout_box/transferred_frame_queue_underlying_source.cc
|
||||
index 5c62b8f1b752c24f8b8d0048d646ea64dba0e49c..e38173482d455788861a1d831dd3422119d4d4d6 100644
|
||||
--- a/third_party/blink/renderer/modules/breakout_box/transferred_frame_queue_underlying_source.cc
|
||||
+++ b/third_party/blink/renderer/modules/breakout_box/transferred_frame_queue_underlying_source.cc
|
||||
@@ -15,11 +15,14 @@ template <typename NativeFrameType>
|
||||
TransferredFrameQueueUnderlyingSource<NativeFrameType>::
|
||||
TransferredFrameQueueUnderlyingSource(
|
||||
ScriptState* script_state,
|
||||
- FrameQueueHost* host,
|
||||
- scoped_refptr<base::SequencedTaskRunner> host_runner)
|
||||
+ CrossThreadPersistent<FrameQueueHost> host,
|
||||
+ scoped_refptr<base::SequencedTaskRunner> host_runner,
|
||||
+ CrossThreadOnceClosure transferred_source_destroyed_callback)
|
||||
: FrameQueueUnderlyingSource<NativeFrameType>(script_state, host),
|
||||
host_runner_(host_runner),
|
||||
- host_(host) {}
|
||||
+ host_(std::move(host)),
|
||||
+ transferred_source_destroyed_callback_(
|
||||
+ std::move(transferred_source_destroyed_callback)) {}
|
||||
|
||||
template <typename NativeFrameType>
|
||||
bool TransferredFrameQueueUnderlyingSource<
|
||||
@@ -44,6 +47,13 @@ void TransferredFrameQueueUnderlyingSource<
|
||||
CrossThreadBindOnce(&FrameQueueHost::Close, host_));
|
||||
}
|
||||
|
||||
+template <typename NativeFrameType>
|
||||
+void TransferredFrameQueueUnderlyingSource<
|
||||
+ NativeFrameType>::ContextDestroyed() {
|
||||
+ std::move(transferred_source_destroyed_callback_).Run();
|
||||
+ FrameQueueUnderlyingSource<NativeFrameType>::ContextDestroyed();
|
||||
+}
|
||||
+
|
||||
template <typename NativeFrameType>
|
||||
void TransferredFrameQueueUnderlyingSource<NativeFrameType>::Trace(
|
||||
Visitor* visitor) const {
|
||||
diff --git a/third_party/blink/renderer/modules/breakout_box/transferred_frame_queue_underlying_source.h b/third_party/blink/renderer/modules/breakout_box/transferred_frame_queue_underlying_source.h
|
||||
index 5f8a36719407a404756d672530c0b9fcff9d6924..7cd3270fbb3cf5b0e2c09b16000ea5c0e4247866 100644
|
||||
--- a/third_party/blink/renderer/modules/breakout_box/transferred_frame_queue_underlying_source.h
|
||||
+++ b/third_party/blink/renderer/modules/breakout_box/transferred_frame_queue_underlying_source.h
|
||||
@@ -19,8 +19,9 @@ class TransferredFrameQueueUnderlyingSource
|
||||
|
||||
TransferredFrameQueueUnderlyingSource(
|
||||
ScriptState*,
|
||||
- FrameQueueHost*,
|
||||
- scoped_refptr<base::SequencedTaskRunner> host_runner);
|
||||
+ CrossThreadPersistent<FrameQueueHost>,
|
||||
+ scoped_refptr<base::SequencedTaskRunner> host_runner,
|
||||
+ CrossThreadOnceClosure transferred_source_destroyed_callback);
|
||||
~TransferredFrameQueueUnderlyingSource() override = default;
|
||||
|
||||
TransferredFrameQueueUnderlyingSource(
|
||||
@@ -32,11 +33,15 @@ class TransferredFrameQueueUnderlyingSource
|
||||
bool StartFrameDelivery() override;
|
||||
void StopFrameDelivery() override;
|
||||
|
||||
+ // ExecutionLifecycleObserver
|
||||
+ void ContextDestroyed() override;
|
||||
+
|
||||
void Trace(Visitor*) const override;
|
||||
|
||||
private:
|
||||
scoped_refptr<base::SequencedTaskRunner> host_runner_;
|
||||
CrossThreadPersistent<FrameQueueHost> host_;
|
||||
+ CrossThreadOnceClosure transferred_source_destroyed_callback_;
|
||||
};
|
||||
|
||||
extern template class MODULES_EXTERN_TEMPLATE_EXPORT
|
||||
@@ -0,0 +1,125 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Hassan Talat <hatalat@microsoft.com>
|
||||
Date: Mon, 13 Jun 2022 21:27:53 +0000
|
||||
Subject: dpwa: Enable Window Controls Overlay by default
|
||||
|
||||
This reverts commit d61c4042374672712176e43e33f39a1e66da4faa.
|
||||
I2S: https://groups.google.com/a/chromium.org/g/blink-dev/c/guI1QCPJTAA
|
||||
|
||||
Bug: 937121
|
||||
Change-Id: I3dfebec2356c7a12fd7eab32f12ef8d9e4bf6ee6
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3430266
|
||||
Commit-Queue: Alex Russell <slightlyoff@chromium.org>
|
||||
Reviewed-by: Alex Russell <slightlyoff@chromium.org>
|
||||
Reviewed-by: Avi Drissman <avi@chromium.org>
|
||||
Cr-Commit-Position: refs/heads/main@{#1013665}
|
||||
|
||||
diff --git a/content/public/common/content_features.cc b/content/public/common/content_features.cc
|
||||
index aa4a054fad59f57af17251a3ede7cd6c9806b4cb..ea32976ab88bdae7417b2e0ce25d6778369085ae 100644
|
||||
--- a/content/public/common/content_features.cc
|
||||
+++ b/content/public/common/content_features.cc
|
||||
@@ -1045,7 +1045,7 @@ const base::Feature kV8VmFuture{"V8VmFuture",
|
||||
|
||||
// Enable window controls overlays for desktop PWAs
|
||||
const base::Feature kWebAppWindowControlsOverlay{
|
||||
- "WebAppWindowControlsOverlay", base::FEATURE_DISABLED_BY_DEFAULT};
|
||||
+ "WebAppWindowControlsOverlay", base::FEATURE_ENABLED_BY_DEFAULT};
|
||||
|
||||
// Enable WebAssembly baseline compilation (Liftoff).
|
||||
const base::Feature kWebAssemblyBaseline{"WebAssemblyBaseline",
|
||||
diff --git a/third_party/blink/renderer/platform/runtime_enabled_features.json5 b/third_party/blink/renderer/platform/runtime_enabled_features.json5
|
||||
index 47cfcc8c758bed2fe46c6c75ba45b3cec2576ba6..ebf862fcc88579db6300b6972187f4b06f2af9e3 100644
|
||||
--- a/third_party/blink/renderer/platform/runtime_enabled_features.json5
|
||||
+++ b/third_party/blink/renderer/platform/runtime_enabled_features.json5
|
||||
@@ -2543,7 +2543,7 @@
|
||||
name: "WebAppWindowControlsOverlay",
|
||||
origin_trial_feature_name: "WebAppWindowControlsOverlay",
|
||||
origin_trial_os: ["win", "mac", "linux", "chromeos"],
|
||||
- status: "experimental",
|
||||
+ status: "stable",
|
||||
},
|
||||
{
|
||||
name: "WebAssemblyCSP",
|
||||
diff --git a/third_party/blink/web_tests/virtual/stable/fast/dom/Window/property-access-on-cached-properties-after-frame-navigated-expected.txt b/third_party/blink/web_tests/virtual/stable/fast/dom/Window/property-access-on-cached-properties-after-frame-navigated-expected.txt
|
||||
index a2bac6e1f0fc6404a8fabbab87cd78da3e50570c..d6e4d3d5846ec3de2056af5a89a74f168a0e216d 100644
|
||||
--- a/third_party/blink/web_tests/virtual/stable/fast/dom/Window/property-access-on-cached-properties-after-frame-navigated-expected.txt
|
||||
+++ b/third_party/blink/web_tests/virtual/stable/fast/dom/Window/property-access-on-cached-properties-after-frame-navigated-expected.txt
|
||||
@@ -77,6 +77,8 @@ PASS window.cached_navigator_virtualKeyboard.boundingRect.x is 0
|
||||
PASS window.cached_navigator_virtualKeyboard.boundingRect.y is 0
|
||||
PASS window.cached_navigator_virtualKeyboard.ongeometrychange is null
|
||||
PASS window.cached_navigator_virtualKeyboard.overlaysContent is false
|
||||
+PASS window.cached_navigator_windowControlsOverlay.ongeometrychange is null
|
||||
+PASS window.cached_navigator_windowControlsOverlay.visible is false
|
||||
PASS window.cached_navigator_xr.ondevicechange is null
|
||||
PASS window.cached_performance.onresourcetimingbufferfull is null
|
||||
PASS window.cached_performance_navigation.redirectCount is 0
|
||||
diff --git a/third_party/blink/web_tests/virtual/stable/fast/dom/Window/property-access-on-cached-properties-after-frame-removed-and-gced-expected.txt b/third_party/blink/web_tests/virtual/stable/fast/dom/Window/property-access-on-cached-properties-after-frame-removed-and-gced-expected.txt
|
||||
index 9b413dea03d864d6cef496279187b39cf81ba4b0..5cfdedb36e5f9bd0dbfae11d5ba5cc1172823071 100644
|
||||
--- a/third_party/blink/web_tests/virtual/stable/fast/dom/Window/property-access-on-cached-properties-after-frame-removed-and-gced-expected.txt
|
||||
+++ b/third_party/blink/web_tests/virtual/stable/fast/dom/Window/property-access-on-cached-properties-after-frame-removed-and-gced-expected.txt
|
||||
@@ -77,6 +77,8 @@ PASS window.cached_navigator_virtualKeyboard.boundingRect.x is 0
|
||||
PASS window.cached_navigator_virtualKeyboard.boundingRect.y is 0
|
||||
PASS window.cached_navigator_virtualKeyboard.ongeometrychange is null
|
||||
PASS window.cached_navigator_virtualKeyboard.overlaysContent is false
|
||||
+PASS window.cached_navigator_windowControlsOverlay.ongeometrychange is null
|
||||
+PASS window.cached_navigator_windowControlsOverlay.visible is false
|
||||
PASS window.cached_navigator_xr.ondevicechange is null
|
||||
PASS window.cached_performance.onresourcetimingbufferfull is null
|
||||
PASS window.cached_performance_navigation.redirectCount is 0
|
||||
diff --git a/third_party/blink/web_tests/virtual/stable/fast/dom/Window/property-access-on-cached-properties-after-frame-removed-expected.txt b/third_party/blink/web_tests/virtual/stable/fast/dom/Window/property-access-on-cached-properties-after-frame-removed-expected.txt
|
||||
index 6f480ccfc7031fbdab98b50511a667aed5840af1..37bba469a00c719128762f861313e383d1ad4b86 100644
|
||||
--- a/third_party/blink/web_tests/virtual/stable/fast/dom/Window/property-access-on-cached-properties-after-frame-removed-expected.txt
|
||||
+++ b/third_party/blink/web_tests/virtual/stable/fast/dom/Window/property-access-on-cached-properties-after-frame-removed-expected.txt
|
||||
@@ -77,6 +77,8 @@ PASS window.cached_navigator_virtualKeyboard.boundingRect.x is 0
|
||||
PASS window.cached_navigator_virtualKeyboard.boundingRect.y is 0
|
||||
PASS window.cached_navigator_virtualKeyboard.ongeometrychange is null
|
||||
PASS window.cached_navigator_virtualKeyboard.overlaysContent is false
|
||||
+PASS window.cached_navigator_windowControlsOverlay.ongeometrychange is null
|
||||
+PASS window.cached_navigator_windowControlsOverlay.visible is false
|
||||
PASS window.cached_navigator_xr.ondevicechange is null
|
||||
PASS window.cached_performance.onresourcetimingbufferfull is null
|
||||
PASS window.cached_performance_navigation.redirectCount is 0
|
||||
diff --git a/third_party/blink/web_tests/virtual/stable/fast/dom/Window/property-access-on-cached-window-after-frame-navigated-expected.txt b/third_party/blink/web_tests/virtual/stable/fast/dom/Window/property-access-on-cached-window-after-frame-navigated-expected.txt
|
||||
index ef72385e2cc50ae9519f2d0cf496e8cc771cf5aa..36efa30d35e4b8e5e7752bfde58f50cdef865e89 100644
|
||||
--- a/third_party/blink/web_tests/virtual/stable/fast/dom/Window/property-access-on-cached-window-after-frame-navigated-expected.txt
|
||||
+++ b/third_party/blink/web_tests/virtual/stable/fast/dom/Window/property-access-on-cached-window-after-frame-navigated-expected.txt
|
||||
@@ -87,6 +87,8 @@ PASS oldChildWindow.navigator.virtualKeyboard.boundingRect.y is newChildWindow.n
|
||||
PASS oldChildWindow.navigator.virtualKeyboard.ongeometrychange is newChildWindow.navigator.virtualKeyboard.ongeometrychange
|
||||
PASS oldChildWindow.navigator.virtualKeyboard.overlaysContent is newChildWindow.navigator.virtualKeyboard.overlaysContent
|
||||
PASS oldChildWindow.navigator.webdriver is newChildWindow.navigator.webdriver
|
||||
+PASS oldChildWindow.navigator.windowControlsOverlay.ongeometrychange is newChildWindow.navigator.windowControlsOverlay.ongeometrychange
|
||||
+PASS oldChildWindow.navigator.windowControlsOverlay.visible is newChildWindow.navigator.windowControlsOverlay.visible
|
||||
PASS oldChildWindow.navigator.xr.ondevicechange is newChildWindow.navigator.xr.ondevicechange
|
||||
PASS oldChildWindow.onabort is newChildWindow.onabort
|
||||
PASS oldChildWindow.onafterprint is newChildWindow.onafterprint
|
||||
diff --git a/third_party/blink/web_tests/virtual/stable/webexposed/global-interface-listing-expected.txt b/third_party/blink/web_tests/virtual/stable/webexposed/global-interface-listing-expected.txt
|
||||
index 1f0f00e9879c0e5f24029617d146f760e6abb100..6789814dd76154ce4d2547d5e89616255585249f 100644
|
||||
--- a/third_party/blink/web_tests/virtual/stable/webexposed/global-interface-listing-expected.txt
|
||||
+++ b/third_party/blink/web_tests/virtual/stable/webexposed/global-interface-listing-expected.txt
|
||||
@@ -4955,6 +4955,7 @@ interface Navigator
|
||||
getter webdriver
|
||||
getter webkitPersistentStorage
|
||||
getter webkitTemporaryStorage
|
||||
+ getter windowControlsOverlay
|
||||
getter xr
|
||||
method clearAppBadge
|
||||
method constructor
|
||||
@@ -9646,6 +9647,18 @@ interface Window : EventTarget
|
||||
attribute PERSISTENT
|
||||
attribute TEMPORARY
|
||||
method constructor
|
||||
+interface WindowControlsOverlay : EventTarget
|
||||
+ attribute @@toStringTag
|
||||
+ getter ongeometrychange
|
||||
+ getter visible
|
||||
+ method constructor
|
||||
+ method getTitlebarAreaRect
|
||||
+ setter ongeometrychange
|
||||
+interface WindowControlsOverlayGeometryChangeEvent : Event
|
||||
+ attribute @@toStringTag
|
||||
+ getter titlebarAreaRect
|
||||
+ getter visible
|
||||
+ method constructor
|
||||
interface Worker : EventTarget
|
||||
attribute @@toStringTag
|
||||
getter onerror
|
||||
@@ -0,0 +1,50 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Adam Rice <ricea@chromium.org>
|
||||
Date: Thu, 2 Jun 2022 07:33:07 +0000
|
||||
Subject: Fix crash-on-close for Mac UDP sockets
|
||||
|
||||
guarded_close_np() on UDP sockets on Mac may fail with an EPROTOTYPE
|
||||
error. Avoid a crash for that error as well as the ENOTCONN error we are
|
||||
already checking for.
|
||||
|
||||
BUG=1151048
|
||||
|
||||
Change-Id: I11ed84b879fbeda6bd6aee8614e54d8ed791f4ef
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3682001
|
||||
Commit-Queue: Adam Rice <ricea@chromium.org>
|
||||
Reviewed-by: Kenichi Ishibashi <bashi@chromium.org>
|
||||
Cr-Commit-Position: refs/heads/main@{#1009976}
|
||||
|
||||
diff --git a/net/socket/udp_socket_posix.cc b/net/socket/udp_socket_posix.cc
|
||||
index 63ae4274d11f53b0e2edf25ebcceb580813455d9..43e1ab15e2f1b66fb7946db6c0cbdae86a6a85a0 100644
|
||||
--- a/net/socket/udp_socket_posix.cc
|
||||
+++ b/net/socket/udp_socket_posix.cc
|
||||
@@ -320,19 +320,20 @@ void UDPSocketPosix::Close() {
|
||||
: perfetto::StaticString{"CloseSocketUDP"});
|
||||
|
||||
// Attempt to clear errors on the socket so that they are not returned by
|
||||
- // close(). See https://crbug.com/1151048.
|
||||
+ // close(). This seems to be effective at clearing some, but not all,
|
||||
+ // EPROTOTYPE errors. See https://crbug.com/1151048.
|
||||
int value = 0;
|
||||
socklen_t value_len = sizeof(value);
|
||||
HANDLE_EINTR(getsockopt(socket_, SOL_SOCKET, SO_ERROR, &value, &value_len));
|
||||
|
||||
if (IGNORE_EINTR(guarded_close_np(socket_, &kSocketFdGuard)) != 0) {
|
||||
- // There is a bug in the Mac OS kernel that it can return an
|
||||
- // ENOTCONN error. In this case we don't know whether the file
|
||||
- // descriptor is still allocated or not. We cannot safely close the
|
||||
- // file descriptor because it may have been reused by another
|
||||
- // thread in the meantime. We may leak file handles here and cause
|
||||
- // a crash indirectly later. See https://crbug.com/1151048.
|
||||
- PCHECK(errno == ENOTCONN);
|
||||
+ // There is a bug in the Mac OS kernel that it can return an ENOTCONN or
|
||||
+ // EPROTOTYPE error. In this case we don't know whether the file descriptor
|
||||
+ // is still allocated or not. We cannot safely close the file descriptor
|
||||
+ // because it may have been reused by another thread in the meantime. We may
|
||||
+ // leak file handles here and cause a crash indirectly later. See
|
||||
+ // https://crbug.com/1151048.
|
||||
+ PCHECK(errno == ENOTCONN || errno == EPROTOTYPE);
|
||||
}
|
||||
#else
|
||||
PCHECK(IGNORE_EINTR(close(socket_)) == 0);
|
||||
@@ -0,0 +1,115 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: =?UTF-8?q?Jacobo=20Aragunde=20P=C3=A9rez?= <jaragunde@igalia.com>
|
||||
Date: Fri, 20 May 2022 10:22:05 +0000
|
||||
Subject: Refresh cached attributes before name computation traversal.
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
|
||||
It was possible to trigger a children clear operation while running
|
||||
TextFromDescendants to compute a node name from its children. This
|
||||
is the sequence:
|
||||
|
||||
* A node changes its aria-hidden value.
|
||||
* We run TextFromDescendants on that node, it queries the hidden value
|
||||
for each child.
|
||||
* To know the hidden value, it refreshes cached attributes in
|
||||
UpdateCachedAttributeValuesIfNeeded
|
||||
* To refresh the cached aria-hidden value, it needs to check the
|
||||
parent's aria-hidden
|
||||
* The parent also refreshes cached attributes in
|
||||
UpdateCachedAttributeValuesIfNeeded
|
||||
* It detects aria-hidden value has changed, that triggers
|
||||
SetNeedsToUpdateChildren, which runs ClearChildren
|
||||
|
||||
To prevent children being cleared while we traverse them, which can
|
||||
cause an invalid pointer being addressed, we run a refresh of cached
|
||||
values before the traversal, knowing that operation may trigger a
|
||||
children clear (and we will need to use those cached values anyway).
|
||||
|
||||
We also add a regression test, based on a clusterfuzz-generated one,
|
||||
which is known to trigger this situation.
|
||||
|
||||
Bug: 1315044
|
||||
Change-Id: I0a7ca27cca5d93fbdbc07d31cab6a21b1401d8dc
|
||||
AX-relnotes: prevent crash in name computation.
|
||||
Cq-Include-Trybots: luci.chromium.try:linux-blink-web-tests-force-accessibility-rel
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3633568
|
||||
Commit-Queue: Jacobo Aragunde Pérez <jaragunde@igalia.com>
|
||||
Reviewed-by: Aaron Leventhal <aleventhal@chromium.org>
|
||||
Cr-Commit-Position: refs/heads/main@{#1005708}
|
||||
|
||||
diff --git a/content/browser/accessibility/dump_accessibility_tree_browsertest.cc b/content/browser/accessibility/dump_accessibility_tree_browsertest.cc
|
||||
index ee4bc3c0766c2d1b6f279e5a9cf12303af098f0a..44304f626679bb7b4fc5f631170462bf0d79a120 100644
|
||||
--- a/content/browser/accessibility/dump_accessibility_tree_browsertest.cc
|
||||
+++ b/content/browser/accessibility/dump_accessibility_tree_browsertest.cc
|
||||
@@ -3277,6 +3277,12 @@ IN_PROC_BROWSER_TEST_P(DumpAccessibilityTreeTest, AriaHiddenTabindexChange) {
|
||||
RunRegressionTest(FILE_PATH_LITERAL("aria-hidden-tabindex-change.html"));
|
||||
}
|
||||
|
||||
+IN_PROC_BROWSER_TEST_P(DumpAccessibilityTreeTest,
|
||||
+ ClearChildrenWhileComputingName) {
|
||||
+ RunRegressionTest(
|
||||
+ FILE_PATH_LITERAL("clear-children-while-computing-name.html"));
|
||||
+}
|
||||
+
|
||||
IN_PROC_BROWSER_TEST_P(DumpAccessibilityTreeTest, HiddenTable) {
|
||||
RunRegressionTest(FILE_PATH_LITERAL("hidden-table.html"));
|
||||
}
|
||||
diff --git a/content/test/data/accessibility/regression/clear-children-while-computing-name-expected-blink.txt b/content/test/data/accessibility/regression/clear-children-while-computing-name-expected-blink.txt
|
||||
new file mode 100644
|
||||
index 0000000000000000000000000000000000000000..59e71c6983acae4e4cb519e423f3aa2db030c88a
|
||||
--- /dev/null
|
||||
+++ b/content/test/data/accessibility/regression/clear-children-while-computing-name-expected-blink.txt
|
||||
@@ -0,0 +1,7 @@
|
||||
+rootWebArea name='done'
|
||||
+++genericContainer ignored
|
||||
+++++genericContainer ignored
|
||||
+++++++genericContainer ignored invisible
|
||||
+++++++++heading ignored invisible
|
||||
+++++++++++staticText ignored invisible name='Browser'
|
||||
+++++++++genericContainer ignored invisible
|
||||
diff --git a/content/test/data/accessibility/regression/clear-children-while-computing-name.html b/content/test/data/accessibility/regression/clear-children-while-computing-name.html
|
||||
new file mode 100644
|
||||
index 0000000000000000000000000000000000000000..415e25e70604ac74a73618075e0b97fca3b08bac
|
||||
--- /dev/null
|
||||
+++ b/content/test/data/accessibility/regression/clear-children-while-computing-name.html
|
||||
@@ -0,0 +1,23 @@
|
||||
+<!--
|
||||
+@WAIT-FOR:done
|
||||
+-->
|
||||
+<head>
|
||||
+<style>
|
||||
+.c4 {}
|
||||
+</style>
|
||||
+</head>
|
||||
+<body>
|
||||
+<div id="container">
|
||||
+ <h3 id="heading">Browser</h3>
|
||||
+ <a id="anchor"></a>
|
||||
+</div>
|
||||
+<script>
|
||||
+ function crash() {
|
||||
+ document.getElementById('container').setAttribute('aria-hidden', 'true');
|
||||
+ document.getElementById('heading').setAttribute('aria-hidden', 'false');
|
||||
+ document.getElementById('anchor').setAttribute('class', 'c4');
|
||||
+ heading['computedName']; // access to the property triggers name computation
|
||||
+ document.title = 'done';
|
||||
+ }
|
||||
+ setTimeout(crash, 100);
|
||||
+</script>
|
||||
diff --git a/third_party/blink/renderer/modules/accessibility/ax_node_object.cc b/third_party/blink/renderer/modules/accessibility/ax_node_object.cc
|
||||
index 0beba99f522a9932390306e46988832ddbc258b0..ddfeeb3f32a8a0448ecae3ee54ba8b3c3e0f68c5 100644
|
||||
--- a/third_party/blink/renderer/modules/accessibility/ax_node_object.cc
|
||||
+++ b/third_party/blink/renderer/modules/accessibility/ax_node_object.cc
|
||||
@@ -3444,6 +3444,10 @@ String AXNodeObject::TextFromDescendants(
|
||||
ax::mojom::blink::NameFrom last_used_name_from =
|
||||
ax::mojom::blink::NameFrom::kUninitialized;
|
||||
|
||||
+ // Ensure that if this node needs to invalidate its children (e.g. due to
|
||||
+ // included in tree status change), that we do it now, rather than while
|
||||
+ // traversing the children.
|
||||
+ UpdateCachedAttributeValuesIfNeeded();
|
||||
#if defined(AX_FAIL_FAST_BUILD)
|
||||
base::AutoReset<bool> auto_reset(&is_computing_text_from_descendants_, true);
|
||||
#endif
|
||||
@@ -0,0 +1,89 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: =?UTF-8?q?Jacobo=20Aragunde=20P=C3=A9rez?= <jaragunde@igalia.com>
|
||||
Date: Fri, 27 May 2022 14:42:10 +0000
|
||||
Subject: Review add/clear children checks during accname traversal.
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
|
||||
We want to make sure there are no new children added to a node while
|
||||
we traverse them for accname computation. There is a check for
|
||||
(!is_adding_children_) in TextFromDescendants(), but it's not really
|
||||
serving that purpose: the AddChildren() operation will start and end,
|
||||
resetting is_adding_children_, before execution flows back to
|
||||
TextFromDescendants().
|
||||
|
||||
We reverse the condition, checking for the flag
|
||||
is_computing_text_from_descendants_ in AddChildren(), which should
|
||||
detect the situation explained above.
|
||||
|
||||
We replace the DCHECK for a check, because we want these to be caught
|
||||
not only in debug builds.
|
||||
|
||||
Bug: none.
|
||||
Change-Id: I88039838bd5b50257871c223633c4eb69d5c3878
|
||||
Cq-Include-Trybots: luci.chromium.try:linux-blink-web-tests-force-accessibility-rel
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3657488
|
||||
Commit-Queue: Jacobo Aragunde Pérez <jaragunde@igalia.com>
|
||||
Reviewed-by: Aaron Leventhal <aleventhal@chromium.org>
|
||||
Cr-Commit-Position: refs/heads/main@{#1008248}
|
||||
|
||||
diff --git a/third_party/blink/renderer/modules/accessibility/ax_node_object.cc b/third_party/blink/renderer/modules/accessibility/ax_node_object.cc
|
||||
index ddfeeb3f32a8a0448ecae3ee54ba8b3c3e0f68c5..7476ecdd4904e6b62e16da7aef2a9e15b8a84967 100644
|
||||
--- a/third_party/blink/renderer/modules/accessibility/ax_node_object.cc
|
||||
+++ b/third_party/blink/renderer/modules/accessibility/ax_node_object.cc
|
||||
@@ -3433,9 +3433,6 @@ String AXNodeObject::TextFromDescendants(
|
||||
AXObjectSet& visited,
|
||||
const AXObject* aria_label_or_description_root,
|
||||
bool recursive) const {
|
||||
-#if defined(AX_FAIL_FAST_BUILD)
|
||||
- DCHECK(!is_adding_children_);
|
||||
-#endif
|
||||
if (!CanHaveChildren())
|
||||
return recursive ? String() : GetElement()->GetInnerTextWithoutUpdate();
|
||||
|
||||
@@ -3448,11 +3445,12 @@ String AXNodeObject::TextFromDescendants(
|
||||
// included in tree status change), that we do it now, rather than while
|
||||
// traversing the children.
|
||||
UpdateCachedAttributeValuesIfNeeded();
|
||||
+
|
||||
+ const AXObjectVector& children = ChildrenIncludingIgnored();
|
||||
#if defined(AX_FAIL_FAST_BUILD)
|
||||
base::AutoReset<bool> auto_reset(&is_computing_text_from_descendants_, true);
|
||||
#endif
|
||||
-
|
||||
- for (AXObject* child : ChildrenIncludingIgnored()) {
|
||||
+ for (AXObject* child : children) {
|
||||
constexpr size_t kMaxDescendantsForTextAlternativeComputation = 100;
|
||||
if (visited.size() > kMaxDescendantsForTextAlternativeComputation)
|
||||
break;
|
||||
@@ -4123,6 +4121,10 @@ void AXNodeObject::AddChildren() {
|
||||
#endif
|
||||
|
||||
#if defined(AX_FAIL_FAST_BUILD)
|
||||
+ SANITIZER_CHECK(!is_computing_text_from_descendants_)
|
||||
+ << "Should not attempt to simultaneously compute text from descendants "
|
||||
+ "and add children on: "
|
||||
+ << ToString(true, true);
|
||||
SANITIZER_CHECK(!is_adding_children_)
|
||||
<< " Reentering method on " << GetNode();
|
||||
base::AutoReset<bool> reentrancy_protector(&is_adding_children_, true);
|
||||
diff --git a/third_party/blink/renderer/modules/accessibility/ax_object.cc b/third_party/blink/renderer/modules/accessibility/ax_object.cc
|
||||
index 06fd95c7c457c20cde3a53bbafcac23dba8fb21c..de987935346051c4f9e1cfdd7c9290376c4c0e2a 100644
|
||||
--- a/third_party/blink/renderer/modules/accessibility/ax_object.cc
|
||||
+++ b/third_party/blink/renderer/modules/accessibility/ax_object.cc
|
||||
@@ -4923,11 +4923,12 @@ void AXObject::ClearChildren() const {
|
||||
// AccessibilityExposeIgnoredNodes().
|
||||
|
||||
// Loop through AXObject children.
|
||||
+
|
||||
#if defined(AX_FAIL_FAST_BUILD)
|
||||
- CHECK(!is_adding_children_)
|
||||
+ SANITIZER_CHECK(!is_adding_children_)
|
||||
<< "Should not attempt to simultaneously add and clear children on: "
|
||||
<< ToString(true, true);
|
||||
- CHECK(!is_computing_text_from_descendants_)
|
||||
+ SANITIZER_CHECK(!is_computing_text_from_descendants_)
|
||||
<< "Should not attempt to simultaneously compute text from descendants "
|
||||
"and clear children on: "
|
||||
<< ToString(true, true);
|
||||
@@ -23,5 +23,13 @@
|
||||
|
||||
"src/electron/patches/angle": "src/third_party/angle",
|
||||
|
||||
"src/electron/patches/sqlite": "src/third_party/sqlite/src"
|
||||
"src/electron/patches/sqlite": "src/third_party/sqlite/src",
|
||||
|
||||
"src/electron/patches/pdfium": "src/third_party/pdfium",
|
||||
|
||||
"src/electron/patches/ffmpeg": "src/third_party/ffmpeg",
|
||||
|
||||
"src/electron/patches/libaom": "src/third_party/libaom/source/libaom",
|
||||
|
||||
"src/electron/patches/skia": "src/third_party/skia"
|
||||
}
|
||||
|
||||
1
patches/ffmpeg/.patches
Normal file
1
patches/ffmpeg/.patches
Normal file
@@ -0,0 +1 @@
|
||||
cherry-pick-c2c8cac2131b.patch
|
||||
57
patches/ffmpeg/cherry-pick-c2c8cac2131b.patch
Normal file
57
patches/ffmpeg/cherry-pick-c2c8cac2131b.patch
Normal file
@@ -0,0 +1,57 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Michael Niedermayer <michael@niedermayer.cc>
|
||||
Date: Thu, 28 Jul 2022 14:42:43 +0200
|
||||
Subject: avformat/mov: Check count sums in build_open_gop_key_points()
|
||||
|
||||
Fixes: ffmpeg.md
|
||||
Fixes: Out of array access
|
||||
Fixes: CVE-2022-2566
|
||||
|
||||
Bug: 1348283
|
||||
Found-by: Andy Nguyen <theflow@google.com>
|
||||
Found-by: 3pvd <3pvd@google.com>
|
||||
Change-Id: I6821c87acce5a62cd9a5b829c17f56ae6418116a
|
||||
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
|
||||
(cherry picked from commit 64d7d8d0e5035087ebe24a65845b36f78e7fad92)
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/third_party/ffmpeg/+/3890391
|
||||
Reviewed-by: Matthew Wolenetz <wolenetz@chromium.org>
|
||||
|
||||
diff --git a/libavformat/mov.c b/libavformat/mov.c
|
||||
index 124c8e907f2e0cb5777b5433ccdb17ac52f0b6eb..595babcd4bfb1298d2928b1f4c9b40b2d09971e9 100644
|
||||
--- a/libavformat/mov.c
|
||||
+++ b/libavformat/mov.c
|
||||
@@ -3943,8 +3943,11 @@ static int build_open_gop_key_points(AVStream *st)
|
||||
|
||||
/* Build an unrolled index of the samples */
|
||||
sc->sample_offsets_count = 0;
|
||||
- for (uint32_t i = 0; i < sc->ctts_count; i++)
|
||||
+ for (uint32_t i = 0; i < sc->ctts_count; i++) {
|
||||
+ if (sc->ctts_data[i].count > INT_MAX - sc->sample_offsets_count)
|
||||
+ return AVERROR(ENOMEM);
|
||||
sc->sample_offsets_count += sc->ctts_data[i].count;
|
||||
+ }
|
||||
av_freep(&sc->sample_offsets);
|
||||
sc->sample_offsets = av_calloc(sc->sample_offsets_count, sizeof(*sc->sample_offsets));
|
||||
if (!sc->sample_offsets)
|
||||
@@ -3963,8 +3966,11 @@ static int build_open_gop_key_points(AVStream *st)
|
||||
/* Build a list of open-GOP key samples */
|
||||
sc->open_key_samples_count = 0;
|
||||
for (uint32_t i = 0; i < sc->sync_group_count; i++)
|
||||
- if (sc->sync_group[i].index == cra_index)
|
||||
+ if (sc->sync_group[i].index == cra_index) {
|
||||
+ if (sc->sync_group[i].count > INT_MAX - sc->open_key_samples_count)
|
||||
+ return AVERROR(ENOMEM);
|
||||
sc->open_key_samples_count += sc->sync_group[i].count;
|
||||
+ }
|
||||
av_freep(&sc->open_key_samples);
|
||||
sc->open_key_samples = av_calloc(sc->open_key_samples_count, sizeof(*sc->open_key_samples));
|
||||
if (!sc->open_key_samples)
|
||||
@@ -3975,6 +3981,8 @@ static int build_open_gop_key_points(AVStream *st)
|
||||
if (sg->index == cra_index)
|
||||
for (uint32_t j = 0; j < sg->count; j++)
|
||||
sc->open_key_samples[k++] = sample_id;
|
||||
+ if (sg->count > INT_MAX - sample_id)
|
||||
+ return AVERROR_PATCHWELCOME;
|
||||
sample_id += sg->count;
|
||||
}
|
||||
|
||||
1
patches/libaom/.patches
Normal file
1
patches/libaom/.patches
Normal file
@@ -0,0 +1 @@
|
||||
use_non_normative_scaler_for_non_optimized_ratio.patch
|
||||
@@ -0,0 +1,96 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Jerome Jiang <jianj@google.com>
|
||||
Date: Tue, 30 Aug 2022 14:45:28 -0400
|
||||
Subject: Use non normative scaler for non optimized ratio
|
||||
|
||||
There are only optimized scalers for 1/4, 1/2 and 3/4 scaling ratio.
|
||||
SSSE3 also has 2x upscaling optimization.
|
||||
Use non normative scalers for all other scaling ratios.
|
||||
|
||||
Bug: chromium:1346938
|
||||
Bug: chromium:1338114
|
||||
Change-Id: I2a01717b56c53c42906440d5a3f95ca2c00dc571
|
||||
(cherry picked from commit ff7b753a63a536423a91b64a066bd385c52ceacc)
|
||||
|
||||
diff --git a/av1/common/resize.c b/av1/common/resize.c
|
||||
index a3c3c0e5160940974fbbbc84d7011fb4bd26f67e..322363fa1e136ce3b77498b9c20b63d27d339471 100644
|
||||
--- a/av1/common/resize.c
|
||||
+++ b/av1/common/resize.c
|
||||
@@ -1366,15 +1366,20 @@ YV12_BUFFER_CONFIG *av1_realloc_and_scale_if_required(
|
||||
aom_internal_error(cm->error, AOM_CODEC_MEM_ERROR,
|
||||
"Failed to allocate scaled buffer");
|
||||
|
||||
+ const bool has_optimized_scaler = av1_has_optimized_scaler(
|
||||
+ unscaled->y_crop_width, unscaled->y_crop_height, scaled_width,
|
||||
+ scaled_height);
|
||||
+
|
||||
#if CONFIG_AV1_HIGHBITDEPTH
|
||||
- if (use_optimized_scaler && cm->seq_params->bit_depth == AOM_BITS_8) {
|
||||
+ if (use_optimized_scaler && has_optimized_scaler &&
|
||||
+ cm->seq_params->bit_depth == AOM_BITS_8) {
|
||||
av1_resize_and_extend_frame(unscaled, scaled, filter, phase, num_planes);
|
||||
} else {
|
||||
av1_resize_and_extend_frame_nonnormative(
|
||||
unscaled, scaled, (int)cm->seq_params->bit_depth, num_planes);
|
||||
}
|
||||
#else
|
||||
- if (use_optimized_scaler) {
|
||||
+ if (use_optimized_scaler && has_optimized_scaler) {
|
||||
av1_resize_and_extend_frame(unscaled, scaled, filter, phase, num_planes);
|
||||
} else {
|
||||
av1_resize_and_extend_frame_nonnormative(
|
||||
diff --git a/av1/common/resize.h b/av1/common/resize.h
|
||||
index 75abe6274ee73a202bddd14962f1a4ae8083ce94..9bc23b3ffacd4121bf32dd96bae82ba5c799b1ea 100644
|
||||
--- a/av1/common/resize.h
|
||||
+++ b/av1/common/resize.h
|
||||
@@ -105,6 +105,24 @@ static INLINE int av1_superres_scaled(const AV1_COMMON *cm) {
|
||||
return !(cm->width == cm->superres_upscaled_width);
|
||||
}
|
||||
|
||||
+// There's SIMD optimizations for 1/4, 1/2 and 3/4 downscaling.
|
||||
+// SSSE3 also has optimizations for 2x upscaling.
|
||||
+// Use non normative scalers for other scaling ratios.
|
||||
+static INLINE bool av1_has_optimized_scaler(const int src_width,
|
||||
+ const int src_height,
|
||||
+ const int dst_width,
|
||||
+ const int dst_height) {
|
||||
+ const bool has_optimized_scaler =
|
||||
+ (dst_width * 4 == src_width && dst_height * 4 == src_height) ||
|
||||
+ (dst_width * 2 == src_width && dst_height * 2 == src_height) ||
|
||||
+ (dst_width * 4 == src_width * 3 && dst_height * 4 == src_height * 3);
|
||||
+#if HAVE_SSSE3
|
||||
+ return has_optimized_scaler ||
|
||||
+ (dst_width == src_width * 2 && dst_height == src_height * 2);
|
||||
+#endif
|
||||
+ return has_optimized_scaler;
|
||||
+}
|
||||
+
|
||||
#define UPSCALE_NORMATIVE_TAPS 8
|
||||
extern const int16_t av1_resize_filter_normative[1 << RS_SUBPEL_BITS]
|
||||
[UPSCALE_NORMATIVE_TAPS];
|
||||
diff --git a/av1/encoder/encoder_utils.c b/av1/encoder/encoder_utils.c
|
||||
index fd8be7bf18e6a138bf20c25370c635cf3b302e10..cebea60eee37777b175f75d863f8cb94410a065a 100644
|
||||
--- a/av1/encoder/encoder_utils.c
|
||||
+++ b/av1/encoder/encoder_utils.c
|
||||
@@ -733,15 +733,19 @@ void av1_scale_references(AV1_COMP *cpi, const InterpFilter filter,
|
||||
aom_internal_error(cm->error, AOM_CODEC_MEM_ERROR,
|
||||
"Failed to allocate frame buffer");
|
||||
}
|
||||
+ const bool has_optimized_scaler = av1_has_optimized_scaler(
|
||||
+ cm->width, cm->height, new_fb->buf.y_crop_width,
|
||||
+ new_fb->buf.y_crop_height);
|
||||
#if CONFIG_AV1_HIGHBITDEPTH
|
||||
- if (use_optimized_scaler && cm->seq_params->bit_depth == AOM_BITS_8)
|
||||
+ if (use_optimized_scaler && has_optimized_scaler &&
|
||||
+ cm->seq_params->bit_depth == AOM_BITS_8)
|
||||
av1_resize_and_extend_frame(ref, &new_fb->buf, filter, phase,
|
||||
num_planes);
|
||||
else
|
||||
av1_resize_and_extend_frame_nonnormative(
|
||||
ref, &new_fb->buf, (int)cm->seq_params->bit_depth, num_planes);
|
||||
#else
|
||||
- if (use_optimized_scaler)
|
||||
+ if (use_optimized_scaler && has_optimized_scaler)
|
||||
av1_resize_and_extend_frame(ref, &new_fb->buf, filter, phase,
|
||||
num_planes);
|
||||
else
|
||||
@@ -44,3 +44,4 @@ process_fix_hang_after_note_exit_3521.patch
|
||||
feat_add_uv_loop_interrupt_on_io_change_option_to_uv_loop_configure.patch
|
||||
fix_preserve_proper_method_names_as-is_in_error_stack.patch
|
||||
macos_avoid_posix_spawnp_cwd_bug_3597.patch
|
||||
buffer_fix_atob_input_validation.patch
|
||||
|
||||
89
patches/node/buffer_fix_atob_input_validation.patch
Normal file
89
patches/node/buffer_fix_atob_input_validation.patch
Normal file
@@ -0,0 +1,89 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Shelley Vohr <shelley.vohr@gmail.com>
|
||||
Date: Tue, 23 Aug 2022 11:13:45 +0200
|
||||
Subject: buffer: fix `atob` input validation
|
||||
|
||||
This patch combines:
|
||||
|
||||
* https://github.com/nodejs/node/pull/42539
|
||||
* https://github.com/nodejs/node/pull/42662
|
||||
|
||||
To bring the Node.js implementation of atob into alignment with the
|
||||
WHATWG spec.
|
||||
|
||||
diff --git a/lib/buffer.js b/lib/buffer.js
|
||||
index 2d0057544395bc4aabff891fb30bfb9932a441f7..565753f76663611f0c069321b938c465b46f4ec8 100644
|
||||
--- a/lib/buffer.js
|
||||
+++ b/lib/buffer.js
|
||||
@@ -23,8 +23,10 @@
|
||||
|
||||
const {
|
||||
Array,
|
||||
+ ArrayFrom,
|
||||
ArrayIsArray,
|
||||
ArrayPrototypeForEach,
|
||||
+ ArrayPrototypeIndexOf,
|
||||
Error,
|
||||
MathFloor,
|
||||
MathMin,
|
||||
@@ -1227,8 +1229,25 @@ function btoa(input) {
|
||||
return buf.toString('base64');
|
||||
}
|
||||
|
||||
-const kBase64Digits =
|
||||
- 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=';
|
||||
+// Refs: https://infra.spec.whatwg.org/#forgiving-base64-decode
|
||||
+const kForgivingBase64AllowedChars = [
|
||||
+ // ASCII whitespace
|
||||
+ // Refs: https://infra.spec.whatwg.org/#ascii-whitespace
|
||||
+ 0x09, 0x0A, 0x0C, 0x0D, 0x20,
|
||||
+
|
||||
+ // Uppercase letters
|
||||
+ ...ArrayFrom({ length: 26 }, (_, i) => StringPrototypeCharCodeAt('A') + i),
|
||||
+
|
||||
+ // Lowercase letters
|
||||
+ ...ArrayFrom({ length: 26 }, (_, i) => StringPrototypeCharCodeAt('a') + i),
|
||||
+
|
||||
+ // Decimal digits
|
||||
+ ...ArrayFrom({ length: 10 }, (_, i) => StringPrototypeCharCodeAt('0') + i),
|
||||
+
|
||||
+ 0x2B, // +
|
||||
+ 0x2F, // /
|
||||
+ 0x3D, // =
|
||||
+];
|
||||
|
||||
function atob(input) {
|
||||
// The implementation here has not been performance optimized in any way and
|
||||
@@ -1237,11 +1256,31 @@ function atob(input) {
|
||||
if (arguments.length === 0) {
|
||||
throw new ERR_MISSING_ARGS('input');
|
||||
}
|
||||
+
|
||||
input = `${input}`;
|
||||
+ let nonAsciiWhitespaceCharCount = 0;
|
||||
+
|
||||
for (let n = 0; n < input.length; n++) {
|
||||
- if (!kBase64Digits.includes(input[n]))
|
||||
+ const index = ArrayPrototypeIndexOf(
|
||||
+ kForgivingBase64AllowedChars,
|
||||
+ StringPrototypeCharCodeAt(input, n));
|
||||
+
|
||||
+ if (index > 4) {
|
||||
+ // The first 5 elements of `kForgivingBase64AllowedChars` are
|
||||
+ // ASCII whitespace char codes.
|
||||
+ nonAsciiWhitespaceCharCount++;
|
||||
+ } else if (index === -1) {
|
||||
throw lazyDOMException('Invalid character', 'InvalidCharacterError');
|
||||
+ }
|
||||
}
|
||||
+
|
||||
+ // See #3 - https://infra.spec.whatwg.org/#forgiving-base64
|
||||
+ if (nonAsciiWhitespaceCharCount % 4 === 1) {
|
||||
+ throw lazyDOMException(
|
||||
+ 'The string to be decoded is not correctly encoded.',
|
||||
+ 'InvalidCharacterError');
|
||||
+ }
|
||||
+
|
||||
return Buffer.from(input, 'base64').toString('latin1');
|
||||
}
|
||||
|
||||
@@ -6,7 +6,7 @@ Subject: fix: crash caused by GetHostNameW on Windows 7
|
||||
Backported from https://github.com/libuv/libuv/pull/3285.
|
||||
|
||||
diff --git a/deps/uv/src/win/util.c b/deps/uv/src/win/util.c
|
||||
index 33e874ac442f88b58d2b68c8ec9764f6f664552e..2d4cc0aaa02e61bf359e80eca27527efb49fd85e 100644
|
||||
index 33e874ac442f88b58d2b68c8ec9764f6f664552e..37ece5e2867ab836492a8b7faa0aa5e1b8e562f0 100644
|
||||
--- a/deps/uv/src/win/util.c
|
||||
+++ b/deps/uv/src/win/util.c
|
||||
@@ -37,6 +37,7 @@
|
||||
@@ -166,3 +166,17 @@ index 33e874ac442f88b58d2b68c8ec9764f6f664552e..2d4cc0aaa02e61bf359e80eca27527ef
|
||||
int uv_os_gethostname(char* buffer, size_t* size) {
|
||||
WCHAR buf[UV_MAXHOSTNAMESIZE];
|
||||
size_t len;
|
||||
@@ -1674,10 +1803,10 @@ int uv_os_gethostname(char* buffer, size_t* size) {
|
||||
|
||||
uv__once_init(); /* Initialize winsock */
|
||||
|
||||
- if (pGetHostNameW == NULL)
|
||||
- return UV_ENOSYS;
|
||||
+ uv_sGetHostNameW gethostnamew =
|
||||
+ pGetHostNameW == NULL ? uv__gethostnamew_nt60 : pGetHostNameW;
|
||||
|
||||
- if (pGetHostNameW(buf, UV_MAXHOSTNAMESIZE) != 0)
|
||||
+ if (gethostnamew(buf, UV_MAXHOSTNAMESIZE) != 0)
|
||||
return uv_translate_sys_error(WSAGetLastError());
|
||||
|
||||
convert_result = uv__convert_utf16_to_utf8(buf, -1, &utf8_str);
|
||||
|
||||
@@ -6,7 +6,7 @@ Subject: fix: suppress clang -Wdeprecated-declarations in libuv
|
||||
Should be upstreamed.
|
||||
|
||||
diff --git a/deps/uv/src/win/util.c b/deps/uv/src/win/util.c
|
||||
index 2d4cc0aaa02e61bf359e80eca27527efb49fd85e..aaa16052e2a9c7d1dca82763c41c0890371f1471 100644
|
||||
index 37ece5e2867ab836492a8b7faa0aa5e1b8e562f0..d50296728f7e0810064647125a469f3ed714f8ea 100644
|
||||
--- a/deps/uv/src/win/util.c
|
||||
+++ b/deps/uv/src/win/util.c
|
||||
@@ -1950,10 +1950,17 @@ int uv_os_uname(uv_utsname_t* buffer) {
|
||||
|
||||
3
patches/pdfium/.patches
Normal file
3
patches/pdfium/.patches
Normal file
@@ -0,0 +1,3 @@
|
||||
cherry-pick-a66438897056.patch
|
||||
cherry-pick-497f077a1d46.patch
|
||||
cherry-pick-7f0bb5197ed1.patch
|
||||
374
patches/pdfium/cherry-pick-497f077a1d46.patch
Normal file
374
patches/pdfium/cherry-pick-497f077a1d46.patch
Normal file
@@ -0,0 +1,374 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Tom Sepez <tsepez@chromium.org>
|
||||
Date: Thu, 8 Sep 2022 23:05:34 +0000
|
||||
Subject: Return retained const objects from SearchNameNodeByNameInternal()
|
||||
|
||||
Cherry-pick of d51720c9bb55d1163ab4fdcdc6981e753aa2354d + manual
|
||||
conflict resolution.
|
||||
|
||||
Bug: chromium:1358075
|
||||
Change-Id: Ibb20a6feaf79f7b351f22c607c306da40026d53e
|
||||
Reviewed-on: https://pdfium-review.googlesource.com/c/pdfium/+/97739
|
||||
Auto-Submit: Tom Sepez <tsepez@chromium.org>
|
||||
Reviewed-by: Lei Zhang <thestig@chromium.org>
|
||||
Commit-Queue: Lei Zhang <thestig@chromium.org>
|
||||
Commit-Queue: Tom Sepez <tsepez@chromium.org>
|
||||
|
||||
diff --git a/core/fpdfapi/parser/cpdf_array.h b/core/fpdfapi/parser/cpdf_array.h
|
||||
index 223cd59ab7cb6cc2c08071118d1fbb3241904c6b..a2c067878847cc8ed17eb78bee416716f08a338b 100644
|
||||
--- a/core/fpdfapi/parser/cpdf_array.h
|
||||
+++ b/core/fpdfapi/parser/cpdf_array.h
|
||||
@@ -194,4 +194,8 @@ inline RetainPtr<CPDF_Array> ToArray(RetainPtr<CPDF_Object> obj) {
|
||||
return RetainPtr<CPDF_Array>(ToArray(obj.Get()));
|
||||
}
|
||||
|
||||
+inline RetainPtr<const CPDF_Array> ToArray(RetainPtr<const CPDF_Object> obj) {
|
||||
+ return RetainPtr<const CPDF_Array>(ToArray(obj.Get()));
|
||||
+}
|
||||
+
|
||||
#endif // CORE_FPDFAPI_PARSER_CPDF_ARRAY_H_
|
||||
diff --git a/core/fpdfapi/parser/cpdf_dictionary.h b/core/fpdfapi/parser/cpdf_dictionary.h
|
||||
index c7ccdc6eef50ddb93585975fb613ce442199e0ee..658ed6586959b5c2165589c9633060f86825c535 100644
|
||||
--- a/core/fpdfapi/parser/cpdf_dictionary.h
|
||||
+++ b/core/fpdfapi/parser/cpdf_dictionary.h
|
||||
@@ -170,4 +170,9 @@ inline RetainPtr<CPDF_Dictionary> ToDictionary(RetainPtr<CPDF_Object> obj) {
|
||||
return RetainPtr<CPDF_Dictionary>(ToDictionary(obj.Get()));
|
||||
}
|
||||
|
||||
+inline RetainPtr<const CPDF_Dictionary> ToDictionary(
|
||||
+ RetainPtr<const CPDF_Object> obj) {
|
||||
+ return RetainPtr<const CPDF_Dictionary>(ToDictionary(obj.Get()));
|
||||
+}
|
||||
+
|
||||
#endif // CORE_FPDFAPI_PARSER_CPDF_DICTIONARY_H_
|
||||
diff --git a/core/fpdfapi/parser/cpdf_number.h b/core/fpdfapi/parser/cpdf_number.h
|
||||
index 864bbb2186f0c6208db9942121d2f80b214d46a1..0ca1130ec5a0f595054ff3e4d3d73c5e57f94e6c 100644
|
||||
--- a/core/fpdfapi/parser/cpdf_number.h
|
||||
+++ b/core/fpdfapi/parser/cpdf_number.h
|
||||
@@ -49,4 +49,12 @@ inline const CPDF_Number* ToNumber(const CPDF_Object* obj) {
|
||||
return obj ? obj->AsNumber() : nullptr;
|
||||
}
|
||||
|
||||
+inline RetainPtr<CPDF_Number> ToNumber(RetainPtr<CPDF_Object> obj) {
|
||||
+ return RetainPtr<CPDF_Number>(ToNumber(obj.Get()));
|
||||
+}
|
||||
+
|
||||
+inline RetainPtr<const CPDF_Number> ToNumber(RetainPtr<const CPDF_Object> obj) {
|
||||
+ return RetainPtr<const CPDF_Number>(ToNumber(obj.Get()));
|
||||
+}
|
||||
+
|
||||
#endif // CORE_FPDFAPI_PARSER_CPDF_NUMBER_H_
|
||||
diff --git a/core/fpdfapi/parser/cpdf_stream.h b/core/fpdfapi/parser/cpdf_stream.h
|
||||
index 497db20cfcf98792bef6cb3b4bef1a4c0b1b1bff..171d93eb28e26baf1e51f4fafd4c83e39798f88b 100644
|
||||
--- a/core/fpdfapi/parser/cpdf_stream.h
|
||||
+++ b/core/fpdfapi/parser/cpdf_stream.h
|
||||
@@ -92,4 +92,8 @@ inline RetainPtr<CPDF_Stream> ToStream(RetainPtr<CPDF_Object> obj) {
|
||||
return RetainPtr<CPDF_Stream>(ToStream(obj.Get()));
|
||||
}
|
||||
|
||||
+inline RetainPtr<const CPDF_Stream> ToStream(RetainPtr<const CPDF_Object> obj) {
|
||||
+ return RetainPtr<const CPDF_Stream>(ToStream(obj.Get()));
|
||||
+}
|
||||
+
|
||||
#endif // CORE_FPDFAPI_PARSER_CPDF_STREAM_H_
|
||||
diff --git a/core/fpdfdoc/cpdf_dest.cpp b/core/fpdfdoc/cpdf_dest.cpp
|
||||
index f3b11523918258e7702bda360129857165abc945..fcc09d9e580832678980987489d58ac3c7c0b9bf 100644
|
||||
--- a/core/fpdfdoc/cpdf_dest.cpp
|
||||
+++ b/core/fpdfdoc/cpdf_dest.cpp
|
||||
@@ -41,9 +41,11 @@ CPDF_Dest CPDF_Dest::Create(CPDF_Document* pDoc, const CPDF_Object* pDest) {
|
||||
if (!pDest)
|
||||
return CPDF_Dest(nullptr);
|
||||
|
||||
- if (pDest->IsString() || pDest->IsName())
|
||||
- return CPDF_Dest(CPDF_NameTree::LookupNamedDest(pDoc, pDest->GetString()));
|
||||
-
|
||||
+ if (pDest->IsString() || pDest->IsName()) {
|
||||
+ // TODO(tsepez): make CPDF_Dest constructor take retained args.
|
||||
+ return CPDF_Dest(
|
||||
+ CPDF_NameTree::LookupNamedDest(pDoc, pDest->GetString()).Get());
|
||||
+ }
|
||||
return CPDF_Dest(pDest->AsArray());
|
||||
}
|
||||
|
||||
diff --git a/core/fpdfdoc/cpdf_nametree.cpp b/core/fpdfdoc/cpdf_nametree.cpp
|
||||
index 09d4a873fbd9e1151ddbe4f943903d796b18dbe1..2dfecbb5eeb95525c0a83023ee85b722588f3489 100644
|
||||
--- a/core/fpdfdoc/cpdf_nametree.cpp
|
||||
+++ b/core/fpdfdoc/cpdf_nametree.cpp
|
||||
@@ -170,7 +170,7 @@ bool UpdateNodesAndLimitsUponDeletion(CPDF_Dictionary* pNode,
|
||||
// will be the index of |csName| in |ppFind|. If |csName| is not found, |ppFind|
|
||||
// will be the leaf array that |csName| should be added to, and |pFindIndex|
|
||||
// will be the index that it should be added at.
|
||||
-CPDF_Object* SearchNameNodeByNameInternal(
|
||||
+RetainPtr<const CPDF_Object> SearchNameNodeByNameInternal(
|
||||
const RetainPtr<CPDF_Dictionary>& pNode,
|
||||
const WideString& csName,
|
||||
int nLevel,
|
||||
@@ -217,7 +217,7 @@ CPDF_Object* SearchNameNodeByNameInternal(
|
||||
continue;
|
||||
|
||||
*nIndex += i;
|
||||
- return pNames->GetDirectObjectAt(i * 2 + 1);
|
||||
+ return pdfium::WrapRetain(pNames->GetDirectObjectAt(i * 2 + 1));
|
||||
}
|
||||
*nIndex += dwCount;
|
||||
return nullptr;
|
||||
@@ -233,7 +233,7 @@ CPDF_Object* SearchNameNodeByNameInternal(
|
||||
if (!pKid)
|
||||
continue;
|
||||
|
||||
- CPDF_Object* pFound = SearchNameNodeByNameInternal(
|
||||
+ RetainPtr<const CPDF_Object> pFound = SearchNameNodeByNameInternal(
|
||||
pKid, csName, nLevel + 1, nIndex, ppFind, pFindIndex);
|
||||
if (pFound)
|
||||
return pFound;
|
||||
@@ -243,10 +243,11 @@ CPDF_Object* SearchNameNodeByNameInternal(
|
||||
|
||||
// Wrapper for SearchNameNodeByNameInternal() so callers do not need to know
|
||||
// about the details.
|
||||
-CPDF_Object* SearchNameNodeByName(const RetainPtr<CPDF_Dictionary>& pNode,
|
||||
- const WideString& csName,
|
||||
- RetainPtr<CPDF_Array>* ppFind,
|
||||
- int* pFindIndex) {
|
||||
+RetainPtr<const CPDF_Object> SearchNameNodeByName(
|
||||
+ const RetainPtr<CPDF_Dictionary>& pNode,
|
||||
+ const WideString& csName,
|
||||
+ RetainPtr<CPDF_Array>* ppFind,
|
||||
+ int* pFindIndex) {
|
||||
size_t nIndex = 0;
|
||||
return SearchNameNodeByNameInternal(pNode, csName, 0, &nIndex, ppFind,
|
||||
pFindIndex);
|
||||
@@ -344,24 +345,25 @@ size_t CountNamesInternal(CPDF_Dictionary* pNode, int nLevel) {
|
||||
return nCount;
|
||||
}
|
||||
|
||||
-CPDF_Array* GetNamedDestFromObject(CPDF_Object* obj) {
|
||||
- if (!obj)
|
||||
- return nullptr;
|
||||
- CPDF_Array* array = obj->AsArray();
|
||||
+RetainPtr<const CPDF_Array> GetNamedDestFromObject(
|
||||
+ RetainPtr<const CPDF_Object> obj) {
|
||||
+ RetainPtr<const CPDF_Array> array = ToArray(obj);
|
||||
if (array)
|
||||
return array;
|
||||
- CPDF_Dictionary* dict = obj->AsDictionary();
|
||||
+ RetainPtr<const CPDF_Dictionary> dict = ToDictionary(obj);
|
||||
if (dict)
|
||||
- return dict->GetArrayFor("D");
|
||||
+ return pdfium::WrapRetain(dict->GetArrayFor("D"));
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
-CPDF_Array* LookupOldStyleNamedDest(CPDF_Document* pDoc,
|
||||
- const ByteString& name) {
|
||||
- CPDF_Dictionary* pDests = pDoc->GetRoot()->GetDictFor("Dests");
|
||||
+RetainPtr<const CPDF_Array> LookupOldStyleNamedDest(CPDF_Document* pDoc,
|
||||
+ const ByteString& name) {
|
||||
+ const CPDF_Dictionary* pDests = pDoc->GetRoot()->GetDictFor("Dests");
|
||||
if (!pDests)
|
||||
return nullptr;
|
||||
- return GetNamedDestFromObject(pDests->GetDirectObjectFor(name));
|
||||
+ // TODO(tsepez): return const retained objects from CPDF object getters.
|
||||
+ return GetNamedDestFromObject(
|
||||
+ pdfium::WrapRetain(pDests->GetDirectObjectFor(name)));
|
||||
}
|
||||
|
||||
} // namespace
|
||||
@@ -424,9 +426,10 @@ std::unique_ptr<CPDF_NameTree> CPDF_NameTree::CreateForTesting(
|
||||
}
|
||||
|
||||
// static
|
||||
-CPDF_Array* CPDF_NameTree::LookupNamedDest(CPDF_Document* pDoc,
|
||||
- const ByteString& name) {
|
||||
- CPDF_Array* dest_array = nullptr;
|
||||
+RetainPtr<const CPDF_Array> CPDF_NameTree::LookupNamedDest(
|
||||
+ CPDF_Document* pDoc,
|
||||
+ const ByteString& name) {
|
||||
+ RetainPtr<const CPDF_Array> dest_array;
|
||||
std::unique_ptr<CPDF_NameTree> name_tree = Create(pDoc, "Dests");
|
||||
if (name_tree)
|
||||
dest_array = name_tree->LookupNewStyleNamedDest(name);
|
||||
@@ -526,10 +529,12 @@ CPDF_Object* CPDF_NameTree::LookupValueAndName(size_t nIndex,
|
||||
return result.value().value;
|
||||
}
|
||||
|
||||
-CPDF_Object* CPDF_NameTree::LookupValue(const WideString& csName) const {
|
||||
+RetainPtr<const CPDF_Object> CPDF_NameTree::LookupValue(
|
||||
+ const WideString& csName) const {
|
||||
return SearchNameNodeByName(m_pRoot, csName, nullptr, nullptr);
|
||||
}
|
||||
|
||||
-CPDF_Array* CPDF_NameTree::LookupNewStyleNamedDest(const ByteString& sName) {
|
||||
+RetainPtr<const CPDF_Array> CPDF_NameTree::LookupNewStyleNamedDest(
|
||||
+ const ByteString& sName) {
|
||||
return GetNamedDestFromObject(LookupValue(PDF_DecodeText(sName.raw_span())));
|
||||
}
|
||||
diff --git a/core/fpdfdoc/cpdf_nametree.h b/core/fpdfdoc/cpdf_nametree.h
|
||||
index e27f5b13cd76052e1de533b94f85ae505aa56339..30371b42ac622b53b79e180789a491a917c3f263 100644
|
||||
--- a/core/fpdfdoc/cpdf_nametree.h
|
||||
+++ b/core/fpdfdoc/cpdf_nametree.h
|
||||
@@ -38,14 +38,14 @@ class CPDF_NameTree {
|
||||
static std::unique_ptr<CPDF_NameTree> CreateForTesting(
|
||||
CPDF_Dictionary* pRoot);
|
||||
|
||||
- static CPDF_Array* LookupNamedDest(CPDF_Document* doc,
|
||||
- const ByteString& name);
|
||||
+ static RetainPtr<const CPDF_Array> LookupNamedDest(CPDF_Document* doc,
|
||||
+ const ByteString& name);
|
||||
|
||||
bool AddValueAndName(RetainPtr<CPDF_Object> pObj, const WideString& name);
|
||||
bool DeleteValueAndName(size_t nIndex);
|
||||
|
||||
CPDF_Object* LookupValueAndName(size_t nIndex, WideString* csName) const;
|
||||
- CPDF_Object* LookupValue(const WideString& csName) const;
|
||||
+ RetainPtr<const CPDF_Object> LookupValue(const WideString& csName) const;
|
||||
|
||||
size_t GetCount() const;
|
||||
CPDF_Dictionary* GetRootForTesting() const { return m_pRoot.Get(); }
|
||||
@@ -53,7 +53,7 @@ class CPDF_NameTree {
|
||||
private:
|
||||
explicit CPDF_NameTree(CPDF_Dictionary* pRoot);
|
||||
|
||||
- CPDF_Array* LookupNewStyleNamedDest(const ByteString& name);
|
||||
+ RetainPtr<const CPDF_Array> LookupNewStyleNamedDest(const ByteString& name);
|
||||
|
||||
const RetainPtr<CPDF_Dictionary> m_pRoot;
|
||||
};
|
||||
diff --git a/core/fpdfdoc/cpdf_nametree_unittest.cpp b/core/fpdfdoc/cpdf_nametree_unittest.cpp
|
||||
index 36617e74d438985b17a889043f2e5ac73836bb3a..e144033bfd66448e45267788d66e577ab366b964 100644
|
||||
--- a/core/fpdfdoc/cpdf_nametree_unittest.cpp
|
||||
+++ b/core/fpdfdoc/cpdf_nametree_unittest.cpp
|
||||
@@ -120,7 +120,7 @@ TEST(cpdf_nametree, GetUnicodeNameWithBOM) {
|
||||
EXPECT_STREQ(L"1", stored_name.c_str());
|
||||
|
||||
// Check that the correct value object can be obtained by looking up "1".
|
||||
- const CPDF_Number* pNumber = ToNumber(name_tree->LookupValue(L"1"));
|
||||
+ RetainPtr<const CPDF_Number> pNumber = ToNumber(name_tree->LookupValue(L"1"));
|
||||
ASSERT_TRUE(pNumber);
|
||||
EXPECT_EQ(100, pNumber->GetInteger());
|
||||
}
|
||||
@@ -140,7 +140,8 @@ TEST(cpdf_nametree, GetFromTreeWithLimitsArrayWith4Items) {
|
||||
std::unique_ptr<CPDF_NameTree> name_tree =
|
||||
CPDF_NameTree::CreateForTesting(pRootDict.Get());
|
||||
|
||||
- const CPDF_Number* pNumber = ToNumber(name_tree->LookupValue(L"9.txt"));
|
||||
+ RetainPtr<const CPDF_Number> pNumber =
|
||||
+ ToNumber(name_tree->LookupValue(L"9.txt"));
|
||||
ASSERT_TRUE(pNumber);
|
||||
EXPECT_EQ(999, pNumber->GetInteger());
|
||||
CheckLimitsArray(pKid1, "1.txt", "9.txt");
|
||||
diff --git a/fpdfsdk/fpdf_view.cpp b/fpdfsdk/fpdf_view.cpp
|
||||
index 161340b8a1b406987b62934d9ad6a67ec49d4bb5..b89efdd063d6c81a38536686965f7bdf8f4da244 100644
|
||||
--- a/fpdfsdk/fpdf_view.cpp
|
||||
+++ b/fpdfsdk/fpdf_view.cpp
|
||||
@@ -1050,7 +1050,9 @@ FPDF_GetNamedDestByName(FPDF_DOCUMENT document, FPDF_BYTESTRING name) {
|
||||
return nullptr;
|
||||
|
||||
ByteString dest_name(name);
|
||||
- return FPDFDestFromCPDFArray(CPDF_NameTree::LookupNamedDest(pDoc, dest_name));
|
||||
+ // TODO(tsepez): murky ownership, should caller get a reference?
|
||||
+ return FPDFDestFromCPDFArray(
|
||||
+ CPDF_NameTree::LookupNamedDest(pDoc, dest_name).Get());
|
||||
}
|
||||
|
||||
#ifdef PDF_ENABLE_V8
|
||||
diff --git a/fxjs/cjs_document.cpp b/fxjs/cjs_document.cpp
|
||||
index a0bcf868157446cd664eab2717a1adff4e6155b5..991c3aa4a3a41cd58bf22b37626658750831691c 100644
|
||||
--- a/fxjs/cjs_document.cpp
|
||||
+++ b/fxjs/cjs_document.cpp
|
||||
@@ -1395,12 +1395,13 @@ CJS_Result CJS_Document::gotoNamedDest(
|
||||
return CJS_Result::Failure(JSMessage::kBadObjectError);
|
||||
|
||||
CPDF_Document* pDocument = m_pFormFillEnv->GetPDFDocument();
|
||||
- CPDF_Array* dest_array = CPDF_NameTree::LookupNamedDest(
|
||||
+ RetainPtr<const CPDF_Array> dest_array = CPDF_NameTree::LookupNamedDest(
|
||||
pDocument, pRuntime->ToByteString(params[0]));
|
||||
if (!dest_array)
|
||||
return CJS_Result::Failure(JSMessage::kBadObjectError);
|
||||
|
||||
- CPDF_Dest dest(dest_array);
|
||||
+ // TODO(tsepez): make CPDF_Dest constructor take retained argument.
|
||||
+ CPDF_Dest dest(dest_array.Get());
|
||||
const CPDF_Array* arrayObject = dest.GetArray();
|
||||
std::vector<float> scrollPositionArray;
|
||||
if (arrayObject) {
|
||||
diff --git a/testing/resources/javascript/bug_1358075.in b/testing/resources/javascript/bug_1358075.in
|
||||
new file mode 100644
|
||||
index 0000000000000000000000000000000000000000..b503bf2d81eb3ca9adaa108c5075c04fa1c69f89
|
||||
--- /dev/null
|
||||
+++ b/testing/resources/javascript/bug_1358075.in
|
||||
@@ -0,0 +1,39 @@
|
||||
+{{header}}
|
||||
+{{object 1 0}} <<
|
||||
+ /Pages 1 0 R
|
||||
+ /OpenAction 2 0 R
|
||||
+ /Names <<
|
||||
+ /Dests 3 0 R
|
||||
+ >>
|
||||
+>>
|
||||
+endobj
|
||||
+{{object 2 0}} <<
|
||||
+ /Type /Action
|
||||
+ /S /JavaScript
|
||||
+ /JS (
|
||||
+ this.gotoNamedDest\("2"\);
|
||||
+ app.alert\("completed"\);
|
||||
+ )
|
||||
+>>
|
||||
+endobj
|
||||
+{{object 3 0}} <<
|
||||
+ /Kids 4 0 R
|
||||
+>>
|
||||
+endobj
|
||||
+{{object 4 0}} [
|
||||
+ (1)
|
||||
+ (3)
|
||||
+ <<
|
||||
+ /Kids [
|
||||
+ <<
|
||||
+ /Limits 4 0 R
|
||||
+ /Names [(2) []]
|
||||
+ >>
|
||||
+ ]
|
||||
+ >>
|
||||
+]
|
||||
+endobj
|
||||
+{{xref}}
|
||||
+{{trailer}}
|
||||
+{{startxref}}
|
||||
+%%EOF
|
||||
diff --git a/testing/resources/javascript/bug_1358075_expected.txt b/testing/resources/javascript/bug_1358075_expected.txt
|
||||
new file mode 100644
|
||||
index 0000000000000000000000000000000000000000..13d460b3b9aa905cec757ab821b980f379772565
|
||||
--- /dev/null
|
||||
+++ b/testing/resources/javascript/bug_1358075_expected.txt
|
||||
@@ -0,0 +1 @@
|
||||
+Alert: completed
|
||||
diff --git a/xfa/fxfa/cxfa_ffdoc.cpp b/xfa/fxfa/cxfa_ffdoc.cpp
|
||||
index 691248d2709508fc4aff096c80c535a2863bc851..5693d231122ed953c863f4a2333c5ee782bcd68e 100644
|
||||
--- a/xfa/fxfa/cxfa_ffdoc.cpp
|
||||
+++ b/xfa/fxfa/cxfa_ffdoc.cpp
|
||||
@@ -279,7 +279,8 @@ RetainPtr<CFX_DIBitmap> CXFA_FFDoc::GetPDFNamedImage(WideStringView wsName,
|
||||
if (count == 0)
|
||||
return nullptr;
|
||||
|
||||
- CPDF_Object* pObject = name_tree->LookupValue(WideString(wsName));
|
||||
+ RetainPtr<const CPDF_Object> pObject =
|
||||
+ name_tree->LookupValue(WideString(wsName));
|
||||
if (!pObject) {
|
||||
for (size_t i = 0; i < count; ++i) {
|
||||
WideString wsTemp;
|
||||
@@ -291,11 +292,12 @@ RetainPtr<CFX_DIBitmap> CXFA_FFDoc::GetPDFNamedImage(WideStringView wsName,
|
||||
}
|
||||
}
|
||||
|
||||
- CPDF_Stream* pStream = ToStream(pObject);
|
||||
+ RetainPtr<const CPDF_Stream> pStream = ToStream(pObject);
|
||||
if (!pStream)
|
||||
return nullptr;
|
||||
|
||||
- auto pAcc = pdfium::MakeRetain<CPDF_StreamAcc>(pStream);
|
||||
+ // TODO(tsepez): make CPDF_StreamAcc constructor take retained argument.
|
||||
+ auto pAcc = pdfium::MakeRetain<CPDF_StreamAcc>(pStream.Get());
|
||||
pAcc->LoadAllDataFiltered();
|
||||
|
||||
auto pImageFileRead =
|
||||
30
patches/pdfium/cherry-pick-7f0bb5197ed1.patch
Normal file
30
patches/pdfium/cherry-pick-7f0bb5197ed1.patch
Normal file
@@ -0,0 +1,30 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Tom Sepez <tsepez@chromium.org>
|
||||
Date: Thu, 8 Sep 2022 23:45:54 +0000
|
||||
Subject: Avoid de-referencing end() in GetNextAvailContentHeight().
|
||||
|
||||
Add the same HasCurrentViewRecord() check as in other methods.
|
||||
|
||||
Bug: chromium:1355682
|
||||
Change-Id: I466f386f037801daa82ead30239f34e025748748
|
||||
Reviewed-on: https://pdfium-review.googlesource.com/c/pdfium/+/96910
|
||||
Reviewed-by: Lei Zhang <thestig@chromium.org>
|
||||
Auto-Submit: Tom Sepez <tsepez@chromium.org>
|
||||
Commit-Queue: Lei Zhang <thestig@chromium.org>
|
||||
(cherry picked from commit 0d76a139d7ffbbdfb0ef5f5e714597a25f9767c4)
|
||||
Reviewed-on: https://pdfium-review.googlesource.com/c/pdfium/+/97738
|
||||
Commit-Queue: Tom Sepez <tsepez@chromium.org>
|
||||
|
||||
diff --git a/xfa/fxfa/layout/cxfa_viewlayoutprocessor.cpp b/xfa/fxfa/layout/cxfa_viewlayoutprocessor.cpp
|
||||
index a8efdb7dfa740bd9f3e70aeadc3c8d4ccb12587f..295854f655807ce706cc76d4786ad3c57564736e 100644
|
||||
--- a/xfa/fxfa/layout/cxfa_viewlayoutprocessor.cpp
|
||||
+++ b/xfa/fxfa/layout/cxfa_viewlayoutprocessor.cpp
|
||||
@@ -1551,6 +1551,8 @@ void CXFA_ViewLayoutProcessor::ProcessLastPageSet() {
|
||||
}
|
||||
|
||||
bool CXFA_ViewLayoutProcessor::GetNextAvailContentHeight(float fChildHeight) {
|
||||
+ if (!HasCurrentViewRecord())
|
||||
+ return false;
|
||||
CXFA_Node* pCurContentNode =
|
||||
GetCurrentViewRecord()->pCurContentArea->GetFormNode();
|
||||
if (!pCurContentNode)
|
||||
127
patches/pdfium/cherry-pick-a66438897056.patch
Normal file
127
patches/pdfium/cherry-pick-a66438897056.patch
Normal file
@@ -0,0 +1,127 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Tom Sepez <tsepez@chromium.org>
|
||||
Date: Thu, 8 Sep 2022 21:45:44 +0000
|
||||
Subject: Enforce maximum legal object number during linearized parses.
|
||||
|
||||
- Watch for overflow of object numbers.
|
||||
- Re-validate CPDF_Object pointer after notification in CPDF_FormField.
|
||||
|
||||
Bug: chromium:1358090
|
||||
Change-Id: I1effd8f47277d177c804dd14b20b101e71780067
|
||||
Reviewed-on: https://pdfium-review.googlesource.com/c/pdfium/+/97130
|
||||
Reviewed-by: Lei Zhang <thestig@chromium.org>
|
||||
Commit-Queue: Tom Sepez <tsepez@chromium.org>
|
||||
(cherry picked from commit 81ab3354f79765438bad0e9d683adcfce96727fa)
|
||||
Reviewed-on: https://pdfium-review.googlesource.com/c/pdfium/+/97733
|
||||
Auto-Submit: Tom Sepez <tsepez@chromium.org>
|
||||
Commit-Queue: Lei Zhang <thestig@chromium.org>
|
||||
|
||||
diff --git a/core/fpdfapi/parser/cpdf_hint_tables.cpp b/core/fpdfapi/parser/cpdf_hint_tables.cpp
|
||||
index 3445e90c9f68bc2386272b4d72f72d90c10bf7ec..0f2632c6d4a5dd7e6cd18c7d2bdc370b68e5bcb9 100644
|
||||
--- a/core/fpdfapi/parser/cpdf_hint_tables.cpp
|
||||
+++ b/core/fpdfapi/parser/cpdf_hint_tables.cpp
|
||||
@@ -13,6 +13,7 @@
|
||||
#include "core/fpdfapi/parser/cpdf_dictionary.h"
|
||||
#include "core/fpdfapi/parser/cpdf_document.h"
|
||||
#include "core/fpdfapi/parser/cpdf_linearized_header.h"
|
||||
+#include "core/fpdfapi/parser/cpdf_parser.h"
|
||||
#include "core/fpdfapi/parser/cpdf_read_validator.h"
|
||||
#include "core/fpdfapi/parser/cpdf_stream.h"
|
||||
#include "core/fpdfapi/parser/cpdf_stream_acc.h"
|
||||
@@ -101,7 +102,7 @@ bool CPDF_HintTables::ReadPageHintTable(CFX_BitStream* hStream) {
|
||||
|
||||
// Item 1: The least number of objects in a page.
|
||||
const uint32_t dwObjLeastNum = hStream->GetBits(32);
|
||||
- if (!dwObjLeastNum)
|
||||
+ if (!dwObjLeastNum || dwObjLeastNum >= CPDF_Parser::kMaxObjectNumber)
|
||||
return false;
|
||||
|
||||
// Item 2: The location of the first page's page object.
|
||||
@@ -164,7 +165,7 @@ bool CPDF_HintTables::ReadPageHintTable(CFX_BitStream* hStream) {
|
||||
m_PageInfos[nFirstPageNum].set_start_obj_num(
|
||||
m_pLinearized->GetFirstPageObjNum());
|
||||
// The object number of remaining pages starts from 1.
|
||||
- uint32_t dwStartObjNum = 1;
|
||||
+ FX_SAFE_UINT32 dwStartObjNum = 1;
|
||||
for (uint32_t i = 0; i < nPages; ++i) {
|
||||
FX_SAFE_UINT32 safeDeltaObj = hStream->GetBits(dwDeltaObjectsBits);
|
||||
safeDeltaObj += dwObjLeastNum;
|
||||
@@ -173,8 +174,12 @@ bool CPDF_HintTables::ReadPageHintTable(CFX_BitStream* hStream) {
|
||||
m_PageInfos[i].set_objects_count(safeDeltaObj.ValueOrDie());
|
||||
if (i == nFirstPageNum)
|
||||
continue;
|
||||
- m_PageInfos[i].set_start_obj_num(dwStartObjNum);
|
||||
+ m_PageInfos[i].set_start_obj_num(dwStartObjNum.ValueOrDie());
|
||||
dwStartObjNum += m_PageInfos[i].objects_count();
|
||||
+ if (!dwStartObjNum.IsValid() ||
|
||||
+ dwStartObjNum.ValueOrDie() >= CPDF_Parser::kMaxObjectNumber) {
|
||||
+ return false;
|
||||
+ }
|
||||
}
|
||||
hStream->ByteAlign();
|
||||
|
||||
diff --git a/core/fpdfdoc/cpdf_formfield.cpp b/core/fpdfdoc/cpdf_formfield.cpp
|
||||
index e882098fa36058d5454475743a7e4f34186469b4..c27576e494568f66d82a7b77f81afc265ab2aea6 100644
|
||||
--- a/core/fpdfdoc/cpdf_formfield.cpp
|
||||
+++ b/core/fpdfdoc/cpdf_formfield.cpp
|
||||
@@ -178,14 +178,15 @@ bool CPDF_FormField::ResetField() {
|
||||
case kRichText:
|
||||
case kFile:
|
||||
default: {
|
||||
- const CPDF_Object* pDV = GetDefaultValueObject();
|
||||
WideString csDValue;
|
||||
- if (pDV)
|
||||
- csDValue = pDV->GetUnicodeText();
|
||||
-
|
||||
WideString csValue;
|
||||
{
|
||||
- // Limit the scope of |pV| because it may get invalidated below.
|
||||
+ // Limit scope of |pDV| and |pV| because they may get invalidated
|
||||
+ // during notification below.
|
||||
+ const CPDF_Object* pDV = GetDefaultValueObject();
|
||||
+ if (pDV)
|
||||
+ csDValue = pDV->GetUnicodeText();
|
||||
+
|
||||
const CPDF_Object* pV = GetValueObject();
|
||||
if (pV)
|
||||
csValue = pV->GetUnicodeText();
|
||||
@@ -195,21 +196,26 @@ bool CPDF_FormField::ResetField() {
|
||||
if (!bHasRV && (csDValue == csValue))
|
||||
return false;
|
||||
|
||||
- if (!NotifyBeforeValueChange(csDValue)) {
|
||||
+ if (!NotifyBeforeValueChange(csDValue))
|
||||
return false;
|
||||
- }
|
||||
- if (pDV) {
|
||||
- RetainPtr<CPDF_Object> pClone = pDV->Clone();
|
||||
- if (!pClone)
|
||||
- return false;
|
||||
-
|
||||
- m_pDict->SetFor(pdfium::form_fields::kV, std::move(pClone));
|
||||
- if (bHasRV) {
|
||||
- m_pDict->SetFor("RV", pDV->Clone());
|
||||
+
|
||||
+ {
|
||||
+ // Limit scope of |pDV| because it may get invalidated during
|
||||
+ // notification below.
|
||||
+ const CPDF_Object* pDV = GetDefaultValueObject();
|
||||
+ if (pDV) {
|
||||
+ RetainPtr<CPDF_Object> pClone = pDV->Clone();
|
||||
+ if (!pClone)
|
||||
+ return false;
|
||||
+
|
||||
+ m_pDict->SetFor(pdfium::form_fields::kV, std::move(pClone));
|
||||
+ if (bHasRV) {
|
||||
+ m_pDict->SetFor("RV", pDV->Clone());
|
||||
+ }
|
||||
+ } else {
|
||||
+ m_pDict->RemoveFor(pdfium::form_fields::kV);
|
||||
+ m_pDict->RemoveFor("RV");
|
||||
}
|
||||
- } else {
|
||||
- m_pDict->RemoveFor(pdfium::form_fields::kV);
|
||||
- m_pDict->RemoveFor("RV");
|
||||
}
|
||||
NotifyAfterValueChange();
|
||||
break;
|
||||
1
patches/skia/.patches
Normal file
1
patches/skia/.patches
Normal file
@@ -0,0 +1 @@
|
||||
cherry-pick-07a2ce61e31a.patch
|
||||
52
patches/skia/cherry-pick-07a2ce61e31a.patch
Normal file
52
patches/skia/cherry-pick-07a2ce61e31a.patch
Normal file
@@ -0,0 +1,52 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Greg Daniel <egdaniel@google.com>
|
||||
Date: Wed, 5 Oct 2022 15:28:56 -0400
|
||||
Subject: Fix GrDirectContext::fClinetMappedBuffer access in abandoned
|
||||
callbacks.
|
||||
|
||||
Bug: chromium:1364604
|
||||
Change-Id: I1ca44cab1c762e7f94ac94be94991ec94a7497be
|
||||
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/583963
|
||||
Commit-Queue: Greg Daniel <egdaniel@google.com>
|
||||
Reviewed-by: Brian Salomon <bsalomon@google.com>
|
||||
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/587879
|
||||
Auto-Submit: Greg Daniel <egdaniel@google.com>
|
||||
Commit-Queue: Brian Salomon <bsalomon@google.com>
|
||||
|
||||
diff --git a/src/gpu/ganesh/GrDirectContext.cpp b/src/gpu/ganesh/GrDirectContext.cpp
|
||||
index abec1a933ee2623aa18beb582966df30db8ec9fa..19f162083d506658394347046ada0de45908de81 100644
|
||||
--- a/src/gpu/ganesh/GrDirectContext.cpp
|
||||
+++ b/src/gpu/ganesh/GrDirectContext.cpp
|
||||
@@ -142,9 +142,6 @@ void GrDirectContext::abandonContext() {
|
||||
|
||||
fGpu->disconnect(GrGpu::DisconnectType::kAbandon);
|
||||
|
||||
- // Must be after GrResourceCache::abandonAll().
|
||||
- fMappedBufferManager.reset();
|
||||
-
|
||||
if (fSmallPathAtlasMgr) {
|
||||
fSmallPathAtlasMgr->reset();
|
||||
}
|
||||
diff --git a/src/gpu/ganesh/GrFinishCallbacks.cpp b/src/gpu/ganesh/GrFinishCallbacks.cpp
|
||||
index 5519d2ca639d31f86e33ff0f617246b785fbc779..172f07d4de4554663140fdc2ad30ceab9bf449aa 100644
|
||||
--- a/src/gpu/ganesh/GrFinishCallbacks.cpp
|
||||
+++ b/src/gpu/ganesh/GrFinishCallbacks.cpp
|
||||
@@ -35,10 +35,16 @@ void GrFinishCallbacks::check() {
|
||||
|
||||
void GrFinishCallbacks::callAll(bool doDelete) {
|
||||
while (!fCallbacks.empty()) {
|
||||
- fCallbacks.front().fCallback(fCallbacks.front().fContext);
|
||||
+ // While we are processing a proc we need to make sure to remove it from
|
||||
+ // the callback list before calling it. This is because the client could
|
||||
+ // trigger a call (e.g. calling flushAndSubmit(/*sync=*/true)) that has
|
||||
+ // us process the finished callbacks. We also must process deleting the
|
||||
+ // fence before a client may abandon the context.
|
||||
+ auto finishCallback = fCallbacks.front();
|
||||
if (doDelete) {
|
||||
- fGpu->deleteFence(fCallbacks.front().fFence);
|
||||
+ fGpu->deleteFence(finishCallback.fFence);
|
||||
}
|
||||
fCallbacks.pop_front();
|
||||
+ finishCallback.fCallback(finishCallback.fContext);
|
||||
}
|
||||
}
|
||||
@@ -1 +1,2 @@
|
||||
utf-8_q_simplify_20the_20logic_20that_20converts_20the_20_1_20.patch
|
||||
utf-8_q_m102-lts_20enhance_20defensive_20mode_20so_20that_20i.patch
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -7,3 +7,10 @@ do_not_export_private_v8_symbols_on_windows.patch
|
||||
fix_build_deprecated_attribute_for_older_msvc_versions.patch
|
||||
fix_disable_implies_dcheck_for_node_stream_array_buffers.patch
|
||||
revert_fix_cppgc_removed_deleted_cstors_in_cppheapcreateparams.patch
|
||||
cherry-pick-3704cf78f471.patch
|
||||
cherry-pick-2f6a2939514f.patch
|
||||
cherry-pick-8b040cb69e96.patch
|
||||
cherry-pick-194bcc127f21.patch
|
||||
cherry-pick-ec236fef54b8.patch
|
||||
cherry-pick-80ed4b917477.patch
|
||||
cherry-pick-2ac0620a5bbb.patch
|
||||
|
||||
135
patches/v8/cherry-pick-194bcc127f21.patch
Normal file
135
patches/v8/cherry-pick-194bcc127f21.patch
Normal file
@@ -0,0 +1,135 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Tobias Tebbi <tebbi@chromium.org>
|
||||
Date: Thu, 6 Oct 2022 13:43:19 +0200
|
||||
Subject: Merged: [turbofan] validate more concurrent reads
|
||||
|
||||
Bug: chromium:1369871
|
||||
(cherry picked from commit ebe5675360e4735589a92a8836303822da79a8f4)
|
||||
|
||||
Change-Id: I49243d2c604cb4635d0d49a572245f7469eabffa
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/3952937
|
||||
Reviewed-by: Nico Hartmann <nicohartmann@chromium.org>
|
||||
Commit-Queue: Tobias Tebbi <tebbi@chromium.org>
|
||||
Cr-Commit-Position: refs/branch-heads/10.6@{#41}
|
||||
Cr-Branched-From: 41bc7435693fbce8ef86753cd9239e30550a3e2d-refs/heads/10.6.194@{#1}
|
||||
Cr-Branched-From: d5f29b929ce7746409201d77f44048f3e9529b40-refs/heads/main@{#82548}
|
||||
|
||||
diff --git a/src/compiler/compilation-dependencies.cc b/src/compiler/compilation-dependencies.cc
|
||||
index 6f5514289b764667fb849ec70c8afe076de33dcb..62bd0f8c46d1e57812605d2425f76679183dc943 100644
|
||||
--- a/src/compiler/compilation-dependencies.cc
|
||||
+++ b/src/compiler/compilation-dependencies.cc
|
||||
@@ -35,7 +35,8 @@ namespace compiler {
|
||||
V(Protector) \
|
||||
V(PrototypeProperty) \
|
||||
V(StableMap) \
|
||||
- V(Transition)
|
||||
+ V(Transition) \
|
||||
+ V(ObjectSlotValue)
|
||||
|
||||
CompilationDependencies::CompilationDependencies(JSHeapBroker* broker,
|
||||
Zone* zone)
|
||||
@@ -863,6 +864,42 @@ class ProtectorDependency final : public CompilationDependency {
|
||||
const PropertyCellRef cell_;
|
||||
};
|
||||
|
||||
+// Check that an object slot will not change during compilation.
|
||||
+class ObjectSlotValueDependency final : public CompilationDependency {
|
||||
+ public:
|
||||
+ explicit ObjectSlotValueDependency(const HeapObjectRef& object, int offset,
|
||||
+ const ObjectRef& value)
|
||||
+ : CompilationDependency(kObjectSlotValue),
|
||||
+ object_(object.object()),
|
||||
+ offset_(offset),
|
||||
+ value_(value.object()) {}
|
||||
+
|
||||
+ bool IsValid() const override {
|
||||
+ PtrComprCageBase cage_base = GetPtrComprCageBase(*object_);
|
||||
+ Object current_value =
|
||||
+ offset_ == HeapObject::kMapOffset
|
||||
+ ? object_->map()
|
||||
+ : TaggedField<Object>::Relaxed_Load(cage_base, *object_, offset_);
|
||||
+ return *value_ == current_value;
|
||||
+ }
|
||||
+ void Install(PendingDependencies* deps) const override {}
|
||||
+
|
||||
+ private:
|
||||
+ size_t Hash() const override {
|
||||
+ return base::hash_combine(object_.address(), offset_, value_.address());
|
||||
+ }
|
||||
+
|
||||
+ bool Equals(const CompilationDependency* that) const override {
|
||||
+ const ObjectSlotValueDependency* const zat = that->AsObjectSlotValue();
|
||||
+ return object_->address() == zat->object_->address() &&
|
||||
+ offset_ == zat->offset_ && value_.address() == zat->value_.address();
|
||||
+ }
|
||||
+
|
||||
+ Handle<HeapObject> object_;
|
||||
+ int offset_;
|
||||
+ Handle<Object> value_;
|
||||
+};
|
||||
+
|
||||
class ElementsKindDependency final : public CompilationDependency {
|
||||
public:
|
||||
ElementsKindDependency(const AllocationSiteRef& site, ElementsKind kind)
|
||||
@@ -1110,6 +1147,12 @@ void CompilationDependencies::DependOnElementsKind(
|
||||
}
|
||||
}
|
||||
|
||||
+void CompilationDependencies::DependOnObjectSlotValue(
|
||||
+ const HeapObjectRef& object, int offset, const ObjectRef& value) {
|
||||
+ RecordDependency(
|
||||
+ zone_->New<ObjectSlotValueDependency>(object, offset, value));
|
||||
+}
|
||||
+
|
||||
void CompilationDependencies::DependOnOwnConstantElement(
|
||||
const JSObjectRef& holder, uint32_t index, const ObjectRef& element) {
|
||||
RecordDependency(
|
||||
diff --git a/src/compiler/compilation-dependencies.h b/src/compiler/compilation-dependencies.h
|
||||
index aa8ff7b82abd2b75d0f32b312f4625de29827bb5..c6a18c400fe7571af67aa45f7a4d2666e09d8de1 100644
|
||||
--- a/src/compiler/compilation-dependencies.h
|
||||
+++ b/src/compiler/compilation-dependencies.h
|
||||
@@ -93,6 +93,10 @@ class V8_EXPORT_PRIVATE CompilationDependencies : public ZoneObject {
|
||||
// Record the assumption that {site}'s {ElementsKind} doesn't change.
|
||||
void DependOnElementsKind(const AllocationSiteRef& site);
|
||||
|
||||
+ // Check that an object slot will not change during compilation.
|
||||
+ void DependOnObjectSlotValue(const HeapObjectRef& object, int offset,
|
||||
+ const ObjectRef& value);
|
||||
+
|
||||
void DependOnOwnConstantElement(const JSObjectRef& holder, uint32_t index,
|
||||
const ObjectRef& element);
|
||||
|
||||
diff --git a/src/compiler/js-create-lowering.cc b/src/compiler/js-create-lowering.cc
|
||||
index fab65507ea0566e27a6793532b5f471fd5104ea5..25a2ec03d2f4ac6834baf2de7132619ce73b8bcc 100644
|
||||
--- a/src/compiler/js-create-lowering.cc
|
||||
+++ b/src/compiler/js-create-lowering.cc
|
||||
@@ -1677,6 +1677,10 @@ base::Optional<Node*> JSCreateLowering::TryAllocateFastLiteral(
|
||||
|
||||
// Now that we hold the migration lock, get the current map.
|
||||
MapRef boilerplate_map = boilerplate.map();
|
||||
+ // Protect against concurrent changes to the boilerplate object by checking
|
||||
+ // for an identical value at the end of the compilation.
|
||||
+ dependencies()->DependOnObjectSlotValue(boilerplate, HeapObject::kMapOffset,
|
||||
+ boilerplate_map);
|
||||
{
|
||||
base::Optional<MapRef> current_boilerplate_map =
|
||||
boilerplate.map_direct_read();
|
||||
@@ -1841,10 +1845,18 @@ base::Optional<Node*> JSCreateLowering::TryAllocateFastLiteralElements(
|
||||
boilerplate.elements(kRelaxedLoad);
|
||||
if (!maybe_boilerplate_elements.has_value()) return {};
|
||||
FixedArrayBaseRef boilerplate_elements = maybe_boilerplate_elements.value();
|
||||
+ // Protect against concurrent changes to the boilerplate object by checking
|
||||
+ // for an identical value at the end of the compilation.
|
||||
+ dependencies()->DependOnObjectSlotValue(
|
||||
+ boilerplate, JSObject::kElementsOffset, boilerplate_elements);
|
||||
|
||||
// Empty or copy-on-write elements just store a constant.
|
||||
int const elements_length = boilerplate_elements.length();
|
||||
MapRef elements_map = boilerplate_elements.map();
|
||||
+ // Protect against concurrent changes to the boilerplate object by checking
|
||||
+ // for an identical value at the end of the compilation.
|
||||
+ dependencies()->DependOnObjectSlotValue(boilerplate_elements,
|
||||
+ HeapObject::kMapOffset, elements_map);
|
||||
if (boilerplate_elements.length() == 0 || elements_map.IsFixedCowArrayMap()) {
|
||||
if (allocation == AllocationType::kOld &&
|
||||
!boilerplate.IsElementsTenured(boilerplate_elements)) {
|
||||
49
patches/v8/cherry-pick-2ac0620a5bbb.patch
Normal file
49
patches/v8/cherry-pick-2ac0620a5bbb.patch
Normal file
@@ -0,0 +1,49 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Thibaud Michaud <thibaudm@chromium.org>
|
||||
Date: Wed, 26 Oct 2022 17:03:36 +0200
|
||||
Subject: Merged: [wasm] Reload cached instance fields in catch handler
|
||||
|
||||
Bug: chromium:1377816
|
||||
(cherry picked from commit f517e518af26b7eac23c9e328b463eb1e8ee3499)
|
||||
|
||||
Change-Id: I993bcff0389a1ba134e89e8ac5299d742ddd150c
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/3999134
|
||||
Commit-Queue: Thibaud Michaud <thibaudm@chromium.org>
|
||||
Reviewed-by: Jakob Kummerow <jkummerow@chromium.org>
|
||||
Cr-Commit-Position: refs/branch-heads/10.6@{#47}
|
||||
Cr-Branched-From: 41bc7435693fbce8ef86753cd9239e30550a3e2d-refs/heads/10.6.194@{#1}
|
||||
Cr-Branched-From: d5f29b929ce7746409201d77f44048f3e9529b40-refs/heads/main@{#82548}
|
||||
|
||||
diff --git a/src/wasm/graph-builder-interface.cc b/src/wasm/graph-builder-interface.cc
|
||||
index f2d776435dd8cff94eea9533a06f6023813a233b..24452564d8159fbaed1acec98c30832b1383c1d8 100644
|
||||
--- a/src/wasm/graph-builder-interface.cc
|
||||
+++ b/src/wasm/graph-builder-interface.cc
|
||||
@@ -87,6 +87,7 @@ class WasmGraphBuildingInterface {
|
||||
struct TryInfo : public ZoneObject {
|
||||
SsaEnv* catch_env;
|
||||
TFNode* exception = nullptr;
|
||||
+ bool first_catch = true;
|
||||
|
||||
bool might_throw() const { return exception != nullptr; }
|
||||
|
||||
@@ -879,6 +880,10 @@ class WasmGraphBuildingInterface {
|
||||
|
||||
TFNode* exception = block->try_info->exception;
|
||||
SetEnv(block->try_info->catch_env);
|
||||
+ if (block->try_info->first_catch) {
|
||||
+ LoadContextIntoSsa(ssa_env_);
|
||||
+ block->try_info->first_catch = false;
|
||||
+ }
|
||||
|
||||
TFNode* if_catch = nullptr;
|
||||
TFNode* if_no_catch = nullptr;
|
||||
@@ -956,6 +961,9 @@ class WasmGraphBuildingInterface {
|
||||
}
|
||||
|
||||
SetEnv(block->try_info->catch_env);
|
||||
+ if (block->try_info->first_catch) {
|
||||
+ LoadContextIntoSsa(ssa_env_);
|
||||
+ }
|
||||
}
|
||||
|
||||
void AtomicOp(FullDecoder* decoder, WasmOpcode opcode,
|
||||
33
patches/v8/cherry-pick-2f6a2939514f.patch
Normal file
33
patches/v8/cherry-pick-2f6a2939514f.patch
Normal file
@@ -0,0 +1,33 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Tobias Tebbi <tebbi@chromium.org>
|
||||
Date: Thu, 1 Sep 2022 15:35:33 +0200
|
||||
Subject: Merged: [compiler] fix typing of [[DateValue]]
|
||||
|
||||
Bug: chromium:1356308
|
||||
(cherry picked from commit ae329407989f1e4689baba7a7827863057d688a9)
|
||||
|
||||
Change-Id: I1e132e96325296d180488774ef183daa36dc22c7
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/3915224
|
||||
Reviewed-by: Darius Mercadier <dmercadier@chromium.org>
|
||||
Cr-Commit-Position: refs/branch-heads/10.6@{#25}
|
||||
Cr-Branched-From: 41bc7435693fbce8ef86753cd9239e30550a3e2d-refs/heads/10.6.194@{#1}
|
||||
Cr-Branched-From: d5f29b929ce7746409201d77f44048f3e9529b40-refs/heads/main@{#82548}
|
||||
|
||||
diff --git a/src/compiler/type-cache.h b/src/compiler/type-cache.h
|
||||
index 6442b6f6b0ee39bf1a820168e9dd924e81bc0cb3..a34d094edaa4cb7dd7ac692e4a11d7c890744d7c 100644
|
||||
--- a/src/compiler/type-cache.h
|
||||
+++ b/src/compiler/type-cache.h
|
||||
@@ -131,9 +131,10 @@ class V8_EXPORT_PRIVATE TypeCache final {
|
||||
Type const kStringLengthType = CreateRange(0.0, String::kMaxLength);
|
||||
|
||||
// A time value always contains a tagged number in the range
|
||||
- // [-kMaxTimeInMs, kMaxTimeInMs].
|
||||
- Type const kTimeValueType =
|
||||
- CreateRange(-DateCache::kMaxTimeInMs, DateCache::kMaxTimeInMs);
|
||||
+ // [-kMaxTimeInMs, kMaxTimeInMs] or -0.
|
||||
+ Type const kTimeValueType = Type::Union(
|
||||
+ CreateRange(-DateCache::kMaxTimeInMs, DateCache::kMaxTimeInMs),
|
||||
+ Type::MinusZero(), zone());
|
||||
|
||||
// The JSDate::day property always contains a tagged number in the range
|
||||
// [1, 31] or NaN.
|
||||
33
patches/v8/cherry-pick-3704cf78f471.patch
Normal file
33
patches/v8/cherry-pick-3704cf78f471.patch
Normal file
@@ -0,0 +1,33 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: =?UTF-8?q?Dominik=20Inf=C3=BChr?= <dinfuehr@chromium.org>
|
||||
Date: Thu, 8 Sep 2022 16:27:54 +0200
|
||||
Subject: Merged: [heap] Fix aborting compaction with map space compaction
|
||||
|
||||
Revision: 3ec02e314cfca04e7457a60363af98b9c9957b16
|
||||
|
||||
BUG=chromium:1359294,v8:12578
|
||||
NOTRY=true
|
||||
NOPRESUBMIT=true
|
||||
NOTREECHECKS=true
|
||||
R=mlippautz@chromium.org
|
||||
|
||||
Change-Id: I04093833a1bfef4269eb578fa5a002872015199e
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/3882977
|
||||
Reviewed-by: Michael Lippautz <mlippautz@chromium.org>
|
||||
Cr-Commit-Position: refs/branch-heads/10.4@{#43}
|
||||
Cr-Branched-From: b1413ed7c71ababe05d590de4b5c4ed97b68693e-refs/heads/10.4.132@{#1}
|
||||
Cr-Branched-From: 9d0a09368569234a1d1094975e2e92591922cd08-refs/heads/main@{#80972}
|
||||
|
||||
diff --git a/src/heap/mark-compact.cc b/src/heap/mark-compact.cc
|
||||
index ef0b67ca2b62745e3d9102a8c73b5841d782e21b..1fef50f691e9dfd44b30cf27e6cdf389f5d89d45 100644
|
||||
--- a/src/heap/mark-compact.cc
|
||||
+++ b/src/heap/mark-compact.cc
|
||||
@@ -1943,7 +1943,7 @@ class EvacuateRecordOnlyVisitor final : public HeapObjectVisitor {
|
||||
// Instead of calling object.IterateBodyFast(cage_base(), &visitor) here
|
||||
// we can shortcut and use the precomputed size value passed to the visitor.
|
||||
DCHECK_EQ(object.SizeFromMap(map), size);
|
||||
- object.IterateBodyFast(map, size, &visitor);
|
||||
+ object.IterateFast(map, size, &visitor);
|
||||
return true;
|
||||
}
|
||||
|
||||
111
patches/v8/cherry-pick-80ed4b917477.patch
Normal file
111
patches/v8/cherry-pick-80ed4b917477.patch
Normal file
@@ -0,0 +1,111 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Maya Lekova <mslekova@chromium.org>
|
||||
Date: Wed, 2 Nov 2022 11:02:24 +0100
|
||||
Subject: Merged: [compiler] Fix mutable heap number object reference leak
|
||||
|
||||
(cherry picked from commit 64112122374c00a86771b4612d20ca5d88ad5bfb)
|
||||
|
||||
Bug: chromium:1380063
|
||||
No-Try: true
|
||||
No-Presubmit: true
|
||||
No-Tree-Checks: true
|
||||
Change-Id: Ifa1737af7fbc7e14d69a5080cbe0aabf7ef466fa
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/4009978
|
||||
Reviewed-by: Igor Sheludko <ishell@chromium.org>
|
||||
Commit-Queue: Maya Lekova <mslekova@chromium.org>
|
||||
Cr-Commit-Position: refs/branch-heads/10.6@{#51}
|
||||
Cr-Branched-From: 41bc7435693fbce8ef86753cd9239e30550a3e2d-refs/heads/10.6.194@{#1}
|
||||
Cr-Branched-From: d5f29b929ce7746409201d77f44048f3e9529b40-refs/heads/main@{#82548}
|
||||
|
||||
diff --git a/src/compiler/effect-control-linearizer.cc b/src/compiler/effect-control-linearizer.cc
|
||||
index 191f50e9e10406f4320d539aeb78f3bec59e8482..ed68b117f21530b66e957654516c6b7208446780 100644
|
||||
--- a/src/compiler/effect-control-linearizer.cc
|
||||
+++ b/src/compiler/effect-control-linearizer.cc
|
||||
@@ -5384,6 +5384,8 @@ Node* EffectControlLinearizer::LowerLoadFieldByIndex(Node* node) {
|
||||
|
||||
auto if_double = __ MakeDeferredLabel();
|
||||
auto done = __ MakeLabel(MachineRepresentation::kTagged);
|
||||
+ auto loaded_field = __ MakeLabel(MachineRepresentation::kTagged);
|
||||
+ auto done_double = __ MakeLabel(MachineRepresentation::kFloat64);
|
||||
|
||||
// Check if field is a mutable double field.
|
||||
__ GotoIfNot(__ IntPtrEqual(__ WordAnd(index, one), zero), &if_double);
|
||||
@@ -5400,8 +5402,8 @@ Node* EffectControlLinearizer::LowerLoadFieldByIndex(Node* node) {
|
||||
Node* offset =
|
||||
__ IntAdd(__ WordShl(index, __ IntPtrConstant(kTaggedSizeLog2 - 1)),
|
||||
__ IntPtrConstant(JSObject::kHeaderSize - kHeapObjectTag));
|
||||
- Node* result = __ Load(MachineType::AnyTagged(), object, offset);
|
||||
- __ Goto(&done, result);
|
||||
+ Node* field = __ Load(MachineType::AnyTagged(), object, offset);
|
||||
+ __ Goto(&loaded_field, field);
|
||||
}
|
||||
|
||||
// The field is located in the properties backing store of {object}.
|
||||
@@ -5415,8 +5417,8 @@ Node* EffectControlLinearizer::LowerLoadFieldByIndex(Node* node) {
|
||||
__ IntPtrConstant(kTaggedSizeLog2 - 1)),
|
||||
__ IntPtrConstant((FixedArray::kHeaderSize - kTaggedSize) -
|
||||
kHeapObjectTag));
|
||||
- Node* result = __ Load(MachineType::AnyTagged(), properties, offset);
|
||||
- __ Goto(&done, result);
|
||||
+ Node* field = __ Load(MachineType::AnyTagged(), properties, offset);
|
||||
+ __ Goto(&loaded_field, field);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5424,9 +5426,6 @@ Node* EffectControlLinearizer::LowerLoadFieldByIndex(Node* node) {
|
||||
// architectures, or a mutable HeapNumber.
|
||||
__ Bind(&if_double);
|
||||
{
|
||||
- auto loaded_field = __ MakeLabel(MachineRepresentation::kTagged);
|
||||
- auto done_double = __ MakeLabel(MachineRepresentation::kFloat64);
|
||||
-
|
||||
index = __ WordSar(index, one);
|
||||
|
||||
// Check if field is in-object or out-of-object.
|
||||
@@ -5454,27 +5453,27 @@ Node* EffectControlLinearizer::LowerLoadFieldByIndex(Node* node) {
|
||||
Node* field = __ Load(MachineType::AnyTagged(), properties, offset);
|
||||
__ Goto(&loaded_field, field);
|
||||
}
|
||||
+ }
|
||||
|
||||
- __ Bind(&loaded_field);
|
||||
- {
|
||||
- Node* field = loaded_field.PhiAt(0);
|
||||
- // We may have transitioned in-place away from double, so check that
|
||||
- // this is a HeapNumber -- otherwise the load is fine and we don't need
|
||||
- // to copy anything anyway.
|
||||
- __ GotoIf(ObjectIsSmi(field), &done, field);
|
||||
- Node* field_map = __ LoadField(AccessBuilder::ForMap(), field);
|
||||
- __ GotoIfNot(__ TaggedEqual(field_map, __ HeapNumberMapConstant()), &done,
|
||||
- field);
|
||||
-
|
||||
- Node* value = __ LoadField(AccessBuilder::ForHeapNumberValue(), field);
|
||||
- __ Goto(&done_double, value);
|
||||
- }
|
||||
+ __ Bind(&loaded_field);
|
||||
+ {
|
||||
+ Node* field = loaded_field.PhiAt(0);
|
||||
+ // We may have transitioned in-place away from double, so check that
|
||||
+ // this is a HeapNumber -- otherwise the load is fine and we don't need
|
||||
+ // to copy anything anyway.
|
||||
+ __ GotoIf(ObjectIsSmi(field), &done, field);
|
||||
+ Node* field_map = __ LoadField(AccessBuilder::ForMap(), field);
|
||||
+ __ GotoIfNot(__ TaggedEqual(field_map, __ HeapNumberMapConstant()), &done,
|
||||
+ field);
|
||||
|
||||
- __ Bind(&done_double);
|
||||
- {
|
||||
- Node* result = AllocateHeapNumberWithValue(done_double.PhiAt(0));
|
||||
- __ Goto(&done, result);
|
||||
- }
|
||||
+ Node* value = __ LoadField(AccessBuilder::ForHeapNumberValue(), field);
|
||||
+ __ Goto(&done_double, value);
|
||||
+ }
|
||||
+
|
||||
+ __ Bind(&done_double);
|
||||
+ {
|
||||
+ Node* result = AllocateHeapNumberWithValue(done_double.PhiAt(0));
|
||||
+ __ Goto(&done, result);
|
||||
}
|
||||
|
||||
__ Bind(&done);
|
||||
47
patches/v8/cherry-pick-8b040cb69e96.patch
Normal file
47
patches/v8/cherry-pick-8b040cb69e96.patch
Normal file
@@ -0,0 +1,47 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Jakob Kummerow <jkummerow@chromium.org>
|
||||
Date: Fri, 23 Sep 2022 13:13:37 +0200
|
||||
Subject: Fix a register reuse corner case
|
||||
|
||||
Fixed: chromium:1366399
|
||||
(cherry picked from commit 6c214db445827707d65be08d177c9a4257a03a7b)
|
||||
|
||||
Change-Id: I72cf30cbd31a21acb44b524a194acfb89d8fecbc
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/3925795
|
||||
Reviewed-by: Matthias Liedtke <mliedtke@chromium.org>
|
||||
Cr-Commit-Position: refs/branch-heads/10.6@{#29}
|
||||
Cr-Branched-From: 41bc7435693fbce8ef86753cd9239e30550a3e2d-refs/heads/10.6.194@{#1}
|
||||
Cr-Branched-From: d5f29b929ce7746409201d77f44048f3e9529b40-refs/heads/main@{#82548}
|
||||
|
||||
diff --git a/src/wasm/baseline/liftoff-compiler.cc b/src/wasm/baseline/liftoff-compiler.cc
|
||||
index 34b51e37c650274ec89a1930c4a9d9443f9838a2..508a91ecb8aa068b942fe445e186267832378cef 100644
|
||||
--- a/src/wasm/baseline/liftoff-compiler.cc
|
||||
+++ b/src/wasm/baseline/liftoff-compiler.cc
|
||||
@@ -1417,9 +1417,11 @@ class LiftoffCompiler {
|
||||
__ MergeFullStackWith(c->label_state, *__ cache_state());
|
||||
__ emit_jump(c->label.get());
|
||||
}
|
||||
- // Merge the else state into the end state.
|
||||
+ // Merge the else state into the end state. Set this state as the current
|
||||
+ // state first so helper functions know which registers are in use.
|
||||
__ bind(c->else_state->label.get());
|
||||
- __ MergeFullStackWith(c->label_state, c->else_state->state);
|
||||
+ __ cache_state()->Steal(c->else_state->state);
|
||||
+ __ MergeFullStackWith(c->label_state, *__ cache_state());
|
||||
__ cache_state()->Steal(c->label_state);
|
||||
} else if (c->reachable()) {
|
||||
// No merge yet at the end of the if, but we need to create a merge for
|
||||
@@ -1431,9 +1433,11 @@ class LiftoffCompiler {
|
||||
c->stack_depth + c->num_exceptions);
|
||||
__ MergeFullStackWith(c->label_state, *__ cache_state());
|
||||
__ emit_jump(c->label.get());
|
||||
- // Merge the else state into the end state.
|
||||
+ // Merge the else state into the end state. Set this state as the current
|
||||
+ // state first so helper functions know which registers are in use.
|
||||
__ bind(c->else_state->label.get());
|
||||
- __ MergeFullStackWith(c->label_state, c->else_state->state);
|
||||
+ __ cache_state()->Steal(c->else_state->state);
|
||||
+ __ MergeFullStackWith(c->label_state, *__ cache_state());
|
||||
__ cache_state()->Steal(c->label_state);
|
||||
} else {
|
||||
// No merge needed, just continue with the else state.
|
||||
39
patches/v8/cherry-pick-ec236fef54b8.patch
Normal file
39
patches/v8/cherry-pick-ec236fef54b8.patch
Normal file
@@ -0,0 +1,39 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Tobias Tebbi <tebbi@chromium.org>
|
||||
Date: Wed, 26 Oct 2022 11:19:59 +0200
|
||||
Subject: Merged: [turbofan] do not optimize any stores for field type None
|
||||
|
||||
Fixed: chromium:1378239
|
||||
(cherry picked from commit db83e72034c0d431ff2f73e3c4ae3130c0f3e4e1)
|
||||
|
||||
Change-Id: I061d5dfe6e4ee24e6d0e7df56e15fbe37752d51e
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/3982254
|
||||
Reviewed-by: Tobias Tebbi <tebbi@chromium.org>
|
||||
Commit-Queue: Igor Sheludko <ishell@chromium.org>
|
||||
Cr-Commit-Position: refs/branch-heads/10.6@{#45}
|
||||
Cr-Branched-From: 41bc7435693fbce8ef86753cd9239e30550a3e2d-refs/heads/10.6.194@{#1}
|
||||
Cr-Branched-From: d5f29b929ce7746409201d77f44048f3e9529b40-refs/heads/main@{#82548}
|
||||
|
||||
diff --git a/src/compiler/access-info.cc b/src/compiler/access-info.cc
|
||||
index 53cab92b8e72bbfcead07b94f68f0872b9379b53..6ad6a68092efc36591204f9aacde97a49b13812d 100644
|
||||
--- a/src/compiler/access-info.cc
|
||||
+++ b/src/compiler/access-info.cc
|
||||
@@ -454,9 +454,15 @@ PropertyAccessInfo AccessInfoFactory::ComputeDataFieldAccessInfo(
|
||||
map, descriptor, details_representation));
|
||||
} else if (details_representation.IsHeapObject()) {
|
||||
if (descriptors_field_type->IsNone()) {
|
||||
- // Store is not safe if the field type was cleared.
|
||||
- if (access_mode == AccessMode::kStore) {
|
||||
- return Invalid();
|
||||
+ switch (access_mode) {
|
||||
+ case AccessMode::kStore:
|
||||
+ case AccessMode::kStoreInLiteral:
|
||||
+ case AccessMode::kDefine:
|
||||
+ // Store is not safe if the field type was cleared.
|
||||
+ return Invalid();
|
||||
+ case AccessMode::kLoad:
|
||||
+ case AccessMode::kHas:
|
||||
+ break;
|
||||
}
|
||||
|
||||
// The field type was cleared by the GC, so we don't know anything
|
||||
@@ -2,13 +2,14 @@ const fs = require('fs');
|
||||
const path = require('path');
|
||||
|
||||
const utils = require('./lib/utils');
|
||||
const branding = require('../shell/app/BRANDING.json');
|
||||
|
||||
if (process.platform !== 'darwin') {
|
||||
console.log('Not checking symlinks on non-darwin platform');
|
||||
process.exit(0);
|
||||
}
|
||||
|
||||
const appPath = path.resolve(__dirname, '..', '..', 'out', utils.getOutDir(), 'Electron.app');
|
||||
const appPath = path.resolve(__dirname, '..', '..', 'out', utils.getOutDir(), `${branding.product_name}.app`);
|
||||
const visited = new Set();
|
||||
const traverse = (p) => {
|
||||
if (visited.has(p)) return;
|
||||
|
||||
17
script/create-api-json.js
Normal file
17
script/create-api-json.js
Normal file
@@ -0,0 +1,17 @@
|
||||
const { parseDocs } = require('@electron/docs-parser');
|
||||
const fs = require('fs');
|
||||
const path = require('path');
|
||||
|
||||
const { getElectronVersion } = require('./lib/get-version');
|
||||
|
||||
parseDocs({
|
||||
baseDirectory: path.resolve(__dirname, '..'),
|
||||
packageMode: 'single',
|
||||
useReadme: false,
|
||||
moduleVersion: getElectronVersion()
|
||||
}).then((api) => {
|
||||
return fs.promises.writeFile(path.resolve(__dirname, '..', 'electron-api.json'), JSON.stringify(api, null, 2));
|
||||
}).catch((err) => {
|
||||
console.error(err);
|
||||
process.exit(1);
|
||||
});
|
||||
@@ -3,8 +3,7 @@ const path = require('path');
|
||||
const semver = require('semver');
|
||||
|
||||
const outputPath = process.argv[2];
|
||||
|
||||
const currentVersion = fs.readFileSync(path.resolve(__dirname, '../ELECTRON_VERSION'), 'utf8').trim();
|
||||
const currentVersion = process.argv[3];
|
||||
|
||||
const parsed = semver.parse(currentVersion);
|
||||
|
||||
@@ -20,9 +19,11 @@ const {
|
||||
} = parsed;
|
||||
|
||||
fs.writeFileSync(outputPath, JSON.stringify({
|
||||
full_version: currentVersion,
|
||||
major,
|
||||
minor,
|
||||
patch,
|
||||
prerelease,
|
||||
prerelease_number: prerelease ? parsed.prerelease[parsed.prerelease.length - 1] : '0',
|
||||
has_prerelease: prerelease === '' ? 0 : 1
|
||||
}, null, 2));
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
const asar = require('asar');
|
||||
const asar = require('@electron/asar');
|
||||
const crypto = require('crypto');
|
||||
const fs = require('fs');
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
const asar = require('asar');
|
||||
const asar = require('@electron/asar');
|
||||
const assert = require('assert');
|
||||
const fs = require('fs-extra');
|
||||
const os = require('os');
|
||||
|
||||
22
script/lib/get-version.js
Normal file
22
script/lib/get-version.js
Normal file
@@ -0,0 +1,22 @@
|
||||
const { spawnSync } = require('child_process');
|
||||
const path = require('path');
|
||||
|
||||
module.exports.getElectronVersion = () => {
|
||||
// Find the nearest tag to the current HEAD
|
||||
// This is equivilant to our old logic of "use a value in package.json" for the following reasons
|
||||
//
|
||||
// 1. Whenever we updated the package.json we ALSO pushed a tag with the same version
|
||||
// 2. Whenever we _reverted_ a bump all we actually did was push a commit that deleted the tag and changed the version number back
|
||||
//
|
||||
// The only difference in the "git describe" technique is that technically a commit can "change" it's version
|
||||
// number if a tag is created / removed retroactively. i.e. the first time a commit is pushed it will be 1.2.3
|
||||
// and after the tag is made rebuilding the same commit will result in it being 1.2.4
|
||||
const output = spawnSync('git', ['describe', '--tags', '--abbrev=0'], {
|
||||
cwd: path.resolve(__dirname, '..', '..')
|
||||
});
|
||||
if (output.status !== 0) {
|
||||
console.error(output.stderr);
|
||||
throw new Error('Failed to get current electron version');
|
||||
}
|
||||
return output.stdout.toString().trim().replace(/^v/g, '');
|
||||
};
|
||||
@@ -15,7 +15,9 @@ except ImportError:
|
||||
from urllib2 import urlopen
|
||||
import zipfile
|
||||
|
||||
from lib.config import is_verbose_mode
|
||||
# from lib.config import is_verbose_mode
|
||||
def is_verbose_mode():
|
||||
return False
|
||||
|
||||
ELECTRON_DIR = os.path.abspath(
|
||||
os.path.dirname(os.path.dirname(os.path.dirname(__file__)))
|
||||
@@ -149,11 +151,17 @@ def get_electron_branding():
|
||||
with open(branding_file_path) as f:
|
||||
return json.load(f)
|
||||
|
||||
|
||||
cached_electron_version = None
|
||||
def get_electron_version():
|
||||
SOURCE_ROOT = os.path.abspath(os.path.join(__file__, '..', '..', '..'))
|
||||
version_file = os.path.join(SOURCE_ROOT, 'ELECTRON_VERSION')
|
||||
with open(version_file) as f:
|
||||
return 'v' + f.read().strip()
|
||||
global cached_electron_version
|
||||
if cached_electron_version is None:
|
||||
cached_electron_version = str.strip(execute([
|
||||
'node',
|
||||
'-p',
|
||||
'require("./script/lib/get-version").getElectronVersion()'
|
||||
], cwd=ELECTRON_DIR).decode())
|
||||
return cached_electron_version
|
||||
|
||||
def store_artifact(prefix, key_prefix, files):
|
||||
# Azure Storage
|
||||
|
||||
3
script/print-version.py
Normal file
3
script/print-version.py
Normal file
@@ -0,0 +1,3 @@
|
||||
from lib.util import get_electron_version
|
||||
|
||||
print(get_electron_version())
|
||||
@@ -6,6 +6,7 @@ const got = require('got');
|
||||
const semver = require('semver');
|
||||
|
||||
const { getCurrentBranch, ELECTRON_DIR } = require('../lib/utils');
|
||||
const { getElectronVersion } = require('../lib/get-version');
|
||||
const rootPackageJson = require('../../package.json');
|
||||
|
||||
const { Octokit } = require('@octokit/rest');
|
||||
@@ -34,7 +35,6 @@ const files = [
|
||||
|
||||
const jsonFields = [
|
||||
'name',
|
||||
'version',
|
||||
'repository',
|
||||
'description',
|
||||
'license',
|
||||
@@ -44,6 +44,9 @@ const jsonFields = [
|
||||
|
||||
let npmTag = '';
|
||||
|
||||
const currentElectronVersion = getElectronVersion();
|
||||
const isNightlyElectronVersion = currentElectronVersion.includes('nightly');
|
||||
|
||||
new Promise((resolve, reject) => {
|
||||
temp.mkdir('electron-npm', (err, dirPath) => {
|
||||
if (err) {
|
||||
@@ -68,6 +71,7 @@ new Promise((resolve, reject) => {
|
||||
jsonFields.forEach((fieldName) => {
|
||||
packageJson[fieldName] = rootPackageJson[fieldName];
|
||||
});
|
||||
packageJson.version = currentElectronVersion;
|
||||
fs.writeFileSync(
|
||||
path.join(tempDir, 'package.json'),
|
||||
JSON.stringify(packageJson, null, 2)
|
||||
@@ -75,27 +79,27 @@ new Promise((resolve, reject) => {
|
||||
|
||||
return octokit.repos.listReleases({
|
||||
owner: 'electron',
|
||||
repo: rootPackageJson.version.indexOf('nightly') > 0 ? 'nightlies' : 'electron'
|
||||
repo: isNightlyElectronVersion ? 'nightlies' : 'electron'
|
||||
});
|
||||
})
|
||||
.then((releases) => {
|
||||
// download electron.d.ts from release
|
||||
const release = releases.data.find(
|
||||
(release) => release.tag_name === `v${rootPackageJson.version}`
|
||||
(release) => release.tag_name === `v${currentElectronVersion}`
|
||||
);
|
||||
if (!release) {
|
||||
throw new Error(`cannot find release with tag v${rootPackageJson.version}`);
|
||||
throw new Error(`cannot find release with tag v${currentElectronVersion}`);
|
||||
}
|
||||
return release;
|
||||
})
|
||||
.then(async (release) => {
|
||||
const tsdAsset = release.assets.find((asset) => asset.name === 'electron.d.ts');
|
||||
if (!tsdAsset) {
|
||||
throw new Error(`cannot find electron.d.ts from v${rootPackageJson.version} release assets`);
|
||||
throw new Error(`cannot find electron.d.ts from v${currentElectronVersion} release assets`);
|
||||
}
|
||||
|
||||
const typingsContent = await getAssetContents(
|
||||
rootPackageJson.version.indexOf('nightly') > 0 ? 'nightlies' : 'electron',
|
||||
isNightlyElectronVersion ? 'nightlies' : 'electron',
|
||||
tsdAsset.id
|
||||
);
|
||||
|
||||
@@ -106,11 +110,11 @@ new Promise((resolve, reject) => {
|
||||
.then(async (release) => {
|
||||
const checksumsAsset = release.assets.find((asset) => asset.name === 'SHASUMS256.txt');
|
||||
if (!checksumsAsset) {
|
||||
throw new Error(`cannot find SHASUMS256.txt from v${rootPackageJson.version} release assets`);
|
||||
throw new Error(`cannot find SHASUMS256.txt from v${currentElectronVersion} release assets`);
|
||||
}
|
||||
|
||||
const checksumsContent = await getAssetContents(
|
||||
rootPackageJson.version.indexOf('nightly') > 0 ? 'nightlies' : 'electron',
|
||||
isNightlyElectronVersion ? 'nightlies' : 'electron',
|
||||
checksumsAsset.id
|
||||
);
|
||||
|
||||
@@ -127,7 +131,7 @@ new Promise((resolve, reject) => {
|
||||
.then(async (release) => {
|
||||
const currentBranch = await getCurrentBranch();
|
||||
|
||||
if (release.tag_name.indexOf('nightly') > 0) {
|
||||
if (isNightlyElectronVersion) {
|
||||
// TODO(main-migration): Simplify once main branch is renamed.
|
||||
if (currentBranch === 'master' || currentBranch === 'main') {
|
||||
// Nightlies get published to their own module, so they should be tagged as latest
|
||||
@@ -164,7 +168,7 @@ new Promise((resolve, reject) => {
|
||||
.then(() => childProcess.execSync('npm pack', { cwd: tempDir }))
|
||||
.then(() => {
|
||||
// test that the package can install electron prebuilt from github release
|
||||
const tarballPath = path.join(tempDir, `${rootPackageJson.name}-${rootPackageJson.version}.tgz`);
|
||||
const tarballPath = path.join(tempDir, `${rootPackageJson.name}-${currentElectronVersion}.tgz`);
|
||||
return new Promise((resolve, reject) => {
|
||||
const result = childProcess.spawnSync('npm', ['install', tarballPath, '--force', '--silent'], {
|
||||
env: Object.assign({}, process.env, { electron_config_cache: tempDir }),
|
||||
@@ -190,7 +194,7 @@ new Promise((resolve, reject) => {
|
||||
});
|
||||
})
|
||||
.then((tarballPath) => {
|
||||
const existingVersionJSON = childProcess.execSync(`npm view electron@${rootPackageJson.version} --json`).toString('utf-8');
|
||||
const existingVersionJSON = childProcess.execSync(`npx npm@7 view ${rootPackageJson.name}@${currentElectronVersion} --json`).toString('utf-8');
|
||||
// It's possible this is a re-run and we already have published the package, if not we just publish like normal
|
||||
if (!existingVersionJSON) {
|
||||
childProcess.execSync(`npm publish ${tarballPath} --tag ${npmTag} --otp=${process.env.ELECTRON_NPM_OTP}`);
|
||||
@@ -198,22 +202,21 @@ new Promise((resolve, reject) => {
|
||||
})
|
||||
.then(() => {
|
||||
const currentTags = JSON.parse(childProcess.execSync('npm show electron dist-tags --json').toString());
|
||||
const localVersion = rootPackageJson.version;
|
||||
const parsedLocalVersion = semver.parse(localVersion);
|
||||
const parsedLocalVersion = semver.parse(currentElectronVersion);
|
||||
if (rootPackageJson.name === 'electron') {
|
||||
// We should only customly add dist tags for non-nightly releases where the package name is still
|
||||
// "electron"
|
||||
if (parsedLocalVersion.prerelease.length === 0 &&
|
||||
semver.gt(localVersion, currentTags.latest)) {
|
||||
childProcess.execSync(`npm dist-tag add electron@${localVersion} latest --otp=${process.env.ELECTRON_NPM_OTP}`);
|
||||
semver.gt(currentElectronVersion, currentTags.latest)) {
|
||||
childProcess.execSync(`npm dist-tag add electron@${currentElectronVersion} latest --otp=${process.env.ELECTRON_NPM_OTP}`);
|
||||
}
|
||||
if (parsedLocalVersion.prerelease[0] === 'beta' &&
|
||||
semver.gt(localVersion, currentTags.beta)) {
|
||||
childProcess.execSync(`npm dist-tag add electron@${localVersion} beta --otp=${process.env.ELECTRON_NPM_OTP}`);
|
||||
semver.gt(currentElectronVersion, currentTags.beta)) {
|
||||
childProcess.execSync(`npm dist-tag add electron@${currentElectronVersion} beta --otp=${process.env.ELECTRON_NPM_OTP}`);
|
||||
}
|
||||
if (parsedLocalVersion.prerelease[0] === 'alpha' &&
|
||||
semver.gt(localVersion, currentTags.alpha)) {
|
||||
childProcess.execSync(`npm dist-tag add electron@${localVersion} alpha --otp=${process.env.ELECTRON_NPM_OTP}`);
|
||||
semver.gt(currentElectronVersion, currentTags.alpha)) {
|
||||
childProcess.execSync(`npm dist-tag add electron@${currentElectronVersion} alpha --otp=${process.env.ELECTRON_NPM_OTP}`);
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
@@ -18,26 +18,6 @@ require('colors');
|
||||
const pass = '✓'.green;
|
||||
const fail = '✗'.red;
|
||||
|
||||
function getLastBumpCommit (tag) {
|
||||
const data = execSync(`git log -n1 --grep "Bump ${tag}" --format='format:{"hash": "%H", "message": "%s"}'`).toString();
|
||||
return JSON.parse(data);
|
||||
}
|
||||
|
||||
async function revertBumpCommit (tag) {
|
||||
const branch = await getCurrentBranch();
|
||||
const commitToRevert = getLastBumpCommit(tag).hash;
|
||||
await GitProcess.exec(['pull', '--rebase']);
|
||||
await GitProcess.exec(['revert', commitToRevert], ELECTRON_DIR);
|
||||
const pushDetails = await GitProcess.exec(['push', 'origin', `HEAD:${branch}`, '--follow-tags'], ELECTRON_DIR);
|
||||
if (pushDetails.exitCode === 0) {
|
||||
console.log(`${pass} successfully reverted release commit.`);
|
||||
} else {
|
||||
const error = GitProcess.parseError(pushDetails.stderr);
|
||||
console.error(`${fail} could not push release commit: `, error);
|
||||
process.exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
async function deleteDraft (releaseId, targetRepo) {
|
||||
try {
|
||||
const result = await octokit.repos.getRelease({
|
||||
@@ -80,9 +60,6 @@ async function cleanReleaseArtifacts () {
|
||||
const releaseId = args.releaseID.length > 0 ? args.releaseID : null;
|
||||
const isNightly = args.tag.includes('nightly');
|
||||
|
||||
// try to revert commit regardless of tag and draft deletion status
|
||||
await revertBumpCommit(args.tag);
|
||||
|
||||
if (releaseId) {
|
||||
if (isNightly) {
|
||||
await deleteDraft(releaseId, 'nightlies');
|
||||
|
||||
@@ -12,8 +12,6 @@ const args = require('minimist')(process.argv.slice(2), {
|
||||
const fs = require('fs');
|
||||
const { execSync } = require('child_process');
|
||||
const got = require('got');
|
||||
const pkg = require('../../package.json');
|
||||
const pkgVersion = `v${pkg.version}`;
|
||||
const path = require('path');
|
||||
const temp = require('temp').track();
|
||||
const { URL } = require('url');
|
||||
@@ -25,8 +23,11 @@ const pass = '✓'.green;
|
||||
const fail = '✗'.red;
|
||||
|
||||
const { ELECTRON_DIR } = require('../lib/utils');
|
||||
const { getElectronVersion } = require('../lib/get-version');
|
||||
const getUrlHash = require('./get-url-hash');
|
||||
|
||||
const pkgVersion = `v${getElectronVersion()}`;
|
||||
|
||||
const octokit = new Octokit({
|
||||
auth: process.env.ELECTRON_GITHUB_TOKEN
|
||||
});
|
||||
|
||||
@@ -23,7 +23,7 @@ from lib.util import get_electron_branding, execute, get_electron_version, \
|
||||
SRC_DIR, ELECTRON_DIR, TS_NODE
|
||||
|
||||
|
||||
ELECTRON_VERSION = get_electron_version()
|
||||
ELECTRON_VERSION = 'v' + get_electron_version()
|
||||
|
||||
PROJECT_NAME = get_electron_branding()['project_name']
|
||||
PRODUCT_NAME = get_electron_branding()['product_name']
|
||||
|
||||
@@ -1,17 +1,10 @@
|
||||
#!/usr/bin/env node
|
||||
|
||||
const { GitProcess } = require('dugite');
|
||||
const { promises: fs } = require('fs');
|
||||
const semver = require('semver');
|
||||
const path = require('path');
|
||||
const minimist = require('minimist');
|
||||
|
||||
const { ELECTRON_DIR } = require('../lib/utils');
|
||||
const { getElectronVersion } = require('../lib/get-version');
|
||||
const versionUtils = require('./version-utils');
|
||||
const supported = path.resolve(ELECTRON_DIR, 'docs', 'tutorial', 'support.md');
|
||||
|
||||
const writeFile = fs.writeFile;
|
||||
const readFile = fs.readFile;
|
||||
|
||||
function parseCommandLine () {
|
||||
let help;
|
||||
@@ -37,7 +30,7 @@ function parseCommandLine () {
|
||||
// run the script
|
||||
async function main () {
|
||||
const opts = parseCommandLine();
|
||||
const currentVersion = await versionUtils.getElectronVersion();
|
||||
const currentVersion = getElectronVersion();
|
||||
const version = await nextVersion(opts.bump, currentVersion);
|
||||
|
||||
const parsed = semver.parse(version);
|
||||
@@ -54,20 +47,6 @@ async function main () {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (shouldUpdateSupported(opts.bump, currentVersion, version)) {
|
||||
await updateSupported(version, supported);
|
||||
}
|
||||
|
||||
// update all version-related files
|
||||
await Promise.all([
|
||||
updateVersion(version),
|
||||
updatePackageJSON(version),
|
||||
updateWinRC(components)
|
||||
]);
|
||||
|
||||
// commit all updated version-related files
|
||||
await commitVersionBump(version);
|
||||
|
||||
console.log(`Bumped to version: ${version}`);
|
||||
}
|
||||
|
||||
@@ -118,10 +97,6 @@ async function nextVersion (bumpType, version) {
|
||||
return version;
|
||||
}
|
||||
|
||||
function shouldUpdateSupported (bump, current, version) {
|
||||
return isMajorStable(bump, current) || isMajorNightly(version, current);
|
||||
}
|
||||
|
||||
function isMajorStable (bump, currentVersion) {
|
||||
if (versionUtils.isBeta(currentVersion) && (bump === 'stable')) return true;
|
||||
return false;
|
||||
@@ -134,59 +109,6 @@ function isMajorNightly (version, currentVersion) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// update VERSION file with latest release info
|
||||
async function updateVersion (version) {
|
||||
const versionPath = path.resolve(ELECTRON_DIR, 'ELECTRON_VERSION');
|
||||
await writeFile(versionPath, version, 'utf8');
|
||||
}
|
||||
|
||||
// update package metadata files with new version
|
||||
async function updatePackageJSON (version) {
|
||||
const filePath = path.resolve(ELECTRON_DIR, 'package.json');
|
||||
const file = require(filePath);
|
||||
file.version = version;
|
||||
await writeFile(filePath, JSON.stringify(file, null, 2));
|
||||
}
|
||||
|
||||
// push bump commit to release branch
|
||||
async function commitVersionBump (version) {
|
||||
const gitArgs = ['commit', '-a', '-m', `Bump v${version}`, '-n'];
|
||||
await GitProcess.exec(gitArgs, ELECTRON_DIR);
|
||||
}
|
||||
|
||||
// updates electron.rc file with new semver values
|
||||
async function updateWinRC (components) {
|
||||
const filePath = path.resolve(ELECTRON_DIR, 'shell', 'browser', 'resources', 'win', 'electron.rc');
|
||||
const data = await readFile(filePath, 'utf8');
|
||||
const arr = data.split('\n');
|
||||
arr.forEach((line, idx) => {
|
||||
if (line.includes('FILEVERSION')) {
|
||||
arr[idx] = ` FILEVERSION ${versionUtils.makeVersion(components, ',', versionUtils.preType.PARTIAL)}`;
|
||||
arr[idx + 1] = ` PRODUCTVERSION ${versionUtils.makeVersion(components, ',', versionUtils.preType.PARTIAL)}`;
|
||||
} else if (line.includes('FileVersion')) {
|
||||
arr[idx] = ` VALUE "FileVersion", "${versionUtils.makeVersion(components, '.')}"`;
|
||||
arr[idx + 5] = ` VALUE "ProductVersion", "${versionUtils.makeVersion(components, '.')}"`;
|
||||
}
|
||||
});
|
||||
await writeFile(filePath, arr.join('\n'));
|
||||
}
|
||||
|
||||
// updates support.md file with new semver values (stable only)
|
||||
async function updateSupported (version, filePath) {
|
||||
const v = parseInt(version);
|
||||
const newVersions = [`* ${v}.x.y`, `* ${v - 1}.x.y`, `* ${v - 2}.x.y`, `* ${v - 3}.x.y`];
|
||||
const contents = await readFile(filePath, 'utf8');
|
||||
const previousVersions = contents.split('\n').filter((elem) => {
|
||||
return (/[^\n]*\.x\.y[^\n]*/).test(elem);
|
||||
}, []);
|
||||
|
||||
const newContents = previousVersions.reduce((contents, current, i) => {
|
||||
return contents.replace(current, newVersions[i]);
|
||||
}, contents);
|
||||
|
||||
await writeFile(filePath, newContents, 'utf8');
|
||||
}
|
||||
|
||||
if (process.mainModule === module) {
|
||||
main().catch((error) => {
|
||||
console.error(error);
|
||||
@@ -194,4 +116,4 @@ if (process.mainModule === module) {
|
||||
});
|
||||
}
|
||||
|
||||
module.exports = { nextVersion, shouldUpdateSupported, updateSupported };
|
||||
module.exports = { nextVersion };
|
||||
|
||||
@@ -68,12 +68,6 @@ async function nextBeta (v) {
|
||||
return tags.length === 0 ? `${next}-beta.1` : semver.inc(tags.pop(), 'prerelease');
|
||||
}
|
||||
|
||||
async function getElectronVersion () {
|
||||
const versionPath = path.resolve(ELECTRON_DIR, 'ELECTRON_VERSION');
|
||||
const version = await readFile(versionPath, 'utf8');
|
||||
return version.trim();
|
||||
}
|
||||
|
||||
async function nextNightly (v) {
|
||||
let next = semver.valid(semver.coerce(v));
|
||||
const pre = `nightly.${getCurrentDate()}`;
|
||||
@@ -114,7 +108,6 @@ module.exports = {
|
||||
nextAlpha,
|
||||
nextBeta,
|
||||
makeVersion,
|
||||
getElectronVersion,
|
||||
nextNightly,
|
||||
preType
|
||||
};
|
||||
|
||||
@@ -88,8 +88,11 @@ class DataPipeReader {
|
||||
if (result == MOJO_RESULT_OK) { // success
|
||||
remaining_size_ -= length;
|
||||
head_ += length;
|
||||
if (remaining_size_ == 0)
|
||||
if (remaining_size_ == 0) {
|
||||
OnSuccess();
|
||||
} else {
|
||||
handle_watcher_.ArmOrNotify();
|
||||
}
|
||||
} else if (result == MOJO_RESULT_SHOULD_WAIT) { // IO pending
|
||||
handle_watcher_.ArmOrNotify();
|
||||
} else { // error
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
|
||||
#include "shell/browser/api/electron_api_desktop_capturer.h"
|
||||
|
||||
#include <map>
|
||||
#include <memory>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
@@ -24,12 +25,125 @@
|
||||
#include "third_party/webrtc/modules/desktop_capture/desktop_capture_options.h"
|
||||
#include "third_party/webrtc/modules/desktop_capture/desktop_capturer.h"
|
||||
|
||||
#if defined(USE_OZONE)
|
||||
#include "ui/ozone/buildflags.h"
|
||||
#if BUILDFLAG(OZONE_PLATFORM_X11)
|
||||
#define USE_OZONE_PLATFORM_X11
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if BUILDFLAG(IS_WIN)
|
||||
#include "third_party/webrtc/modules/desktop_capture/win/dxgi_duplicator_controller.h"
|
||||
#include "third_party/webrtc/modules/desktop_capture/win/screen_capturer_win_directx.h"
|
||||
#include "ui/display/win/display_info.h"
|
||||
#elif BUILDFLAG(IS_LINUX)
|
||||
#if defined(USE_OZONE_PLATFORM_X11)
|
||||
#include "base/logging.h"
|
||||
#include "ui/base/x/x11_display_util.h"
|
||||
#include "ui/base/x/x11_util.h"
|
||||
#include "ui/display/util/edid_parser.h" // nogncheck
|
||||
#include "ui/gfx/x/randr.h"
|
||||
#include "ui/gfx/x/x11_atom_cache.h"
|
||||
#include "ui/gfx/x/xproto_util.h"
|
||||
#endif // defined(USE_OZONE_PLATFORM_X11)
|
||||
#endif // BUILDFLAG(IS_WIN)
|
||||
|
||||
#if BUILDFLAG(IS_LINUX)
|
||||
// Private function in ui/base/x/x11_display_util.cc
|
||||
std::map<x11::RandR::Output, int> GetMonitors(int version,
|
||||
x11::RandR* randr,
|
||||
x11::Window window) {
|
||||
std::map<x11::RandR::Output, int> output_to_monitor;
|
||||
if (version >= 105) {
|
||||
if (auto reply = randr->GetMonitors({window}).Sync()) {
|
||||
for (size_t monitor = 0; monitor < reply->monitors.size(); monitor++) {
|
||||
for (x11::RandR::Output output : reply->monitors[monitor].outputs)
|
||||
output_to_monitor[output] = monitor;
|
||||
}
|
||||
}
|
||||
}
|
||||
return output_to_monitor;
|
||||
}
|
||||
// Get the EDID data from the |output| and stores to |edid|.
|
||||
// Private function in ui/base/x/x11_display_util.cc
|
||||
std::vector<uint8_t> GetEDIDProperty(x11::RandR* randr,
|
||||
x11::RandR::Output output) {
|
||||
constexpr const char kRandrEdidProperty[] = "EDID";
|
||||
auto future = randr->GetOutputProperty(x11::RandR::GetOutputPropertyRequest{
|
||||
.output = output,
|
||||
.property = x11::GetAtom(kRandrEdidProperty),
|
||||
.long_length = 128});
|
||||
auto response = future.Sync();
|
||||
std::vector<uint8_t> edid;
|
||||
if (response && response->format == 8 && response->type != x11::Atom::None)
|
||||
edid = std::move(response->data);
|
||||
return edid;
|
||||
}
|
||||
|
||||
// Find the mapping from monitor name atom to the display identifier
|
||||
// that the screen API uses. Based on the logic in BuildDisplaysFromXRandRInfo
|
||||
// in ui/base/x/x11_display_util.cc
|
||||
std::map<int32_t, uint32_t> MonitorAtomIdToDisplayId() {
|
||||
auto* connection = x11::Connection::Get();
|
||||
auto& randr = connection->randr();
|
||||
auto x_root_window = ui::GetX11RootWindow();
|
||||
int version = ui::GetXrandrVersion();
|
||||
|
||||
std::map<int32_t, uint32_t> monitor_atom_to_display;
|
||||
|
||||
auto resources = randr.GetScreenResourcesCurrent({x_root_window}).Sync();
|
||||
if (!resources) {
|
||||
LOG(ERROR) << "XRandR returned no displays; don't know how to map ids";
|
||||
return monitor_atom_to_display;
|
||||
}
|
||||
|
||||
std::map<x11::RandR::Output, int> output_to_monitor =
|
||||
GetMonitors(version, &randr, x_root_window);
|
||||
auto monitors_reply = randr.GetMonitors({x_root_window}).Sync();
|
||||
|
||||
for (size_t i = 0; i < resources->outputs.size(); i++) {
|
||||
x11::RandR::Output output_id = resources->outputs[i];
|
||||
auto output_info =
|
||||
randr.GetOutputInfo({output_id, resources->config_timestamp}).Sync();
|
||||
if (!output_info)
|
||||
continue;
|
||||
|
||||
if (output_info->connection != x11::RandR::RandRConnection::Connected)
|
||||
continue;
|
||||
|
||||
if (output_info->crtc == static_cast<x11::RandR::Crtc>(0))
|
||||
continue;
|
||||
|
||||
auto crtc =
|
||||
randr.GetCrtcInfo({output_info->crtc, resources->config_timestamp})
|
||||
.Sync();
|
||||
if (!crtc)
|
||||
continue;
|
||||
display::EdidParser edid_parser(
|
||||
GetEDIDProperty(&randr, static_cast<x11::RandR::Output>(output_id)));
|
||||
auto output_32 = static_cast<uint32_t>(output_id);
|
||||
int64_t display_id =
|
||||
output_32 > 0xff ? 0 : edid_parser.GetIndexBasedDisplayId(output_32);
|
||||
// It isn't ideal, but if we can't parse the EDID data, fall back on the
|
||||
// display number.
|
||||
if (!display_id)
|
||||
display_id = i;
|
||||
|
||||
// Find the mapping between output identifier and the monitor name atom
|
||||
// Note this isn't the atom string, but the numeric atom identifier,
|
||||
// since this is what the WebRTC system uses as the display identifier
|
||||
auto output_monitor_iter = output_to_monitor.find(output_id);
|
||||
if (output_monitor_iter != output_to_monitor.end()) {
|
||||
x11::Atom atom =
|
||||
monitors_reply->monitors[output_monitor_iter->second].name;
|
||||
monitor_atom_to_display[static_cast<int32_t>(atom)] = display_id;
|
||||
}
|
||||
}
|
||||
|
||||
return monitor_atom_to_display;
|
||||
}
|
||||
#endif
|
||||
|
||||
namespace gin {
|
||||
|
||||
template <>
|
||||
@@ -181,10 +295,22 @@ void DesktopCapturer::UpdateSourcesList(DesktopMediaList* list) {
|
||||
for (auto& source : screen_sources) {
|
||||
source.display_id = base::NumberToString(source.media_list_source.id.id);
|
||||
}
|
||||
#elif BUILDFLAG(IS_LINUX)
|
||||
#if defined(USE_OZONE_PLATFORM_X11)
|
||||
// On Linux, with X11, the source id is the numeric value of the
|
||||
// display name atom and the display id is either the EDID or the
|
||||
// loop index when that display was found (see
|
||||
// BuildDisplaysFromXRandRInfo in ui/base/x/x11_display_util.cc)
|
||||
std::map<int32_t, uint32_t> monitor_atom_to_display_id =
|
||||
MonitorAtomIdToDisplayId();
|
||||
for (auto& source : screen_sources) {
|
||||
auto display_id_iter =
|
||||
monitor_atom_to_display_id.find(source.media_list_source.id.id);
|
||||
if (display_id_iter != monitor_atom_to_display_id.end())
|
||||
source.display_id = base::NumberToString(display_id_iter->second);
|
||||
}
|
||||
#endif // defined(USE_OZONE_PLATFORM_X11)
|
||||
#endif // BUILDFLAG(IS_WIN)
|
||||
// TODO(ajmacd): Add Linux support. The IDs across APIs differ but Chrome
|
||||
// only supports capturing the entire desktop on Linux. Revisit this if
|
||||
// individual screen support is added.
|
||||
std::move(screen_sources.begin(), screen_sources.end(),
|
||||
std::back_inserter(captured_sources_));
|
||||
}
|
||||
|
||||
@@ -175,4 +175,4 @@ bool Converter<ui::NativeTheme::ThemeSource>::FromV8(
|
||||
|
||||
} // namespace gin
|
||||
|
||||
NODE_LINKED_MODULE_CONTEXT_AWARE(electron_common_native_theme, Initialize)
|
||||
NODE_LINKED_MODULE_CONTEXT_AWARE(electron_browser_native_theme, Initialize)
|
||||
|
||||
@@ -304,4 +304,4 @@ void Initialize(v8::Local<v8::Object> exports,
|
||||
|
||||
} // namespace
|
||||
|
||||
NODE_LINKED_MODULE_CONTEXT_AWARE(electron_common_notification, Initialize)
|
||||
NODE_LINKED_MODULE_CONTEXT_AWARE(electron_browser_notification, Initialize)
|
||||
|
||||
@@ -185,4 +185,4 @@ void Initialize(v8::Local<v8::Object> exports,
|
||||
|
||||
} // namespace
|
||||
|
||||
NODE_LINKED_MODULE_CONTEXT_AWARE(electron_common_screen, Initialize)
|
||||
NODE_LINKED_MODULE_CONTEXT_AWARE(electron_browser_screen, Initialize)
|
||||
|
||||
@@ -144,6 +144,10 @@
|
||||
#include "shell/browser/osr/osr_web_contents_view.h"
|
||||
#endif
|
||||
|
||||
#if BUILDFLAG(IS_WIN)
|
||||
#include "shell/browser/native_window_views.h"
|
||||
#endif
|
||||
|
||||
#if !BUILDFLAG(IS_MAC)
|
||||
#include "ui/aura/window.h"
|
||||
#else
|
||||
@@ -174,9 +178,8 @@
|
||||
|
||||
#if BUILDFLAG(IS_WIN)
|
||||
#include "printing/backend/win_helper.h"
|
||||
#include "shell/browser/native_window_views.h"
|
||||
#endif
|
||||
#endif
|
||||
#endif // BUILDFLAG(ENABLE_PRINTING)
|
||||
|
||||
#if BUILDFLAG(ENABLE_PICTURE_IN_PICTURE)
|
||||
#include "chrome/browser/picture_in_picture/picture_in_picture_window_manager.h"
|
||||
@@ -1325,7 +1328,7 @@ void WebContents::EnterFullscreenModeForTab(
|
||||
auto callback =
|
||||
base::BindRepeating(&WebContents::OnEnterFullscreenModeForTab,
|
||||
base::Unretained(this), requesting_frame, options);
|
||||
permission_helper->RequestFullscreenPermission(callback);
|
||||
permission_helper->RequestFullscreenPermission(requesting_frame, callback);
|
||||
}
|
||||
|
||||
void WebContents::OnEnterFullscreenModeForTab(
|
||||
@@ -1394,11 +1397,6 @@ bool WebContents::HandleContextMenu(content::RenderFrameHost& render_frame_host,
|
||||
return true;
|
||||
}
|
||||
|
||||
bool WebContents::OnGoToEntryOffset(int offset) {
|
||||
GoToOffset(offset);
|
||||
return false;
|
||||
}
|
||||
|
||||
void WebContents::FindReply(content::WebContents* web_contents,
|
||||
int request_id,
|
||||
int number_of_matches,
|
||||
@@ -2430,14 +2428,6 @@ void WebContents::OpenDevTools(gin::Arguments* args) {
|
||||
!owner_window()) {
|
||||
state = "detach";
|
||||
}
|
||||
bool activate = true;
|
||||
if (args && args->Length() == 1) {
|
||||
gin_helper::Dictionary options;
|
||||
if (args->GetNext(&options)) {
|
||||
options.Get("mode", &state);
|
||||
options.Get("activate", &activate);
|
||||
}
|
||||
}
|
||||
|
||||
#if BUILDFLAG(IS_WIN)
|
||||
auto* win = static_cast<NativeWindowViews*>(owner_window());
|
||||
@@ -2447,6 +2437,15 @@ void WebContents::OpenDevTools(gin::Arguments* args) {
|
||||
state = "detach";
|
||||
#endif
|
||||
|
||||
bool activate = true;
|
||||
if (args && args->Length() == 1) {
|
||||
gin_helper::Dictionary options;
|
||||
if (args->GetNext(&options)) {
|
||||
options.Get("mode", &state);
|
||||
options.Get("activate", &activate);
|
||||
}
|
||||
}
|
||||
|
||||
DCHECK(inspectable_web_contents_);
|
||||
inspectable_web_contents_->SetDockState(state);
|
||||
inspectable_web_contents_->ShowDevTools(activate);
|
||||
|
||||
@@ -552,7 +552,6 @@ class WebContents : public ExclusiveAccessContext,
|
||||
content::RenderWidgetHost* render_widget_host) override;
|
||||
bool HandleContextMenu(content::RenderFrameHost& render_frame_host,
|
||||
const content::ContextMenuParams& params) override;
|
||||
bool OnGoToEntryOffset(int offset) override;
|
||||
void FindReply(content::WebContents* web_contents,
|
||||
int request_id,
|
||||
int number_of_matches,
|
||||
|
||||
@@ -291,6 +291,12 @@ GURL WebFrameMain::URL() const {
|
||||
return render_frame_->GetLastCommittedURL();
|
||||
}
|
||||
|
||||
std::string WebFrameMain::Origin() const {
|
||||
if (!CheckRenderFrame())
|
||||
return std::string();
|
||||
return render_frame_->GetLastCommittedOrigin().Serialize();
|
||||
}
|
||||
|
||||
blink::mojom::PageVisibilityState WebFrameMain::VisibilityState() const {
|
||||
if (!CheckRenderFrame())
|
||||
return blink::mojom::PageVisibilityState::kHidden;
|
||||
@@ -380,6 +386,7 @@ v8::Local<v8::ObjectTemplate> WebFrameMain::FillObjectTemplate(
|
||||
.SetProperty("processId", &WebFrameMain::ProcessID)
|
||||
.SetProperty("routingId", &WebFrameMain::RoutingID)
|
||||
.SetProperty("url", &WebFrameMain::URL)
|
||||
.SetProperty("origin", &WebFrameMain::Origin)
|
||||
.SetProperty("visibilityState", &WebFrameMain::VisibilityState)
|
||||
.SetProperty("top", &WebFrameMain::Top)
|
||||
.SetProperty("parent", &WebFrameMain::Parent)
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user