mirror of
https://github.com/electron/electron.git
synced 2026-02-19 03:14:51 -05:00
Compare commits
107 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
454990a201 | ||
|
|
10b49ffa12 | ||
|
|
dc0fc78fac | ||
|
|
1aafc2ae38 | ||
|
|
595e25a270 | ||
|
|
7fe5925c94 | ||
|
|
c4b0ff4994 | ||
|
|
abdb9157c3 | ||
|
|
30e1be9150 | ||
|
|
5b48fa0318 | ||
|
|
be1c22ecab | ||
|
|
2c822ce4ac | ||
|
|
f4041c10cf | ||
|
|
60c84cbd77 | ||
|
|
523fa39765 | ||
|
|
d368492bfd | ||
|
|
3c269d74c9 | ||
|
|
5bbcc22b8d | ||
|
|
9abb7fb7e3 | ||
|
|
364390e039 | ||
|
|
b59963cf04 | ||
|
|
7a026ed3dc | ||
|
|
75b7a858ac | ||
|
|
1ba3da738b | ||
|
|
def64aba17 | ||
|
|
d5e1edf244 | ||
|
|
53d9cdbaf0 | ||
|
|
08ae619c5d | ||
|
|
672c31283a | ||
|
|
a7b58871a8 | ||
|
|
f33a5c727f | ||
|
|
912e211f17 | ||
|
|
be3e7bcd97 | ||
|
|
da7b9a17e2 | ||
|
|
3e6f5ca655 | ||
|
|
e6dc9825cc | ||
|
|
0eb53be29a | ||
|
|
c9e59173d7 | ||
|
|
a4ac36f52e | ||
|
|
22140a68fd | ||
|
|
3d773ee528 | ||
|
|
510abbe71b | ||
|
|
c6e803acfc | ||
|
|
51ed765a20 | ||
|
|
3f7c8cbea4 | ||
|
|
5259afc54a | ||
|
|
26abaeddf1 | ||
|
|
4d8b9a8eec | ||
|
|
d362c30b1d | ||
|
|
2d582221e7 | ||
|
|
1d87bcdbab | ||
|
|
e2eda11b2f | ||
|
|
d458be2761 | ||
|
|
025e3f5313 | ||
|
|
42354e6b5d | ||
|
|
0c8fff74c6 | ||
|
|
9cfddc6cc5 | ||
|
|
826807c6a3 | ||
|
|
5ecf2e24e4 | ||
|
|
07debe81dd | ||
|
|
578624896f | ||
|
|
678f3c12e7 | ||
|
|
3e9f1e65e5 | ||
|
|
f20c1350a0 | ||
|
|
ab7e58bee4 | ||
|
|
d7d5ec5f00 | ||
|
|
bae3380b38 | ||
|
|
5161e961c0 | ||
|
|
675c2eb9f8 | ||
|
|
03e02b62a1 | ||
|
|
7d36a23efc | ||
|
|
e6ef31273d | ||
|
|
b3ef435586 | ||
|
|
26873597a1 | ||
|
|
922581af90 | ||
|
|
f5cb867dd2 | ||
|
|
347c02ec76 | ||
|
|
2dd225e4d5 | ||
|
|
c96e3b9e60 | ||
|
|
5c51515982 | ||
|
|
dc7a49b873 | ||
|
|
96ee0b7c36 | ||
|
|
9e4d81fb0b | ||
|
|
9bcb5dc9f7 | ||
|
|
62540b9120 | ||
|
|
ee9484e05c | ||
|
|
3adb49a831 | ||
|
|
6da4c2f12a | ||
|
|
75ddfcc0e2 | ||
|
|
4e692e2211 | ||
|
|
e508ef2b8c | ||
|
|
cb5b8a6311 | ||
|
|
67788dd2ba | ||
|
|
596cb9d1ed | ||
|
|
71cce1cdd7 | ||
|
|
9b338b91ec | ||
|
|
cb3a169caa | ||
|
|
443699a22f | ||
|
|
269e7ba7e4 | ||
|
|
4382f2adc0 | ||
|
|
c1b8848fd7 | ||
|
|
66683e5caf | ||
|
|
093a215296 | ||
|
|
c174ed70f5 | ||
|
|
12673d8caa | ||
|
|
eeea337757 | ||
|
|
e84dde4bad |
@@ -54,7 +54,7 @@ executors:
|
||||
type: enum
|
||||
enum: ["macos.x86.medium.gen2", "large"]
|
||||
macos:
|
||||
xcode: 13.3.0
|
||||
xcode: 13.4.1
|
||||
resource_class: << parameters.size >>
|
||||
|
||||
# Electron Runners
|
||||
@@ -245,14 +245,27 @@ step-depot-tools-get: &step-depot-tools-get
|
||||
sed -i '/ninjalog_uploader_wrapper.py/d' ./depot_tools/autoninja
|
||||
# Remove swift-format dep from cipd on macOS until we send a patch upstream.
|
||||
cd depot_tools
|
||||
patch gclient.py -R \<<'EOF'
|
||||
676,677c676
|
||||
< packages = dep_value.get('packages', [])
|
||||
< for package in (x for x in packages if "infra/3pp/tools/swift-format" not in x.get('package')):
|
||||
---
|
||||
> for package in dep_value.get('packages', []):
|
||||
cat > gclient.diff \<< 'EOF'
|
||||
diff --git a/gclient.py b/gclient.py
|
||||
index 3a9c5c6..f222043 100755
|
||||
--- a/gclient.py
|
||||
+++ b/gclient.py
|
||||
@@ -712,7 +712,8 @@ class Dependency(gclient_utils.WorkItem, DependencySettings):
|
||||
|
||||
if dep_type == 'cipd':
|
||||
cipd_root = self.GetCipdRoot()
|
||||
- for package in dep_value.get('packages', []):
|
||||
+ packages = dep_value.get('packages', [])
|
||||
+ for package in (x for x in packages if "infra/3pp/tools/swift-format" not in x.get('package')):
|
||||
deps_to_add.append(
|
||||
CipdDependency(
|
||||
parent=self,
|
||||
EOF
|
||||
git apply --3way gclient.diff
|
||||
fi
|
||||
# Ensure depot_tools does not update.
|
||||
test -d depot_tools && cd depot_tools
|
||||
touch .disable_auto_update
|
||||
|
||||
step-depot-tools-add-to-path: &step-depot-tools-add-to-path
|
||||
run:
|
||||
@@ -274,7 +287,7 @@ step-gclient-sync: &step-gclient-sync
|
||||
ELECTRON_USE_THREE_WAY_MERGE_FOR_PATCHES=1 gclient sync --with_branch_heads --with_tags
|
||||
if [ "$IS_RELEASE" != "true" ]; then
|
||||
# Re-export all the patches to check if there were changes.
|
||||
python src/electron/script/export_all_patches.py src/electron/patches/config.json
|
||||
python3 src/electron/script/export_all_patches.py src/electron/patches/config.json
|
||||
cd src/electron
|
||||
git update-index --refresh || true
|
||||
if ! git diff-index --quiet HEAD --; then
|
||||
@@ -328,8 +341,8 @@ step-setup-goma-for-build: &step-setup-goma-for-build
|
||||
mkdir third_party
|
||||
node -e "require('./src/utils/goma.js').downloadAndPrepare({ gomaOneForAll: true })"
|
||||
export GOMA_FALLBACK_ON_AUTH_FAILURE=true
|
||||
third_party/goma/goma_ctl.py ensure_start
|
||||
if [ ! -z "$RAW_GOMA_AUTH" ] && [ "`third_party/goma/goma_auth.py info`" != "Login as Fermi Planck" ]; then
|
||||
python3 third_party/goma/goma_ctl.py ensure_start
|
||||
if [ ! -z "$RAW_GOMA_AUTH" ] && [ "`python3 third_party/goma/goma_auth.py info`" != "Login as Fermi Planck" ]; then
|
||||
echo "WARNING!!!!!! Goma authentication is incorrect; please update Goma auth token."
|
||||
exit 1
|
||||
fi
|
||||
@@ -357,14 +370,14 @@ step-restore-brew-cache: &step-restore-brew-cache
|
||||
- /usr/local/Cellar/gnu-tar
|
||||
- /usr/local/bin/gtar
|
||||
keys:
|
||||
- v5-brew-cache-{{ arch }}
|
||||
- v7-brew-cache-{{ arch }}
|
||||
|
||||
step-save-brew-cache: &step-save-brew-cache
|
||||
save_cache:
|
||||
paths:
|
||||
- /usr/local/Cellar/gnu-tar
|
||||
- /usr/local/bin/gtar
|
||||
key: v5-brew-cache-{{ arch }}
|
||||
key: v7-brew-cache-{{ arch }}
|
||||
name: Persisting brew cache
|
||||
|
||||
step-get-more-space-on-mac: &step-get-more-space-on-mac
|
||||
@@ -667,9 +680,9 @@ step-verify-mksnapshot: &step-verify-mksnapshot
|
||||
if [ "$IS_ASAN" != "1" ]; then
|
||||
cd src
|
||||
if [ "$TARGET_ARCH" == "arm" ] || [ "$TARGET_ARCH" == "arm64" ]; then
|
||||
python electron/script/verify-mksnapshot.py --source-root "$PWD" --build-dir out/Default --snapshot-files-dir $PWD/cross-arch-snapshots
|
||||
python3 electron/script/verify-mksnapshot.py --source-root "$PWD" --build-dir out/Default --snapshot-files-dir $PWD/cross-arch-snapshots
|
||||
else
|
||||
python electron/script/verify-mksnapshot.py --source-root "$PWD" --build-dir out/Default
|
||||
python3 electron/script/verify-mksnapshot.py --source-root "$PWD" --build-dir out/Default
|
||||
fi
|
||||
fi
|
||||
|
||||
@@ -679,7 +692,7 @@ step-verify-chromedriver: &step-verify-chromedriver
|
||||
command: |
|
||||
if [ "$IS_ASAN" != "1" ]; then
|
||||
cd src
|
||||
python electron/script/verify-chromedriver.py --source-root "$PWD" --build-dir out/Default
|
||||
python3 electron/script/verify-chromedriver.py --source-root "$PWD" --build-dir out/Default
|
||||
fi
|
||||
|
||||
step-setup-linux-for-headless-testing: &step-setup-linux-for-headless-testing
|
||||
@@ -805,7 +818,7 @@ step-maybe-cross-arch-snapshot: &step-maybe-cross-arch-snapshot
|
||||
elif [ "`uname`" == "Darwin" ]; then
|
||||
cp "out/Default/$MKSNAPSHOT_PATH/libffmpeg.dylib" out/Default
|
||||
fi
|
||||
python electron/script/verify-mksnapshot.py --source-root "$PWD" --build-dir out/Default --create-snapshot-only
|
||||
python3 electron/script/verify-mksnapshot.py --source-root "$PWD" --build-dir out/Default --create-snapshot-only
|
||||
mkdir cross-arch-snapshots
|
||||
cp out/Default-mksnapshot-test/*.bin cross-arch-snapshots
|
||||
# Clean up so that ninja does not get confused
|
||||
@@ -962,26 +975,12 @@ step-ts-compile: &step-ts-compile
|
||||
# List of all steps.
|
||||
steps-electron-gn-check: &steps-electron-gn-check
|
||||
steps:
|
||||
- *step-checkout-electron
|
||||
- *step-depot-tools-get
|
||||
- *step-depot-tools-add-to-path
|
||||
- install-python2-mac
|
||||
- *step-setup-env-for-build
|
||||
- *step-setup-goma-for-build
|
||||
- *step-generate-deps-hash
|
||||
- *step-touch-sync-done
|
||||
- maybe-restore-portaled-src-cache
|
||||
- run:
|
||||
name: Ensure src checkout worked
|
||||
command: |
|
||||
if [ ! -d "src/third_party/blink" ]; then
|
||||
echo src cache was not restored for an unknown reason
|
||||
exit 1
|
||||
fi
|
||||
- run:
|
||||
name: Wipe Electron
|
||||
command: rm -rf src/electron
|
||||
- *step-checkout-electron
|
||||
- checkout-from-cache
|
||||
- *step-setup-env-for-build
|
||||
- *step-wait-for-goma
|
||||
- *step-gn-gen-default
|
||||
- *step-gn-check
|
||||
|
||||
steps-electron-ts-compile-for-doc-change: &steps-electron-ts-compile-for-doc-change
|
||||
steps:
|
||||
@@ -994,31 +993,6 @@ steps-electron-ts-compile-for-doc-change: &steps-electron-ts-compile-for-doc-cha
|
||||
|
||||
# Command Aliases
|
||||
commands:
|
||||
install-python2-mac:
|
||||
steps:
|
||||
- restore_cache:
|
||||
keys:
|
||||
- v2.7.18-python-cache-{{ arch }}
|
||||
name: Restore python cache
|
||||
- run:
|
||||
name: Install python2 on macos
|
||||
command: |
|
||||
if [ "`uname`" == "Darwin" ] && [ "$IS_ELECTRON_RUNNER" != "1" ]; then
|
||||
if [ ! -f "python-downloads/python-2.7.18-macosx10.9.pkg" ]; then
|
||||
mkdir python-downloads
|
||||
echo 'Downloading Python 2.7.18'
|
||||
curl -O https://dev-cdn.electronjs.org/python/python-2.7.18-macosx10.9.pkg
|
||||
mv python-2.7.18-macosx10.9.pkg python-downloads
|
||||
else
|
||||
echo 'Using Python install from cache'
|
||||
fi
|
||||
sudo installer -pkg python-downloads/python-2.7.18-macosx10.9.pkg -target /
|
||||
fi
|
||||
- save_cache:
|
||||
paths:
|
||||
- python-downloads
|
||||
key: v2.7.18-python-cache-{{ arch }}
|
||||
name: Persisting python cache
|
||||
maybe-restore-portaled-src-cache:
|
||||
parameters:
|
||||
halt-if-successful:
|
||||
@@ -1315,7 +1289,6 @@ commands:
|
||||
- run: rm -rf src/electron
|
||||
- *step-restore-brew-cache
|
||||
- *step-install-gnutar-on-mac
|
||||
- install-python2-mac
|
||||
- *step-save-brew-cache
|
||||
- when:
|
||||
condition: << parameters.build >>
|
||||
@@ -1476,7 +1449,6 @@ commands:
|
||||
- *step-setup-linux-for-headless-testing
|
||||
- *step-restore-brew-cache
|
||||
- *step-fix-known-hosts-linux
|
||||
- install-python2-mac
|
||||
- *step-install-signing-cert-on-mac
|
||||
|
||||
- run:
|
||||
@@ -1586,7 +1558,6 @@ commands:
|
||||
- *step-depot-tools-get
|
||||
- *step-depot-tools-add-to-path
|
||||
- *step-restore-brew-cache
|
||||
- install-python2-mac
|
||||
- *step-get-more-space-on-mac
|
||||
- when:
|
||||
condition: << parameters.checkout >>
|
||||
|
||||
@@ -35,8 +35,13 @@ if [ ! -f $buildtools/configs/evm.testing.json ]; then
|
||||
write_config() {
|
||||
echo "
|
||||
{
|
||||
\"root\": \"/workspaces/gclient\",
|
||||
\"goma\": \"$1\",
|
||||
\"root\": \"/workspaces/gclient\",
|
||||
\"remotes\": {
|
||||
\"electron\": {
|
||||
\"origin\": \"https://github.com/electron/electron.git\"
|
||||
}
|
||||
}
|
||||
\"gen\": {
|
||||
\"args\": [
|
||||
\"import(\\\"//electron/build/args/testing.gn\\\")\",
|
||||
@@ -48,11 +53,7 @@ if [ ! -f $buildtools/configs/evm.testing.json ]; then
|
||||
\"CHROMIUM_BUILDTOOLS_PATH\": \"/workspaces/gclient/src/buildtools\",
|
||||
\"GIT_CACHE_PATH\": \"/workspaces/gclient/.git-cache\"
|
||||
},
|
||||
\"remotes\": {
|
||||
\"electron\": {
|
||||
\"origin\": \"https://github.com/electron/electron.git\"
|
||||
}
|
||||
}
|
||||
\"$schema\": \"file:///home/builduser/.electron_build_tools/evm-config.schema.json\"
|
||||
}
|
||||
" >$buildtools/configs/evm.testing.json
|
||||
}
|
||||
|
||||
2
DEPS
2
DEPS
@@ -2,7 +2,7 @@ gclient_gn_args_from = 'src'
|
||||
|
||||
vars = {
|
||||
'chromium_version':
|
||||
'110.0.5481.177',
|
||||
'110.0.5481.208',
|
||||
'node_version':
|
||||
'v18.12.1',
|
||||
'nan_version':
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
|
||||
version: 1.0.{build}
|
||||
build_cloud: electronhq-16-core
|
||||
image: e-111.0.5560.0-node18
|
||||
image: e-110.0.5481.208
|
||||
environment:
|
||||
GIT_CACHE_PATH: C:\Users\appveyor\libcc_cache
|
||||
ELECTRON_OUT_DIR: Default
|
||||
|
||||
@@ -29,7 +29,7 @@
|
||||
|
||||
version: 1.0.{build}
|
||||
build_cloud: electronhq-16-core
|
||||
image: e-110.0.5481.77
|
||||
image: e-110.0.5481.208
|
||||
environment:
|
||||
GIT_CACHE_PATH: C:\Users\appveyor\libcc_cache
|
||||
ELECTRON_OUT_DIR: Default
|
||||
@@ -83,6 +83,8 @@ for:
|
||||
Remove-Item -Recurse -Force $pwd\build-tools
|
||||
}
|
||||
- git clone --depth=1 https://chromium.googlesource.com/chromium/tools/depot_tools.git
|
||||
- ps: New-Item -Name depot_tools\.disable_auto_update -ItemType File
|
||||
- depot_tools\bootstrap\win_tools.bat
|
||||
- ps: $env:PATH="$pwd\depot_tools;$env:PATH"
|
||||
- ps: >-
|
||||
if (Test-Path -Path "$pwd\src\electron") {
|
||||
@@ -192,16 +194,28 @@ for:
|
||||
on_finish:
|
||||
# Uncomment this lines to enable RDP
|
||||
# - ps: $blockRdp = $true; iex ((new-object net.webclient).DownloadString('https://raw.githubusercontent.com/appveyor/ci/master/scripts/enable-rdp.ps1'))
|
||||
- cd C:\projects\src
|
||||
- if exist out\Default\windows_toolchain_profile.json ( appveyor-retry appveyor PushArtifact out\Default\windows_toolchain_profile.json )
|
||||
- if exist out\Default\dist.zip (appveyor-retry appveyor PushArtifact out\Default\dist.zip)
|
||||
- if exist out\Default\shell_browser_ui_unittests.exe (appveyor-retry appveyor PushArtifact out\Default\shell_browser_ui_unittests.exe)
|
||||
- if exist out\Default\chromedriver.zip (appveyor-retry appveyor PushArtifact out\Default\chromedriver.zip)
|
||||
- if exist out\ffmpeg\ffmpeg.zip (appveyor-retry appveyor PushArtifact out\ffmpeg\ffmpeg.zip)
|
||||
- if exist node_headers.zip (appveyor-retry appveyor PushArtifact node_headers.zip)
|
||||
- if exist out\Default\mksnapshot.zip (appveyor-retry appveyor PushArtifact out\Default\mksnapshot.zip)
|
||||
- if exist out\Default\hunspell_dictionaries.zip (appveyor-retry appveyor PushArtifact out\Default\hunspell_dictionaries.zip)
|
||||
- if exist out\Default\electron.lib (appveyor-retry appveyor PushArtifact out\Default\electron.lib)
|
||||
- ps: |
|
||||
cd C:\projects\src
|
||||
$missing_artifacts = $false
|
||||
$artifacts_to_upload = @('dist.zip','windows_toolchain_profile.json','shell_browser_ui_unittests.exe','chromedriver.zip','ffmpeg.zip','node_headers.zip','mksnapshot.zip','electron.lib','hunspell_dictionaries.zip')
|
||||
foreach($artifact_name in $artifacts_to_upload) {
|
||||
if ($artifact_name -eq 'ffmpeg.zip') {
|
||||
$artifact_file = "out\ffmpeg\ffmpeg.zip"
|
||||
} elseif ($artifact_name -eq 'node_headers.zip') {
|
||||
$artifact_file = $artifact_name
|
||||
} else {
|
||||
$artifact_file = "out\Default\$artifact_name"
|
||||
}
|
||||
if (Test-Path $artifact_file) {
|
||||
appveyor-retry appveyor PushArtifact $artifact_file
|
||||
} else {
|
||||
Write-warning "$artifact_name is missing and cannot be added to artifacts"
|
||||
$missing_artifacts = $true
|
||||
}
|
||||
}
|
||||
if ($missing_artifacts) {
|
||||
throw "Build failed due to missing artifacts"
|
||||
}
|
||||
- ps: >-
|
||||
if ((Test-Path "pdb.zip") -And ($env:GN_CONFIG -ne 'release')) {
|
||||
appveyor-retry appveyor PushArtifact pdb.zip
|
||||
@@ -232,7 +246,7 @@ for:
|
||||
# Download build artifacts
|
||||
$apiUrl = 'https://ci.appveyor.com/api'
|
||||
$build_info = Invoke-RestMethod -Method Get -Uri "$apiUrl/projects/$env:APPVEYOR_ACCOUNT_NAME/$env:APPVEYOR_PROJECT_SLUG/builds/$env:APPVEYOR_BUILD_ID"
|
||||
$artifacts_to_download = @('dist.zip','ffmpeg.zip','node_headers.zip','pdb.zip','electron.lib')
|
||||
$artifacts_to_download = @('dist.zip','ffmpeg.zip','node_headers.zip','electron.lib')
|
||||
foreach ($job in $build_info.build.jobs) {
|
||||
if ($job.name -eq "Build Arm on X64 Windows") {
|
||||
$jobId = $job.jobId
|
||||
@@ -244,10 +258,13 @@ for:
|
||||
}
|
||||
Invoke-RestMethod -Method Get -Uri "$apiUrl/buildjobs/$jobId/artifacts/$artifact_name" -OutFile $outfile
|
||||
}
|
||||
# Uncomment the following lines to download the pdb.zip to show real stacktraces when crashes happen during testing
|
||||
# Invoke-RestMethod -Method Get -Uri "$apiUrl/buildjobs/$jobId/artifacts/pdb.zip" -OutFile pdb.zip
|
||||
# 7z x -y -osrc pdb.zip
|
||||
}
|
||||
}
|
||||
- ps: |
|
||||
$out_default_zips = @('dist.zip','pdb.zip')
|
||||
$out_default_zips = @('dist.zip')
|
||||
foreach($zip_name in $out_default_zips) {
|
||||
7z x -y -osrc\out\Default $zip_name
|
||||
}
|
||||
|
||||
39
appveyor.yml
39
appveyor.yml
@@ -29,7 +29,7 @@
|
||||
|
||||
version: 1.0.{build}
|
||||
build_cloud: electronhq-16-core
|
||||
image: e-110.0.5481.77-node18
|
||||
image: e-110.0.5481.208
|
||||
environment:
|
||||
GIT_CACHE_PATH: C:\Users\appveyor\libcc_cache
|
||||
ELECTRON_OUT_DIR: Default
|
||||
@@ -81,6 +81,8 @@ for:
|
||||
Remove-Item -Recurse -Force $pwd\build-tools
|
||||
}
|
||||
- git clone --depth=1 https://chromium.googlesource.com/chromium/tools/depot_tools.git
|
||||
- ps: New-Item -Name depot_tools\.disable_auto_update -ItemType File
|
||||
- depot_tools\bootstrap\win_tools.bat
|
||||
- ps: $env:PATH="$pwd\depot_tools;$env:PATH"
|
||||
- ps: >-
|
||||
if (Test-Path -Path "$pwd\src\electron") {
|
||||
@@ -190,16 +192,28 @@ for:
|
||||
on_finish:
|
||||
# Uncomment this lines to enable RDP
|
||||
# - ps: $blockRdp = $true; iex ((new-object net.webclient).DownloadString('https://raw.githubusercontent.com/appveyor/ci/master/scripts/enable-rdp.ps1'))
|
||||
- cd C:\projects\src
|
||||
- if exist out\Default\windows_toolchain_profile.json ( appveyor-retry appveyor PushArtifact out\Default\windows_toolchain_profile.json )
|
||||
- if exist out\Default\dist.zip (appveyor-retry appveyor PushArtifact out\Default\dist.zip)
|
||||
- if exist out\Default\shell_browser_ui_unittests.exe (appveyor-retry appveyor PushArtifact out\Default\shell_browser_ui_unittests.exe)
|
||||
- if exist out\Default\chromedriver.zip (appveyor-retry appveyor PushArtifact out\Default\chromedriver.zip)
|
||||
- if exist out\ffmpeg\ffmpeg.zip (appveyor-retry appveyor PushArtifact out\ffmpeg\ffmpeg.zip)
|
||||
- if exist node_headers.zip (appveyor-retry appveyor PushArtifact node_headers.zip)
|
||||
- if exist out\Default\mksnapshot.zip (appveyor-retry appveyor PushArtifact out\Default\mksnapshot.zip)
|
||||
- if exist out\Default\hunspell_dictionaries.zip (appveyor-retry appveyor PushArtifact out\Default\hunspell_dictionaries.zip)
|
||||
- if exist out\Default\electron.lib (appveyor-retry appveyor PushArtifact out\Default\electron.lib)
|
||||
- ps: |
|
||||
cd C:\projects\src
|
||||
$missing_artifacts = $false
|
||||
$artifacts_to_upload = @('dist.zip','windows_toolchain_profile.json','shell_browser_ui_unittests.exe','chromedriver.zip','ffmpeg.zip','node_headers.zip','mksnapshot.zip','electron.lib','hunspell_dictionaries.zip')
|
||||
foreach($artifact_name in $artifacts_to_upload) {
|
||||
if ($artifact_name -eq 'ffmpeg.zip') {
|
||||
$artifact_file = "out\ffmpeg\ffmpeg.zip"
|
||||
} elseif ($artifact_name -eq 'node_headers.zip') {
|
||||
$artifact_file = $artifact_name
|
||||
} else {
|
||||
$artifact_file = "out\Default\$artifact_name"
|
||||
}
|
||||
if (Test-Path $artifact_file) {
|
||||
appveyor-retry appveyor PushArtifact $artifact_file
|
||||
} else {
|
||||
Write-warning "$artifact_name is missing and cannot be added to artifacts"
|
||||
$missing_artifacts = $true
|
||||
}
|
||||
}
|
||||
if ($missing_artifacts) {
|
||||
throw "Build failed due to missing artifacts"
|
||||
}
|
||||
- ps: >-
|
||||
if ((Test-Path "pdb.zip") -And ($env:GN_CONFIG -ne 'release')) {
|
||||
appveyor-retry appveyor PushArtifact pdb.zip
|
||||
@@ -240,6 +254,9 @@ for:
|
||||
}
|
||||
Invoke-RestMethod -Method Get -Uri "$apiUrl/buildjobs/$jobId/artifacts/$artifact_name" -OutFile $outfile
|
||||
}
|
||||
# Uncomment the following lines to download the pdb.zip to show real stacktraces when crashes happen during testing
|
||||
# Invoke-RestMethod -Method Get -Uri "$apiUrl/buildjobs/$jobId/artifacts/pdb.zip" -OutFile pdb.zip
|
||||
# 7z x -y -osrc pdb.zip
|
||||
}
|
||||
}
|
||||
- ps: |
|
||||
|
||||
@@ -23,8 +23,7 @@ The `app` object emits the following events:
|
||||
Emitted when the application has finished basic startup. On Windows and Linux,
|
||||
the `will-finish-launching` event is the same as the `ready` event; on macOS,
|
||||
this event represents the `applicationWillFinishLaunching` notification of
|
||||
`NSApplication`. You would usually set up listeners for the `open-file` and
|
||||
`open-url` events here, and start the crash reporter and auto updater.
|
||||
`NSApplication`.
|
||||
|
||||
In most cases, you should do everything in the `ready` event handler.
|
||||
|
||||
@@ -128,8 +127,6 @@ Emitted when the user wants to open a URL with the application. Your application
|
||||
`Info.plist` file must define the URL scheme within the `CFBundleURLTypes` key, and
|
||||
set `NSPrincipalClass` to `AtomApplication`.
|
||||
|
||||
You should call `event.preventDefault()` if you want to handle this event.
|
||||
|
||||
As with the `open-file` event, be sure to register a listener for the `open-url`
|
||||
event early in your application startup to detect if the the application being
|
||||
is being opened to handle a URL. If you register the listener in response to a
|
||||
@@ -754,14 +751,21 @@ This API can be used for purposes such as deciding what language to present the
|
||||
|
||||
Here are some examples of return values of the various language and locale APIs with different configurations:
|
||||
|
||||
* For Windows, where the application locale is German, the regional format is Finnish (Finland), and the preferred system languages from most to least preferred are French (Canada), English (US), Simplified Chinese (China), Finnish, and Spanish (Latin America):
|
||||
* `app.getLocale()` returns `'de'`
|
||||
* `app.getSystemLocale()` returns `'fi-FI'`
|
||||
* `app.getPreferredSystemLanguages()` returns `['fr-CA', 'en-US', 'zh-Hans-CN', 'fi', 'es-419']`
|
||||
* On macOS, where the application locale is German, the region is Finland, and the preferred system languages from most to least preferred are French (Canada), English (US), Simplified Chinese, and Spanish (Latin America):
|
||||
* `app.getLocale()` returns `'de'`
|
||||
* `app.getSystemLocale()` returns `'fr-FI'`
|
||||
* `app.getPreferredSystemLanguages()` returns `['fr-CA', 'en-US', 'zh-Hans-FI', 'es-419']`
|
||||
On Windows, given application locale is German, the regional format is Finnish (Finland), and the preferred system languages from most to least preferred are French (Canada), English (US), Simplified Chinese (China), Finnish, and Spanish (Latin America):
|
||||
|
||||
```js
|
||||
app.getLocale() // 'de'
|
||||
app.getSystemLocale() // 'fi-FI'
|
||||
app.getPreferredSystemLanguages() // ['fr-CA', 'en-US', 'zh-Hans-CN', 'fi', 'es-419']
|
||||
```
|
||||
|
||||
On macOS, given the application locale is German, the region is Finland, and the preferred system languages from most to least preferred are French (Canada), English (US), Simplified Chinese, and Spanish (Latin America):
|
||||
|
||||
```js
|
||||
app.getLocale() // 'de'
|
||||
app.getSystemLocale() // 'fr-FI'
|
||||
app.getPreferredSystemLanguages() // ['fr-CA', 'en-US', 'zh-Hans-FI', 'es-419']
|
||||
```
|
||||
|
||||
Both the available languages and regions and the possible return values differ between the two operating systems.
|
||||
|
||||
@@ -1513,18 +1517,18 @@ dock on macOS.
|
||||
|
||||
A `boolean` property that returns `true` if the app is packaged, `false` otherwise. For many apps, this property can be used to distinguish development and production environments.
|
||||
|
||||
[tasks]:https://msdn.microsoft.com/en-us/library/windows/desktop/dd378460(v=vs.85).aspx#tasks
|
||||
[app-user-model-id]: https://msdn.microsoft.com/en-us/library/windows/desktop/dd378459(v=vs.85).aspx
|
||||
[tasks]:https://learn.microsoft.com/en-us/windows/win32/shell/taskbar-extensions#tasks
|
||||
[app-user-model-id]: https://learn.microsoft.com/en-us/windows/win32/shell/appids
|
||||
[electron-forge]: https://www.electronforge.io/
|
||||
[electron-packager]: https://github.com/electron/electron-packager
|
||||
[CFBundleURLTypes]: https://developer.apple.com/library/ios/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html#//apple_ref/doc/uid/TP40009249-102207-TPXREF115
|
||||
[LSCopyDefaultHandlerForURLScheme]: https://developer.apple.com/library/mac/documentation/Carbon/Reference/LaunchServicesReference/#//apple_ref/c/func/LSCopyDefaultHandlerForURLScheme
|
||||
[LSCopyDefaultHandlerForURLScheme]: https://developer.apple.com/documentation/coreservices/1441725-lscopydefaulthandlerforurlscheme?language=objc
|
||||
[handoff]: https://developer.apple.com/library/ios/documentation/UserExperience/Conceptual/Handoff/HandoffFundamentals/HandoffFundamentals.html
|
||||
[activity-type]: https://developer.apple.com/library/ios/documentation/Foundation/Reference/NSUserActivity_Class/index.html#//apple_ref/occ/instp/NSUserActivity/activityType
|
||||
[unity-requirement]: https://help.ubuntu.com/community/UnityLaunchersAndDesktopFiles#Adding_shortcuts_to_a_launcher
|
||||
[mas-builds]: ../tutorial/mac-app-store-submission-guide.md
|
||||
[Squirrel-Windows]: https://github.com/Squirrel/Squirrel.Windows
|
||||
[JumpListBeginListMSDN]: https://msdn.microsoft.com/en-us/library/windows/desktop/dd378398(v=vs.85).aspx
|
||||
[JumpListBeginListMSDN]: https://learn.microsoft.com/en-us/windows/win32/api/shobjidl_core/nf-shobjidl_core-icustomdestinationlist-beginlist
|
||||
[about-panel-options]: https://developer.apple.com/reference/appkit/nsapplication/1428479-orderfrontstandardaboutpanelwith?language=objc
|
||||
|
||||
### `app.name`
|
||||
|
||||
@@ -140,5 +140,5 @@ application starts.
|
||||
[installer]: https://github.com/electron/grunt-electron-installer
|
||||
[installer-lib]: https://github.com/electron/windows-installer
|
||||
[electron-forge-lib]: https://github.com/electron/forge
|
||||
[app-user-model-id]: https://msdn.microsoft.com/en-us/library/windows/desktop/dd378459(v=vs.85).aspx
|
||||
[app-user-model-id]: https://learn.microsoft.com/en-us/windows/win32/shell/appids
|
||||
[event-emitter]: https://nodejs.org/api/events.html#events_class_eventemitter
|
||||
|
||||
@@ -629,7 +629,7 @@ Returns:
|
||||
* `event` Event
|
||||
* `command` string
|
||||
|
||||
Emitted when an [App Command](https://msdn.microsoft.com/en-us/library/windows/desktop/ms646275(v=vs.85).aspx)
|
||||
Emitted when an [App Command](https://learn.microsoft.com/en-us/windows/win32/inputdev/wm-appcommand)
|
||||
is invoked. These are typically related to keyboard media keys or browser
|
||||
commands, as well as the "Back" button built into some mice on Windows.
|
||||
|
||||
@@ -954,7 +954,7 @@ Hides the window.
|
||||
|
||||
#### `win.isVisible()`
|
||||
|
||||
Returns `boolean` - Whether the window is visible to the user.
|
||||
Returns `boolean` - Whether the window is visible to the user in the foreground of the app.
|
||||
|
||||
#### `win.isModal()`
|
||||
|
||||
@@ -992,6 +992,8 @@ Returns `boolean` - Whether the window is minimized.
|
||||
|
||||
Sets whether the window should be in fullscreen mode.
|
||||
|
||||
**Note:** On macOS, fullscreen transitions take place asynchronously. If further actions depend on the fullscreen state, use the ['enter-full-screen'](browser-window.md#event-enter-full-screen) or ['leave-full-screen'](browser-window.md#event-leave-full-screen) events.
|
||||
|
||||
#### `win.isFullScreen()`
|
||||
|
||||
Returns `boolean` - Whether the window is in fullscreen mode.
|
||||
@@ -1657,13 +1659,13 @@ in the taskbar.
|
||||
#### `win.setAppDetails(options)` _Windows_
|
||||
|
||||
* `options` Object
|
||||
* `appId` string (optional) - Window's [App User Model ID](https://msdn.microsoft.com/en-us/library/windows/desktop/dd391569(v=vs.85).aspx).
|
||||
* `appId` string (optional) - Window's [App User Model ID](https://learn.microsoft.com/en-us/windows/win32/shell/appids).
|
||||
It has to be set, otherwise the other options will have no effect.
|
||||
* `appIconPath` string (optional) - Window's [Relaunch Icon](https://msdn.microsoft.com/en-us/library/windows/desktop/dd391573(v=vs.85).aspx).
|
||||
* `appIconPath` string (optional) - Window's [Relaunch Icon](https://learn.microsoft.com/en-us/windows/win32/properties/props-system-appusermodel-relaunchiconresource).
|
||||
* `appIconIndex` Integer (optional) - Index of the icon in `appIconPath`.
|
||||
Ignored when `appIconPath` is not set. Default is `0`.
|
||||
* `relaunchCommand` string (optional) - Window's [Relaunch Command](https://msdn.microsoft.com/en-us/library/windows/desktop/dd391571(v=vs.85).aspx).
|
||||
* `relaunchDisplayName` string (optional) - Window's [Relaunch Display Name](https://msdn.microsoft.com/en-us/library/windows/desktop/dd391572(v=vs.85).aspx).
|
||||
* `relaunchCommand` string (optional) - Window's [Relaunch Command](https://learn.microsoft.com/en-us/windows/win32/properties/props-system-appusermodel-relaunchcommand).
|
||||
* `relaunchDisplayName` string (optional) - Window's [Relaunch Display Name](https://learn.microsoft.com/en-us/windows/win32/properties/props-system-appusermodel-relaunchdisplaynameresource).
|
||||
|
||||
Sets the properties for the window's taskbar button.
|
||||
|
||||
|
||||
@@ -78,6 +78,7 @@ The following methods are available on instances of `Cookies`:
|
||||
* `path` string (optional) - Retrieves cookies whose path matches `path`.
|
||||
* `secure` boolean (optional) - Filters cookies by their Secure property.
|
||||
* `session` boolean (optional) - Filters out session or persistent cookies.
|
||||
* `httpOnly` boolean (optional) - Filters cookies by httpOnly.
|
||||
|
||||
Returns `Promise<Cookie[]>` - A promise which resolves an array of cookie objects.
|
||||
|
||||
|
||||
@@ -223,10 +223,10 @@ expanding and collapsing the dialog.
|
||||
* `browserWindow` [BrowserWindow](browser-window.md) (optional)
|
||||
* `options` Object
|
||||
* `message` string - Content of the message box.
|
||||
* `type` string (optional) - Can be `"none"`, `"info"`, `"error"`, `"question"` or
|
||||
`"warning"`. On Windows, `"question"` displays the same icon as `"info"`, unless
|
||||
you set an icon using the `"icon"` option. On macOS, both `"warning"` and
|
||||
`"error"` display the same warning icon.
|
||||
* `type` string (optional) - Can be `none`, `info`, `error`, `question` or
|
||||
`warning`. On Windows, `question` displays the same icon as `info`, unless
|
||||
you set an icon using the `icon` option. On macOS, both `warning` and
|
||||
`error` display the same warning icon.
|
||||
* `buttons` string[] (optional) - Array of texts for buttons. On Windows, an empty array
|
||||
will result in one button labeled "OK".
|
||||
* `defaultId` Integer (optional) - Index of the button in the buttons array which will
|
||||
@@ -266,10 +266,10 @@ If `browserWindow` is not shown dialog will not be attached to it. In such case
|
||||
* `browserWindow` [BrowserWindow](browser-window.md) (optional)
|
||||
* `options` Object
|
||||
* `message` string - Content of the message box.
|
||||
* `type` string (optional) - Can be `"none"`, `"info"`, `"error"`, `"question"` or
|
||||
`"warning"`. On Windows, `"question"` displays the same icon as `"info"`, unless
|
||||
you set an icon using the `"icon"` option. On macOS, both `"warning"` and
|
||||
`"error"` display the same warning icon.
|
||||
* `type` string (optional) - Can be `none`, `info`, `error`, `question` or
|
||||
`warning`. On Windows, `question` displays the same icon as `info`, unless
|
||||
you set an icon using the `icon` option. On macOS, both `warning` and
|
||||
`error` display the same warning icon.
|
||||
* `buttons` string[] (optional) - Array of texts for buttons. On Windows, an empty array
|
||||
will result in one button labeled "OK".
|
||||
* `defaultId` Integer (optional) - Index of the button in the buttons array which will
|
||||
|
||||
@@ -49,7 +49,7 @@ quality, it is recommended to include at least the following sizes in the:
|
||||
|
||||
Check the *Size requirements* section in [this article][icons].
|
||||
|
||||
[icons]:https://msdn.microsoft.com/en-us/library/windows/desktop/dn742485(v=vs.85).aspx
|
||||
[icons]: https://learn.microsoft.com/en-us/windows/win32/uxguide/vis-icons
|
||||
|
||||
## High Resolution Image
|
||||
|
||||
|
||||
@@ -4,9 +4,12 @@
|
||||
|
||||
Process: [Main](../glossary.md#main-process)
|
||||
|
||||
## Using in the renderer process
|
||||
:::info Renderer process notifications
|
||||
|
||||
If you want to show Notifications from a renderer process you should use the [HTML5 Notification API](../tutorial/notifications.md)
|
||||
If you want to show notifications from a renderer process you should use the
|
||||
[web Notifications API](../tutorial/notifications.md)
|
||||
|
||||
:::
|
||||
|
||||
## Class: Notification
|
||||
|
||||
@@ -29,10 +32,10 @@ Returns `boolean` - Whether or not desktop notifications are supported on the cu
|
||||
### `new Notification([options])`
|
||||
|
||||
* `options` Object (optional)
|
||||
* `title` string (optional) - A title for the notification, which will be shown at the top of the notification window when it is shown.
|
||||
* `title` string (optional) - A title for the notification, which will be displayed at the top of the notification window when it is shown.
|
||||
* `subtitle` string (optional) _macOS_ - A subtitle for the notification, which will be displayed below the title.
|
||||
* `body` string (optional) - The body text of the notification, which will be displayed below the title or subtitle.
|
||||
* `silent` boolean (optional) - Whether or not to emit an OS notification noise when showing the notification.
|
||||
* `silent` boolean (optional) - Whether or not to suppress the OS notification noise when showing the notification.
|
||||
* `icon` (string | [NativeImage](native-image.md)) (optional) - An icon to use in the notification.
|
||||
* `hasReply` boolean (optional) _macOS_ - Whether or not to add an inline reply option to the notification.
|
||||
* `timeoutType` string (optional) _Linux_ _Windows_ - The timeout duration of the notification. Can be 'default' or 'never'.
|
||||
@@ -47,8 +50,11 @@ Returns `boolean` - Whether or not desktop notifications are supported on the cu
|
||||
|
||||
Objects created with `new Notification` emit the following events:
|
||||
|
||||
**Note:** Some events are only available on specific operating systems and are
|
||||
labeled as such.
|
||||
:::info
|
||||
|
||||
Some events are only available on specific operating systems and are labeled as such.
|
||||
|
||||
:::
|
||||
|
||||
#### Event: 'show'
|
||||
|
||||
@@ -56,7 +62,7 @@ Returns:
|
||||
|
||||
* `event` Event
|
||||
|
||||
Emitted when the notification is shown to the user, note this could be fired
|
||||
Emitted when the notification is shown to the user. Note that this event can be fired
|
||||
multiple times as a notification can be shown multiple times through the
|
||||
`show()` method.
|
||||
|
||||
@@ -106,14 +112,13 @@ Emitted when an error is encountered while creating and showing the native notif
|
||||
|
||||
### Instance Methods
|
||||
|
||||
Objects created with `new Notification` have the following instance methods:
|
||||
Objects created with the `new Notification()` constructor have the following instance methods:
|
||||
|
||||
#### `notification.show()`
|
||||
|
||||
Immediately shows the notification to the user, please note this means unlike the
|
||||
HTML5 Notification implementation, instantiating a `new Notification` does
|
||||
not immediately show it to the user, you need to call this method before the OS
|
||||
will display it.
|
||||
Immediately shows the notification to the user. Unlike the web notification API,
|
||||
instantiating a `new Notification()` does not immediately show it to the user. Instead, you need to
|
||||
call this method before the OS will display it.
|
||||
|
||||
If the notification has been shown before, this method will dismiss the previously
|
||||
shown notification and create a new one with identical properties.
|
||||
@@ -160,7 +165,7 @@ A `boolean` property representing whether the notification has a reply action.
|
||||
|
||||
A `string` property representing the urgency level of the notification. Can be 'normal', 'critical', or 'low'.
|
||||
|
||||
Default is 'low' - see [NotifyUrgency](https://developer.gnome.org/notification-spec/#urgency-levels) for more information.
|
||||
Default is 'low' - see [NotifyUrgency](https://developer-old.gnome.org/notification-spec/#urgency-levels) for more information.
|
||||
|
||||
#### `notification.timeoutType` _Linux_ _Windows_
|
||||
|
||||
|
||||
@@ -39,7 +39,7 @@ The `pushNotification` module has the following methods:
|
||||
|
||||
Returns `Promise<string>`
|
||||
|
||||
Registers the app with Apple Push Notification service (APNS) to receive [Badge, Sound, and Alert](https://developer.apple.com/documentation/appkit/sremotenotificationtype?language=objc) notifications. If registration is successful, the promise will be resolved with the APNS device token. Otherwise, the promise will be rejected with an error message.
|
||||
Registers the app with Apple Push Notification service (APNS) to receive [Badge, Sound, and Alert](https://developer.apple.com/documentation/appkit/nsremotenotificationtype?language=objc) notifications. If registration is successful, the promise will be resolved with the APNS device token. Otherwise, the promise will be rejected with an error message.
|
||||
See: https://developer.apple.com/documentation/appkit/nsapplication/1428476-registerforremotenotificationtyp?language=objc
|
||||
|
||||
### `pushNotifications.unregisterForAPNSNotifications()` _macOS_
|
||||
|
||||
@@ -879,6 +879,10 @@ session.fromPartition('some-partition').setPermissionCheckHandler((webContents,
|
||||
Specifying a loopback device will capture system audio, and is
|
||||
currently only supported on Windows. If a WebFrameMain is specified,
|
||||
will capture audio from that frame.
|
||||
* `enableLocalEcho` Boolean (optional) - If `audio` is a [WebFrameMain](web-frame-main.md)
|
||||
and this is set to `true`, then local playback of audio will not be muted (e.g. using `MediaRecorder`
|
||||
to record `WebFrameMain` with this flag set to `true` will allow audio to pass through to the speakers
|
||||
while recording). Default is `false`.
|
||||
|
||||
This handler will be called when web content requests access to display media
|
||||
via the `navigator.mediaDevices.getDisplayMedia` API. Use the
|
||||
@@ -916,7 +920,7 @@ Passing `null` instead of a function resets the handler to its default state.
|
||||
* `details` Object
|
||||
* `deviceType` string - The type of device that permission is being requested on, can be `hid`, `serial`, or `usb`.
|
||||
* `origin` string - The origin URL of the device permission check.
|
||||
* `device` [HIDDevice](structures/hid-device.md) | [SerialPort](structures/serial-port.md)- the device that permission is being requested for.
|
||||
* `device` [HIDDevice](structures/hid-device.md) | [SerialPort](structures/serial-port.md) | [USBDevice](structures/usb-device.md) - the device that permission is being requested for.
|
||||
|
||||
Sets the handler which can be used to respond to device permission checks for the `session`.
|
||||
Returning `true` will allow the device to be permitted and `false` will reject it.
|
||||
|
||||
@@ -3,9 +3,9 @@
|
||||
* `processId` Integer - The internal ID of the renderer process that sent this message
|
||||
* `frameId` Integer - The ID of the renderer frame that sent this message
|
||||
* `returnValue` any - Set this to the value to be returned in a synchronous message
|
||||
* `sender` WebContents - Returns the `webContents` that sent the message
|
||||
* `senderFrame` WebFrameMain _Readonly_ - The frame that sent this message
|
||||
* `ports` MessagePortMain[] - A list of MessagePorts that were transferred with this message
|
||||
* `sender` [WebContents](../web-contents.md) - Returns the `webContents` that sent the message
|
||||
* `senderFrame` [WebFrameMain](../web-frame-main.md) _Readonly_ - The frame that sent this message
|
||||
* `ports` [MessagePortMain](../message-port-main.md)[] - A list of MessagePorts that were transferred with this message
|
||||
* `reply` Function - A function that will send an IPC message to the renderer frame that sent the original message that you are currently handling. You should use this method to "reply" to the sent message in order to guarantee the reply will go to the correct process and frame.
|
||||
* `channel` string
|
||||
* `...args` any[]
|
||||
|
||||
@@ -2,5 +2,5 @@
|
||||
|
||||
* `processId` Integer - The internal ID of the renderer process that sent this message
|
||||
* `frameId` Integer - The ID of the renderer frame that sent this message
|
||||
* `sender` WebContents - Returns the `webContents` that sent the message
|
||||
* `senderFrame` WebFrameMain _Readonly_ - The frame that sent this message
|
||||
* `sender` [WebContents](../web-contents.md) - Returns the `webContents` that sent the message
|
||||
* `senderFrame` [WebFrameMain](../web-frame-main.md) _Readonly_ - The frame that sent this message
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
# IpcRendererEvent Object extends `Event`
|
||||
|
||||
* `sender` IpcRenderer - The `IpcRenderer` instance that emitted the event originally
|
||||
* `sender` [IpcRenderer](../ipc-renderer.md) - The `IpcRenderer` instance that emitted the event originally
|
||||
* `senderId` Integer - The `webContents.id` that sent the message, you can call `event.sender.sendTo(event.senderId, ...)` to reply to the message, see [ipcRenderer.sendTo][ipc-renderer-sendto] for more information. This only applies to messages sent from a different renderer. Messages sent directly from the main process set `event.senderId` to `0`.
|
||||
* `ports` MessagePort[] - A list of MessagePorts that were transferred with this message
|
||||
* `ports` [MessagePort][][] - A list of MessagePorts that were transferred with this message
|
||||
|
||||
[ipc-renderer-sendto]: ../ipc-renderer.md#ipcrenderersendtowebcontentsid-channel-args
|
||||
[MessagePort]: https://developer.mozilla.org/en-US/docs/Web/API/MessagePort
|
||||
|
||||
@@ -235,7 +235,7 @@ if (browserOptions.transparent) {
|
||||
}
|
||||
```
|
||||
|
||||
[dwm-composition]:https://msdn.microsoft.com/en-us/library/windows/desktop/aa969540.aspx
|
||||
[dwm-composition]: https://learn.microsoft.com/en-us/windows/win32/dwm/composition-ovw
|
||||
|
||||
### `systemPreferences.getAccentColor()` _Windows_ _macOS_
|
||||
|
||||
@@ -336,8 +336,8 @@ See the [Windows docs][windows-colors] and the [macOS docs][macos-colors] for mo
|
||||
|
||||
The following colors are only available on macOS 10.14: `find-highlight`, `selected-content-background`, `separator`, `unemphasized-selected-content-background`, `unemphasized-selected-text-background`, and `unemphasized-selected-text`.
|
||||
|
||||
[windows-colors]:https://msdn.microsoft.com/en-us/library/windows/desktop/ms724371(v=vs.85).aspx
|
||||
[macos-colors]:https://developer.apple.com/design/human-interface-guidelines/macos/visual-design/color#dynamic-system-colors
|
||||
[windows-colors]: https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-getsyscolor
|
||||
[macos-colors]: https://developer.apple.com/design/human-interface-guidelines/macos/visual-design/color#dynamic-system-colors
|
||||
|
||||
### `systemPreferences.getSystemColor(color)` _macOS_
|
||||
|
||||
|
||||
@@ -35,28 +35,28 @@ for all windows, webviews, opened devtools, and devtools extension background pa
|
||||
|
||||
### `webContents.getFocusedWebContents()`
|
||||
|
||||
Returns `WebContents` | null - The web contents that is focused in this application, otherwise
|
||||
Returns `WebContents | null` - The web contents that is focused in this application, otherwise
|
||||
returns `null`.
|
||||
|
||||
### `webContents.fromId(id)`
|
||||
|
||||
* `id` Integer
|
||||
|
||||
Returns `WebContents` | undefined - A WebContents instance with the given ID, or
|
||||
Returns `WebContents | undefined` - A WebContents instance with the given ID, or
|
||||
`undefined` if there is no WebContents associated with the given ID.
|
||||
|
||||
### `webContents.fromFrame(frame)`
|
||||
|
||||
* `frame` WebFrameMain
|
||||
|
||||
Returns `WebContents` | undefined - A WebContents instance with the given WebFrameMain, or
|
||||
Returns `WebContents | undefined` - A WebContents instance with the given WebFrameMain, or
|
||||
`undefined` if there is no WebContents associated with the given WebFrameMain.
|
||||
|
||||
### `webContents.fromDevToolsTargetId(targetId)`
|
||||
|
||||
* `targetId` string - The Chrome DevTools Protocol [TargetID](https://chromedevtools.github.io/devtools-protocol/tot/Target/#type-TargetID) associated with the WebContents instance.
|
||||
|
||||
Returns `WebContents` | undefined - A WebContents instance with the given TargetID, or
|
||||
Returns `WebContents | undefined` - A WebContents instance with the given TargetID, or
|
||||
`undefined` if there is no WebContents associated with the given TargetID.
|
||||
|
||||
When communicating with the [Chrome DevTools Protocol](https://chromedevtools.github.io/devtools-protocol/),
|
||||
@@ -713,20 +713,24 @@ Returns:
|
||||
* `callback` Function
|
||||
* `deviceId` string
|
||||
|
||||
Emitted when bluetooth device needs to be selected on call to
|
||||
`navigator.bluetooth.requestDevice`. To use `navigator.bluetooth` api
|
||||
`webBluetooth` should be enabled. If `event.preventDefault` is not called,
|
||||
first available device will be selected. `callback` should be called with
|
||||
`deviceId` to be selected, passing empty string to `callback` will
|
||||
cancel the request.
|
||||
Emitted when a bluetooth device needs to be selected when a call to
|
||||
`navigator.bluetooth.requestDevice` is made. `callback` should be called with
|
||||
the `deviceId` of the device to be selected. Passing an empty string to
|
||||
`callback` will cancel the request.
|
||||
|
||||
If no event listener is added for this event, all bluetooth requests will be cancelled.
|
||||
If an event listener is not added for this event, or if `event.preventDefault`
|
||||
is not called when handling this event, the first available device will be
|
||||
automatically selected.
|
||||
|
||||
```javascript
|
||||
Due to the nature of bluetooth, scanning for devices when
|
||||
`navigator.bluetooth.requestDevice` is called may take time and will cause
|
||||
`select-bluetooth-device` to fire multiple times until `callback` is called
|
||||
with either a device id or an empty string to cancel the request.
|
||||
|
||||
```javascript title='main.js'
|
||||
const { app, BrowserWindow } = require('electron')
|
||||
|
||||
let win = null
|
||||
app.commandLine.appendSwitch('enable-experimental-web-platform-features')
|
||||
|
||||
app.whenReady().then(() => {
|
||||
win = new BrowserWindow({ width: 800, height: 600 })
|
||||
@@ -736,6 +740,9 @@ app.whenReady().then(() => {
|
||||
return device.deviceName === 'test'
|
||||
})
|
||||
if (!result) {
|
||||
// The device wasn't found so we need to either wait longer (eg until the
|
||||
// device is turned on) or cancel the request by calling the callback
|
||||
// with an empty string.
|
||||
callback('')
|
||||
} else {
|
||||
callback(result.deviceId)
|
||||
@@ -1567,7 +1574,7 @@ ipcMain.on('open-devtools', (event, targetContentsId, devtoolsContentsId) => {
|
||||
|
||||
An example of showing devtools in a `BrowserWindow`:
|
||||
|
||||
```js
|
||||
```js title='main.js'
|
||||
const { app, BrowserWindow } = require('electron')
|
||||
|
||||
let win = null
|
||||
@@ -1650,40 +1657,14 @@ Algorithm][SCA], just like [`postMessage`][], so prototype chains will not be
|
||||
included. Sending Functions, Promises, Symbols, WeakMaps, or WeakSets will
|
||||
throw an exception.
|
||||
|
||||
> **NOTE**: Sending non-standard JavaScript types such as DOM objects or
|
||||
> special Electron objects will throw an exception.
|
||||
:::warning
|
||||
|
||||
The renderer process can handle the message by listening to `channel` with the
|
||||
[`ipcRenderer`](ipc-renderer.md) module.
|
||||
Sending non-standard JavaScript types such as DOM objects or
|
||||
special Electron objects will throw an exception.
|
||||
|
||||
An example of sending messages from the main process to the renderer process:
|
||||
:::
|
||||
|
||||
```javascript
|
||||
// In the main process.
|
||||
const { app, BrowserWindow } = require('electron')
|
||||
let win = null
|
||||
|
||||
app.whenReady().then(() => {
|
||||
win = new BrowserWindow({ width: 800, height: 600 })
|
||||
win.loadURL(`file://${__dirname}/index.html`)
|
||||
win.webContents.on('did-finish-load', () => {
|
||||
win.webContents.send('ping', 'whoooooooh!')
|
||||
})
|
||||
})
|
||||
```
|
||||
|
||||
```html
|
||||
<!-- index.html -->
|
||||
<html>
|
||||
<body>
|
||||
<script>
|
||||
require('electron').ipcRenderer.on('ping', (event, message) => {
|
||||
console.log(message) // Prints 'whoooooooh!'
|
||||
})
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
```
|
||||
For additional reading, refer to [Electron's IPC guide](../tutorial/ipc.md).
|
||||
|
||||
#### `contents.sendToFrame(frameId, channel, ...args)`
|
||||
|
||||
|
||||
@@ -184,6 +184,8 @@ page is loaded, use the `setUserAgent` method to change the user agent.
|
||||
A `boolean`. When this attribute is present the guest page will have web security disabled.
|
||||
Web security is enabled by default.
|
||||
|
||||
This value can only be modified before the first navigation.
|
||||
|
||||
### `partition`
|
||||
|
||||
```html
|
||||
|
||||
@@ -154,6 +154,39 @@ webContents.setWindowOpenHandler((details) => {
|
||||
})
|
||||
```
|
||||
|
||||
### Removed: `<webview>` `new-window` event
|
||||
|
||||
The `new-window` event of `<webview>` has been removed. There is no direct replacement.
|
||||
|
||||
```js
|
||||
// Removed in Electron 22
|
||||
webview.addEventListener('new-window', (event) => {})
|
||||
```
|
||||
|
||||
```javascript fiddle='docs/fiddles/ipc/webview-new-window'
|
||||
// Replace with
|
||||
|
||||
// main.js
|
||||
mainWindow.webContents.on('did-attach-webview', (event, wc) => {
|
||||
wc.setWindowOpenHandler((details) => {
|
||||
mainWindow.webContents.send('webview-new-window', wc.id, details)
|
||||
return { action: 'deny' }
|
||||
})
|
||||
})
|
||||
|
||||
// preload.js
|
||||
const { ipcRenderer } = require('electron')
|
||||
ipcRenderer.on('webview-new-window', (e, webContentsId, details) => {
|
||||
console.log('webview-new-window', webContentsId, details)
|
||||
document.getElementById('webview').dispatchEvent(new Event('new-window'))
|
||||
})
|
||||
|
||||
// renderer.js
|
||||
document.getElementById('webview').addEventListener('new-window', () => {
|
||||
console.log('got new-window event')
|
||||
})
|
||||
```
|
||||
|
||||
### Deprecated: BrowserWindow `scroll-touch-*` events
|
||||
|
||||
The `scroll-touch-begin`, `scroll-touch-end` and `scroll-touch-edge` events on
|
||||
|
||||
@@ -158,7 +158,7 @@ We will need to create a new TypeScript file in the path that follows:
|
||||
|
||||
`"lib/browser/api/{electron_browser_{api_name}}.ts"`
|
||||
|
||||
An example of the contents of this file can be found [here](https://github.com/electron/electron/blob/main/lib/browser/api/native-image.ts).
|
||||
An example of the contents of this file can be found [here](https://github.com/electron/electron/blob/main/lib/browser/api/native-theme.ts).
|
||||
|
||||
### Expose your module to TypeScript
|
||||
|
||||
|
||||
@@ -89,7 +89,7 @@ For an introduction to ProcMon's basic and advanced debugging features, go check
|
||||
out [this video tutorial][procmon-instructions] provided by Microsoft.
|
||||
|
||||
[sys-internals]: https://technet.microsoft.com/en-us/sysinternals/processmonitor.aspx
|
||||
[procmon-instructions]: https://channel9.msdn.com/shows/defrag-tools/defrag-tools-4-process-monitor
|
||||
[procmon-instructions]: https://learn.microsoft.com/en-us/shows/defrag-tools/4-process-monitor
|
||||
|
||||
## Using WinDbg
|
||||
<!-- TODO(@codebytere): add images and more information here? -->
|
||||
|
||||
@@ -60,7 +60,7 @@ garbage collected.
|
||||
If you encounter this problem, the following articles may prove helpful:
|
||||
|
||||
* [Memory Management][memory-management]
|
||||
* [Variable Scope][variable-scope]
|
||||
* [Closures][closures]
|
||||
|
||||
If you want a quick fix, you can make the variables global by changing your
|
||||
code from this:
|
||||
@@ -153,8 +153,7 @@ The effect is visible only on (some?) LCD screens. Even if you don't see a diffe
|
||||
Notice that just setting the background in the CSS does not have the desired effect.
|
||||
|
||||
[memory-management]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Memory_Management
|
||||
[variable-scope]: https://msdn.microsoft.com/library/bzt2dkta(v=vs.94).aspx
|
||||
[electron-module]: https://www.npmjs.com/package/electron
|
||||
[closures]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Closures
|
||||
[storage]: https://developer.mozilla.org/en-US/docs/Web/API/Storage
|
||||
[local-storage]: https://developer.mozilla.org/en-US/docs/Web/API/Window/localStorage
|
||||
[session-storage]: https://developer.mozilla.org/en-US/docs/Web/API/Window/sessionStorage
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
<h1>Web Bluetooth API</h1>
|
||||
|
||||
<button id="clickme">Test Bluetooth</button>
|
||||
<button id="cancel">Cancel Bluetooth Request</button>
|
||||
|
||||
<p>Currently selected bluetooth device: <strong id="device-name""></strong></p>
|
||||
|
||||
|
||||
@@ -1,22 +1,37 @@
|
||||
const {app, BrowserWindow, ipcMain} = require('electron')
|
||||
const path = require('path')
|
||||
|
||||
let bluetoothPinCallback
|
||||
let selectBluetoothCallback
|
||||
|
||||
function createWindow () {
|
||||
const mainWindow = new BrowserWindow({
|
||||
width: 800,
|
||||
height: 600,
|
||||
webPreferences: {
|
||||
preload: path.join(__dirname, 'preload.js')
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
mainWindow.webContents.on('select-bluetooth-device', (event, deviceList, callback) => {
|
||||
event.preventDefault()
|
||||
if (deviceList && deviceList.length > 0) {
|
||||
callback(deviceList[0].deviceId)
|
||||
}
|
||||
selectBluetoothCallback = callback
|
||||
const result = deviceList.find((device) => {
|
||||
return device.deviceName === 'test'
|
||||
})
|
||||
if (result) {
|
||||
callback(result.deviceId)
|
||||
} else {
|
||||
// The device wasn't found so we need to either wait longer (eg until the
|
||||
// device is turned on) or until the user cancels the request
|
||||
}
|
||||
})
|
||||
|
||||
ipcMain.on('cancel-bluetooth-request', (event) => {
|
||||
selectBluetoothCallback('')
|
||||
})
|
||||
|
||||
|
||||
// Listen for a message from the renderer to get the response for the Bluetooth pairing.
|
||||
ipcMain.on('bluetooth-pairing-response', (event, response) => {
|
||||
bluetoothPinCallback(response)
|
||||
@@ -27,14 +42,14 @@ function createWindow () {
|
||||
bluetoothPinCallback = callback
|
||||
// Send a message to the renderer to prompt the user to confirm the pairing.
|
||||
mainWindow.webContents.send('bluetooth-pairing-request', details)
|
||||
})
|
||||
})
|
||||
|
||||
mainWindow.loadFile('index.html')
|
||||
}
|
||||
|
||||
app.whenReady().then(() => {
|
||||
createWindow()
|
||||
|
||||
|
||||
app.on('activate', function () {
|
||||
if (BrowserWindow.getAllWindows().length === 0) createWindow()
|
||||
})
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
const { contextBridge, ipcRenderer } = require('electron')
|
||||
|
||||
contextBridge.exposeInMainWorld('electronAPI', {
|
||||
cancelBluetoothRequest: (callback) => ipcRenderer.send('cancel-bluetooth-request', callback),
|
||||
bluetoothPairingRequest: (callback) => ipcRenderer.on('bluetooth-pairing-request', callback),
|
||||
bluetoothPairingResponse: (response) => ipcRenderer.send('bluetooth-pairing-response', response)
|
||||
})
|
||||
@@ -7,9 +7,15 @@ async function testIt() {
|
||||
|
||||
document.getElementById('clickme').addEventListener('click',testIt)
|
||||
|
||||
function cancelRequest() {
|
||||
window.electronAPI.cancelBluetoothRequest()
|
||||
}
|
||||
|
||||
document.getElementById('cancel').addEventListener('click', cancelRequest)
|
||||
|
||||
window.electronAPI.bluetoothPairingRequest((event, details) => {
|
||||
const response = {}
|
||||
|
||||
|
||||
switch (details.pairingKind) {
|
||||
case 'confirm': {
|
||||
response.confirmed = confirm(`Do you want to connect to device ${details.deviceId}?`)
|
||||
@@ -31,4 +37,4 @@ window.electronAPI.bluetoothPairingRequest((event, details) => {
|
||||
}
|
||||
|
||||
window.electronAPI.bluetoothPairingResponse(response)
|
||||
})
|
||||
})
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
const {app, BrowserWindow} = require('electron')
|
||||
const e = require('express')
|
||||
const path = require('path')
|
||||
|
||||
function createWindow () {
|
||||
@@ -44,7 +43,6 @@ function createWindow () {
|
||||
}
|
||||
})
|
||||
|
||||
|
||||
mainWindow.webContents.session.setDevicePermissionHandler((details) => {
|
||||
if (details.deviceType === 'usb' && details.origin === 'file://') {
|
||||
if (!grantedDeviceThroughPermHandler) {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
function getDeviceDetails(device) {
|
||||
return grantedDevice.productName || `Unknown device ${grantedDevice.deviceId}`
|
||||
return device.productName || `Unknown device ${device.deviceId}`
|
||||
}
|
||||
|
||||
async function testIt() {
|
||||
|
||||
3
docs/fiddles/ipc/webview-new-window/child.html
Normal file
3
docs/fiddles/ipc/webview-new-window/child.html
Normal file
@@ -0,0 +1,3 @@
|
||||
<body>
|
||||
<a href="child.html" target="_blank">new window</a>
|
||||
</body>
|
||||
4
docs/fiddles/ipc/webview-new-window/index.html
Normal file
4
docs/fiddles/ipc/webview-new-window/index.html
Normal file
@@ -0,0 +1,4 @@
|
||||
<body>
|
||||
<webview id=webview src="child.html" allowpopups></webview>
|
||||
<script src="renderer.js"></script>
|
||||
</body>
|
||||
51
docs/fiddles/ipc/webview-new-window/main.js
Normal file
51
docs/fiddles/ipc/webview-new-window/main.js
Normal file
@@ -0,0 +1,51 @@
|
||||
// Modules to control application life and create native browser window
|
||||
const { app, BrowserWindow } = require('electron')
|
||||
const path = require('path')
|
||||
|
||||
function createWindow () {
|
||||
// Create the browser window.
|
||||
const mainWindow = new BrowserWindow({
|
||||
width: 800,
|
||||
height: 600,
|
||||
webPreferences: {
|
||||
preload: path.join(__dirname, 'preload.js'),
|
||||
webviewTag: true
|
||||
}
|
||||
})
|
||||
|
||||
mainWindow.webContents.on('did-attach-webview', (event, wc) => {
|
||||
wc.setWindowOpenHandler((details) => {
|
||||
mainWindow.webContents.send('webview-new-window', wc.id, details)
|
||||
return { action: 'deny' }
|
||||
})
|
||||
})
|
||||
|
||||
// and load the index.html of the app.
|
||||
mainWindow.loadFile('index.html')
|
||||
|
||||
// Open the DevTools.
|
||||
// mainWindow.webContents.openDevTools()
|
||||
}
|
||||
|
||||
// This method will be called when Electron has finished
|
||||
// initialization and is ready to create browser windows.
|
||||
// Some APIs can only be used after this event occurs.
|
||||
app.whenReady().then(() => {
|
||||
createWindow()
|
||||
|
||||
app.on('activate', function () {
|
||||
// On macOS it's common to re-create a window in the app when the
|
||||
// dock icon is clicked and there are no other windows open.
|
||||
if (BrowserWindow.getAllWindows().length === 0) createWindow()
|
||||
})
|
||||
})
|
||||
|
||||
// Quit when all windows are closed, except on macOS. There, it's common
|
||||
// for applications and their menu bar to stay active until the user quits
|
||||
// explicitly with Cmd + Q.
|
||||
app.on('window-all-closed', function () {
|
||||
if (process.platform !== 'darwin') app.quit()
|
||||
})
|
||||
|
||||
// In this file you can include the rest of your app's specific main process
|
||||
// code. You can also put them in separate files and require them here.
|
||||
6
docs/fiddles/ipc/webview-new-window/preload.js
Normal file
6
docs/fiddles/ipc/webview-new-window/preload.js
Normal file
@@ -0,0 +1,6 @@
|
||||
const { ipcRenderer } = require('electron')
|
||||
const webview = document.getElementById('webview')
|
||||
ipcRenderer.on('webview-new-window', (e, webContentsId, details) => {
|
||||
console.log('webview-new-window', webContentsId, details)
|
||||
webview.dispatchEvent(new Event('new-window'))
|
||||
})
|
||||
4
docs/fiddles/ipc/webview-new-window/renderer.js
Normal file
4
docs/fiddles/ipc/webview-new-window/renderer.js
Normal file
@@ -0,0 +1,4 @@
|
||||
const webview = document.getElementById('webview')
|
||||
webview.addEventListener('new-window', () => {
|
||||
console.log('got new-window event')
|
||||
})
|
||||
@@ -70,7 +70,7 @@
|
||||
</li>
|
||||
<li>
|
||||
<a
|
||||
href="https://msdn.microsoft.com/en-us/library/windows/desktop/bb226797(v=vs.85).aspx"
|
||||
href="https://learn.microsoft.com/en-us/previous-versions/windows/desktop/bb226797"
|
||||
>Windows<span
|
||||
>(opens in new window)</span
|
||||
></a
|
||||
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 21 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 22 KiB |
@@ -28,6 +28,8 @@ On macOS, third-party assistive technology can toggle accessibility features ins
|
||||
Electron applications by setting the `AXManualAccessibility` attribute
|
||||
programmatically:
|
||||
|
||||
Using Objective-C:
|
||||
|
||||
```objc
|
||||
CFStringRef kAXManualAccessibility = CFSTR("AXManualAccessibility");
|
||||
|
||||
@@ -43,5 +45,16 @@ CFStringRef kAXManualAccessibility = CFSTR("AXManualAccessibility");
|
||||
}
|
||||
```
|
||||
|
||||
Using Swift:
|
||||
|
||||
```swift
|
||||
import Cocoa
|
||||
let name = CommandLine.arguments.count >= 2 ? CommandLine.arguments[1] : "Electron"
|
||||
let pid = NSWorkspace.shared.runningApplications.first(where: {$0.localizedName == name})!.processIdentifier
|
||||
let axApp = AXUIElementCreateApplication(pid)
|
||||
let result = AXUIElementSetAttributeValue(axApp, "AXManualAccessibility" as CFString, true as CFTypeRef)
|
||||
print("Setting 'AXManualAccessibility' \(error.rawValue == 0 ? "succeeded" : "failed")")
|
||||
```
|
||||
|
||||
[a11y-docs]: https://www.chromium.org/developers/design-documents/accessibility#TOC-How-Chrome-detects-the-presence-of-Assistive-Technology
|
||||
[setAccessibilitySupportEnabled]: ../api/app.md#appsetaccessibilitysupportenabledenabled-macos-windows
|
||||
|
||||
@@ -95,7 +95,7 @@ Before signing Windows builds, you must do the following:
|
||||
You can get a code signing certificate from a lot of resellers. Prices vary, so
|
||||
it may be worth your time to shop around. Popular resellers include:
|
||||
|
||||
- [digicert](https://www.digicert.com/code-signing/microsoft-authenticode.htm)
|
||||
- [digicert](https://www.digicert.com/dc/code-signing/microsoft-authenticode.htm)
|
||||
- [Sectigo](https://sectigo.com/ssl-certificates-tls/code-signing)
|
||||
- Amongst others, please shop around to find one that suits your needs! 😄
|
||||
|
||||
|
||||
@@ -129,7 +129,7 @@ Electron provides several APIs for working with the WebUSB API:
|
||||
when handling the `select-usb-device` event.
|
||||
**Note:** These two events only fire until the callback from `select-usb-device`
|
||||
is called. They are not intended to be used as a generic usb device listener.
|
||||
* The [`usb-device-revoked' event on the Session](../api/session.md#event-usb-device-revoked) can
|
||||
* The [`usb-device-revoked` event on the Session](../api/session.md#event-usb-device-revoked) can
|
||||
be used to respond when [device.forget()](https://developer.chrome.com/articles/usb/#revoke-access)
|
||||
is called on a USB device.
|
||||
* [`ses.setDevicePermissionHandler(handler)`](../api/session.md#sessetdevicepermissionhandlerhandler)
|
||||
|
||||
@@ -1,98 +1,108 @@
|
||||
# Notifications
|
||||
|
||||
## Overview
|
||||
Each operating system has its own mechanism to display notifications to users. Electron's notification
|
||||
APIs are cross-platform, but are different for each process type.
|
||||
|
||||
All three operating systems provide means for applications to send
|
||||
notifications to the user. The technique of showing notifications is different
|
||||
for the Main and Renderer processes.
|
||||
If you want to use a renderer process API in the main process or vice-versa, consider using
|
||||
[inter-process communication](./ipc.md).
|
||||
|
||||
For the Renderer process, Electron conveniently allows developers to send
|
||||
notifications with the [HTML5 Notification API](https://notifications.spec.whatwg.org/),
|
||||
using the currently running operating system's native notification APIs
|
||||
to display it.
|
||||
## Usage
|
||||
|
||||
To show notifications in the Main process, you need to use the
|
||||
[Notification](../api/notification.md) module.
|
||||
Below are two examples showing how to display notifications for each process type.
|
||||
|
||||
## Example
|
||||
### Show notifications in the main process
|
||||
|
||||
### Show notifications in the Renderer process
|
||||
Main process notifications are displayed using Electron's [Notification module](../api/notification.md).
|
||||
Notification objects created using this module do not appear unless their `show()` instance
|
||||
method is called.
|
||||
|
||||
Starting with a working application from the
|
||||
[Quick Start Guide](quick-start.md), add the following line to the
|
||||
`index.html` file before the closing `</body>` tag:
|
||||
```js title='Main Process'
|
||||
const { Notification } = require("electron");
|
||||
|
||||
```html
|
||||
<script src="renderer.js"></script>
|
||||
const NOTIFICATION_TITLE = "Basic Notification";
|
||||
const NOTIFICATION_BODY = "Notification from the Main process";
|
||||
|
||||
new Notification({
|
||||
title: NOTIFICATION_TITLE,
|
||||
body: NOTIFICATION_BODY,
|
||||
}).show();
|
||||
```
|
||||
|
||||
...and add the `renderer.js` file:
|
||||
|
||||
```javascript fiddle='docs/fiddles/features/notifications/renderer'
|
||||
const NOTIFICATION_TITLE = 'Title'
|
||||
const NOTIFICATION_BODY = 'Notification from the Renderer process. Click to log to console.'
|
||||
const CLICK_MESSAGE = 'Notification clicked'
|
||||
|
||||
new Notification(NOTIFICATION_TITLE, { body: NOTIFICATION_BODY })
|
||||
.onclick = () => console.log(CLICK_MESSAGE)
|
||||
```
|
||||
|
||||
After launching the Electron application, you should see the notification:
|
||||
|
||||

|
||||
|
||||
Additionally, if you click on the notification, the DOM will update to show "Notification clicked!".
|
||||
|
||||
### Show notifications in the Main process
|
||||
|
||||
Starting with a working application from the
|
||||
[Quick Start Guide](quick-start.md), update the `main.js` file with the following lines:
|
||||
Here's a full example that you can open with Electron Fiddle:
|
||||
|
||||
```javascript fiddle='docs/fiddles/features/notifications/main'
|
||||
const { Notification } = require('electron')
|
||||
const { Notification } = require("electron");
|
||||
|
||||
const NOTIFICATION_TITLE = 'Basic Notification'
|
||||
const NOTIFICATION_BODY = 'Notification from the Main process'
|
||||
const NOTIFICATION_TITLE = "Basic Notification";
|
||||
const NOTIFICATION_BODY = "Notification from the Main process";
|
||||
|
||||
const showNotification = () => {
|
||||
new Notification({ title: NOTIFICATION_TITLE, body: NOTIFICATION_BODY }).show()
|
||||
}
|
||||
|
||||
app.whenReady().then(createWindow).then(showNotification)
|
||||
new Notification({
|
||||
title: NOTIFICATION_TITLE,
|
||||
body: NOTIFICATION_BODY,
|
||||
}).show();
|
||||
```
|
||||
|
||||
After launching the Electron application, you should see the system notification:
|
||||
### Show notifications in the renderer process
|
||||
|
||||

|
||||
Notifications can be displayed directly from the renderer process with the
|
||||
[web Notifications API](https://developer.mozilla.org/en-US/docs/Web/API/Notifications_API/Using_the_Notifications_API).
|
||||
|
||||
## Additional information
|
||||
```js title='Renderer Process'
|
||||
const NOTIFICATION_TITLE = "Title";
|
||||
const NOTIFICATION_BODY =
|
||||
"Notification from the Renderer process. Click to log to console.";
|
||||
const CLICK_MESSAGE = "Notification clicked";
|
||||
|
||||
new Notification(NOTIFICATION_TITLE, { body: NOTIFICATION_BODY }).onclick =
|
||||
() => console.log(CLICK_MESSAGE);
|
||||
```
|
||||
|
||||
Here's a full example that you can open with Electron Fiddle:
|
||||
|
||||
```javascript fiddle='docs/fiddles/features/notifications/renderer'
|
||||
const NOTIFICATION_TITLE = "Title";
|
||||
const NOTIFICATION_BODY =
|
||||
"Notification from the Renderer process. Click to log to console.";
|
||||
const CLICK_MESSAGE = "Notification clicked";
|
||||
|
||||
new Notification(NOTIFICATION_TITLE, { body: NOTIFICATION_BODY }).onclick =
|
||||
() => console.log(CLICK_MESSAGE);
|
||||
```
|
||||
|
||||
## Platform considerations
|
||||
|
||||
While code and user experience across operating systems are similar, there
|
||||
are subtle differences.
|
||||
|
||||
### Windows
|
||||
|
||||
* On Windows 10, a shortcut to your app with an
|
||||
[Application User Model ID][app-user-model-id] must be installed to the
|
||||
Start Menu. This can be overkill during development, so adding
|
||||
`node_modules\electron\dist\electron.exe` to your Start Menu also does the
|
||||
trick. Navigate to the file in Explorer, right-click and 'Pin to Start Menu'.
|
||||
You will then need to add the line `app.setAppUserModelId(process.execPath)` to
|
||||
your main process to see notifications.
|
||||
For notifications on Windows, your Electron app needs to have a Start Menu shortcut with an
|
||||
[AppUserModelID][app-user-model-id] and a corresponding [ToastActivatorCLSID][toast-activator-clsid].
|
||||
|
||||
Electron attempts to automate the work around the Application User Model ID. When
|
||||
Electron is used together with the installation and update framework Squirrel,
|
||||
[shortcuts will automatically be set correctly][squirrel-events]. Furthermore,
|
||||
Electron will detect that Squirrel was used and will automatically call
|
||||
Electron attempts to automate the work around the AppUserModelID and ToastActivatorCLSID. When
|
||||
Electron is used together with Squirrel.Windows (e.g. if you're using electron-winstaller),
|
||||
[shortcuts will automatically be set correctly][squirrel-events].
|
||||
|
||||
In production, Electron will also detect that Squirrel was used and will automatically call
|
||||
`app.setAppUserModelId()` with the correct value. During development, you may have
|
||||
to call [`app.setAppUserModelId()`][set-app-user-model-id] yourself.
|
||||
|
||||
#### Advanced Notifications
|
||||
:::info Notifications in development
|
||||
|
||||
Later versions of Windows allow for advanced notifications, with custom templates,
|
||||
images, and other flexible elements. To send those notifications (from either the
|
||||
main process or the renderer process), use the userland module
|
||||
[electron-windows-notifications](https://github.com/felixrieseberg/electron-windows-notifications),
|
||||
To quickly bootstrap notifications during development, adding
|
||||
`node_modules\electron\dist\electron.exe` to your Start Menu also does the
|
||||
trick. Navigate to the file in Explorer, right-click and 'Pin to Start Menu'.
|
||||
Then, call `app.setAppUserModelId(process.execPath)` in the main process to see notifications.
|
||||
|
||||
:::
|
||||
|
||||
#### Use advanced notifications
|
||||
|
||||
Windows also allow for advanced notifications with custom templates, images, and other flexible
|
||||
elements.
|
||||
|
||||
To send those notifications from the main process, you can use the userland module
|
||||
[`electron-windows-notifications`](https://github.com/felixrieseberg/electron-windows-notifications),
|
||||
which uses native Node addons to send `ToastNotification` and `TileNotification` objects.
|
||||
|
||||
While notifications including buttons work with `electron-windows-notifications`,
|
||||
@@ -101,41 +111,41 @@ handling replies requires the use of
|
||||
which helps with registering the required COM components and calling your
|
||||
Electron app with the entered user data.
|
||||
|
||||
#### Quiet Hours / Presentation Mode
|
||||
#### Query notification state
|
||||
|
||||
To detect whether or not you're allowed to send a notification, use the
|
||||
userland module [electron-notification-state](https://github.com/felixrieseberg/electron-notification-state).
|
||||
userland module [`windows-notification-state`][windows-notification-state].
|
||||
|
||||
This allows you to determine ahead of time whether or not Windows will
|
||||
silently throw the notification away.
|
||||
This module allows you to determine ahead of time whether or not Windows will silently throw the
|
||||
notification away.
|
||||
|
||||
### macOS
|
||||
|
||||
Notifications are straight-forward on macOS, but you should be aware of
|
||||
Notifications are straightforward on macOS, but you should be aware of
|
||||
[Apple's Human Interface guidelines regarding notifications][apple-notification-guidelines].
|
||||
|
||||
Note that notifications are limited to 256 bytes in size and will be truncated
|
||||
if you exceed that limit.
|
||||
|
||||
[apple-notification-guidelines]: https://developer.apple.com/macos/human-interface-guidelines/system-capabilities/notifications/
|
||||
|
||||
#### Do not disturb / Session State
|
||||
#### Query notification state
|
||||
|
||||
To detect whether or not you're allowed to send a notification, use the userland module
|
||||
[electron-notification-state][electron-notification-state].
|
||||
[`macos-notification-state`][macos-notification-state].
|
||||
|
||||
This will allow you to detect ahead of time whether or not the notification will be displayed.
|
||||
|
||||
[electron-notification-state]: https://github.com/felixrieseberg/electron-notification-state
|
||||
This module allows you to detect ahead of time whether or not the notification will be displayed.
|
||||
|
||||
### Linux
|
||||
|
||||
Notifications are sent using `libnotify` which can show notifications on any
|
||||
Notifications are sent using `libnotify`, which can show notifications on any
|
||||
desktop environment that follows [Desktop Notifications
|
||||
Specification][notification-spec], including Cinnamon, Enlightenment, Unity,
|
||||
GNOME, KDE.
|
||||
GNOME, and KDE.
|
||||
|
||||
[notification-spec]: https://developer-old.gnome.org/notification-spec/
|
||||
[app-user-model-id]: https://msdn.microsoft.com/en-us/library/windows/desktop/dd378459(v=vs.85).aspx
|
||||
[app-user-model-id]: https://learn.microsoft.com/en-us/windows/win32/shell/appids
|
||||
[set-app-user-model-id]: ../api/app.md#appsetappusermodelidid-windows
|
||||
[squirrel-events]: https://github.com/electron/windows-installer/blob/main/README.md#handling-squirrel-events
|
||||
[toast-activator-clsid]: https://learn.microsoft.com/en-us/windows/win32/properties/props-system-appusermodel-toastactivatorclsid
|
||||
[apple-notification-guidelines]: https://developer.apple.com/macos/human-interface-guidelines/system-capabilities/notifications/
|
||||
[windows-notification-state]: https://github.com/felixrieseberg/windows-notification-state
|
||||
[macos-notification-state]: https://github.com/felixrieseberg/macos-notification-state
|
||||
|
||||
@@ -138,5 +138,5 @@ of `app` module will be emitted for it.
|
||||
[dock-menu-image]: https://cloud.githubusercontent.com/assets/639601/5069610/2aa80758-6e97-11e4-8cfb-c1a414a10774.png
|
||||
[addrecentdocument]: ../api/app.md#appaddrecentdocumentpath-macos-windows
|
||||
[clearrecentdocuments]: ../api/app.md#appclearrecentdocuments-macos-windows
|
||||
[app-registration]: https://msdn.microsoft.com/en-us/library/cc144104(VS.85).aspx
|
||||
[app-registration]: https://learn.microsoft.com/en-us/windows/win32/shell/app-registration
|
||||
[menu-item-image]: https://user-images.githubusercontent.com/3168941/33003655-ea601c3a-cd70-11e7-97fa-7c062149cfb1.png
|
||||
|
||||
@@ -84,7 +84,7 @@ the `sandbox: false` preference in the [`BrowserWindow`][browser-window] constru
|
||||
app.whenReady().then(() => {
|
||||
const win = new BrowserWindow({
|
||||
webPreferences: {
|
||||
sandbox: true
|
||||
sandbox: false
|
||||
}
|
||||
})
|
||||
win.loadURL('https://google.com')
|
||||
|
||||
@@ -81,10 +81,13 @@ the exact dependency versions to install.
|
||||
"version": "1.0.0",
|
||||
"description": "Hello World!",
|
||||
"main": "main.js",
|
||||
"scripts": {
|
||||
"test": "echo \"Error: no test specified\" && exit 1"
|
||||
},
|
||||
"author": "Jane Doe",
|
||||
"license": "MIT",
|
||||
"devDependencies": {
|
||||
"electron": "19.0.0"
|
||||
"electron": "23.1.3"
|
||||
}
|
||||
}
|
||||
```
|
||||
@@ -137,13 +140,14 @@ script in the current directory and run it in dev mode.
|
||||
"version": "1.0.0",
|
||||
"description": "Hello World!",
|
||||
"main": "main.js",
|
||||
"scripts": {
|
||||
"start": "electron .",
|
||||
"test": "echo \"Error: no test specified\" && exit 1"
|
||||
},
|
||||
"author": "Jane Doe",
|
||||
"license": "MIT",
|
||||
"scripts": {
|
||||
"start": "electron ."
|
||||
},
|
||||
"devDependencies": {
|
||||
"electron": "^19.0.0"
|
||||
"electron": "23.1.3"
|
||||
}
|
||||
}
|
||||
```
|
||||
@@ -270,7 +274,7 @@ calling `createWindow()` once its promise is fulfilled.
|
||||
You typically listen to Node.js events by using an emitter's `.on` function.
|
||||
|
||||
```diff
|
||||
+ app.on('ready').then(() => {
|
||||
+ app.on('ready', () => {
|
||||
- app.whenReady().then(() => {
|
||||
createWindow()
|
||||
})
|
||||
|
||||
@@ -231,7 +231,7 @@ rest of our docs and happy developing! If you have questions, please stop by our
|
||||
[new-pat]: https://github.com/settings/tokens/new
|
||||
[publish command]: https://www.electronforge.io/cli#publish
|
||||
[publisher]: https://www.electronforge.io/config/publishers
|
||||
[`publishergithubconfig`]: https://js.electronforge.io/publisher/github/interfaces/publishergithubconfig
|
||||
[`publishergithubconfig`]: https://js.electronforge.io/interfaces/_electron_forge_publisher_github.PublisherGitHubConfig.html
|
||||
[`update-electron-app`]: https://github.com/electron/update-electron-app
|
||||
[update-server]: ./updates.md
|
||||
|
||||
|
||||
@@ -110,7 +110,7 @@ On Windows, by default, `node-gyp` links native modules against `node.dll`.
|
||||
However, in Electron 4.x and higher, the symbols needed by native modules are
|
||||
exported by `electron.exe`, and there is no `node.dll`. In order to load native
|
||||
modules on Windows, `node-gyp` installs a [delay-load
|
||||
hook](https://msdn.microsoft.com/en-us/library/z9h1h6ty.aspx) that triggers
|
||||
hook](https://learn.microsoft.com/en-us/cpp/build/reference/error-handling-and-notification?view=msvc-170#notification-hooks) that triggers
|
||||
when the native module is loaded, and redirects the `node.dll` reference to use
|
||||
the loading executable instead of looking for `node.dll` in the library search
|
||||
path (which would turn up nothing). As such, on Electron 4.x and higher,
|
||||
|
||||
@@ -175,8 +175,6 @@ filenames = {
|
||||
"shell/browser/ui/cocoa/electron_touch_bar.mm",
|
||||
"shell/browser/ui/cocoa/event_dispatching_window.h",
|
||||
"shell/browser/ui/cocoa/event_dispatching_window.mm",
|
||||
"shell/browser/ui/cocoa/NSColor+Hex.h",
|
||||
"shell/browser/ui/cocoa/NSColor+Hex.mm",
|
||||
"shell/browser/ui/cocoa/NSString+ANSI.h",
|
||||
"shell/browser/ui/cocoa/NSString+ANSI.mm",
|
||||
"shell/browser/ui/cocoa/root_view_mac.h",
|
||||
|
||||
@@ -271,6 +271,10 @@ libcxx_headers = [
|
||||
"//buildtools/third_party/libc++/trunk/include/__debug",
|
||||
"//buildtools/third_party/libc++/trunk/include/__debug_utils/randomize_range.h",
|
||||
"//buildtools/third_party/libc++/trunk/include/__errc",
|
||||
"//buildtools/third_party/libc++/trunk/include/__expected/bad_expected_access.h",
|
||||
"//buildtools/third_party/libc++/trunk/include/__expected/expected.h",
|
||||
"//buildtools/third_party/libc++/trunk/include/__expected/unexpect.h",
|
||||
"//buildtools/third_party/libc++/trunk/include/__expected/unexpected.h",
|
||||
"//buildtools/third_party/libc++/trunk/include/__filesystem/copy_options.h",
|
||||
"//buildtools/third_party/libc++/trunk/include/__filesystem/directory_entry.h",
|
||||
"//buildtools/third_party/libc++/trunk/include/__filesystem/directory_iterator.h",
|
||||
@@ -670,6 +674,7 @@ libcxx_headers = [
|
||||
"//buildtools/third_party/libc++/trunk/include/__type_traits/remove_reference.h",
|
||||
"//buildtools/third_party/libc++/trunk/include/__type_traits/remove_volatile.h",
|
||||
"//buildtools/third_party/libc++/trunk/include/__type_traits/result_of.h",
|
||||
"//buildtools/third_party/libc++/trunk/include/__type_traits/strip_signature.h",
|
||||
"//buildtools/third_party/libc++/trunk/include/__type_traits/type_identity.h",
|
||||
"//buildtools/third_party/libc++/trunk/include/__type_traits/type_list.h",
|
||||
"//buildtools/third_party/libc++/trunk/include/__type_traits/underlying_type.h",
|
||||
@@ -742,6 +747,7 @@ libcxx_headers = [
|
||||
"//buildtools/third_party/libc++/trunk/include/errno.h",
|
||||
"//buildtools/third_party/libc++/trunk/include/exception",
|
||||
"//buildtools/third_party/libc++/trunk/include/execution",
|
||||
"//buildtools/third_party/libc++/trunk/include/expected",
|
||||
"//buildtools/third_party/libc++/trunk/include/experimental/__config",
|
||||
"//buildtools/third_party/libc++/trunk/include/experimental/__memory",
|
||||
"//buildtools/third_party/libc++/trunk/include/experimental/algorithm",
|
||||
|
||||
@@ -12,6 +12,14 @@ BrowserWindow.prototype._init = function (this: BWT) {
|
||||
// Avoid recursive require.
|
||||
const { app } = require('electron');
|
||||
|
||||
// Set ID at constructon time so it's accessible after
|
||||
// underlying window destruction.
|
||||
const id = this.id;
|
||||
Object.defineProperty(this, 'id', {
|
||||
value: id,
|
||||
writable: false
|
||||
});
|
||||
|
||||
const nativeSetBounds = this.setBounds;
|
||||
this.setBounds = (bounds, ...opts) => {
|
||||
bounds = {
|
||||
|
||||
@@ -26,7 +26,7 @@ export const roleList: Record<RoleId, Role> = {
|
||||
get label () {
|
||||
return isLinux ? 'About' : `About ${app.name}`;
|
||||
},
|
||||
...(isWindows && { appMethod: () => app.showAboutPanel() })
|
||||
...((isWindows || isLinux) && { appMethod: () => app.showAboutPanel() })
|
||||
},
|
||||
close: {
|
||||
label: isMac ? 'Close Window' : 'Close',
|
||||
|
||||
@@ -524,17 +524,10 @@ WebContents.prototype._callWindowOpenHandler = function (event: Electron.Event,
|
||||
event.preventDefault();
|
||||
return defaultResponse;
|
||||
} else if (response.action === 'allow') {
|
||||
if (typeof response.overrideBrowserWindowOptions === 'object' && response.overrideBrowserWindowOptions !== null) {
|
||||
return {
|
||||
browserWindowConstructorOptions: response.overrideBrowserWindowOptions,
|
||||
outlivesOpener: typeof response.outlivesOpener === 'boolean' ? response.outlivesOpener : false
|
||||
};
|
||||
} else {
|
||||
return {
|
||||
browserWindowConstructorOptions: {},
|
||||
outlivesOpener: typeof response.outlivesOpener === 'boolean' ? response.outlivesOpener : false
|
||||
};
|
||||
}
|
||||
return {
|
||||
browserWindowConstructorOptions: typeof response.overrideBrowserWindowOptions === 'object' ? response.overrideBrowserWindowOptions : null,
|
||||
outlivesOpener: typeof response.outlivesOpener === 'boolean' ? response.outlivesOpener : false
|
||||
};
|
||||
} else {
|
||||
event.preventDefault();
|
||||
console.error('The window open handler response must be an object with an \'action\' property of \'allow\' or \'deny\'.');
|
||||
|
||||
@@ -1 +1,4 @@
|
||||
fix_rename_webswapcgllayer_to_webswapcgllayerchromium.patch
|
||||
cherry-pick-6da1a8953313.patch
|
||||
cherry-pick-aed05b609629.patch
|
||||
cherry-pick-d0ee0197ddff.patch
|
||||
|
||||
134
patches/angle/cherry-pick-6da1a8953313.patch
Normal file
134
patches/angle/cherry-pick-6da1a8953313.patch
Normal file
@@ -0,0 +1,134 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Shahbaz Youssefi <syoussefi@chromium.org>
|
||||
Date: Thu, 16 Feb 2023 23:16:46 -0500
|
||||
Subject: M110: Vulkan: Don't close render pass if rebind to same fbo
|
||||
|
||||
In the Vulkan backend, the render pass can occasionally (and
|
||||
transiently) be in a state of "open but inactive". This is when the
|
||||
render pass is closed, but has the potential for future modifications
|
||||
(for example to add a resolve attachment). Under many circumstances, it
|
||||
is expected that an open render pass cannot be in such a state.
|
||||
|
||||
This assumption can be broken in this scenario:
|
||||
|
||||
- Open render pass, draw, etc
|
||||
- Change framebuffer binding
|
||||
- Change framebuffer binding back to original
|
||||
- Masked Clear
|
||||
|
||||
When ContextVk is synced before clear, it sees that the framebuffer
|
||||
binding is changed (though it hasn't really), and it closes the render
|
||||
passes and sets the render pass dirty bit. If a draw were to follow, a
|
||||
new render pass would have started (unnecessarily). However, in the
|
||||
case of a masked clear, UtilsVk notices that the render pass is started,
|
||||
assumes it must be active, and continues recording to it. While the
|
||||
operation itself succeeds, the assumption that the render pass is active
|
||||
is false (and fails assertion).
|
||||
|
||||
This change makes sure that framebuffer binding change is no-oped if the
|
||||
framebuffer is the same one that has opened the current render pass. If
|
||||
any application does unnecessary binding changes and back, it will be
|
||||
optimized by this change as well.
|
||||
|
||||
Bug: chromium:1411210
|
||||
Change-Id: I37a3a9f2eaa1a81a1b3393840b9458ec71a87377
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/4261215
|
||||
Reviewed-by: Charlie Lao <cclao@google.com>
|
||||
Commit-Queue: Shahbaz Youssefi <syoussefi@chromium.org>
|
||||
(cherry picked from commit 05e62f39412e8c6bfc98582f5e7a49041991c97b)
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/4296296
|
||||
Commit-Queue: Geoff Lang <geofflang@chromium.org>
|
||||
Reviewed-by: Prudhvikumar Bommana <pbommana@google.com>
|
||||
Commit-Queue: Prudhvikumar Bommana <pbommana@google.com>
|
||||
|
||||
diff --git a/src/libANGLE/renderer/vulkan/ContextVk.cpp b/src/libANGLE/renderer/vulkan/ContextVk.cpp
|
||||
index ad5f83854f29c7245553fe3e98b7f6545d7ea91c..9f05c2a32ae2e0f6a4b1466d9f4423b3022b4975 100644
|
||||
--- a/src/libANGLE/renderer/vulkan/ContextVk.cpp
|
||||
+++ b/src/libANGLE/renderer/vulkan/ContextVk.cpp
|
||||
@@ -5224,6 +5224,15 @@ angle::Result ContextVk::syncState(const gl::Context *context,
|
||||
// as some optimizations in non-draw commands require the render pass to remain
|
||||
// open, such as invalidate or blit. Note that we always start a new command buffer
|
||||
// because we currently can only support one open RenderPass at a time.
|
||||
+ //
|
||||
+ // The render pass is not closed if binding is changed to the same framebuffer as
|
||||
+ // before.
|
||||
+ if (hasStartedRenderPass() && hasStartedRenderPassWithQueueSerial(
|
||||
+ drawFramebufferVk->getLastRenderPassQueueSerial()))
|
||||
+ {
|
||||
+ break;
|
||||
+ }
|
||||
+
|
||||
onRenderPassFinished(RenderPassClosureReason::FramebufferBindingChange);
|
||||
if (getFeatures().preferSubmitAtFBOBoundary.enabled &&
|
||||
mRenderPassCommands->started())
|
||||
diff --git a/src/tests/gl_tests/ClearTest.cpp b/src/tests/gl_tests/ClearTest.cpp
|
||||
index bbe243281fce2b7503767b2553d2900b598b7e81..51a953019c53e8ed1f09184965164002f4cc4c79 100644
|
||||
--- a/src/tests/gl_tests/ClearTest.cpp
|
||||
+++ b/src/tests/gl_tests/ClearTest.cpp
|
||||
@@ -2863,6 +2863,26 @@ TEST_P(ClearTest, DISABLED_ClearReachesWindow)
|
||||
angle::Sleep(2000);
|
||||
}
|
||||
|
||||
+// Tests that masked clear after a no-op framebuffer binding change with an open render pass works.
|
||||
+TEST_P(ClearTest, DrawThenChangeFBOBindingAndBackThenMaskedClear)
|
||||
+{
|
||||
+ ANGLE_GL_PROGRAM(blueProgram, essl1_shaders::vs::Simple(), essl1_shaders::fs::Blue());
|
||||
+
|
||||
+ // Draw blue.
|
||||
+ drawQuad(blueProgram, essl1_shaders::PositionAttrib(), 0.5f);
|
||||
+
|
||||
+ // Change framebuffer and back
|
||||
+ glBindFramebuffer(GL_FRAMEBUFFER, mFBOs[0]);
|
||||
+ glBindFramebuffer(GL_FRAMEBUFFER, 0);
|
||||
+
|
||||
+ // Masked clear
|
||||
+ glColorMask(1, 0, 0, 1);
|
||||
+ glClearColor(1.0f, 0.5f, 0.5f, 1.0f);
|
||||
+ glClear(GL_COLOR_BUFFER_BIT);
|
||||
+
|
||||
+ EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::magenta);
|
||||
+}
|
||||
+
|
||||
// Test that clearing slices of a 3D texture and reading them back works.
|
||||
TEST_P(ClearTestES3, ClearAndReadPixels3DTexture)
|
||||
{
|
||||
diff --git a/src/tests/gl_tests/VulkanPerformanceCounterTest.cpp b/src/tests/gl_tests/VulkanPerformanceCounterTest.cpp
|
||||
index b62f434d5db1eac4bf5039db49d50ffd092b3621..bacac33673b9d2c2b8d62b9ff12a61773273eff1 100644
|
||||
--- a/src/tests/gl_tests/VulkanPerformanceCounterTest.cpp
|
||||
+++ b/src/tests/gl_tests/VulkanPerformanceCounterTest.cpp
|
||||
@@ -5,7 +5,7 @@
|
||||
//
|
||||
// VulkanPerformanceCounterTest:
|
||||
// Validates specific GL call patterns with ANGLE performance counters.
|
||||
-// For example we can verify a certain call set doesn't break the RenderPass.
|
||||
+// For example we can verify a certain call set doesn't break the render pass.
|
||||
|
||||
#include "test_utils/ANGLETest.h"
|
||||
#include "test_utils/angle_test_instantiate.h"
|
||||
@@ -7090,6 +7090,26 @@ TEST_P(VulkanPerformanceCounterTest, AsyncMonolithicPipelineCreation)
|
||||
EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
|
||||
}
|
||||
|
||||
+// Verify that changing framebuffer and back doesn't break the render pass.
|
||||
+TEST_P(VulkanPerformanceCounterTest, FBOChangeAndBackDoesNotBreakRenderPass)
|
||||
+{
|
||||
+ uint64_t expectedRenderPassCount = getPerfCounters().renderPasses + 1;
|
||||
+
|
||||
+ ANGLE_GL_PROGRAM(drawRed, essl3_shaders::vs::Simple(), essl3_shaders::fs::Red());
|
||||
+ drawQuad(drawRed, essl1_shaders::PositionAttrib(), 0);
|
||||
+
|
||||
+ GLFramebuffer fbo;
|
||||
+ glBindFramebuffer(GL_FRAMEBUFFER, fbo);
|
||||
+ glBindFramebuffer(GL_FRAMEBUFFER, 0);
|
||||
+
|
||||
+ drawQuad(drawRed, essl1_shaders::PositionAttrib(), 0);
|
||||
+
|
||||
+ // Verify render pass count.
|
||||
+ EXPECT_EQ(getPerfCounters().renderPasses, expectedRenderPassCount);
|
||||
+
|
||||
+ EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
|
||||
+}
|
||||
+
|
||||
GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(VulkanPerformanceCounterTest);
|
||||
ANGLE_INSTANTIATE_TEST(
|
||||
VulkanPerformanceCounterTest,
|
||||
108
patches/angle/cherry-pick-aed05b609629.patch
Normal file
108
patches/angle/cherry-pick-aed05b609629.patch
Normal file
@@ -0,0 +1,108 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Geoff Lang <geofflang@chromium.org>
|
||||
Date: Fri, 31 Mar 2023 16:44:35 -0400
|
||||
Subject: M112: Mark RGBX and BGRX formats as having 8 unused bits.
|
||||
|
||||
This makes sure that pixelBytes ends up being 4 and fixes potential
|
||||
buffer size validation.
|
||||
|
||||
Fix EGL configs using pixelBytes to compute EGL_BUFFER_SIZE which
|
||||
is not supposed to include unused bits. This is covered by
|
||||
dEQP-EGL.functional.query_config.constraints.color_buffer_size
|
||||
|
||||
Bug: chromium:1404790
|
||||
Change-Id: Ie0480cbdc6229c4bb3a6c6242337eaed5a3ae3b7
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/4428752
|
||||
Reviewed-by: Amirali Abdolrashidi <abdolrashidi@google.com>
|
||||
|
||||
diff --git a/src/libANGLE/formatutils.cpp b/src/libANGLE/formatutils.cpp
|
||||
index a28db6081e0707c28e15ebbc0b0ef08a854fc785..d0dbb403961a5f32edc175e9d01f94728486e47f 100644
|
||||
--- a/src/libANGLE/formatutils.cpp
|
||||
+++ b/src/libANGLE/formatutils.cpp
|
||||
@@ -549,6 +549,21 @@ bool InternalFormat::isDepthOrStencil() const
|
||||
return depthBits != 0 || stencilBits != 0;
|
||||
}
|
||||
|
||||
+GLuint InternalFormat::getEGLConfigBufferSize() const
|
||||
+{
|
||||
+ // EGL config's EGL_BUFFER_SIZE is measured in bits and is the sum of all the color channels for
|
||||
+ // color formats or the luma channels for luma formats. It ignores unused bits so compute the
|
||||
+ // bit count by summing instead of using pixelBytes.
|
||||
+ if (isLUMA())
|
||||
+ {
|
||||
+ return luminanceBits + alphaBits;
|
||||
+ }
|
||||
+ else
|
||||
+ {
|
||||
+ return redBits + greenBits + blueBits + alphaBits;
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
Format::Format(GLenum internalFormat) : Format(GetSizedInternalFormatInfo(internalFormat)) {}
|
||||
|
||||
Format::Format(const InternalFormat &internalFormat) : info(&internalFormat) {}
|
||||
@@ -1141,10 +1156,10 @@ static InternalFormatInfoMap BuildInternalFormatInfoMap()
|
||||
AddRGBAFormat(&map, GL_BGR10_A2_ANGLEX, true, 10, 10, 10, 2, 0, GL_BGRA_EXT, GL_UNSIGNED_INT_2_10_10_10_REV, GL_UNSIGNED_NORMALIZED, false, NeverSupported, NeverSupported, NeverSupported, NeverSupported, NeverSupported);
|
||||
|
||||
// Special format to emulate RGB8 with RGBA8 within ANGLE.
|
||||
- AddRGBAFormat(&map, GL_RGBX8_ANGLE, true, 8, 8, 8, 0, 0, GL_RGB, GL_UNSIGNED_BYTE, GL_UNSIGNED_NORMALIZED, false, AlwaysSupported, AlwaysSupported, AlwaysSupported, AlwaysSupported, NeverSupported);
|
||||
+ AddRGBAXFormat(&map, GL_RGBX8_ANGLE, true, FB< 8, 8, 8, 0, 8, 0>(), GL_RGB, GL_UNSIGNED_BYTE, GL_UNSIGNED_NORMALIZED, false, AlwaysSupported, AlwaysSupported, AlwaysSupported, AlwaysSupported, NeverSupported);
|
||||
|
||||
// Special format to emulate BGR8 with BGRA8 within ANGLE.
|
||||
- AddRGBAFormat(&map, GL_BGRX8_ANGLEX, true, 8, 8, 8, 0, 0, GL_BGRA_EXT, GL_UNSIGNED_BYTE, GL_UNSIGNED_NORMALIZED, false, NeverSupported, AlwaysSupported, NeverSupported, NeverSupported, NeverSupported);
|
||||
+ AddRGBAXFormat(&map, GL_BGRX8_ANGLEX, true, FB< 8, 8, 8, 0, 8, 0>(), GL_BGRA_EXT, GL_UNSIGNED_BYTE, GL_UNSIGNED_NORMALIZED, false, NeverSupported, AlwaysSupported, NeverSupported, NeverSupported, NeverSupported);
|
||||
|
||||
// This format is supported on ES 2.0 with two extensions, so keep it out-of-line to not widen the table above even more.
|
||||
// | Internal format |sized| R | G | B | A |S | Format | Type | Component type | SRGB | Texture supported | Filterable | Texture attachment | Renderbuffer | Blend
|
||||
diff --git a/src/libANGLE/formatutils.h b/src/libANGLE/formatutils.h
|
||||
index af7f6df09efd9b08586a6cebe0042bb9555d4b7f..a651ab8ffc4d51159b9f53c60594f43bf9b83ae5 100644
|
||||
--- a/src/libANGLE/formatutils.h
|
||||
+++ b/src/libANGLE/formatutils.h
|
||||
@@ -205,6 +205,8 @@ struct InternalFormat
|
||||
bool isInt() const;
|
||||
bool isDepthOrStencil() const;
|
||||
|
||||
+ GLuint getEGLConfigBufferSize() const;
|
||||
+
|
||||
bool operator==(const InternalFormat &other) const;
|
||||
bool operator!=(const InternalFormat &other) const;
|
||||
|
||||
diff --git a/src/libANGLE/renderer/d3d/d3d11/Renderer11.cpp b/src/libANGLE/renderer/d3d/d3d11/Renderer11.cpp
|
||||
index cf3c53ec00fff1eaacd5a9cce5742278a49aa314..abd3d5fa2a4c8a84aa6751bf1f6f64b3504a07b6 100644
|
||||
--- a/src/libANGLE/renderer/d3d/d3d11/Renderer11.cpp
|
||||
+++ b/src/libANGLE/renderer/d3d/d3d11/Renderer11.cpp
|
||||
@@ -1263,7 +1263,7 @@ egl::ConfigSet Renderer11::generateConfigs()
|
||||
egl::Config config;
|
||||
config.renderTargetFormat = colorBufferInternalFormat;
|
||||
config.depthStencilFormat = depthStencilBufferInternalFormat;
|
||||
- config.bufferSize = colorBufferFormatInfo.pixelBytes * 8;
|
||||
+ config.bufferSize = colorBufferFormatInfo.getEGLConfigBufferSize();
|
||||
config.redSize = colorBufferFormatInfo.redBits;
|
||||
config.greenSize = colorBufferFormatInfo.greenBits;
|
||||
config.blueSize = colorBufferFormatInfo.blueBits;
|
||||
diff --git a/src/libANGLE/renderer/d3d/d3d9/Renderer9.cpp b/src/libANGLE/renderer/d3d/d3d9/Renderer9.cpp
|
||||
index cfe6ef850d9afb317bdc2c10a8f93b2f98a7a20b..66950965fdeb3d57b84f524920bc41823e6cf377 100644
|
||||
--- a/src/libANGLE/renderer/d3d/d3d9/Renderer9.cpp
|
||||
+++ b/src/libANGLE/renderer/d3d/d3d9/Renderer9.cpp
|
||||
@@ -523,7 +523,7 @@ egl::ConfigSet Renderer9::generateConfigs()
|
||||
egl::Config config;
|
||||
config.renderTargetFormat = colorBufferInternalFormat;
|
||||
config.depthStencilFormat = depthStencilBufferInternalFormat;
|
||||
- config.bufferSize = colorBufferFormatInfo.pixelBytes * 8;
|
||||
+ config.bufferSize = colorBufferFormatInfo.getEGLConfigBufferSize();
|
||||
config.redSize = colorBufferFormatInfo.redBits;
|
||||
config.greenSize = colorBufferFormatInfo.greenBits;
|
||||
config.blueSize = colorBufferFormatInfo.blueBits;
|
||||
diff --git a/src/libANGLE/renderer/vulkan/vk_caps_utils.cpp b/src/libANGLE/renderer/vulkan/vk_caps_utils.cpp
|
||||
index 173a04c1ebb2b7d5f6997d696699fef09e5c0d9c..766750a163cae6ba22502fc0c8922e9421ef52eb 100644
|
||||
--- a/src/libANGLE/renderer/vulkan/vk_caps_utils.cpp
|
||||
+++ b/src/libANGLE/renderer/vulkan/vk_caps_utils.cpp
|
||||
@@ -1257,7 +1257,7 @@ egl::Config GenerateDefaultConfig(DisplayVk *display,
|
||||
|
||||
config.renderTargetFormat = colorFormat.internalFormat;
|
||||
config.depthStencilFormat = depthStencilFormat.internalFormat;
|
||||
- config.bufferSize = colorFormat.pixelBytes * 8;
|
||||
+ config.bufferSize = colorFormat.getEGLConfigBufferSize();
|
||||
config.redSize = colorFormat.redBits;
|
||||
config.greenSize = colorFormat.greenBits;
|
||||
config.blueSize = colorFormat.blueBits;
|
||||
214
patches/angle/cherry-pick-d0ee0197ddff.patch
Normal file
214
patches/angle/cherry-pick-d0ee0197ddff.patch
Normal file
@@ -0,0 +1,214 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Shahbaz Youssefi <syoussefi@chromium.org>
|
||||
Date: Wed, 3 May 2023 13:41:36 -0400
|
||||
Subject: WebGL: Limit total size of private data
|
||||
|
||||
... not just individual arrays.
|
||||
|
||||
Bug: chromium:1431761
|
||||
Change-Id: I721e29aeceeaf12c3f6a67b668abffb8dfbc89b0
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/4503753
|
||||
Reviewed-by: Kenneth Russell <kbr@chromium.org>
|
||||
Commit-Queue: Shahbaz Youssefi <syoussefi@chromium.org>
|
||||
|
||||
diff --git a/src/compiler/translator/ValidateTypeSizeLimitations.cpp b/src/compiler/translator/ValidateTypeSizeLimitations.cpp
|
||||
index c9607db74b53487950d31f6a56d55f3e834556a0..a05e857d7111528ad7f21799e3825b9d3f488dd3 100644
|
||||
--- a/src/compiler/translator/ValidateTypeSizeLimitations.cpp
|
||||
+++ b/src/compiler/translator/ValidateTypeSizeLimitations.cpp
|
||||
@@ -23,6 +23,7 @@ namespace
|
||||
// Arbitrarily enforce that types - even local variables' - declared
|
||||
// with a size in bytes of over 2 GB will cause compilation failure.
|
||||
constexpr size_t kMaxTypeSizeInBytes = static_cast<size_t>(2) * 1024 * 1024 * 1024;
|
||||
+constexpr size_t kMaxPrivateVariableSizeInBytes = static_cast<size_t>(1) * 1024 * 1024;
|
||||
|
||||
// Traverses intermediate tree to ensure that the shader does not
|
||||
// exceed certain implementation-defined limits on the sizes of types.
|
||||
@@ -31,7 +32,9 @@ class ValidateTypeSizeLimitationsTraverser : public TIntermTraverser
|
||||
{
|
||||
public:
|
||||
ValidateTypeSizeLimitationsTraverser(TSymbolTable *symbolTable, TDiagnostics *diagnostics)
|
||||
- : TIntermTraverser(true, false, false, symbolTable), mDiagnostics(diagnostics)
|
||||
+ : TIntermTraverser(true, false, false, symbolTable),
|
||||
+ mDiagnostics(diagnostics),
|
||||
+ mTotalPrivateVariablesSize(0)
|
||||
{
|
||||
ASSERT(diagnostics);
|
||||
}
|
||||
@@ -85,11 +88,37 @@ class ValidateTypeSizeLimitationsTraverser : public TIntermTraverser
|
||||
asSymbol->getName());
|
||||
return false;
|
||||
}
|
||||
+
|
||||
+ const bool isPrivate = variableType.getQualifier() == EvqTemporary ||
|
||||
+ variableType.getQualifier() == EvqGlobal ||
|
||||
+ variableType.getQualifier() == EvqConst;
|
||||
+ if (isPrivate)
|
||||
+ {
|
||||
+ if (layoutEncoder.getCurrentOffset() > kMaxPrivateVariableSizeInBytes)
|
||||
+ {
|
||||
+ error(asSymbol->getLine(),
|
||||
+ "Size of declared private variable exceeds implementation-defined limit",
|
||||
+ asSymbol->getName());
|
||||
+ return false;
|
||||
+ }
|
||||
+ mTotalPrivateVariablesSize += layoutEncoder.getCurrentOffset();
|
||||
+ }
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
+ void validateTotalPrivateVariableSize()
|
||||
+ {
|
||||
+ if (mTotalPrivateVariablesSize > kMaxPrivateVariableSizeInBytes)
|
||||
+ {
|
||||
+ mDiagnostics->error(
|
||||
+ TSourceLoc{},
|
||||
+ "Total size of declared private variables exceeds implementation-defined limit",
|
||||
+ "");
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
private:
|
||||
void error(TSourceLoc loc, const char *reason, const ImmutableString &token)
|
||||
{
|
||||
@@ -198,6 +227,8 @@ class ValidateTypeSizeLimitationsTraverser : public TIntermTraverser
|
||||
|
||||
TDiagnostics *mDiagnostics;
|
||||
std::vector<int> mLoopSymbolIds;
|
||||
+
|
||||
+ size_t mTotalPrivateVariablesSize;
|
||||
};
|
||||
|
||||
} // namespace
|
||||
@@ -208,6 +239,7 @@ bool ValidateTypeSizeLimitations(TIntermNode *root,
|
||||
{
|
||||
ValidateTypeSizeLimitationsTraverser validate(symbolTable, diagnostics);
|
||||
root->traverse(&validate);
|
||||
+ validate.validateTotalPrivateVariableSize();
|
||||
return diagnostics->numErrors() == 0;
|
||||
}
|
||||
|
||||
diff --git a/src/tests/gl_tests/WebGLCompatibilityTest.cpp b/src/tests/gl_tests/WebGLCompatibilityTest.cpp
|
||||
index 7dc56cddbc63add1aca6fca3bfd031f3da8d04fc..64287af5834607f6819f1197e2eed1a56f712ffe 100644
|
||||
--- a/src/tests/gl_tests/WebGLCompatibilityTest.cpp
|
||||
+++ b/src/tests/gl_tests/WebGLCompatibilityTest.cpp
|
||||
@@ -5271,11 +5271,12 @@ TEST_P(WebGLCompatibilityTest, ValidateArraySizes)
|
||||
// fairly small array.
|
||||
constexpr char kVSArrayOK[] =
|
||||
R"(varying vec4 color;
|
||||
-const int array_size = 1000;
|
||||
+const int array_size = 500;
|
||||
void main()
|
||||
{
|
||||
mat2 array[array_size];
|
||||
- if (array[0][0][0] == 2.0)
|
||||
+ mat2 array2[array_size];
|
||||
+ if (array[0][0][0] + array2[0][0][0] == 2.0)
|
||||
color = vec4(0.0, 1.0, 0.0, 1.0);
|
||||
else
|
||||
color = vec4(1.0, 0.0, 0.0, 1.0);
|
||||
@@ -5353,6 +5354,103 @@ void main()
|
||||
EXPECT_EQ(0u, program);
|
||||
}
|
||||
|
||||
+// Reject attempts to allocate too much private memory.
|
||||
+// This is an implementation-defined limit - crbug.com/1431761.
|
||||
+TEST_P(WebGLCompatibilityTest, ValidateTotalPrivateSize)
|
||||
+{
|
||||
+ constexpr char kTooLargeGlobalMemory1[] =
|
||||
+ R"(precision mediump float;
|
||||
+
|
||||
+// 1 MB / 16 bytes per vec4 = 65536
|
||||
+vec4 array[32768];
|
||||
+vec4 array2[32769];
|
||||
+
|
||||
+void main()
|
||||
+{
|
||||
+ if (array[0].x + array[1].x == 0.)
|
||||
+ gl_FragColor = vec4(0.0, 1.0, 0.0, 1.0);
|
||||
+ else
|
||||
+ gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0);
|
||||
+})";
|
||||
+
|
||||
+ constexpr char kTooLargeGlobalMemory2[] =
|
||||
+ R"(precision mediump float;
|
||||
+
|
||||
+// 1 MB / 16 bytes per vec4 = 65536
|
||||
+vec4 array[32767];
|
||||
+vec4 array2[32767];
|
||||
+vec4 x, y, z;
|
||||
+
|
||||
+void main()
|
||||
+{
|
||||
+ if (array[0].x + array[1].x == x.w + y.w + z.w)
|
||||
+ gl_FragColor = vec4(0.0, 1.0, 0.0, 1.0);
|
||||
+ else
|
||||
+ gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0);
|
||||
+})";
|
||||
+
|
||||
+ constexpr char kTooLargeGlobalAndLocalMemory1[] =
|
||||
+ R"(precision mediump float;
|
||||
+
|
||||
+// 1 MB / 16 bytes per vec4 = 65536
|
||||
+vec4 array[32768];
|
||||
+
|
||||
+void main()
|
||||
+{
|
||||
+ vec4 array2[32769];
|
||||
+ if (array[0].x + array[1].x == 2.0)
|
||||
+ gl_FragColor = vec4(0.0, 1.0, 0.0, 1.0);
|
||||
+ else
|
||||
+ gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0);
|
||||
+})";
|
||||
+
|
||||
+ // Note: The call stack is not taken into account for the purposes of total memory calculation.
|
||||
+ constexpr char kTooLargeGlobalAndLocalMemory2[] =
|
||||
+ R"(precision mediump float;
|
||||
+
|
||||
+// 1 MB / 16 bytes per vec4 = 65536
|
||||
+vec4 array[32768];
|
||||
+
|
||||
+float f()
|
||||
+{
|
||||
+ vec4 array2[16384];
|
||||
+ return array2[0].x;
|
||||
+}
|
||||
+
|
||||
+float g()
|
||||
+{
|
||||
+ vec4 array3[16383];
|
||||
+ return array3[0].x;
|
||||
+}
|
||||
+
|
||||
+float h()
|
||||
+{
|
||||
+ vec4 value;
|
||||
+ float value2
|
||||
+ return value.x + value2;
|
||||
+}
|
||||
+
|
||||
+void main()
|
||||
+{
|
||||
+ if (array[0].x + f() + g() + h() == 2.0)
|
||||
+ gl_FragColor = vec4(0.0, 1.0, 0.0, 1.0);
|
||||
+ else
|
||||
+ gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0);
|
||||
+})";
|
||||
+
|
||||
+ GLuint program = CompileProgram(essl1_shaders::vs::Simple(), kTooLargeGlobalMemory1);
|
||||
+ EXPECT_EQ(0u, program);
|
||||
+
|
||||
+ program = CompileProgram(essl1_shaders::vs::Simple(), kTooLargeGlobalMemory2);
|
||||
+ EXPECT_EQ(0u, program);
|
||||
+
|
||||
+ program = CompileProgram(essl1_shaders::vs::Simple(), kTooLargeGlobalAndLocalMemory1);
|
||||
+ EXPECT_EQ(0u, program);
|
||||
+
|
||||
+ program = CompileProgram(essl1_shaders::vs::Simple(), kTooLargeGlobalAndLocalMemory2);
|
||||
+ EXPECT_EQ(0u, program);
|
||||
+}
|
||||
+
|
||||
// Linking should fail when corresponding vertex/fragment uniform blocks have different precision
|
||||
// qualifiers.
|
||||
TEST_P(WebGL2CompatibilityTest, UniformBlockPrecisionMismatch)
|
||||
@@ -126,3 +126,29 @@ chore_patch_out_partition_attribute_dcheck_for_webviews.patch
|
||||
expose_v8initializer_codegenerationcheckcallbackinmainthread.patch
|
||||
chore_patch_out_profile_methods_in_profile_selections_cc.patch
|
||||
fix_x11_window_restore_minimized_maximized_window.patch
|
||||
chore_defer_usb_service_getdevices_request_until_usb_service_is.patch
|
||||
cherry-pick-d9081493c4b2.patch
|
||||
cherry-pick-d6946b70b431.patch
|
||||
revert_x11_keep_windowcache_alive_for_a_time_interval.patch
|
||||
cherry-pick-9585757f9fad.patch
|
||||
cherry-pick-2b30a50d0e62.patch
|
||||
cherry-pick-f58218891f8c.patch
|
||||
cherry-pick-ec53103cc72d.patch
|
||||
cherry-pick-f098ff0d1230.patch
|
||||
cherry-pick-63686953dc22.patch
|
||||
merge_m112_remove_the_second_weakptrfactory_from.patch
|
||||
merge_m112_check_spdyproxyclientsocket_is_alive_after_write.patch
|
||||
check_callback_availability_in.patch
|
||||
m112_cherry_pick_libxml_cve_fix.patch
|
||||
m112_fix_scopedobservation_uaf_in.patch
|
||||
cherry-pick-48785f698b1c.patch
|
||||
cherry-pick-675562695049.patch
|
||||
cherry-pick-ea1cd76358e0.patch
|
||||
m114_merge_fix_a_crash_caused_by_calling_trace_event.patch
|
||||
mojoipcz_copy_incoming_messages_early.patch
|
||||
base_do_not_use_va_args_twice_in_asprintf.patch
|
||||
cherry-pick-85beff6fd302.patch
|
||||
m114_webcodecs_fix_crash_when_changing_temporal_layer_count_in_av1.patch
|
||||
cherry-pick-933b9fad3a53.patch
|
||||
cherry-pick-b03973561862.patch
|
||||
cherry-pick-c60a1ab717c7.patch
|
||||
|
||||
@@ -0,0 +1,96 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Benoit Lize <lizeb@chromium.org>
|
||||
Date: Fri, 9 Jun 2023 17:59:08 +0000
|
||||
Subject: Do not use va_args twice in asprintf()
|
||||
|
||||
(cherry picked from commit 3cff0cb19a6d01cbdd9932f43dabaaeda9c0330a)
|
||||
|
||||
Bug: 1450536
|
||||
Change-Id: Ib34d96935278869a63897f9a1c66afc98865d90f
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/4579347
|
||||
Reviewed-by: Egor Pasko <pasko@chromium.org>
|
||||
Commit-Queue: Benoit Lize <lizeb@chromium.org>
|
||||
Cr-Original-Commit-Position: refs/heads/main@{#1151796}
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/4604070
|
||||
Reviewed-by: Michael Thiessen <mthiesse@chromium.org>
|
||||
Cr-Commit-Position: refs/branch-heads/5735@{#1224}
|
||||
Cr-Branched-From: 2f562e4ddbaf79a3f3cb338b4d1bd4398d49eb67-refs/heads/main@{#1135570}
|
||||
|
||||
diff --git a/base/allocator/partition_allocator/shim/allocator_shim_override_linker_wrapped_symbols.h b/base/allocator/partition_allocator/shim/allocator_shim_override_linker_wrapped_symbols.h
|
||||
index 621873126602463a09efca1bf1548ed10910d323..de2af6d7d54e254b9e7b8264b53d30a338fb13e8 100644
|
||||
--- a/base/allocator/partition_allocator/shim/allocator_shim_override_linker_wrapped_symbols.h
|
||||
+++ b/base/allocator/partition_allocator/shim/allocator_shim_override_linker_wrapped_symbols.h
|
||||
@@ -123,13 +123,21 @@ SHIM_ALWAYS_EXPORT char* __wrap_getcwd(char* buffer, size_t size) {
|
||||
SHIM_ALWAYS_EXPORT int __wrap_vasprintf(char** strp,
|
||||
const char* fmt,
|
||||
va_list va_args) {
|
||||
+ // There are cases where we need to use the list of arguments twice, namely
|
||||
+ // when the original buffer is too small. It is not allowed to walk the list
|
||||
+ // twice, so make a copy for the second invocation of vsnprintf().
|
||||
+ va_list va_args_copy;
|
||||
+ va_copy(va_args_copy, va_args);
|
||||
+
|
||||
constexpr int kInitialSize = 128;
|
||||
*strp = static_cast<char*>(
|
||||
malloc(kInitialSize)); // Our malloc() doesn't return nullptr.
|
||||
|
||||
int actual_size = vsnprintf(*strp, kInitialSize, fmt, va_args);
|
||||
- if (actual_size < 0)
|
||||
+ if (actual_size < 0) {
|
||||
+ va_end(va_args_copy);
|
||||
return actual_size;
|
||||
+ }
|
||||
*strp =
|
||||
static_cast<char*>(realloc(*strp, static_cast<size_t>(actual_size + 1)));
|
||||
|
||||
@@ -139,9 +147,14 @@ SHIM_ALWAYS_EXPORT int __wrap_vasprintf(char** strp,
|
||||
//
|
||||
// This is very lightly used in Chromium in practice, see crbug.com/116558 for
|
||||
// details.
|
||||
- if (actual_size >= kInitialSize)
|
||||
- return vsnprintf(*strp, static_cast<size_t>(actual_size + 1), fmt, va_args);
|
||||
-
|
||||
+ if (actual_size >= kInitialSize) {
|
||||
+ int ret = vsnprintf(*strp, static_cast<size_t>(actual_size + 1), fmt,
|
||||
+ va_args_copy);
|
||||
+ va_end(va_args_copy);
|
||||
+ return ret;
|
||||
+ }
|
||||
+
|
||||
+ va_end(va_args_copy);
|
||||
return actual_size;
|
||||
}
|
||||
|
||||
diff --git a/base/allocator/partition_allocator/shim/allocator_shim_unittest.cc b/base/allocator/partition_allocator/shim/allocator_shim_unittest.cc
|
||||
index 59b4a2c915caa192346f3fa342c5a2852a2f7b9b..1f3d5956b198ddf89cdf6951739ef68a29a74936 100644
|
||||
--- a/base/allocator/partition_allocator/shim/allocator_shim_unittest.cc
|
||||
+++ b/base/allocator/partition_allocator/shim/allocator_shim_unittest.cc
|
||||
@@ -726,6 +726,28 @@ TEST_F(AllocatorShimTest, InterceptVasprintf) {
|
||||
// Should not crash.
|
||||
}
|
||||
|
||||
+TEST_F(AllocatorShimTest, InterceptLongVasprintf) {
|
||||
+ char* str = nullptr;
|
||||
+ const char* lorem_ipsum =
|
||||
+ "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed non risus. "
|
||||
+ "Suspendisse lectus tortor, dignissim sit amet, adipiscing nec, "
|
||||
+ "ultricies sed, dolor. Cras elementum ultrices diam. Maecenas ligula "
|
||||
+ "massa, varius a, semper congue, euismod non, mi. Proin porttitor, orci "
|
||||
+ "nec nonummy molestie, enim est eleifend mi, non fermentum diam nisl sit "
|
||||
+ "amet erat. Duis semper. Duis arcu massa, scelerisque vitae, consequat "
|
||||
+ "in, pretium a, enim. Pellentesque congue. Ut in risus volutpat libero "
|
||||
+ "pharetra tempor. Cras vestibulum bibendum augue. Praesent egestas leo "
|
||||
+ "in pede. Praesent blandit odio eu enim. Pellentesque sed dui ut augue "
|
||||
+ "blandit sodales. Vestibulum ante ipsum primis in faucibus orci luctus "
|
||||
+ "et ultrices posuere cubilia Curae; Aliquam nibh. Mauris ac mauris sed "
|
||||
+ "pede pellentesque fermentum. Maecenas adipiscing ante non diam sodales "
|
||||
+ "hendrerit.";
|
||||
+ int err = asprintf(&str, "%s", lorem_ipsum);
|
||||
+ EXPECT_EQ(err, static_cast<int>(strlen(lorem_ipsum)));
|
||||
+ EXPECT_TRUE(str);
|
||||
+ free(str);
|
||||
+}
|
||||
+
|
||||
#endif // BUILDFLAG(USE_PARTITION_ALLOC_AS_MALLOC)
|
||||
|
||||
#endif // BUILDFLAG(IS_ANDROID)
|
||||
36
patches/chromium/check_callback_availability_in.patch
Normal file
36
patches/chromium/check_callback_availability_in.patch
Normal file
@@ -0,0 +1,36 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Kenichi Ishibashi <bashi@chromium.org>
|
||||
Date: Tue, 18 Apr 2023 05:58:29 +0000
|
||||
Subject: Check callback availability in
|
||||
SpdyProxyClientSocket::RunWriteCallback
|
||||
|
||||
OnClose() could consume `write_callback_` so it may not be available
|
||||
when RunWriteCallback() is invoked.
|
||||
|
||||
Bug: 1428820
|
||||
Change-Id: I9a5ade62d67f5bf15e12d0915d1ad6098657ffd4
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/4437791
|
||||
Code-Coverage: Findit <findit-for-me@appspot.gserviceaccount.com>
|
||||
Reviewed-by: Adam Rice <ricea@chromium.org>
|
||||
Commit-Queue: Kenichi Ishibashi <bashi@chromium.org>
|
||||
Cr-Commit-Position: refs/heads/main@{#1131689}
|
||||
|
||||
diff --git a/net/spdy/spdy_proxy_client_socket.cc b/net/spdy/spdy_proxy_client_socket.cc
|
||||
index 73ca8d0c2958e532ac9810f5de40405d6e91cdeb..e1b9ba74afc49a5ddef1f45ada996bad3db05d12 100644
|
||||
--- a/net/spdy/spdy_proxy_client_socket.cc
|
||||
+++ b/net/spdy/spdy_proxy_client_socket.cc
|
||||
@@ -277,10 +277,11 @@ int SpdyProxyClientSocket::GetLocalAddress(IPEndPoint* address) const {
|
||||
}
|
||||
|
||||
void SpdyProxyClientSocket::RunWriteCallback(int result) {
|
||||
- CHECK(write_callback_);
|
||||
-
|
||||
base::WeakPtr<SpdyProxyClientSocket> weak_ptr = weak_factory_.GetWeakPtr();
|
||||
- std::move(write_callback_).Run(result);
|
||||
+ // `write_callback_` might be consumed by OnClose().
|
||||
+ if (write_callback_) {
|
||||
+ std::move(write_callback_).Run(result);
|
||||
+ }
|
||||
if (!weak_ptr) {
|
||||
// `this` was already destroyed while running `write_callback_`. Must
|
||||
// return immediately without touching any field member.
|
||||
91
patches/chromium/cherry-pick-2b30a50d0e62.patch
Normal file
91
patches/chromium/cherry-pick-2b30a50d0e62.patch
Normal file
@@ -0,0 +1,91 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Yoshisato Yanagisawa <yyanagisawa@chromium.org>
|
||||
Date: Mon, 10 Apr 2023 05:32:06 +0000
|
||||
Subject: Use ScriptState::Scope instead of setting HandleScope.
|
||||
|
||||
Since `GetEffectiveFunction` may call `Get` if the given v8 listener is
|
||||
an object, we need to prepare `v8::Context::Scope` before calling it.
|
||||
Blink already have a helper class to prepare the environment for the
|
||||
script execution, which has already been used used in other
|
||||
ServiceWorkerGlobalScope member functions. It is `ScriptState::Scope`
|
||||
This CL also use it instead.
|
||||
|
||||
(cherry picked from commit 299385e09d41d5ce3abd434879b5f9b0a8880cd7)
|
||||
|
||||
Bug: 1429197
|
||||
Change-Id: Idbcfdfa9c06160a18b57155a9540f72eed4ec0b8
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/4387655
|
||||
Commit-Queue: Yoshisato Yanagisawa <yyanagisawa@chromium.org>
|
||||
Commit-Queue: Kouhei Ueno <kouhei@chromium.org>
|
||||
Reviewed-by: Leszek Swirski <leszeks@chromium.org>
|
||||
Auto-Submit: Yoshisato Yanagisawa <yyanagisawa@chromium.org>
|
||||
Reviewed-by: Kouhei Ueno <kouhei@chromium.org>
|
||||
Cr-Original-Commit-Position: refs/heads/main@{#1125148}
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/4411454
|
||||
Reviewed-by: Shunya Shishido <sisidovski@chromium.org>
|
||||
Cr-Commit-Position: refs/branch-heads/5615@{#1191}
|
||||
Cr-Branched-From: 9c6408ef696e83a9936b82bbead3d41c93c82ee4-refs/heads/main@{#1109224}
|
||||
|
||||
diff --git a/content/browser/service_worker/service_worker_version_browsertest.cc b/content/browser/service_worker/service_worker_version_browsertest.cc
|
||||
index 8ab1f54b2453fe100fdc9b4f1b41ce031c5ecf29..5834127a6e70389540cbf347e65ae4bc80495317 100644
|
||||
--- a/content/browser/service_worker/service_worker_version_browsertest.cc
|
||||
+++ b/content/browser/service_worker/service_worker_version_browsertest.cc
|
||||
@@ -976,6 +976,18 @@ IN_PROC_BROWSER_TEST_F(ServiceWorkerVersionBrowserTest,
|
||||
version_->fetch_handler_type());
|
||||
}
|
||||
|
||||
+IN_PROC_BROWSER_TEST_F(ServiceWorkerVersionBrowserTest,
|
||||
+ NonFunctionFetchHandlerWithHandleEventProperty) {
|
||||
+ StartServerAndNavigateToSetup();
|
||||
+ ASSERT_EQ(
|
||||
+ Install("/service_worker/fetch_event_with_handle_event_property.js"),
|
||||
+ blink::ServiceWorkerStatusCode::kOk);
|
||||
+ EXPECT_EQ(ServiceWorkerVersion::FetchHandlerExistence::EXISTS,
|
||||
+ version_->fetch_handler_existence());
|
||||
+ EXPECT_EQ(ServiceWorkerVersion::FetchHandlerType::kNotSkippable,
|
||||
+ version_->fetch_handler_type());
|
||||
+}
|
||||
+
|
||||
// Check that fetch event handler added in the install event should result in a
|
||||
// service worker that doesn't count as having a fetch event handler.
|
||||
IN_PROC_BROWSER_TEST_F(ServiceWorkerVersionBrowserTest,
|
||||
diff --git a/content/test/data/service_worker/fetch_event_with_handle_event_property.js b/content/test/data/service_worker/fetch_event_with_handle_event_property.js
|
||||
new file mode 100644
|
||||
index 0000000000000000000000000000000000000000..2fe6153af242a10162f7ecb8eaab93c17d840211
|
||||
--- /dev/null
|
||||
+++ b/content/test/data/service_worker/fetch_event_with_handle_event_property.js
|
||||
@@ -0,0 +1,11 @@
|
||||
+// Copyright 2023 The Chromium Authors
|
||||
+// Use of this source code is governed by a BSD-style license that can be
|
||||
+// found in the LICENSE file.
|
||||
+
|
||||
+let obj = {};
|
||||
+Object.defineProperty(obj, "handleEvent", {
|
||||
+ get: () => {},
|
||||
+ configurable: true,
|
||||
+ enumerable: true,
|
||||
+});
|
||||
+self.addEventListener('fetch', obj);
|
||||
diff --git a/third_party/blink/renderer/modules/service_worker/service_worker_global_scope.cc b/third_party/blink/renderer/modules/service_worker/service_worker_global_scope.cc
|
||||
index bbbbcd3691ac646716d78a17251909fc4ba43ea0..9438405e331f1978a5c9b76bf8a7148064fb6b7d 100644
|
||||
--- a/third_party/blink/renderer/modules/service_worker/service_worker_global_scope.cc
|
||||
+++ b/third_party/blink/renderer/modules/service_worker/service_worker_global_scope.cc
|
||||
@@ -2619,12 +2619,15 @@ ServiceWorkerGlobalScope::FetchHandlerType() {
|
||||
if (!elv) {
|
||||
return mojom::blink::ServiceWorkerFetchHandlerType::kNoHandler;
|
||||
}
|
||||
- v8::Isolate* isolate = GetIsolate();
|
||||
- v8::HandleScope handle_scope(isolate);
|
||||
+
|
||||
+ ScriptState* script_state = ScriptController()->GetScriptState();
|
||||
+ // Do not remove this, |scope| is needed by `GetEffectiveFunction`.
|
||||
+ ScriptState::Scope scope(script_state);
|
||||
+
|
||||
// TODO(crbug.com/1349613): revisit the way to implement this.
|
||||
// The following code returns kEmptyFetchHandler if all handlers are nop.
|
||||
for (RegisteredEventListener& e : *elv) {
|
||||
- EventTarget* et = EventTarget::Create(ScriptController()->GetScriptState());
|
||||
+ EventTarget* et = EventTarget::Create(script_state);
|
||||
v8::Local<v8::Value> v =
|
||||
To<JSBasedEventListener>(e.Callback())->GetEffectiveFunction(*et);
|
||||
if (!v->IsFunction() ||
|
||||
107
patches/chromium/cherry-pick-48785f698b1c.patch
Normal file
107
patches/chromium/cherry-pick-48785f698b1c.patch
Normal file
@@ -0,0 +1,107 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Arthur Sonzogni <arthursonzogni@chromium.org>
|
||||
Date: Tue, 2 May 2023 09:40:37 +0000
|
||||
Subject: Avoid buffer overflow read in HFSReadNextNonIgnorableCodePoint
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
|
||||
Unicode codepoints goes beyond 0xFFFF.
|
||||
|
||||
It exists upper and lower case characters there: `𞤡 `vs `𞥃`.
|
||||
|
||||
The buffer overflow occurred when using the lookup table:
|
||||
```
|
||||
lower_case_table[codepoint >> 8]
|
||||
```
|
||||
|
||||
Bug: 1425115
|
||||
Fixed: 1425115
|
||||
Change-Id: I679da02dbe570283a68176fbd3c0c620caa4f9ce
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/4481260
|
||||
Reviewed-by: Alexander Timin <altimin@chromium.org>
|
||||
Commit-Queue: Arthur Sonzogni <arthursonzogni@chromium.org>
|
||||
Cr-Commit-Position: refs/heads/main@{#1138234}
|
||||
|
||||
diff --git a/base/files/file_path.cc b/base/files/file_path.cc
|
||||
index a43c09317da96332584286fdb67284b2bedd753f..3a7cca6fad051816d6d018857c8039594c51ec65 100644
|
||||
--- a/base/files/file_path.cc
|
||||
+++ b/base/files/file_path.cc
|
||||
@@ -775,7 +775,7 @@ int FilePath::CompareIgnoreCase(StringPieceType string1,
|
||||
#elif BUILDFLAG(IS_APPLE)
|
||||
// Mac OS X specific implementation of file string comparisons.
|
||||
|
||||
-// cf. http://developer.apple.com/mac/library/technotes/tn/tn1150.html#UnicodeSubtleties
|
||||
+// cf. https://developer.apple.com/library/archive/technotes/tn/tn1150.html#UnicodeSubtleties
|
||||
//
|
||||
// "When using CreateTextEncoding to create a text encoding, you should set
|
||||
// the TextEncodingBase to kTextEncodingUnicodeV2_0, set the
|
||||
@@ -801,11 +801,12 @@ int FilePath::CompareIgnoreCase(StringPieceType string1,
|
||||
// Ignored characters are mapped to zero.
|
||||
//
|
||||
// cf. downloadable file linked in
|
||||
-// http://developer.apple.com/mac/library/technotes/tn/tn1150.html#StringComparisonAlgorithm
|
||||
+// https://developer.apple.com/library/archive/technotes/tn/tn1150.html#Downloads
|
||||
|
||||
namespace {
|
||||
|
||||
-const UInt16 lower_case_table[] = {
|
||||
+// clang-format off
|
||||
+const UInt16 lower_case_table[11 * 256] = {
|
||||
// High-byte indices ( == 0 iff no case mapping and no ignorables )
|
||||
|
||||
/* 0 */ 0x0100, 0x0200, 0x0000, 0x0300, 0x0400, 0x0500, 0x0000, 0x0000,
|
||||
@@ -1191,11 +1192,12 @@ const UInt16 lower_case_table[] = {
|
||||
/* F */ 0xFFF0, 0xFFF1, 0xFFF2, 0xFFF3, 0xFFF4, 0xFFF5, 0xFFF6, 0xFFF7,
|
||||
0xFFF8, 0xFFF9, 0xFFFA, 0xFFFB, 0xFFFC, 0xFFFD, 0xFFFE, 0xFFFF,
|
||||
};
|
||||
+// clang-format on
|
||||
|
||||
-// Returns the next non-ignorable codepoint within string starting from the
|
||||
-// position indicated by index, or zero if there are no more.
|
||||
-// The passed-in index is automatically advanced as the characters in the input
|
||||
-// HFS-decomposed UTF-8 strings are read.
|
||||
+// Returns the next non-ignorable codepoint within `string` starting from the
|
||||
+// position indicated by `index`, or zero if there are no more.
|
||||
+// The passed-in `index` is automatically advanced as the characters in the
|
||||
+// input HFS-decomposed UTF-8 strings are read.
|
||||
inline base_icu::UChar32 HFSReadNextNonIgnorableCodepoint(const char* string,
|
||||
size_t length,
|
||||
size_t* index) {
|
||||
@@ -1206,12 +1208,16 @@ inline base_icu::UChar32 HFSReadNextNonIgnorableCodepoint(const char* string,
|
||||
CBU8_NEXT(reinterpret_cast<const uint8_t*>(string), *index, length,
|
||||
codepoint);
|
||||
DCHECK_GT(codepoint, 0);
|
||||
- if (codepoint > 0) {
|
||||
+
|
||||
+ // Note: Here, there are no lower case conversion implemented in the
|
||||
+ // Supplementary Multilingual Plane (codepoint > 0xFFFF).
|
||||
+
|
||||
+ if (codepoint > 0 && codepoint <= 0xFFFF) {
|
||||
// Check if there is a subtable for this upper byte.
|
||||
int lookup_offset = lower_case_table[codepoint >> 8];
|
||||
if (lookup_offset != 0)
|
||||
codepoint = lower_case_table[lookup_offset + (codepoint & 0x00FF)];
|
||||
- // Note: codepoint1 may be again 0 at this point if the character was
|
||||
+ // Note: `codepoint` may be again 0 at this point if the character was
|
||||
// an ignorable.
|
||||
}
|
||||
}
|
||||
diff --git a/base/files/file_path_unittest.cc b/base/files/file_path_unittest.cc
|
||||
index 3cfdcbe445c1f6e0d66e3798927131f94759fb3c..08c3e75b7e1ad55f5f81aed80f80081115f8f49c 100644
|
||||
--- a/base/files/file_path_unittest.cc
|
||||
+++ b/base/files/file_path_unittest.cc
|
||||
@@ -1195,6 +1195,13 @@ TEST_F(FilePathTest, CompareIgnoreCase) {
|
||||
{{FPL("K\u0301U\u032DO\u0304\u0301N"), FPL("\u1E31\u1E77\u1E53n")}, 0},
|
||||
{{FPL("k\u0301u\u032Do\u0304\u0301n"), FPL("\u1E30\u1E76\u1E52n")}, 0},
|
||||
{{FPL("k\u0301u\u032Do\u0304\u0302n"), FPL("\u1E30\u1E76\u1E52n")}, 1},
|
||||
+
|
||||
+ // Codepoints > 0xFFFF
|
||||
+ // Here, we compare the `Adlam Letter Shu` in its capital and small version.
|
||||
+ {{FPL("\U0001E921"), FPL("\U0001E943")}, -1},
|
||||
+ {{FPL("\U0001E943"), FPL("\U0001E921")}, 1},
|
||||
+ {{FPL("\U0001E921"), FPL("\U0001E921")}, 0},
|
||||
+ {{FPL("\U0001E943"), FPL("\U0001E943")}, 0},
|
||||
#endif
|
||||
};
|
||||
|
||||
124
patches/chromium/cherry-pick-63686953dc22.patch
Normal file
124
patches/chromium/cherry-pick-63686953dc22.patch
Normal file
@@ -0,0 +1,124 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Florian Leimgruber <fleimgruber@google.com>
|
||||
Date: Thu, 6 Apr 2023 09:21:41 +0000
|
||||
Subject: Add lock to AlternativeStateNameMap.
|
||||
|
||||
To prevent the class from accessing its localized_state_names_map_ and
|
||||
localized_state_names_reverse_lookup_map_ members, a lock is added. It
|
||||
locks all reads/write from the aforementioned members.
|
||||
|
||||
(cherry picked from commit dd848883aa0d7d88520846bbf6735eaae9f2b60e)
|
||||
|
||||
Bug: 1360571, 1414241, 1425951
|
||||
Change-Id: Ic01b0cba3878748617863274deb04ec9e13645d4
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/4352658
|
||||
Reviewed-by: Christoph Schwering <schwering@google.com>
|
||||
Commit-Queue: Florian Leimgruber <fleimgruber@google.com>
|
||||
Cr-Original-Commit-Position: refs/heads/main@{#1119411}
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/4402262
|
||||
Auto-Submit: Florian Leimgruber <fleimgruber@google.com>
|
||||
Cr-Commit-Position: refs/branch-heads/5615@{#1147}
|
||||
Cr-Branched-From: 9c6408ef696e83a9936b82bbead3d41c93c82ee4-refs/heads/main@{#1109224}
|
||||
|
||||
diff --git a/components/autofill/core/browser/geo/alternative_state_name_map.cc b/components/autofill/core/browser/geo/alternative_state_name_map.cc
|
||||
index d217082a0faf23d2fd74dce8eec1043d83b5e509..ed22752c50f15e1f45e48b9ef561b0cb7134fba8 100644
|
||||
--- a/components/autofill/core/browser/geo/alternative_state_name_map.cc
|
||||
+++ b/components/autofill/core/browser/geo/alternative_state_name_map.cc
|
||||
@@ -53,7 +53,6 @@ AlternativeStateNameMap::GetCanonicalStateName(
|
||||
const CountryCode& country_code,
|
||||
const StateName& state_name,
|
||||
bool is_state_name_normalized) const {
|
||||
- DCHECK_CALLED_ON_VALID_SEQUENCE(alternative_state_name_map_sequence_checker_);
|
||||
// Example:
|
||||
// Entries in |localized_state_names_map_| are:
|
||||
// ("DE", "Bavaria") -> {
|
||||
@@ -73,6 +72,7 @@ AlternativeStateNameMap::GetCanonicalStateName(
|
||||
if (!is_state_name_normalized)
|
||||
normalized_state_name = NormalizeStateName(state_name);
|
||||
|
||||
+ base::AutoLock lock(lock_);
|
||||
auto it = localized_state_names_reverse_lookup_map_.find(
|
||||
{country_code, normalized_state_name});
|
||||
if (it != localized_state_names_reverse_lookup_map_.end())
|
||||
@@ -84,8 +84,6 @@ AlternativeStateNameMap::GetCanonicalStateName(
|
||||
absl::optional<StateEntry> AlternativeStateNameMap::GetEntry(
|
||||
const CountryCode& country_code,
|
||||
const StateName& state_string_from_profile) const {
|
||||
- DCHECK_CALLED_ON_VALID_SEQUENCE(alternative_state_name_map_sequence_checker_);
|
||||
-
|
||||
StateName normalized_state_string_from_profile =
|
||||
NormalizeStateName(state_string_from_profile);
|
||||
absl::optional<CanonicalStateName> canonical_state_name =
|
||||
@@ -93,6 +91,7 @@ absl::optional<StateEntry> AlternativeStateNameMap::GetEntry(
|
||||
/*is_state_name_normalized=*/true);
|
||||
|
||||
if (canonical_state_name) {
|
||||
+ base::AutoLock lock(lock_);
|
||||
auto it = localized_state_names_map_.find(
|
||||
{country_code, canonical_state_name.value()});
|
||||
if (it != localized_state_names_map_.end())
|
||||
@@ -108,8 +107,6 @@ void AlternativeStateNameMap::AddEntry(
|
||||
const StateEntry& state_entry,
|
||||
const std::vector<StateName>& normalized_alternative_state_names,
|
||||
const CanonicalStateName& normalized_canonical_state_name) {
|
||||
- DCHECK_CALLED_ON_VALID_SEQUENCE(alternative_state_name_map_sequence_checker_);
|
||||
-
|
||||
// Example:
|
||||
// AddEntry("DE", "Bavaria", {
|
||||
// "canonical_name": "Bayern",
|
||||
@@ -126,12 +123,15 @@ void AlternativeStateNameMap::AddEntry(
|
||||
// ("DE", "Bayern") -> "Bayern"
|
||||
// ("DE", "BY") -> "Bayern"
|
||||
// ("DE", "Bavaria") -> "Bayern"
|
||||
- if (localized_state_names_map_.size() == kMaxMapSize ||
|
||||
- GetCanonicalStateName(country_code, normalized_state_value_from_profile,
|
||||
+ if (GetCanonicalStateName(country_code, normalized_state_value_from_profile,
|
||||
/*is_state_name_normalized=*/true)) {
|
||||
return;
|
||||
}
|
||||
|
||||
+ base::AutoLock lock(lock_);
|
||||
+ if (localized_state_names_map_.size() == kMaxMapSize) {
|
||||
+ return;
|
||||
+ }
|
||||
localized_state_names_map_[{country_code, normalized_canonical_state_name}] =
|
||||
state_entry;
|
||||
for (const auto& alternative_name : normalized_alternative_state_names) {
|
||||
@@ -141,12 +141,12 @@ void AlternativeStateNameMap::AddEntry(
|
||||
}
|
||||
|
||||
bool AlternativeStateNameMap::IsLocalisedStateNamesMapEmpty() const {
|
||||
- DCHECK_CALLED_ON_VALID_SEQUENCE(alternative_state_name_map_sequence_checker_);
|
||||
+ base::AutoLock lock(lock_);
|
||||
return localized_state_names_map_.empty();
|
||||
}
|
||||
|
||||
void AlternativeStateNameMap::ClearAlternativeStateNameMap() {
|
||||
- DCHECK_CALLED_ON_VALID_SEQUENCE(alternative_state_name_map_sequence_checker_);
|
||||
+ base::AutoLock lock(lock_);
|
||||
localized_state_names_map_.clear();
|
||||
localized_state_names_reverse_lookup_map_.clear();
|
||||
}
|
||||
diff --git a/components/autofill/core/browser/geo/alternative_state_name_map.h b/components/autofill/core/browser/geo/alternative_state_name_map.h
|
||||
index d20cdf8a02fff5d3c3ea91ef3aa67c6522804692..58dd754bfbf39fd24c82e6d46ccb566008a4cd73 100644
|
||||
--- a/components/autofill/core/browser/geo/alternative_state_name_map.h
|
||||
+++ b/components/autofill/core/browser/geo/alternative_state_name_map.h
|
||||
@@ -9,7 +9,7 @@
|
||||
|
||||
#include "base/i18n/case_conversion.h"
|
||||
#include "base/no_destructor.h"
|
||||
-#include "base/sequence_checker.h"
|
||||
+#include "base/synchronization/lock.h"
|
||||
#include "base/types/strong_alias.h"
|
||||
#include "components/autofill/core/browser/proto/states.pb.h"
|
||||
#include "third_party/abseil-cpp/absl/types/optional.h"
|
||||
@@ -177,7 +177,8 @@ class AlternativeStateNameMap {
|
||||
CaseInsensitiveLessComparator>
|
||||
localized_state_names_reverse_lookup_map_;
|
||||
|
||||
- SEQUENCE_CHECKER(alternative_state_name_map_sequence_checker_);
|
||||
+ // TODO(crbug.com/1425951): Remove lock.
|
||||
+ mutable base::Lock lock_;
|
||||
};
|
||||
|
||||
} // namespace autofill
|
||||
142
patches/chromium/cherry-pick-675562695049.patch
Normal file
142
patches/chromium/cherry-pick-675562695049.patch
Normal file
@@ -0,0 +1,142 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Rakina Zata Amni <rakina@chromium.org>
|
||||
Date: Mon, 15 May 2023 03:21:49 +0000
|
||||
Subject: Return after ReadyCommitNavigation call in CommitErrorPage if it
|
||||
deletes NavigationRequest
|
||||
|
||||
NavigationRequest::ReadyToCommitNavigation() can cause deletion of the
|
||||
NavigationRequest, so callers should check for that possibility after
|
||||
calling the function. A caller in CommitErrorPage is missing that
|
||||
check, which this CL adds, along with a regression test.
|
||||
|
||||
(cherry picked from commit 42db806805ef2be64ee92803d3a784631b2a7df0)
|
||||
|
||||
Bug: 1444360
|
||||
Change-Id: I3964da4909a6709b7730d25d6497b19c098f4f21
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/4520493
|
||||
Commit-Queue: Charlie Reis <creis@chromium.org>
|
||||
Reviewed-by: Charlie Reis <creis@chromium.org>
|
||||
Cr-Original-Commit-Position: refs/heads/main@{#1143298}
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/4531446
|
||||
Reviewed-by: Prudhvikumar Bommana <pbommana@google.com>
|
||||
Commit-Queue: Rakina Zata Amni <rakina@chromium.org>
|
||||
Commit-Queue: Prudhvikumar Bommana <pbommana@google.com>
|
||||
Owners-Override: Prudhvikumar Bommana <pbommana@google.com>
|
||||
Cr-Commit-Position: refs/branch-heads/5735@{#607}
|
||||
Cr-Branched-From: 2f562e4ddbaf79a3f3cb338b4d1bd4398d49eb67-refs/heads/main@{#1135570}
|
||||
|
||||
diff --git a/content/browser/renderer_host/navigation_request.cc b/content/browser/renderer_host/navigation_request.cc
|
||||
index fd95d91a9a4efbfbbcfb117d9f2129b1b1c95011..c3f1bb989c30bf00750404995d080c3b8ee0e1c6 100644
|
||||
--- a/content/browser/renderer_host/navigation_request.cc
|
||||
+++ b/content/browser/renderer_host/navigation_request.cc
|
||||
@@ -5034,7 +5034,13 @@ void NavigationRequest::CommitErrorPage(
|
||||
}
|
||||
}
|
||||
|
||||
+ base::WeakPtr<NavigationRequest> weak_self(weak_factory_.GetWeakPtr());
|
||||
ReadyToCommitNavigation(true /* is_error */);
|
||||
+ // The caller above might result in the deletion of `this`. Return immediately
|
||||
+ // if so.
|
||||
+ if (!weak_self) {
|
||||
+ return;
|
||||
+ }
|
||||
|
||||
PopulateDocumentTokenForCrossDocumentNavigation();
|
||||
// Use a separate cache shard, and no cookies, for error pages.
|
||||
diff --git a/content/browser/renderer_host/navigation_request_browsertest.cc b/content/browser/renderer_host/navigation_request_browsertest.cc
|
||||
index 1213eb485a25a183ca23643941ae97ee6cfb596f..837af410e31d90769cb7e5d0f9c0bb9abf3035df 100644
|
||||
--- a/content/browser/renderer_host/navigation_request_browsertest.cc
|
||||
+++ b/content/browser/renderer_host/navigation_request_browsertest.cc
|
||||
@@ -44,6 +44,7 @@
|
||||
#include "content/public/test/prerender_test_util.h"
|
||||
#include "content/public/test/test_frame_navigation_observer.h"
|
||||
#include "content/public/test/test_navigation_observer.h"
|
||||
+#include "content/public/test/test_service.mojom.h"
|
||||
#include "content/public/test/test_utils.h"
|
||||
#include "content/public/test/url_loader_interceptor.h"
|
||||
#include "content/shell/browser/shell.h"
|
||||
@@ -4032,4 +4033,84 @@ IN_PROC_BROWSER_TEST_P(NavigationRequestMPArchBrowserTest,
|
||||
}
|
||||
}
|
||||
|
||||
+// Tests that when trying to commit an error page for a failed navigation, but
|
||||
+// the renderer process of the, the navigation won't commit and won't crash.
|
||||
+// Regression test for https://crbug.com/1444360.
|
||||
+IN_PROC_BROWSER_TEST_F(NavigationRequestBrowserTest,
|
||||
+ RendererCrashedBeforeCommitErrorPage) {
|
||||
+ // Navigate to `url_a` first.
|
||||
+ GURL url_a(embedded_test_server()->GetURL("a.com", "/title1.html"));
|
||||
+ ASSERT_TRUE(NavigateToURL(shell(), url_a));
|
||||
+
|
||||
+ // Set up an URLLoaderInterceptor which will cause future navigations to fail.
|
||||
+ auto url_loader_interceptor = std::make_unique<URLLoaderInterceptor>(
|
||||
+ base::BindRepeating([](URLLoaderInterceptor::RequestParams* params) {
|
||||
+ network::URLLoaderCompletionStatus status;
|
||||
+ status.error_code = net::ERR_NOT_IMPLEMENTED;
|
||||
+ params->client->OnComplete(status);
|
||||
+ return true;
|
||||
+ }));
|
||||
+
|
||||
+ // Do a navigation to `url_b1` that will fail and commit an error page. This
|
||||
+ // is important so that the next error page navigation won't need to create a
|
||||
+ // speculative RenderFrameHost (unless RenderDocument is enabled) and won't
|
||||
+ // get cancelled earlier than commit time due to speculative RFH deletion.
|
||||
+ GURL url_b1(embedded_test_server()->GetURL("b.com", "/title1.html"));
|
||||
+ EXPECT_FALSE(NavigateToURL(shell(), url_b1));
|
||||
+ EXPECT_EQ(shell()->web_contents()->GetLastCommittedURL(), url_b1);
|
||||
+ EXPECT_TRUE(
|
||||
+ shell()->web_contents()->GetPrimaryMainFrame()->IsErrorDocument());
|
||||
+
|
||||
+ // For the next navigation, set up a throttle that will be used to wait for
|
||||
+ // WillFailRequest() and then defer the navigation, so that we can crash the
|
||||
+ // error page process first.
|
||||
+ TestNavigationThrottleInstaller installer(
|
||||
+ shell()->web_contents(),
|
||||
+ NavigationThrottle::PROCEED /* will_start_result */,
|
||||
+ NavigationThrottle::PROCEED /* will_redirect_result */,
|
||||
+ NavigationThrottle::DEFER /* will_fail_result */,
|
||||
+ NavigationThrottle::PROCEED /* will_process_result */,
|
||||
+ NavigationThrottle::PROCEED /* will_commit_without_url_loader_result */);
|
||||
+
|
||||
+ // Start a navigation to `url_b2` that will also fail, but before it commits
|
||||
+ // an error page, cause the error page process to crash.
|
||||
+ GURL url_b2(embedded_test_server()->GetURL("b.com", "/title2.html"));
|
||||
+ TestNavigationManager manager(shell()->web_contents(), url_b2);
|
||||
+ shell()->LoadURL(url_b2);
|
||||
+ EXPECT_TRUE(manager.WaitForRequestStart());
|
||||
+
|
||||
+ // Resume the navigation and wait for WillFailRequest(). After this point, we
|
||||
+ // will have picked the final RenderFrameHost & RenderProcessHost for the
|
||||
+ // failed navigation.
|
||||
+ manager.ResumeNavigation();
|
||||
+ installer.WaitForThrottleWillFail();
|
||||
+
|
||||
+ // Kill the error page process. This will cause for the navigation to `url_b2`
|
||||
+ // to return early in `NavigationRequest::ReadyToCommitNavigation()` and not
|
||||
+ // commit a new error page.
|
||||
+ RenderProcessHost* process_to_kill =
|
||||
+ manager.GetNavigationHandle()->GetRenderFrameHost()->GetProcess();
|
||||
+ ASSERT_TRUE(process_to_kill->IsInitializedAndNotDead());
|
||||
+ {
|
||||
+ // Trigger a renderer kill by calling DoSomething() which will cause a bad
|
||||
+ // message to be reported.
|
||||
+ RenderProcessHostBadIpcMessageWaiter kill_waiter(process_to_kill);
|
||||
+ mojo::Remote<mojom::TestService> service;
|
||||
+ process_to_kill->BindReceiver(service.BindNewPipeAndPassReceiver());
|
||||
+ service->DoSomething(base::DoNothing());
|
||||
+ EXPECT_EQ(bad_message::RPH_MOJO_PROCESS_ERROR, kill_waiter.Wait());
|
||||
+ }
|
||||
+ ASSERT_FALSE(process_to_kill->IsInitializedAndNotDead());
|
||||
+
|
||||
+ // Resume the navigation, which won't commit.
|
||||
+ if (!ShouldCreateNewHostForAllFrames()) {
|
||||
+ installer.navigation_throttle()->ResumeNavigation();
|
||||
+ }
|
||||
+ EXPECT_TRUE(manager.WaitForNavigationFinished());
|
||||
+ EXPECT_FALSE(WaitForLoadStop(shell()->web_contents()));
|
||||
+
|
||||
+ // The tab stayed at `url_b1` as the `url_b2` navigation didn't commit.
|
||||
+ EXPECT_EQ(shell()->web_contents()->GetLastCommittedURL(), url_b1);
|
||||
+}
|
||||
+
|
||||
} // namespace content
|
||||
215
patches/chromium/cherry-pick-85beff6fd302.patch
Normal file
215
patches/chromium/cherry-pick-85beff6fd302.patch
Normal file
@@ -0,0 +1,215 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Kevin McNee <mcnee@chromium.org>
|
||||
Date: Wed, 14 Jun 2023 01:10:19 +0000
|
||||
Subject: M114: Don't recursively destroy guests when clearing unattached
|
||||
guests
|
||||
|
||||
Don't recursively destroy guests when clearing unattached guests
|
||||
|
||||
When an embedder process is destroyed, we also destroy any unattached
|
||||
guests associated with that process. This is currently done with a
|
||||
single call to `owned_guests_.erase`. However, it's possible that two
|
||||
unattached guests could have an opener relationship, which causes the
|
||||
destruction of the opener guest to also destroy the other guest, during
|
||||
the call to `erase`, which is unsafe.
|
||||
|
||||
We now separate the steps of erasing `owned_guests_` and destroying the
|
||||
guests, to avoid this recursive guest destruction.
|
||||
|
||||
This also fixes the WaitForNumGuestsCreated test method to not
|
||||
return prematurely.
|
||||
|
||||
(cherry picked from commit 6345e7871e8197af92f9c6158b06c6e197f87945)
|
||||
|
||||
Bug: 1450397
|
||||
Change-Id: Ifef5ec9ff3a1e6952ff56ec279e29e8522625ac0
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/4589949
|
||||
Commit-Queue: Kevin McNee <mcnee@chromium.org>
|
||||
Auto-Submit: Kevin McNee <mcnee@chromium.org>
|
||||
Reviewed-by: James Maclean <wjmaclean@chromium.org>
|
||||
Cr-Original-Commit-Position: refs/heads/main@{#1153396}
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/4611152
|
||||
Commit-Queue: James Maclean <wjmaclean@chromium.org>
|
||||
Cr-Commit-Position: refs/branch-heads/5735@{#1292}
|
||||
Cr-Branched-From: 2f562e4ddbaf79a3f3cb338b4d1bd4398d49eb67-refs/heads/main@{#1135570}
|
||||
|
||||
diff --git a/chrome/browser/apps/guest_view/web_view_browsertest.cc b/chrome/browser/apps/guest_view/web_view_browsertest.cc
|
||||
index 3748f8119bf1d4f37635bdb4fb87d825881de7f0..00f0bcb19ae291e5389284f98ee922562f116496 100644
|
||||
--- a/chrome/browser/apps/guest_view/web_view_browsertest.cc
|
||||
+++ b/chrome/browser/apps/guest_view/web_view_browsertest.cc
|
||||
@@ -2779,6 +2779,22 @@ IN_PROC_BROWSER_TEST_P(WebViewNewWindowTest,
|
||||
EXPECT_TRUE(content::NavigateToURLFromRenderer(guest2, coop_url));
|
||||
}
|
||||
|
||||
+// This test creates a situation where we have two unattached webviews which
|
||||
+// have an opener relationship, and ensures that we can shutdown safely. See
|
||||
+// https://crbug.com/1450397.
|
||||
+IN_PROC_BROWSER_TEST_P(WebViewNewWindowTest, DestroyOpenerBeforeAttachment) {
|
||||
+ TestHelper("testDestroyOpenerBeforeAttachment", "web_view/newwindow",
|
||||
+ NEEDS_TEST_SERVER);
|
||||
+ GetGuestViewManager()->WaitForNumGuestsCreated(2);
|
||||
+
|
||||
+ content::RenderProcessHost* embedder_rph =
|
||||
+ GetEmbedderWebContents()->GetPrimaryMainFrame()->GetProcess();
|
||||
+ content::RenderProcessHostWatcher kill_observer(
|
||||
+ embedder_rph, content::RenderProcessHostWatcher::WATCH_FOR_PROCESS_EXIT);
|
||||
+ EXPECT_TRUE(embedder_rph->Shutdown(content::RESULT_CODE_KILLED));
|
||||
+ kill_observer.Wait();
|
||||
+}
|
||||
+
|
||||
IN_PROC_BROWSER_TEST_P(WebViewTest, ContextMenuInspectElement) {
|
||||
LoadAppWithGuest("web_view/context_menus/basic");
|
||||
content::RenderFrameHost* guest_rfh = GetGuestRenderFrameHost();
|
||||
diff --git a/chrome/test/data/extensions/platform_apps/web_view/newwindow/embedder.js b/chrome/test/data/extensions/platform_apps/web_view/newwindow/embedder.js
|
||||
index 900911f4963d23d74225868dce01326ba533f63a..4dd25d8849b0b13957ab7fa2912c0a158d3cd244 100644
|
||||
--- a/chrome/test/data/extensions/platform_apps/web_view/newwindow/embedder.js
|
||||
+++ b/chrome/test/data/extensions/platform_apps/web_view/newwindow/embedder.js
|
||||
@@ -34,6 +34,9 @@ embedder.setUp_ = function(config) {
|
||||
embedder.guestWithLinkURL = embedder.baseGuestURL +
|
||||
'/extensions/platform_apps/web_view/newwindow' +
|
||||
'/guest_with_link.html';
|
||||
+ embedder.guestOpenOnLoadURL = embedder.baseGuestURL +
|
||||
+ '/extensions/platform_apps/web_view/newwindow' +
|
||||
+ '/guest_opener_open_on_load.html';
|
||||
};
|
||||
|
||||
/** @private */
|
||||
@@ -652,6 +655,24 @@ function testNewWindowDeferredAttachmentIndefinitely() {
|
||||
embedder.setUpNewWindowRequest_(webview, 'guest.html', '', testName);
|
||||
}
|
||||
|
||||
+// This is not a test in and of itself, but a means of creating a webview that
|
||||
+// is left in an unattached state while its opener webview is also in an
|
||||
+// unattached state, so that the C++ side can test it in that state.
|
||||
+function testDestroyOpenerBeforeAttachment() {
|
||||
+ embedder.test.succeed();
|
||||
+
|
||||
+ let webview = new WebView();
|
||||
+ webview.src = embedder.guestOpenOnLoadURL;
|
||||
+ document.body.appendChild(webview);
|
||||
+
|
||||
+ // By spinning forever here, we prevent `webview` from completing the
|
||||
+ // attachment process. But since the guest is still created and it calls
|
||||
+ // window.open, we have a situation where two unattached webviews have an
|
||||
+ // opener relationship. The C++ side will test that we can shutdown safely in
|
||||
+ // this case.
|
||||
+ while (true) {}
|
||||
+}
|
||||
+
|
||||
embedder.test.testList = {
|
||||
'testNewWindowAttachAfterOpenerDestroyed':
|
||||
testNewWindowAttachAfterOpenerDestroyed,
|
||||
@@ -675,7 +696,9 @@ embedder.test.testList = {
|
||||
testNewWindowWebViewNameTakesPrecedence,
|
||||
'testNewWindowAndUpdateOpener': testNewWindowAndUpdateOpener,
|
||||
'testNewWindowDeferredAttachmentIndefinitely':
|
||||
- testNewWindowDeferredAttachmentIndefinitely
|
||||
+ testNewWindowDeferredAttachmentIndefinitely,
|
||||
+ 'testDestroyOpenerBeforeAttachment':
|
||||
+ testDestroyOpenerBeforeAttachment
|
||||
};
|
||||
|
||||
onload = function() {
|
||||
diff --git a/chrome/test/data/extensions/platform_apps/web_view/newwindow/guest_opener_open_on_load.html b/chrome/test/data/extensions/platform_apps/web_view/newwindow/guest_opener_open_on_load.html
|
||||
new file mode 100644
|
||||
index 0000000000000000000000000000000000000000..e961feb3c6487066801adf414bf4a2746c50a3f6
|
||||
--- /dev/null
|
||||
+++ b/chrome/test/data/extensions/platform_apps/web_view/newwindow/guest_opener_open_on_load.html
|
||||
@@ -0,0 +1,13 @@
|
||||
+<!--
|
||||
+Copyright 2023 The Chromium Authors
|
||||
+Use of this source code is governed by a BSD-style license that can be
|
||||
+found in the LICENSE file.
|
||||
+-->
|
||||
+<html>
|
||||
+<body>
|
||||
+<script>
|
||||
+ // A guest that opens a new window on load.
|
||||
+ window.open('guest.html');
|
||||
+</script>
|
||||
+</body>
|
||||
+</html>
|
||||
diff --git a/components/guest_view/browser/guest_view_manager.cc b/components/guest_view/browser/guest_view_manager.cc
|
||||
index 94867bbd2ea58908b52474c3923354852c070aed..24199000741b29bcbe25a695090b2de3be894af2 100644
|
||||
--- a/components/guest_view/browser/guest_view_manager.cc
|
||||
+++ b/components/guest_view/browser/guest_view_manager.cc
|
||||
@@ -324,7 +324,20 @@ void GuestViewManager::RemoveGuest(int guest_instance_id) {
|
||||
|
||||
void GuestViewManager::EmbedderProcessDestroyed(int embedder_process_id) {
|
||||
embedders_observed_.erase(embedder_process_id);
|
||||
+
|
||||
+ // We can't just call std::multimap::erase here because destroying a guest
|
||||
+ // could trigger the destruction of another guest which is also owned by
|
||||
+ // `owned_guests_`. Recursively calling std::multimap::erase is unsafe (see
|
||||
+ // https://crbug.com/1450397). So we take ownership of all of the guests that
|
||||
+ // will be destroyed before erasing the entries from the map.
|
||||
+ std::vector<std::unique_ptr<GuestViewBase>> guests_to_destroy;
|
||||
+ const auto destroy_range = owned_guests_.equal_range(embedder_process_id);
|
||||
+ for (auto it = destroy_range.first; it != destroy_range.second; ++it) {
|
||||
+ guests_to_destroy.push_back(std::move(it->second));
|
||||
+ }
|
||||
owned_guests_.erase(embedder_process_id);
|
||||
+ guests_to_destroy.clear();
|
||||
+
|
||||
CallViewDestructionCallbacks(embedder_process_id);
|
||||
}
|
||||
|
||||
diff --git a/components/guest_view/browser/test_guest_view_manager.cc b/components/guest_view/browser/test_guest_view_manager.cc
|
||||
index b1835691dfd8e7699575c26d4cb38b2247f9c9bc..69f4161746f756fdc022a20c23f44f593c09a6d6 100644
|
||||
--- a/components/guest_view/browser/test_guest_view_manager.cc
|
||||
+++ b/components/guest_view/browser/test_guest_view_manager.cc
|
||||
@@ -36,7 +36,6 @@ TestGuestViewManager::TestGuestViewManager(
|
||||
num_guests_created_(0),
|
||||
expected_num_guests_created_(0),
|
||||
num_views_garbage_collected_(0),
|
||||
- waiting_for_guests_created_(false),
|
||||
waiting_for_attach_(nullptr) {}
|
||||
|
||||
TestGuestViewManager::~TestGuestViewManager() = default;
|
||||
@@ -127,14 +126,15 @@ GuestViewBase* TestGuestViewManager::WaitForNextGuestViewCreated() {
|
||||
}
|
||||
|
||||
void TestGuestViewManager::WaitForNumGuestsCreated(size_t count) {
|
||||
- if (count == num_guests_created_)
|
||||
+ if (count == num_guests_created_) {
|
||||
return;
|
||||
+ }
|
||||
|
||||
- waiting_for_guests_created_ = true;
|
||||
expected_num_guests_created_ = count;
|
||||
|
||||
num_created_run_loop_ = std::make_unique<base::RunLoop>();
|
||||
num_created_run_loop_->Run();
|
||||
+ num_created_run_loop_ = nullptr;
|
||||
}
|
||||
|
||||
void TestGuestViewManager::WaitUntilAttached(GuestViewBase* guest_view) {
|
||||
@@ -179,13 +179,11 @@ void TestGuestViewManager::AddGuest(int guest_instance_id,
|
||||
created_run_loop_->Quit();
|
||||
|
||||
++num_guests_created_;
|
||||
- if (!waiting_for_guests_created_ &&
|
||||
- num_guests_created_ != expected_num_guests_created_) {
|
||||
- return;
|
||||
- }
|
||||
|
||||
- if (num_created_run_loop_)
|
||||
+ if (num_created_run_loop_ &&
|
||||
+ num_guests_created_ == expected_num_guests_created_) {
|
||||
num_created_run_loop_->Quit();
|
||||
+ }
|
||||
}
|
||||
|
||||
void TestGuestViewManager::AttachGuest(int embedder_process_id,
|
||||
diff --git a/components/guest_view/browser/test_guest_view_manager.h b/components/guest_view/browser/test_guest_view_manager.h
|
||||
index dfb9f9001ed3324b507f5478391ad3640ebeeae9..f12db0cf32ef03c1e4dacc68b782e01e698cbcdb 100644
|
||||
--- a/components/guest_view/browser/test_guest_view_manager.h
|
||||
+++ b/components/guest_view/browser/test_guest_view_manager.h
|
||||
@@ -119,7 +119,6 @@ class TestGuestViewManager : public GuestViewManager {
|
||||
size_t num_guests_created_;
|
||||
size_t expected_num_guests_created_;
|
||||
int num_views_garbage_collected_;
|
||||
- bool waiting_for_guests_created_;
|
||||
|
||||
// Tracks the life time of the GuestView's main FrameTreeNode. The main FTN
|
||||
// has the same lifesspan as the GuestView.
|
||||
404
patches/chromium/cherry-pick-933b9fad3a53.patch
Normal file
404
patches/chromium/cherry-pick-933b9fad3a53.patch
Normal file
@@ -0,0 +1,404 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Ken Rockot <rockot@google.com>
|
||||
Date: Fri, 9 Jun 2023 07:49:02 +0000
|
||||
Subject: Reland "ipcz: Refactor FragmentDescriptor decode"
|
||||
|
||||
This is a reland of commit 17dd18d1f2194089b8433e0ca334c81343b591e2
|
||||
|
||||
Original change's description:
|
||||
> ipcz: Refactor FragmentDescriptor decode
|
||||
>
|
||||
> Funnels untrusted FragmentDescriptor mapping through a new
|
||||
> Fragment::MappedFromDescriptor helper. See the linked bug
|
||||
> for more details.
|
||||
>
|
||||
> Fixed: 1450899
|
||||
> Change-Id: I4c7751b9f4299da4a13c0becc1b889160a0c6e66
|
||||
> Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/4599218
|
||||
> Reviewed-by: Daniel Cheng <dcheng@chromium.org>
|
||||
> Commit-Queue: Ken Rockot <rockot@google.com>
|
||||
> Cr-Commit-Position: refs/heads/main@{#1155133}
|
||||
|
||||
Change-Id: I86ee9118a30dea59d837c377a1f751b20a85a3c3
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/4602794
|
||||
Reviewed-by: Daniel Cheng <dcheng@chromium.org>
|
||||
Commit-Queue: Ken Rockot <rockot@google.com>
|
||||
Cr-Commit-Position: refs/heads/main@{#1155397}
|
||||
|
||||
diff --git a/third_party/ipcz/src/BUILD.gn b/third_party/ipcz/src/BUILD.gn
|
||||
index 94177b5ec335bcfa28ba47eb0e9887c991073946..5dda0f2f806936d9bd6c986afd20ec5b53e06c28 100644
|
||||
--- a/third_party/ipcz/src/BUILD.gn
|
||||
+++ b/third_party/ipcz/src/BUILD.gn
|
||||
@@ -212,6 +212,7 @@ ipcz_source_set("impl") {
|
||||
"ipcz/application_object.h",
|
||||
"ipcz/block_allocator.h",
|
||||
"ipcz/box.h",
|
||||
+ "ipcz/buffer_id.h",
|
||||
"ipcz/buffer_pool.h",
|
||||
"ipcz/driver_memory.h",
|
||||
"ipcz/driver_memory_mapping.h",
|
||||
@@ -254,7 +255,6 @@ ipcz_source_set("impl") {
|
||||
"ipcz/block_allocator_pool.cc",
|
||||
"ipcz/block_allocator_pool.h",
|
||||
"ipcz/box.cc",
|
||||
- "ipcz/buffer_id.h",
|
||||
"ipcz/buffer_pool.cc",
|
||||
"ipcz/driver_memory.cc",
|
||||
"ipcz/driver_memory_mapping.cc",
|
||||
@@ -376,6 +376,7 @@ ipcz_source_set("ipcz_tests_sources") {
|
||||
"ipcz/driver_memory_test.cc",
|
||||
"ipcz/driver_object_test.cc",
|
||||
"ipcz/driver_transport_test.cc",
|
||||
+ "ipcz/fragment_test.cc",
|
||||
"ipcz/message_test.cc",
|
||||
"ipcz/node_connector_test.cc",
|
||||
"ipcz/node_link_memory_test.cc",
|
||||
diff --git a/third_party/ipcz/src/ipcz/block_allocator_pool.cc b/third_party/ipcz/src/ipcz/block_allocator_pool.cc
|
||||
index bd464f897d1fcbde03941ee334d0e1706bf59868..1b9d50b2c77c046d815a94d7760328c8b379ecab 100644
|
||||
--- a/third_party/ipcz/src/ipcz/block_allocator_pool.cc
|
||||
+++ b/third_party/ipcz/src/ipcz/block_allocator_pool.cc
|
||||
@@ -86,7 +86,7 @@ Fragment BlockAllocatorPool::Allocate() {
|
||||
FragmentDescriptor descriptor(
|
||||
entry->buffer_id, checked_cast<uint32_t>(offset),
|
||||
checked_cast<uint32_t>(allocator.block_size()));
|
||||
- return Fragment(descriptor, block);
|
||||
+ return Fragment::FromDescriptorUnsafe(descriptor, block);
|
||||
}
|
||||
|
||||
// Allocation from the active allocator failed. Try another if available.
|
||||
diff --git a/third_party/ipcz/src/ipcz/buffer_pool.cc b/third_party/ipcz/src/ipcz/buffer_pool.cc
|
||||
index 6881346d8f8532f070e5121da16f064ae4a9bdaf..27b23049848967f29f81b10ba4f8fa4ead14d2e2 100644
|
||||
--- a/third_party/ipcz/src/ipcz/buffer_pool.cc
|
||||
+++ b/third_party/ipcz/src/ipcz/buffer_pool.cc
|
||||
@@ -26,15 +26,11 @@ Fragment BufferPool::GetFragment(const FragmentDescriptor& descriptor) {
|
||||
absl::MutexLock lock(&mutex_);
|
||||
auto it = mappings_.find(descriptor.buffer_id());
|
||||
if (it == mappings_.end()) {
|
||||
- return Fragment(descriptor, nullptr);
|
||||
+ return Fragment::PendingFromDescriptor(descriptor);
|
||||
}
|
||||
|
||||
auto& [id, mapping] = *it;
|
||||
- if (descriptor.end() > mapping.bytes().size()) {
|
||||
- return {};
|
||||
- }
|
||||
-
|
||||
- return Fragment(descriptor, mapping.address_at(descriptor.offset()));
|
||||
+ return Fragment::MappedFromDescriptor(descriptor, mapping);
|
||||
}
|
||||
|
||||
bool BufferPool::AddBlockBuffer(
|
||||
diff --git a/third_party/ipcz/src/ipcz/buffer_pool_test.cc b/third_party/ipcz/src/ipcz/buffer_pool_test.cc
|
||||
index a009ffe1c20ade013a19b51eceee4faf334eb591..bff66c452a3e2c38b0f208cca1fa1a082f1ee871 100644
|
||||
--- a/third_party/ipcz/src/ipcz/buffer_pool_test.cc
|
||||
+++ b/third_party/ipcz/src/ipcz/buffer_pool_test.cc
|
||||
@@ -194,9 +194,11 @@ TEST_F(BufferPoolTest, BasicBlockAllocation) {
|
||||
pool.GetTotalBlockCapacity(kBlockSize));
|
||||
|
||||
// We can't free something that isn't a valid allocation.
|
||||
- EXPECT_FALSE(pool.FreeBlock(Fragment{{}, nullptr}));
|
||||
- EXPECT_FALSE(pool.FreeBlock(Fragment{{BufferId{1000}, 0, 1}, nullptr}));
|
||||
- EXPECT_FALSE(pool.FreeBlock(Fragment{{BufferId{0}, 0, 1}, bytes0.data()}));
|
||||
+ EXPECT_FALSE(pool.FreeBlock(Fragment::FromDescriptorUnsafe({}, nullptr)));
|
||||
+ EXPECT_FALSE(pool.FreeBlock(
|
||||
+ Fragment::FromDescriptorUnsafe({BufferId{1000}, 0, 1}, nullptr)));
|
||||
+ EXPECT_FALSE(pool.FreeBlock(
|
||||
+ Fragment::FromDescriptorUnsafe({BufferId{0}, 0, 1}, bytes0.data())));
|
||||
|
||||
// Allocate all available capacity.
|
||||
std::vector<Fragment> fragments;
|
||||
diff --git a/third_party/ipcz/src/ipcz/fragment.cc b/third_party/ipcz/src/ipcz/fragment.cc
|
||||
index 651d1c2fca5fe4fb69cdf61c6062bd8804ebf704..2ef4ed8dcfa0a56a73975a0b7dcc3f86bf5a83a0 100644
|
||||
--- a/third_party/ipcz/src/ipcz/fragment.cc
|
||||
+++ b/third_party/ipcz/src/ipcz/fragment.cc
|
||||
@@ -6,10 +6,38 @@
|
||||
|
||||
#include <cstdint>
|
||||
|
||||
+#include "ipcz/driver_memory_mapping.h"
|
||||
+#include "ipcz/fragment_descriptor.h"
|
||||
#include "third_party/abseil-cpp/absl/base/macros.h"
|
||||
+#include "util/safe_math.h"
|
||||
|
||||
namespace ipcz {
|
||||
|
||||
+// static
|
||||
+Fragment Fragment::MappedFromDescriptor(const FragmentDescriptor& descriptor,
|
||||
+ DriverMemoryMapping& mapping) {
|
||||
+ if (descriptor.is_null()) {
|
||||
+ return {};
|
||||
+ }
|
||||
+
|
||||
+ const uint32_t end = SaturatedAdd(descriptor.offset(), descriptor.size());
|
||||
+ if (end > mapping.bytes().size()) {
|
||||
+ return {};
|
||||
+ }
|
||||
+ return Fragment{descriptor, mapping.address_at(descriptor.offset())};
|
||||
+}
|
||||
+
|
||||
+// static
|
||||
+Fragment Fragment::PendingFromDescriptor(const FragmentDescriptor& descriptor) {
|
||||
+ return Fragment{descriptor, nullptr};
|
||||
+}
|
||||
+
|
||||
+// static
|
||||
+Fragment Fragment::FromDescriptorUnsafe(const FragmentDescriptor& descriptor,
|
||||
+ void* base_address) {
|
||||
+ return Fragment{descriptor, base_address};
|
||||
+}
|
||||
+
|
||||
Fragment::Fragment(const FragmentDescriptor& descriptor, void* address)
|
||||
: descriptor_(descriptor), address_(address) {
|
||||
// If `address` is non-null, the descriptor must also be. Note that the
|
||||
diff --git a/third_party/ipcz/src/ipcz/fragment.h b/third_party/ipcz/src/ipcz/fragment.h
|
||||
index c0151fdcf4b418680172a29d1c0d28b58a5807cd..de65f087b0bc27fd59ab88e23130d5ce0d345a8a 100644
|
||||
--- a/third_party/ipcz/src/ipcz/fragment.h
|
||||
+++ b/third_party/ipcz/src/ipcz/fragment.h
|
||||
@@ -14,21 +14,32 @@
|
||||
|
||||
namespace ipcz {
|
||||
|
||||
+class DriverMemoryMapping;
|
||||
+
|
||||
// Represents a span of memory located within the shared memory regions owned by
|
||||
// a NodeLinkMemory, via BufferPool. This is essentially a FragmentDescriptor
|
||||
// plus the actual mapped address of the given buffer and offset.
|
||||
struct Fragment {
|
||||
constexpr Fragment() = default;
|
||||
|
||||
- // Constructs a new Fragment over `descriptor`, mapped to `address`. If
|
||||
- // `address` is null, the Fragment is considered "pending" -- it has a
|
||||
- // potentially valid descriptor, but could not be resolved to a mapped address
|
||||
- // yet (e.g. because the relevant BufferPool doesn't have the identified
|
||||
- // buffer mapped yet.)
|
||||
- Fragment(const FragmentDescriptor& descriptor, void* address);
|
||||
Fragment(const Fragment&);
|
||||
Fragment& operator=(const Fragment&);
|
||||
|
||||
+ // Returns a new concrete Fragment corresponding to `descriptor` within the
|
||||
+ // context of `mapping`. This validates that the fragment's bounds fall within
|
||||
+ // the bounds of `mapping`. If `descriptor` was null or validation fails, this
|
||||
+ // returns a null Fragment.
|
||||
+ static Fragment MappedFromDescriptor(const FragmentDescriptor& descriptor,
|
||||
+ DriverMemoryMapping& mapping);
|
||||
+
|
||||
+ // Returns a pending Fragment corresponding to `descriptor`.
|
||||
+ static Fragment PendingFromDescriptor(const FragmentDescriptor& descriptor);
|
||||
+
|
||||
+ // Returns a Fragment corresponding to `descriptor`, with the starting address
|
||||
+ // already mapped to `address`.
|
||||
+ static Fragment FromDescriptorUnsafe(const FragmentDescriptor& descriptor,
|
||||
+ void* address);
|
||||
+
|
||||
// A null fragment is a fragment with a null descriptor, meaning it does not
|
||||
// reference a valid buffer ID.
|
||||
bool is_null() const { return descriptor_.is_null(); }
|
||||
@@ -66,6 +77,13 @@ struct Fragment {
|
||||
}
|
||||
|
||||
private:
|
||||
+ // Constructs a new Fragment over `descriptor`, mapped to `address`. If
|
||||
+ // `address` is null, the Fragment is considered "pending" -- it has a
|
||||
+ // potentially valid descriptor, but could not be resolved to a mapped address
|
||||
+ // yet (e.g. because the relevant BufferPool doesn't have the identified
|
||||
+ // buffer mapped yet.)
|
||||
+ Fragment(const FragmentDescriptor& descriptor, void* address);
|
||||
+
|
||||
FragmentDescriptor descriptor_;
|
||||
|
||||
// The actual mapped address corresponding to `descriptor_`.
|
||||
diff --git a/third_party/ipcz/src/ipcz/fragment_descriptor.h b/third_party/ipcz/src/ipcz/fragment_descriptor.h
|
||||
index b247215fd5e5f7c69e521416614465b0321f5d83..aeaa7da9c82761854948d009e7f245c9c9d042c7 100644
|
||||
--- a/third_party/ipcz/src/ipcz/fragment_descriptor.h
|
||||
+++ b/third_party/ipcz/src/ipcz/fragment_descriptor.h
|
||||
@@ -39,7 +39,6 @@ struct IPCZ_ALIGN(8) FragmentDescriptor {
|
||||
BufferId buffer_id() const { return buffer_id_; }
|
||||
uint32_t offset() const { return offset_; }
|
||||
uint32_t size() const { return size_; }
|
||||
- uint32_t end() const { return offset_ + size_; }
|
||||
|
||||
private:
|
||||
// Identifies the shared memory buffer in which the memory resides. This ID is
|
||||
diff --git a/third_party/ipcz/src/ipcz/fragment_test.cc b/third_party/ipcz/src/ipcz/fragment_test.cc
|
||||
new file mode 100644
|
||||
index 0000000000000000000000000000000000000000..e6b6baa6cb2f1fbdfb89d87d644f63681c797c01
|
||||
--- /dev/null
|
||||
+++ b/third_party/ipcz/src/ipcz/fragment_test.cc
|
||||
@@ -0,0 +1,102 @@
|
||||
+// Copyright 2023 The Chromium Authors
|
||||
+// Use of this source code is governed by a BSD-style license that can be
|
||||
+// found in the LICENSE file.
|
||||
+
|
||||
+#include "ipcz/fragment.h"
|
||||
+
|
||||
+#include <algorithm>
|
||||
+#include <cstring>
|
||||
+#include <limits>
|
||||
+#include <string>
|
||||
+#include <utility>
|
||||
+
|
||||
+#include "ipcz/buffer_id.h"
|
||||
+#include "ipcz/driver_memory.h"
|
||||
+#include "ipcz/driver_memory_mapping.h"
|
||||
+#include "reference_drivers/sync_reference_driver.h"
|
||||
+#include "testing/gtest/include/gtest/gtest.h"
|
||||
+
|
||||
+namespace ipcz {
|
||||
+namespace {
|
||||
+
|
||||
+const IpczDriver& kTestDriver = reference_drivers::kSyncReferenceDriver;
|
||||
+
|
||||
+using FragmentTest = testing::Test;
|
||||
+
|
||||
+TEST_F(FragmentTest, FromDescriptorUnsafe) {
|
||||
+ char kBuffer[] = "Hello, world!";
|
||||
+
|
||||
+ Fragment f = Fragment::FromDescriptorUnsafe({BufferId{0}, 1, 4}, kBuffer + 1);
|
||||
+ EXPECT_FALSE(f.is_null());
|
||||
+ EXPECT_FALSE(f.is_pending());
|
||||
+ EXPECT_EQ(1u, f.offset());
|
||||
+ EXPECT_EQ(4u, f.size());
|
||||
+ EXPECT_EQ("ello", std::string(f.bytes().begin(), f.bytes().end()));
|
||||
+
|
||||
+ f = Fragment::FromDescriptorUnsafe({BufferId{0}, 7, 6}, kBuffer + 7);
|
||||
+ EXPECT_FALSE(f.is_null());
|
||||
+ EXPECT_FALSE(f.is_pending());
|
||||
+ EXPECT_EQ(7u, f.offset());
|
||||
+ EXPECT_EQ(6u, f.size());
|
||||
+ EXPECT_EQ("world!", std::string(f.bytes().begin(), f.bytes().end()));
|
||||
+}
|
||||
+
|
||||
+TEST_F(FragmentTest, PendingFromDescriptor) {
|
||||
+ Fragment f = Fragment::PendingFromDescriptor({BufferId{0}, 5, 42});
|
||||
+ EXPECT_TRUE(f.is_pending());
|
||||
+ EXPECT_FALSE(f.is_null());
|
||||
+ EXPECT_EQ(5u, f.offset());
|
||||
+ EXPECT_EQ(42u, f.size());
|
||||
+
|
||||
+ f = Fragment::PendingFromDescriptor({kInvalidBufferId, 0, 0});
|
||||
+ EXPECT_TRUE(f.is_null());
|
||||
+ EXPECT_FALSE(f.is_pending());
|
||||
+}
|
||||
+
|
||||
+TEST_F(FragmentTest, NullMappedFromDescriptor) {
|
||||
+ constexpr size_t kDataSize = 32;
|
||||
+ DriverMemory memory(kTestDriver, kDataSize);
|
||||
+ auto mapping = memory.Map();
|
||||
+
|
||||
+ Fragment f =
|
||||
+ Fragment::MappedFromDescriptor({kInvalidBufferId, 0, 0}, mapping);
|
||||
+ EXPECT_TRUE(f.is_null());
|
||||
+}
|
||||
+
|
||||
+TEST_F(FragmentTest, InvalidMappedFromDescriptor) {
|
||||
+ constexpr size_t kDataSize = 32;
|
||||
+ DriverMemory memory(kTestDriver, kDataSize);
|
||||
+ auto mapping = memory.Map();
|
||||
+
|
||||
+ Fragment f;
|
||||
+
|
||||
+ // Offset out of bounds
|
||||
+ f = Fragment::MappedFromDescriptor({BufferId{0}, kDataSize, 1}, mapping);
|
||||
+ EXPECT_TRUE(f.is_null());
|
||||
+
|
||||
+ // Tail out of bounds
|
||||
+ f = Fragment::MappedFromDescriptor({BufferId{0}, 0, kDataSize + 5}, mapping);
|
||||
+ EXPECT_TRUE(f.is_null());
|
||||
+
|
||||
+ // Tail overflow
|
||||
+ f = Fragment::MappedFromDescriptor(
|
||||
+ {BufferId{0}, std::numeric_limits<uint32_t>::max(), 2}, mapping);
|
||||
+ EXPECT_TRUE(f.is_null());
|
||||
+}
|
||||
+
|
||||
+TEST_F(FragmentTest, ValidMappedFromDescriptor) {
|
||||
+ const char kData[] = "0123456789abcdef";
|
||||
+ DriverMemory memory(kTestDriver, std::size(kData));
|
||||
+ auto mapping = memory.Map();
|
||||
+ memcpy(mapping.bytes().data(), kData, std::size(kData));
|
||||
+
|
||||
+ Fragment f = Fragment::MappedFromDescriptor({BufferId{0}, 2, 11}, mapping);
|
||||
+ EXPECT_FALSE(f.is_null());
|
||||
+ EXPECT_FALSE(f.is_pending());
|
||||
+ EXPECT_EQ(2u, f.offset());
|
||||
+ EXPECT_EQ(11u, f.size());
|
||||
+ EXPECT_EQ("23456789abc", std::string(f.bytes().begin(), f.bytes().end()));
|
||||
+}
|
||||
+
|
||||
+} // namespace
|
||||
+} // namespace ipcz
|
||||
diff --git a/third_party/ipcz/src/ipcz/node_link_memory.cc b/third_party/ipcz/src/ipcz/node_link_memory.cc
|
||||
index b4715bca8b59c1a53fa4777510c75c7aca1cdf9d..f70a6b1aee08d749a6266d3cb88f9d12f4e1f281 100644
|
||||
--- a/third_party/ipcz/src/ipcz/node_link_memory.cc
|
||||
+++ b/third_party/ipcz/src/ipcz/node_link_memory.cc
|
||||
@@ -259,8 +259,9 @@ FragmentRef<RouterLinkState> NodeLinkMemory::GetInitialRouterLinkState(
|
||||
FragmentDescriptor descriptor(kPrimaryBufferId,
|
||||
ToOffset(state, primary_buffer_memory_.data()),
|
||||
sizeof(RouterLinkState));
|
||||
- return FragmentRef<RouterLinkState>(RefCountedFragment::kUnmanagedRef,
|
||||
- Fragment(descriptor, state));
|
||||
+ return FragmentRef<RouterLinkState>(
|
||||
+ RefCountedFragment::kUnmanagedRef,
|
||||
+ Fragment::FromDescriptorUnsafe(descriptor, state));
|
||||
}
|
||||
|
||||
Fragment NodeLinkMemory::GetFragment(const FragmentDescriptor& descriptor) {
|
||||
diff --git a/third_party/ipcz/src/ipcz/ref_counted_fragment_test.cc b/third_party/ipcz/src/ipcz/ref_counted_fragment_test.cc
|
||||
index d5a2243a693597e43f87f116f80599fde383cb59..220c3556a261c5caab7194114af4cf375d9af683 100644
|
||||
--- a/third_party/ipcz/src/ipcz/ref_counted_fragment_test.cc
|
||||
+++ b/third_party/ipcz/src/ipcz/ref_counted_fragment_test.cc
|
||||
@@ -64,7 +64,8 @@ TEST_F(RefCountedFragmentTest, SimpleRef) {
|
||||
|
||||
FragmentRef<TestObject> ref(
|
||||
RefCountedFragment::kUnmanagedRef,
|
||||
- Fragment(FragmentDescriptor(BufferId(0), 0, sizeof(object)), &object));
|
||||
+ Fragment::FromDescriptorUnsafe(
|
||||
+ FragmentDescriptor(BufferId(0), 0, sizeof(object)), &object));
|
||||
EXPECT_EQ(1, object.ref_count_for_testing());
|
||||
ref.reset();
|
||||
EXPECT_EQ(0, object.ref_count_for_testing());
|
||||
@@ -75,7 +76,8 @@ TEST_F(RefCountedFragmentTest, Copy) {
|
||||
|
||||
FragmentRef<TestObject> ref1(
|
||||
RefCountedFragment::kUnmanagedRef,
|
||||
- Fragment(FragmentDescriptor(BufferId(0), 0, sizeof(object1)), &object1));
|
||||
+ Fragment::FromDescriptorUnsafe(
|
||||
+ FragmentDescriptor(BufferId(0), 0, sizeof(object1)), &object1));
|
||||
EXPECT_EQ(1, object1.ref_count_for_testing());
|
||||
|
||||
FragmentRef<TestObject> other1 = ref1;
|
||||
@@ -88,7 +90,8 @@ TEST_F(RefCountedFragmentTest, Copy) {
|
||||
TestObject object2;
|
||||
auto ref2 = FragmentRef<TestObject>(
|
||||
RefCountedFragment::kUnmanagedRef,
|
||||
- Fragment(FragmentDescriptor(BufferId(0), 0, sizeof(object2)), &object2));
|
||||
+ Fragment::FromDescriptorUnsafe(
|
||||
+ FragmentDescriptor(BufferId(0), 0, sizeof(object2)), &object2));
|
||||
EXPECT_EQ(1, object1.ref_count_for_testing());
|
||||
EXPECT_EQ(1, object2.ref_count_for_testing());
|
||||
ref2 = ref1;
|
||||
@@ -115,7 +118,8 @@ TEST_F(RefCountedFragmentTest, Move) {
|
||||
|
||||
FragmentRef<TestObject> ref1(
|
||||
RefCountedFragment::kUnmanagedRef,
|
||||
- Fragment(FragmentDescriptor(BufferId(0), 0, sizeof(object1)), &object1));
|
||||
+ Fragment::FromDescriptorUnsafe(
|
||||
+ FragmentDescriptor(BufferId(0), 0, sizeof(object1)), &object1));
|
||||
EXPECT_EQ(1, ref1.ref_count_for_testing());
|
||||
|
||||
FragmentRef<TestObject> other1 = std::move(ref1);
|
||||
@@ -133,10 +137,12 @@ TEST_F(RefCountedFragmentTest, Move) {
|
||||
TestObject object3;
|
||||
FragmentRef<TestObject> ref2(
|
||||
RefCountedFragment::kUnmanagedRef,
|
||||
- Fragment(FragmentDescriptor(BufferId(0), 0, sizeof(object2)), &object2));
|
||||
+ Fragment::FromDescriptorUnsafe(
|
||||
+ FragmentDescriptor(BufferId(0), 0, sizeof(object2)), &object2));
|
||||
FragmentRef<TestObject> ref3(
|
||||
RefCountedFragment::kUnmanagedRef,
|
||||
- Fragment(FragmentDescriptor(BufferId(0), 0, sizeof(object3)), &object3));
|
||||
+ Fragment::FromDescriptorUnsafe(
|
||||
+ FragmentDescriptor(BufferId(0), 0, sizeof(object3)), &object3));
|
||||
|
||||
EXPECT_FALSE(ref2.is_null());
|
||||
EXPECT_TRUE(ref2.is_addressable());
|
||||
88
patches/chromium/cherry-pick-9585757f9fad.patch
Normal file
88
patches/chromium/cherry-pick-9585757f9fad.patch
Normal file
@@ -0,0 +1,88 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Tom Anderson <thomasanderson@chromium.org>
|
||||
Date: Thu, 19 Jan 2023 17:03:20 +0000
|
||||
Subject: StatusIconLinuxDbus: Use default session bus name
|
||||
|
||||
The StatusNotifierItem spec requires status items register with the name
|
||||
`org.kde.StatusNotifierItem-$PID-$ID`. However this causes problems
|
||||
in sandboxed environments such as flatpak because extra permissions
|
||||
are required to register the bus name. Additionally, the name
|
||||
`org.kde.StatusNotifierItem-2-1` will be used every time when PID
|
||||
namespaces are used for sandboxing.
|
||||
|
||||
To address this, just use the default bus name we were given on
|
||||
initially connecting to the bus. This violates the spec, but there's
|
||||
actually no consequence for doing this.
|
||||
|
||||
R=sky
|
||||
|
||||
Fixed: 1408315
|
||||
Change-Id: I1abc4100c2899206eaa1804a3ff47dce7ad4e565
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/4179380
|
||||
Auto-Submit: Thomas Anderson <thomasanderson@chromium.org>
|
||||
Commit-Queue: Scott Violet <sky@chromium.org>
|
||||
Reviewed-by: Scott Violet <sky@chromium.org>
|
||||
Cr-Commit-Position: refs/heads/main@{#1094509}
|
||||
|
||||
diff --git a/chrome/browser/ui/views/status_icons/status_icon_linux_dbus.cc b/chrome/browser/ui/views/status_icons/status_icon_linux_dbus.cc
|
||||
index 88289caa2518a2888de596fd65b7dfb6efa3e1ab..c523874ecc329e5a722c5923334fc578ebdf6a84 100644
|
||||
--- a/chrome/browser/ui/views/status_icons/status_icon_linux_dbus.cc
|
||||
+++ b/chrome/browser/ui/views/status_icons/status_icon_linux_dbus.cc
|
||||
@@ -101,12 +101,6 @@ int NextServiceId() {
|
||||
return ++status_icon_count;
|
||||
}
|
||||
|
||||
-std::string ServiceNameFromId(int service_id) {
|
||||
- return std::string(kInterfaceStatusNotifierItem) + '-' +
|
||||
- base::NumberToString(base::Process::Current().Pid()) + '-' +
|
||||
- base::NumberToString(service_id);
|
||||
-}
|
||||
-
|
||||
std::string PropertyIdFromId(int service_id) {
|
||||
return "chrome_status_icon_" + base::NumberToString(service_id);
|
||||
}
|
||||
@@ -295,19 +289,6 @@ void StatusIconLinuxDbus::OnHostRegisteredResponse(dbus::Response* response) {
|
||||
}
|
||||
|
||||
service_id_ = NextServiceId();
|
||||
- bus_->RequestOwnership(ServiceNameFromId(service_id_),
|
||||
- dbus::Bus::ServiceOwnershipOptions::REQUIRE_PRIMARY,
|
||||
- base::BindOnce(&StatusIconLinuxDbus::OnOwnership,
|
||||
- weak_factory_.GetWeakPtr()));
|
||||
-}
|
||||
-
|
||||
-void StatusIconLinuxDbus::OnOwnership(const std::string& service_name,
|
||||
- bool success) {
|
||||
- DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
|
||||
- if (!success) {
|
||||
- delegate_->OnImplInitializationFailed();
|
||||
- return;
|
||||
- }
|
||||
|
||||
static constexpr struct {
|
||||
const char* name;
|
||||
@@ -390,7 +371,7 @@ void StatusIconLinuxDbus::RegisterStatusNotifierItem() {
|
||||
dbus::MethodCall method_call(kInterfaceStatusNotifierWatcher,
|
||||
kMethodRegisterStatusNotifierItem);
|
||||
dbus::MessageWriter writer(&method_call);
|
||||
- writer.AppendString(ServiceNameFromId(service_id_));
|
||||
+ writer.AppendString(bus_->GetConnectionName());
|
||||
watcher_->CallMethod(&method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
|
||||
base::BindOnce(&StatusIconLinuxDbus::OnRegistered,
|
||||
weak_factory_.GetWeakPtr()));
|
||||
diff --git a/chrome/browser/ui/views/status_icons/status_icon_linux_dbus.h b/chrome/browser/ui/views/status_icons/status_icon_linux_dbus.h
|
||||
index eae1c332a0972aefb8843cac947aeb2f4c48d360..d4ad41f9a2a7e2df4bc38889d883f52ad90bd799 100644
|
||||
--- a/chrome/browser/ui/views/status_icons/status_icon_linux_dbus.h
|
||||
+++ b/chrome/browser/ui/views/status_icons/status_icon_linux_dbus.h
|
||||
@@ -65,10 +65,7 @@ class StatusIconLinuxDbus : public ui::StatusIconLinux,
|
||||
// registered.
|
||||
void OnHostRegisteredResponse(dbus::Response* response);
|
||||
|
||||
- // Step 3: register a StatusNotifierItem service.
|
||||
- void OnOwnership(const std::string& service_name, bool success);
|
||||
-
|
||||
- // Step 4: export methods for the StatusNotifierItem and the properties
|
||||
+ // Step 3: export methods for the StatusNotifierItem and the properties
|
||||
// interface.
|
||||
void OnExported(const std::string& interface_name,
|
||||
const std::string& method_name,
|
||||
119
patches/chromium/cherry-pick-b03973561862.patch
Normal file
119
patches/chromium/cherry-pick-b03973561862.patch
Normal file
@@ -0,0 +1,119 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Tommi <tommi@chromium.org>
|
||||
Date: Wed, 5 Jul 2023 10:55:53 +0000
|
||||
Subject: Make RTCDataChannel's channel and observer pointers const.
|
||||
|
||||
This allows channel properties to be queried while the RTCDataChannel
|
||||
instance exists and avoids potential null deref after entering the
|
||||
kClosed state.
|
||||
|
||||
(cherry picked from commit 08d5ad011f53a1995bfccef6728bfa62541f7608)
|
||||
|
||||
Bug: 1456567, 1457421
|
||||
Change-Id: I4747f9c00804b35711667d7320ec6188f20910c4
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/4663082
|
||||
Commit-Queue: Tomas Gunnarsson <tommi@chromium.org>
|
||||
Reviewed-by: Elad Alon <eladalon@chromium.org>
|
||||
Cr-Original-Commit-Position: refs/heads/main@{#1165406}
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/4665530
|
||||
Cr-Commit-Position: refs/branch-heads/5845@{#300}
|
||||
Cr-Branched-From: 5a5dff63a4a4c63b9b18589819bebb2566c85443-refs/heads/main@{#1160321}
|
||||
|
||||
diff --git a/third_party/blink/renderer/modules/peerconnection/rtc_data_channel.cc b/third_party/blink/renderer/modules/peerconnection/rtc_data_channel.cc
|
||||
index 78d28d60822f4ce206d869846235352224378076..91c20cbcc5042373964d57545177ff06074db564 100644
|
||||
--- a/third_party/blink/renderer/modules/peerconnection/rtc_data_channel.cc
|
||||
+++ b/third_party/blink/renderer/modules/peerconnection/rtc_data_channel.cc
|
||||
@@ -228,11 +228,12 @@ RTCDataChannel::Observer::Observer(
|
||||
scoped_refptr<webrtc::DataChannelInterface> channel)
|
||||
: main_thread_(main_thread),
|
||||
blink_channel_(blink_channel),
|
||||
- webrtc_channel_(channel) {}
|
||||
+ webrtc_channel_(std::move(channel)) {
|
||||
+ CHECK(webrtc_channel_.get());
|
||||
+}
|
||||
|
||||
RTCDataChannel::Observer::~Observer() {
|
||||
DCHECK(!blink_channel_) << "Reference to blink channel hasn't been released.";
|
||||
- DCHECK(!webrtc_channel_.get()) << "Unregister hasn't been called.";
|
||||
}
|
||||
|
||||
const scoped_refptr<webrtc::DataChannelInterface>&
|
||||
@@ -242,13 +243,8 @@ RTCDataChannel::Observer::channel() const {
|
||||
|
||||
void RTCDataChannel::Observer::Unregister() {
|
||||
DCHECK(main_thread_->BelongsToCurrentThread());
|
||||
+ webrtc_channel_->UnregisterObserver();
|
||||
blink_channel_ = nullptr;
|
||||
- if (webrtc_channel_.get()) {
|
||||
- webrtc_channel_->UnregisterObserver();
|
||||
- // Now that we're guaranteed to not get further OnStateChange callbacks,
|
||||
- // it's safe to release our reference to the channel.
|
||||
- webrtc_channel_ = nullptr;
|
||||
- }
|
||||
}
|
||||
|
||||
void RTCDataChannel::Observer::OnStateChange() {
|
||||
@@ -302,7 +298,7 @@ void RTCDataChannel::Observer::OnMessageImpl(
|
||||
|
||||
RTCDataChannel::RTCDataChannel(
|
||||
ExecutionContext* context,
|
||||
- scoped_refptr<webrtc::DataChannelInterface> channel,
|
||||
+ scoped_refptr<webrtc::DataChannelInterface> data_channel,
|
||||
RTCPeerConnectionHandler* peer_connection_handler)
|
||||
: ExecutionContextLifecycleObserver(context),
|
||||
state_(webrtc::DataChannelInterface::kConnecting),
|
||||
@@ -317,7 +313,7 @@ RTCDataChannel::RTCDataChannel(
|
||||
observer_(base::MakeRefCounted<Observer>(
|
||||
context->GetTaskRunner(TaskType::kNetworking),
|
||||
this,
|
||||
- channel)),
|
||||
+ std::move(data_channel))),
|
||||
signaling_thread_(peer_connection_handler->signaling_thread()) {
|
||||
DCHECK(peer_connection_handler);
|
||||
|
||||
@@ -340,7 +336,7 @@ RTCDataChannel::RTCDataChannel(
|
||||
observer_, state_),
|
||||
"RegisterObserverAndGetStateUpdate");
|
||||
|
||||
- IncrementCounters(*channel.get());
|
||||
+ IncrementCounters(*(observer_->channel()).get());
|
||||
}
|
||||
|
||||
RTCDataChannel::~RTCDataChannel() = default;
|
||||
@@ -689,9 +685,8 @@ void RTCDataChannel::Dispose() {
|
||||
if (stopped_)
|
||||
return;
|
||||
|
||||
- // Clears the weak persistent reference to this on-heap object.
|
||||
+ // Clear the weak persistent reference to this on-heap object.
|
||||
observer_->Unregister();
|
||||
- observer_ = nullptr;
|
||||
}
|
||||
|
||||
void RTCDataChannel::ScheduleDispatchEvent(Event* event) {
|
||||
diff --git a/third_party/blink/renderer/modules/peerconnection/rtc_data_channel.h b/third_party/blink/renderer/modules/peerconnection/rtc_data_channel.h
|
||||
index 21bb39382ac0c6acbf984ffbda5f6a4e6c863432..6959b8b1e3a0b586be68cb4a8d0389b7926b98fe 100644
|
||||
--- a/third_party/blink/renderer/modules/peerconnection/rtc_data_channel.h
|
||||
+++ b/third_party/blink/renderer/modules/peerconnection/rtc_data_channel.h
|
||||
@@ -152,7 +152,7 @@ class MODULES_EXPORT RTCDataChannel final
|
||||
|
||||
const scoped_refptr<base::SingleThreadTaskRunner> main_thread_;
|
||||
WeakPersistent<RTCDataChannel> blink_channel_;
|
||||
- scoped_refptr<webrtc::DataChannelInterface> webrtc_channel_;
|
||||
+ const scoped_refptr<webrtc::DataChannelInterface> webrtc_channel_;
|
||||
};
|
||||
|
||||
void OnStateChange(webrtc::DataChannelInterface::DataState state);
|
||||
@@ -195,7 +195,11 @@ class MODULES_EXPORT RTCDataChannel final
|
||||
unsigned buffered_amount_;
|
||||
bool stopped_;
|
||||
bool closed_from_owner_;
|
||||
- scoped_refptr<Observer> observer_;
|
||||
+ // Keep the `observer_` reference const to make it clear that we don't want
|
||||
+ // to free the underlying channel (or callback observer) until the
|
||||
+ // `RTCDataChannel` instance goes away. This allows properties to be queried
|
||||
+ // after the state reaches `kClosed`.
|
||||
+ const scoped_refptr<Observer> observer_;
|
||||
scoped_refptr<base::SingleThreadTaskRunner> signaling_thread_;
|
||||
THREAD_CHECKER(thread_checker_);
|
||||
};
|
||||
187
patches/chromium/cherry-pick-c60a1ab717c7.patch
Normal file
187
patches/chromium/cherry-pick-c60a1ab717c7.patch
Normal file
@@ -0,0 +1,187 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Taylor Bergquist <tbergquist@chromium.org>
|
||||
Date: Tue, 11 Jul 2023 01:32:22 +0000
|
||||
Subject: Fix UAF when exiting a nested run loop in
|
||||
TabDragContextImpl::OnGestureEvent.
|
||||
|
||||
OnGestureEvent may call ContinueDrag, which may run a nested run loop. After the nested run loop returns, multiple seconds of time may have passed, and the world may be in a very different state; in particular, the window that contains this TabDragContext may have closed.
|
||||
|
||||
This CL checks if this has happened, and returns early in that case.
|
||||
|
||||
(cherry picked from commit 63d6b8ba8126b16215d33670df8c67dcbc6c9bef)
|
||||
|
||||
Bug: 1453465
|
||||
Change-Id: I6095c0afeb5aa5f422717f1bbd93b96175e52afa
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/4657527
|
||||
Reviewed-by: Darryl James <dljames@chromium.org>
|
||||
Commit-Queue: Taylor Bergquist <tbergquist@chromium.org>
|
||||
Code-Coverage: Findit <findit-for-me@appspot.gserviceaccount.com>
|
||||
Cr-Original-Commit-Position: refs/heads/main@{#1164449}
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/4676126
|
||||
Reviewed-by: Shibalik Mohapatra <shibalik@chromium.org>
|
||||
Cr-Commit-Position: refs/branch-heads/5845@{#410}
|
||||
Cr-Branched-From: 5a5dff63a4a4c63b9b18589819bebb2566c85443-refs/heads/main@{#1160321}
|
||||
|
||||
diff --git a/chrome/browser/ui/views/tabs/fake_tab_slot_controller.cc b/chrome/browser/ui/views/tabs/fake_tab_slot_controller.cc
|
||||
index d1f5a96ed729fde1224f596212f49e386fc6f170..c80536b0d4601c68ce279dfa122f38b39b13fb72 100644
|
||||
--- a/chrome/browser/ui/views/tabs/fake_tab_slot_controller.cc
|
||||
+++ b/chrome/browser/ui/views/tabs/fake_tab_slot_controller.cc
|
||||
@@ -43,6 +43,12 @@ bool FakeTabSlotController::IsFocusInTabs() const {
|
||||
return false;
|
||||
}
|
||||
|
||||
+TabSlotController::Liveness FakeTabSlotController::ContinueDrag(
|
||||
+ views::View* view,
|
||||
+ const ui::LocatedEvent& event) {
|
||||
+ return Liveness::kAlive;
|
||||
+}
|
||||
+
|
||||
bool FakeTabSlotController::EndDrag(EndDragReason reason) {
|
||||
return false;
|
||||
}
|
||||
diff --git a/chrome/browser/ui/views/tabs/fake_tab_slot_controller.h b/chrome/browser/ui/views/tabs/fake_tab_slot_controller.h
|
||||
index 25f1c66d131189ebec2711b49f7f0c141f2c06d2..98dab21cfe2e3ecb88f70cac3868fb30828658be 100644
|
||||
--- a/chrome/browser/ui/views/tabs/fake_tab_slot_controller.h
|
||||
+++ b/chrome/browser/ui/views/tabs/fake_tab_slot_controller.h
|
||||
@@ -60,8 +60,8 @@ class FakeTabSlotController : public TabSlotController {
|
||||
TabSlotView* source,
|
||||
const ui::LocatedEvent& event,
|
||||
const ui::ListSelectionModel& original_selection) override {}
|
||||
- void ContinueDrag(views::View* view, const ui::LocatedEvent& event) override {
|
||||
- }
|
||||
+ Liveness ContinueDrag(views::View* view,
|
||||
+ const ui::LocatedEvent& event) override;
|
||||
bool EndDrag(EndDragReason reason) override;
|
||||
Tab* GetTabAt(const gfx::Point& point) override;
|
||||
const Tab* GetAdjacentTab(const Tab* tab, int offset) override;
|
||||
diff --git a/chrome/browser/ui/views/tabs/tab_slot_controller.h b/chrome/browser/ui/views/tabs/tab_slot_controller.h
|
||||
index f729425995ffd1ee6926ef953417d2e81a1b527b..c57760f30ae515cf5ee7a021e07c8d049082e371 100644
|
||||
--- a/chrome/browser/ui/views/tabs/tab_slot_controller.h
|
||||
+++ b/chrome/browser/ui/views/tabs/tab_slot_controller.h
|
||||
@@ -49,6 +49,8 @@ class TabSlotController {
|
||||
kEvent
|
||||
};
|
||||
|
||||
+ enum class Liveness { kAlive, kDeleted };
|
||||
+
|
||||
virtual const ui::ListSelectionModel& GetSelectionModel() const = 0;
|
||||
|
||||
// Returns the tab at |index|.
|
||||
@@ -126,9 +128,10 @@ class TabSlotController {
|
||||
const ui::LocatedEvent& event,
|
||||
const ui::ListSelectionModel& original_selection) = 0;
|
||||
|
||||
- // Continues dragging a Tab.
|
||||
- virtual void ContinueDrag(views::View* view,
|
||||
- const ui::LocatedEvent& event) = 0;
|
||||
+ // Continues dragging a Tab. May enter a nested event loop - returns
|
||||
+ // Liveness::kDeleted if `this` was destroyed during this nested event loop,
|
||||
+ // and Liveness::kAlive if `this` is still alive.
|
||||
+ virtual Liveness ContinueDrag(views::View* view, const ui::LocatedEvent& event) = 0;
|
||||
|
||||
// Ends dragging a Tab. Returns whether the tab has been destroyed.
|
||||
virtual bool EndDrag(EndDragReason reason) = 0;
|
||||
diff --git a/chrome/browser/ui/views/tabs/tab_strip.cc b/chrome/browser/ui/views/tabs/tab_strip.cc
|
||||
index 0a9ffa81d06d4bb284e8aa51758fbafc9e1b6644..cb82dc62aee1970d50a91f9692208b7303333d1d 100644
|
||||
--- a/chrome/browser/ui/views/tabs/tab_strip.cc
|
||||
+++ b/chrome/browser/ui/views/tabs/tab_strip.cc
|
||||
@@ -186,7 +186,7 @@ class TabStrip::TabDragContextImpl : public TabDragContext,
|
||||
}
|
||||
|
||||
bool OnMouseDragged(const ui::MouseEvent& event) override {
|
||||
- ContinueDrag(this, event);
|
||||
+ (void)ContinueDrag(this, event);
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -197,6 +197,7 @@ class TabStrip::TabDragContextImpl : public TabDragContext,
|
||||
void OnMouseCaptureLost() override { EndDrag(END_DRAG_CAPTURE_LOST); }
|
||||
|
||||
void OnGestureEvent(ui::GestureEvent* event) override {
|
||||
+ Liveness tabstrip_alive = Liveness::kAlive;
|
||||
switch (event->type()) {
|
||||
case ui::ET_GESTURE_SCROLL_END:
|
||||
case ui::ET_SCROLL_FLING_START:
|
||||
@@ -210,7 +211,8 @@ class TabStrip::TabDragContextImpl : public TabDragContext,
|
||||
}
|
||||
|
||||
case ui::ET_GESTURE_SCROLL_UPDATE:
|
||||
- ContinueDrag(this, *event);
|
||||
+ // N.B. !! ContinueDrag may enter a nested run loop !!
|
||||
+ tabstrip_alive = ContinueDrag(this, *event);
|
||||
break;
|
||||
|
||||
case ui::ET_GESTURE_TAP_DOWN:
|
||||
@@ -222,6 +224,12 @@ class TabStrip::TabDragContextImpl : public TabDragContext,
|
||||
}
|
||||
event->SetHandled();
|
||||
|
||||
+ // If tabstrip was destroyed (during ContinueDrag above), return early to
|
||||
+ // avoid UAF below.
|
||||
+ if (tabstrip_alive == Liveness::kDeleted) {
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
// TabDragContext gets event capture as soon as a drag session begins, which
|
||||
// precludes TabStrip from ever getting events like tap or long tap. Forward
|
||||
// this on to TabStrip so it can respond to those events.
|
||||
@@ -310,20 +318,20 @@ class TabStrip::TabDragContextImpl : public TabDragContext,
|
||||
std::move(drag_controller_set_callback_).Run(drag_controller_.get());
|
||||
}
|
||||
|
||||
- void ContinueDrag(views::View* view, const ui::LocatedEvent& event) {
|
||||
- if (drag_controller_.get() &&
|
||||
- drag_controller_->event_source() == EventSourceFromEvent(event)) {
|
||||
- gfx::Point screen_location(event.location());
|
||||
- views::View::ConvertPointToScreen(view, &screen_location);
|
||||
+ Liveness ContinueDrag(views::View* view, const ui::LocatedEvent& event) {
|
||||
+ if (!drag_controller_.get() ||
|
||||
+ drag_controller_->event_source() != EventSourceFromEvent(event)) {
|
||||
+ return Liveness::kAlive;
|
||||
+ }
|
||||
|
||||
- // Note: |tab_strip_| can be destroyed during drag, also destroying
|
||||
- // |this|.
|
||||
- base::WeakPtr<TabDragContext> weak_ptr(weak_factory_.GetWeakPtr());
|
||||
- drag_controller_->Drag(screen_location);
|
||||
+ gfx::Point screen_location(event.location());
|
||||
+ views::View::ConvertPointToScreen(view, &screen_location);
|
||||
|
||||
- if (!weak_ptr)
|
||||
- return;
|
||||
- }
|
||||
+ // Note: `tab_strip_` can be destroyed during drag, also destroying `this`.
|
||||
+ base::WeakPtr<TabDragContext> weak_ptr(weak_factory_.GetWeakPtr());
|
||||
+ drag_controller_->Drag(screen_location);
|
||||
+
|
||||
+ return weak_ptr ? Liveness::kAlive : Liveness::kDeleted;
|
||||
}
|
||||
|
||||
bool EndDrag(EndDragReason reason) {
|
||||
@@ -1607,8 +1615,10 @@ void TabStrip::MaybeStartDrag(
|
||||
drag_context_->MaybeStartDrag(source, event, original_selection);
|
||||
}
|
||||
|
||||
-void TabStrip::ContinueDrag(views::View* view, const ui::LocatedEvent& event) {
|
||||
- drag_context_->ContinueDrag(view, event);
|
||||
+TabSlotController::Liveness TabStrip::ContinueDrag(
|
||||
+ views::View* view,
|
||||
+ const ui::LocatedEvent& event) {
|
||||
+ return drag_context_->ContinueDrag(view, event);
|
||||
}
|
||||
|
||||
bool TabStrip::EndDrag(EndDragReason reason) {
|
||||
diff --git a/chrome/browser/ui/views/tabs/tab_strip.h b/chrome/browser/ui/views/tabs/tab_strip.h
|
||||
index c542581822cabc26b41ab8619fd73cb15c7f8524..682a44d3d9ad10aecc28e542c0cea0c323ee0c85 100644
|
||||
--- a/chrome/browser/ui/views/tabs/tab_strip.h
|
||||
+++ b/chrome/browser/ui/views/tabs/tab_strip.h
|
||||
@@ -278,7 +278,8 @@ class TabStrip : public views::View,
|
||||
TabSlotView* source,
|
||||
const ui::LocatedEvent& event,
|
||||
const ui::ListSelectionModel& original_selection) override;
|
||||
- void ContinueDrag(views::View* view, const ui::LocatedEvent& event) override;
|
||||
+ Liveness ContinueDrag(views::View* view,
|
||||
+ const ui::LocatedEvent& event) override;
|
||||
bool EndDrag(EndDragReason reason) override;
|
||||
Tab* GetTabAt(const gfx::Point& point) override;
|
||||
const Tab* GetAdjacentTab(const Tab* tab, int offset) override;
|
||||
47
patches/chromium/cherry-pick-d6946b70b431.patch
Normal file
47
patches/chromium/cherry-pick-d6946b70b431.patch
Normal file
@@ -0,0 +1,47 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Dave Tapuska <dtapuska@chromium.org>
|
||||
Date: Fri, 24 Mar 2023 19:32:54 +0000
|
||||
Subject: Move the edit commands to an on stack variable
|
||||
|
||||
DevTools uses nested event loops and the usage of the class member can
|
||||
be problematic for iteration because the nested loop can change the
|
||||
variable's storage causing a UAF.
|
||||
|
||||
(cherry picked from commit d9b34f0f3a2d0dd73648eca3ef940fb66806227b)
|
||||
|
||||
Bug: 1420510
|
||||
Change-Id: Ie08a71b60401fa4322cca0cc31062ba64672126a
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/4355811
|
||||
Reviewed-by: David Bokan <bokan@chromium.org>
|
||||
Commit-Queue: Dave Tapuska <dtapuska@chromium.org>
|
||||
Reviewed-by: Daniel Cheng <dcheng@chromium.org>
|
||||
Cr-Original-Commit-Position: refs/heads/main@{#1120123}
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/4369603
|
||||
Cr-Commit-Position: refs/branch-heads/5615@{#809}
|
||||
Cr-Branched-From: 9c6408ef696e83a9936b82bbead3d41c93c82ee4-refs/heads/main@{#1109224}
|
||||
|
||||
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 7d3c2c0a0db83ae5b7980deedd605174837fa801..0da9bc6d464f09d81c0bd8943f74370ee81325b0 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
|
||||
@@ -3198,11 +3198,18 @@ void WebFrameWidgetImpl::AddEditCommandForNextKeyEvent(const WebString& name,
|
||||
}
|
||||
|
||||
bool WebFrameWidgetImpl::HandleCurrentKeyboardEvent() {
|
||||
- bool did_execute_command = false;
|
||||
+ if (edit_commands_.empty()) {
|
||||
+ return false;
|
||||
+ }
|
||||
WebLocalFrame* frame = FocusedWebLocalFrameInWidget();
|
||||
if (!frame)
|
||||
frame = local_root_;
|
||||
- for (const auto& command : edit_commands_) {
|
||||
+ bool did_execute_command = false;
|
||||
+ // Executing an edit command can run JS and we can end up reassigning
|
||||
+ // `edit_commands_` so move it to a stack variable before iterating on it.
|
||||
+ Vector<mojom::blink::EditCommandPtr> edit_commands =
|
||||
+ std::move(edit_commands_);
|
||||
+ for (const auto& command : edit_commands) {
|
||||
// In gtk and cocoa, it's possible to bind multiple edit commands to one
|
||||
// key (but it's the exception). Once one edit command is not executed, it
|
||||
// seems safest to not execute the rest.
|
||||
90
patches/chromium/cherry-pick-d9081493c4b2.patch
Normal file
90
patches/chromium/cherry-pick-d9081493c4b2.patch
Normal file
@@ -0,0 +1,90 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: kylechar <kylechar@chromium.org>
|
||||
Date: Tue, 28 Feb 2023 21:02:51 +0000
|
||||
Subject: Add CHECKs in HostFrameSinkManager
|
||||
|
||||
It looks like it's possible for a compromised renderer to get multiple
|
||||
things to register the same FrameSinkId with HostFrameSinkManager. This
|
||||
violates assumptions around ownership so turn DCHECKs here into CHECKs.
|
||||
Also convert DCHECKs into CHECKs for registering/unregistering frame
|
||||
sink hierarchy just in case.
|
||||
|
||||
(cherry picked from commit a707ac2d95e4726f4cf0267c9b0c038926c2a691)
|
||||
|
||||
Bug: 1414018
|
||||
Change-Id: If948e758a8484024666f4066360620bc3a9cb493
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/4283141
|
||||
Reviewed-by: Martin Kreichgauer <martinkr@google.com>
|
||||
Reviewed-by: Jonathan Ross <jonross@chromium.org>
|
||||
Commit-Queue: Kyle Charbonneau <kylechar@chromium.org>
|
||||
Cr-Original-Commit-Position: refs/heads/main@{#1109533}
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/4298330
|
||||
Cr-Commit-Position: refs/branch-heads/5615@{#69}
|
||||
Cr-Branched-From: 9c6408ef696e83a9936b82bbead3d41c93c82ee4-refs/heads/main@{#1109224}
|
||||
|
||||
diff --git a/components/viz/host/host_frame_sink_manager.cc b/components/viz/host/host_frame_sink_manager.cc
|
||||
index 923cd827c31fcaaf41bd0247ec5221704c0bb3ea..65241be62293d64f3b09e2cf2b68bb6d946bcdb2 100644
|
||||
--- a/components/viz/host/host_frame_sink_manager.cc
|
||||
+++ b/components/viz/host/host_frame_sink_manager.cc
|
||||
@@ -68,7 +68,7 @@ void HostFrameSinkManager::RegisterFrameSinkId(
|
||||
DCHECK(client);
|
||||
|
||||
FrameSinkData& data = frame_sink_data_map_[frame_sink_id];
|
||||
- DCHECK(!data.IsFrameSinkRegistered());
|
||||
+ CHECK(!data.IsFrameSinkRegistered());
|
||||
DCHECK(!data.has_created_compositor_frame_sink);
|
||||
data.client = client;
|
||||
data.report_activation = report_activation;
|
||||
@@ -87,7 +87,7 @@ void HostFrameSinkManager::InvalidateFrameSinkId(
|
||||
DCHECK(frame_sink_id.is_valid());
|
||||
|
||||
FrameSinkData& data = frame_sink_data_map_[frame_sink_id];
|
||||
- DCHECK(data.IsFrameSinkRegistered());
|
||||
+ CHECK(data.IsFrameSinkRegistered());
|
||||
|
||||
const bool destroy_synchronously =
|
||||
data.has_created_compositor_frame_sink && data.wait_on_destruction;
|
||||
@@ -227,14 +227,14 @@ bool HostFrameSinkManager::RegisterFrameSinkHierarchy(
|
||||
return false;
|
||||
}
|
||||
|
||||
+ FrameSinkData& parent_data = iter->second;
|
||||
+ CHECK(!base::Contains(parent_data.children, child_frame_sink_id));
|
||||
+ parent_data.children.push_back(child_frame_sink_id);
|
||||
+
|
||||
// Register and store the parent.
|
||||
frame_sink_manager_->RegisterFrameSinkHierarchy(parent_frame_sink_id,
|
||||
child_frame_sink_id);
|
||||
|
||||
- FrameSinkData& parent_data = iter->second;
|
||||
- DCHECK(!base::Contains(parent_data.children, child_frame_sink_id));
|
||||
- parent_data.children.push_back(child_frame_sink_id);
|
||||
-
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -243,8 +243,9 @@ void HostFrameSinkManager::UnregisterFrameSinkHierarchy(
|
||||
const FrameSinkId& child_frame_sink_id) {
|
||||
// Unregister and clear the stored parent.
|
||||
FrameSinkData& parent_data = frame_sink_data_map_[parent_frame_sink_id];
|
||||
- DCHECK(base::Contains(parent_data.children, child_frame_sink_id));
|
||||
- base::Erase(parent_data.children, child_frame_sink_id);
|
||||
+ size_t num_erased = base::Erase(parent_data.children, child_frame_sink_id);
|
||||
+ CHECK_EQ(num_erased, 1u);
|
||||
+
|
||||
if (parent_data.IsEmpty())
|
||||
frame_sink_data_map_.erase(parent_frame_sink_id);
|
||||
|
||||
diff --git a/components/viz/service/frame_sinks/frame_sink_manager_impl.cc b/components/viz/service/frame_sinks/frame_sink_manager_impl.cc
|
||||
index b55780a0e0c5c59d97a0123829dac512eca07029..ad2575c1666ea0be7d65774309447c89b199cf7a 100644
|
||||
--- a/components/viz/service/frame_sinks/frame_sink_manager_impl.cc
|
||||
+++ b/components/viz/service/frame_sinks/frame_sink_manager_impl.cc
|
||||
@@ -284,7 +284,7 @@ void FrameSinkManagerImpl::UnregisterFrameSinkHierarchy(
|
||||
}
|
||||
|
||||
auto iter = frame_sink_source_map_.find(parent_frame_sink_id);
|
||||
- DCHECK(iter != frame_sink_source_map_.end());
|
||||
+ CHECK(iter != frame_sink_source_map_.end());
|
||||
|
||||
// Remove |child_frame_sink_id| from parents list of children.
|
||||
auto& mapping = iter->second;
|
||||
200
patches/chromium/cherry-pick-ea1cd76358e0.patch
Normal file
200
patches/chromium/cherry-pick-ea1cd76358e0.patch
Normal file
@@ -0,0 +1,200 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Kevin McNee <mcnee@chromium.org>
|
||||
Date: Tue, 23 May 2023 15:46:16 +0000
|
||||
Subject: M114: Compute all webview find options before cloning them
|
||||
|
||||
Compute all webview find options before cloning them
|
||||
|
||||
In WebViewFindHelper::Find, we're cloning the find options before we've
|
||||
set the value for `new_session`. For requests that are part of the same
|
||||
session, in WebViewFindHelper::FindReply, we're using the incorrect
|
||||
value for `new_session` and we're destroying the FindInfo for what we
|
||||
think is a previous session but is actually for the request we're
|
||||
currently processing.
|
||||
|
||||
We now fully compute the options before cloning them.
|
||||
|
||||
(cherry picked from commit bb8e17b942b8b1de0a58b2dce34197e00a3b6525)
|
||||
|
||||
Bug: 1443401
|
||||
Change-Id: Ife6747aedabaf74f9a4855a173349ffe612b6f95
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/4533923
|
||||
Reviewed-by: James Maclean <wjmaclean@chromium.org>
|
||||
Commit-Queue: James Maclean <wjmaclean@chromium.org>
|
||||
Auto-Submit: Kevin McNee <mcnee@chromium.org>
|
||||
Cr-Original-Commit-Position: refs/heads/main@{#1145265}
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/4556646
|
||||
Commit-Queue: Rubber Stamper <rubber-stamper@appspot.gserviceaccount.com>
|
||||
Bot-Commit: Rubber Stamper <rubber-stamper@appspot.gserviceaccount.com>
|
||||
Cr-Commit-Position: refs/branch-heads/5735@{#941}
|
||||
Cr-Branched-From: 2f562e4ddbaf79a3f3cb338b4d1bd4398d49eb67-refs/heads/main@{#1135570}
|
||||
|
||||
diff --git a/chrome/browser/apps/guest_view/web_view_browsertest.cc b/chrome/browser/apps/guest_view/web_view_browsertest.cc
|
||||
index cebe56b9e79cbe0e5a58f73e68faf1b93b17ce5c..3748f8119bf1d4f37635bdb4fb87d825881de7f0 100644
|
||||
--- a/chrome/browser/apps/guest_view/web_view_browsertest.cc
|
||||
+++ b/chrome/browser/apps/guest_view/web_view_browsertest.cc
|
||||
@@ -3888,6 +3888,11 @@ IN_PROC_BROWSER_TEST_P(WebViewTest, Shim_testFindInMultipleWebViews) {
|
||||
TestHelper("testFindInMultipleWebViews", "web_view/shim", NO_TEST_SERVER);
|
||||
}
|
||||
|
||||
+IN_PROC_BROWSER_TEST_F(WebViewTest, Shim_TestFindAfterTerminate) {
|
||||
+ content::ScopedAllowRendererCrashes scoped_allow_renderer_crashes;
|
||||
+ TestHelper("testFindAfterTerminate", "web_view/shim", NO_TEST_SERVER);
|
||||
+}
|
||||
+
|
||||
IN_PROC_BROWSER_TEST_P(WebViewTest, Shim_TestLoadDataAPI) {
|
||||
TestHelper("testLoadDataAPI", "web_view/shim", NEEDS_TEST_SERVER);
|
||||
|
||||
diff --git a/chrome/test/data/extensions/platform_apps/web_view/shim/main.js b/chrome/test/data/extensions/platform_apps/web_view/shim/main.js
|
||||
index 5ed4f0223346b01d83cc04c8cda6c0e92e1a72e3..4a1543d1751cc817a511594d0123deacc0e61ebb 100644
|
||||
--- a/chrome/test/data/extensions/platform_apps/web_view/shim/main.js
|
||||
+++ b/chrome/test/data/extensions/platform_apps/web_view/shim/main.js
|
||||
@@ -2859,6 +2859,20 @@ function testFindInMultipleWebViews() {
|
||||
});
|
||||
}
|
||||
|
||||
+function testFindAfterTerminate() {
|
||||
+ let webview = new WebView();
|
||||
+ webview.src = 'data:text/html,<body><iframe></iframe></body>';
|
||||
+ webview.addEventListener('loadstop', () => {
|
||||
+ webview.find('A');
|
||||
+ webview.terminate();
|
||||
+ webview.find('B', {'backward': true});
|
||||
+ webview.find('B', {'backward': true}, (results) => {
|
||||
+ embedder.test.succeed();
|
||||
+ });
|
||||
+ });
|
||||
+ document.body.appendChild(webview);
|
||||
+}
|
||||
+
|
||||
function testLoadDataAPI() {
|
||||
var webview = new WebView();
|
||||
webview.src = 'about:blank';
|
||||
@@ -3600,6 +3614,7 @@ embedder.test.testList = {
|
||||
'testFindAPI': testFindAPI,
|
||||
'testFindAPI_findupdate': testFindAPI_findupdate,
|
||||
'testFindInMultipleWebViews': testFindInMultipleWebViews,
|
||||
+ 'testFindAfterTerminate': testFindAfterTerminate,
|
||||
'testLoadDataAPI': testLoadDataAPI,
|
||||
'testLoadDataAPIAccessibleResources': testLoadDataAPIAccessibleResources,
|
||||
'testResizeEvents': testResizeEvents,
|
||||
diff --git a/extensions/browser/guest_view/web_view/web_view_find_helper.cc b/extensions/browser/guest_view/web_view/web_view_find_helper.cc
|
||||
index 1e9148687f6871dff8a394cce53771e443775679..37630dc2f0a6365bbf33e765f4d126e2962fbb2a 100644
|
||||
--- a/extensions/browser/guest_view/web_view/web_view_find_helper.cc
|
||||
+++ b/extensions/browser/guest_view/web_view/web_view_find_helper.cc
|
||||
@@ -36,12 +36,12 @@ void WebViewFindHelper::CancelAllFindSessions() {
|
||||
|
||||
void WebViewFindHelper::DispatchFindUpdateEvent(bool canceled,
|
||||
bool final_update) {
|
||||
- DCHECK(find_update_event_.get());
|
||||
+ CHECK(find_update_event_);
|
||||
base::Value::Dict args;
|
||||
find_update_event_->PrepareResults(args);
|
||||
args.Set(webview::kFindCanceled, canceled);
|
||||
args.Set(webview::kFindFinalUpdate, final_update);
|
||||
- DCHECK(webview_guest_);
|
||||
+ CHECK(webview_guest_);
|
||||
webview_guest_->DispatchEventToView(std::make_unique<GuestViewEvent>(
|
||||
webview::kEventFindReply, std::move(args)));
|
||||
}
|
||||
@@ -94,6 +94,17 @@ void WebViewFindHelper::Find(
|
||||
// Need a new request_id for each new find request.
|
||||
++current_find_request_id_;
|
||||
|
||||
+ if (current_find_session_) {
|
||||
+ const std::u16string& current_search_text =
|
||||
+ current_find_session_->search_text();
|
||||
+ bool current_match_case = current_find_session_->options()->match_case;
|
||||
+ options->new_session = current_search_text.empty() ||
|
||||
+ current_search_text != search_text ||
|
||||
+ current_match_case != options->match_case;
|
||||
+ } else {
|
||||
+ options->new_session = true;
|
||||
+ }
|
||||
+
|
||||
// Stores the find request information by request_id so that its callback
|
||||
// function can be called when the find results are available.
|
||||
std::pair<FindInfoMap::iterator, bool> insert_result =
|
||||
@@ -102,32 +113,19 @@ void WebViewFindHelper::Find(
|
||||
base::MakeRefCounted<FindInfo>(current_find_request_id_, search_text,
|
||||
options.Clone(), find_function)));
|
||||
// No duplicate insertions.
|
||||
- DCHECK(insert_result.second);
|
||||
-
|
||||
- blink::mojom::FindOptionsPtr full_options =
|
||||
- insert_result.first->second->options().Clone();
|
||||
-
|
||||
- if (current_find_session_) {
|
||||
- const std::u16string& current_search_text =
|
||||
- current_find_session_->search_text();
|
||||
- bool current_match_case = current_find_session_->options()->match_case;
|
||||
- full_options->new_session = current_search_text.empty() ||
|
||||
- current_search_text != search_text ||
|
||||
- current_match_case != options->match_case;
|
||||
- } else {
|
||||
- full_options->new_session = true;
|
||||
- }
|
||||
+ CHECK(insert_result.second);
|
||||
|
||||
// Link find requests that are a part of the same find session.
|
||||
- if (!full_options->new_session && current_find_session_) {
|
||||
- DCHECK(current_find_request_id_ != current_find_session_->request_id());
|
||||
+ if (!options->new_session && current_find_session_) {
|
||||
+ CHECK(current_find_request_id_ != current_find_session_->request_id());
|
||||
current_find_session_->AddFindNextRequest(
|
||||
insert_result.first->second->AsWeakPtr());
|
||||
}
|
||||
|
||||
// Update the current find session, if necessary.
|
||||
- if (full_options->new_session)
|
||||
+ if (options->new_session) {
|
||||
current_find_session_ = insert_result.first->second;
|
||||
+ }
|
||||
|
||||
// Handle the empty |search_text| case internally.
|
||||
if (search_text.empty()) {
|
||||
@@ -137,7 +135,7 @@ void WebViewFindHelper::Find(
|
||||
}
|
||||
|
||||
guest_web_contents->Find(current_find_request_id_, search_text,
|
||||
- std::move(full_options), /*skip_delay=*/true);
|
||||
+ std::move(options), /*skip_delay=*/true);
|
||||
}
|
||||
|
||||
void WebViewFindHelper::FindReply(int request_id,
|
||||
@@ -152,14 +150,14 @@ void WebViewFindHelper::FindReply(int request_id,
|
||||
return;
|
||||
|
||||
// This find request must be a part of an existing find session.
|
||||
- DCHECK(current_find_session_);
|
||||
+ CHECK(current_find_session_);
|
||||
|
||||
WebViewFindHelper::FindInfo* find_info = find_iterator->second.get();
|
||||
// Handle canceled find requests.
|
||||
if (find_info->options()->new_session &&
|
||||
find_info_map_.begin()->first < request_id) {
|
||||
- DCHECK_NE(current_find_session_->request_id(),
|
||||
- find_info_map_.begin()->first);
|
||||
+ CHECK_NE(current_find_session_->request_id(),
|
||||
+ find_info_map_.begin()->first);
|
||||
if (find_update_event_)
|
||||
DispatchFindUpdateEvent(true /* canceled */, true /* final_update */);
|
||||
EndFindSession(find_info_map_.begin()->first, true /* canceled */);
|
||||
@@ -174,11 +172,12 @@ void WebViewFindHelper::FindReply(int request_id,
|
||||
// Aggregate the find results.
|
||||
find_info->AggregateResults(number_of_matches, selection_rect,
|
||||
active_match_ordinal, final_update);
|
||||
- find_update_event_->AggregateResults(number_of_matches, selection_rect,
|
||||
- active_match_ordinal, final_update);
|
||||
-
|
||||
- // Propagate incremental results to the |findupdate| event.
|
||||
- DispatchFindUpdateEvent(false /* canceled */, final_update);
|
||||
+ if (find_update_event_) {
|
||||
+ find_update_event_->AggregateResults(number_of_matches, selection_rect,
|
||||
+ active_match_ordinal, final_update);
|
||||
+ // Propagate incremental results to the |findupdate| event.
|
||||
+ DispatchFindUpdateEvent(false /* canceled */, final_update);
|
||||
+ }
|
||||
|
||||
// Call the callback functions of completed find requests.
|
||||
if (final_update)
|
||||
52
patches/chromium/cherry-pick-ec53103cc72d.patch
Normal file
52
patches/chromium/cherry-pick-ec53103cc72d.patch
Normal file
@@ -0,0 +1,52 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: chromium-autoroll
|
||||
<chromium-autoroll@skia-public.iam.gserviceaccount.com>
|
||||
Date: Wed, 12 Apr 2023 21:54:57 +0000
|
||||
Subject: Roll Skia from 288bdaeb99a4 to d5846fb1f236 (5 revisions)
|
||||
|
||||
https://skia.googlesource.com/skia.git/+log/288bdaeb99a4..d5846fb1f236
|
||||
|
||||
2023-04-12 johnstiles@google.com Use packed contexts for binary ops in SkRP.
|
||||
2023-04-12 kjlubick@google.com Add more stubs for encoders
|
||||
2023-04-12 johnstiles@google.com Enforce program stack limits on function parameters.
|
||||
2023-04-12 johnstiles@google.com Reland "Use packed contexts for copy/splat-constant ops in SkRP."
|
||||
2023-04-12 jamesgk@google.com [graphite] Use replay translation in Dawn backend
|
||||
|
||||
If this roll has caused a breakage, revert this CL and stop the roller
|
||||
using the controls here:
|
||||
https://autoroll.skia.org/r/skia-autoroll
|
||||
Please CC borenet@google.com,lovisolo@google.com on the revert to ensure that a human
|
||||
is aware of the problem.
|
||||
|
||||
To file a bug in Skia: https://bugs.chromium.org/p/skia/issues/entry
|
||||
To file a bug in Chromium: https://bugs.chromium.org/p/chromium/issues/entry
|
||||
|
||||
To report a problem with the AutoRoller itself, please file a bug:
|
||||
https://bugs.chromium.org/p/skia/issues/entry?template=Autoroller+Bug
|
||||
|
||||
Documentation for the AutoRoller is here:
|
||||
https://skia.googlesource.com/buildbot/+doc/main/autoroll/README.md
|
||||
|
||||
Cq-Include-Trybots: luci.chromium.try:android_optional_gpu_tests_rel;luci.chromium.try:linux-blink-rel;luci.chromium.try:linux-chromeos-compile-dbg;luci.chromium.try:linux_optional_gpu_tests_rel;luci.chromium.try:mac_optional_gpu_tests_rel;luci.chromium.try:win_optional_gpu_tests_rel
|
||||
Cq-Do-Not-Cancel-Tryjobs: true
|
||||
Bug: chromium:1432603
|
||||
Tbr: lovisolo@google.com
|
||||
Change-Id: I8e08120b5eabe293c64fecfd76ff60b2d73401c5
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/4420129
|
||||
Commit-Queue: chromium-autoroll <chromium-autoroll@skia-public.iam.gserviceaccount.com>
|
||||
Bot-Commit: chromium-autoroll <chromium-autoroll@skia-public.iam.gserviceaccount.com>
|
||||
Cr-Commit-Position: refs/heads/main@{#1129520}
|
||||
|
||||
diff --git a/DEPS b/DEPS
|
||||
index eefdda416ecc032bf2fad613c64efde49a59e9ad..7440c4f0394f9457b69da3ab41906650847ae6c8 100644
|
||||
--- a/DEPS
|
||||
+++ b/DEPS
|
||||
@@ -299,7 +299,7 @@ vars = {
|
||||
# Three lines of non-changing comments so that
|
||||
# the commit queue can handle CLs rolling Skia
|
||||
# and whatever else without interference from each other.
|
||||
- 'skia_revision': 'aab9fb4100da797d25fe340e9a2fcb2ae30fc2e1',
|
||||
+ 'skia_revision': 'd5846fb1f236b9a115f0acd432daa3de18a64419',
|
||||
# Three lines of non-changing comments so that
|
||||
# the commit queue can handle CLs rolling V8
|
||||
# and whatever else without interference from each other.
|
||||
143
patches/chromium/cherry-pick-f098ff0d1230.patch
Normal file
143
patches/chromium/cherry-pick-f098ff0d1230.patch
Normal file
@@ -0,0 +1,143 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Andrey Kosyakov <caseq@chromium.org>
|
||||
Date: Thu, 13 Apr 2023 03:55:24 +0000
|
||||
Subject: Retain DevToolsAgentHost after ForceDetachAllSessions()
|
||||
|
||||
(cherry picked from commit 8c4aee2a90d08535cfb1bf0a59e00cae956b1762)
|
||||
|
||||
Bug: 1424337
|
||||
Change-Id: Ie0ebe2a49ffbd2356b896c39446b93e09cd81f5a
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/4378100
|
||||
Reviewed-by: Dmitry Gozman <dgozman@chromium.org>
|
||||
Commit-Queue: Andrey Kosyakov <caseq@chromium.org>
|
||||
Cr-Original-Commit-Position: refs/heads/main@{#1123772}
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/4420271
|
||||
Commit-Queue: Srinivas Sista <srinivassista@chromium.org>
|
||||
Cr-Commit-Position: refs/branch-heads/5615@{#1244}
|
||||
Cr-Branched-From: 9c6408ef696e83a9936b82bbead3d41c93c82ee4-refs/heads/main@{#1109224}
|
||||
|
||||
diff --git a/content/browser/devtools/auction_worklet_devtools_agent_host.cc b/content/browser/devtools/auction_worklet_devtools_agent_host.cc
|
||||
index 20a989999b6da5d269bca3d6c9bf181eea7180e7..34a13a884885926e3985098315fd9121902099e9 100644
|
||||
--- a/content/browser/devtools/auction_worklet_devtools_agent_host.cc
|
||||
+++ b/content/browser/devtools/auction_worklet_devtools_agent_host.cc
|
||||
@@ -96,7 +96,7 @@ AuctionWorkletDevToolsAgentHost::~AuctionWorkletDevToolsAgentHost() = default;
|
||||
|
||||
void AuctionWorkletDevToolsAgentHost::WorkletDestroyed() {
|
||||
worklet_ = nullptr;
|
||||
- ForceDetachAllSessions();
|
||||
+ auto retain_this = ForceDetachAllSessionsImpl();
|
||||
associated_agent_remote_.reset();
|
||||
}
|
||||
|
||||
diff --git a/content/browser/devtools/devtools_agent_host_impl.cc b/content/browser/devtools/devtools_agent_host_impl.cc
|
||||
index 12779c33fd74ce96ebfd7da2666f9fa3865ccfae..002e41a67314327a9b1354c3d6ed79f17b4dace8 100644
|
||||
--- a/content/browser/devtools/devtools_agent_host_impl.cc
|
||||
+++ b/content/browser/devtools/devtools_agent_host_impl.cc
|
||||
@@ -358,12 +358,18 @@ bool DevToolsAgentHostImpl::Inspect() {
|
||||
}
|
||||
|
||||
void DevToolsAgentHostImpl::ForceDetachAllSessions() {
|
||||
- scoped_refptr<DevToolsAgentHostImpl> protect(this);
|
||||
+ std::ignore = ForceDetachAllSessionsImpl();
|
||||
+}
|
||||
+
|
||||
+scoped_refptr<DevToolsAgentHost>
|
||||
+DevToolsAgentHostImpl::ForceDetachAllSessionsImpl() {
|
||||
+ scoped_refptr<DevToolsAgentHost> retain_this(this);
|
||||
while (!sessions_.empty()) {
|
||||
DevToolsAgentHostClient* client = (*sessions_.begin())->GetClient();
|
||||
DetachClient(client);
|
||||
client->AgentHostClosed(this);
|
||||
}
|
||||
+ return retain_this;
|
||||
}
|
||||
|
||||
void DevToolsAgentHostImpl::ForceDetachRestrictedSessions(
|
||||
diff --git a/content/browser/devtools/devtools_agent_host_impl.h b/content/browser/devtools/devtools_agent_host_impl.h
|
||||
index 7c1bb43345084074b27d4b87aa99af582657fb0f..552b3ec81de3b6e5f222f94835802e6c6aac645f 100644
|
||||
--- a/content/browser/devtools/devtools_agent_host_impl.h
|
||||
+++ b/content/browser/devtools/devtools_agent_host_impl.h
|
||||
@@ -62,7 +62,6 @@ class CONTENT_EXPORT DevToolsAgentHostImpl : public DevToolsAgentHost {
|
||||
void DisconnectWebContents() override;
|
||||
void ConnectWebContents(WebContents* wc) override;
|
||||
RenderProcessHost* GetProcessHost() override;
|
||||
- void ForceDetachAllSessions() override;
|
||||
|
||||
struct NetworkLoaderFactoryParamsAndInfo {
|
||||
NetworkLoaderFactoryParamsAndInfo();
|
||||
@@ -126,8 +125,18 @@ class CONTENT_EXPORT DevToolsAgentHostImpl : public DevToolsAgentHost {
|
||||
DevToolsRendererChannel* GetRendererChannel() { return &renderer_channel_; }
|
||||
|
||||
const std::vector<DevToolsSession*>& sessions() const { return sessions_; }
|
||||
+ // Returns refptr retaining `this`. All other references may be removed
|
||||
+ // at this point, so `this` will become invalid as soon as returned refptr
|
||||
+ // gets destroyed.
|
||||
+ [[nodiscard]] scoped_refptr<DevToolsAgentHost> ForceDetachAllSessionsImpl();
|
||||
|
||||
private:
|
||||
+ // Note that calling this may result in the instance being deleted,
|
||||
+ // as instance may be owned by client sessions. This should not be
|
||||
+ // used by methods of derived classes, use `ForceDetachAllSessionsImpl()`
|
||||
+ // above instead.
|
||||
+ void ForceDetachAllSessions() override;
|
||||
+
|
||||
friend class DevToolsAgentHost; // for static methods
|
||||
friend class DevToolsSession;
|
||||
friend class DevToolsRendererChannel;
|
||||
diff --git a/content/browser/devtools/render_frame_devtools_agent_host.cc b/content/browser/devtools/render_frame_devtools_agent_host.cc
|
||||
index 2e0ecd508c3b6b3b3593985b19c0b2d92ebbe4f4..c4da2a97f95c0e213c0ce3fddc96b5596fc8bc0b 100644
|
||||
--- a/content/browser/devtools/render_frame_devtools_agent_host.cc
|
||||
+++ b/content/browser/devtools/render_frame_devtools_agent_host.cc
|
||||
@@ -541,9 +541,9 @@ void RenderFrameDevToolsAgentHost::RenderFrameDeleted(RenderFrameHost* rfh) {
|
||||
}
|
||||
|
||||
void RenderFrameDevToolsAgentHost::DestroyOnRenderFrameGone() {
|
||||
- scoped_refptr<RenderFrameDevToolsAgentHost> protect(this);
|
||||
+ scoped_refptr<DevToolsAgentHost> retain_this;
|
||||
if (IsAttached()) {
|
||||
- ForceDetachAllSessions();
|
||||
+ retain_this = ForceDetachAllSessionsImpl();
|
||||
UpdateRawHeadersAccess(frame_host_);
|
||||
}
|
||||
ChangeFrameHostAndObservedProcess(nullptr);
|
||||
diff --git a/content/browser/devtools/service_worker_devtools_agent_host.cc b/content/browser/devtools/service_worker_devtools_agent_host.cc
|
||||
index 47d2d169a3eb6cf7c135beeb667cfa5b186987a2..14165045182712b71fef70b758f269b1cbbfc7e8 100644
|
||||
--- a/content/browser/devtools/service_worker_devtools_agent_host.cc
|
||||
+++ b/content/browser/devtools/service_worker_devtools_agent_host.cc
|
||||
@@ -320,8 +320,9 @@ void ServiceWorkerDevToolsAgentHost::UpdateProcessHost() {
|
||||
|
||||
void ServiceWorkerDevToolsAgentHost::RenderProcessHostDestroyed(
|
||||
RenderProcessHost* host) {
|
||||
+ scoped_refptr<DevToolsAgentHost> retain_this;
|
||||
if (context_wrapper_->process_manager()->IsShutdown())
|
||||
- ForceDetachAllSessions();
|
||||
+ retain_this = ForceDetachAllSessionsImpl();
|
||||
GetRendererChannel()->SetRenderer(mojo::NullRemote(), mojo::NullReceiver(),
|
||||
ChildProcessHost::kInvalidUniqueID);
|
||||
process_observation_.Reset();
|
||||
diff --git a/content/browser/devtools/web_contents_devtools_agent_host.cc b/content/browser/devtools/web_contents_devtools_agent_host.cc
|
||||
index fb8e10a18bb725eb9280db8695ae12899dba2eef..2203dcef48c70ecc1758062ac871e80983059464 100644
|
||||
--- a/content/browser/devtools/web_contents_devtools_agent_host.cc
|
||||
+++ b/content/browser/devtools/web_contents_devtools_agent_host.cc
|
||||
@@ -299,7 +299,7 @@ DevToolsAgentHostImpl* WebContentsDevToolsAgentHost::GetPrimaryFrameAgent() {
|
||||
|
||||
void WebContentsDevToolsAgentHost::WebContentsDestroyed() {
|
||||
DCHECK_EQ(this, FindAgentHost(web_contents()));
|
||||
- ForceDetachAllSessions();
|
||||
+ auto retain_this = ForceDetachAllSessionsImpl();
|
||||
auto_attacher_.reset();
|
||||
g_agent_host_instances.Get().erase(web_contents());
|
||||
Observe(nullptr);
|
||||
diff --git a/content/browser/devtools/worker_devtools_agent_host.cc b/content/browser/devtools/worker_devtools_agent_host.cc
|
||||
index db788e7298d6696ec5a354cb387dfdc4030d8ce0..0984b3ae35459d8676b903394577cc6a43601ac8 100644
|
||||
--- a/content/browser/devtools/worker_devtools_agent_host.cc
|
||||
+++ b/content/browser/devtools/worker_devtools_agent_host.cc
|
||||
@@ -87,7 +87,7 @@ void WorkerDevToolsAgentHost::ChildWorkerCreated(
|
||||
}
|
||||
|
||||
void WorkerDevToolsAgentHost::Disconnected() {
|
||||
- ForceDetachAllSessions();
|
||||
+ auto retain_this = ForceDetachAllSessionsImpl();
|
||||
GetRendererChannel()->SetRenderer(mojo::NullRemote(), mojo::NullReceiver(),
|
||||
ChildProcessHost::kInvalidUniqueID);
|
||||
std::move(destroyed_callback_).Run(this);
|
||||
98
patches/chromium/cherry-pick-f58218891f8c.patch
Normal file
98
patches/chromium/cherry-pick-f58218891f8c.patch
Normal file
@@ -0,0 +1,98 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Yoshisato Yanagisawa <yyanagisawa@chromium.org>
|
||||
Date: Tue, 11 Apr 2023 07:12:34 +0000
|
||||
Subject: Stop supporting { handleEvent }.
|
||||
|
||||
Make the code aligned with the following specification update:
|
||||
https://github.com/w3c/ServiceWorker/pull/1676
|
||||
|
||||
With the previous specification and code, event listener vector
|
||||
can be modified during the GetEffectiveFunction execution, which may
|
||||
bring unexpected vector state.
|
||||
|
||||
(cherry picked from commit 5105ce37a6853d52ec97894bf6969b3c29a23afd)
|
||||
|
||||
Change-Id: I732c4c9ab2caebc49a7f4ef52640df7b8476d838
|
||||
Bug: 1429201
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/4394402
|
||||
Commit-Queue: Yoshisato Yanagisawa <yyanagisawa@chromium.org>
|
||||
Reviewed-by: Kouhei Ueno <kouhei@chromium.org>
|
||||
Reviewed-by: Domenic Denicola <domenic@chromium.org>
|
||||
Cr-Original-Commit-Position: refs/heads/main@{#1126483}
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/4408837
|
||||
Reviewed-by: Shunya Shishido <sisidovski@chromium.org>
|
||||
Reviewed-by: Minoru Chikamune <chikamune@chromium.org>
|
||||
Cr-Commit-Position: refs/branch-heads/5615@{#1203}
|
||||
Cr-Branched-From: 9c6408ef696e83a9936b82bbead3d41c93c82ee4-refs/heads/main@{#1109224}
|
||||
|
||||
diff --git a/content/browser/service_worker/service_worker_version_browsertest.cc b/content/browser/service_worker/service_worker_version_browsertest.cc
|
||||
index 5834127a6e70389540cbf347e65ae4bc80495317..bff53482eb05f25542bcd9d7cb5b5a05932b9064 100644
|
||||
--- a/content/browser/service_worker/service_worker_version_browsertest.cc
|
||||
+++ b/content/browser/service_worker/service_worker_version_browsertest.cc
|
||||
@@ -988,6 +988,17 @@ IN_PROC_BROWSER_TEST_F(ServiceWorkerVersionBrowserTest,
|
||||
version_->fetch_handler_type());
|
||||
}
|
||||
|
||||
+IN_PROC_BROWSER_TEST_F(ServiceWorkerVersionBrowserTest,
|
||||
+ RemoveFetchEventListenersInGet) {
|
||||
+ StartServerAndNavigateToSetup();
|
||||
+ ASSERT_EQ(Install("/service_worker/fetch_event_object_removing_itself.js"),
|
||||
+ blink::ServiceWorkerStatusCode::kOk);
|
||||
+ EXPECT_EQ(ServiceWorkerVersion::FetchHandlerExistence::EXISTS,
|
||||
+ version_->fetch_handler_existence());
|
||||
+ EXPECT_EQ(ServiceWorkerVersion::FetchHandlerType::kNotSkippable,
|
||||
+ version_->fetch_handler_type());
|
||||
+}
|
||||
+
|
||||
// Check that fetch event handler added in the install event should result in a
|
||||
// service worker that doesn't count as having a fetch event handler.
|
||||
IN_PROC_BROWSER_TEST_F(ServiceWorkerVersionBrowserTest,
|
||||
diff --git a/content/test/data/service_worker/fetch_event_object_removing_itself.js b/content/test/data/service_worker/fetch_event_object_removing_itself.js
|
||||
new file mode 100644
|
||||
index 0000000000000000000000000000000000000000..110bc4821fae3a63a374d3dc6ca954d4bd744952
|
||||
--- /dev/null
|
||||
+++ b/content/test/data/service_worker/fetch_event_object_removing_itself.js
|
||||
@@ -0,0 +1,19 @@
|
||||
+// Copyright 2023 The Chromium Authors
|
||||
+// Use of this source code is governed by a BSD-style license that can be
|
||||
+// found in the LICENSE file.
|
||||
+
|
||||
+let obj = {};
|
||||
+function victim() {}
|
||||
+
|
||||
+Object.defineProperty(obj, 'handleEvent', {
|
||||
+ get: () => {
|
||||
+ // Remove the victim function from the listener vector to break the loop.
|
||||
+ self.removeEventListener('fetch', victim);
|
||||
+ return () => {};
|
||||
+ },
|
||||
+ configurable: true,
|
||||
+ enumerable: true,
|
||||
+});
|
||||
+
|
||||
+self.addEventListener('fetch', obj);
|
||||
+self.addEventListener('fetch', victim);
|
||||
diff --git a/third_party/blink/renderer/modules/service_worker/service_worker_global_scope.cc b/third_party/blink/renderer/modules/service_worker/service_worker_global_scope.cc
|
||||
index 9438405e331f1978a5c9b76bf8a7148064fb6b7d..75d728dd76aec7e5b5a6d2d15e65c65b4c036ca7 100644
|
||||
--- a/third_party/blink/renderer/modules/service_worker/service_worker_global_scope.cc
|
||||
+++ b/third_party/blink/renderer/modules/service_worker/service_worker_global_scope.cc
|
||||
@@ -2621,7 +2621,7 @@ ServiceWorkerGlobalScope::FetchHandlerType() {
|
||||
}
|
||||
|
||||
ScriptState* script_state = ScriptController()->GetScriptState();
|
||||
- // Do not remove this, |scope| is needed by `GetEffectiveFunction`.
|
||||
+ // Do not remove this, |scope| is needed by `GetListenerObject`.
|
||||
ScriptState::Scope scope(script_state);
|
||||
|
||||
// TODO(crbug.com/1349613): revisit the way to implement this.
|
||||
@@ -2629,8 +2629,8 @@ ServiceWorkerGlobalScope::FetchHandlerType() {
|
||||
for (RegisteredEventListener& e : *elv) {
|
||||
EventTarget* et = EventTarget::Create(script_state);
|
||||
v8::Local<v8::Value> v =
|
||||
- To<JSBasedEventListener>(e.Callback())->GetEffectiveFunction(*et);
|
||||
- if (!v->IsFunction() ||
|
||||
+ To<JSBasedEventListener>(e.Callback())->GetListenerObject(*et);
|
||||
+ if (v.IsEmpty() || !v->IsFunction() ||
|
||||
!v.As<v8::Function>()->Experimental_IsNopFunction()) {
|
||||
return mojom::blink::ServiceWorkerFetchHandlerType::kNotSkippable;
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: John Kleinschmidt <jkleinsc@electronjs.org>
|
||||
Date: Thu, 2 Mar 2023 15:26:46 -0500
|
||||
Subject: chore: defer USB service GetDevices request until USB service is
|
||||
ready.
|
||||
|
||||
On macOS we need to wait until the USB service is ready before the list of
|
||||
devices is available. This should no longer be necessary if/when
|
||||
https://crbug.com/1096743 is completed.
|
||||
|
||||
diff --git a/services/device/usb/usb_service_impl.cc b/services/device/usb/usb_service_impl.cc
|
||||
index 9acfb687b85986c2f2ba787e7b67556092a714d2..244fe386e499930e9a9f031edae216bb18b6fc4e 100644
|
||||
--- a/services/device/usb/usb_service_impl.cc
|
||||
+++ b/services/device/usb/usb_service_impl.cc
|
||||
@@ -198,7 +198,7 @@ void UsbServiceImpl::GetDevices(GetDevicesCallback callback) {
|
||||
return;
|
||||
}
|
||||
|
||||
- if (enumeration_in_progress_) {
|
||||
+ if (enumeration_in_progress_ || !enumeration_ready_) {
|
||||
pending_enumeration_callbacks_.push_back(std::move(callback));
|
||||
return;
|
||||
}
|
||||
@@ -82,7 +82,7 @@ index 33ca7a53dfb6d2c9e3a33f0065a3acd806e82e01..9fdf2e8ff0056ff407015b914c6b03eb
|
||||
const Source& GetSource(int index) const override;
|
||||
DesktopMediaList::Type GetMediaListType() const override;
|
||||
diff --git a/chrome/browser/media/webrtc/native_desktop_media_list.cc b/chrome/browser/media/webrtc/native_desktop_media_list.cc
|
||||
index 836f7683b77b3b28f33984f27649d675ddddd5b7..84135d3cf983c88fc165a0fc012200e5132a52ff 100644
|
||||
index 836f7683b77b3b28f33984f27649d675ddddd5b7..18f795dd77754e115aa66a7404a2e4075372bc5f 100644
|
||||
--- a/chrome/browser/media/webrtc/native_desktop_media_list.cc
|
||||
+++ b/chrome/browser/media/webrtc/native_desktop_media_list.cc
|
||||
@@ -141,7 +141,7 @@ BOOL CALLBACK AllHwndCollector(HWND hwnd, LPARAM param) {
|
||||
@@ -94,17 +94,20 @@ index 836f7683b77b3b28f33984f27649d675ddddd5b7..84135d3cf983c88fc165a0fc012200e5
|
||||
#endif
|
||||
|
||||
} // namespace
|
||||
@@ -451,6 +451,9 @@ void NativeDesktopMediaList::Worker::RefreshNextThumbnail() {
|
||||
@@ -451,6 +451,12 @@ void NativeDesktopMediaList::Worker::RefreshNextThumbnail() {
|
||||
FROM_HERE,
|
||||
base::BindOnce(&NativeDesktopMediaList::UpdateNativeThumbnailsFinished,
|
||||
media_list_));
|
||||
+
|
||||
+ // This call is necessary to release underlying OS screen capture mechanisms.
|
||||
+ capturer_.reset();
|
||||
+ // Skip if the source list is delegated, as the source list window will be active.
|
||||
+ if (!capturer_->GetDelegatedSourceListController()) {
|
||||
+ capturer_.reset();
|
||||
+ }
|
||||
}
|
||||
|
||||
void NativeDesktopMediaList::Worker::OnCaptureResult(
|
||||
@@ -823,6 +826,11 @@ void NativeDesktopMediaList::RefreshForVizFrameSinkWindows(
|
||||
@@ -823,6 +829,11 @@ void NativeDesktopMediaList::RefreshForVizFrameSinkWindows(
|
||||
FROM_HERE, base::BindOnce(&Worker::RefreshThumbnails,
|
||||
base::Unretained(worker_.get()),
|
||||
std::move(native_ids), thumbnail_size_));
|
||||
|
||||
@@ -17,10 +17,10 @@ policy->CanCommitOriginAndUrl.
|
||||
Upstreamed at https://chromium-review.googlesource.com/c/chromium/src/+/3856266.
|
||||
|
||||
diff --git a/content/browser/renderer_host/navigation_request.cc b/content/browser/renderer_host/navigation_request.cc
|
||||
index 8dcc8499e45be5127d80ac882d10a9a2c7a9e8dd..da992c06c75a1c7c48cb628ffa8ecd7e17489d8e 100644
|
||||
index 3166af39da993beb4fc75b88bdada2821a8ce672..fd95d91a9a4efbfbbcfb117d9f2129b1b1c95011 100644
|
||||
--- a/content/browser/renderer_host/navigation_request.cc
|
||||
+++ b/content/browser/renderer_host/navigation_request.cc
|
||||
@@ -6833,10 +6833,11 @@ NavigationRequest::GetOriginForURLLoaderFactoryAfterResponseWithDebugInfo() {
|
||||
@@ -6842,10 +6842,11 @@ NavigationRequest::GetOriginForURLLoaderFactoryAfterResponseWithDebugInfo() {
|
||||
if (IsForMhtmlSubframe())
|
||||
return origin_with_debug_info;
|
||||
|
||||
|
||||
47
patches/chromium/m112_cherry_pick_libxml_cve_fix.patch
Normal file
47
patches/chromium/m112_cherry_pick_libxml_cve_fix.patch
Normal file
@@ -0,0 +1,47 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Joey Arhar <jarhar@chromium.org>
|
||||
Date: Fri, 21 Apr 2023 20:53:40 +0000
|
||||
Subject: M112: Cherry pick libxml CVE fix
|
||||
|
||||
This patch cherry-picks a fix for [CVE-2023-29469] from libxml:
|
||||
https://gitlab.gnome.org/GNOME/libxml2/-/commit/547edbf1cbdccd46b2e8ff322a456eaa5931c5df
|
||||
|
||||
I cherry-picked these by going into my libxml checkout, checking out the
|
||||
commit that libxml is at for this M112 branch, cherry-picking the CVE
|
||||
fixes, then running the roll script on all platforms.
|
||||
|
||||
Bug: 1433328
|
||||
Change-Id: Iaee58b0890f7190386cca3e430286f39ccbbdb02
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/4456592
|
||||
Commit-Queue: David Baron <dbaron@chromium.org>
|
||||
Reviewed-by: David Baron <dbaron@chromium.org>
|
||||
Commit-Queue: Joey Arhar <jarhar@chromium.org>
|
||||
Auto-Submit: Joey Arhar <jarhar@chromium.org>
|
||||
Cr-Commit-Position: refs/branch-heads/5615@{#1325}
|
||||
Cr-Branched-From: 9c6408ef696e83a9936b82bbead3d41c93c82ee4-refs/heads/main@{#1109224}
|
||||
|
||||
diff --git a/third_party/libxml/README.chromium b/third_party/libxml/README.chromium
|
||||
index 9813d7cd51b62164cd9cad86b57a0b660d22a223..182f0a73439a5e549aed0fa01b22bdca94a8ccbc 100644
|
||||
--- a/third_party/libxml/README.chromium
|
||||
+++ b/third_party/libxml/README.chromium
|
||||
@@ -25,5 +25,6 @@ Modifications:
|
||||
in chromium's copy of maldoca. See https://github.com/google/maldoca/issues/87
|
||||
- Add helper classes in the chromium/ subdirectory.
|
||||
- Delete various unused files, see chromium/roll.py
|
||||
+- Cherry picked fix for CVE-2023-29469
|
||||
|
||||
This import was generated by the chromium/roll.py script.
|
||||
diff --git a/third_party/libxml/src/dict.c b/third_party/libxml/src/dict.c
|
||||
index 5c9ca71940ceea9f4aec9f1e7dfb6c3ba6bd8c76..300df7a55638f4c6728a88c336b3c3197ab05676 100644
|
||||
--- a/third_party/libxml/src/dict.c
|
||||
+++ b/third_party/libxml/src/dict.c
|
||||
@@ -455,7 +455,8 @@ static unsigned long
|
||||
xmlDictComputeFastKey(const xmlChar *name, int namelen, int seed) {
|
||||
unsigned long value = seed;
|
||||
|
||||
- if (name == NULL) return(0);
|
||||
+ if ((name == NULL) || (namelen <= 0))
|
||||
+ return(value);
|
||||
value += *name;
|
||||
value <<= 5;
|
||||
if (namelen > 10) {
|
||||
43
patches/chromium/m112_fix_scopedobservation_uaf_in.patch
Normal file
43
patches/chromium/m112_fix_scopedobservation_uaf_in.patch
Normal file
@@ -0,0 +1,43 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Keren Zhu <kerenzhu@chromium.org>
|
||||
Date: Mon, 24 Apr 2023 15:36:21 +0000
|
||||
Subject: Fix ScopedObservation UaF in
|
||||
BubbleDialogDelegate::AnchorWidgetObserver
|
||||
|
||||
A ScopedObservation can outlive the aura::Window it observes, leading to
|
||||
a use-after-free error in ~ScopedObservation(). The problem occurs in
|
||||
BubbleDialogDelegate::AnchorWidgetObserver. This fix listens for
|
||||
OnWindowDestroying() and resets the observation to prevent the UaF.
|
||||
|
||||
(cherry picked from commit 72bd6a1018548ee63a2ec06d6c7714d3a8cdf8a8)
|
||||
|
||||
Bug: 1423360
|
||||
Change-Id: I742b4624b2664dea3fd97db7b399fcd15e45c8fe
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/4455016
|
||||
Code-Coverage: Findit <findit-for-me@appspot.gserviceaccount.com>
|
||||
Reviewed-by: Elly Fong-Jones <ellyjones@chromium.org>
|
||||
Commit-Queue: Keren Zhu <kerenzhu@chromium.org>
|
||||
Cr-Original-Commit-Position: refs/heads/main@{#1133511}
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/4466947
|
||||
Reviewed-by: Allen Bauer <kylixrd@chromium.org>
|
||||
Cr-Commit-Position: refs/branch-heads/5615@{#1353}
|
||||
Cr-Branched-From: 9c6408ef696e83a9936b82bbead3d41c93c82ee4-refs/heads/main@{#1109224}
|
||||
|
||||
diff --git a/ui/views/bubble/bubble_dialog_delegate_view.cc b/ui/views/bubble/bubble_dialog_delegate_view.cc
|
||||
index 83c8a188d455b0db143b4747ef79d8d72d7717ca..0fca4fa9786ae405cc9f9198f21a2aaae66f748d 100644
|
||||
--- a/ui/views/bubble/bubble_dialog_delegate_view.cc
|
||||
+++ b/ui/views/bubble/bubble_dialog_delegate_view.cc
|
||||
@@ -320,6 +320,13 @@ class BubbleDialogDelegate::AnchorWidgetObserver : public WidgetObserver,
|
||||
owner_->OnAnchorBoundsChanged();
|
||||
}
|
||||
}
|
||||
+
|
||||
+ // If the native window is closed by the OS, OnWidgetDestroying() won't
|
||||
+ // fire. Instead, OnWindowDestroying() will fire before aura::Window
|
||||
+ // destruction. See //docs/ui/views/widget_destruction.md.
|
||||
+ void OnWindowDestroying(aura::Window* window) override {
|
||||
+ window_observation_.Reset();
|
||||
+ }
|
||||
#endif
|
||||
|
||||
private:
|
||||
@@ -0,0 +1,38 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Maggie Chen <magchen@chromium.org>
|
||||
Date: Thu, 18 May 2023 00:20:34 +0000
|
||||
Subject: Fix a crash caused by calling TRACE_EVENT
|
||||
|
||||
Now use literal constant for TRACE_EVENT. Passing a pointer instead of
|
||||
string content to TRACE_EVENT causes a crash in ScopedTracer.
|
||||
|
||||
(cherry picked from commit 6f2e587807aff2306309025db1c15fc59290eb6f)
|
||||
|
||||
Bug: 1444195
|
||||
Change-Id: I02aa1148d61e7596e9293ffc866135e99991e42e
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/4522164
|
||||
Reviewed-by: Sunny Sachanandani <sunnyps@chromium.org>
|
||||
Commit-Queue: Maggie Chen <magchen@chromium.org>
|
||||
Cr-Original-Commit-Position: refs/heads/main@{#1144352}
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/4544885
|
||||
Bot-Commit: Rubber Stamper <rubber-stamper@appspot.gserviceaccount.com>
|
||||
Cr-Commit-Position: refs/branch-heads/5735@{#749}
|
||||
Cr-Branched-From: 2f562e4ddbaf79a3f3cb338b4d1bd4398d49eb67-refs/heads/main@{#1135570}
|
||||
|
||||
diff --git a/ui/gl/swap_chain_presenter.cc b/ui/gl/swap_chain_presenter.cc
|
||||
index 54a8dfdd931a22c5acfe3613204ea3a89b842d13..1e76a1a655d0f9de1dd218ad4025a6210ceafc57 100644
|
||||
--- a/ui/gl/swap_chain_presenter.cc
|
||||
+++ b/ui/gl/swap_chain_presenter.cc
|
||||
@@ -1698,10 +1698,8 @@ bool SwapChainPresenter::ReallocateSwapChain(
|
||||
}
|
||||
}
|
||||
if (!use_yuv_swap_chain) {
|
||||
- std::ostringstream trace_event_stream;
|
||||
- trace_event_stream << "SwapChainPresenter::ReallocateSwapChain::"
|
||||
- << DxgiFormatToString(swap_chain_format);
|
||||
- TRACE_EVENT0("gpu", trace_event_stream.str().c_str());
|
||||
+ TRACE_EVENT1("gpu", "SwapChainPresenter::ReallocateSwapChain::BGRA",
|
||||
+ "format", DxgiFormatToString(swap_chain_format));
|
||||
|
||||
desc.Format = swap_chain_format;
|
||||
desc.Flags = DXGI_SWAP_CHAIN_FLAG_FULLSCREEN_VIDEO;
|
||||
@@ -0,0 +1,99 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Eugene Zemtsov <eugene@chromium.org>
|
||||
Date: Wed, 21 Jun 2023 17:57:52 +0000
|
||||
Subject: webcodecs: Fix crash when changing temporal layer count in AV1
|
||||
encoder
|
||||
|
||||
(cherry picked from commit f312efac1b90117729e8961b58c643fc0eae1fbd)
|
||||
|
||||
Bug: 1447568
|
||||
Change-Id: I4ecb02ed956707571573a65ade17fdffe676b502
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/4554300
|
||||
Auto-Submit: Eugene Zemtsov <eugene@chromium.org>
|
||||
Commit-Queue: Dale Curtis <dalecurtis@chromium.org>
|
||||
Reviewed-by: Dale Curtis <dalecurtis@chromium.org>
|
||||
Cr-Original-Commit-Position: refs/heads/main@{#1148041}
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/4610718
|
||||
Cr-Commit-Position: refs/branch-heads/5735@{#1360}
|
||||
Cr-Branched-From: 2f562e4ddbaf79a3f3cb338b4d1bd4398d49eb67-refs/heads/main@{#1135570}
|
||||
|
||||
diff --git a/media/video/av1_video_encoder.cc b/media/video/av1_video_encoder.cc
|
||||
index b5a075a8986cea0a07ce588330c4c0fa6e9ef593..73b072f05522c88248fc228f91fd61f18e23c352 100644
|
||||
--- a/media/video/av1_video_encoder.cc
|
||||
+++ b/media/video/av1_video_encoder.cc
|
||||
@@ -118,6 +118,7 @@ EncoderStatus SetUpAomConfig(const VideoEncoder::Options& opts,
|
||||
svc_params = {};
|
||||
svc_params.framerate_factor[0] = 1;
|
||||
svc_params.number_spatial_layers = 1;
|
||||
+ svc_params.number_temporal_layers = 1;
|
||||
if (opts.scalability_mode.has_value()) {
|
||||
switch (opts.scalability_mode.value()) {
|
||||
case SVCScalabilityMode::kL1T2:
|
||||
diff --git a/media/video/software_video_encoder_test.cc b/media/video/software_video_encoder_test.cc
|
||||
index 19d16a443e616303de0b7264eeaabaa9520b4c97..9fd17dbc726f949eccd3f4ed8a9fee4414623c0f 100644
|
||||
--- a/media/video/software_video_encoder_test.cc
|
||||
+++ b/media/video/software_video_encoder_test.cc
|
||||
@@ -610,6 +610,63 @@ TEST_P(SVCVideoEncoderTest, EncodeClipTemporalSvc) {
|
||||
}
|
||||
}
|
||||
|
||||
+TEST_P(SVCVideoEncoderTest, ChangeLayers) {
|
||||
+ VideoEncoder::Options options;
|
||||
+ options.frame_size = gfx::Size(640, 480);
|
||||
+ options.bitrate = Bitrate::ConstantBitrate(1000000u); // 1Mbps
|
||||
+ options.framerate = 25;
|
||||
+ options.scalability_mode = GetParam().scalability_mode;
|
||||
+ std::vector<scoped_refptr<VideoFrame>> frames_to_encode;
|
||||
+
|
||||
+ std::vector<VideoEncoderOutput> chunks;
|
||||
+ size_t total_frames_count = 80;
|
||||
+
|
||||
+ // Encoder all frames with 3 temporal layers and put all outputs in |chunks|
|
||||
+ auto frame_duration = base::Seconds(1.0 / options.framerate.value());
|
||||
+
|
||||
+ VideoEncoder::OutputCB encoder_output_cb = base::BindLambdaForTesting(
|
||||
+ [&](VideoEncoderOutput output,
|
||||
+ absl::optional<VideoEncoder::CodecDescription> desc) {
|
||||
+ chunks.push_back(std::move(output));
|
||||
+ });
|
||||
+
|
||||
+ encoder_->Initialize(profile_, options, /*info_cb=*/base::DoNothing(),
|
||||
+ std::move(encoder_output_cb),
|
||||
+ ValidatingStatusCB(/* quit_run_loop_on_call */ true));
|
||||
+ RunUntilQuit();
|
||||
+
|
||||
+ uint32_t color = 0x964050;
|
||||
+ for (auto frame_index = 0u; frame_index < total_frames_count; frame_index++) {
|
||||
+ auto timestamp = frame_index * frame_duration;
|
||||
+
|
||||
+ const bool reconfigure = (frame_index == total_frames_count / 2);
|
||||
+ if (reconfigure) {
|
||||
+ encoder_->Flush(ValidatingStatusCB(/* quit_run_loop_on_call */ true));
|
||||
+ RunUntilQuit();
|
||||
+
|
||||
+ // Ask encoder to change SVC mode, empty output callback
|
||||
+ // means the encoder should keep the old one.
|
||||
+ options.scalability_mode = SVCScalabilityMode::kL1T1;
|
||||
+ encoder_->ChangeOptions(
|
||||
+ options, VideoEncoder::OutputCB(),
|
||||
+ ValidatingStatusCB(/* quit_run_loop_on_call */ true));
|
||||
+ RunUntilQuit();
|
||||
+ }
|
||||
+
|
||||
+ auto frame =
|
||||
+ CreateFrame(options.frame_size, pixel_format_, timestamp, color);
|
||||
+ color = (color << 1) + frame_index;
|
||||
+ frames_to_encode.push_back(frame);
|
||||
+ encoder_->Encode(frame, VideoEncoder::EncodeOptions(false),
|
||||
+ ValidatingStatusCB(/* quit_run_loop_on_call */ true));
|
||||
+ RunUntilQuit();
|
||||
+ }
|
||||
+
|
||||
+ encoder_->Flush(ValidatingStatusCB(/* quit_run_loop_on_call */ true));
|
||||
+ RunUntilQuit();
|
||||
+ EXPECT_EQ(chunks.size(), total_frames_count);
|
||||
+}
|
||||
+
|
||||
TEST_P(H264VideoEncoderTest, ReconfigureWithResize) {
|
||||
VideoEncoder::Options options;
|
||||
gfx::Size size1(320, 200), size2(400, 240);
|
||||
@@ -0,0 +1,41 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Kenichi Ishibashi <bashi@chromium.org>
|
||||
Date: Sat, 8 Apr 2023 04:16:50 +0000
|
||||
Subject: Check SpdyProxyClientSocket is alive after write callback
|
||||
|
||||
To ensure that we don't use any member field.
|
||||
|
||||
(cherry picked from commit b71541b22ca19d5c3a7c01fedffe521b26577b72)
|
||||
|
||||
Bug: 1428820
|
||||
Change-Id: Icf6677c652a47dc2fd2d01675e94cda031a015f2
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/4394863
|
||||
Reviewed-by: Adam Rice <ricea@chromium.org>
|
||||
Commit-Queue: Kenichi Ishibashi <bashi@chromium.org>
|
||||
Cr-Original-Commit-Position: refs/heads/main@{#1125634}
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/4410322
|
||||
Commit-Queue: Rubber Stamper <rubber-stamper@appspot.gserviceaccount.com>
|
||||
Auto-Submit: Kenichi Ishibashi <bashi@chromium.org>
|
||||
Bot-Commit: Rubber Stamper <rubber-stamper@appspot.gserviceaccount.com>
|
||||
Cr-Commit-Position: refs/branch-heads/5615@{#1172}
|
||||
Cr-Branched-From: 9c6408ef696e83a9936b82bbead3d41c93c82ee4-refs/heads/main@{#1109224}
|
||||
|
||||
diff --git a/net/spdy/spdy_proxy_client_socket.cc b/net/spdy/spdy_proxy_client_socket.cc
|
||||
index 5af712b05af47bd207e9ef3fb9fe33342d152be0..73ca8d0c2958e532ac9810f5de40405d6e91cdeb 100644
|
||||
--- a/net/spdy/spdy_proxy_client_socket.cc
|
||||
+++ b/net/spdy/spdy_proxy_client_socket.cc
|
||||
@@ -278,7 +278,14 @@ int SpdyProxyClientSocket::GetLocalAddress(IPEndPoint* address) const {
|
||||
|
||||
void SpdyProxyClientSocket::RunWriteCallback(int result) {
|
||||
CHECK(write_callback_);
|
||||
+
|
||||
+ base::WeakPtr<SpdyProxyClientSocket> weak_ptr = weak_factory_.GetWeakPtr();
|
||||
std::move(write_callback_).Run(result);
|
||||
+ if (!weak_ptr) {
|
||||
+ // `this` was already destroyed while running `write_callback_`. Must
|
||||
+ // return immediately without touching any field member.
|
||||
+ return;
|
||||
+ }
|
||||
|
||||
if (end_stream_state_ == EndStreamState::kEndStreamReceived) {
|
||||
base::SingleThreadTaskRunner::GetCurrentDefault()->PostTask(
|
||||
@@ -0,0 +1,94 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Kenichi Ishibashi <bashi@chromium.org>
|
||||
Date: Sat, 8 Apr 2023 01:56:25 +0000
|
||||
Subject: Remove the second WeakPtrFactory from SpdyProxyClientSocket
|
||||
|
||||
It was introduced [1] to work around an old issue that wouldn't happen
|
||||
any more since we store a write callback in the class. Instead of having
|
||||
the second WeakPtrFactory and moving the callback, we can just keep it
|
||||
until RunWriteCallback() is called.
|
||||
|
||||
This is a speculative fix for the linked bug.
|
||||
|
||||
[1] https://codereview.chromium.org/338583003/
|
||||
|
||||
(cherry picked from commit 01b25615896b911e21103dd381fafc1f85886d91)
|
||||
|
||||
Bug: 1428820
|
||||
Change-Id: I0b5af2675b68188e208c2ecd42293251b2722b28
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/4393905
|
||||
Reviewed-by: Adam Rice <ricea@chromium.org>
|
||||
Commit-Queue: Kenichi Ishibashi <bashi@chromium.org>
|
||||
Cr-Original-Commit-Position: refs/heads/main@{#1125216}
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/4410320
|
||||
Auto-Submit: Kenichi Ishibashi <bashi@chromium.org>
|
||||
Bot-Commit: Rubber Stamper <rubber-stamper@appspot.gserviceaccount.com>
|
||||
Commit-Queue: Rubber Stamper <rubber-stamper@appspot.gserviceaccount.com>
|
||||
Cr-Commit-Position: refs/branch-heads/5615@{#1171}
|
||||
Cr-Branched-From: 9c6408ef696e83a9936b82bbead3d41c93c82ee4-refs/heads/main@{#1109224}
|
||||
|
||||
diff --git a/net/spdy/spdy_proxy_client_socket.cc b/net/spdy/spdy_proxy_client_socket.cc
|
||||
index 9b5b47ac05de773024e46f1cce534ddabed5ebd3..5af712b05af47bd207e9ef3fb9fe33342d152be0 100644
|
||||
--- a/net/spdy/spdy_proxy_client_socket.cc
|
||||
+++ b/net/spdy/spdy_proxy_client_socket.cc
|
||||
@@ -122,7 +122,6 @@ void SpdyProxyClientSocket::Disconnect() {
|
||||
|
||||
write_buffer_len_ = 0;
|
||||
write_callback_.Reset();
|
||||
- write_callback_weak_factory_.InvalidateWeakPtrs();
|
||||
|
||||
next_state_ = STATE_DISCONNECTED;
|
||||
|
||||
@@ -277,9 +276,9 @@ int SpdyProxyClientSocket::GetLocalAddress(IPEndPoint* address) const {
|
||||
return spdy_stream_->GetLocalAddress(address);
|
||||
}
|
||||
|
||||
-void SpdyProxyClientSocket::RunWriteCallback(CompletionOnceCallback callback,
|
||||
- int result) const {
|
||||
- std::move(callback).Run(result);
|
||||
+void SpdyProxyClientSocket::RunWriteCallback(int result) {
|
||||
+ CHECK(write_callback_);
|
||||
+ std::move(write_callback_).Run(result);
|
||||
|
||||
if (end_stream_state_ == EndStreamState::kEndStreamReceived) {
|
||||
base::SingleThreadTaskRunner::GetCurrentDefault()->PostTask(
|
||||
@@ -516,8 +515,7 @@ void SpdyProxyClientSocket::OnDataSent() {
|
||||
// stream's write callback chain to unwind (see crbug.com/355511).
|
||||
base::SingleThreadTaskRunner::GetCurrentDefault()->PostTask(
|
||||
FROM_HERE, base::BindOnce(&SpdyProxyClientSocket::RunWriteCallback,
|
||||
- write_callback_weak_factory_.GetWeakPtr(),
|
||||
- std::move(write_callback_), rv));
|
||||
+ weak_factory_.GetWeakPtr(), rv));
|
||||
}
|
||||
|
||||
void SpdyProxyClientSocket::OnTrailers(const spdy::Http2HeaderBlock& trailers) {
|
||||
diff --git a/net/spdy/spdy_proxy_client_socket.h b/net/spdy/spdy_proxy_client_socket.h
|
||||
index 7576ebed45d4983592528f90856c170ece0c04c6..87a731fe42159770098624e3073012061ed0b360 100644
|
||||
--- a/net/spdy/spdy_proxy_client_socket.h
|
||||
+++ b/net/spdy/spdy_proxy_client_socket.h
|
||||
@@ -121,9 +121,9 @@ class NET_EXPORT_PRIVATE SpdyProxyClientSocket : public ProxyClientSocket,
|
||||
STATE_CLOSED
|
||||
};
|
||||
|
||||
- // Calls |callback.Run(result)|. Used to run a callback posted to the
|
||||
+ // Calls `write_callback_(result)`. Used to run a callback posted to the
|
||||
// message loop.
|
||||
- void RunWriteCallback(CompletionOnceCallback callback, int result) const;
|
||||
+ void RunWriteCallback(int result);
|
||||
|
||||
void OnIOComplete(int result);
|
||||
|
||||
@@ -195,13 +195,7 @@ class NET_EXPORT_PRIVATE SpdyProxyClientSocket : public ProxyClientSocket,
|
||||
};
|
||||
EndStreamState end_stream_state_ = EndStreamState::kNone;
|
||||
|
||||
- // The default weak pointer factory.
|
||||
base::WeakPtrFactory<SpdyProxyClientSocket> weak_factory_{this};
|
||||
-
|
||||
- // Only used for posting write callbacks. Weak pointers created by this
|
||||
- // factory are invalidated in Disconnect().
|
||||
- base::WeakPtrFactory<SpdyProxyClientSocket> write_callback_weak_factory_{
|
||||
- this};
|
||||
};
|
||||
|
||||
} // namespace net
|
||||
51
patches/chromium/mojoipcz_copy_incoming_messages_early.patch
Normal file
51
patches/chromium/mojoipcz_copy_incoming_messages_early.patch
Normal file
@@ -0,0 +1,51 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Ken Rockot <rockot@google.com>
|
||||
Date: Mon, 3 Apr 2023 19:43:13 +0000
|
||||
Subject: MojoIpcz: Copy incoming messages early
|
||||
|
||||
Fixed: 1429720
|
||||
Change-Id: Id6cb7269d3a3e9118cc6ff1579b56e18bf911c07
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/4390758
|
||||
Commit-Queue: Ken Rockot <rockot@google.com>
|
||||
Reviewed-by: Daniel Cheng <dcheng@chromium.org>
|
||||
Cr-Commit-Position: refs/heads/main@{#1125510}
|
||||
|
||||
diff --git a/mojo/core/ipcz_driver/mojo_message.cc b/mojo/core/ipcz_driver/mojo_message.cc
|
||||
index 6194c0c2da8292b8229972eadf9fd6fa56ef0c86..b8372a6281ddcaf0990f55856a9e815fb9d78195 100644
|
||||
--- a/mojo/core/ipcz_driver/mojo_message.cc
|
||||
+++ b/mojo/core/ipcz_driver/mojo_message.cc
|
||||
@@ -112,23 +112,20 @@ void MojoMessage::SetParcel(ScopedIpczHandle parcel) {
|
||||
|
||||
// We always pass a parcel object in, so Begin/EndGet() must always succeed.
|
||||
DCHECK_EQ(result, IPCZ_RESULT_OK);
|
||||
+ if (num_bytes > 0) {
|
||||
+ data_storage_.reset(
|
||||
+ static_cast<uint8_t*>(base::AllocNonScannable(num_bytes)));
|
||||
+ memcpy(data_storage_.get(), data, num_bytes);
|
||||
+ } else {
|
||||
+ data_storage_.reset();
|
||||
+ }
|
||||
+ data_ = {data_storage_.get(), num_bytes};
|
||||
+ data_storage_size_ = num_bytes;
|
||||
|
||||
- // Grab only the handles.
|
||||
handles_.resize(num_handles);
|
||||
- result = GetIpczAPI().EndGet(parcel_.get(), 0, num_handles, IPCZ_NO_FLAGS,
|
||||
- nullptr, handles_.data());
|
||||
- DCHECK_EQ(result, IPCZ_RESULT_OK);
|
||||
-
|
||||
- // Now start a new two-phase get, which we'll leave active indefinitely for
|
||||
- // `data_` to reference.
|
||||
- result = GetIpczAPI().BeginGet(parcel_.get(), IPCZ_NO_FLAGS, nullptr, &data,
|
||||
- &num_bytes, &num_handles);
|
||||
+ result = GetIpczAPI().EndGet(parcel_.get(), num_bytes, num_handles,
|
||||
+ IPCZ_NO_FLAGS, nullptr, handles_.data());
|
||||
DCHECK_EQ(result, IPCZ_RESULT_OK);
|
||||
-
|
||||
- DCHECK_EQ(0u, num_handles);
|
||||
- data_ = base::make_span(static_cast<uint8_t*>(const_cast<void*>(data)),
|
||||
- num_bytes);
|
||||
-
|
||||
if (!FixUpDataPipeHandles(handles_)) {
|
||||
// The handle list was malformed. Although this is a validation error, it
|
||||
// is not safe to trigger MojoNotifyBadMessage from within MojoReadMessage,
|
||||
@@ -8,10 +8,10 @@ needed in chromium but our autofill implementation uses them. This patch can be
|
||||
our autofill implementation to work like Chromium's.
|
||||
|
||||
diff --git a/ui/color/color_id.h b/ui/color/color_id.h
|
||||
index cabd236eaa3f24b8564d471587543eb5be9ec6bf..53812c4fd4103f60896b5c9b1c9ae811dba75fe2 100644
|
||||
index f0f097e58303cbfd86acc38c65be30706c59b595..ab4fd53fa85ba85256f629fb1fe9417b3e225337 100644
|
||||
--- a/ui/color/color_id.h
|
||||
+++ b/ui/color/color_id.h
|
||||
@@ -260,6 +260,10 @@
|
||||
@@ -261,6 +261,10 @@
|
||||
E_CPONLY(kColorScrollbarThumbInactive) \
|
||||
E_CPONLY(kColorScrollbarThumbPressed) \
|
||||
E_CPONLY(kColorScrollbarTrack) \
|
||||
@@ -22,7 +22,7 @@ index cabd236eaa3f24b8564d471587543eb5be9ec6bf..53812c4fd4103f60896b5c9b1c9ae811
|
||||
E_CPONLY(kColorSeparator) \
|
||||
E_CPONLY(kColorShadowBase) \
|
||||
E_CPONLY(kColorShadowValueAmbientShadowElevationSixteen) \
|
||||
@@ -314,6 +318,7 @@
|
||||
@@ -315,6 +319,7 @@
|
||||
E_CPONLY(kColorTreeNodeForeground) \
|
||||
E_CPONLY(kColorTreeNodeForegroundSelectedFocused) \
|
||||
E_CPONLY(kColorTreeNodeForegroundSelectedUnfocused) \
|
||||
@@ -31,10 +31,10 @@ index cabd236eaa3f24b8564d471587543eb5be9ec6bf..53812c4fd4103f60896b5c9b1c9ae811
|
||||
|
||||
#if BUILDFLAG(IS_CHROMEOS)
|
||||
diff --git a/ui/color/ui_color_mixer.cc b/ui/color/ui_color_mixer.cc
|
||||
index 80394f269c91cb1064f9f960e3ecca41704c8e03..0885bf11672d47544d067deb74dbe786aa227127 100644
|
||||
index d23901f25760a33afd00302f6f88eafa87321b20..8b2e59f0a046a194302269555aaac0965fd2abc5 100644
|
||||
--- a/ui/color/ui_color_mixer.cc
|
||||
+++ b/ui/color/ui_color_mixer.cc
|
||||
@@ -192,6 +192,17 @@ void AddUiColorMixer(ColorProvider* provider,
|
||||
@@ -201,6 +201,17 @@ void AddUiColorMixer(ColorProvider* provider,
|
||||
: SkColorSetA(SK_ColorBLACK, 0x80)};
|
||||
mixer[kColorScrollbarTrack] = {dark_mode ? SkColorSetRGB(0x42, 0x42, 0x42)
|
||||
: SkColorSetRGB(0xF1, 0xF1, 0xF1)};
|
||||
@@ -52,7 +52,7 @@ index 80394f269c91cb1064f9f960e3ecca41704c8e03..0885bf11672d47544d067deb74dbe786
|
||||
mixer[kColorSeparator] = {kColorMidground};
|
||||
mixer[kColorShadowBase] = {dark_mode ? SK_ColorBLACK : gfx::kGoogleGrey800};
|
||||
mixer[kColorShadowValueAmbientShadowElevationThree] =
|
||||
@@ -273,6 +284,7 @@ void AddUiColorMixer(ColorProvider* provider,
|
||||
@@ -291,6 +302,7 @@ void AddUiColorMixer(ColorProvider* provider,
|
||||
mixer[kColorTreeNodeForegroundSelectedFocused] = {kColorTreeNodeForeground};
|
||||
mixer[kColorTreeNodeForegroundSelectedUnfocused] = {
|
||||
kColorTreeNodeForegroundSelectedFocused};
|
||||
|
||||
@@ -0,0 +1,240 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: David Sanders <dsanders11@ucsbalum.com>
|
||||
Date: Sun, 2 Apr 2023 05:52:30 -0700
|
||||
Subject: Revert "[X11] Keep WindowCache alive for a time interval"
|
||||
|
||||
This reverts commit bbc20a9c1b91ac6d6035408748091369cc96d4d7.
|
||||
|
||||
While intended as a performance improvement, the commit breaks
|
||||
Views menus on X11 after certain window events such as resizing,
|
||||
or maximizing and unmaximizing.
|
||||
|
||||
The patch can be removed once the upstream issue is fixed. That
|
||||
was reported in https://crbug.com/1429935.
|
||||
|
||||
diff --git a/ui/base/x/x11_whole_screen_move_loop.cc b/ui/base/x/x11_whole_screen_move_loop.cc
|
||||
index 14b7a26e474f1a11937c3923d6ef715568c30f20..a0baf8a03c8f614af37954fecd543375fc56e2b1 100644
|
||||
--- a/ui/base/x/x11_whole_screen_move_loop.cc
|
||||
+++ b/ui/base/x/x11_whole_screen_move_loop.cc
|
||||
@@ -26,6 +26,7 @@
|
||||
#include "ui/events/x/x11_event_translation.h"
|
||||
#include "ui/gfx/x/connection.h"
|
||||
#include "ui/gfx/x/keysyms/keysyms.h"
|
||||
+#include "ui/gfx/x/window_cache.h"
|
||||
#include "ui/gfx/x/x11_window_event_manager.h"
|
||||
#include "ui/gfx/x/xproto.h"
|
||||
|
||||
@@ -151,6 +152,10 @@ bool X11WholeScreenMoveLoop::RunMoveLoop(
|
||||
auto* connection = x11::Connection::Get();
|
||||
CreateDragInputWindow(connection);
|
||||
|
||||
+ // Keep a window cache alive for the duration of the drag so that the drop
|
||||
+ // target under the drag window can be quickly determined.
|
||||
+ x11::WindowCache cache(connection, connection->default_root(), true);
|
||||
+
|
||||
// Only grab mouse capture of |grab_input_window_| if |can_grab_pointer| is
|
||||
// true aka the source that initiated the move loop doesn't have explicit
|
||||
// grab.
|
||||
diff --git a/ui/gfx/x/window_cache.cc b/ui/gfx/x/window_cache.cc
|
||||
index 048a9068a8671ec40acc1f91fdc0ddce0b3645c7..e2ababce59750952dba1dc0976db47338ecfef87 100644
|
||||
--- a/ui/gfx/x/window_cache.cc
|
||||
+++ b/ui/gfx/x/window_cache.cc
|
||||
@@ -11,8 +11,6 @@
|
||||
#include "base/notreached.h"
|
||||
#include "base/ranges/algorithm.h"
|
||||
#include "base/run_loop.h"
|
||||
-#include "base/task/single_thread_task_runner.h"
|
||||
-#include "base/time/time.h"
|
||||
#include "ui/gfx/geometry/insets.h"
|
||||
#include "ui/gfx/geometry/rect.h"
|
||||
#include "ui/gfx/geometry/vector2d.h"
|
||||
@@ -24,23 +22,19 @@
|
||||
|
||||
namespace x11 {
|
||||
|
||||
-const base::TimeDelta kDestroyTimerInterval = base::Seconds(3);
|
||||
-
|
||||
Window GetWindowAtPoint(const gfx::Point& point_px,
|
||||
const base::flat_set<Window>* ignore) {
|
||||
auto* connection = Connection::Get();
|
||||
Window root = connection->default_root();
|
||||
|
||||
- if (!WindowCache::instance()) {
|
||||
- auto instance =
|
||||
- std::make_unique<WindowCache>(connection, connection->default_root());
|
||||
- auto* cache = instance.get();
|
||||
- cache->BeginDestroyTimer(std::move(instance));
|
||||
+ if (auto* instance = WindowCache::instance()) {
|
||||
+ instance->WaitUntilReady();
|
||||
+ return instance->GetWindowAtPoint(point_px, root, ignore);
|
||||
}
|
||||
|
||||
- auto* instance = WindowCache::instance();
|
||||
- instance->WaitUntilReady();
|
||||
- return instance->GetWindowAtPoint(point_px, root, ignore);
|
||||
+ WindowCache cache(connection, connection->default_root(), false);
|
||||
+ cache.WaitUntilReady();
|
||||
+ return cache.GetWindowAtPoint(point_px, root, ignore);
|
||||
}
|
||||
|
||||
ScopedShapeEventSelector::ScopedShapeEventSelector(Connection* connection,
|
||||
@@ -62,21 +56,24 @@ WindowCache::WindowInfo::~WindowInfo() = default;
|
||||
// static
|
||||
WindowCache* WindowCache::instance_ = nullptr;
|
||||
|
||||
-WindowCache::WindowCache(Connection* connection, Window root)
|
||||
+WindowCache::WindowCache(Connection* connection, Window root, bool track_events)
|
||||
: connection_(connection),
|
||||
root_(root),
|
||||
+ track_events_(track_events),
|
||||
gtk_frame_extents_(GetAtom("_GTK_FRAME_EXTENTS")) {
|
||||
DCHECK(!instance_) << "Only one WindowCache should be active at a time";
|
||||
instance_ = this;
|
||||
|
||||
connection_->AddEventObserver(this);
|
||||
|
||||
- // We select for SubstructureNotify events on all windows (to receive
|
||||
- // CreateNotify events), which will cause events to be sent for all child
|
||||
- // windows. This means we need to additionally select for StructureNotify
|
||||
- // changes for the root window.
|
||||
- root_events_ =
|
||||
- std::make_unique<XScopedEventSelector>(root_, EventMask::StructureNotify);
|
||||
+ if (track_events_) {
|
||||
+ // We select for SubstructureNotify events on all windows (to receive
|
||||
+ // CreateNotify events), which will cause events to be sent for all child
|
||||
+ // windows. This means we need to additionally select for StructureNotify
|
||||
+ // changes for the root window.
|
||||
+ root_events_ = std::make_unique<XScopedEventSelector>(
|
||||
+ root_, EventMask::StructureNotify);
|
||||
+ }
|
||||
AddWindow(root_, Window::None);
|
||||
}
|
||||
|
||||
@@ -106,16 +103,6 @@ void WindowCache::WaitUntilReady() {
|
||||
last_processed_event_ = events[event - 1].sequence();
|
||||
}
|
||||
|
||||
-void WindowCache::BeginDestroyTimer(std::unique_ptr<WindowCache> self) {
|
||||
- DCHECK_EQ(this, self.get());
|
||||
- delete_when_destroy_timer_fires_ = false;
|
||||
- base::SingleThreadTaskRunner::GetCurrentDefault()->PostDelayedTask(
|
||||
- FROM_HERE,
|
||||
- base::BindOnce(&WindowCache::OnDestroyTimerExpired,
|
||||
- base::Unretained(this), std::move(self)),
|
||||
- kDestroyTimerInterval);
|
||||
-}
|
||||
-
|
||||
void WindowCache::SyncForTest() {
|
||||
do {
|
||||
// Perform a blocking sync to prevent spinning while waiting for replies.
|
||||
@@ -127,7 +114,6 @@ void WindowCache::SyncForTest() {
|
||||
Window WindowCache::GetWindowAtPoint(gfx::Point point_px,
|
||||
Window window,
|
||||
const base::flat_set<Window>* ignore) {
|
||||
- delete_when_destroy_timer_fires_ = true;
|
||||
if (ignore && ignore->contains(window))
|
||||
return Window::None;
|
||||
auto* info = GetInfo(window);
|
||||
@@ -265,10 +251,12 @@ void WindowCache::AddWindow(Window window, Window parent) {
|
||||
return;
|
||||
WindowInfo& info = windows_[window];
|
||||
info.parent = parent;
|
||||
- // Events must be selected before getting the initial window info to
|
||||
- // prevent race conditions.
|
||||
- info.events = std::make_unique<XScopedEventSelector>(
|
||||
- window, EventMask::SubstructureNotify | EventMask::PropertyChange);
|
||||
+ if (track_events_) {
|
||||
+ // Events must be selected before getting the initial window info to
|
||||
+ // prevent race conditions.
|
||||
+ info.events = std::make_unique<XScopedEventSelector>(
|
||||
+ window, EventMask::SubstructureNotify | EventMask::PropertyChange);
|
||||
+ }
|
||||
|
||||
AddRequest(connection_->GetWindowAttributes(window),
|
||||
&WindowCache::OnGetWindowAttributesResponse, window);
|
||||
@@ -282,8 +270,10 @@ void WindowCache::AddWindow(Window window, Window parent) {
|
||||
|
||||
auto& shape = connection_->shape();
|
||||
if (shape.present()) {
|
||||
- info.shape_events =
|
||||
- std::make_unique<ScopedShapeEventSelector>(connection_, window);
|
||||
+ if (track_events_) {
|
||||
+ info.shape_events =
|
||||
+ std::make_unique<ScopedShapeEventSelector>(connection_, window);
|
||||
+ }
|
||||
|
||||
for (auto kind : {Shape::Sk::Bounding, Shape::Sk::Input}) {
|
||||
AddRequest(shape.GetRectangles(window, kind),
|
||||
@@ -391,11 +381,4 @@ void WindowCache::OnGetRectanglesResponse(
|
||||
}
|
||||
}
|
||||
|
||||
-void WindowCache::OnDestroyTimerExpired(std::unique_ptr<WindowCache> self) {
|
||||
- if (!delete_when_destroy_timer_fires_)
|
||||
- return; // destroy `this`
|
||||
-
|
||||
- BeginDestroyTimer(std::move(self));
|
||||
-}
|
||||
-
|
||||
} // namespace x11
|
||||
diff --git a/ui/gfx/x/window_cache.h b/ui/gfx/x/window_cache.h
|
||||
index f241d6c23855fad478813ff3029fa6a17d084d34..ebc05d311ed3719be98180086baae8230ec9c58e 100644
|
||||
--- a/ui/gfx/x/window_cache.h
|
||||
+++ b/ui/gfx/x/window_cache.h
|
||||
@@ -78,7 +78,7 @@ class COMPONENT_EXPORT(X11) WindowCache : public EventObserver {
|
||||
// If `track_events` is true, the WindowCache will keep the cache state synced
|
||||
// with the server's state over time. It may be set to false if the cache is
|
||||
// short-lived, if only a single GetWindowAtPoint call is made.
|
||||
- WindowCache(Connection* connection, Window root);
|
||||
+ WindowCache(Connection* connection, Window root, bool track_events);
|
||||
WindowCache(const WindowCache&) = delete;
|
||||
WindowCache& operator=(const WindowCache&) = delete;
|
||||
~WindowCache() override;
|
||||
@@ -92,10 +92,6 @@ class COMPONENT_EXPORT(X11) WindowCache : public EventObserver {
|
||||
// Blocks until all outstanding requests are processed.
|
||||
void WaitUntilReady();
|
||||
|
||||
- // Destroys |self| if no calls to GetWindowAtPoint() are made within
|
||||
- // a time window.
|
||||
- void BeginDestroyTimer(std::unique_ptr<WindowCache> self);
|
||||
-
|
||||
void SyncForTest();
|
||||
|
||||
const std::unordered_map<Window, WindowInfo>& windows() const {
|
||||
@@ -147,12 +143,11 @@ class COMPONENT_EXPORT(X11) WindowCache : public EventObserver {
|
||||
Shape::Sk kind,
|
||||
Shape::GetRectanglesResponse response);
|
||||
|
||||
- void OnDestroyTimerExpired(std::unique_ptr<WindowCache> self);
|
||||
-
|
||||
static WindowCache* instance_;
|
||||
|
||||
const raw_ptr<Connection> connection_;
|
||||
const Window root_;
|
||||
+ const bool track_events_;
|
||||
const Atom gtk_frame_extents_;
|
||||
std::unique_ptr<XScopedEventSelector> root_events_;
|
||||
|
||||
@@ -164,9 +159,6 @@ class COMPONENT_EXPORT(X11) WindowCache : public EventObserver {
|
||||
// processed in order.
|
||||
absl::optional<uint32_t> last_processed_event_;
|
||||
|
||||
- // True iff GetWindowAtPoint() was called since the last timer interval.
|
||||
- bool delete_when_destroy_timer_fires_ = false;
|
||||
-
|
||||
// Although only one instance of WindowCache may be created at a time, the
|
||||
// instance will be created and destroyed as needed, so WeakPtrs are still
|
||||
// necessary.
|
||||
diff --git a/ui/gfx/x/window_cache_unittest.cc b/ui/gfx/x/window_cache_unittest.cc
|
||||
index 2199ddac2577a33ff7a42f3d3752613cef00dd32..af0a2d3737c132b596096514b5ca4f572d6c9d64 100644
|
||||
--- a/ui/gfx/x/window_cache_unittest.cc
|
||||
+++ b/ui/gfx/x/window_cache_unittest.cc
|
||||
@@ -21,7 +21,7 @@ class WindowCacheTest : public testing::Test {
|
||||
protected:
|
||||
void ResetCache() {
|
||||
cache_.reset();
|
||||
- cache_ = std::make_unique<WindowCache>(connection_, root_);
|
||||
+ cache_ = std::make_unique<WindowCache>(connection_, root_, true);
|
||||
cache_->SyncForTest();
|
||||
}
|
||||
|
||||
@@ -21,5 +21,13 @@
|
||||
|
||||
"src/electron/patches/Mantle": "src/third_party/squirrel.mac/vendor/Mantle",
|
||||
|
||||
"src/electron/patches/ReactiveObjC": "src/third_party/squirrel.mac/vendor/ReactiveObjC"
|
||||
"src/electron/patches/ReactiveObjC": "src/third_party/squirrel.mac/vendor/ReactiveObjC",
|
||||
|
||||
"src/electron/patches/webrtc": "src/third_party/webrtc",
|
||||
|
||||
"src/electron/patches/skia": "src/third_party/skia",
|
||||
|
||||
"src/electron/patches/dawn": "src/third_party/dawn",
|
||||
|
||||
"src/electron/patches/pdfium": "src/third_party/pdfium"
|
||||
}
|
||||
|
||||
1
patches/dawn/.patches
Normal file
1
patches/dawn/.patches
Normal file
@@ -0,0 +1 @@
|
||||
change_d3d12_descriptor_allocator_to_invalidate_submitted_descriptors.patch
|
||||
@@ -0,0 +1,42 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Brandon Jones <brandon1.jones@intel.com>
|
||||
Date: Fri, 5 May 2023 18:02:42 +0000
|
||||
Subject: Change D3D12 Descriptor Allocator To Invalidate Submitted Descriptors
|
||||
|
||||
Changes D3D12 descriptor allocator to invalidate existing descriptors
|
||||
after the descriptor heap was submitted for use. This fixes a
|
||||
synchonization issue where stale descriptors were seen as valid because
|
||||
command list execution ran long.
|
||||
|
||||
Bug: dawn:1701
|
||||
Bug: chromium:1442263
|
||||
No-Try: true
|
||||
Change-Id: Ibfd450b3be6cf91d66e8dce4ffd19ecf1a37f7f5
|
||||
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/129920
|
||||
Kokoro: Kokoro <noreply+kokoro@google.com>
|
||||
Reviewed-by: Corentin Wallez <cwallez@chromium.org>
|
||||
Commit-Queue: Brandon1 Jones <brandon1.jones@intel.com>
|
||||
(cherry picked from commit df6cb236493da101dad79fe50d4e6df0d5d1e915)
|
||||
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/131508
|
||||
Kokoro: Austin Eng <enga@chromium.org>
|
||||
Reviewed-by: Austin Eng <enga@chromium.org>
|
||||
|
||||
diff --git a/src/dawn/native/d3d12/ShaderVisibleDescriptorAllocatorD3D12.cpp b/src/dawn/native/d3d12/ShaderVisibleDescriptorAllocatorD3D12.cpp
|
||||
index fe99a63ac9d2d082c2c23eb7940a733a9d13846a..aedb28ad58a0a972879f07a6037499f901fcf04a 100644
|
||||
--- a/src/dawn/native/d3d12/ShaderVisibleDescriptorAllocatorD3D12.cpp
|
||||
+++ b/src/dawn/native/d3d12/ShaderVisibleDescriptorAllocatorD3D12.cpp
|
||||
@@ -237,9 +237,11 @@ bool ShaderVisibleDescriptorAllocator::IsLastShaderVisibleHeapInLRUForTesting()
|
||||
|
||||
bool ShaderVisibleDescriptorAllocator::IsAllocationStillValid(
|
||||
const GPUDescriptorHeapAllocation& allocation) const {
|
||||
- // Consider valid if allocated for the pending submit and the shader visible heaps
|
||||
- // have not switched over.
|
||||
- return (allocation.GetLastUsageSerial() > mDevice->GetCompletedCommandSerial() &&
|
||||
+ // Descriptor allocations are only valid for the serial they were created for and are
|
||||
+ // re-allocated every submit. For this reason, we view any descriptors allocated prior to the
|
||||
+ // pending submit as invalid. We must also verify the descriptor heap has not switched (because
|
||||
+ // a larger descriptor heap was needed).
|
||||
+ return (allocation.GetLastUsageSerial() == mDevice->GetPendingCommandSerial() &&
|
||||
allocation.GetHeapSerial() == mHeapSerial);
|
||||
}
|
||||
|
||||
@@ -53,3 +53,6 @@ chore_add_missing_algorithm_include.patch
|
||||
enable_crashpad_linux_node_processes.patch
|
||||
allow_embedder_to_control_codegenerationfromstringscallback.patch
|
||||
cherry-pick-09ae62b.patch
|
||||
lib_fix_broadcastchannel_initialization_location.patch
|
||||
src_allow_optional_isolation_termination_in_node.patch
|
||||
fix_do_not_resolve_electron_entrypoints.patch
|
||||
|
||||
@@ -30,7 +30,7 @@ index b6981c37d5b286e22f24d11751eb05f72ca27619..c4a3a54753767e7686a0e32996bcda0c
|
||||
Mutex::ScopedLock lock(node::per_process::cli_options_mutex);
|
||||
if (per_process::cli_options->get_per_isolate_options()
|
||||
diff --git a/src/node.h b/src/node.h
|
||||
index bee494f9da8470530ee9ec58958f8f2c7ce6a302..387ce8e5edf6524db170e2d46ef501a1cd956d98 100644
|
||||
index f8f2cde5c2e07e032955b0342a31db52f20460f3..7e1be61a9cca8205666a129bafa2b2f4f4dbcc4b 100644
|
||||
--- a/src/node.h
|
||||
+++ b/src/node.h
|
||||
@@ -461,6 +461,8 @@ struct IsolateSettings {
|
||||
|
||||
@@ -52,7 +52,7 @@ index 1b7a721585764aecfd855ee47c47a3bd235d2ef3..c152ea9f29478729ec3752132140e3ec
|
||||
o['variables']['v8_enable_javascript_promise_hooks'] = 1
|
||||
o['variables']['v8_enable_lite_mode'] = 1 if options.v8_lite_mode else 0
|
||||
diff --git a/src/node.h b/src/node.h
|
||||
index 10061d4298368bc0ad53c0c8c3a3c964c13d4c3c..bee494f9da8470530ee9ec58958f8f2c7ce6a302 100644
|
||||
index 10061d4298368bc0ad53c0c8c3a3c964c13d4c3c..f8f2cde5c2e07e032955b0342a31db52f20460f3 100644
|
||||
--- a/src/node.h
|
||||
+++ b/src/node.h
|
||||
@@ -22,6 +22,12 @@
|
||||
@@ -61,7 +61,7 @@ index 10061d4298368bc0ad53c0c8c3a3c964c13d4c3c..bee494f9da8470530ee9ec58958f8f2c
|
||||
|
||||
+#ifdef ELECTRON_ENSURE_CONFIG_GYPI
|
||||
+#ifndef USING_ELECTRON_CONFIG_GYPI
|
||||
+#error "It looks like you are building this native module without using the right config.gypi. This normally means that you need to update electron-rebuild (>=3.2.8) or node-gyp (>=8.4.0) if you're building modules directly."
|
||||
+#error "It looks like you are building this native module without using the right config.gypi. This normally means that you need to update electron-rebuild (>=3.2.8) or node-gyp (>=9.0.0) if you're building modules directly."
|
||||
+#endif
|
||||
+#endif
|
||||
+
|
||||
|
||||
24
patches/node/fix_do_not_resolve_electron_entrypoints.patch
Normal file
24
patches/node/fix_do_not_resolve_electron_entrypoints.patch
Normal file
@@ -0,0 +1,24 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Samuel Attard <marshallofsound@electronjs.org>
|
||||
Date: Wed, 26 Jul 2023 17:03:15 -0700
|
||||
Subject: fix: do not resolve electron entrypoints
|
||||
|
||||
This wastes fs cycles and can result in strange behavior if this path actually exists on disk
|
||||
|
||||
diff --git a/lib/internal/modules/run_main.js b/lib/internal/modules/run_main.js
|
||||
index 5a50d5d6afab6e6648f72a1c0efa1df4cd80bcd9..0be45309028b00a6957ee473322a9452a7fa7d67 100644
|
||||
--- a/lib/internal/modules/run_main.js
|
||||
+++ b/lib/internal/modules/run_main.js
|
||||
@@ -13,6 +13,12 @@ const {
|
||||
} = require('internal/modules/esm/handle_process_exit');
|
||||
|
||||
function resolveMainPath(main) {
|
||||
+ // For built-in modules used as the main entry point we _never_
|
||||
+ // want to waste cycles resolving them to file paths on disk
|
||||
+ // that actually might exist
|
||||
+ if (typeof main === 'string' && main.startsWith('electron/js2c')) {
|
||||
+ return main;
|
||||
+ }
|
||||
// Note extension resolution for the main entry point can be deprecated in a
|
||||
// future major.
|
||||
// Module._findPath is monkey-patchable here.
|
||||
@@ -0,0 +1,44 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Shelley Vohr <shelley.vohr@gmail.com>
|
||||
Date: Mon, 27 Feb 2023 12:56:15 +0100
|
||||
Subject: lib: fix BroadcastChannel initialization location
|
||||
|
||||
Refs https://github.com/nodejs/node/pull/40532.
|
||||
|
||||
Fixes a bug in the above, wherein BroadcastChannel should have been
|
||||
initialized in bootstrap/browser instead of bootstrap/node. That
|
||||
inadvertently made it such that there was incorrect handling of the
|
||||
DOM vs Node.js implementations of BroadcastChannel.
|
||||
|
||||
This will be upstreamed.
|
||||
|
||||
diff --git a/lib/internal/bootstrap/browser.js b/lib/internal/bootstrap/browser.js
|
||||
index d0c01ca2a512be549b0fea8a829c05eabbec799a..210a1bb7e929021725b04786bc11d9b3ce09ad04 100644
|
||||
--- a/lib/internal/bootstrap/browser.js
|
||||
+++ b/lib/internal/bootstrap/browser.js
|
||||
@@ -12,6 +12,10 @@ const {
|
||||
} = require('internal/util');
|
||||
const config = internalBinding('config');
|
||||
|
||||
+// Non-standard extensions:
|
||||
+const { BroadcastChannel } = require('internal/worker/io');
|
||||
+exposeInterface(globalThis, 'BroadcastChannel', BroadcastChannel);
|
||||
+
|
||||
// https://console.spec.whatwg.org/#console-namespace
|
||||
exposeNamespace(globalThis, 'console',
|
||||
createGlobalConsole());
|
||||
diff --git a/lib/internal/bootstrap/node.js b/lib/internal/bootstrap/node.js
|
||||
index 83ac636db19a66f43fc7d3c1fc1e8290eeadd334..cb5072df3c23b499292887c56501820aee5cbd0e 100644
|
||||
--- a/lib/internal/bootstrap/node.js
|
||||
+++ b/lib/internal/bootstrap/node.js
|
||||
@@ -248,10 +248,6 @@ const {
|
||||
queueMicrotask
|
||||
} = require('internal/process/task_queues');
|
||||
|
||||
-// Non-standard extensions:
|
||||
-const { BroadcastChannel } = require('internal/worker/io');
|
||||
-exposeInterface(globalThis, 'BroadcastChannel', BroadcastChannel);
|
||||
-
|
||||
defineOperation(globalThis, 'queueMicrotask', queueMicrotask);
|
||||
|
||||
const timers = require('timers');
|
||||
@@ -0,0 +1,75 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Shelley Vohr <shelley.vohr@gmail.com>
|
||||
Date: Tue, 7 Feb 2023 10:53:11 +0100
|
||||
Subject: src: allow optional isolation termination in node
|
||||
|
||||
This patch allows for node::Stop() to conditionally call
|
||||
V8:Isolate::TerminateExecution().
|
||||
|
||||
We do not want to invoke a termination exception at exit when
|
||||
we're running with only_terminate_in_safe_scope set to false. Heap and
|
||||
coverage profilers run after environment exit and if there is a pending
|
||||
exception at this stage then they will fail to generate the appropriate
|
||||
profiles. Node.js does not call node::Stop(), which previously always
|
||||
called isolate->TerminateExecution(), and therefore does not have this
|
||||
issue when also running with only_terminate_in_safe_scope set to false.
|
||||
|
||||
diff --git a/src/env.cc b/src/env.cc
|
||||
index de41e5b7f6ff9f818c661484a93b74db7569e31f..819fcfa6be46328a01a612315d48e93eb025423c 100644
|
||||
--- a/src/env.cc
|
||||
+++ b/src/env.cc
|
||||
@@ -920,10 +920,11 @@ void Environment::InitializeLibuv() {
|
||||
StartProfilerIdleNotifier();
|
||||
}
|
||||
|
||||
-void Environment::ExitEnv() {
|
||||
+void Environment::ExitEnv(bool terminate) {
|
||||
set_can_call_into_js(false);
|
||||
set_stopping(true);
|
||||
- isolate_->TerminateExecution();
|
||||
+ if (terminate)
|
||||
+ isolate_->TerminateExecution();
|
||||
SetImmediateThreadsafe([](Environment* env) { uv_stop(env->event_loop()); });
|
||||
}
|
||||
|
||||
diff --git a/src/env.h b/src/env.h
|
||||
index 34c88c1addc5f64bd46332451e5b4ba8343c8818..1d32bf5945ab814294b5b5676b228c86518a05cd 100644
|
||||
--- a/src/env.h
|
||||
+++ b/src/env.h
|
||||
@@ -1100,7 +1100,7 @@ class Environment : public MemoryRetainer {
|
||||
void RegisterHandleCleanups();
|
||||
void CleanupHandles();
|
||||
void Exit(int code);
|
||||
- void ExitEnv();
|
||||
+ void ExitEnv(bool terminate);
|
||||
|
||||
// Register clean-up cb to be called on environment destruction.
|
||||
inline void RegisterHandleCleanup(uv_handle_t* handle,
|
||||
diff --git a/src/node.cc b/src/node.cc
|
||||
index 357ca1eb55652d88d6de60618e62cd54eaff6601..e0f84c3a7ba1c1866971eacfe0b508a52446bd7e 100644
|
||||
--- a/src/node.cc
|
||||
+++ b/src/node.cc
|
||||
@@ -1344,8 +1344,8 @@ int Start(int argc, char** argv) {
|
||||
return LoadSnapshotDataAndRun(&snapshot_data, result.get());
|
||||
}
|
||||
|
||||
-int Stop(Environment* env) {
|
||||
- env->ExitEnv();
|
||||
+int Stop(Environment* env, bool terminate) {
|
||||
+ env->ExitEnv(terminate);
|
||||
return 0;
|
||||
}
|
||||
|
||||
diff --git a/src/node.h b/src/node.h
|
||||
index 7e1be61a9cca8205666a129bafa2b2f4f4dbcc4b..00ff1d6d6560a2e97da1c675a46bcd6defe963d7 100644
|
||||
--- a/src/node.h
|
||||
+++ b/src/node.h
|
||||
@@ -314,7 +314,7 @@ NODE_EXTERN int Start(int argc, char* argv[]);
|
||||
|
||||
// Tear down Node.js while it is running (there are active handles
|
||||
// in the loop and / or actively executing JavaScript code).
|
||||
-NODE_EXTERN int Stop(Environment* env);
|
||||
+NODE_EXTERN int Stop(Environment* env, bool terminate = true);
|
||||
|
||||
// This runs a subset of the initialization performed by
|
||||
// InitializeOncePerProcess(), which supersedes this function.
|
||||
3
patches/pdfium/.patches
Normal file
3
patches/pdfium/.patches
Normal file
@@ -0,0 +1,3 @@
|
||||
m114_observe_cpwl_combobox_across_all_on_methods.patch
|
||||
m114_observe_widget_across_setoptionselection_calls.patch
|
||||
m114_always_check_return_code_from_cpwl_combobox_setpopup.patch
|
||||
@@ -0,0 +1,236 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Tom Sepez <tsepez@chromium.org>
|
||||
Date: Fri, 19 May 2023 18:41:31 +0000
|
||||
Subject: Always check return code from CPWL_ComboBox::SetPopup().
|
||||
|
||||
Operation must not continue when false is returned.
|
||||
|
||||
Bug: chromium:1444238
|
||||
Change-Id: Ic8c29653ac185ac80b6248203649ce05d0e10f06
|
||||
Reviewed-on: https://pdfium-review.googlesource.com/c/pdfium/+/107390
|
||||
Commit-Queue: Tom Sepez <tsepez@chromium.org>
|
||||
Reviewed-by: Lei Zhang <thestig@chromium.org>
|
||||
(cherry picked from commit 3eb3c4d77d4f9372f77aa4895b85a1d4e4755c89)
|
||||
Reviewed-on: https://pdfium-review.googlesource.com/c/pdfium/+/107812
|
||||
|
||||
diff --git a/fpdfsdk/pwl/cpwl_combo_box.cpp b/fpdfsdk/pwl/cpwl_combo_box.cpp
|
||||
index 4cda2135433b07d641d773f184034b0f3dee7e58..f9a8550da29e7a7afca757167af257d95a67bd9f 100644
|
||||
--- a/fpdfsdk/pwl/cpwl_combo_box.cpp
|
||||
+++ b/fpdfsdk/pwl/cpwl_combo_box.cpp
|
||||
@@ -400,7 +400,9 @@ bool CPWL_ComboBox::OnChar(uint16_t nChar, Mask<FWL_EVENTFLAG> nFlag) {
|
||||
// options.
|
||||
switch (nChar) {
|
||||
case pdfium::ascii::kReturn:
|
||||
- SetPopup(!IsPopup());
|
||||
+ if (!SetPopup(!IsPopup())) {
|
||||
+ return false;
|
||||
+ }
|
||||
SetSelectText();
|
||||
return true;
|
||||
case pdfium::ascii::kSpace:
|
||||
@@ -408,7 +410,9 @@ bool CPWL_ComboBox::OnChar(uint16_t nChar, Mask<FWL_EVENTFLAG> nFlag) {
|
||||
// editable
|
||||
if (!HasFlag(PCBS_ALLOWCUSTOMTEXT)) {
|
||||
if (!IsPopup()) {
|
||||
- SetPopup(/*bPopUp=*/true);
|
||||
+ if (!SetPopup(/*bPopUp=*/true)) {
|
||||
+ return false;
|
||||
+ }
|
||||
SetSelectText();
|
||||
}
|
||||
return true;
|
||||
@@ -438,7 +442,7 @@ bool CPWL_ComboBox::OnChar(uint16_t nChar, Mask<FWL_EVENTFLAG> nFlag) {
|
||||
|
||||
void CPWL_ComboBox::NotifyLButtonDown(CPWL_Wnd* child, const CFX_PointF& pos) {
|
||||
if (child == m_pButton) {
|
||||
- SetPopup(!m_bPopup);
|
||||
+ (void)SetPopup(!m_bPopup);
|
||||
// Note, |this| may no longer be viable at this point. If more work needs to
|
||||
// be done, check the return value of SetPopup().
|
||||
}
|
||||
@@ -451,7 +455,7 @@ void CPWL_ComboBox::NotifyLButtonUp(CPWL_Wnd* child, const CFX_PointF& pos) {
|
||||
SetSelectText();
|
||||
SelectAllText();
|
||||
m_pEdit->SetFocus();
|
||||
- SetPopup(false);
|
||||
+ (void)SetPopup(false);
|
||||
// Note, |this| may no longer be viable at this point. If more work needs to
|
||||
// be done, check the return value of SetPopup().
|
||||
}
|
||||
diff --git a/fpdfsdk/pwl/cpwl_combo_box.h b/fpdfsdk/pwl/cpwl_combo_box.h
|
||||
index 480da52d7a65538dee190e2a609215f9c424bb38..b1ac3d9e8ac29e9433330ff86df7ef4b71a3fabd 100644
|
||||
--- a/fpdfsdk/pwl/cpwl_combo_box.h
|
||||
+++ b/fpdfsdk/pwl/cpwl_combo_box.h
|
||||
@@ -64,7 +64,7 @@ class CPWL_ComboBox final : public CPWL_Wnd {
|
||||
void CreateListBox(const CreateParams& cp);
|
||||
|
||||
// Returns |true| iff this instance is still allocated.
|
||||
- bool SetPopup(bool bPopup);
|
||||
+ [[nodiscard]] bool SetPopup(bool bPopup);
|
||||
|
||||
UnownedPtr<CPWL_Edit> m_pEdit;
|
||||
UnownedPtr<CPWL_CBButton> m_pButton;
|
||||
diff --git a/testing/resources/javascript/xfa_specific/bug_1444238.evt b/testing/resources/javascript/xfa_specific/bug_1444238.evt
|
||||
new file mode 100644
|
||||
index 0000000000000000000000000000000000000000..adca35aa0d756e76eb395c5d60ba41b86c3d0090
|
||||
--- /dev/null
|
||||
+++ b/testing/resources/javascript/xfa_specific/bug_1444238.evt
|
||||
@@ -0,0 +1,3 @@
|
||||
+mousedown,left,91,539
|
||||
+mouseup,left,91,539
|
||||
+charcode,32
|
||||
diff --git a/testing/resources/javascript/xfa_specific/bug_1444238.in b/testing/resources/javascript/xfa_specific/bug_1444238.in
|
||||
new file mode 100644
|
||||
index 0000000000000000000000000000000000000000..675178c9446b0181c3633a4b5c9bc664bb4c127d
|
||||
--- /dev/null
|
||||
+++ b/testing/resources/javascript/xfa_specific/bug_1444238.in
|
||||
@@ -0,0 +1,149 @@
|
||||
+{{header}}
|
||||
+{{object 1 0}} <<
|
||||
+ /Type /Catalog
|
||||
+ /Pages 2 0 R
|
||||
+ /AcroForm 4 0 R
|
||||
+ /OpenAction 40 0 R
|
||||
+>>
|
||||
+endobj
|
||||
+{{object 2 0}} <<
|
||||
+ /Type /Pages
|
||||
+ /Count 2
|
||||
+ /Kids [
|
||||
+ 32 0 R
|
||||
+ 34 0 R
|
||||
+ ]
|
||||
+>>
|
||||
+endobj
|
||||
+% Forms
|
||||
+{{object 4 0}} <<
|
||||
+ /XFA 43 0 R
|
||||
+ /Fields [
|
||||
+ 10 0 R
|
||||
+ 11 0 R
|
||||
+ ]
|
||||
+>>
|
||||
+endobj
|
||||
+% Fields
|
||||
+{{object 10 0}} <<
|
||||
+ /Type /Annot
|
||||
+ /Subtype /Widget
|
||||
+ /FT /Tx
|
||||
+ /T (MyField5)
|
||||
+ /V (myfield_5)
|
||||
+ /Rect [0 500 600 600]
|
||||
+>>
|
||||
+% Fields
|
||||
+{{object 11 0}} <<
|
||||
+ /T (MyField3)
|
||||
+ /Parent 4 0 R
|
||||
+ /Kids [12 0 R]
|
||||
+ /Opt [(a) (b) (c) (d)]
|
||||
+ /V [(a) (b) (c)]
|
||||
+>>
|
||||
+endobj
|
||||
+% Fields
|
||||
+{{object 12 0}} <<
|
||||
+ /Type /Annot
|
||||
+ /Subtype /Widget
|
||||
+ /FT /Ch
|
||||
+ /Ff 131072
|
||||
+ /Parent 11 0 R
|
||||
+ /Kids [13 0 R]
|
||||
+>>
|
||||
+endobj
|
||||
+% Fields
|
||||
+{{object 13 0}} <<
|
||||
+ /Type /Annot
|
||||
+ /Subtype /Widget
|
||||
+ /Parent 12 0 R
|
||||
+ /Rect [0 400 600 600]
|
||||
+>>
|
||||
+endobj
|
||||
+% Fields
|
||||
+{{object 14 0}} <<
|
||||
+ /Type /Annot
|
||||
+ /Subtype /Widget
|
||||
+ /Parent 12 0 R
|
||||
+ /Rect [100 400 500 500]
|
||||
+>>
|
||||
+endobj
|
||||
+% Page number 2.
|
||||
+{{object 32 0}} <<
|
||||
+ /Type /Page
|
||||
+ /Parent 2 0 R
|
||||
+ /MediaBox [0 0 612 792]
|
||||
+ /Annots [13 0 R]
|
||||
+
|
||||
+>>
|
||||
+endobj
|
||||
+{{object 34 0}} <<
|
||||
+ /Type /Page
|
||||
+ /Parent 2 0 R
|
||||
+ /MediaBox [0 0 612 792]
|
||||
+ /Annots [10 0 R]
|
||||
+>>
|
||||
+endobj
|
||||
+% Document JS Action
|
||||
+{{object 40 0}} <<
|
||||
+ /Type /Action
|
||||
+ /S /JavaScript
|
||||
+ /JS 41 0 R
|
||||
+>>
|
||||
+endobj
|
||||
+% JS program to exexute
|
||||
+{{object 41 0}} <<
|
||||
+>>
|
||||
+stream
|
||||
+var f5 = this.getField("MyField5");
|
||||
+var f3 = this.getField("MyField3");
|
||||
+f3.setFocus();
|
||||
+this.__defineGetter__("pageNum",function o(){f5.setFocus(); f3.borderStyle="dashed"; f3.setFocus();});
|
||||
+endstream
|
||||
+endobj
|
||||
+{{object 43 0}} <<
|
||||
+ {{streamlen}}
|
||||
+>>
|
||||
+stream
|
||||
+<?xml version="1.0" encoding="UTF-8"?>
|
||||
+<xdp:xdp xmlns:xdp="http://ns.adobe.com/xdp/">
|
||||
+<config></config>
|
||||
+<template xmlns="http://www.xfa.org/schema/xfa-template/2.8/">
|
||||
+ <subform layout="tb" locale="en_US">
|
||||
+ <pageSet>
|
||||
+ <pageArea id="Page1" name="Page1">
|
||||
+ <contentArea h="268.939mm" w="203.2mm" x="6.35mm" y="6.35mm"/>
|
||||
+ <medium long="792pt" short="612pt" stock="default"/>
|
||||
+ </pageArea>
|
||||
+ </pageSet>
|
||||
+ <field h="9.0001mm" name="MyField3" w="47.625mm" x="120mm" y="120mm">
|
||||
+ <ui>
|
||||
+ <choiceList open="onEntry">
|
||||
+ <border>
|
||||
+ <edge/>
|
||||
+ </border>
|
||||
+ </choiceList>
|
||||
+ </ui>
|
||||
+ <items save="1">
|
||||
+ <text>apples</text>
|
||||
+ <text>bananas</text>
|
||||
+ <text>pears</text>
|
||||
+ </items>
|
||||
+ <value>
|
||||
+ <text>apples</text>
|
||||
+ </value>
|
||||
+ <event activity="preOpen">
|
||||
+ <script contentType="application/x-javascript">
|
||||
+ var aa = this.pageNum;
|
||||
+ </script>
|
||||
+ </event>
|
||||
+ </field>
|
||||
+ </subform>
|
||||
+</template>
|
||||
+</xdp:xdp>
|
||||
+endstream
|
||||
+endobj
|
||||
+{{xref}}
|
||||
+{{trailer}}
|
||||
+{{startxref}}
|
||||
+%%EOF
|
||||
@@ -0,0 +1,213 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Tom Sepez <tsepez@chromium.org>
|
||||
Date: Fri, 19 May 2023 20:05:10 +0000
|
||||
Subject: Observe CPWL_ComboBox across all On* methods
|
||||
|
||||
Bug: chromium:1445426
|
||||
Change-Id: I1d7ebf66fe170ca016c27a0df3ac4574e75c763c
|
||||
Reviewed-on: https://pdfium-review.googlesource.com/c/pdfium/+/107650
|
||||
Reviewed-by: Lei Zhang <thestig@chromium.org>
|
||||
Commit-Queue: Tom Sepez <tsepez@chromium.org>
|
||||
(cherry picked from commit 29c665ea4c61b089746c3f502c30fcb5f4b11486)
|
||||
Reviewed-on: https://pdfium-review.googlesource.com/c/pdfium/+/107811
|
||||
|
||||
diff --git a/fpdfsdk/pwl/cpwl_combo_box.cpp b/fpdfsdk/pwl/cpwl_combo_box.cpp
|
||||
index dde76521a7c15070c1245938063830a003986a69..4cda2135433b07d641d773f184034b0f3dee7e58 100644
|
||||
--- a/fpdfsdk/pwl/cpwl_combo_box.cpp
|
||||
+++ b/fpdfsdk/pwl/cpwl_combo_box.cpp
|
||||
@@ -339,31 +339,42 @@ bool CPWL_ComboBox::OnKeyDown(FWL_VKEYCODE nKeyCode,
|
||||
if (!m_pEdit)
|
||||
return false;
|
||||
|
||||
+ ObservedPtr<CPWL_Wnd> thisObserved(this);
|
||||
m_nSelectItem = -1;
|
||||
|
||||
switch (nKeyCode) {
|
||||
case FWL_VKEY_Up:
|
||||
if (m_pList->GetCurSel() > 0) {
|
||||
- if (GetFillerNotify()->OnPopupPreOpen(GetAttachedData(), nFlag))
|
||||
+ if (GetFillerNotify()->OnPopupPreOpen(GetAttachedData(), nFlag) ||
|
||||
+ !thisObserved) {
|
||||
return false;
|
||||
- if (GetFillerNotify()->OnPopupPostOpen(GetAttachedData(), nFlag))
|
||||
+ }
|
||||
+ if (GetFillerNotify()->OnPopupPostOpen(GetAttachedData(), nFlag) ||
|
||||
+ !thisObserved) {
|
||||
return false;
|
||||
+ }
|
||||
if (m_pList->IsMovementKey(nKeyCode)) {
|
||||
- if (m_pList->OnMovementKeyDown(nKeyCode, nFlag))
|
||||
+ if (m_pList->OnMovementKeyDown(nKeyCode, nFlag) || !thisObserved) {
|
||||
return false;
|
||||
+ }
|
||||
SetSelectText();
|
||||
}
|
||||
}
|
||||
return true;
|
||||
case FWL_VKEY_Down:
|
||||
if (m_pList->GetCurSel() < m_pList->GetCount() - 1) {
|
||||
- if (GetFillerNotify()->OnPopupPreOpen(GetAttachedData(), nFlag))
|
||||
+ if (GetFillerNotify()->OnPopupPreOpen(GetAttachedData(), nFlag) ||
|
||||
+ !thisObserved) {
|
||||
return false;
|
||||
- if (GetFillerNotify()->OnPopupPostOpen(GetAttachedData(), nFlag))
|
||||
+ }
|
||||
+ if (GetFillerNotify()->OnPopupPostOpen(GetAttachedData(), nFlag) ||
|
||||
+ !thisObserved) {
|
||||
return false;
|
||||
+ }
|
||||
if (m_pList->IsMovementKey(nKeyCode)) {
|
||||
- if (m_pList->OnMovementKeyDown(nKeyCode, nFlag))
|
||||
+ if (m_pList->OnMovementKeyDown(nKeyCode, nFlag) || !thisObserved) {
|
||||
return false;
|
||||
+ }
|
||||
SetSelectText();
|
||||
}
|
||||
}
|
||||
@@ -411,10 +422,15 @@ bool CPWL_ComboBox::OnChar(uint16_t nChar, Mask<FWL_EVENTFLAG> nFlag) {
|
||||
if (HasFlag(PCBS_ALLOWCUSTOMTEXT))
|
||||
return m_pEdit->OnChar(nChar, nFlag);
|
||||
|
||||
- if (GetFillerNotify()->OnPopupPreOpen(GetAttachedData(), nFlag))
|
||||
+ ObservedPtr<CPWL_Wnd> thisObserved(this);
|
||||
+ if (GetFillerNotify()->OnPopupPreOpen(GetAttachedData(), nFlag) ||
|
||||
+ !thisObserved) {
|
||||
return false;
|
||||
- if (GetFillerNotify()->OnPopupPostOpen(GetAttachedData(), nFlag))
|
||||
+ }
|
||||
+ if (GetFillerNotify()->OnPopupPostOpen(GetAttachedData(), nFlag) ||
|
||||
+ !thisObserved) {
|
||||
return false;
|
||||
+ }
|
||||
if (!m_pList->IsChar(nChar, nFlag))
|
||||
return false;
|
||||
return m_pList->OnCharNotify(nChar, nFlag);
|
||||
diff --git a/testing/resources/javascript/bug_1445426.evt b/testing/resources/javascript/bug_1445426.evt
|
||||
new file mode 100644
|
||||
index 0000000000000000000000000000000000000000..265e85b0471b33509568238ccae30d2395b4b4ab
|
||||
--- /dev/null
|
||||
+++ b/testing/resources/javascript/bug_1445426.evt
|
||||
@@ -0,0 +1,3 @@
|
||||
+mousedown,left,202,697
|
||||
+mouseup,left,202,697
|
||||
+keycode,40
|
||||
diff --git a/testing/resources/javascript/bug_1445426.in b/testing/resources/javascript/bug_1445426.in
|
||||
new file mode 100644
|
||||
index 0000000000000000000000000000000000000000..1483da72f5759e9f2c8fdb538d5c6fa0cd1611c5
|
||||
--- /dev/null
|
||||
+++ b/testing/resources/javascript/bug_1445426.in
|
||||
@@ -0,0 +1,114 @@
|
||||
+{{header}}
|
||||
+{{object 1 0}} <<
|
||||
+ /Type /Catalog
|
||||
+ /Pages 2 0 R
|
||||
+ /AcroForm 4 0 R
|
||||
+ /OpenAction 40 0 R
|
||||
+>>
|
||||
+endobj
|
||||
+{{object 2 0}} <<
|
||||
+ /Type /Pages
|
||||
+ /Count 2
|
||||
+ /Kids [
|
||||
+ 32 0 R
|
||||
+ 34 0 R
|
||||
+ ]
|
||||
+>>
|
||||
+endobj
|
||||
+% Forms
|
||||
+{{object 4 0}} <<
|
||||
+ /Fields [
|
||||
+ 10 0 R
|
||||
+ 11 0 R
|
||||
+ ]
|
||||
+>>
|
||||
+endobj
|
||||
+% Fields
|
||||
+{{object 10 0}} <<
|
||||
+ /Type /Annot
|
||||
+ /Subtype /Widget
|
||||
+ /FT /Tx
|
||||
+ /T (Field_TextEdit)
|
||||
+ /Rect [0 0 612 792]
|
||||
+>>
|
||||
+{{object 11 0}} <<
|
||||
+ /T (Field_ComboBox)
|
||||
+ /Parent 4 0 R
|
||||
+ /Kids [12 0 R]
|
||||
+ /Opt [(a) (b) (c) (d)]
|
||||
+ /V [(a)]
|
||||
+>>
|
||||
+endobj
|
||||
+{{object 12 0}} <<
|
||||
+ /Type /Annot
|
||||
+ /Subtype /Widget
|
||||
+ /FT /Ch
|
||||
+ /Ff 131072
|
||||
+ /Parent 11 0 R
|
||||
+ /Kids [13 0 R]
|
||||
+>>
|
||||
+endobj
|
||||
+{{object 13 0}} <<
|
||||
+ /Parent 12 0 R
|
||||
+ /Type /Annot
|
||||
+ /Subtype /Widget
|
||||
+ /Rect [0 0 612 792]
|
||||
+ /AA << /K 20 0 R >>
|
||||
+>>
|
||||
+endobj
|
||||
+% Pages
|
||||
+{{object 32 0}} <<
|
||||
+ /Type /Page
|
||||
+ /Parent 2 0 R
|
||||
+ /MediaBox [0 0 612 792]
|
||||
+ /Annots [13 0 R]
|
||||
+
|
||||
+>>
|
||||
+endobj
|
||||
+{{object 34 0}} <<
|
||||
+ /Type /Page
|
||||
+ /Parent 2 0 R
|
||||
+ /MediaBox [0 0 612 792]
|
||||
+ /Annots [10 0 R]
|
||||
+>>
|
||||
+endobj
|
||||
+% Document JS Action
|
||||
+{{object 40 0}} <<
|
||||
+ /Type /Action
|
||||
+ /S /JavaScript
|
||||
+ /JS 41 0 R
|
||||
+>>
|
||||
+endobj
|
||||
+% JS program to exexute
|
||||
+{{object 41 0}} <<
|
||||
+ {{streamlen}}
|
||||
+>>
|
||||
+stream
|
||||
+var field_text = this.getField("Field_TextEdit");
|
||||
+var field_combobox = this.getField("Field_ComboBox");
|
||||
+field_combobox.setFocus();
|
||||
+this.__defineGetter__("filesize", function new_getter(){
|
||||
+ field_text.setFocus();
|
||||
+ field_combobox.borderStyle="dashed";
|
||||
+ field_combobox.setFocus();
|
||||
+ });
|
||||
+endstream
|
||||
+endobj
|
||||
+% OpenAction action
|
||||
+{{object 20 0}} <<
|
||||
+ /S /JavaScript
|
||||
+ /JS 21 0 R
|
||||
+>>
|
||||
+endobj
|
||||
+% JS program to exexute
|
||||
+{{object 21 0}} <<
|
||||
+ {{streamlen}}
|
||||
+>>
|
||||
+stream
|
||||
+var t = this.filesize;
|
||||
+endstream
|
||||
+endobj
|
||||
+{{xref}}
|
||||
+{{trailer}}
|
||||
+{{startxref}}
|
||||
+%%EOF
|
||||
@@ -0,0 +1,40 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Tom Sepez <tsepez@chromium.org>
|
||||
Date: Thu, 18 May 2023 18:37:17 +0000
|
||||
Subject: Observe widget across SetOptionSelection() calls.
|
||||
|
||||
Call may re-enter JavaScript.
|
||||
|
||||
Bug: chromium:1444581
|
||||
Change-Id: Id7a2f17b3b81f822ca8f4496ac08c19b7794c48a
|
||||
Reviewed-on: https://pdfium-review.googlesource.com/c/pdfium/+/107394
|
||||
Commit-Queue: Tom Sepez <tsepez@chromium.org>
|
||||
Reviewed-by: Lei Zhang <thestig@chromium.org>
|
||||
(cherry picked from commit a9ff918a86d700c3bdf9b5820faed35490c0cd25)
|
||||
Reviewed-on: https://pdfium-review.googlesource.com/c/pdfium/+/107735
|
||||
Auto-Submit: Tom Sepez <tsepez@chromium.org>
|
||||
|
||||
diff --git a/fpdfsdk/formfiller/cffl_listbox.cpp b/fpdfsdk/formfiller/cffl_listbox.cpp
|
||||
index ea119ec093c748c6c8bfb7b3c31b4ae97f959908..31134bb1e576003cc377eb90a61898f8097f080c 100644
|
||||
--- a/fpdfsdk/formfiller/cffl_listbox.cpp
|
||||
+++ b/fpdfsdk/formfiller/cffl_listbox.cpp
|
||||
@@ -116,11 +116,18 @@ void CFFL_ListBox::SaveData(const CPDFSDK_PageView* pPageView) {
|
||||
}
|
||||
if (m_pWidget->GetFieldFlags() & pdfium::form_flags::kChoiceMultiSelect) {
|
||||
for (int32_t i = 0, sz = pListBox->GetCount(); i < sz; i++) {
|
||||
- if (pListBox->IsItemSelected(i))
|
||||
+ if (pListBox->IsItemSelected(i)) {
|
||||
m_pWidget->SetOptionSelection(i);
|
||||
+ if (!observed_box) {
|
||||
+ return;
|
||||
+ }
|
||||
+ }
|
||||
}
|
||||
} else {
|
||||
m_pWidget->SetOptionSelection(pListBox->GetCurSel());
|
||||
+ if (!observed_box) {
|
||||
+ return;
|
||||
+ }
|
||||
}
|
||||
ObservedPtr<CPDFSDK_Widget> observed_widget(m_pWidget);
|
||||
ObservedPtr<CFFL_ListBox> observed_this(this);
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user