mirror of
https://github.com/electron/electron.git
synced 2026-02-19 03:14:51 -05:00
Compare commits
119 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
5b0665f4ae | ||
|
|
48247343c5 | ||
|
|
d0edcc25e3 | ||
|
|
7ef42017e1 | ||
|
|
fbedad73ce | ||
|
|
73cd1a880b | ||
|
|
334627ce74 | ||
|
|
e7791771ca | ||
|
|
2223b295df | ||
|
|
90d51ea331 | ||
|
|
2a9691fd3f | ||
|
|
40cbdd340d | ||
|
|
156a0cd12f | ||
|
|
27856acfdd | ||
|
|
cb5d93e9a7 | ||
|
|
751fc04502 | ||
|
|
ee5b2523f7 | ||
|
|
820bc2a499 | ||
|
|
b110a19358 | ||
|
|
418605e0fb | ||
|
|
a571cfdf8c | ||
|
|
19e35495ee | ||
|
|
cfac858d65 | ||
|
|
545fd1c287 | ||
|
|
c73577ca99 | ||
|
|
82ff0acb11 | ||
|
|
5d530d31f4 | ||
|
|
e9b5cd7d2e | ||
|
|
61af436d78 | ||
|
|
d1e9dfdb75 | ||
|
|
54c11f7b10 | ||
|
|
5698beef8f | ||
|
|
846d6570ee | ||
|
|
023b4bb51f | ||
|
|
bd78e092d4 | ||
|
|
fa77a9da46 | ||
|
|
067c4c4dc6 | ||
|
|
8a150a2a3f | ||
|
|
fdf96debe1 | ||
|
|
ed8c8334f4 | ||
|
|
570c146fe3 | ||
|
|
5828a25dc6 | ||
|
|
88146b4140 | ||
|
|
a0701fd622 | ||
|
|
44e0345320 | ||
|
|
d77c0f2e23 | ||
|
|
86af860c29 | ||
|
|
4615e4afda | ||
|
|
4c2f91198b | ||
|
|
ef73a91f02 | ||
|
|
0d7537772d | ||
|
|
c9e67c38b7 | ||
|
|
5abed6e890 | ||
|
|
5f37729c17 | ||
|
|
f6e9ab2234 | ||
|
|
5312995148 | ||
|
|
c9590a7c3a | ||
|
|
6ea76082de | ||
|
|
6b571240ad | ||
|
|
ba93dc3c83 | ||
|
|
039a1852a2 | ||
|
|
12df0267eb | ||
|
|
f1500363dc | ||
|
|
4435461885 | ||
|
|
dcdfe231fc | ||
|
|
bc2c39e668 | ||
|
|
95d1cf0670 | ||
|
|
423cdb02a7 | ||
|
|
cc8d02db5d | ||
|
|
3afea231ca | ||
|
|
49b624ef1f | ||
|
|
d8a1298eaf | ||
|
|
3026615784 | ||
|
|
23a81e6e59 | ||
|
|
801cbe2ab3 | ||
|
|
e857073d65 | ||
|
|
86a1ee1e89 | ||
|
|
2212933858 | ||
|
|
c5346bde08 | ||
|
|
c678f7b872 | ||
|
|
3aac61e60c | ||
|
|
e91dba1730 | ||
|
|
019c05b924 | ||
|
|
0fe2a73f83 | ||
|
|
69cb9c1581 | ||
|
|
b176c95226 | ||
|
|
fa9ffa77b8 | ||
|
|
9870a31225 | ||
|
|
0ee70e9431 | ||
|
|
47bc841d6c | ||
|
|
a75e369e9c | ||
|
|
bec207c931 | ||
|
|
28b9856094 | ||
|
|
ed999f5456 | ||
|
|
67363441a5 | ||
|
|
47dd47d8c4 | ||
|
|
0a34be3e55 | ||
|
|
72eea879e7 | ||
|
|
bcfafc4386 | ||
|
|
c8c335874a | ||
|
|
de9889e78a | ||
|
|
27944d805b | ||
|
|
8dcdf5c26d | ||
|
|
cef7f6f99b | ||
|
|
17d8889e41 | ||
|
|
a86510b30c | ||
|
|
0874e61e4f | ||
|
|
1cb0a98f6c | ||
|
|
16a3a456a6 | ||
|
|
7727b7ecba | ||
|
|
595ed3e128 | ||
|
|
fd52089635 | ||
|
|
77bc03e051 | ||
|
|
9f99f4ed0e | ||
|
|
bc27dc4597 | ||
|
|
9048de7cab | ||
|
|
cef4f6a8e7 | ||
|
|
80a4ea2601 | ||
|
|
0b733793c3 |
@@ -235,6 +235,11 @@ step-depot-tools-get: &step-depot-tools-get
|
||||
name: Get depot tools
|
||||
command: |
|
||||
git clone --depth=1 https://chromium.googlesource.com/chromium/tools/depot_tools.git
|
||||
cd depot_tools
|
||||
git fetch --depth 1 origin b7d8efd8bee494f4cfacacc19cf50fc4d4be3900
|
||||
git checkout b7d8efd8bee494f4cfacacc19cf50fc4d4be3900
|
||||
touch .disable_auto_update
|
||||
cd ..
|
||||
if [ "`uname`" == "Darwin" ]; then
|
||||
# remove ninjalog_uploader_wrapper.py from autoninja since we don't use it and it causes problems
|
||||
sed -i '' '/ninjalog_uploader_wrapper.py/d' ./depot_tools/autoninja
|
||||
@@ -454,7 +459,7 @@ step-delete-git-directories: &step-delete-git-directories
|
||||
command: |
|
||||
if [ "`uname`" == "Darwin" ]; then
|
||||
cd src
|
||||
( find . -type d -name ".git" -not -path "./third_party/angle/*" -not -path "./third_party/dawn/*" ) | xargs rm -rf
|
||||
( find . -type d -name ".git" -not -path "./third_party/angle/*" -not -path "./third_party/dawn/*" -not -path "./electron/*" ) | xargs rm -rf
|
||||
fi
|
||||
|
||||
# On macOS the yarn install command during gclient sync was run on a linux
|
||||
@@ -483,7 +488,9 @@ step-fix-sync: &step-fix-sync
|
||||
run:
|
||||
name: Fix Sync
|
||||
command: |
|
||||
SEDOPTION="-i"
|
||||
if [ "`uname`" == "Darwin" ]; then
|
||||
SEDOPTION="-i ''"
|
||||
# Fix Clang Install (wrong binary)
|
||||
rm -rf src/third_party/llvm-build
|
||||
python3 src/tools/clang/scripts/update.py
|
||||
@@ -568,6 +575,13 @@ step-electron-build: &step-electron-build
|
||||
ninja -C out/Default electron:electron_mksnapshot_zip -j $NUMBER_OF_NINJA_PROCESSES
|
||||
ninja -C out/Default tools/v8_context_snapshot -j $NUMBER_OF_NINJA_PROCESSES
|
||||
gn desc out/Default v8:run_mksnapshot_default args > out/Default/mksnapshot_args
|
||||
# Remove unused args from mksnapshot_args
|
||||
SEDOPTION=
|
||||
if [ "`uname`" == "Darwin" ]; then
|
||||
SEDOPTION="-i ''"
|
||||
fi
|
||||
sed $SEDOPTION '/.*builtins-pgo/d' out/Default/mksnapshot_args
|
||||
sed $SEDOPTION '/--turbo-profiling-input/d' out/Default/mksnapshot_args
|
||||
(cd out/Default; zip mksnapshot.zip mksnapshot_args clang_x64_v8_arm64/gen/v8/embedded.S)
|
||||
rm -rf out/Default/clang_x64_v8_arm64/gen
|
||||
rm -rf out/Default/clang_x64_v8_arm64/obj
|
||||
@@ -758,6 +772,13 @@ step-mksnapshot-build: &step-mksnapshot-build
|
||||
if [ "$USE_PREBUILT_V8_CONTEXT_SNAPSHOT" != "1" ]; then
|
||||
ninja -C out/Default electron:electron_mksnapshot -j $NUMBER_OF_NINJA_PROCESSES
|
||||
gn desc out/Default v8:run_mksnapshot_default args > out/Default/mksnapshot_args
|
||||
# Remove unused args from mksnapshot_args
|
||||
SEDOPTION=
|
||||
if [ "`uname`" == "Darwin" ]; then
|
||||
SEDOPTION="-i ''"
|
||||
fi
|
||||
sed $SEDOPTION '/.*builtins-pgo/d' out/Default/mksnapshot_args
|
||||
sed $SEDOPTION '/--turbo-profiling-input/d' out/Default/mksnapshot_args
|
||||
fi
|
||||
if [ "`uname`" != "Darwin" ]; then
|
||||
if [ "$TARGET_ARCH" == "arm" ]; then
|
||||
@@ -813,7 +834,7 @@ step-maybe-zip-symbols: &step-maybe-zip-symbols
|
||||
cd src
|
||||
export BUILD_PATH="$PWD/out/Default"
|
||||
ninja -C out/Default electron:licenses
|
||||
ninja -C out/Default electron:electron_version
|
||||
ninja -C out/Default electron:electron_version_file
|
||||
DELETE_DSYMS_AFTER_ZIP=1 electron/script/zip-symbols.py -b $BUILD_PATH
|
||||
|
||||
step-maybe-cross-arch-snapshot: &step-maybe-cross-arch-snapshot
|
||||
@@ -873,12 +894,12 @@ step-touch-sync-done: &step-touch-sync-done
|
||||
step-maybe-restore-src-cache: &step-maybe-restore-src-cache
|
||||
restore_cache:
|
||||
keys:
|
||||
- v14-src-cache-{{ checksum "src/electron/.depshash" }}
|
||||
- v16-src-cache-{{ checksum "src/electron/.depshash" }}
|
||||
name: Restoring src cache
|
||||
step-maybe-restore-src-cache-marker: &step-maybe-restore-src-cache-marker
|
||||
restore_cache:
|
||||
keys:
|
||||
- v14-src-cache-marker-{{ checksum "src/electron/.depshash" }}
|
||||
- v16-src-cache-marker-{{ checksum "src/electron/.depshash" }}
|
||||
name: Restoring src cache marker
|
||||
|
||||
# Restore exact or closest git cache based on the hash of DEPS and .circle-sync-done
|
||||
@@ -893,14 +914,6 @@ step-maybe-restore-git-cache: &step-maybe-restore-git-cache
|
||||
- v1-git-cache-{{ checksum "src/electron/.circle-sync-done" }}
|
||||
name: Conditionally restoring git cache
|
||||
|
||||
step-restore-out-cache: &step-restore-out-cache
|
||||
restore_cache:
|
||||
paths:
|
||||
- ./src/out/Default
|
||||
keys:
|
||||
- v10-out-cache-{{ checksum "src/electron/.depshash" }}-{{ checksum "src/electron/.depshash-target" }}
|
||||
name: Restoring out cache
|
||||
|
||||
step-set-git-cache-path: &step-set-git-cache-path
|
||||
run:
|
||||
name: Set GIT_CACHE_PATH to make gclient to use the cache
|
||||
@@ -918,13 +931,6 @@ step-save-git-cache: &step-save-git-cache
|
||||
key: v1-git-cache-{{ checksum "src/electron/.circle-sync-done" }}-{{ checksum "src/electron/DEPS" }}
|
||||
name: Persisting git cache
|
||||
|
||||
step-save-out-cache: &step-save-out-cache
|
||||
save_cache:
|
||||
paths:
|
||||
- ./src/out/Default
|
||||
key: v10-out-cache-{{ checksum "src/electron/.depshash" }}-{{ checksum "src/electron/.depshash-target" }}
|
||||
name: Persisting out cache
|
||||
|
||||
step-run-electron-only-hooks: &step-run-electron-only-hooks
|
||||
run:
|
||||
name: Run Electron Only Hooks
|
||||
@@ -954,13 +960,16 @@ step-minimize-workspace-size-from-checkout: &step-minimize-workspace-size-from-c
|
||||
rm -rf third_party/electron_node/deps/openssl
|
||||
rm -rf third_party/electron_node/deps/v8
|
||||
rm -rf chrome/test/data/xr/webvr_info
|
||||
rm -rf src/third_party/angle/third_party/VK-GL-CTS/src
|
||||
rm -rf src/third_party/swift-toolchain
|
||||
rm -rf src/third_party/swiftshader/tests/regres/testlists
|
||||
|
||||
# Save the src cache based on the deps hash
|
||||
step-save-src-cache: &step-save-src-cache
|
||||
save_cache:
|
||||
paths:
|
||||
- /var/portal
|
||||
key: v14-src-cache-{{ checksum "/var/portal/src/electron/.depshash" }}
|
||||
key: v16-src-cache-{{ checksum "/var/portal/src/electron/.depshash" }}
|
||||
name: Persisting src cache
|
||||
step-make-src-cache-marker: &step-make-src-cache-marker
|
||||
run:
|
||||
@@ -970,7 +979,7 @@ step-save-src-cache-marker: &step-save-src-cache-marker
|
||||
save_cache:
|
||||
paths:
|
||||
- .src-cache-marker
|
||||
key: v14-src-cache-marker-{{ checksum "/var/portal/src/electron/.depshash" }}
|
||||
key: v16-src-cache-marker-{{ checksum "/var/portal/src/electron/.depshash" }}
|
||||
|
||||
step-maybe-early-exit-no-doc-change: &step-maybe-early-exit-no-doc-change
|
||||
run:
|
||||
@@ -1302,9 +1311,6 @@ commands:
|
||||
build:
|
||||
type: boolean
|
||||
default: true
|
||||
use-out-cache:
|
||||
type: boolean
|
||||
default: true
|
||||
restore-src-cache:
|
||||
type: boolean
|
||||
default: true
|
||||
@@ -1427,10 +1433,6 @@ commands:
|
||||
- *step-delete-git-directories
|
||||
|
||||
# Electron app
|
||||
- when:
|
||||
condition: << parameters.use-out-cache >>
|
||||
steps:
|
||||
- *step-restore-out-cache
|
||||
- *step-gn-gen-default
|
||||
- *step-electron-build
|
||||
- *step-maybe-electron-dist-strip
|
||||
@@ -1473,22 +1475,6 @@ commands:
|
||||
condition: << parameters.build >>
|
||||
steps:
|
||||
- move_and_store_all_artifacts
|
||||
- run:
|
||||
name: Remove the big things on macOS, this seems to be better on average
|
||||
command: |
|
||||
if [ "`uname`" == "Darwin" ]; then
|
||||
mkdir -p src/out/Default
|
||||
cd src/out/Default
|
||||
find . -type f -size +50M -delete
|
||||
mkdir -p gen/electron
|
||||
cd gen/electron
|
||||
# These files do not seem to like being in a cache, let us remove them
|
||||
find . -type f -name '*_pkg_info' -delete
|
||||
fi
|
||||
- when:
|
||||
condition: << parameters.use-out-cache >>
|
||||
steps:
|
||||
- *step-save-out-cache
|
||||
|
||||
- *step-maybe-notify-slack-failure
|
||||
|
||||
@@ -1642,7 +1628,6 @@ jobs:
|
||||
persist: true
|
||||
checkout: false
|
||||
checkout-and-assume-cache: true
|
||||
use-out-cache: false
|
||||
|
||||
linux-x64-testing-asan:
|
||||
executor:
|
||||
@@ -1659,7 +1644,6 @@ jobs:
|
||||
- electron-build:
|
||||
persist: true
|
||||
checkout: true
|
||||
use-out-cache: false
|
||||
build-nonproprietary-ffmpeg: false
|
||||
|
||||
linux-x64-testing-no-run-as-node:
|
||||
@@ -1676,7 +1660,6 @@ jobs:
|
||||
- electron-build:
|
||||
persist: false
|
||||
checkout: true
|
||||
use-out-cache: false
|
||||
|
||||
linux-x64-testing-gn-check:
|
||||
executor:
|
||||
@@ -1727,7 +1710,6 @@ jobs:
|
||||
persist: true
|
||||
checkout: false
|
||||
checkout-and-assume-cache: true
|
||||
use-out-cache: false
|
||||
|
||||
linux-arm-publish:
|
||||
executor:
|
||||
@@ -1770,7 +1752,6 @@ jobs:
|
||||
persist: true
|
||||
checkout: false
|
||||
checkout-and-assume-cache: true
|
||||
use-out-cache: false
|
||||
|
||||
linux-arm64-testing-gn-check:
|
||||
executor:
|
||||
@@ -2234,3 +2215,5 @@ workflows:
|
||||
lint:
|
||||
jobs:
|
||||
- lint
|
||||
|
||||
# VS Code Extension Version: 1.5.1
|
||||
178
.github/workflows/electron_woa_testing.yml
vendored
178
.github/workflows/electron_woa_testing.yml
vendored
@@ -1,178 +0,0 @@
|
||||
name: Electron WOA Testing
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: '**'
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
appveyor_job_id:
|
||||
description: 'Job Id of Appveyor WOA job to test'
|
||||
type: text
|
||||
required: true
|
||||
|
||||
jobs:
|
||||
electron-woa-init:
|
||||
if: ${{ github.event_name == 'push' && github.repository == 'electron/electron' }}
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Dummy step for push event
|
||||
run: |
|
||||
echo "This job is a needed initialization step for Electron WOA testing. Another test result will appear once the electron-woa-testing build is done."
|
||||
|
||||
electron-woa-testing:
|
||||
if: ${{ github.event_name == 'workflow_dispatch' && github.repository == 'electron/electron' }}
|
||||
runs-on: [self-hosted, woa]
|
||||
permissions:
|
||||
checks: write
|
||||
pull-requests: write
|
||||
steps:
|
||||
- uses: LouisBrunner/checks-action@v1.1.1
|
||||
with:
|
||||
token: ${{ secrets.GITHUB_TOKEN }}
|
||||
name: electron-woa-testing
|
||||
status: in_progress
|
||||
details_url: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}
|
||||
output: |
|
||||
{"summary":"Test In Progress","text_description":"See job details here: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}"}
|
||||
- name: Clean Workspace
|
||||
run: |
|
||||
Remove-Item * -Recurse -Force
|
||||
shell: powershell
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v3
|
||||
with:
|
||||
path: src\electron
|
||||
fetch-depth: 0
|
||||
- name: Yarn install
|
||||
run: |
|
||||
cd src\electron
|
||||
node script/yarn.js install --frozen-lockfile
|
||||
- name: Download and extract dist.zip for test
|
||||
run: |
|
||||
$localArtifactPath = "$pwd\dist.zip"
|
||||
$serverArtifactPath = "https://ci.appveyor.com/api/buildjobs/${{ inputs.appveyor_job_id }}/artifacts/dist.zip"
|
||||
Invoke-RestMethod -Method Get -Uri $serverArtifactPath -OutFile $localArtifactPath -Headers @{ "Authorization" = "Bearer ${{ secrets.APPVEYOR_TOKEN }}" }
|
||||
& "${env:ProgramFiles(x86)}\7-Zip\7z.exe" x -osrc\out\Default -y $localArtifactPath
|
||||
shell: powershell
|
||||
- name: Download and extract native test executables for test
|
||||
run: |
|
||||
$localArtifactPath = "src\out\Default\shell_browser_ui_unittests.exe"
|
||||
$serverArtifactPath = "https://ci.appveyor.com/api/buildjobs/${{ inputs.appveyor_job_id }}/artifacts/shell_browser_ui_unittests.exe"
|
||||
Invoke-RestMethod -Method Get -Uri $serverArtifactPath -OutFile $localArtifactPath -Headers @{ "Authorization" = "Bearer ${{ secrets.APPVEYOR_TOKEN }}" }
|
||||
shell: powershell
|
||||
- name: Download and extract ffmpeg.zip for test
|
||||
run: |
|
||||
$localArtifactPath = "$pwd\ffmpeg.zip"
|
||||
$serverArtifactPath = "https://ci.appveyor.com/api/buildjobs/${{ inputs.appveyor_job_id }}/artifacts/ffmpeg.zip"
|
||||
Invoke-RestMethod -Method Get -Uri $serverArtifactPath -OutFile $localArtifactPath -Headers @{ "Authorization" = "Bearer ${{ secrets.APPVEYOR_TOKEN }}" }
|
||||
& "${env:ProgramFiles(x86)}\7-Zip\7z.exe" x -osrc\out\ffmpeg $localArtifactPath
|
||||
shell: powershell
|
||||
- name: Download node headers for test
|
||||
run: |
|
||||
$localArtifactPath = "src\node_headers.zip"
|
||||
$serverArtifactPath = "https://ci.appveyor.com/api/buildjobs/${{ inputs.appveyor_job_id }}/artifacts/node_headers.zip"
|
||||
Invoke-RestMethod -Method Get -Uri $serverArtifactPath -OutFile $localArtifactPath -Headers @{ "Authorization" = "Bearer ${{ secrets.APPVEYOR_TOKEN }}" }
|
||||
cd src
|
||||
& "${env:ProgramFiles(x86)}\7-Zip\7z.exe" x -y node_headers.zip
|
||||
shell: powershell
|
||||
- name: Download electron.lib for test
|
||||
run: |
|
||||
$localArtifactPath = "src\out\Default\electron.lib"
|
||||
$serverArtifactPath = "https://ci.appveyor.com/api/buildjobs/${{ inputs.appveyor_job_id }}/artifacts/electron.lib"
|
||||
Invoke-RestMethod -Method Get -Uri $serverArtifactPath -OutFile $localArtifactPath -Headers @{ "Authorization" = "Bearer ${{ secrets.APPVEYOR_TOKEN }}" }
|
||||
shell: powershell
|
||||
# Uncomment the following block if pdb files are needed to debug issues
|
||||
# - name: Download pdb files for detailed stacktraces
|
||||
# if: ${{ github.event_name == 'workflow_dispatch' }}
|
||||
# run: |
|
||||
# try {
|
||||
# $localArtifactPath = "src\pdb.zip"
|
||||
# $serverArtifactPath = "https://ci.appveyor.com/api/buildjobs/${{ inputs.appveyor_job_id }}/artifacts/pdb.zip"
|
||||
# Invoke-RestMethod -Method Get -Uri $serverArtifactPath -OutFile $localArtifactPath -Headers @{ "Authorization" = "Bearer ${{ secrets.APPVEYOR_TOKEN }}" }
|
||||
# cd src
|
||||
# & "${env:ProgramFiles(x86)}\7-Zip\7z.exe" x -y pdb.zip
|
||||
# } catch {
|
||||
# Write-Host "There was an exception encountered while downloading pdb files:" $_.Exception.Message
|
||||
# } finally {
|
||||
# $global:LASTEXITCODE = 0
|
||||
# }
|
||||
# shell: powershell
|
||||
- name: Setup node headers
|
||||
run: |
|
||||
New-Item src\out\Default\gen\node_headers\Release -Type directory
|
||||
Copy-Item -path src\out\Default\electron.lib -destination src\out\Default\gen\node_headers\Release\node.lib
|
||||
shell: powershell
|
||||
- name: Run Electron Main process tests
|
||||
run: |
|
||||
cd src
|
||||
set npm_config_nodedir=%cd%\out\Default\gen\node_headers
|
||||
set npm_config_arch=arm64
|
||||
cd electron
|
||||
node script/yarn test --runners=main --enable-logging --disable-features=CalculateNativeWinOcclusion
|
||||
env:
|
||||
ELECTRON_ENABLE_STACK_DUMPING: true
|
||||
ELECTRON_OUT_DIR: Default
|
||||
IGNORE_YARN_INSTALL_ERROR: 1
|
||||
ELECTRON_TEST_RESULTS_DIR: junit
|
||||
MOCHA_MULTI_REPORTERS: 'mocha-junit-reporter, tap'
|
||||
MOCHA_REPORTER: mocha-multi-reporters
|
||||
ELECTRON_SKIP_NATIVE_MODULE_TESTS: true
|
||||
- name: Run Electron Remote based tests
|
||||
if: ${{ success() || failure() }}
|
||||
run: |
|
||||
cd src
|
||||
set npm_config_nodedir=%cd%\out\Default\gen\node_headers
|
||||
set npm_config_arch=arm64
|
||||
cd electron
|
||||
node script/yarn test --runners=remote --enable-logging --disable-features=CalculateNativeWinOcclusion
|
||||
env:
|
||||
ELECTRON_OUT_DIR: Default
|
||||
IGNORE_YARN_INSTALL_ERROR: 1
|
||||
ELECTRON_TEST_RESULTS_DIR: junit
|
||||
MOCHA_MULTI_REPORTERS: 'mocha-junit-reporter, tap'
|
||||
MOCHA_REPORTER: mocha-multi-reporters
|
||||
ELECTRON_SKIP_NATIVE_MODULE_TESTS: true
|
||||
- name: Verify ffmpeg
|
||||
run: |
|
||||
cd src
|
||||
echo "Verifying non proprietary ffmpeg"
|
||||
python electron\script\verify-ffmpeg.py --build-dir out\Default --source-root %cd% --ffmpeg-path out\ffmpeg
|
||||
shell: cmd
|
||||
- name: Kill processes left running from last test run
|
||||
if: ${{ always() }}
|
||||
run: |
|
||||
Get-Process | Where Name -Like "electron*" | Stop-Process
|
||||
Get-Process | Where Name -Like "msedge*" | Stop-Process
|
||||
shell: powershell
|
||||
- name: Delete user app data directories
|
||||
if: ${{ always() }}
|
||||
run: |
|
||||
Remove-Item -path $env:APPDATA/Electron* -Recurse -Force -ErrorAction Ignore
|
||||
shell: powershell
|
||||
- uses: LouisBrunner/checks-action@v1.1.1
|
||||
if: ${{ success() }}
|
||||
with:
|
||||
token: ${{ secrets.GITHUB_TOKEN }}
|
||||
name: electron-woa-testing
|
||||
conclusion: "${{ job.status }}"
|
||||
details_url: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}
|
||||
output: |
|
||||
{"summary":"${{ job.status }}","text_description":"See job details here: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}"}
|
||||
- uses: LouisBrunner/checks-action@v1.1.1
|
||||
if: ${{ success() }}
|
||||
with:
|
||||
token: ${{ secrets.GITHUB_TOKEN }}
|
||||
name: electron-woa-testing
|
||||
conclusion: "${{ job.status }}"
|
||||
details_url: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}
|
||||
output: |
|
||||
{"summary":"Job Succeeded","text_description":"See job details here: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}"}
|
||||
- uses: LouisBrunner/checks-action@v1.1.1
|
||||
if: ${{ ! success() }}
|
||||
with:
|
||||
token: ${{ secrets.GITHUB_TOKEN }}
|
||||
name: electron-woa-testing
|
||||
conclusion: "${{ job.status }}"
|
||||
details_url: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}
|
||||
output: |
|
||||
{"summary":"Job Failed","text_description":"See job details here: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}"}
|
||||
62
.github/workflows/update_appveyor_image.yml
vendored
Normal file
62
.github/workflows/update_appveyor_image.yml
vendored
Normal file
@@ -0,0 +1,62 @@
|
||||
name: Update AppVeyor Image
|
||||
|
||||
# Run chron daily Mon-Fri
|
||||
on:
|
||||
schedule:
|
||||
- cron: '0 8 * * 1-5' # runs 8:00 every business day (see https://crontab.guru)
|
||||
|
||||
permissions:
|
||||
contents: write
|
||||
pull-requests: write
|
||||
|
||||
jobs:
|
||||
bake-appveyor-image:
|
||||
name: Bake AppVeyor Image
|
||||
permissions:
|
||||
contents: write
|
||||
pull-requests: write # to create a new PR with updated Appveyor images
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v3
|
||||
with:
|
||||
fetch-depth: 0
|
||||
- name: Yarn install
|
||||
run: |
|
||||
node script/yarn.js install --frozen-lockfile
|
||||
- name: Set Repo for Commit
|
||||
run: git config --global --add safe.directory $GITHUB_WORKSPACE
|
||||
- name: Check AppVeyor Image
|
||||
env:
|
||||
APPVEYOR_TOKEN: ${{ secrets.APPVEYOR_TOKEN }}
|
||||
run: |
|
||||
node ./script/prepare-appveyor
|
||||
if [ -f ./image_version.txt ]; then
|
||||
echo "APPVEYOR_IMAGE_VERSION="$(cat image_version.txt)"" >> $GITHUB_ENV
|
||||
rm image_version.txt
|
||||
fi
|
||||
- name: (Optionally) Update Appveyor Image
|
||||
if: ${{ env.APPVEYOR_IMAGE_VERSION }}
|
||||
uses: mikefarah/yq@v4.27.2
|
||||
with:
|
||||
cmd: yq '.image = "${{ env.APPVEYOR_IMAGE_VERSION }}"' "appveyor.yml" > "appveyor2.yml"
|
||||
- name: (Optionally) Generate Commit Diff
|
||||
if: ${{ env.APPVEYOR_IMAGE_VERSION }}
|
||||
run: |
|
||||
diff -w -B appveyor.yml appveyor2.yml > appveyor.diff || true
|
||||
patch -f appveyor.yml < appveyor.diff
|
||||
rm appveyor2.yml appveyor.diff
|
||||
- name: (Optionally) Commit and Pull Request
|
||||
if: ${{ env.APPVEYOR_IMAGE_VERSION }}
|
||||
uses: peter-evans/create-pull-request@v4
|
||||
with:
|
||||
token: ${{ secrets.ACTIONS_GITHUB_TOKEN }}
|
||||
commit-message: 'build: update appveyor image to latest version'
|
||||
committer: GitHub <noreply@github.com>
|
||||
author: ${{ github.actor }} <${{ github.actor }}@users.noreply.github.com>
|
||||
signoff: false
|
||||
branch: bump-appveyor-image
|
||||
delete-branch: true
|
||||
title: 'build: update appveyor image to latest version'
|
||||
body: |
|
||||
This PR updates appveyor.yml to the latest baked image, ${{ env.APPVEYOR_IMAGE_VERSION }}.
|
||||
73
BUILD.gn
73
BUILD.gn
@@ -107,6 +107,14 @@ branding = read_file("shell/app/BRANDING.json", "json")
|
||||
electron_project_name = branding.project_name
|
||||
electron_product_name = branding.product_name
|
||||
electron_mac_bundle_id = branding.mac_bundle_id
|
||||
electron_version = exec_script("script/print-version.py",
|
||||
[],
|
||||
"trim string",
|
||||
[
|
||||
".git/packed-refs",
|
||||
".git/HEAD",
|
||||
"script/lib/get-version.js",
|
||||
])
|
||||
|
||||
if (is_mas_build) {
|
||||
assert(is_mac,
|
||||
@@ -302,12 +310,9 @@ npm_action("electron_version_args") {
|
||||
|
||||
outputs = [ "$target_gen_dir/electron_version.args" ]
|
||||
|
||||
args = rebase_path(outputs)
|
||||
args = rebase_path(outputs) + [ "$electron_version" ]
|
||||
|
||||
inputs = [
|
||||
"ELECTRON_VERSION",
|
||||
"script/generate-version-json.js",
|
||||
]
|
||||
inputs = [ "script/generate-version-json.js" ]
|
||||
}
|
||||
|
||||
templated_file("electron_version_header") {
|
||||
@@ -319,6 +324,39 @@ templated_file("electron_version_header") {
|
||||
args_files = get_target_outputs(":electron_version_args")
|
||||
}
|
||||
|
||||
templated_file("electron_win_rc") {
|
||||
deps = [ ":electron_version_args" ]
|
||||
|
||||
template = "build/templates/electron_rc.tmpl"
|
||||
output = "$target_gen_dir/win-resources/electron.rc"
|
||||
|
||||
args_files = get_target_outputs(":electron_version_args")
|
||||
}
|
||||
|
||||
copy("electron_win_resource_files") {
|
||||
sources = [
|
||||
"shell/browser/resources/win/electron.ico",
|
||||
"shell/browser/resources/win/resource.h",
|
||||
]
|
||||
outputs = [ "$target_gen_dir/win-resources/{{source_file_part}}" ]
|
||||
}
|
||||
|
||||
templated_file("electron_version_file") {
|
||||
deps = [ ":electron_version_args" ]
|
||||
|
||||
template = "build/templates/version_string.tmpl"
|
||||
output = "$root_build_dir/version"
|
||||
|
||||
args_files = get_target_outputs(":electron_version_args")
|
||||
}
|
||||
|
||||
group("electron_win32_resources") {
|
||||
public_deps = [
|
||||
":electron_win_rc",
|
||||
":electron_win_resource_files",
|
||||
]
|
||||
}
|
||||
|
||||
action("electron_fuses") {
|
||||
script = "build/fuses/build.py"
|
||||
|
||||
@@ -404,9 +442,6 @@ source_set("electron_lib") {
|
||||
"//media/mojo/mojom",
|
||||
"//net:extras",
|
||||
"//net:net_resources",
|
||||
"//ppapi/host",
|
||||
"//ppapi/proxy",
|
||||
"//ppapi/shared_impl",
|
||||
"//printing/buildflags",
|
||||
"//services/device/public/cpp/geolocation",
|
||||
"//services/device/public/cpp/hid",
|
||||
@@ -620,11 +655,21 @@ source_set("electron_lib") {
|
||||
if (enable_plugins) {
|
||||
deps += [ "chromium_src:plugins" ]
|
||||
sources += [
|
||||
"shell/renderer/electron_renderer_pepper_host_factory.cc",
|
||||
"shell/renderer/electron_renderer_pepper_host_factory.h",
|
||||
"shell/renderer/pepper_helper.cc",
|
||||
"shell/renderer/pepper_helper.h",
|
||||
]
|
||||
}
|
||||
|
||||
if (enable_ppapi) {
|
||||
deps += [
|
||||
"//ppapi/host",
|
||||
"//ppapi/proxy",
|
||||
"//ppapi/shared_impl",
|
||||
]
|
||||
}
|
||||
|
||||
if (enable_run_as_node) {
|
||||
sources += [
|
||||
"shell/app/node_main.cc",
|
||||
@@ -750,7 +795,6 @@ if (is_mac) {
|
||||
electron_helper_name = "$electron_product_name Helper"
|
||||
electron_login_helper_name = "$electron_product_name Login Helper"
|
||||
electron_framework_version = "A"
|
||||
electron_version = read_file("ELECTRON_VERSION", "trim string")
|
||||
|
||||
mac_xib_bundle_data("electron_xibs") {
|
||||
sources = [ "shell/common/resources/mac/MainMenu.xib" ]
|
||||
@@ -1191,6 +1235,7 @@ if (is_mac) {
|
||||
":default_app_asar",
|
||||
":electron_app_manifest",
|
||||
":electron_lib",
|
||||
":electron_win32_resources",
|
||||
":packed_resources",
|
||||
"//components/crash/core/app",
|
||||
"//content:sandbox_helper_win",
|
||||
@@ -1224,8 +1269,7 @@ if (is_mac) {
|
||||
|
||||
if (is_win) {
|
||||
sources += [
|
||||
# TODO: we should be generating our .rc files more like how chrome does
|
||||
"shell/browser/resources/win/electron.rc",
|
||||
"$target_gen_dir/win-resources/electron.rc",
|
||||
"shell/browser/resources/win/resource.h",
|
||||
]
|
||||
|
||||
@@ -1407,15 +1451,10 @@ group("licenses") {
|
||||
]
|
||||
}
|
||||
|
||||
copy("electron_version") {
|
||||
sources = [ "ELECTRON_VERSION" ]
|
||||
outputs = [ "$root_build_dir/version" ]
|
||||
}
|
||||
|
||||
dist_zip("electron_dist_zip") {
|
||||
data_deps = [
|
||||
":electron_app",
|
||||
":electron_version",
|
||||
":electron_version_file",
|
||||
":licenses",
|
||||
]
|
||||
if (is_linux) {
|
||||
|
||||
2
DEPS
2
DEPS
@@ -2,7 +2,7 @@ gclient_gn_args_from = 'src'
|
||||
|
||||
vars = {
|
||||
'chromium_version':
|
||||
'106.0.5249.91',
|
||||
'106.0.5249.199',
|
||||
'node_version':
|
||||
'v16.16.0',
|
||||
'nan_version':
|
||||
|
||||
@@ -1 +0,0 @@
|
||||
21.1.0
|
||||
2
README.md
Executable file → Normal file
2
README.md
Executable file → Normal file
@@ -12,7 +12,7 @@ using JavaScript, HTML and CSS. It is based on [Node.js](https://nodejs.org/) an
|
||||
[Chromium](https://www.chromium.org) and is used by the [Atom
|
||||
editor](https://github.com/atom/atom) and many other [apps](https://electronjs.org/apps).
|
||||
|
||||
Follow [@ElectronJS](https://twitter.com/electronjs) on Twitter for important
|
||||
Follow [@electronjs](https://twitter.com/electronjs) on Twitter for important
|
||||
announcements.
|
||||
|
||||
This project adheres to the Contributor Covenant
|
||||
|
||||
107
appveyor-bake.yml
Normal file
107
appveyor-bake.yml
Normal file
@@ -0,0 +1,107 @@
|
||||
# The config is used to bake appveyor images, not for running CI jobs.
|
||||
# The config expects the following environment variables to be set:
|
||||
# - "APPVEYOR_BAKE_IMAGE" e.g. 'electron-99.0.4767.0'. Name of the image to be baked.
|
||||
# Typically named after the Chromium version on which the image is built.
|
||||
# This can be set dynamically in the prepare-appveyor script.
|
||||
|
||||
version: 1.0.{build}
|
||||
build_cloud: electronhq-16-core
|
||||
image: e-111.0.5560.0-2
|
||||
environment:
|
||||
GIT_CACHE_PATH: C:\Users\appveyor\libcc_cache
|
||||
ELECTRON_OUT_DIR: Default
|
||||
ELECTRON_ENABLE_STACK_DUMPING: 1
|
||||
MOCHA_REPORTER: mocha-multi-reporters
|
||||
MOCHA_MULTI_REPORTERS: mocha-appveyor-reporter, tap
|
||||
GOMA_FALLBACK_ON_AUTH_FAILURE: true
|
||||
DEPOT_TOOLS_WIN_TOOLCHAIN: 0
|
||||
PYTHONIOENCODING: UTF-8
|
||||
|
||||
# The following lines are needed when baking from a completely new image (eg MicrosoftWindowsServer:WindowsServer:2019-Datacenter:latest via image: base-windows-server2019)
|
||||
# init:
|
||||
# - ps: $blockRdp = $true; iex ((new-object net.webclient).DownloadString('https://raw.githubusercontent.com/appveyor/ci/master/scripts/enable-rdp.ps1'))
|
||||
# - appveyor version
|
||||
# - ps: $ErrorActionPreference = 'Stop'
|
||||
# - ps: 'Write-Host "OS Build: $((Get-CimInstance Win32_OperatingSystem).BuildNumber)"'
|
||||
|
||||
# clone_folder: '%USERPROFILE%\image-bake-scripts'
|
||||
|
||||
# clone_script:
|
||||
# - ps: Invoke-WebRequest "https://github.com/appveyor/build-images/archive/1f90d94e74c8243c909a09b994e527584dfcb838.zip" -OutFile "$env:temp\scripts.zip"
|
||||
# - ps: Expand-Archive -Path "$env:temp\scripts.zip" -DestinationPath "$env:temp\scripts" -Force
|
||||
# - ps: Copy-Item -Path "$env:temp\scripts\build-images-1f90d94e74c8243c909a09b994e527584dfcb838\scripts\Windows\*" -Destination $env:APPVEYOR_BUILD_FOLDER -Recurse
|
||||
|
||||
build_script:
|
||||
# The following lines are needed when baking from a completely new image (eg MicrosoftWindowsServer:WindowsServer:2019-Datacenter:latest via image: base-windows-server2019)
|
||||
# - ps: .\init_server.ps1
|
||||
# - ps: .\extend_system_volume.ps1
|
||||
|
||||
# # Restart VM
|
||||
# - ps: Start-Sleep -s 5; Restart-Computer
|
||||
# - ps: Start-Sleep -s 5
|
||||
|
||||
# - appveyor version
|
||||
# - ps: .\install_path_utils.ps1
|
||||
# - ps: .\install_powershell_core.ps1
|
||||
# - ps: .\install_powershell_get.ps1
|
||||
# - ps: .\install_7zip.ps1
|
||||
# - ps: .\install_chocolatey.ps1
|
||||
# - ps: .\install_webpi.ps1
|
||||
# - ps: .\install_nuget.ps1
|
||||
# - ps: .\install_pstools.ps1
|
||||
|
||||
# - ps: .\install_git.ps1
|
||||
# - ps: .\install_git_lfs.ps1
|
||||
|
||||
# # Restart VM
|
||||
# - ps: Start-Sleep -s 5; Restart-Computer
|
||||
# - ps: Start-Sleep -s 5
|
||||
# END LINES FOR COMPLETELY NEW IMAGE
|
||||
|
||||
- git config --global core.longpaths true
|
||||
- ps: >-
|
||||
if (-not (Test-Path -Path C:\projects\src)) {
|
||||
New-Item -Path C:\projects\src -ItemType Directory
|
||||
}
|
||||
- cd C:\projects\
|
||||
- git clone -q --branch=%APPVEYOR_REPO_BRANCH% https://github.com/electron/electron.git C:\projects\src\electron
|
||||
- git clone --depth=1 https://chromium.googlesource.com/chromium/tools/depot_tools.git
|
||||
- ps: $env:PATH="$pwd\depot_tools;$env:PATH"
|
||||
- update_depot_tools.bat
|
||||
# Uncomment the following line if windows deps change
|
||||
# - src\electron\script\setup-win-for-dev.bat
|
||||
- >-
|
||||
gclient config
|
||||
--name "src\electron"
|
||||
--unmanaged
|
||||
%GCLIENT_EXTRA_ARGS%
|
||||
"https://github.com/electron/electron"
|
||||
- ps: cd src\electron
|
||||
- ps: node script\generate-deps-hash.js
|
||||
- ps: $depshash = Get-Content .\.depshash -Raw
|
||||
- ps: Copy-Item -path .\.depshash -destination ..\.depshash
|
||||
- ps: cd ..\..
|
||||
- gclient sync --with_branch_heads --with_tags --nohooks
|
||||
- ps: regsvr32 /s "C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\DIA SDK\bin\amd64\msdia140.dll"
|
||||
|
||||
# The following lines are needed when baking from a completely new image (eg MicrosoftWindowsServer:WindowsServer:2019-Datacenter:latest via image: base-windows-server2019)
|
||||
# # Restart VM
|
||||
# - ps: Start-Sleep -s 5; Restart-Computer
|
||||
# - ps: Start-Sleep -s 5
|
||||
|
||||
# - cd %USERPROFILE%\image-bake-scripts
|
||||
# - appveyor version
|
||||
# - ps: .\optimize_dotnet_runtime.ps1
|
||||
# - ps: .\disable_windows_background_services.ps1
|
||||
# - ps: .\enforce_windows_firewall.ps1
|
||||
# - ps: .\cleanup_windows.ps1
|
||||
# END LINES FOR COMPLETELY NEW IMAGE
|
||||
on_image_bake:
|
||||
- ps: >-
|
||||
echo "Baking image: $env:APPVEYOR_BAKE_IMAGE at dir $PWD"
|
||||
- ps: Remove-Item -Recurse -Force C:\projects\depot_tools
|
||||
- ps: Remove-Item -Recurse -Force C:\projects\src\electron
|
||||
# Uncomment these lines and set APPVEYOR_RDP_PASSWORD in project settings to enable RDP after bake is done
|
||||
# # on_finish:
|
||||
# - ps: >-
|
||||
# $blockRdp = $true; iex ((new-object net.webclient).DownloadString('https://raw.githubusercontent.com/appveyor/ci/master/scripts/enable-rdp.ps1'))
|
||||
286
appveyor-woa.yml
Normal file
286
appveyor-woa.yml
Normal file
@@ -0,0 +1,286 @@
|
||||
# NOTE IF CHANGING THIS FILE, ALSO APPLY THE CHANGE TO appveyor.yml
|
||||
# IF APPLICABLE!!!!
|
||||
#
|
||||
#
|
||||
# The config expects the following environment variables to be set:
|
||||
# - "GN_CONFIG" Build type. One of {'testing', 'release'}.
|
||||
# - "GN_EXTRA_ARGS" Additional gn arguments for a build config,
|
||||
# e.g. 'target_cpu="x86"' to build for a 32bit platform.
|
||||
# https://gn.googlesource.com/gn/+/master/docs/reference.md#target_cpu
|
||||
# Don't forget to set up "NPM_CONFIG_ARCH" and "TARGET_ARCH" accordingly
|
||||
# if you pass a custom value for 'target_cpu'.
|
||||
# - "ELECTRON_RELEASE" Set it to '1' upload binaries on success.
|
||||
# - "NPM_CONFIG_ARCH" E.g. 'x86'. Is used to build native Node.js modules.
|
||||
# Must match 'target_cpu' passed to "GN_EXTRA_ARGS" and "TARGET_ARCH" value.
|
||||
# - "TARGET_ARCH" Choose from {'ia32', 'x64', 'arm', 'arm64', 'mips64el'}.
|
||||
# Is used in some publishing scripts, but does NOT affect the Electron binary.
|
||||
# Must match 'target_cpu' passed to "GN_EXTRA_ARGS" and "NPM_CONFIG_ARCH" value.
|
||||
# - "UPLOAD_TO_STORAGE" Set it to '1' upload a release to the Azure bucket.
|
||||
# Otherwise the release will be uploaded to the GitHub Releases.
|
||||
# (The value is only checked if "ELECTRON_RELEASE" is defined.)
|
||||
#
|
||||
# The publishing scripts expect access tokens to be defined as env vars,
|
||||
# but those are not covered here.
|
||||
#
|
||||
# AppVeyor docs on variables:
|
||||
# https://www.appveyor.com/docs/environment-variables/
|
||||
# https://www.appveyor.com/docs/build-configuration/#secure-variables
|
||||
# https://www.appveyor.com/docs/build-configuration/#custom-environment-variables
|
||||
|
||||
version: 1.0.{build}
|
||||
build_cloud: electronhq-16-core
|
||||
image: e-106.0.5249.199-2
|
||||
environment:
|
||||
GIT_CACHE_PATH: C:\Users\appveyor\libcc_cache
|
||||
ELECTRON_OUT_DIR: Default
|
||||
ELECTRON_ENABLE_STACK_DUMPING: 1
|
||||
ELECTRON_ALSO_LOG_TO_STDERR: 1
|
||||
MOCHA_REPORTER: mocha-multi-reporters
|
||||
MOCHA_MULTI_REPORTERS: mocha-appveyor-reporter, tap
|
||||
GOMA_FALLBACK_ON_AUTH_FAILURE: true
|
||||
DEPOT_TOOLS_WIN_TOOLCHAIN: 0
|
||||
PYTHONIOENCODING: UTF-8
|
||||
|
||||
matrix:
|
||||
|
||||
- job_name: Build Arm on X64 Windows
|
||||
- job_name: Test On Windows On Arm Hardware
|
||||
job_depends_on: Build Arm on X64 Windows
|
||||
APPVEYOR_BUILD_WORKER_IMAGE: base-woa
|
||||
APPVEYOR_BUILD_WORKER_CLOUD: electronhq-woa
|
||||
|
||||
clone_folder: C:\projects\src\electron
|
||||
|
||||
skip_branch_with_pr: true
|
||||
|
||||
# the first failed job cancels other jobs and fails entire build
|
||||
matrix:
|
||||
fast_finish: true
|
||||
|
||||
for:
|
||||
|
||||
- matrix:
|
||||
only:
|
||||
- job_name: Build Arm on X64 Windows
|
||||
|
||||
build_script:
|
||||
- ps: |
|
||||
node script/yarn.js install --frozen-lockfile
|
||||
node script/doc-only-change.js --prNumber=$env:APPVEYOR_PULL_REQUEST_NUMBER --prBranch=$env:APPVEYOR_REPO_BRANCH
|
||||
if ($LASTEXITCODE -eq 0) {
|
||||
Write-warning "Skipping build for doc only change"; Exit-AppveyorBuild
|
||||
}
|
||||
$global:LASTEXITCODE = 0
|
||||
- cd ..
|
||||
- ps: Write-Host "Building $env:GN_CONFIG build"
|
||||
- git config --global core.longpaths true
|
||||
- ps: >-
|
||||
if (Test-Path -Path "$pwd\depot_tools") {
|
||||
Remove-Item -Recurse -Force $pwd\depot_tools
|
||||
}
|
||||
- ps: >-
|
||||
if (Test-Path -Path "$pwd\build-tools") {
|
||||
Remove-Item -Recurse -Force $pwd\build-tools
|
||||
}
|
||||
- git clone --depth=1 https://chromium.googlesource.com/chromium/tools/depot_tools.git
|
||||
- ps: |
|
||||
cd depot_tools
|
||||
git fetch --depth 1 origin b7d8efd8bee494f4cfacacc19cf50fc4d4be3900
|
||||
git checkout b7d8efd8bee494f4cfacacc19cf50fc4d4be3900
|
||||
New-Item -Name .disable_auto_update -ItemType File
|
||||
bootstrap\win_tools.bat
|
||||
cd ..
|
||||
- ps: $env:PATH="$pwd\depot_tools;$env:PATH"
|
||||
- ps: >-
|
||||
if (Test-Path -Path "$pwd\src\electron") {
|
||||
Remove-Item -Recurse -Force $pwd\src\electron
|
||||
}
|
||||
- ps: >-
|
||||
if (Test-Path 'env:RAW_GOMA_AUTH') {
|
||||
$env:GOMA_OAUTH2_CONFIG_FILE = "$pwd\.goma_oauth2_config"
|
||||
$env:RAW_GOMA_AUTH | Set-Content $env:GOMA_OAUTH2_CONFIG_FILE
|
||||
}
|
||||
- git clone https://github.com/electron/build-tools.git
|
||||
- cd build-tools
|
||||
- npm install
|
||||
- mkdir third_party
|
||||
- ps: >-
|
||||
node -e "require('./src/utils/goma.js').downloadAndPrepare({ gomaOneForAll: true })"
|
||||
- ps: $env:GN_GOMA_FILE = node -e "console.log(require('./src/utils/goma.js').gnFilePath)"
|
||||
- ps: $env:LOCAL_GOMA_DIR = node -e "console.log(require('./src/utils/goma.js').dir)"
|
||||
- cd ..\..
|
||||
- ps: .\src\electron\script\start-goma.ps1 -gomaDir $env:LOCAL_GOMA_DIR
|
||||
- ps: >-
|
||||
if (Test-Path 'env:RAW_GOMA_AUTH') {
|
||||
$goma_login = python $env:LOCAL_GOMA_DIR\goma_auth.py info
|
||||
if ($goma_login -eq 'Login as Fermi Planck') {
|
||||
Write-warning "Goma authentication is correct";
|
||||
} else {
|
||||
Write-warning "WARNING!!!!!! Goma authentication is incorrect; please update Goma auth token.";
|
||||
$host.SetShouldExit(1)
|
||||
}
|
||||
}
|
||||
- ps: $env:CHROMIUM_BUILDTOOLS_PATH="$pwd\src\buildtools"
|
||||
- ps: >-
|
||||
if ($env:GN_CONFIG -ne 'release') {
|
||||
$env:NINJA_STATUS="[%r processes, %f/%t @ %o/s : %es] "
|
||||
}
|
||||
- gclient config --name "src\electron" --unmanaged %GCLIENT_EXTRA_ARGS% "https://github.com/electron/electron"
|
||||
# Patches are applied in the image bake. Check depshash to see if patches have changed.
|
||||
- ps: $env:RUN_GCLIENT_SYNC="false"
|
||||
- ps: $depshash_baked = Get-Content .\src\.depshash -Raw
|
||||
- ps: cd src\electron
|
||||
- ps: node script\generate-deps-hash.js
|
||||
- ps: $depshash = Get-Content .\.depshash -Raw
|
||||
- ps: cd ..\..
|
||||
- ps: >-
|
||||
if ($depshash_baked -ne $depshash) {
|
||||
$env:RUN_GCLIENT_SYNC="true"
|
||||
}
|
||||
- if "%RUN_GCLIENT_SYNC%"=="true" ( gclient sync --with_branch_heads --with_tags ) else ( gclient runhooks )
|
||||
- cd src
|
||||
- ps: $env:PATH="$pwd\third_party\ninja;$env:PATH"
|
||||
- set BUILD_CONFIG_PATH=//electron/build/args/%GN_CONFIG%.gn
|
||||
- gn gen out/Default "--args=import(\"%BUILD_CONFIG_PATH%\") import(\"%GN_GOMA_FILE%\") %GN_EXTRA_ARGS% "
|
||||
- gn check out/Default //electron:electron_lib
|
||||
- gn check out/Default //electron:electron_app
|
||||
- gn check out/Default //electron/shell/common/api:mojo
|
||||
- if DEFINED GN_GOMA_FILE (ninja -j 300 -C out/Default electron:electron_app) else (ninja -C out/Default electron:electron_app)
|
||||
- if "%GN_CONFIG%"=="testing" ( python C:\depot_tools\post_build_ninja_summary.py -C out\Default )
|
||||
- gn gen out/ffmpeg "--args=import(\"//electron/build/args/ffmpeg.gn\") %GN_EXTRA_ARGS%"
|
||||
- ninja -C out/ffmpeg electron:electron_ffmpeg_zip
|
||||
- ninja -C out/Default electron:electron_dist_zip
|
||||
- ninja -C out/Default shell_browser_ui_unittests
|
||||
- gn desc out/Default v8:run_mksnapshot_default args > out/Default/default_mksnapshot_args
|
||||
# Remove unused args from mksnapshot_args
|
||||
- ps: >-
|
||||
Get-Content out/Default/default_mksnapshot_args | Where-Object { -not $_.Contains('--turbo-profiling-input') -And -not $_.Contains('builtins-pgo') } | Set-Content out/Default/mksnapshot_args
|
||||
- ninja -C out/Default electron:electron_mksnapshot_zip
|
||||
- cd out\Default
|
||||
- 7z a mksnapshot.zip mksnapshot_args gen\v8\embedded.S
|
||||
- cd ..\..
|
||||
- ninja -C out/Default electron:hunspell_dictionaries_zip
|
||||
- ninja -C out/Default electron:electron_chromedriver_zip
|
||||
- ninja -C out/Default third_party/electron_node:headers
|
||||
- python %LOCAL_GOMA_DIR%\goma_ctl.py stat
|
||||
- ps: >-
|
||||
Get-CimInstance -Namespace root\cimv2 -Class Win32_product | Select vendor, description, @{l='install_location';e='InstallLocation'}, @{l='install_date';e='InstallDate'}, @{l='install_date_2';e='InstallDate2'}, caption, version, name, @{l='sku_number';e='SKUNumber'} | ConvertTo-Json | Out-File -Encoding utf8 -FilePath .\installed_software.json
|
||||
- python3 electron/build/profile_toolchain.py --output-json=out/Default/windows_toolchain_profile.json
|
||||
- 7z a node_headers.zip out\Default\gen\node_headers
|
||||
- ps: >-
|
||||
if ($env:GN_CONFIG -eq 'release') {
|
||||
# Needed for msdia140.dll on 64-bit windows
|
||||
$env:Path += ";$pwd\third_party\llvm-build\Release+Asserts\bin"
|
||||
ninja -C out/Default electron:electron_symbols
|
||||
}
|
||||
- ps: >-
|
||||
if ($env:GN_CONFIG -eq 'release') {
|
||||
python3 electron\script\zip-symbols.py
|
||||
appveyor-retry appveyor PushArtifact out/Default/symbols.zip
|
||||
} else {
|
||||
# It's useful to have pdb files when debugging testing builds that are
|
||||
# built on CI.
|
||||
7z a pdb.zip out\Default\*.pdb
|
||||
}
|
||||
- python3 electron/script/zip_manifests/check-zip-manifest.py out/Default/dist.zip electron/script/zip_manifests/dist_zip.win.%TARGET_ARCH%.manifest
|
||||
|
||||
deploy_script:
|
||||
- cd electron
|
||||
- ps: >-
|
||||
if (Test-Path Env:\ELECTRON_RELEASE) {
|
||||
if (Test-Path Env:\UPLOAD_TO_STORAGE) {
|
||||
Write-Output "Uploading Electron release distribution to azure"
|
||||
& python3 script\release\uploaders\upload.py --verbose --upload_to_storage
|
||||
} else {
|
||||
Write-Output "Uploading Electron release distribution to github releases"
|
||||
& python3 script\release\uploaders\upload.py --verbose
|
||||
}
|
||||
}
|
||||
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: >-
|
||||
if ((Test-Path "pdb.zip") -And ($env:GN_CONFIG -ne 'release')) {
|
||||
appveyor-retry appveyor PushArtifact pdb.zip
|
||||
}
|
||||
- matrix:
|
||||
only:
|
||||
- job_name: Test On Windows On Arm Hardware
|
||||
|
||||
environment:
|
||||
IGNORE_YARN_INSTALL_ERROR: 1
|
||||
ELECTRON_TEST_RESULTS_DIR: junit
|
||||
MOCHA_MULTI_REPORTERS: 'mocha-junit-reporter, tap'
|
||||
MOCHA_REPORTER: mocha-multi-reporters
|
||||
ELECTRON_SKIP_NATIVE_MODULE_TESTS: true
|
||||
|
||||
build_script:
|
||||
- ps: |
|
||||
node script/yarn.js install --frozen-lockfile
|
||||
node script/doc-only-change.js --prNumber=$env:APPVEYOR_PULL_REQUEST_NUMBER --prBranch=$env:APPVEYOR_REPO_BRANCH
|
||||
if ($LASTEXITCODE -eq 0) {
|
||||
Write-warning "Skipping build for doc only change"; Exit-AppveyorBuild
|
||||
}
|
||||
$global:LASTEXITCODE = 0
|
||||
- cd ..
|
||||
- mkdir out\Default
|
||||
- cd ..
|
||||
- ps: |
|
||||
# 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')
|
||||
foreach ($job in $build_info.build.jobs) {
|
||||
if ($job.name -eq "Build Arm on X64 Windows") {
|
||||
$jobId = $job.jobId
|
||||
foreach($artifact_name in $artifacts_to_download) {
|
||||
if ($artifact_name -eq 'shell_browser_ui_unittests.exe' -Or $artifact_name -eq 'electron.lib') {
|
||||
$outfile = "src\out\Default\$artifact_name"
|
||||
} else {
|
||||
$outfile = $artifact_name
|
||||
}
|
||||
Invoke-RestMethod -Method Get -Uri "$apiUrl/buildjobs/$jobId/artifacts/$artifact_name" -OutFile $outfile
|
||||
}
|
||||
}
|
||||
}
|
||||
- ps: |
|
||||
$out_default_zips = @('dist.zip','pdb.zip')
|
||||
foreach($zip_name in $out_default_zips) {
|
||||
7z x -y -osrc\out\Default $zip_name
|
||||
}
|
||||
- ps: 7z x -y -osrc\out\ffmpeg ffmpeg.zip
|
||||
- ps: 7z x -y -osrc node_headers.zip
|
||||
|
||||
test_script:
|
||||
# Workaround for https://github.com/appveyor/ci/issues/2420
|
||||
- set "PATH=%PATH%;C:\Program Files\Git\mingw64\libexec\git-core"
|
||||
- ps: |
|
||||
cd src
|
||||
New-Item .\out\Default\gen\node_headers\Release -Type directory
|
||||
Copy-Item -path .\out\Default\electron.lib -destination .\out\Default\gen\node_headers\Release\node.lib
|
||||
- set npm_config_nodedir=%cd%\out\Default\gen\node_headers
|
||||
- set npm_config_arch=arm64
|
||||
- cd electron
|
||||
# Explicitly set npm_config_arch because the .env doesn't persist
|
||||
- ps: >-
|
||||
if ($env:TARGET_ARCH -eq 'ia32') {
|
||||
$env:npm_config_arch = "ia32"
|
||||
}
|
||||
- echo Running main test suite & node script/yarn test --runners=main --enable-logging --disable-features=CalculateNativeWinOcclusion
|
||||
- cd ..
|
||||
- echo Verifying non proprietary ffmpeg & python electron\script\verify-ffmpeg.py --build-dir out\Default --source-root %cd% --ffmpeg-path out\ffmpeg
|
||||
|
||||
on_finish:
|
||||
# Uncomment these lines to enable RDP
|
||||
# - ps: $blockRdp = $true; iex ((new-object net.webclient).DownloadString('https://raw.githubusercontent.com/appveyor/ci/master/scripts/enable-rdp.ps1'))
|
||||
- if exist electron\electron.log ( appveyor-retry appveyor PushArtifact electron\electron.log )
|
||||
455
appveyor.yml
455
appveyor.yml
@@ -1,3 +1,7 @@
|
||||
# NOTE IF CHANGING THIS FILE, ALSO APPLY THE CHANGE TO appveyor-woa.yml
|
||||
# IF APPLICABLE!!!!
|
||||
#
|
||||
#
|
||||
# The config expects the following environment variables to be set:
|
||||
# - "GN_CONFIG" Build type. One of {'testing', 'release'}.
|
||||
# - "GN_EXTRA_ARGS" Additional gn arguments for a build config,
|
||||
@@ -24,223 +28,258 @@
|
||||
# https://www.appveyor.com/docs/build-configuration/#custom-environment-variables
|
||||
|
||||
version: 1.0.{build}
|
||||
build_cloud: electron-16-core
|
||||
image: vs2019bt-16.16.11
|
||||
build_cloud: electronhq-16-core
|
||||
image: e-106.0.5249.199-2
|
||||
environment:
|
||||
GIT_CACHE_PATH: C:\Users\electron\libcc_cache
|
||||
GIT_CACHE_PATH: C:\Users\appveyor\libcc_cache
|
||||
ELECTRON_OUT_DIR: Default
|
||||
ELECTRON_ENABLE_STACK_DUMPING: 1
|
||||
ELECTRON_ALSO_LOG_TO_STDERR: 1
|
||||
MOCHA_REPORTER: mocha-multi-reporters
|
||||
MOCHA_MULTI_REPORTERS: mocha-appveyor-reporter, tap
|
||||
GOMA_FALLBACK_ON_AUTH_FAILURE: true
|
||||
build_script:
|
||||
- ps: >-
|
||||
if(($env:APPVEYOR_PULL_REQUEST_HEAD_REPO_NAME -split "/")[0] -eq ($env:APPVEYOR_REPO_NAME -split "/")[0]) {
|
||||
Write-warning "Skipping PR build for branch"; Exit-AppveyorBuild
|
||||
} else {
|
||||
node script/yarn.js install --frozen-lockfile
|
||||
DEPOT_TOOLS_WIN_TOOLCHAIN: 0
|
||||
PYTHONIOENCODING: UTF-8
|
||||
|
||||
$result = node script/doc-only-change.js --prNumber=$env:APPVEYOR_PULL_REQUEST_NUMBER --prBranch=$env:APPVEYOR_REPO_BRANCH
|
||||
Write-Output $result
|
||||
if ($result.ExitCode -eq 0) {
|
||||
Write-warning "Skipping build for doc only change"; Exit-AppveyorBuild
|
||||
}
|
||||
}
|
||||
- echo "Building $env:GN_CONFIG build"
|
||||
- git config --global core.longpaths true
|
||||
- cd ..
|
||||
- mkdir src
|
||||
- update_depot_tools.bat
|
||||
- ps: Move-Item $env:APPVEYOR_BUILD_FOLDER -Destination src\electron
|
||||
- ps: >-
|
||||
if (Test-Path 'env:RAW_GOMA_AUTH') {
|
||||
$env:GOMA_OAUTH2_CONFIG_FILE = "$pwd\.goma_oauth2_config"
|
||||
$env:RAW_GOMA_AUTH | Set-Content $env:GOMA_OAUTH2_CONFIG_FILE
|
||||
}
|
||||
- git clone https://github.com/electron/build-tools.git
|
||||
- cd build-tools
|
||||
- npm install
|
||||
- mkdir third_party
|
||||
- ps: >-
|
||||
node -e "require('./src/utils/goma.js').downloadAndPrepare({ gomaOneForAll: true })"
|
||||
- ps: $env:GN_GOMA_FILE = node -e "console.log(require('./src/utils/goma.js').gnFilePath)"
|
||||
- ps: $env:LOCAL_GOMA_DIR = node -e "console.log(require('./src/utils/goma.js').dir)"
|
||||
- cd ..
|
||||
- ps: .\src\electron\script\start-goma.ps1 -gomaDir $env:LOCAL_GOMA_DIR
|
||||
- ps: >-
|
||||
if (Test-Path 'env:RAW_GOMA_AUTH') {
|
||||
$goma_login = python $env:LOCAL_GOMA_DIR\goma_auth.py info
|
||||
if ($goma_login -eq 'Login as Fermi Planck') {
|
||||
Write-warning "Goma authentication is correct";
|
||||
} else {
|
||||
Write-warning "WARNING!!!!!! Goma authentication is incorrect; please update Goma auth token.";
|
||||
$host.SetShouldExit(1)
|
||||
}
|
||||
}
|
||||
- ps: $env:CHROMIUM_BUILDTOOLS_PATH="$pwd\src\buildtools"
|
||||
- ps: >-
|
||||
if ($env:GN_CONFIG -ne 'release') {
|
||||
$env:NINJA_STATUS="[%r processes, %f/%t @ %o/s : %es] "
|
||||
}
|
||||
- >-
|
||||
gclient config
|
||||
--name "src\electron"
|
||||
--unmanaged
|
||||
%GCLIENT_EXTRA_ARGS%
|
||||
"https://github.com/electron/electron"
|
||||
- ps: >-
|
||||
if ($env:GN_CONFIG -eq 'release') {
|
||||
$env:RUN_GCLIENT_SYNC="true"
|
||||
} else {
|
||||
cd src\electron
|
||||
node script\generate-deps-hash.js
|
||||
$depshash = Get-Content .\.depshash -Raw
|
||||
$zipfile = "Z:\$depshash.7z"
|
||||
cd ..\..
|
||||
if (Test-Path -Path $zipfile) {
|
||||
# file exists, unzip and then gclient sync
|
||||
7z x -y $zipfile -mmt=30 -aoa
|
||||
if (-not (Test-Path -Path "src\buildtools")) {
|
||||
# the zip file must be corrupt - resync
|
||||
$env:RUN_GCLIENT_SYNC="true"
|
||||
if ($env:TARGET_ARCH -ne 'ia32') {
|
||||
# only save on x64/woa to avoid contention saving
|
||||
$env:SAVE_GCLIENT_SRC="true"
|
||||
matrix:
|
||||
|
||||
- job_name: Build
|
||||
- job_name: Test
|
||||
job_depends_on: Build
|
||||
|
||||
clone_folder: C:\projects\src\electron
|
||||
|
||||
skip_branch_with_pr: true
|
||||
|
||||
# the first failed job cancels other jobs and fails entire build
|
||||
matrix:
|
||||
fast_finish: true
|
||||
|
||||
for:
|
||||
|
||||
- matrix:
|
||||
only:
|
||||
- job_name: Build
|
||||
|
||||
build_script:
|
||||
- ps: |
|
||||
node script/yarn.js install --frozen-lockfile
|
||||
node script/doc-only-change.js --prNumber=$env:APPVEYOR_PULL_REQUEST_NUMBER --prBranch=$env:APPVEYOR_REPO_BRANCH
|
||||
if ($LASTEXITCODE -eq 0) {
|
||||
Write-warning "Skipping build for doc only change"; Exit-AppveyorBuild
|
||||
}
|
||||
$global:LASTEXITCODE = 0
|
||||
- cd ..
|
||||
- ps: Write-Host "Building $env:GN_CONFIG build"
|
||||
- git config --global core.longpaths true
|
||||
- ps: >-
|
||||
if (Test-Path -Path "$pwd\depot_tools") {
|
||||
Remove-Item -Recurse -Force $pwd\depot_tools
|
||||
}
|
||||
- ps: >-
|
||||
if (Test-Path -Path "$pwd\build-tools") {
|
||||
Remove-Item -Recurse -Force $pwd\build-tools
|
||||
}
|
||||
- git clone --depth=1 https://chromium.googlesource.com/chromium/tools/depot_tools.git
|
||||
- ps: |
|
||||
cd depot_tools
|
||||
git fetch --depth 1 origin b7d8efd8bee494f4cfacacc19cf50fc4d4be3900
|
||||
git checkout b7d8efd8bee494f4cfacacc19cf50fc4d4be3900
|
||||
New-Item -Name .disable_auto_update -ItemType File
|
||||
bootstrap\win_tools.bat
|
||||
cd ..
|
||||
- ps: $env:PATH="$pwd\depot_tools;$env:PATH"
|
||||
- ps: >-
|
||||
if (Test-Path -Path "$pwd\src\electron") {
|
||||
Remove-Item -Recurse -Force $pwd\src\electron
|
||||
}
|
||||
- ps: >-
|
||||
if (Test-Path 'env:RAW_GOMA_AUTH') {
|
||||
$env:GOMA_OAUTH2_CONFIG_FILE = "$pwd\.goma_oauth2_config"
|
||||
$env:RAW_GOMA_AUTH | Set-Content $env:GOMA_OAUTH2_CONFIG_FILE
|
||||
}
|
||||
- git clone https://github.com/electron/build-tools.git
|
||||
- cd build-tools
|
||||
- npm install
|
||||
- mkdir third_party
|
||||
- ps: >-
|
||||
node -e "require('./src/utils/goma.js').downloadAndPrepare({ gomaOneForAll: true })"
|
||||
- ps: $env:GN_GOMA_FILE = node -e "console.log(require('./src/utils/goma.js').gnFilePath)"
|
||||
- ps: $env:LOCAL_GOMA_DIR = node -e "console.log(require('./src/utils/goma.js').dir)"
|
||||
- cd ..\..
|
||||
- ps: .\src\electron\script\start-goma.ps1 -gomaDir $env:LOCAL_GOMA_DIR
|
||||
- ps: >-
|
||||
if (Test-Path 'env:RAW_GOMA_AUTH') {
|
||||
$goma_login = python $env:LOCAL_GOMA_DIR\goma_auth.py info
|
||||
if ($goma_login -eq 'Login as Fermi Planck') {
|
||||
Write-warning "Goma authentication is correct";
|
||||
} else {
|
||||
Write-warning "WARNING!!!!!! Goma authentication is incorrect; please update Goma auth token.";
|
||||
$host.SetShouldExit(1)
|
||||
}
|
||||
}
|
||||
- ps: $env:CHROMIUM_BUILDTOOLS_PATH="$pwd\src\buildtools"
|
||||
- ps: >-
|
||||
if ($env:GN_CONFIG -ne 'release') {
|
||||
$env:NINJA_STATUS="[%r processes, %f/%t @ %o/s : %es] "
|
||||
}
|
||||
- gclient config --name "src\electron" --unmanaged %GCLIENT_EXTRA_ARGS% "https://github.com/electron/electron"
|
||||
# Patches are applied in the image bake. Check depshash to see if patches have changed.
|
||||
- ps: $env:RUN_GCLIENT_SYNC="false"
|
||||
- ps: $depshash_baked = Get-Content .\src\.depshash -Raw
|
||||
- ps: cd src\electron
|
||||
- ps: node script\generate-deps-hash.js
|
||||
- ps: $depshash = Get-Content .\.depshash -Raw
|
||||
- ps: cd ..\..
|
||||
- ps: >-
|
||||
if ($depshash_baked -ne $depshash) {
|
||||
$env:RUN_GCLIENT_SYNC="true"
|
||||
}
|
||||
- if "%RUN_GCLIENT_SYNC%"=="true" ( gclient sync --with_branch_heads --with_tags ) else ( gclient runhooks )
|
||||
- cd src
|
||||
- set BUILD_CONFIG_PATH=//electron/build/args/%GN_CONFIG%.gn
|
||||
- gn gen out/Default "--args=import(\"%BUILD_CONFIG_PATH%\") import(\"%GN_GOMA_FILE%\") %GN_EXTRA_ARGS% "
|
||||
- gn check out/Default //electron:electron_lib
|
||||
- gn check out/Default //electron:electron_app
|
||||
- gn check out/Default //electron/shell/common/api:mojo
|
||||
- if DEFINED GN_GOMA_FILE (ninja -j 300 -C out/Default electron:electron_app) else (ninja -C out/Default electron:electron_app)
|
||||
- if "%GN_CONFIG%"=="testing" ( python C:\depot_tools\post_build_ninja_summary.py -C out\Default )
|
||||
- gn gen out/ffmpeg "--args=import(\"//electron/build/args/ffmpeg.gn\") %GN_EXTRA_ARGS%"
|
||||
- ninja -C out/ffmpeg electron:electron_ffmpeg_zip
|
||||
- ninja -C out/Default electron:electron_dist_zip
|
||||
- ninja -C out/Default shell_browser_ui_unittests
|
||||
- gn desc out/Default v8:run_mksnapshot_default args > out/Default/default_mksnapshot_args
|
||||
# Remove unused args from mksnapshot_args
|
||||
- ps: >-
|
||||
Get-Content out/Default/default_mksnapshot_args | Where-Object { -not $_.Contains('--turbo-profiling-input') -And -not $_.Contains('builtins-pgo') } | Set-Content out/Default/mksnapshot_args
|
||||
- ninja -C out/Default electron:electron_mksnapshot_zip
|
||||
- cd out\Default
|
||||
- 7z a mksnapshot.zip mksnapshot_args gen\v8\embedded.S
|
||||
- cd ..\..
|
||||
- ninja -C out/Default electron:hunspell_dictionaries_zip
|
||||
- ninja -C out/Default electron:electron_chromedriver_zip
|
||||
- ninja -C out/Default third_party/electron_node:headers
|
||||
- python %LOCAL_GOMA_DIR%\goma_ctl.py stat
|
||||
- ps: >-
|
||||
Get-CimInstance -Namespace root\cimv2 -Class Win32_product | Select vendor, description, @{l='install_location';e='InstallLocation'}, @{l='install_date';e='InstallDate'}, @{l='install_date_2';e='InstallDate2'}, caption, version, name, @{l='sku_number';e='SKUNumber'} | ConvertTo-Json | Out-File -Encoding utf8 -FilePath .\installed_software.json
|
||||
- python3 electron/build/profile_toolchain.py --output-json=out/Default/windows_toolchain_profile.json
|
||||
- 7z a node_headers.zip out\Default\gen\node_headers
|
||||
- ps: >-
|
||||
if ($env:GN_CONFIG -eq 'release') {
|
||||
# Needed for msdia140.dll on 64-bit windows
|
||||
$env:Path += ";$pwd\third_party\llvm-build\Release+Asserts\bin"
|
||||
ninja -C out/Default electron:electron_symbols
|
||||
}
|
||||
- ps: >-
|
||||
if ($env:GN_CONFIG -eq 'release') {
|
||||
python3 electron\script\zip-symbols.py
|
||||
appveyor-retry appveyor PushArtifact out/Default/symbols.zip
|
||||
} else {
|
||||
# update angle
|
||||
cd src\third_party\angle
|
||||
git remote set-url origin https://chromium.googlesource.com/angle/angle.git
|
||||
git fetch
|
||||
cd ..\..\..
|
||||
# It's useful to have pdb files when debugging testing builds that are
|
||||
# built on CI.
|
||||
7z a pdb.zip out\Default\*.pdb
|
||||
}
|
||||
} else {
|
||||
# file does not exist, gclient sync, then zip
|
||||
$env:RUN_GCLIENT_SYNC="true"
|
||||
if ($env:TARGET_ARCH -ne 'ia32') {
|
||||
# only save on x64/woa to avoid contention saving
|
||||
$env:SAVE_GCLIENT_SRC="true"
|
||||
}
|
||||
}
|
||||
}
|
||||
- if "%RUN_GCLIENT_SYNC%"=="true" ( gclient sync )
|
||||
- ps: >-
|
||||
if ($env:SAVE_GCLIENT_SRC -eq 'true') {
|
||||
# archive current source for future use
|
||||
# only run on x64/woa to avoid contention saving
|
||||
$(7z a $zipfile src -xr!android_webview -xr!electron -xr'!*\.git' -xr!third_party\WebKit\LayoutTests! -xr!third_party\blink\web_tests -xr!third_party\blink\perf_tests -slp -t7z -mmt=30)
|
||||
if ($LASTEXITCODE -ne 0) {
|
||||
Write-warning "Could not save source to shared drive; continuing anyway"
|
||||
}
|
||||
# build time generation of file gen/angle/angle_commit.h depends on
|
||||
# third_party/angle/.git
|
||||
# https://chromium-review.googlesource.com/c/angle/angle/+/2074924
|
||||
$(7z a $zipfile src\third_party\angle\.git)
|
||||
if ($LASTEXITCODE -ne 0) {
|
||||
Write-warning "Failed to add third_party\angle\.git; continuing anyway"
|
||||
}
|
||||
# build time generation of file dawn/common/Version_autogen.h depends on third_party/dawn/.git/HEAD
|
||||
# https://dawn-review.googlesource.com/c/dawn/+/83901
|
||||
$(7z a $zipfile src\third_party\dawn\.git)
|
||||
if ($LASTEXITCODE -ne 0) {
|
||||
Write-warning "Failed to add third_party\dawn\.git; continuing anyway"
|
||||
}
|
||||
}
|
||||
- cd src
|
||||
- set BUILD_CONFIG_PATH=//electron/build/args/%GN_CONFIG%.gn
|
||||
- gn gen out/Default "--args=import(\"%BUILD_CONFIG_PATH%\") import(\"%GN_GOMA_FILE%\") %GN_EXTRA_ARGS% "
|
||||
- gn check out/Default //electron:electron_lib
|
||||
- gn check out/Default //electron:electron_app
|
||||
- gn check out/Default //electron/shell/common/api:mojo
|
||||
- if DEFINED GN_GOMA_FILE (ninja -j 300 -C out/Default electron:electron_app) else (ninja -C out/Default electron:electron_app)
|
||||
- if "%GN_CONFIG%"=="testing" ( python C:\depot_tools\post_build_ninja_summary.py -C out\Default )
|
||||
- gn gen out/ffmpeg "--args=import(\"//electron/build/args/ffmpeg.gn\") %GN_EXTRA_ARGS%"
|
||||
- ninja -C out/ffmpeg electron:electron_ffmpeg_zip
|
||||
- ninja -C out/Default electron:electron_dist_zip
|
||||
- ninja -C out/Default shell_browser_ui_unittests
|
||||
- gn desc out/Default v8:run_mksnapshot_default args > out/Default/mksnapshot_args
|
||||
- ninja -C out/Default electron:electron_mksnapshot_zip
|
||||
- cd out\Default
|
||||
- 7z a mksnapshot.zip mksnapshot_args gen\v8\embedded.S
|
||||
- cd ..\..
|
||||
- ninja -C out/Default electron:hunspell_dictionaries_zip
|
||||
- ninja -C out/Default electron:electron_chromedriver_zip
|
||||
- ninja -C out/Default third_party/electron_node:headers
|
||||
- python %LOCAL_GOMA_DIR%\goma_ctl.py stat
|
||||
- python3 electron/build/profile_toolchain.py --output-json=out/Default/windows_toolchain_profile.json
|
||||
- 7z a node_headers.zip out\Default\gen\node_headers
|
||||
- ps: >-
|
||||
if ($env:GN_CONFIG -eq 'release') {
|
||||
# Needed for msdia140.dll on 64-bit windows
|
||||
$env:Path += ";$pwd\third_party\llvm-build\Release+Asserts\bin"
|
||||
ninja -C out/Default electron:electron_symbols
|
||||
}
|
||||
- ps: >-
|
||||
if ($env:GN_CONFIG -eq 'release') {
|
||||
python electron\script\zip-symbols.py
|
||||
appveyor-retry appveyor PushArtifact out/Default/symbols.zip
|
||||
} else {
|
||||
# It's useful to have pdb files when debugging testing builds that are
|
||||
# built on CI.
|
||||
7z a pdb.zip out\Default\*.pdb
|
||||
}
|
||||
- python electron/script/zip_manifests/check-zip-manifest.py out/Default/dist.zip electron/script/zip_manifests/dist_zip.win.%TARGET_ARCH%.manifest
|
||||
test_script:
|
||||
# Workaround for https://github.com/appveyor/ci/issues/2420
|
||||
- set "PATH=%PATH%;C:\Program Files\Git\mingw64\libexec\git-core"
|
||||
- ps: >-
|
||||
if ((-Not (Test-Path Env:\TEST_WOA)) -And (-Not (Test-Path Env:\ELECTRON_RELEASE)) -And ($env:GN_CONFIG -in "testing", "release")) {
|
||||
$env:RUN_TESTS="true"
|
||||
}
|
||||
- ps: >-
|
||||
if ($env:RUN_TESTS -eq 'true') {
|
||||
New-Item .\out\Default\gen\node_headers\Release -Type directory
|
||||
Copy-Item -path .\out\Default\electron.lib -destination .\out\Default\gen\node_headers\Release\node.lib
|
||||
} else {
|
||||
echo "Skipping tests for $env:GN_CONFIG build"
|
||||
}
|
||||
- cd electron
|
||||
- if "%RUN_TESTS%"=="true" ( echo Running main test suite & node script/yarn test -- --trace-uncaught --runners=main --enable-logging=file --log-file=%cd%\electron.log )
|
||||
- if "%RUN_TESTS%"=="true" ( echo Running remote test suite & node script/yarn test -- --trace-uncaught --runners=remote --runTestFilesSeparately --enable-logging=file --log-file=%cd%\electron.log )
|
||||
- if "%RUN_TESTS%"=="true" ( echo Running native test suite & node script/yarn test -- --trace-uncaught --runners=native --enable-logging=file --log-file=%cd%\electron.log )
|
||||
- cd ..
|
||||
- if "%RUN_TESTS%"=="true" ( echo Verifying non proprietary ffmpeg & python electron\script\verify-ffmpeg.py --build-dir out\Default --source-root %cd% --ffmpeg-path out\ffmpeg )
|
||||
- echo "About to verify mksnapshot"
|
||||
- if "%RUN_TESTS%"=="true" ( echo Verifying mksnapshot & python electron\script\verify-mksnapshot.py --build-dir out\Default --source-root %cd% )
|
||||
- echo "Done verifying mksnapshot"
|
||||
- if "%RUN_TESTS%"=="true" ( echo Verifying chromedriver & python electron\script\verify-chromedriver.py --build-dir out\Default --source-root %cd% )
|
||||
- echo "Done verifying chromedriver"
|
||||
deploy_script:
|
||||
- cd electron
|
||||
- ps: >-
|
||||
if (Test-Path Env:\ELECTRON_RELEASE) {
|
||||
if (Test-Path Env:\UPLOAD_TO_STORAGE) {
|
||||
Write-Output "Uploading Electron release distribution to azure"
|
||||
& python script\release\uploaders\upload.py --verbose --upload_to_storage
|
||||
} else {
|
||||
Write-Output "Uploading Electron release distribution to github releases"
|
||||
& python script\release\uploaders\upload.py --verbose
|
||||
}
|
||||
} elseif (Test-Path Env:\TEST_WOA) {
|
||||
node script/release/ci-release-build.js --job=electron-woa-testing --ci=GHA --appveyorJobId=$env:APPVEYOR_JOB_ID $env:APPVEYOR_REPO_BRANCH
|
||||
}
|
||||
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 ..
|
||||
- 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: >-
|
||||
if ((Test-Path "pdb.zip") -And ($env:GN_CONFIG -ne 'release')) {
|
||||
appveyor-retry appveyor PushArtifact pdb.zip
|
||||
}
|
||||
- python3 electron/script/zip_manifests/check-zip-manifest.py out/Default/dist.zip electron/script/zip_manifests/dist_zip.win.%TARGET_ARCH%.manifest
|
||||
|
||||
- if exist electron\electron.log ( appveyor-retry appveyor PushArtifact electron\electron.log )
|
||||
deploy_script:
|
||||
- cd electron
|
||||
- ps: >-
|
||||
if (Test-Path Env:\ELECTRON_RELEASE) {
|
||||
if (Test-Path Env:\UPLOAD_TO_STORAGE) {
|
||||
Write-Output "Uploading Electron release distribution to azure"
|
||||
& python3 script\release\uploaders\upload.py --verbose --upload_to_storage
|
||||
} else {
|
||||
Write-Output "Uploading Electron release distribution to github releases"
|
||||
& python3 script\release\uploaders\upload.py --verbose
|
||||
}
|
||||
}
|
||||
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: >-
|
||||
if ((Test-Path "pdb.zip") -And ($env:GN_CONFIG -ne 'release')) {
|
||||
appveyor-retry appveyor PushArtifact pdb.zip
|
||||
}
|
||||
- matrix:
|
||||
only:
|
||||
- job_name: Test
|
||||
|
||||
init:
|
||||
- ps: |
|
||||
if ($env:RUN_TESTS -ne 'true') {
|
||||
Write-warning "Skipping tests for $env:APPVEYOR_PROJECT_NAME"; Exit-AppveyorBuild
|
||||
}
|
||||
build_script:
|
||||
- ps: |
|
||||
node script/yarn.js install --frozen-lockfile
|
||||
node script/doc-only-change.js --prNumber=$env:APPVEYOR_PULL_REQUEST_NUMBER --prBranch=$env:APPVEYOR_REPO_BRANCH
|
||||
if ($LASTEXITCODE -eq 0) {
|
||||
Write-warning "Skipping build for doc only change"; Exit-AppveyorBuild
|
||||
}
|
||||
$global:LASTEXITCODE = 0
|
||||
- cd ..
|
||||
- mkdir out\Default
|
||||
- cd ..
|
||||
- ps: |
|
||||
# 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','shell_browser_ui_unittests.exe','chromedriver.zip','ffmpeg.zip','node_headers.zip','mksnapshot.zip','electron.lib')
|
||||
foreach ($job in $build_info.build.jobs) {
|
||||
if ($job.name -eq "Build") {
|
||||
$jobId = $job.jobId
|
||||
foreach($artifact_name in $artifacts_to_download) {
|
||||
if ($artifact_name -eq 'shell_browser_ui_unittests.exe' -Or $artifact_name -eq 'electron.lib') {
|
||||
$outfile = "src\out\Default\$artifact_name"
|
||||
} else {
|
||||
$outfile = $artifact_name
|
||||
}
|
||||
Invoke-RestMethod -Method Get -Uri "$apiUrl/buildjobs/$jobId/artifacts/$artifact_name" -OutFile $outfile
|
||||
}
|
||||
}
|
||||
}
|
||||
- ps: |
|
||||
$out_default_zips = @('dist.zip','chromedriver.zip','mksnapshot.zip')
|
||||
foreach($zip_name in $out_default_zips) {
|
||||
7z x -y -osrc\out\Default $zip_name
|
||||
}
|
||||
- ps: 7z x -y -osrc\out\ffmpeg ffmpeg.zip
|
||||
- ps: 7z x -y -osrc node_headers.zip
|
||||
|
||||
test_script:
|
||||
# Workaround for https://github.com/appveyor/ci/issues/2420
|
||||
- set "PATH=%PATH%;C:\Program Files\Git\mingw64\libexec\git-core"
|
||||
- ps: |
|
||||
cd src
|
||||
New-Item .\out\Default\gen\node_headers\Release -Type directory
|
||||
Copy-Item -path .\out\Default\electron.lib -destination .\out\Default\gen\node_headers\Release\node.lib
|
||||
- cd electron
|
||||
# Explicitly set npm_config_arch because the .env doesn't persist
|
||||
- ps: >-
|
||||
if ($env:TARGET_ARCH -eq 'ia32') {
|
||||
$env:npm_config_arch = "ia32"
|
||||
}
|
||||
- echo Running main test suite & node script/yarn test -- --trace-uncaught --runners=main --enable-logging=file --log-file=%cd%\electron.log
|
||||
- echo Running native test suite & node script/yarn test -- --trace-uncaught --runners=native --enable-logging=file --log-file=%cd%\electron.log
|
||||
- cd ..
|
||||
- echo Verifying non proprietary ffmpeg & python electron\script\verify-ffmpeg.py --build-dir out\Default --source-root %cd% --ffmpeg-path out\ffmpeg
|
||||
- echo "About to verify mksnapshot"
|
||||
- echo Verifying mksnapshot & python electron\script\verify-mksnapshot.py --build-dir out\Default --source-root %cd%
|
||||
- echo "Done verifying mksnapshot"
|
||||
- echo Verifying chromedriver & python electron\script\verify-chromedriver.py --build-dir out\Default --source-root %cd%
|
||||
- echo "Done verifying chromedriver"
|
||||
|
||||
on_finish:
|
||||
# Uncomment these lines to enable RDP
|
||||
# - ps: $blockRdp = $true; iex ((new-object net.webclient).DownloadString('https://raw.githubusercontent.com/appveyor/ci/master/scripts/enable-rdp.ps1'))
|
||||
- if exist electron\electron.log ( appveyor-retry appveyor PushArtifact electron\electron.log )
|
||||
@@ -5,8 +5,6 @@ import sys
|
||||
import os
|
||||
import optparse
|
||||
import json
|
||||
import re
|
||||
import subprocess
|
||||
|
||||
sys.path.append("%s/../../build" % os.path.dirname(os.path.realpath(__file__)))
|
||||
|
||||
@@ -36,56 +34,10 @@ def calculate_hash(root):
|
||||
return CalculateHash('.', None)
|
||||
|
||||
def windows_installed_software():
|
||||
powershell_command = [
|
||||
"Get-CimInstance",
|
||||
"-Namespace",
|
||||
"root\cimv2",
|
||||
"-Class",
|
||||
"Win32_product",
|
||||
"|",
|
||||
"Select",
|
||||
"vendor,",
|
||||
"description,",
|
||||
"@{l='install_location';e='InstallLocation'},",
|
||||
"@{l='install_date';e='InstallDate'},",
|
||||
"@{l='install_date_2';e='InstallDate2'},",
|
||||
"caption,",
|
||||
"version,",
|
||||
"name,",
|
||||
"@{l='sku_number';e='SKUNumber'}",
|
||||
"|",
|
||||
"ConvertTo-Json",
|
||||
]
|
||||
|
||||
proc = subprocess.Popen(
|
||||
["powershell.exe", "-Command", "-"],
|
||||
stdin=subprocess.PIPE,
|
||||
stdout=subprocess.PIPE,
|
||||
)
|
||||
|
||||
stdout, _ = proc.communicate(" ".join(powershell_command).encode("utf-8"))
|
||||
|
||||
if proc.returncode != 0:
|
||||
raise RuntimeError("Failed to get list of installed software")
|
||||
|
||||
# On AppVeyor there's other output related to PSReadline,
|
||||
# so grab only the JSON output and ignore everything else
|
||||
json_match = re.match(
|
||||
r".*(\[.*{.*}.*\]).*", stdout.decode("utf-8"), re.DOTALL
|
||||
)
|
||||
|
||||
if not json_match:
|
||||
raise RuntimeError(
|
||||
"Couldn't find JSON output for list of installed software"
|
||||
)
|
||||
|
||||
# Filter out missing keys
|
||||
return list(
|
||||
map(
|
||||
lambda info: {k: info[k] for k in info if info[k]},
|
||||
json.loads(json_match.group(1)),
|
||||
)
|
||||
)
|
||||
# file_path = os.path.join(os.getcwd(), 'installed_software.json')
|
||||
# return json.loads(open('installed_software.json').read().decode('utf-8'))
|
||||
f = open('installed_software.json', encoding='utf-8-sig')
|
||||
return json.load(f)
|
||||
|
||||
|
||||
def windows_profile():
|
||||
|
||||
@@ -50,8 +50,8 @@ END
|
||||
//
|
||||
|
||||
VS_VERSION_INFO VERSIONINFO
|
||||
FILEVERSION 21,1,0,0
|
||||
PRODUCTVERSION 21,1,0,0
|
||||
FILEVERSION $major,$minor,$patch,$prerelease_number
|
||||
PRODUCTVERSION $major,$minor,$patch,$prerelease_number
|
||||
FILEFLAGSMASK 0x3fL
|
||||
#ifdef _DEBUG
|
||||
FILEFLAGS 0x1L
|
||||
@@ -68,12 +68,12 @@ BEGIN
|
||||
BEGIN
|
||||
VALUE "CompanyName", "GitHub, Inc."
|
||||
VALUE "FileDescription", "Electron"
|
||||
VALUE "FileVersion", "21.1.0"
|
||||
VALUE "FileVersion", "$major.$minor.$patch"
|
||||
VALUE "InternalName", "electron.exe"
|
||||
VALUE "LegalCopyright", "Copyright (C) 2015 GitHub, Inc. All rights reserved."
|
||||
VALUE "OriginalFilename", "electron.exe"
|
||||
VALUE "ProductName", "Electron"
|
||||
VALUE "ProductVersion", "21.1.0"
|
||||
VALUE "ProductVersion", "$major.$minor.$patch"
|
||||
VALUE "SquirrelAwareVersion", "1"
|
||||
END
|
||||
END
|
||||
1
build/templates/version_string.tmpl
Normal file
1
build/templates/version_string.tmpl
Normal file
@@ -0,0 +1 @@
|
||||
$full_version
|
||||
@@ -6,6 +6,7 @@ import("//build/config/ozone.gni")
|
||||
import("//build/config/ui.gni")
|
||||
import("//components/spellcheck/spellcheck_build_features.gni")
|
||||
import("//electron/buildflags/buildflags.gni")
|
||||
import("//ppapi/buildflags/buildflags.gni")
|
||||
import("//printing/buildflags/buildflags.gni")
|
||||
import("//third_party/widevine/cdm/widevine.gni")
|
||||
|
||||
@@ -372,15 +373,20 @@ source_set("plugins") {
|
||||
deps += [
|
||||
"//components/strings",
|
||||
"//media:media_buildflags",
|
||||
"//ppapi/buildflags",
|
||||
"//ppapi/host",
|
||||
"//ppapi/proxy",
|
||||
"//ppapi/proxy:ipc",
|
||||
"//ppapi/shared_impl",
|
||||
"//services/device/public/mojom",
|
||||
"//skia",
|
||||
"//storage/browser",
|
||||
]
|
||||
|
||||
if (enable_ppapi) {
|
||||
deps += [
|
||||
"//ppapi/buildflags",
|
||||
"//ppapi/host",
|
||||
"//ppapi/proxy",
|
||||
"//ppapi/proxy:ipc",
|
||||
"//ppapi/shared_impl",
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
# This source set is just so we don't have to depend on all of //chrome/browser
|
||||
|
||||
@@ -83,7 +83,7 @@ function loadApplicationPackage (packagePath: string) {
|
||||
});
|
||||
|
||||
try {
|
||||
// Override app name and version.
|
||||
// Override app's package.json data.
|
||||
packagePath = path.resolve(packagePath);
|
||||
const packageJsonPath = path.join(packagePath, 'package.json');
|
||||
let appPath;
|
||||
@@ -104,6 +104,16 @@ function loadApplicationPackage (packagePath: string) {
|
||||
} else if (packageJson.name) {
|
||||
app.name = packageJson.name;
|
||||
}
|
||||
if (packageJson.desktopName) {
|
||||
app.setDesktopName(packageJson.desktopName);
|
||||
} else {
|
||||
app.setDesktopName(`${app.name}.desktop`);
|
||||
}
|
||||
// Set v8 flags, deliberately lazy load so that apps that do not use this
|
||||
// feature do not pay the price
|
||||
if (packageJson.v8Flags) {
|
||||
require('v8').setFlagsFromString(packageJson.v8Flags);
|
||||
}
|
||||
appPath = packagePath;
|
||||
}
|
||||
|
||||
|
||||
@@ -83,7 +83,6 @@ These individual tutorials expand on topics discussed in the guide above.
|
||||
* Electron Releases & Developer Feedback
|
||||
* [Versioning Policy](tutorial/electron-versioning.md)
|
||||
* [Release Timelines](tutorial/electron-timelines.md)
|
||||
* [Testing Widevine CDM](tutorial/testing-widevine-cdm.md)
|
||||
|
||||
---
|
||||
|
||||
|
||||
@@ -717,6 +717,8 @@ To set the locale, you'll want to use a command line switch at app startup, whic
|
||||
|
||||
**Note:** This API must be called after the `ready` event is emitted.
|
||||
|
||||
**Note:** To see example return values of this API compared to other locale and language APIs, see [`app.getPreferredSystemLanguages()`](#appgetpreferredsystemlanguages).
|
||||
|
||||
### `app.getLocaleCountryCode()`
|
||||
|
||||
Returns `string` - User operating system's locale two-letter [ISO 3166](https://www.iso.org/iso-3166-country-codes.html) country code. The value is taken from native OS APIs.
|
||||
@@ -725,10 +727,42 @@ Returns `string` - User operating system's locale two-letter [ISO 3166](https://
|
||||
|
||||
### `app.getSystemLocale()`
|
||||
|
||||
Returns `string` - The current system locale. On Windows and Linux, it is fetched using Chromium's `i18n` library. On macOS, the `NSLocale` object is used instead.
|
||||
Returns `string` - The current system locale. On Windows and Linux, it is fetched using Chromium's `i18n` library. On macOS, `[NSLocale currentLocale]` is used instead. To get the user's current system language, which is not always the same as the locale, it is better to use [`app.getPreferredSystemLanguages()`](#appgetpreferredsystemlanguages).
|
||||
|
||||
Different operating systems also use the regional data differently:
|
||||
|
||||
* Windows 11 uses the regional format for numbers, dates, and times.
|
||||
* macOS Monterey uses the region for formatting numbers, dates, times, and for selecting the currency symbol to use.
|
||||
|
||||
Therefore, this API can be used for purposes such as choosing a format for rendering dates and times in a calendar app, especially when the developer wants the format to be consistent with the OS.
|
||||
|
||||
**Note:** This API must be called after the `ready` event is emitted.
|
||||
|
||||
**Note:** To see example return values of this API compared to other locale and language APIs, see [`app.getPreferredSystemLanguages()`](#appgetpreferredsystemlanguages).
|
||||
|
||||
### `app.getPreferredSystemLanguages()`
|
||||
|
||||
Returns `string[]` - The user's preferred system languages from most preferred to least preferred, including the country codes if applicable. A user can modify and add to this list on Windows or macOS through the Language and Region settings.
|
||||
|
||||
The API uses `GlobalizationPreferences` (with a fallback to `GetSystemPreferredUILanguages`) on Windows, `\[NSLocale preferredLanguages\]` on macOS, and `g_get_language_names` on Linux.
|
||||
|
||||
This API can be used for purposes such as deciding what language to present the application in.
|
||||
|
||||
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']`
|
||||
|
||||
Both the available languages and regions and the possible return values differ between the two operating systems.
|
||||
|
||||
As can be seen with the example above, on Windows, it is possible that a preferred system language has no country code, and that one of the preferred system languages corresponds with the language used for the regional format. On macOS, the region serves more as a default country code: the user doesn't need to have Finnish as a preferred language to use Finland as the region,and the country code `FI` is used as the country code for preferred system languages that do not have associated countries in the language name.
|
||||
|
||||
### `app.addRecentDocument(path)` _macOS_ _Windows_
|
||||
|
||||
* `path` string
|
||||
@@ -1203,7 +1237,7 @@ For `infoType` equal to `basic`:
|
||||
}
|
||||
```
|
||||
|
||||
Using `basic` should be preferred if only basic information like `vendorId` or `driverId` is needed.
|
||||
Using `basic` should be preferred if only basic information like `vendorId` or `deviceId` is needed.
|
||||
|
||||
### `app.setBadgeCount([count])` _Linux_ _macOS_
|
||||
|
||||
|
||||
@@ -1869,7 +1869,7 @@ removed in future Electron releases.
|
||||
On a Window with Window Controls Overlay already enabled, this method updates
|
||||
the style of the title bar overlay.
|
||||
|
||||
[runtime-enabled-features]: https://cs.chromium.org/chromium/src/third_party/blink/renderer/platform/runtime_enabled_features.json5?l=70
|
||||
[runtime-enabled-features]: https://source.chromium.org/chromium/chromium/src/+/main:third_party/blink/renderer/platform/runtime_enabled_features.json5
|
||||
[page-visibility-api]: https://developer.mozilla.org/en-US/docs/Web/API/Page_Visibility_API
|
||||
[quick-look]: https://en.wikipedia.org/wiki/Quick_Look
|
||||
[vibrancy-docs]: https://developer.apple.com/documentation/appkit/nsvisualeffectview?preferredLanguage=objc
|
||||
|
||||
@@ -20,7 +20,7 @@ work). Extensions are installed per-`session`. To load an extension, call
|
||||
```js
|
||||
const { session } = require('electron')
|
||||
|
||||
session.loadExtension('path/to/unpacked/extension').then(({ id }) => {
|
||||
session.defaultSession.loadExtension('path/to/unpacked/extension').then(({ id }) => {
|
||||
// ...
|
||||
})
|
||||
```
|
||||
|
||||
@@ -96,14 +96,6 @@ Algorithm][SCA], just like [`window.postMessage`][], so prototype chains will no
|
||||
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.
|
||||
>
|
||||
> Since the main process does not have support for DOM objects such as
|
||||
> `ImageBitmap`, `File`, `DOMMatrix` and so on, such objects cannot be sent over
|
||||
> Electron's IPC to the main process, as the main process would have no way to decode
|
||||
> them. Attempting to send such objects over IPC will result in an error.
|
||||
|
||||
The main process should listen for `channel` with
|
||||
[`ipcMain.handle()`](./ipc-main.md#ipcmainhandlechannel-listener).
|
||||
|
||||
@@ -126,6 +118,21 @@ If you need to transfer a [`MessagePort`][] to the main process, use [`ipcRender
|
||||
|
||||
If you do not need a response to the message, consider using [`ipcRenderer.send`](#ipcrenderersendchannel-args).
|
||||
|
||||
> **Note**
|
||||
> Sending non-standard JavaScript types such as DOM objects or
|
||||
> special Electron objects will throw an exception.
|
||||
>
|
||||
> Since the main process does not have support for DOM objects such as
|
||||
> `ImageBitmap`, `File`, `DOMMatrix` and so on, such objects cannot be sent over
|
||||
> Electron's IPC to the main process, as the main process would have no way to decode
|
||||
> them. Attempting to send such objects over IPC will result in an error.
|
||||
|
||||
> **Note**
|
||||
> If the handler in the main process throws an error,
|
||||
> the promise returned by `invoke` will reject.
|
||||
> However, the `Error` object in the renderer process
|
||||
> will not be the same as the one thrown in the main process.
|
||||
|
||||
### `ipcRenderer.sendSync(channel, ...args)`
|
||||
|
||||
* `channel` string
|
||||
|
||||
@@ -14,7 +14,7 @@ See [`Menu`](menu.md) for examples.
|
||||
* `menuItem` MenuItem
|
||||
* `browserWindow` [BrowserWindow](browser-window.md) | undefined - This will not be defined if no window is open.
|
||||
* `event` [KeyboardEvent](structures/keyboard-event.md)
|
||||
* `role` string (optional) - Can be `undo`, `redo`, `cut`, `copy`, `paste`, `pasteAndMatchStyle`, `delete`, `selectAll`, `reload`, `forceReload`, `toggleDevTools`, `resetZoom`, `zoomIn`, `zoomOut`, `toggleSpellChecker`, `togglefullscreen`, `window`, `minimize`, `close`, `help`, `about`, `services`, `hide`, `hideOthers`, `unhide`, `quit`, 'showSubstitutions', 'toggleSmartQuotes', 'toggleSmartDashes', 'toggleTextReplacement', `startSpeaking`, `stopSpeaking`, `zoom`, `front`, `appMenu`, `fileMenu`, `editMenu`, `viewMenu`, `shareMenu`, `recentDocuments`, `toggleTabBar`, `selectNextTab`, `selectPreviousTab`, `mergeAllWindows`, `clearRecentDocuments`, `moveTabToNewWindow` or `windowMenu` - Define the action of the menu item, when specified the
|
||||
* `role` string (optional) - Can be `undo`, `redo`, `cut`, `copy`, `paste`, `pasteAndMatchStyle`, `delete`, `selectAll`, `reload`, `forceReload`, `toggleDevTools`, `resetZoom`, `zoomIn`, `zoomOut`, `toggleSpellChecker`, `togglefullscreen`, `window`, `minimize`, `close`, `help`, `about`, `services`, `hide`, `hideOthers`, `unhide`, `quit`, `showSubstitutions`, `toggleSmartQuotes`, `toggleSmartDashes`, `toggleTextReplacement`, `startSpeaking`, `stopSpeaking`, `zoom`, `front`, `appMenu`, `fileMenu`, `editMenu`, `viewMenu`, `shareMenu`, `recentDocuments`, `toggleTabBar`, `selectNextTab`, `selectPreviousTab`, `mergeAllWindows`, `clearRecentDocuments`, `moveTabToNewWindow` or `windowMenu` - Define the action of the menu item, when specified the
|
||||
`click` property will be ignored. See [roles](#roles).
|
||||
* `type` string (optional) - Can be `normal`, `separator`, `submenu`, `checkbox` or
|
||||
`radio`.
|
||||
|
||||
@@ -405,7 +405,7 @@ Clears the session’s HTTP cache.
|
||||
* `origin` string (optional) - Should follow `window.location.origin`’s representation
|
||||
`scheme://host:port`.
|
||||
* `storages` string[] (optional) - The types of storages to clear, can contain:
|
||||
`appcache`, `cookies`, `filesystem`, `indexdb`, `localstorage`,
|
||||
`cookies`, `filesystem`, `indexdb`, `localstorage`,
|
||||
`shadercache`, `websql`, `serviceworkers`, `cachestorage`. If not
|
||||
specified, clear all storage types.
|
||||
* `quotas` string[] (optional) - The types of quotas to clear, can contain:
|
||||
@@ -638,6 +638,7 @@ win.webContents.session.setCertificateVerifyProc((request, callback) => {
|
||||
* `pointerLock` - Request to directly interpret mouse movements as an input method. Click [here](https://developer.mozilla.org/en-US/docs/Web/API/Pointer_Lock_API) to know more. These requests always appear to originate from the main frame.
|
||||
* `fullscreen` - Request for the app to enter fullscreen mode.
|
||||
* `openExternal` - Request to open links in external applications.
|
||||
* `window-placement` - Request access to enumerate screens using the [`getScreenDetails`](https://developer.chrome.com/en/articles/multi-screen-window-placement/) API.
|
||||
* `unknown` - An unrecognized permission request
|
||||
* `callback` Function
|
||||
* `permissionGranted` boolean - Allow or deny the permission.
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
# Display Object
|
||||
|
||||
* `id` number - Unique identifier associated with the display.
|
||||
* `label` string - User-friendly label, determined by the platform.
|
||||
* `rotation` number - Can be 0, 90, 180, 270, represents screen rotation in
|
||||
clock-wise degrees.
|
||||
* `scaleFactor` number - Output device's pixel scale factor.
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
# WebRequestFilter Object
|
||||
|
||||
* `urls` string[] - Array of URL patterns that will be used to filter out the requests that do not match the URL patterns.
|
||||
* `urls` string[] - Array of [URL patterns](https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/Match_patterns) that will be used to filter out the requests that do not match the URL patterns.
|
||||
|
||||
@@ -1180,7 +1180,7 @@ Ignore application menu shortcuts while this web contents is focused.
|
||||
|
||||
#### `contents.setWindowOpenHandler(handler)`
|
||||
|
||||
* `handler` Function<{action: 'deny'} | {action: 'allow', overrideBrowserWindowOptions?: BrowserWindowConstructorOptions}>
|
||||
* `handler` Function<{action: 'deny'} | {action: 'allow', outlivesOpener?: boolean, overrideBrowserWindowOptions?: BrowserWindowConstructorOptions}>
|
||||
* `details` Object
|
||||
* `url` string - The _resolved_ version of the URL passed to `window.open()`. e.g. opening a window with `window.open('foo')` will yield something like `https://the-origin/the/current/path/foo`.
|
||||
* `frameName` string - Name of the window provided in `window.open()`
|
||||
@@ -1195,8 +1195,11 @@ Ignore application menu shortcuts while this web contents is focused.
|
||||
be set. If no post data is to be sent, the value will be `null`. Only defined
|
||||
when the window is being created by a form that set `target=_blank`.
|
||||
|
||||
Returns `{action: 'deny'} | {action: 'allow', overrideBrowserWindowOptions?: BrowserWindowConstructorOptions}` - `deny` cancels the creation of the new
|
||||
Returns `{action: 'deny'} | {action: 'allow', outlivesOpener?: boolean, overrideBrowserWindowOptions?: BrowserWindowConstructorOptions}` - `deny` cancels the creation of the new
|
||||
window. `allow` will allow the new window to be created. Specifying `overrideBrowserWindowOptions` allows customization of the created window.
|
||||
By default, child windows are closed when their opener is closed. This can be
|
||||
changed by specifying `outlivesOpener: true`, in which case the opened window
|
||||
will not be closed when its opener is closed.
|
||||
Returning an unrecognized value such as a null, undefined, or an object
|
||||
without a recognized 'action' value will result in a console error and have
|
||||
the same effect as returning `{action: 'deny'}`.
|
||||
|
||||
@@ -28,7 +28,7 @@ const { session } = require('electron')
|
||||
|
||||
// Modify the user agent for all requests to the following urls.
|
||||
const filter = {
|
||||
urls: ['https://*.github.com/*', '*://electron.github.io']
|
||||
urls: ['https://*.github.com/*', '*://electron.github.io/*']
|
||||
}
|
||||
|
||||
session.defaultSession.webRequest.onBeforeSendHeaders(filter, (details, callback) => {
|
||||
|
||||
@@ -1020,7 +1020,7 @@ Emitted when DevTools is closed.
|
||||
|
||||
Emitted when DevTools is focused / opened.
|
||||
|
||||
[runtime-enabled-features]: https://cs.chromium.org/chromium/src/third_party/blink/renderer/platform/runtime_enabled_features.json5?l=70
|
||||
[runtime-enabled-features]: https://source.chromium.org/chromium/chromium/src/+/main:third_party/blink/renderer/platform/runtime_enabled_features.json5
|
||||
[chrome-webview]: https://developer.chrome.com/docs/extensions/reference/webviewTag/
|
||||
|
||||
### Event: 'context-menu'
|
||||
|
||||
@@ -100,7 +100,7 @@ requires unsafe mode), so Electron is unable to support this feature on Linux.
|
||||
|
||||
The handler invoked when `session.setDevicePermissionHandler(handler)` is used
|
||||
has a change to its arguments. This handler no longer is passed a frame
|
||||
`[WebFrameMain](api/web-frame-main.md)`, but instead is passed the `origin`, which
|
||||
[`WebFrameMain`](api/web-frame-main.md), but instead is passed the `origin`, which
|
||||
is the origin that is checking for device permission.
|
||||
|
||||
## Planned Breaking API Changes (19.0)
|
||||
|
||||
@@ -18,8 +18,8 @@ See also [V8 Development](v8-development.md)
|
||||
|
||||
### Code Resources
|
||||
|
||||
- [Code Search](https://cs.chromium.org/) - Indexed and searchable source code for Chromium and associated projects.
|
||||
- [Source Code](https://cs.chromium.org/chromium/src/) - The source code for Chromium itself.
|
||||
- [Code Search](https://source.chromium.org/chromium) - Indexed and searchable source code for Chromium and associated projects.
|
||||
- [Source Code](https://source.chromium.org/chromium/chromium/src) - The source code for Chromium itself.
|
||||
- [Chromium Review](https://chromium-review.googlesource.com) - The searchable code host which facilitates code reviews for Chromium and related projects.
|
||||
|
||||
### Informational Resources
|
||||
|
||||
@@ -144,7 +144,7 @@ NODE_LINKED_MODULE_CONTEXT_AWARE(electron_browser_{api_name},Initialize)
|
||||
In your [`shell/common/node_bindings.cc`](https://github.com/electron/electron/blob/main/shell/common/node_bindings.cc) file, add your node binding name to Electron's built-in modules.
|
||||
|
||||
```cpp title='shell/common/node_bindings.cc'
|
||||
#define ELECTRON_BUILTIN_MODULES(V) \
|
||||
#define ELECTRON_BROWSER_MODULES(V) \
|
||||
V(electron_browser_{api_name})
|
||||
```
|
||||
|
||||
|
||||
0
docs/fiddles/features/web-bluetooth/preload.js
Executable file → Normal file
0
docs/fiddles/features/web-bluetooth/preload.js
Executable file → Normal file
@@ -52,15 +52,17 @@ ways to get your application signed and notarized.
|
||||
If you're using Electron's favorite build tool, getting your application signed
|
||||
and notarized requires a few additions to your configuration. [Forge](https://electronforge.io) is a
|
||||
collection of the official Electron tools, using [`electron-packager`],
|
||||
[`electron-osx-sign`], and [`electron-notarize`] under the hood.
|
||||
[`@electron/osx-sign`], and [`@electron/notarize`] under the hood.
|
||||
|
||||
Detailed instructions on how to configure your application can be found in the [Electron Forge Code Signing Tutorial](https://www.electronforge.io/guides/code-signing/code-signing-macos).
|
||||
Detailed instructions on how to configure your application can be found in the
|
||||
[Signing macOS Apps](https://www.electronforge.io/guides/code-signing/code-signing-macos) guide in
|
||||
the Electron Forge docs.
|
||||
|
||||
### Using Electron Packager
|
||||
|
||||
If you're not using an integrated build pipeline like Forge, you
|
||||
are likely using [`electron-packager`], which includes [`electron-osx-sign`] and
|
||||
[`electron-notarize`].
|
||||
are likely using [`electron-packager`], which includes [`@electron/osx-sign`] and
|
||||
[`@electron/notarize`].
|
||||
|
||||
If you're using Packager's API, you can pass [in configuration that both signs
|
||||
and notarizes your application](https://electron.github.io/electron-packager/main/interfaces/electronpackager.options.html).
|
||||
@@ -70,13 +72,7 @@ const packager = require('electron-packager')
|
||||
|
||||
packager({
|
||||
dir: '/path/to/my/app',
|
||||
osxSign: {
|
||||
identity: 'Developer ID Application: Felix Rieseberg (LT94ZKYDCJ)',
|
||||
'hardened-runtime': true,
|
||||
entitlements: 'entitlements.plist',
|
||||
'entitlements-inherit': 'entitlements.plist',
|
||||
'signature-flags': 'library'
|
||||
},
|
||||
osxSign: {},
|
||||
osxNotarize: {
|
||||
appleId: 'felix@felix.fun',
|
||||
appleIdPassword: 'my-apple-id-password'
|
||||
@@ -84,26 +80,6 @@ packager({
|
||||
})
|
||||
```
|
||||
|
||||
The `entitlements.plist` file referenced here needs the following macOS-specific entitlements
|
||||
to assure the Apple security mechanisms that your app is doing these things
|
||||
without meaning any harm:
|
||||
|
||||
```xml title="entitlements.plist"
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>com.apple.security.cs.allow-jit</key>
|
||||
<true/>
|
||||
<key>com.apple.security.cs.debugger</key>
|
||||
<true/>
|
||||
</dict>
|
||||
</plist>
|
||||
```
|
||||
|
||||
Up until Electron 12, the `com.apple.security.cs.allow-unsigned-executable-memory` entitlement was required
|
||||
as well. However, it should not be used anymore if it can be avoided.
|
||||
|
||||
### Signing Mac App Store applications
|
||||
|
||||
See the [Mac App Store Guide].
|
||||
@@ -213,15 +189,14 @@ can find [its documentation here](https://www.electron.build/code-signing).
|
||||
See the [Windows Store Guide].
|
||||
|
||||
[apple developer program]: https://developer.apple.com/programs/
|
||||
[`electron-builder`]: https://github.com/electron-userland/electron-builder
|
||||
[`electron-forge`]: https://github.com/electron-userland/electron-forge
|
||||
[`electron-osx-sign`]: https://github.com/electron-userland/electron-osx-sign
|
||||
[`electron-forge`]: https://github.com/electron/forge
|
||||
[`@electron/osx-sign`]: https://github.com/electron/osx-sign
|
||||
[`electron-packager`]: https://github.com/electron/electron-packager
|
||||
[`electron-notarize`]: https://github.com/electron/electron-notarize
|
||||
[`@electron/notarize`]: https://github.com/electron/notarize
|
||||
[`electron-winstaller`]: https://github.com/electron/windows-installer
|
||||
[`electron-wix-msi`]: https://github.com/felixrieseberg/electron-wix-msi
|
||||
[`electron-wix-msi`]: https://github.com/electron-userland/electron-wix-msi
|
||||
[xcode]: https://developer.apple.com/xcode
|
||||
[signing certificates]: https://github.com/electron/electron-osx-sign/wiki/1.-Getting-Started#certificates
|
||||
[signing certificates]: https://developer.apple.com/support/certificates/
|
||||
[mac app store guide]: ./mac-app-store-submission-guide.md
|
||||
[windows store guide]: ./windows-store-guide.md
|
||||
[maker-squirrel]: https://www.electronforge.io/config/makers/squirrel.windows
|
||||
|
||||
@@ -7,28 +7,29 @@ check out our [Electron Versioning](./electron-versioning.md) doc.
|
||||
|
||||
## Timeline
|
||||
|
||||
| Electron | Alpha | Beta | Stable | Chrome | Node | Supported |
|
||||
| ------- | ----- | ------- | ------ | ------ | ---- | ---- |
|
||||
| 2.0.0 | -- | 2018-Feb-21 | 2018-May-01 | M61 | v8.9 | 🚫 |
|
||||
| 3.0.0 | -- | 2018-Jun-21 | 2018-Sep-18 | M66 | v10.2 | 🚫 |
|
||||
| 4.0.0 | -- | 2018-Oct-11 | 2018-Dec-20 | M69 | v10.11 | 🚫 |
|
||||
| 5.0.0 | -- | 2019-Jan-22 | 2019-Apr-24 | M73 | v12.0 | 🚫 |
|
||||
| 6.0.0 | -- | 2019-May-01 | 2019-Jul-30 | M76 | v12.4 | 🚫 |
|
||||
| 7.0.0 | -- | 2019-Aug-01 | 2019-Oct-22 | M78 | v12.8 | 🚫 |
|
||||
| 8.0.0 | -- | 2019-Oct-24 | 2020-Feb-04 | M80 | v12.13 | 🚫 |
|
||||
| 9.0.0 | -- | 2020-Feb-06 | 2020-May-19 | M83 | v12.14 | 🚫 |
|
||||
| 10.0.0 | -- | 2020-May-21 | 2020-Aug-25 | M85 | v12.16 | 🚫 |
|
||||
| 11.0.0 | -- | 2020-Aug-27 | 2020-Nov-17 | M87 | v12.18 | 🚫 |
|
||||
| 12.0.0 | -- | 2020-Nov-19 | 2021-Mar-02 | M89 | v14.16 | 🚫 |
|
||||
| 13.0.0 | -- | 2021-Mar-04 | 2021-May-25 | M91 | v14.16 | 🚫 |
|
||||
| 14.0.0 | -- | 2021-May-27 | 2021-Aug-31 | M93 | v14.17 | 🚫 |
|
||||
| 15.0.0 | 2021-Jul-20 | 2021-Sep-01 | 2021-Sep-21 | M94 | v16.5 | 🚫 |
|
||||
| 16.0.0 | 2021-Sep-23 | 2021-Oct-20 | 2021-Nov-16 | M96 | v16.9 | 🚫 |
|
||||
| 17.0.0 | 2021-Nov-18 | 2022-Jan-06 | 2022-Feb-01 | M98 | v16.13 | 🚫 |
|
||||
| 18.0.0 | 2022-Feb-03 | 2022-Mar-03 | 2022-Mar-29 | M100 | v16.13 | ✅ |
|
||||
| 19.0.0 | 2022-Mar-31 | 2022-Apr-26 | 2022-May-24 | M102 | v16.14 | ✅ |
|
||||
| 20.0.0 | 2022-May-26 | 2022-Jun-21 | 2022-Aug-02 | M104 | v16.15 | ✅ |
|
||||
| 21.0.0 | 2022-Aug-04 | 2022-Aug-30 | 2022-Sep-27 | M106 | TBD | ✅ |
|
||||
| Electron | Alpha | Beta | Stable | EOL | Chrome | Node | Supported |
|
||||
| ------- | ----- | ------- | ------ | ------ | ---- | ---- | ---- |
|
||||
| 22.0.0 | 2022-Sep-29 | 2022-Oct-25 | 2022-Nov-29 | TBD | M108 | TBD | ✅ |
|
||||
| 21.0.0 | 2022-Aug-04 | 2022-Aug-30 | 2022-Sep-27 | TBD | M106 | v16.17 | ✅ |
|
||||
| 20.0.0 | 2022-May-26 | 2022-Jun-21 | 2022-Aug-02 | TBD | M104 | v16.15 | ✅ |
|
||||
| 19.0.0 | 2022-Mar-31 | 2022-Apr-26 | 2022-May-24 | TBD | M102 | v16.14 | ✅ |
|
||||
| 18.0.0 | 2022-Feb-03 | 2022-Mar-03 | 2022-Mar-29 | 2022-Sep-27 | M100 | v16.13 | 🚫 |
|
||||
| 17.0.0 | 2021-Nov-18 | 2022-Jan-06 | 2022-Feb-01 | 2022-Aug-02 | M98 | v16.13 | 🚫 |
|
||||
| 16.0.0 | 2021-Sep-23 | 2021-Oct-20 | 2021-Nov-16 | 2022-May-24 | M96 | v16.9 | 🚫 |
|
||||
| 15.0.0 | 2021-Jul-20 | 2021-Sep-01 | 2021-Sep-21 | 2022-May-24 | M94 | v16.5 | 🚫 |
|
||||
| 14.0.0 | -- | 2021-May-27 | 2021-Aug-31 | 2022-Mar-29 | M93 | v14.17 | 🚫 |
|
||||
| 13.0.0 | -- | 2021-Mar-04 | 2021-May-25 | 2022-Feb-01 | M91 | v14.16 | 🚫 |
|
||||
| 12.0.0 | -- | 2020-Nov-19 | 2021-Mar-02 | 2021-Nov-16 | M89 | v14.16 | 🚫 |
|
||||
| 11.0.0 | -- | 2020-Aug-27 | 2020-Nov-17 | 2021-Aug-31 | M87 | v12.18 | 🚫 |
|
||||
| 10.0.0 | -- | 2020-May-21 | 2020-Aug-25 | 2021-May-25 | M85 | v12.16 | 🚫 |
|
||||
| 9.0.0 | -- | 2020-Feb-06 | 2020-May-19 | 2021-Mar-02 | M83 | v12.14 | 🚫 |
|
||||
| 8.0.0 | -- | 2019-Oct-24 | 2020-Feb-04 | 2020-Nov-17 | M80 | v12.13 | 🚫 |
|
||||
| 7.0.0 | -- | 2019-Aug-01 | 2019-Oct-22 | 2020-Aug-25 | M78 | v12.8 | 🚫 |
|
||||
| 6.0.0 | -- | 2019-Apr-25 | 2019-Jul-30 | 2020-May-19 | M76 | v12.14.0 | 🚫 |
|
||||
| 5.0.0 | -- | 2019-Jan-22 | 2019-Apr-23 | 2020-Feb-04 | M73 | v12.0 | 🚫 |
|
||||
| 4.0.0 | -- | 2018-Oct-11 | 2018-Dec-20 | 2019-Oct-22 | M69 | v10.11 | 🚫 |
|
||||
| 3.0.0 | -- | 2018-Jun-21 | 2018-Sep-18 | 2019-Jul-30 | M66 | v10.2 | 🚫 |
|
||||
| 2.0.0 | -- | 2018-Feb-21 | 2018-May-01 | 2019-Apr-23 | M61 | v8.9 | 🚫 |
|
||||
|
||||
**Notes:**
|
||||
|
||||
|
||||
@@ -11,7 +11,7 @@ This guide provides information on:
|
||||
To sign Electron apps, the following tools must be installed first:
|
||||
|
||||
* Xcode 11 or above.
|
||||
* The [electron-osx-sign][electron-osx-sign] npm module.
|
||||
* The [@electron/osx-sign] npm module.
|
||||
|
||||
You also have to register an Apple Developer account and join the
|
||||
[Apple Developer Program][developer-program].
|
||||
@@ -103,7 +103,7 @@ Apps submitted to the Mac App Store must run under Apple's
|
||||
the App Sandbox. The standard darwin build of Electron will fail to launch
|
||||
when run under App Sandbox.
|
||||
|
||||
When signing the app with `electron-osx-sign`, it will automatically add the
|
||||
When signing the app with `@electron/osx-sign`, it will automatically add the
|
||||
necessary entitlements to your app's entitlements, but if you are using custom
|
||||
entitlements, you must ensure App Sandbox capacity is added:
|
||||
|
||||
@@ -120,7 +120,7 @@ entitlements, you must ensure App Sandbox capacity is added:
|
||||
|
||||
#### Extra steps without `electron-osx-sign`
|
||||
|
||||
If you are signing your app without using `electron-osx-sign`, you must ensure
|
||||
If you are signing your app without using `@electron/osx-sign`, you must ensure
|
||||
the app bundle's entitlements have at least following keys:
|
||||
|
||||
```xml
|
||||
@@ -170,22 +170,22 @@ your Apple Developer account's Team ID as its value:
|
||||
</plist>
|
||||
```
|
||||
|
||||
When using `electron-osx-sign` the `ElectronTeamID` key will be added
|
||||
When using `@electron/osx-sign` the `ElectronTeamID` key will be added
|
||||
automatically by extracting the Team ID from the certificate's name. You may
|
||||
need to manually add this key if `electron-osx-sign` could not find the correct
|
||||
need to manually add this key if `@electron/osx-sign` could not find the correct
|
||||
Team ID.
|
||||
|
||||
### Sign apps for development
|
||||
|
||||
To sign an app that can run on your development machine, you must sign it with
|
||||
the "Apple Development" certificate and pass the provisioning profile to
|
||||
`electron-osx-sign`.
|
||||
`@electron/osx-sign`.
|
||||
|
||||
```bash
|
||||
electron-osx-sign YourApp.app --identity='Apple Development' --provisioning-profile=/path/to/yourapp.provisionprofile
|
||||
```
|
||||
|
||||
If you are signing without `electron-osx-sign`, you must place the provisioning
|
||||
If you are signing without `@electron/osx-sign`, you must place the provisioning
|
||||
profile to `YourApp.app/Contents/embedded.provisionprofile`.
|
||||
|
||||
The signed app can only run on the machines that registered by the provisioning
|
||||
@@ -213,7 +213,7 @@ use App Sandbox.
|
||||
electron-osx-sign YourApp.app --identity='Developer ID Application' --no-gatekeeper-assess
|
||||
```
|
||||
|
||||
By passing `--no-gatekeeper-assess`, the `electron-osx-sign` will skip the macOS
|
||||
By passing `--no-gatekeeper-assess`, `@electron/osx-sign` will skip the macOS
|
||||
GateKeeper check as your app usually has not been notarized yet by this step.
|
||||
|
||||
<!-- TODO(zcbenz): Add a chapter about App Notarization -->
|
||||
@@ -232,7 +232,7 @@ how to meet the Mac App Store requirements.
|
||||
|
||||
### Upload
|
||||
|
||||
The Application Loader should be used to upload the signed app to iTunes
|
||||
[Apple Transporter][apple-transporter] should be used to upload the signed app to App Store
|
||||
Connect for processing, making sure you have [created a record][create-record]
|
||||
before uploading.
|
||||
|
||||
@@ -341,11 +341,12 @@ Electron uses following cryptographic algorithms:
|
||||
* RIPEMD - [ISO/IEC 10118-3](https://webstore.ansi.org/RecordDetail.aspx?sku=ISO%2FIEC%2010118-3:2004)
|
||||
|
||||
[developer-program]: https://developer.apple.com/support/compare-memberships/
|
||||
[electron-osx-sign]: https://github.com/electron/electron-osx-sign
|
||||
[@electron/osx-sign]: https://github.com/electron/electron-osx-sign
|
||||
[app-sandboxing]: https://developer.apple.com/app-sandboxing/
|
||||
[app-notarization]: https://developer.apple.com/documentation/security/notarizing_macos_software_before_distribution
|
||||
[submitting-your-app]: https://developer.apple.com/library/mac/documentation/IDEs/Conceptual/AppDistributionGuide/SubmittingYourApp/SubmittingYourApp.html
|
||||
[create-record]: https://developer.apple.com/library/ios/documentation/LanguagesUtilities/Conceptual/iTunesConnect_Guide/Chapters/CreatingiTunesConnectRecord.html
|
||||
[create-record]: https://help.apple.com/app-store-connect/#/dev2cd126805
|
||||
[apple-transporter]: https://help.apple.com/itc/transporteruserguide/en.lproj/static.html
|
||||
[submit-for-review]: https://developer.apple.com/library/ios/documentation/LanguagesUtilities/Conceptual/iTunesConnect_Guide/Chapters/SubmittingTheApp.html
|
||||
[export-compliance]: https://help.apple.com/app-store-connect/#/devc3f64248f
|
||||
[user-selected]: https://developer.apple.com/library/mac/documentation/Miscellaneous/Reference/EntitlementKeyReference/Chapters/EnablingAppSandbox.html#//apple_ref/doc/uid/TP40011195-CH4-SW6
|
||||
|
||||
@@ -20,6 +20,8 @@ const win = new BrowserWindow({
|
||||
The `nodeIntegrationInWorker` can be used independent of `nodeIntegration`, but
|
||||
`sandbox` must not be set to `true`.
|
||||
|
||||
**Note:** This option is not available in [`SharedWorker`s](https://developer.mozilla.org/en-US/docs/Web/API/SharedWorker) or [`Service Worker`s](https://developer.mozilla.org/en-US/docs/Web/API/ServiceWorker) owing to incompatibilities in sandboxing policies.
|
||||
|
||||
## Available APIs
|
||||
|
||||
All built-in modules of Node.js are supported in Web Workers, and `asar`
|
||||
|
||||
@@ -1,95 +0,0 @@
|
||||
# Testing Widevine CDM
|
||||
|
||||
In Electron you can use the Widevine CDM library shipped with Chrome browser.
|
||||
|
||||
Widevine Content Decryption Modules (CDMs) are how streaming services protect
|
||||
content using HTML5 video to web browsers without relying on an NPAPI plugin
|
||||
like Flash or Silverlight. Widevine support is an alternative solution for
|
||||
streaming services that currently rely on Silverlight for playback of
|
||||
DRM-protected video content. It will allow websites to show DRM-protected video
|
||||
content in Firefox without the use of NPAPI plugins. The Widevine CDM runs in an
|
||||
open-source CDM sandbox providing better user security than NPAPI plugins.
|
||||
|
||||
#### Note on VMP
|
||||
|
||||
As of [`Electron v1.8.0 (Chrome v59)`](https://electronjs.org/releases#1.8.1),
|
||||
the below steps are may only be some of the necessary steps to enable Widevine;
|
||||
any app on or after that version intending to use the Widevine CDM may need to
|
||||
be signed using a license obtained from [Widevine](https://www.widevine.com/)
|
||||
itself.
|
||||
|
||||
Per [Widevine](https://www.widevine.com/):
|
||||
|
||||
> Chrome 59 (and later) includes support for Verified Media Path (VMP). VMP
|
||||
> provides a method to verify the authenticity of a device platform. For browser
|
||||
> deployments, this will provide an additional signal to determine if a
|
||||
> browser-based implementation is reliable and secure.
|
||||
>
|
||||
> The proxy integration guide has been updated with information about VMP and
|
||||
> how to issue licenses.
|
||||
>
|
||||
> Widevine recommends our browser-based integrations (vendors and browser-based
|
||||
> applications) add support for VMP.
|
||||
|
||||
To enable video playback with this new restriction,
|
||||
[castLabs](https://castlabs.com/open-source/downstream/) has created a
|
||||
[fork](https://github.com/castlabs/electron-releases) that has implemented the
|
||||
necessary changes to enable Widevine to be played in an Electron application if
|
||||
one has obtained the necessary licenses from widevine.
|
||||
|
||||
## Getting the library
|
||||
|
||||
Open `chrome://components/` in Chrome browser, find `Widevine Content Decryption Module`
|
||||
and make sure it is up to date, then you can find the library files from the
|
||||
application directory.
|
||||
|
||||
### On Windows
|
||||
|
||||
The library file `widevinecdm.dll` will be under
|
||||
`Program Files(x86)/Google/Chrome/Application/CHROME_VERSION/WidevineCdm/_platform_specific/win_(x86|x64)/`
|
||||
directory.
|
||||
|
||||
### On macOS
|
||||
|
||||
The library file `libwidevinecdm.dylib` will be under
|
||||
`/Applications/Google Chrome.app/Contents/Versions/CHROME_VERSION/Google Chrome Framework.framework/Versions/A/Libraries/WidevineCdm/_platform_specific/mac_(x86|x64)/`
|
||||
directory.
|
||||
|
||||
**Note:** Make sure that chrome version used by Electron is greater than or
|
||||
equal to the `min_chrome_version` value of Chrome's widevine cdm component.
|
||||
The value can be found in `manifest.json` under `WidevineCdm` directory.
|
||||
|
||||
## Using the library
|
||||
|
||||
After getting the library files, you should pass the path to the file
|
||||
with `--widevine-cdm-path` command line switch, and the library's version
|
||||
with `--widevine-cdm-version` switch. The command line switches have to be
|
||||
passed before the `ready` event of `app` module gets emitted.
|
||||
|
||||
Example code:
|
||||
|
||||
```javascript
|
||||
const { app, BrowserWindow } = require('electron')
|
||||
|
||||
// You have to pass the directory that contains widevine library here, it is
|
||||
// * `libwidevinecdm.dylib` on macOS,
|
||||
// * `widevinecdm.dll` on Windows.
|
||||
app.commandLine.appendSwitch('widevine-cdm-path', '/path/to/widevine_library')
|
||||
// The version of plugin can be got from `chrome://components` page in Chrome.
|
||||
app.commandLine.appendSwitch('widevine-cdm-version', '1.4.8.866')
|
||||
|
||||
let win = null
|
||||
app.whenReady().then(() => {
|
||||
win = new BrowserWindow()
|
||||
win.show()
|
||||
})
|
||||
```
|
||||
|
||||
## Verifying Widevine CDM support
|
||||
|
||||
To verify whether widevine works, you can use following ways:
|
||||
|
||||
* Open https://shaka-player-demo.appspot.com/ and load a manifest that uses
|
||||
`Widevine`.
|
||||
* Open http://www.dash-player.com/demo/drm-test-area/, check whether the page
|
||||
says `bitdash uses Widevine in your browser`, then play the video.
|
||||
@@ -26,6 +26,15 @@ work on Windows, macOS, and Linux with a single JavaScript codebase.
|
||||
This tutorial will guide you through the process of developing a desktop
|
||||
application with Electron and distributing it to end users.
|
||||
|
||||
## Goals
|
||||
|
||||
This tutorial starts by guiding you through the process of piecing together
|
||||
a minimal Electron application from scratch, then teaches you how to
|
||||
package and distribute it to users using Electron Forge.
|
||||
|
||||
If you prefer to get a project started with a single-command boilerplate, we recommend you start
|
||||
with Electron Forge's [`create-electron-app`](https://www.electronforge.io/) command.
|
||||
|
||||
## Assumptions
|
||||
|
||||
Electron is a native wrapper layer for web apps and is run in a Node.js environment.
|
||||
|
||||
@@ -369,12 +369,12 @@ run. Create a launch.json configuration in a new `.vscode` folder in your projec
|
||||
"name": "Renderer",
|
||||
"port": 9222,
|
||||
"request": "attach",
|
||||
"type": "pwa-chrome",
|
||||
"type": "chrome",
|
||||
"webRoot": "${workspaceFolder}"
|
||||
},
|
||||
{
|
||||
"name": "Main",
|
||||
"type": "pwa-node",
|
||||
"type": "node",
|
||||
"request": "launch",
|
||||
"cwd": "${workspaceFolder}",
|
||||
"runtimeExecutable": "${workspaceFolder}/node_modules/.bin/electron",
|
||||
@@ -398,11 +398,11 @@ What we have done in the `launch.json` file is to create 3 configurations:
|
||||
- `Main` is used to start the main process and also expose port 9222 for remote debugging
|
||||
(`--remote-debugging-port=9222`). This is the port that we will use to attach the debugger
|
||||
for the `Renderer`. Because the main process is a Node.js process, the type is set to
|
||||
`pwa-node` (`pwa-` is the prefix that tells VS Code to use the latest JavaScript debugger).
|
||||
`node`.
|
||||
- `Renderer` is used to debug the renderer process. Because the main process is the one
|
||||
that creates the process, we have to "attach" to it (`"request": "attach"`) instead of
|
||||
creating a new one.
|
||||
The renderer process is a web one, so the debugger we have to use is `pwa-chrome`.
|
||||
The renderer process is a web one, so the debugger we have to use is `chrome`.
|
||||
- `Main + renderer` is a [compound task] that executes the previous ones simultaneously.
|
||||
|
||||
:::caution
|
||||
|
||||
@@ -70,10 +70,9 @@ the [Electron Forge CLI documentation].
|
||||
:::
|
||||
|
||||
You should also notice that your package.json now has a few more packages installed
|
||||
under your `devDependencies`, and contains an added `config.forge` field with an array
|
||||
of makers configured. **Makers** are Forge plugins that create distributables from
|
||||
your source code. You should see multiple makers in the pre-populated configuration,
|
||||
one for each target platform.
|
||||
under `devDependencies`, and a new `forge.config.js` file that exports a configuration
|
||||
object. You should see multiple makers (packages that generate distributable app bundles) in the
|
||||
pre-populated configuration, one for each target platform.
|
||||
|
||||
### Creating a distributable
|
||||
|
||||
@@ -111,13 +110,14 @@ Electron Forge can be configured to create distributables in different OS-specif
|
||||
|
||||
:::
|
||||
|
||||
:::tip Creating and Adding Application Icons
|
||||
:::tip Creating and adding application icons
|
||||
|
||||
Setting custom application icons requires a few additions to your config. Check out [Forge's icon tutorial] for more information.
|
||||
Setting custom application icons requires a few additions to your config.
|
||||
Check out [Forge's icon tutorial] for more information.
|
||||
|
||||
:::
|
||||
|
||||
:::note Packaging without Electron Forge
|
||||
:::info Packaging without Electron Forge
|
||||
|
||||
If you want to manually package your code, or if you're just interested understanding the
|
||||
mechanics behind packaging an Electron app, check out the full [Application Packaging]
|
||||
@@ -136,64 +136,51 @@ Code signing is a security technology that you use to certify that a desktop app
|
||||
created by a known source. Windows and macOS have their own OS-specific code signing
|
||||
systems that will make it difficult for users to download or launch unsigned applications.
|
||||
|
||||
If you already have code signing certificates for Windows and macOS, you can set your
|
||||
credentials in your Forge configuration. Otherwise, please refer to the full
|
||||
[Code Signing] documentation to learn how to purchase a certificate and for more information
|
||||
on the desktop app code signing process.
|
||||
|
||||
On macOS, code signing is done at the app packaging level. On Windows, distributable installers
|
||||
are signed instead.
|
||||
are signed instead. If you already have code signing certificates for Windows and macOS, you can set
|
||||
your credentials in your Forge configuration.
|
||||
|
||||
:::info
|
||||
|
||||
For more information on code signing, check out the
|
||||
[Signing macOS Apps](https://www.electronforge.io/guides/code-signing) guide in the Forge docs.
|
||||
|
||||
:::
|
||||
|
||||
<Tabs>
|
||||
<TabItem value="macos" label="macOS" default>
|
||||
|
||||
```json title='package.json' {6-18}
|
||||
{
|
||||
//...
|
||||
"config": {
|
||||
"forge": {
|
||||
//...
|
||||
"packagerConfig": {
|
||||
"osxSign": {
|
||||
"identity": "Developer ID Application: Felix Rieseberg (LT94ZKYDCJ)",
|
||||
"hardened-runtime": true,
|
||||
"entitlements": "entitlements.plist",
|
||||
"entitlements-inherit": "entitlements.plist",
|
||||
"signature-flags": "library"
|
||||
},
|
||||
"osxNotarize": {
|
||||
"appleId": "felix@felix.fun",
|
||||
"appleIdPassword": "this-is-a-secret"
|
||||
}
|
||||
}
|
||||
//...
|
||||
```js title='forge.config.js'
|
||||
module.exports = {
|
||||
packagerConfig: {
|
||||
osxSign: {},
|
||||
//...
|
||||
osxNotarize: {
|
||||
tool: 'notarytool',
|
||||
appleId: process.env.APPLE_ID,
|
||||
appleIdPassword: process.env.APPLE_PASSWORD,
|
||||
teamId: process.env.APPLE_TEAM_ID,
|
||||
}
|
||||
//...
|
||||
}
|
||||
//...
|
||||
}
|
||||
```
|
||||
|
||||
</TabItem>
|
||||
<TabItem value="windows" label="Windows">
|
||||
|
||||
```json title='package.json' {6-14}
|
||||
{
|
||||
```js title='forge.config.js'
|
||||
module.exports = {
|
||||
//...
|
||||
"config": {
|
||||
"forge": {
|
||||
//...
|
||||
"makers": [
|
||||
{
|
||||
"name": "@electron-forge/maker-squirrel",
|
||||
"config": {
|
||||
"certificateFile": "./cert.pfx",
|
||||
"certificatePassword": "this-is-a-secret"
|
||||
}
|
||||
}
|
||||
]
|
||||
//...
|
||||
}
|
||||
}
|
||||
makers: [
|
||||
{
|
||||
name: '@electron-forge/maker-squirrel',
|
||||
config: {
|
||||
certificateFile: './cert.pfx',
|
||||
certificatePassword: process.env.CERTIFICATE_PASSWORD,
|
||||
},
|
||||
},
|
||||
],
|
||||
//...
|
||||
}
|
||||
```
|
||||
@@ -214,13 +201,12 @@ information.
|
||||
|
||||
[`@electron/osx-sign`]: https://github.com/electron/osx-sign
|
||||
[application packaging]: ./application-distribution.md
|
||||
[code signing]: ./code-signing.md
|
||||
[`electron-packager`]: https://github.com/electron/electron-packager
|
||||
[`electron-winstaller`]: https://github.com/electron/windows-installer
|
||||
[electron forge]: https://www.electronforge.io
|
||||
[electron forge cli documentation]: https://www.electronforge.io/cli#commands
|
||||
[makers]: https://www.electronforge.io/config/makers
|
||||
[Forge's icon tutorial]: https://www.electronforge.io/guides/create-and-add-icons
|
||||
[forge's icon tutorial]: https://www.electronforge.io/guides/create-and-add-icons
|
||||
|
||||
<!-- Tutorial links -->
|
||||
|
||||
|
||||
@@ -78,27 +78,21 @@ Once you have it installed, you need to set it up in your Forge
|
||||
configuration. A full list of options is documented in the Forge's
|
||||
[`PublisherGitHubConfig`] API docs.
|
||||
|
||||
```json title='package.json' {6-16}
|
||||
{
|
||||
//...
|
||||
"config": {
|
||||
"forge": {
|
||||
"publishers": [
|
||||
{
|
||||
"name": "@electron-forge/publisher-github",
|
||||
"config": {
|
||||
"repository": {
|
||||
"owner": "github-user-name",
|
||||
"name": "github-repo-name"
|
||||
},
|
||||
"prerelease": false,
|
||||
"draft": true
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
//...
|
||||
```js title='forge.config.js'
|
||||
module.exports = {
|
||||
publishers: [
|
||||
{
|
||||
name: '@electron-forge/publisher-github',
|
||||
config: {
|
||||
repository: {
|
||||
owner: 'github-user-name',
|
||||
name: 'github-repo-name',
|
||||
},
|
||||
prerelease: false,
|
||||
draft: true,
|
||||
},
|
||||
},
|
||||
],
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
@@ -142,7 +142,6 @@ auto_filenames = {
|
||||
"lib/common/define-properties.ts",
|
||||
"lib/common/ipc-messages.ts",
|
||||
"lib/common/web-view-methods.ts",
|
||||
"lib/common/webpack-globals-provider.ts",
|
||||
"lib/renderer/api/context-bridge.ts",
|
||||
"lib/renderer/api/crash-reporter.ts",
|
||||
"lib/renderer/api/ipc-renderer.ts",
|
||||
|
||||
@@ -671,8 +671,6 @@ filenames = {
|
||||
"shell/renderer/electron_render_frame_observer.h",
|
||||
"shell/renderer/electron_renderer_client.cc",
|
||||
"shell/renderer/electron_renderer_client.h",
|
||||
"shell/renderer/electron_renderer_pepper_host_factory.cc",
|
||||
"shell/renderer/electron_renderer_pepper_host_factory.h",
|
||||
"shell/renderer/electron_sandboxed_renderer_client.cc",
|
||||
"shell/renderer/electron_sandboxed_renderer_client.h",
|
||||
"shell/renderer/guest_view_container.cc",
|
||||
|
||||
@@ -623,11 +623,11 @@ export const wrapFsWithAsar = (fs: Record<string, any>) => {
|
||||
};
|
||||
|
||||
const { readdir } = fs;
|
||||
fs.readdir = function (pathArgument: string, options: { encoding?: string | null; withFileTypes?: boolean } = {}, callback?: Function) {
|
||||
fs.readdir = function (pathArgument: string, options?: { encoding?: string | null; withFileTypes?: boolean } | null, callback?: Function) {
|
||||
const pathInfo = splitPath(pathArgument);
|
||||
if (typeof options === 'function') {
|
||||
callback = options;
|
||||
options = {};
|
||||
options = undefined;
|
||||
}
|
||||
if (!pathInfo.isAsar) return readdir.apply(this, arguments);
|
||||
const { asarPath, filePath } = pathInfo;
|
||||
@@ -646,7 +646,7 @@ export const wrapFsWithAsar = (fs: Record<string, any>) => {
|
||||
return;
|
||||
}
|
||||
|
||||
if (options.withFileTypes) {
|
||||
if (options && options.withFileTypes) {
|
||||
const dirents = [];
|
||||
for (const file of files) {
|
||||
const childPath = path.join(filePath, file);
|
||||
|
||||
@@ -173,13 +173,13 @@ WebContents.prototype.printToPDF = async function (options) {
|
||||
headerTemplate: '',
|
||||
footerTemplate: '',
|
||||
printBackground: false,
|
||||
scale: 1,
|
||||
scale: 1.0,
|
||||
paperWidth: 8.5,
|
||||
paperHeight: 11,
|
||||
marginTop: 0,
|
||||
marginBottom: 0,
|
||||
marginLeft: 0,
|
||||
marginRight: 0,
|
||||
paperHeight: 11.0,
|
||||
marginTop: 0.4,
|
||||
marginBottom: 0.4,
|
||||
marginLeft: 0.4,
|
||||
marginRight: 0.4,
|
||||
pageRanges: '',
|
||||
preferCSSPageSize: false
|
||||
};
|
||||
@@ -209,7 +209,7 @@ WebContents.prototype.printToPDF = async function (options) {
|
||||
if (typeof options.scale !== 'number') {
|
||||
return Promise.reject(new Error('scale must be a Number'));
|
||||
}
|
||||
printSettings.scaleFactor = options.scale;
|
||||
printSettings.scale = options.scale;
|
||||
}
|
||||
|
||||
const { pageSize } = options;
|
||||
@@ -449,12 +449,14 @@ WebContents.prototype.loadURL = function (url, options) {
|
||||
const removeListeners = () => {
|
||||
this.removeListener('did-finish-load', finishListener);
|
||||
this.removeListener('did-fail-load', failListener);
|
||||
this.removeListener('did-navigate-in-page', finishListener);
|
||||
this.removeListener('did-start-navigation', navigationListener);
|
||||
this.removeListener('did-stop-loading', stopLoadingListener);
|
||||
this.removeListener('destroyed', stopLoadingListener);
|
||||
};
|
||||
this.on('did-finish-load', finishListener);
|
||||
this.on('did-fail-load', failListener);
|
||||
this.on('did-navigate-in-page', finishListener);
|
||||
this.on('did-start-navigation', navigationListener);
|
||||
this.on('did-stop-loading', stopLoadingListener);
|
||||
this.on('destroyed', stopLoadingListener);
|
||||
|
||||
@@ -186,7 +186,10 @@ export class SrcAttribute extends WebViewAttribute {
|
||||
opts.userAgent = useragent;
|
||||
}
|
||||
|
||||
(this.webViewImpl.webviewNode as Electron.WebviewTag).loadURL(this.getValue(), opts);
|
||||
(this.webViewImpl.webviewNode as Electron.WebviewTag).loadURL(this.getValue(), opts)
|
||||
.catch(err => {
|
||||
console.error('Unexpected error while loading URL', err);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -21,8 +21,9 @@ global.module = new Module('electron/js2c/worker_init');
|
||||
global.require = makeRequireFunction(global.module);
|
||||
|
||||
// Set the __filename to the path of html file if it is file: protocol.
|
||||
if (self.location.protocol === 'file:') {
|
||||
const pathname = process.platform === 'win32' && self.location.pathname[0] === '/' ? self.location.pathname.substr(1) : self.location.pathname;
|
||||
// NB. 'self' isn't defined in an AudioWorklet.
|
||||
if (typeof self !== 'undefined' && self.location.protocol === 'file:') {
|
||||
const pathname = process.platform === 'win32' && self.location && self.location.pathname[0] === '/' ? self.location.pathname.substr(1) : self.location.pathname;
|
||||
global.__filename = path.normalize(decodeURIComponent(pathname));
|
||||
global.__dirname = path.dirname(global.__filename);
|
||||
|
||||
|
||||
@@ -70,29 +70,21 @@ function isInstalled () {
|
||||
|
||||
// unzips and makes path.txt point at the correct executable
|
||||
function extractFile (zipPath) {
|
||||
return new Promise((resolve, reject) => {
|
||||
const distPath = process.env.ELECTRON_OVERRIDE_DIST_PATH || path.join(__dirname, 'dist');
|
||||
const distPath = process.env.ELECTRON_OVERRIDE_DIST_PATH || path.join(__dirname, 'dist');
|
||||
|
||||
extract(zipPath, { dir: path.join(__dirname, 'dist') })
|
||||
.then(() => {
|
||||
// If the zip contains an "electron.d.ts" file,
|
||||
// move that up
|
||||
const srcTypeDefPath = path.join(distPath, 'electron.d.ts');
|
||||
const targetTypeDefPath = path.join(__dirname, 'electron.d.ts');
|
||||
const hasTypeDefinitions = fs.existsSync(srcTypeDefPath);
|
||||
return extract(zipPath, { dir: path.join(__dirname, 'dist') }).then(() => {
|
||||
// If the zip contains an "electron.d.ts" file,
|
||||
// move that up
|
||||
const srcTypeDefPath = path.join(distPath, 'electron.d.ts');
|
||||
const targetTypeDefPath = path.join(__dirname, 'electron.d.ts');
|
||||
const hasTypeDefinitions = fs.existsSync(srcTypeDefPath);
|
||||
|
||||
if (hasTypeDefinitions) {
|
||||
try {
|
||||
fs.renameSync(srcTypeDefPath, targetTypeDefPath);
|
||||
} catch (err) {
|
||||
reject(err);
|
||||
}
|
||||
}
|
||||
if (hasTypeDefinitions) {
|
||||
fs.renameSync(srcTypeDefPath, targetTypeDefPath);
|
||||
}
|
||||
|
||||
// Write a "path.txt" file.
|
||||
return fs.promises.writeFile(path.join(__dirname, 'path.txt'), platformPath);
|
||||
})
|
||||
.catch((err) => reject(err));
|
||||
// Write a "path.txt" file.
|
||||
return fs.promises.writeFile(path.join(__dirname, 'path.txt'), platformPath);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
14
package.json
14
package.json
@@ -1,13 +1,14 @@
|
||||
{
|
||||
"name": "electron",
|
||||
"version": "21.1.0",
|
||||
"version": "0.0.0-development",
|
||||
"repository": "https://github.com/electron/electron",
|
||||
"description": "Build cross platform desktop apps with JavaScript, HTML, and CSS",
|
||||
"devDependencies": {
|
||||
"@azure/storage-blob": "^12.9.0",
|
||||
"@electron/docs-parser": "^0.12.4",
|
||||
"@electron/typescript-definitions": "^8.9.5",
|
||||
"@octokit/auth-app": "^2.10.0",
|
||||
"@electron/asar": "^3.2.1",
|
||||
"@electron/docs-parser": "^1.0.0",
|
||||
"@electron/github-app-auth": "^1.5.0",
|
||||
"@electron/typescript-definitions": "^8.10.0",
|
||||
"@octokit/rest": "^18.0.3",
|
||||
"@primer/octicons": "^10.0.0",
|
||||
"@types/basic-auth": "^1.1.3",
|
||||
@@ -31,7 +32,6 @@
|
||||
"@types/webpack-env": "^1.16.3",
|
||||
"@typescript-eslint/eslint-plugin": "^4.4.1",
|
||||
"@typescript-eslint/parser": "^4.4.1",
|
||||
"asar": "^3.1.0",
|
||||
"aws-sdk": "^2.814.0",
|
||||
"check-for-leaks": "^1.2.1",
|
||||
"colors": "1.4.0",
|
||||
@@ -89,7 +89,7 @@
|
||||
"lint:docs-relative-links": "python3 ./script/check-relative-doc-links.py",
|
||||
"lint:markdownlint": "markdownlint \"*.md\" \"docs/**/*.md\"",
|
||||
"lint:js-in-markdown": "standard-markdown docs",
|
||||
"create-api-json": "electron-docs-parser --dir=./",
|
||||
"create-api-json": "node script/create-api-json.js",
|
||||
"create-typescript-definitions": "npm run create-api-json && electron-typescript-definitions --api=electron-api.json && node spec/ts-smoke/runner.js",
|
||||
"gn-typescript-definitions": "npm run create-typescript-definitions && shx cp electron.d.ts",
|
||||
"pre-flight": "pre-flight",
|
||||
@@ -146,4 +146,4 @@
|
||||
"resolutions": {
|
||||
"nan": "nodejs/nan#16fa32231e2ccd89d2804b3f765319128b20c4ac"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
1
patches/angle/.patches
Normal file
1
patches/angle/.patches
Normal file
@@ -0,0 +1 @@
|
||||
fix_rename_webswapcgllayer_to_webswapcgllayerchromium.patch
|
||||
@@ -0,0 +1,66 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Milan Burda <milan.burda@gmail.com>
|
||||
Date: Mon, 10 Oct 2022 15:11:08 +0400
|
||||
Subject: fix: rename WebSwapCGLLayer to WebSwapCGLLayerChromium
|
||||
|
||||
Class WebSwapCGLLayer is implemented in both /System/Library/Frameworks/WebKit.framework/Versions/A/Frameworks/WebCore.framework/Versions/A/Frameworks/libANGLE-shared.dylib (0x23c589b50)
|
||||
and src/out/testing/Electron.app/Contents/Frameworks/Electron Framework.framework/Versions/A/Libraries/libGLESv2.dylib (0x1123f8488).
|
||||
One of the two will be used. Which one is undefined.
|
||||
|
||||
diff --git a/src/libANGLE/renderer/gl/cgl/WindowSurfaceCGL.h b/src/libANGLE/renderer/gl/cgl/WindowSurfaceCGL.h
|
||||
index 783a3dff46f04ed07934e516a3c39b061402cc84..056b242ab72eba87b036fc3e56c38a89800f1cdd 100644
|
||||
--- a/src/libANGLE/renderer/gl/cgl/WindowSurfaceCGL.h
|
||||
+++ b/src/libANGLE/renderer/gl/cgl/WindowSurfaceCGL.h
|
||||
@@ -18,7 +18,7 @@ struct __IOSurface;
|
||||
typedef __IOSurface *IOSurfaceRef;
|
||||
|
||||
// WebKit's build process requires that every Objective-C class name has the prefix "Web".
|
||||
-@class WebSwapCGLLayer;
|
||||
+@class WebSwapCGLLayerChromium;
|
||||
|
||||
namespace rx
|
||||
{
|
||||
@@ -87,7 +87,7 @@ class WindowSurfaceCGL : public SurfaceGL
|
||||
const gl::FramebufferState &state) override;
|
||||
|
||||
private:
|
||||
- WebSwapCGLLayer *mSwapLayer;
|
||||
+ WebSwapCGLLayerChromium *mSwapLayer;
|
||||
SharedSwapState mSwapState;
|
||||
uint64_t mCurrentSwapId;
|
||||
|
||||
diff --git a/src/libANGLE/renderer/gl/cgl/WindowSurfaceCGL.mm b/src/libANGLE/renderer/gl/cgl/WindowSurfaceCGL.mm
|
||||
index 21894682d4a16f6c4133c4919aba8631f022d1ea..4a4be7f38abbe8242756a6abf810da80e98763c2 100644
|
||||
--- a/src/libANGLE/renderer/gl/cgl/WindowSurfaceCGL.mm
|
||||
+++ b/src/libANGLE/renderer/gl/cgl/WindowSurfaceCGL.mm
|
||||
@@ -24,7 +24,7 @@
|
||||
# include "libANGLE/renderer/gl/StateManagerGL.h"
|
||||
# include "libANGLE/renderer/gl/cgl/DisplayCGL.h"
|
||||
|
||||
-@interface WebSwapCGLLayer : CAOpenGLLayer {
|
||||
+@interface WebSwapCGLLayerChromium : CAOpenGLLayer {
|
||||
CGLContextObj mDisplayContext;
|
||||
|
||||
bool initialized;
|
||||
@@ -38,7 +38,7 @@ - (id)initWithSharedState:(rx::SharedSwapState *)swapState
|
||||
withFunctions:(const rx::FunctionsGL *)functions;
|
||||
@end
|
||||
|
||||
-@implementation WebSwapCGLLayer
|
||||
+@implementation WebSwapCGLLayerChromium
|
||||
- (id)initWithSharedState:(rx::SharedSwapState *)swapState
|
||||
withContext:(CGLContextObj)displayContext
|
||||
withFunctions:(const rx::FunctionsGL *)functions
|
||||
@@ -213,9 +213,9 @@ - (void)drawInCGLContext:(CGLContextObj)glContext
|
||||
mSwapState.lastRendered = &mSwapState.textures[1];
|
||||
mSwapState.beingPresented = &mSwapState.textures[2];
|
||||
|
||||
- mSwapLayer = [[WebSwapCGLLayer alloc] initWithSharedState:&mSwapState
|
||||
- withContext:mContext
|
||||
- withFunctions:mFunctions];
|
||||
+ mSwapLayer = [[WebSwapCGLLayerChromium alloc] initWithSharedState:&mSwapState
|
||||
+ withContext:mContext
|
||||
+ withFunctions:mFunctions];
|
||||
[mLayer addSublayer:mSwapLayer];
|
||||
[mSwapLayer setContentsScale:[mLayer contentsScale]];
|
||||
|
||||
@@ -123,3 +123,31 @@ disable_optimization_guide_for_preconnect_feature.patch
|
||||
fix_the_gn_gen_for_components_segmentation_platform.patch
|
||||
fix_crash_loading_non-standard_schemes_in_iframes.patch
|
||||
create_browser_v8_snapshot_file_name_fuse.patch
|
||||
cherry-pick-c83640db21b5.patch
|
||||
fix_on-screen-keyboard_hides_on_input_blur_in_webview.patch
|
||||
build_allow_electron_to_use_exec_script.patch
|
||||
cherry-pick-67c9cbc784d6.patch
|
||||
cherry-pick-933cc81c6bad.patch
|
||||
cherry-pick-65d46507a0c9.patch
|
||||
cherry-pick-176c526846cb.patch
|
||||
cherry-pick-f46db6aac3e9.patch
|
||||
cherry-pick-9b3d0e2f1aab.patch
|
||||
cherry-pick-42e15c2055c4.patch
|
||||
cherry-pick-2ef09109c0ec.patch
|
||||
cherry-pick-f98adc846aad.patch
|
||||
cherry-pick-eed5a4de2c40.patch
|
||||
cherry-pick-d1d654d73222.patch
|
||||
cherry-pick-77208afba04d.patch
|
||||
cherry-pick-65ad70274d4b.patch
|
||||
cherry-pick-819d876e1bb8.patch
|
||||
mojo_disable_sync_call_interrupts_in_the_browser.patch
|
||||
mojo_validate_that_a_message_is_allowed_to_use_the_sync_flag.patch
|
||||
cherry-pick-43637378b14e.patch
|
||||
cherry-pick-57c54ae221d6.patch
|
||||
cherry-pick-ca2b108a0f1f.patch
|
||||
cherry-pick-d652130c4bc2.patch
|
||||
fix_uaf_problem_in_anglevulkanimagebacking.patch
|
||||
cherry-pick-06851790480e.patch
|
||||
cherry-pick-e79b89b47dac.patch
|
||||
m108-lts_simplify_webmediaplayermscompositor_destruction.patch
|
||||
m108-lts_further_simplify_webmediaplayermscompositor_lifetime.patch
|
||||
|
||||
@@ -0,0 +1,18 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Samuel Attard <sattard@salesforce.com>
|
||||
Date: Fri, 21 Oct 2022 16:29:06 -0700
|
||||
Subject: build: allow electron to use exec_script
|
||||
|
||||
This is similar to the //build usecase so we're OK adding ourselves here
|
||||
|
||||
diff --git a/.gn b/.gn
|
||||
index 7b9768eb315ef8a4d8d61bcf07d43c70f3ea9582..0857ee17a35dabc19c2a04f6a5dd7d631e4b7ee8 100644
|
||||
--- a/.gn
|
||||
+++ b/.gn
|
||||
@@ -169,4 +169,6 @@ exec_script_whitelist =
|
||||
|
||||
"//tools/grit/grit_rule.gni",
|
||||
"//tools/gritsettings/BUILD.gn",
|
||||
+
|
||||
+ "//electron/BUILD.gn"
|
||||
]
|
||||
91
patches/chromium/cherry-pick-06851790480e.patch
Normal file
91
patches/chromium/cherry-pick-06851790480e.patch
Normal file
@@ -0,0 +1,91 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: "Tommy C. Li" <tommycli@chromium.org>
|
||||
Date: Tue, 21 Feb 2023 18:55:00 +0000
|
||||
Subject: Exclude Policy and Play API engines from Sync merging
|
||||
|
||||
There's a security bug in which the call to ResetTemplateURLGUID can
|
||||
cause a policy-created engine to be deleted. This means that after
|
||||
the call, either the current `conflicting_turl` pointer, or future
|
||||
iterations in the loop may point to an already-freed TemplateURL,
|
||||
causing the use-after free bug.
|
||||
|
||||
This CL addresses that by forbidding Policy-created and Play API
|
||||
engines from being merged into Synced engines.
|
||||
|
||||
Although Play API engines aren't directly affected, they seem to also
|
||||
not be something that should be merged to Synced engines.
|
||||
|
||||
(cherry picked from commit 315632458eb795ef9d9dce3fd1062f9e6f2c2077)
|
||||
|
||||
Bug: 1414224
|
||||
Change-Id: Ide43d71e9844e04a7ffe2e7ad2a522b6ca1535a3
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/4250623
|
||||
Reviewed-by: Matthew Denton <mpdenton@chromium.org>
|
||||
Reviewed-by: Mikel Astiz <mastiz@chromium.org>
|
||||
Commit-Queue: Tommy Li <tommycli@chromium.org>
|
||||
Cr-Original-Commit-Position: refs/heads/main@{#1106249}
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/4274984
|
||||
Reviewed-by: Tommy Li <tommycli@chromium.org>
|
||||
Commit-Queue: Krishna Govind <govind@chromium.org>
|
||||
Cr-Commit-Position: refs/branch-heads/5481@{#1238}
|
||||
Cr-Branched-From: 130f3e4d850f4bc7387cfb8d08aa993d288a67a9-refs/heads/main@{#1084008}
|
||||
|
||||
diff --git a/chrome/browser/search_engines/template_url_service_sync_unittest.cc b/chrome/browser/search_engines/template_url_service_sync_unittest.cc
|
||||
index cc36b62044b14b07b08a176d36d606b96147526b..fb56b5cee060972e17d945d84d26247746277256 100644
|
||||
--- a/chrome/browser/search_engines/template_url_service_sync_unittest.cc
|
||||
+++ b/chrome/browser/search_engines/template_url_service_sync_unittest.cc
|
||||
@@ -732,6 +732,34 @@ TEST_F(TemplateURLServiceSyncTest, MergeAddFromNewerSyncData) {
|
||||
processor()->change_for_guid("localguid3").change_type());
|
||||
}
|
||||
|
||||
+TEST_F(TemplateURLServiceSyncTest, MergeIgnoresPolicyAndPlayAPIEngines) {
|
||||
+ // Add a policy-created engine.
|
||||
+ model()->Add(CreateTestTemplateURL(u"key1", "http://key1.com", "localguid1",
|
||||
+ base::Time::FromTimeT(100),
|
||||
+ /*safe_for_autoreplace=*/false,
|
||||
+ /*created_by_policy=*/true));
|
||||
+
|
||||
+ {
|
||||
+ auto play_api_engine = CreateTestTemplateURL(
|
||||
+ u"key2", "http://key2.com", "localguid2", base::Time::FromTimeT(100));
|
||||
+ TemplateURLData data(play_api_engine->data());
|
||||
+ data.created_from_play_api = true;
|
||||
+ play_api_engine = std::make_unique<TemplateURL>(data);
|
||||
+ model()->Add(std::move(play_api_engine));
|
||||
+ }
|
||||
+
|
||||
+ ASSERT_EQ(1U, model()->GetAllSyncData(syncer::SEARCH_ENGINES).size());
|
||||
+ MergeAndExpectNotify(CreateInitialSyncData(), 1);
|
||||
+
|
||||
+ // The policy engine should be ignored when it comes to conflict resolution.
|
||||
+ EXPECT_TRUE(model()->GetTemplateURLForGUID("guid1"));
|
||||
+ EXPECT_TRUE(model()->GetTemplateURLForGUID("localguid1"));
|
||||
+
|
||||
+ // The Play API engine should be ignored when it comes to conflict resolution.
|
||||
+ EXPECT_TRUE(model()->GetTemplateURLForGUID("guid2"));
|
||||
+ EXPECT_TRUE(model()->GetTemplateURLForGUID("localguid2"));
|
||||
+}
|
||||
+
|
||||
TEST_F(TemplateURLServiceSyncTest, ProcessChangesEmptyModel) {
|
||||
// We initially have no data.
|
||||
MergeAndExpectNotify({}, 0);
|
||||
diff --git a/components/search_engines/template_url_service.cc b/components/search_engines/template_url_service.cc
|
||||
index 9d84529033d3883ad007025fe766d4b9571b1439..4f2dbf6d2b2e5b51d967eec29b2e59c163bb46fa 100644
|
||||
--- a/components/search_engines/template_url_service.cc
|
||||
+++ b/components/search_engines/template_url_service.cc
|
||||
@@ -2143,7 +2143,14 @@ void TemplateURLService::MergeInSyncTemplateURL(
|
||||
keyword_to_turl_and_length_.equal_range(sync_turl->keyword());
|
||||
for (auto it = match_range.first; it != match_range.second; ++it) {
|
||||
TemplateURL* local_turl = it->second.first;
|
||||
- if (local_turl->type() == TemplateURL::NORMAL) {
|
||||
+ // The conflict resolution code below sometimes resets the TemplateURL's
|
||||
+ // GUID, which can trigger deleting any Policy-created engines. Avoid this
|
||||
+ // use-after-free bug by excluding any Policy-created engines. Also exclude
|
||||
+ // Play API created engines, as those also seem local-only and should not
|
||||
+ // be merged into Synced engines. crbug.com/1414224.
|
||||
+ if (local_turl->type() == TemplateURL::NORMAL &&
|
||||
+ !local_turl->created_by_policy() &&
|
||||
+ !local_turl->created_from_play_api()) {
|
||||
local_duplicates.push_back(local_turl);
|
||||
}
|
||||
}
|
||||
192
patches/chromium/cherry-pick-176c526846cb.patch
Normal file
192
patches/chromium/cherry-pick-176c526846cb.patch
Normal file
@@ -0,0 +1,192 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Robert Sesek <rsesek@chromium.org>
|
||||
Date: Fri, 18 Nov 2022 19:31:38 +0000
|
||||
Subject: Fix a data race leading to use-after-free in mojo::ChannelMac
|
||||
ShutDown
|
||||
|
||||
(cherry picked from commit bd8a1e43aa93d5bb7674cb5a431e7375f7e2f192)
|
||||
|
||||
Bug: 1378564
|
||||
Change-Id: I67041b1e2ef08dd0ee1ccbf6d534249c539b74db
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/4027242
|
||||
Commit-Queue: Robert Sesek <rsesek@chromium.org>
|
||||
Reviewed-by: Ken Rockot <rockot@google.com>
|
||||
Cr-Original-Commit-Position: refs/heads/main@{#1071700}
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/4035114
|
||||
Commit-Queue: Rubber Stamper <rubber-stamper@appspot.gserviceaccount.com>
|
||||
Auto-Submit: Robert Sesek <rsesek@chromium.org>
|
||||
Bot-Commit: Rubber Stamper <rubber-stamper@appspot.gserviceaccount.com>
|
||||
Cr-Commit-Position: refs/branch-heads/5359@{#881}
|
||||
Cr-Branched-From: 27d3765d341b09369006d030f83f582a29eb57ae-refs/heads/main@{#1058933}
|
||||
|
||||
diff --git a/mojo/core/channel_mac.cc b/mojo/core/channel_mac.cc
|
||||
index ce813f3d66a3d6841b4b04a625d8fd1a816b4a3e..344336b86d7ebb2df7be50db2d2f737320378342 100644
|
||||
--- a/mojo/core/channel_mac.cc
|
||||
+++ b/mojo/core/channel_mac.cc
|
||||
@@ -25,6 +25,7 @@
|
||||
#include "base/mac/scoped_mach_vm.h"
|
||||
#include "base/message_loop/message_pump_for_io.h"
|
||||
#include "base/task/current_thread.h"
|
||||
+#include "base/thread_annotations.h"
|
||||
#include "base/trace_event/typed_macros.h"
|
||||
|
||||
extern "C" {
|
||||
@@ -182,7 +183,10 @@ class ChannelMac : public Channel,
|
||||
vm_allocate(mach_task_self(), &address, size,
|
||||
VM_MAKE_TAG(VM_MEMORY_MACH_MSG) | VM_FLAGS_ANYWHERE);
|
||||
MACH_CHECK(kr == KERN_SUCCESS, kr) << "vm_allocate";
|
||||
- send_buffer_.reset(address, size);
|
||||
+ {
|
||||
+ base::AutoLock lock(write_lock_);
|
||||
+ send_buffer_.reset(address, size);
|
||||
+ }
|
||||
|
||||
kr = vm_allocate(mach_task_self(), &address, size,
|
||||
VM_MAKE_TAG(VM_MEMORY_MACH_MSG) | VM_FLAGS_ANYWHERE);
|
||||
@@ -222,7 +226,11 @@ class ChannelMac : public Channel,
|
||||
|
||||
watch_controller_.StopWatchingMachPort();
|
||||
|
||||
- send_buffer_.reset();
|
||||
+ {
|
||||
+ base::AutoLock lock(write_lock_);
|
||||
+ send_buffer_.reset();
|
||||
+ reject_writes_ = true;
|
||||
+ }
|
||||
receive_buffer_.reset();
|
||||
incoming_handles_.clear();
|
||||
|
||||
@@ -330,7 +338,7 @@ class ChannelMac : public Channel,
|
||||
SendPendingMessagesLocked();
|
||||
}
|
||||
|
||||
- void SendPendingMessagesLocked() {
|
||||
+ void SendPendingMessagesLocked() EXCLUSIVE_LOCKS_REQUIRED(write_lock_) {
|
||||
// If a previous send failed due to the receiver's kernel message queue
|
||||
// being full, attempt to send that failed message first.
|
||||
if (send_buffer_contains_message_ && !reject_writes_) {
|
||||
@@ -357,7 +365,8 @@ class ChannelMac : public Channel,
|
||||
}
|
||||
}
|
||||
|
||||
- bool SendMessageLocked(MessagePtr message) {
|
||||
+ bool SendMessageLocked(MessagePtr message)
|
||||
+ EXCLUSIVE_LOCKS_REQUIRED(write_lock_) {
|
||||
DCHECK(!send_buffer_contains_message_);
|
||||
base::BufferIterator<char> buffer(
|
||||
reinterpret_cast<char*>(send_buffer_.address()), send_buffer_.size());
|
||||
@@ -452,7 +461,8 @@ class ChannelMac : public Channel,
|
||||
return MachMessageSendLocked(header);
|
||||
}
|
||||
|
||||
- bool MachMessageSendLocked(mach_msg_header_t* header) {
|
||||
+ bool MachMessageSendLocked(mach_msg_header_t* header)
|
||||
+ EXCLUSIVE_LOCKS_REQUIRED(write_lock_) {
|
||||
kern_return_t kr = mach_msg(header, MACH_SEND_MSG | MACH_SEND_TIMEOUT,
|
||||
header->msgh_size, 0, MACH_PORT_NULL,
|
||||
/*timeout=*/0, MACH_PORT_NULL);
|
||||
@@ -674,7 +684,7 @@ class ChannelMac : public Channel,
|
||||
}
|
||||
|
||||
// Marks the channel as unaccepting of new messages and shuts it down.
|
||||
- void OnWriteErrorLocked(Error error) {
|
||||
+ void OnWriteErrorLocked(Error error) EXCLUSIVE_LOCKS_REQUIRED(write_lock_) {
|
||||
reject_writes_ = true;
|
||||
io_task_runner_->PostTask(
|
||||
FROM_HERE, base::BindOnce(&ChannelMac::OnError, this, error));
|
||||
@@ -716,17 +726,17 @@ class ChannelMac : public Channel,
|
||||
// Lock that protects the following members.
|
||||
base::Lock write_lock_;
|
||||
// Whether writes should be rejected due to an internal error.
|
||||
- bool reject_writes_ = false;
|
||||
+ bool reject_writes_ GUARDED_BY(write_lock_) = false;
|
||||
// IO buffer for sending Mach messages.
|
||||
- base::mac::ScopedMachVM send_buffer_;
|
||||
+ base::mac::ScopedMachVM send_buffer_ GUARDED_BY(write_lock_);
|
||||
// If a message timed out during send in MachMessageSendLocked(), this will
|
||||
// be true to indicate that |send_buffer_| contains a message that must
|
||||
// be sent. If this is true, then other calls to Write() queue messages onto
|
||||
// |pending_messages_|.
|
||||
- bool send_buffer_contains_message_ = false;
|
||||
+ bool send_buffer_contains_message_ GUARDED_BY(write_lock_) = false;
|
||||
// When |handshake_done_| is false or |send_buffer_contains_message_| is true,
|
||||
// calls to Write() will enqueue messages here.
|
||||
- base::circular_deque<MessagePtr> pending_messages_;
|
||||
+ base::circular_deque<MessagePtr> pending_messages_ GUARDED_BY(write_lock_);
|
||||
};
|
||||
|
||||
} // namespace
|
||||
diff --git a/mojo/core/channel_unittest.cc b/mojo/core/channel_unittest.cc
|
||||
index 3842426dbf494615628d47f9d9d563a631d117ad..2f5c95d79450021a1cbe4b9289f658ba84813453 100644
|
||||
--- a/mojo/core/channel_unittest.cc
|
||||
+++ b/mojo/core/channel_unittest.cc
|
||||
@@ -714,6 +714,69 @@ TEST(ChannelTest, SendToDeadMachPortName) {
|
||||
}
|
||||
#endif // BUILDFLAG(IS_MAC)
|
||||
|
||||
+TEST(ChannelTest, ShutDownStress) {
|
||||
+ base::test::SingleThreadTaskEnvironment task_environment(
|
||||
+ base::test::TaskEnvironment::MainThreadType::IO);
|
||||
+
|
||||
+ // Create a second IO thread for Channel B.
|
||||
+ base::Thread peer_thread("channel_b_io");
|
||||
+ peer_thread.StartWithOptions(
|
||||
+ base::Thread::Options(base::MessagePumpType::IO, 0));
|
||||
+
|
||||
+ // Create two channels, A and B, which run on different threads.
|
||||
+ PlatformChannel platform_channel;
|
||||
+
|
||||
+ CallbackChannelDelegate delegate_a;
|
||||
+ scoped_refptr<Channel> channel_a = Channel::Create(
|
||||
+ &delegate_a, ConnectionParams(platform_channel.TakeLocalEndpoint()),
|
||||
+ Channel::HandlePolicy::kRejectHandles,
|
||||
+ task_environment.GetMainThreadTaskRunner());
|
||||
+ channel_a->Start();
|
||||
+
|
||||
+ scoped_refptr<Channel> channel_b = Channel::Create(
|
||||
+ nullptr, ConnectionParams(platform_channel.TakeRemoteEndpoint()),
|
||||
+ Channel::HandlePolicy::kRejectHandles, peer_thread.task_runner());
|
||||
+ channel_b->Start();
|
||||
+
|
||||
+ base::WaitableEvent go_event;
|
||||
+
|
||||
+ // Warm up the channel to ensure that A and B are connected, then quit.
|
||||
+ channel_b->Write(Channel::Message::CreateMessage(0, 0));
|
||||
+ {
|
||||
+ base::RunLoop run_loop;
|
||||
+ delegate_a.set_on_message(run_loop.QuitClosure());
|
||||
+ run_loop.Run();
|
||||
+ }
|
||||
+
|
||||
+ // Block the peer thread while some tasks are queued up from the test main
|
||||
+ // thread.
|
||||
+ peer_thread.task_runner()->PostTask(
|
||||
+ FROM_HERE,
|
||||
+ base::BindOnce(&base::WaitableEvent::Wait, base::Unretained(&go_event)));
|
||||
+
|
||||
+ // First, write some messages for Channel B.
|
||||
+ for (int i = 0; i < 500; ++i) {
|
||||
+ channel_b->Write(Channel::Message::CreateMessage(0, 0));
|
||||
+ }
|
||||
+
|
||||
+ // Then shut down channel B.
|
||||
+ channel_b->ShutDown();
|
||||
+
|
||||
+ // Un-block the peer thread.
|
||||
+ go_event.Signal();
|
||||
+
|
||||
+ // And then flood the channel with messages. This will suss out data races
|
||||
+ // during Channel B's shutdown, since Writes can happen across threads
|
||||
+ // without a PostTask.
|
||||
+ for (int i = 0; i < 1000; ++i) {
|
||||
+ channel_b->Write(Channel::Message::CreateMessage(0, 0));
|
||||
+ }
|
||||
+
|
||||
+ // Explicitly join the thread to wait for pending tasks, which may reference
|
||||
+ // stack variables, to complete.
|
||||
+ peer_thread.Stop();
|
||||
+}
|
||||
+
|
||||
} // namespace
|
||||
} // namespace core
|
||||
} // namespace mojo
|
||||
364
patches/chromium/cherry-pick-2ef09109c0ec.patch
Normal file
364
patches/chromium/cherry-pick-2ef09109c0ec.patch
Normal file
@@ -0,0 +1,364 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Jun Kokatsu <jkokatsu@google.com>
|
||||
Date: Thu, 22 Sep 2022 22:16:55 +0000
|
||||
Subject: Unify security check for Javascript URL navigation
|
||||
|
||||
This change unifies CSP and Trusted Types check for Javascript URL
|
||||
navigations.
|
||||
|
||||
Bug: 1365082
|
||||
Change-Id: I46aea31a918c6397ea71fd5ab345bc9dc19d91c2
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3905476
|
||||
Auto-Submit: Jun Kokatsu <jkokatsu@google.com>
|
||||
Commit-Queue: Jun Kokatsu <jkokatsu@google.com>
|
||||
Reviewed-by: Nate Chapin <japhet@chromium.org>
|
||||
Cr-Commit-Position: refs/heads/main@{#1050416}
|
||||
|
||||
diff --git a/third_party/blink/renderer/bindings/core/v8/script_controller.cc b/third_party/blink/renderer/bindings/core/v8/script_controller.cc
|
||||
index 0a978ee553cd3bf4b15b923fbf8b93789c441774..1a79fa26c069d10e9e03390f161d70d2adb7b07e 100644
|
||||
--- a/third_party/blink/renderer/bindings/core/v8/script_controller.cc
|
||||
+++ b/third_party/blink/renderer/bindings/core/v8/script_controller.cc
|
||||
@@ -200,34 +200,9 @@ void ScriptController::ExecuteJavaScriptURL(
|
||||
const DOMWrapperWorld* world_for_csp) {
|
||||
DCHECK(url.ProtocolIsJavaScript());
|
||||
|
||||
- const int kJavascriptSchemeLength = sizeof("javascript:") - 1;
|
||||
- String script_source = DecodeURLEscapeSequences(
|
||||
- url.GetString(), DecodeURLMode::kUTF8OrIsomorphic);
|
||||
-
|
||||
if (!window_->GetFrame())
|
||||
return;
|
||||
|
||||
- auto* policy = window_->GetContentSecurityPolicyForWorld(world_for_csp);
|
||||
- if (csp_disposition == network::mojom::CSPDisposition::CHECK &&
|
||||
- !policy->AllowInline(ContentSecurityPolicy::InlineType::kNavigation,
|
||||
- nullptr, script_source, String() /* nonce */,
|
||||
- window_->Url(), EventHandlerPosition().line_)) {
|
||||
- return;
|
||||
- }
|
||||
-
|
||||
- // TODO(crbug.com/896041): Investigate how trusted type checks can be
|
||||
- // implemented for isolated worlds.
|
||||
- const bool should_bypass_trusted_type_check =
|
||||
- csp_disposition == network::mojom::CSPDisposition::DO_NOT_CHECK ||
|
||||
- ContentSecurityPolicy::ShouldBypassMainWorldDeprecated(world_for_csp);
|
||||
- script_source = script_source.Substring(kJavascriptSchemeLength);
|
||||
- if (!should_bypass_trusted_type_check) {
|
||||
- script_source = TrustedTypesCheckForJavascriptURLinNavigation(
|
||||
- script_source, window_.Get());
|
||||
- if (script_source.IsEmpty())
|
||||
- return;
|
||||
- }
|
||||
-
|
||||
bool had_navigation_before =
|
||||
window_->GetFrame()->Loader().HasProvisionalNavigation();
|
||||
|
||||
@@ -235,6 +210,9 @@ void ScriptController::ExecuteJavaScriptURL(
|
||||
// Step 6. "Let baseURL be settings's API base URL." [spec text]
|
||||
const KURL base_url = window_->BaseURL();
|
||||
|
||||
+ String script_source = window_->CheckAndGetJavascriptUrl(
|
||||
+ world_for_csp, url, nullptr /* element */, csp_disposition);
|
||||
+
|
||||
// Step 7. "Let script be the result of creating a classic script given
|
||||
// scriptSource, settings, baseURL, and the default classic script fetch
|
||||
// options." [spec text]
|
||||
diff --git a/third_party/blink/renderer/core/frame/local_dom_window.cc b/third_party/blink/renderer/core/frame/local_dom_window.cc
|
||||
index c4be7a96144ac53be856fbf52dff8e990aa736aa..12183222040fd9ab3e202a510cc71f2ccbf2e4c4 100644
|
||||
--- a/third_party/blink/renderer/core/frame/local_dom_window.cc
|
||||
+++ b/third_party/blink/renderer/core/frame/local_dom_window.cc
|
||||
@@ -418,6 +418,39 @@ bool LocalDOMWindow::CanExecuteScripts(
|
||||
return script_enabled;
|
||||
}
|
||||
|
||||
+String LocalDOMWindow::CheckAndGetJavascriptUrl(
|
||||
+ const DOMWrapperWorld* world,
|
||||
+ const KURL& url,
|
||||
+ Element* element,
|
||||
+ network::mojom::CSPDisposition csp_disposition) {
|
||||
+ const int kJavascriptSchemeLength = sizeof("javascript:") - 1;
|
||||
+ String decoded_url = DecodeURLEscapeSequences(
|
||||
+ url.GetString(), DecodeURLMode::kUTF8OrIsomorphic);
|
||||
+ String script_source = decoded_url.Substring(kJavascriptSchemeLength);
|
||||
+
|
||||
+ if (csp_disposition == network::mojom::CSPDisposition::DO_NOT_CHECK)
|
||||
+ return script_source;
|
||||
+
|
||||
+ // Check the CSP of the caller (the "source browsing context") if required,
|
||||
+ // as per https://html.spec.whatwg.org/C/#javascript-protocol.
|
||||
+ if (!GetContentSecurityPolicyForWorld(world)->AllowInline(
|
||||
+ ContentSecurityPolicy::InlineType::kNavigation, element, decoded_url,
|
||||
+ String() /* nonce */, Url(), OrdinalNumber::First()))
|
||||
+ return String();
|
||||
+
|
||||
+ // TODO(crbug.com/896041): Investigate how trusted type checks can be
|
||||
+ // implemented for isolated worlds.
|
||||
+ if (ContentSecurityPolicy::ShouldBypassMainWorldDeprecated(world))
|
||||
+ return script_source;
|
||||
+
|
||||
+ // https://w3c.github.io/webappsec-trusted-types/dist/spec/#require-trusted-types-for-pre-navigation-check
|
||||
+ // 4.9.1.1. require-trusted-types-for Pre-Navigation check
|
||||
+ script_source =
|
||||
+ TrustedTypesCheckForJavascriptURLinNavigation(script_source, this);
|
||||
+
|
||||
+ return script_source;
|
||||
+}
|
||||
+
|
||||
void LocalDOMWindow::ExceptionThrown(ErrorEvent* event) {
|
||||
MainThreadDebugger::Instance()->ExceptionThrown(this, event);
|
||||
}
|
||||
diff --git a/third_party/blink/renderer/core/frame/local_dom_window.h b/third_party/blink/renderer/core/frame/local_dom_window.h
|
||||
index 7091b979bed2c3ee375453ebc68aa83102745f35..b485bb1a08bc58bc1738c97c0311dc2d47d233e2 100644
|
||||
--- a/third_party/blink/renderer/core/frame/local_dom_window.h
|
||||
+++ b/third_party/blink/renderer/core/frame/local_dom_window.h
|
||||
@@ -31,6 +31,7 @@
|
||||
|
||||
#include "services/metrics/public/cpp/ukm_recorder.h"
|
||||
#include "services/metrics/public/cpp/ukm_source_id.h"
|
||||
+#include "services/network/public/mojom/content_security_policy.mojom-blink.h"
|
||||
#include "third_party/blink/public/common/frame/fullscreen_request_token.h"
|
||||
#include "third_party/blink/public/common/frame/payment_request_token.h"
|
||||
#include "third_party/blink/public/common/metrics/post_message_counter.h"
|
||||
@@ -215,6 +216,16 @@ class CORE_EXPORT LocalDOMWindow final : public DOMWindow,
|
||||
mojom::blink::PermissionsPolicyFeature feature,
|
||||
UseCounterImpl::PermissionsPolicyUsageType type);
|
||||
|
||||
+ // Checks if navigation to Javascript URL is allowed. This check should run
|
||||
+ // before any action is taken (e.g. creating new window) for all
|
||||
+ // same-origin navigations.
|
||||
+ String CheckAndGetJavascriptUrl(
|
||||
+ const DOMWrapperWorld* world,
|
||||
+ const KURL& url,
|
||||
+ Element* element,
|
||||
+ network::mojom::CSPDisposition csp_disposition =
|
||||
+ network::mojom::CSPDisposition::CHECK);
|
||||
+
|
||||
Document* InstallNewDocument(const DocumentInit&);
|
||||
|
||||
// EventTarget overrides:
|
||||
diff --git a/third_party/blink/renderer/core/frame/location.cc b/third_party/blink/renderer/core/frame/location.cc
|
||||
index a1aeede568cfe33267d87fa68f096d20a83d50f9..92740842827d470d63da34dd90bdb937321c1a83 100644
|
||||
--- a/third_party/blink/renderer/core/frame/location.cc
|
||||
+++ b/third_party/blink/renderer/core/frame/location.cc
|
||||
@@ -270,23 +270,6 @@ void Location::SetLocation(const String& url,
|
||||
return;
|
||||
}
|
||||
|
||||
- // Check the source browsing context's CSP to fulfill the CSP check
|
||||
- // requirement of https://html.spec.whatwg.org/C/#navigate for javascript
|
||||
- // URLs. Although the spec states we should perform this check on task
|
||||
- // execution, there are concerns about the correctness of that statement,
|
||||
- // see http://github.com/whatwg/html/issues/2591.
|
||||
- if (completed_url.ProtocolIsJavaScript()) {
|
||||
- String script_source = DecodeURLEscapeSequences(
|
||||
- completed_url.GetString(), DecodeURLMode::kUTF8OrIsomorphic);
|
||||
- if (!incumbent_window->GetContentSecurityPolicyForCurrentWorld()
|
||||
- ->AllowInline(ContentSecurityPolicy::InlineType::kNavigation,
|
||||
- nullptr /* element */, script_source,
|
||||
- String() /* nonce */, incumbent_window->Url(),
|
||||
- OrdinalNumber::First())) {
|
||||
- return;
|
||||
- }
|
||||
- }
|
||||
-
|
||||
V8DOMActivityLogger* activity_logger =
|
||||
V8DOMActivityLogger::CurrentActivityLoggerIfIsolatedWorld();
|
||||
if (activity_logger) {
|
||||
diff --git a/third_party/blink/renderer/core/loader/frame_loader.cc b/third_party/blink/renderer/core/loader/frame_loader.cc
|
||||
index 4786257911cd9cb01222ef375698e0ae669d8ccb..94e04ff48d7a395cd673a9ececd598d00e735ff5 100644
|
||||
--- a/third_party/blink/renderer/core/loader/frame_loader.cc
|
||||
+++ b/third_party/blink/renderer/core/loader/frame_loader.cc
|
||||
@@ -537,19 +537,12 @@ bool FrameLoader::AllowRequestForThisFrame(const FrameLoadRequest& request) {
|
||||
|
||||
const KURL& url = request.GetResourceRequest().Url();
|
||||
if (url.ProtocolIsJavaScript()) {
|
||||
- // Check the CSP of the caller (the "source browsing context") if required,
|
||||
- // as per https://html.spec.whatwg.org/C/#javascript-protocol.
|
||||
- bool javascript_url_is_allowed =
|
||||
- request.GetOriginWindow()
|
||||
- ->GetContentSecurityPolicyForWorld(request.JavascriptWorld().get())
|
||||
- ->AllowInline(ContentSecurityPolicy::InlineType::kNavigation,
|
||||
- frame_->DeprecatedLocalOwner(), url.GetString(),
|
||||
- String() /* nonce */,
|
||||
- request.GetOriginWindow()->Url(),
|
||||
- OrdinalNumber::First());
|
||||
-
|
||||
- if (!javascript_url_is_allowed)
|
||||
+ if (request.GetOriginWindow()
|
||||
+ ->CheckAndGetJavascriptUrl(request.JavascriptWorld().get(), url,
|
||||
+ frame_->DeprecatedLocalOwner())
|
||||
+ .IsEmpty()) {
|
||||
return false;
|
||||
+ }
|
||||
|
||||
if (frame_->Owner() && ((frame_->Owner()->GetFramePolicy().sandbox_flags &
|
||||
network::mojom::blink::WebSandboxFlags::kOrigin) !=
|
||||
diff --git a/third_party/blink/renderer/core/page/create_window.cc b/third_party/blink/renderer/core/page/create_window.cc
|
||||
index 7e73ad64a9b28396473adefaefd6430f81e61011..118ca880ffba6cc96a51b7b083119bd41f990e15 100644
|
||||
--- a/third_party/blink/renderer/core/page/create_window.cc
|
||||
+++ b/third_party/blink/renderer/core/page/create_window.cc
|
||||
@@ -294,15 +294,11 @@ Frame* CreateNewWindow(LocalFrame& opener_frame,
|
||||
request.SetFrameType(mojom::RequestContextFrameType::kAuxiliary);
|
||||
|
||||
const KURL& url = request.GetResourceRequest().Url();
|
||||
- auto* csp_for_world = opener_window.GetContentSecurityPolicyForCurrentWorld();
|
||||
- if (url.ProtocolIsJavaScript() && csp_for_world) {
|
||||
- String script_source = DecodeURLEscapeSequences(
|
||||
- url.GetString(), DecodeURLMode::kUTF8OrIsomorphic);
|
||||
-
|
||||
- if (!csp_for_world->AllowInline(
|
||||
- ContentSecurityPolicy::InlineType::kNavigation,
|
||||
- nullptr /* element */, script_source, String() /* nonce */,
|
||||
- opener_window.Url(), OrdinalNumber::First())) {
|
||||
+ if (url.ProtocolIsJavaScript()) {
|
||||
+ if (opener_window
|
||||
+ .CheckAndGetJavascriptUrl(request.JavascriptWorld().get(), url,
|
||||
+ nullptr /* element */)
|
||||
+ .IsEmpty()) {
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
diff --git a/third_party/blink/web_tests/external/wpt/trusted-types/support/frame-without-trusted-types.html b/third_party/blink/web_tests/external/wpt/trusted-types/support/frame-without-trusted-types.html
|
||||
new file mode 100644
|
||||
index 0000000000000000000000000000000000000000..25cf073e79fa48f4311c3729f0b39d9be2a64e7c
|
||||
--- /dev/null
|
||||
+++ b/third_party/blink/web_tests/external/wpt/trusted-types/support/frame-without-trusted-types.html
|
||||
@@ -0,0 +1,6 @@
|
||||
+<!DOCTYPE html>
|
||||
+<head>
|
||||
+</head>
|
||||
+<body>
|
||||
+</body>
|
||||
+</html>
|
||||
diff --git a/third_party/blink/web_tests/external/wpt/trusted-types/support/navigation-report-only-support.html b/third_party/blink/web_tests/external/wpt/trusted-types/support/navigation-report-only-support.html
|
||||
index d00d0538753a74411feeec42d5682082031c09d4..5f7856fabb7bb16085ffaffffbf6d7553179e8f3 100644
|
||||
--- a/third_party/blink/web_tests/external/wpt/trusted-types/support/navigation-report-only-support.html
|
||||
+++ b/third_party/blink/web_tests/external/wpt/trusted-types/support/navigation-report-only-support.html
|
||||
@@ -5,7 +5,8 @@
|
||||
<p>Support page for trusted-types-navigation-report-only.*.html tests.</p>
|
||||
<a id="anchor" href="#">link</a>
|
||||
<script>
|
||||
- if (location.search == "?defaultpolicy") {
|
||||
+ const params = new URLSearchParams(location.search);
|
||||
+ if (!!params.get("defaultpolicy")) {
|
||||
trustedTypes.createPolicy("default", {
|
||||
createScript: s => s.replace("continue", "defaultpolicywashere"),
|
||||
});
|
||||
@@ -36,9 +37,17 @@
|
||||
// won't disturb delivery of that event to the opener.
|
||||
const anchor = document.getElementById("anchor");
|
||||
anchor.href = target;
|
||||
+
|
||||
+ if (!!params.get("frame")) {
|
||||
+ const frame = document.createElement("iframe");
|
||||
+ frame.src = "frame-without-trusted-types.html";
|
||||
+ frames.name = "frame";
|
||||
+ document.body.appendChild(frame);
|
||||
+ anchor.target = "frame";
|
||||
+ }
|
||||
+
|
||||
if (!location.hash) {
|
||||
document.addEventListener("DOMContentLoaded", _ => anchor.click());
|
||||
}
|
||||
</script>
|
||||
</body>
|
||||
-
|
||||
diff --git a/third_party/blink/web_tests/external/wpt/trusted-types/support/navigation-support.html b/third_party/blink/web_tests/external/wpt/trusted-types/support/navigation-support.html
|
||||
index cd41f3968e7c74f84a7541506053808073ce541d..5e02e6d4bf5aff9fa4f0b4b897a35726ed24168b 100644
|
||||
--- a/third_party/blink/web_tests/external/wpt/trusted-types/support/navigation-support.html
|
||||
+++ b/third_party/blink/web_tests/external/wpt/trusted-types/support/navigation-support.html
|
||||
@@ -5,7 +5,8 @@
|
||||
<p>Support page for trusted-types-navigation.*.html tests.</p>
|
||||
<a id="anchor" href="#">link</a>
|
||||
<script>
|
||||
- if (location.search == "?defaultpolicy") {
|
||||
+ const params = new URLSearchParams(location.search);
|
||||
+ if (!!params.get("defaultpolicy")) {
|
||||
trustedTypes.createPolicy("default", {
|
||||
createScript: s => s.replace("continue", "defaultpolicywashere"),
|
||||
});
|
||||
@@ -35,8 +36,16 @@
|
||||
|
||||
const anchor = document.getElementById("anchor");
|
||||
anchor.href = target;
|
||||
+
|
||||
+ if (!!params.get("frame")) {
|
||||
+ const frame = document.createElement("iframe");
|
||||
+ frame.src = "frame-without-trusted-types.html";
|
||||
+ frames.name = "frame";
|
||||
+ document.body.appendChild(frame);
|
||||
+ anchor.target = "frame";
|
||||
+ }
|
||||
+
|
||||
if (!location.hash)
|
||||
document.addEventListener("DOMContentLoaded", _ => anchor.click());
|
||||
</script>
|
||||
</body>
|
||||
-
|
||||
diff --git a/third_party/blink/web_tests/external/wpt/trusted-types/trusted-types-navigation.tentative.html b/third_party/blink/web_tests/external/wpt/trusted-types/trusted-types-navigation.tentative.html
|
||||
index 4e784611dd64ecf2f9995403b1d4e5a19f8b4548..2113711902ae787cb3ad5d0e44eaed0fc2e99b87 100644
|
||||
--- a/third_party/blink/web_tests/external/wpt/trusted-types/trusted-types-navigation.tentative.html
|
||||
+++ b/third_party/blink/web_tests/external/wpt/trusted-types/trusted-types-navigation.tentative.html
|
||||
@@ -38,10 +38,10 @@
|
||||
}, "Navigate a window with javascript:-urls in enforcing mode.");
|
||||
|
||||
promise_test(t => {
|
||||
- openWindow(t, "support/navigation-support.html?defaultpolicy");
|
||||
+ openWindow(t, "support/navigation-support.html?defaultpolicy=1");
|
||||
return Promise.all([
|
||||
- expectLoadedAsMessage("navigation-support.html?defaultpolicy"),
|
||||
- expectLoadedAsMessage("navigation-support.html?defaultpolicy&defaultpolicywashere"),
|
||||
+ expectLoadedAsMessage("navigation-support.html?defaultpolicy=1"),
|
||||
+ expectLoadedAsMessage("navigation-support.html?defaultpolicy=1&defaultpolicywashere"),
|
||||
]);
|
||||
}, "Navigate a window with javascript:-urls w/ default policy in enforcing mode.");
|
||||
|
||||
@@ -55,12 +55,46 @@
|
||||
}, "Navigate a window with javascript:-urls in report-only mode.");
|
||||
|
||||
promise_test(t => {
|
||||
- const page = "navigation-report-only-support.html?defaultpolicy";
|
||||
+ const page = "navigation-report-only-support.html?defaultpolicy=1";
|
||||
openWindow(t, `support/${page}`);
|
||||
return Promise.all([
|
||||
expectLoadedAsMessage(page),
|
||||
- expectLoadedAsMessage("navigation-support.html?defaultpolicy#defaultpolicywashere"),
|
||||
+ expectLoadedAsMessage("navigation-support.html?defaultpolicy=1#defaultpolicywashere"),
|
||||
]);
|
||||
}, "Navigate a window with javascript:-urls w/ default policy in report-only mode.");
|
||||
+
|
||||
+ promise_test(t => {
|
||||
+ openWindow(t, "support/navigation-support.html?frame=1");
|
||||
+ return Promise.all([
|
||||
+ expectLoadedAsMessage("navigation-support.html?frame=1"),
|
||||
+ expectViolationAsMessage("Location href"),
|
||||
+ ]);
|
||||
+ }, "Navigate a frame with javascript:-urls in enforcing mode.");
|
||||
+
|
||||
+ promise_test(t => {
|
||||
+ openWindow(t, "support/navigation-support.html?defaultpolicy=1&frame=1");
|
||||
+ return Promise.all([
|
||||
+ expectLoadedAsMessage("navigation-support.html?defaultpolicy=1&frame=1"),
|
||||
+ expectLoadedAsMessage("navigation-support.html?defaultpolicy=1&frame=1&defaultpolicywashere"),
|
||||
+ ]);
|
||||
+ }, "Navigate a frame with javascript:-urls w/ default policy in enforcing mode.");
|
||||
+
|
||||
+ promise_test(t => {
|
||||
+ const page = "navigation-report-only-support.html?frame=1"
|
||||
+ openWindow(t, `support/${page}`);
|
||||
+ return Promise.all([
|
||||
+ expectLoadedAsMessage(page),
|
||||
+ expectLoadedAsMessage("navigation-support.html?frame=1#continue"),
|
||||
+ ]);
|
||||
+ }, "Navigate a frame with javascript:-urls in report-only mode.");
|
||||
+
|
||||
+ promise_test(t => {
|
||||
+ const page = "navigation-report-only-support.html?defaultpolicy=1&frame=1";
|
||||
+ openWindow(t, `support/${page}`);
|
||||
+ return Promise.all([
|
||||
+ expectLoadedAsMessage(page),
|
||||
+ expectLoadedAsMessage("navigation-support.html?defaultpolicy=1&frame=1#defaultpolicywashere"),
|
||||
+ ]);
|
||||
+ }, "Navigate a frame with javascript:-urls w/ default policy in report-only mode.");
|
||||
</script>
|
||||
</body>
|
||||
115
patches/chromium/cherry-pick-42e15c2055c4.patch
Normal file
115
patches/chromium/cherry-pick-42e15c2055c4.patch
Normal file
@@ -0,0 +1,115 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Joey Arhar <jarhar@chromium.org>
|
||||
Date: Tue, 22 Nov 2022 00:12:31 +0000
|
||||
Subject: Avoid use-after-free in ValidationMessageOverlayDelegate
|
||||
|
||||
When ValidationMessageOverlayDelegate calls
|
||||
ForceSynchronousDocumentInstall, it can somehow cause another validation
|
||||
overlay to be created and delete the ValidationMessageOverlayDelegate.
|
||||
This patch avoids additional code from being run inside the deleted
|
||||
ValidationMessageOverlayDelegate.
|
||||
|
||||
(cherry picked from commit a37b66ded21af7ff1442bddd2ec3a0845535b3d6)
|
||||
|
||||
Fixed: 1382581
|
||||
Change-Id: I044f91ecb55c77c4a5c40030b6856fc9a8ac7f6f
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/4019655
|
||||
Reviewed-by: David Baron <dbaron@chromium.org>
|
||||
Commit-Queue: Joey Arhar <jarhar@chromium.org>
|
||||
Cr-Original-Commit-Position: refs/heads/main@{#1071652}
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/4043489
|
||||
Commit-Queue: David Baron <dbaron@chromium.org>
|
||||
Auto-Submit: Joey Arhar <jarhar@chromium.org>
|
||||
Cr-Commit-Position: refs/branch-heads/5359@{#911}
|
||||
Cr-Branched-From: 27d3765d341b09369006d030f83f582a29eb57ae-refs/heads/main@{#1058933}
|
||||
|
||||
diff --git a/third_party/blink/renderer/core/page/validation_message_overlay_delegate.cc b/third_party/blink/renderer/core/page/validation_message_overlay_delegate.cc
|
||||
index cd5f11083e268cdf0fca94c9fd9f8d56433b299b..38e0babfb9425d8611df97f8f6a325d6fca513fd 100644
|
||||
--- a/third_party/blink/renderer/core/page/validation_message_overlay_delegate.cc
|
||||
+++ b/third_party/blink/renderer/core/page/validation_message_overlay_delegate.cc
|
||||
@@ -86,6 +86,8 @@ ValidationMessageOverlayDelegate::~ValidationMessageOverlayDelegate() {
|
||||
EventDispatchForbiddenScope::AllowUserAgentEvents allow_events;
|
||||
page_->WillBeDestroyed();
|
||||
}
|
||||
+ if (destroyed_ptr_)
|
||||
+ *destroyed_ptr_ = true;
|
||||
}
|
||||
|
||||
LocalFrameView& ValidationMessageOverlayDelegate::FrameView() const {
|
||||
@@ -176,7 +178,18 @@ void ValidationMessageOverlayDelegate::CreatePage(const FrameOverlay& overlay) {
|
||||
WriteDocument(data.get());
|
||||
float zoom_factor = anchor_->GetDocument().GetFrame()->PageZoomFactor();
|
||||
frame->SetPageZoomFactor(zoom_factor);
|
||||
+
|
||||
+ // ForceSynchronousDocumentInstall can cause another call to
|
||||
+ // ValidationMessageClientImpl::ShowValidationMessage, which will hide this
|
||||
+ // validation message and may even delete this. In order to avoid continuing
|
||||
+ // when this is destroyed, |destroyed| will be set to true in the destructor.
|
||||
+ bool destroyed = false;
|
||||
+ DCHECK(!destroyed_ptr_);
|
||||
+ destroyed_ptr_ = &destroyed;
|
||||
frame->ForceSynchronousDocumentInstall("text/html", data);
|
||||
+ if (destroyed)
|
||||
+ return;
|
||||
+ destroyed_ptr_ = nullptr;
|
||||
|
||||
Element& main_message = GetElementById("main-message");
|
||||
main_message.setTextContent(message_);
|
||||
diff --git a/third_party/blink/renderer/core/page/validation_message_overlay_delegate.h b/third_party/blink/renderer/core/page/validation_message_overlay_delegate.h
|
||||
index 9db786a4fbd12bc6aeefc520143f872965ad7df8..26e96d8ffad11938dcc3dc5b059f2c7ebf077b94 100644
|
||||
--- a/third_party/blink/renderer/core/page/validation_message_overlay_delegate.h
|
||||
+++ b/third_party/blink/renderer/core/page/validation_message_overlay_delegate.h
|
||||
@@ -72,6 +72,10 @@ class CORE_EXPORT ValidationMessageOverlayDelegate
|
||||
String sub_message_;
|
||||
TextDirection message_dir_;
|
||||
TextDirection sub_message_dir_;
|
||||
+
|
||||
+ // Used by CreatePage() to determine if this has been deleted in the middle of
|
||||
+ // the function.
|
||||
+ bool* destroyed_ptr_ = nullptr;
|
||||
};
|
||||
|
||||
} // namespace blink
|
||||
diff --git a/third_party/blink/web_tests/external/wpt/html/semantics/forms/constraints/reportValidity-crash.html b/third_party/blink/web_tests/external/wpt/html/semantics/forms/constraints/reportValidity-crash.html
|
||||
new file mode 100644
|
||||
index 0000000000000000000000000000000000000000..d6bab924adc9fb481235af10d706cbf4d4ef2df9
|
||||
--- /dev/null
|
||||
+++ b/third_party/blink/web_tests/external/wpt/html/semantics/forms/constraints/reportValidity-crash.html
|
||||
@@ -0,0 +1,37 @@
|
||||
+<!DOCTYPE html>
|
||||
+<html>
|
||||
+
|
||||
+<head>
|
||||
+<script>
|
||||
+Object.prototype.__defineGetter__('then', prom);
|
||||
+var prom_count = 0;
|
||||
+function prom() {
|
||||
+prom_count++;
|
||||
+if (prom_count > 2) return;
|
||||
+var v14 = x37.animate({},100);
|
||||
+v14.reverse();
|
||||
+v14.ready;
|
||||
+v14.currentTime = 0;
|
||||
+x57.reportValidity();
|
||||
+}
|
||||
+function f0() {
|
||||
+var v38 = x37.animate({},300);
|
||||
+v38.ready;
|
||||
+x57.prepend(x78);
|
||||
+}
|
||||
+function f1() {
|
||||
+var x57 = document.getElementById("x57");
|
||||
+x57.disabled = false;
|
||||
+}
|
||||
+</script>
|
||||
+</head>
|
||||
+
|
||||
+<body>
|
||||
+<fieldset id="x37">
|
||||
+<canvas onfocusin="f0()" >
|
||||
+<input id="x78" autofocus="" onfocusout="f1()" >
|
||||
+</canvas>
|
||||
+<select id="x57" disabled="" required=""></select>
|
||||
+</body>
|
||||
+
|
||||
+</html>
|
||||
104
patches/chromium/cherry-pick-43637378b14e.patch
Normal file
104
patches/chromium/cherry-pick-43637378b14e.patch
Normal file
@@ -0,0 +1,104 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Maks Orlovich <morlovich@chromium.org>
|
||||
Date: Tue, 22 Nov 2022 22:18:55 +0000
|
||||
Subject: Align NetworkContext::SetNetworkConditions better with devtools
|
||||
emulateNetworkConditions
|
||||
|
||||
The former used values of 0 to disable particular throttles, while the
|
||||
later documents -1, and looks to be pretty much a direct client, and the
|
||||
only one. So make NetworkService handle everything <= 0 as a disable,
|
||||
clamping at intake of config.
|
||||
|
||||
Bug: 1382033
|
||||
|
||||
(cherry picked from commit ce463c2c939818a12bbcec5e2c91c35f2a0a1f0e)
|
||||
|
||||
Change-Id: I2fd3f075d5071cb0cf647838782115b5c00405bf
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/4035891
|
||||
Reviewed-by: Ken Buchanan <kenrb@chromium.org>
|
||||
Reviewed-by: Eric Orth <ericorth@chromium.org>
|
||||
Commit-Queue: Maks Orlovich <morlovich@chromium.org>
|
||||
Cr-Original-Commit-Position: refs/heads/main@{#1073566}
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/4048289
|
||||
Cr-Commit-Position: refs/branch-heads/5414@{#188}
|
||||
Cr-Branched-From: 4417ee59d7bf6df7a9c9ea28f7722d2ee6203413-refs/heads/main@{#1070088}
|
||||
|
||||
diff --git a/services/network/public/mojom/network_context.mojom b/services/network/public/mojom/network_context.mojom
|
||||
index 105011c25861fe00cc8e72fe8f310ee5118725c3..86535284fedeb875b4958322fdddaa52507cfbaa 100644
|
||||
--- a/services/network/public/mojom/network_context.mojom
|
||||
+++ b/services/network/public/mojom/network_context.mojom
|
||||
@@ -561,11 +561,11 @@ struct NetworkConditions {
|
||||
// response received.
|
||||
mojo_base.mojom.TimeDelta latency;
|
||||
|
||||
- // Maximal aggregated download throughput (bytes/sec). 0 disables download
|
||||
+ // Maximal aggregated download throughput (bytes/sec). <=0 disables download
|
||||
// throttling.
|
||||
double download_throughput;
|
||||
|
||||
- // Maximal aggregated upload throughput (bytes/sec). 0 disables upload
|
||||
+ // Maximal aggregated upload throughput (bytes/sec). <=0 disables upload
|
||||
// throttling.
|
||||
double upload_throughput;
|
||||
};
|
||||
diff --git a/services/network/throttling/network_conditions.cc b/services/network/throttling/network_conditions.cc
|
||||
index 71cd4ac0e52cc1f262c5b58caf20448b57b6b64f..18b2b6e0efdc2e17dbbbfaa411b4ab49ec787bc4 100644
|
||||
--- a/services/network/throttling/network_conditions.cc
|
||||
+++ b/services/network/throttling/network_conditions.cc
|
||||
@@ -4,6 +4,8 @@
|
||||
|
||||
#include "services/network/throttling/network_conditions.h"
|
||||
|
||||
+#include <algorithm>
|
||||
+
|
||||
namespace network {
|
||||
|
||||
NetworkConditions::NetworkConditions() : NetworkConditions(false) {}
|
||||
@@ -16,9 +18,9 @@ NetworkConditions::NetworkConditions(bool offline,
|
||||
double download_throughput,
|
||||
double upload_throughput)
|
||||
: offline_(offline),
|
||||
- latency_(latency),
|
||||
- download_throughput_(download_throughput),
|
||||
- upload_throughput_(upload_throughput) {}
|
||||
+ latency_(std::max(latency, 0.0)),
|
||||
+ download_throughput_(std::max(download_throughput, 0.0)),
|
||||
+ upload_throughput_(std::max(upload_throughput, 0.0)) {}
|
||||
|
||||
NetworkConditions::~NetworkConditions() {}
|
||||
|
||||
diff --git a/services/network/throttling/network_conditions.h b/services/network/throttling/network_conditions.h
|
||||
index f8c8214b34bafcb1f656dd3a39a0cf17fea821ea..c5232231d308b09105234101f4bc575491505372 100644
|
||||
--- a/services/network/throttling/network_conditions.h
|
||||
+++ b/services/network/throttling/network_conditions.h
|
||||
@@ -28,6 +28,8 @@ class COMPONENT_EXPORT(NETWORK_SERVICE) NetworkConditions {
|
||||
bool IsThrottling() const;
|
||||
|
||||
bool offline() const { return offline_; }
|
||||
+
|
||||
+ // These are 0 if the corresponding throttle is disabled, >0 otherwise.
|
||||
double latency() const { return latency_; }
|
||||
double download_throughput() const { return download_throughput_; }
|
||||
double upload_throughput() const { return upload_throughput_; }
|
||||
diff --git a/services/network/throttling/throttling_controller_unittest.cc b/services/network/throttling/throttling_controller_unittest.cc
|
||||
index fbe2c6d20d1d5362a77bd951e87b3fe41be13098..e834f8bdc13b5691b1e458dcafead482a0537e14 100644
|
||||
--- a/services/network/throttling/throttling_controller_unittest.cc
|
||||
+++ b/services/network/throttling/throttling_controller_unittest.cc
|
||||
@@ -297,7 +297,7 @@ TEST(ThrottlingControllerTest, DownloadOnly) {
|
||||
ThrottlingControllerTestHelper helper;
|
||||
TestCallback* callback = helper.callback();
|
||||
|
||||
- helper.SetNetworkState(false, 10000000, 0);
|
||||
+ helper.SetNetworkState(false, 10000000, -1);
|
||||
int rv = helper.Start(false);
|
||||
EXPECT_EQ(rv, net::ERR_IO_PENDING);
|
||||
helper.FastForwardUntilNoTasksRemain();
|
||||
@@ -316,7 +316,7 @@ TEST(ThrottlingControllerTest, UploadOnly) {
|
||||
ThrottlingControllerTestHelper helper;
|
||||
TestCallback* callback = helper.callback();
|
||||
|
||||
- helper.SetNetworkState(false, 0, 1000000);
|
||||
+ helper.SetNetworkState(false, -2, 1000000);
|
||||
int rv = helper.Start(true);
|
||||
EXPECT_EQ(rv, net::OK);
|
||||
helper.FastForwardUntilNoTasksRemain();
|
||||
97
patches/chromium/cherry-pick-57c54ae221d6.patch
Normal file
97
patches/chromium/cherry-pick-57c54ae221d6.patch
Normal file
@@ -0,0 +1,97 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Victor Vasiliev <vasilvv@chromium.org>
|
||||
Date: Wed, 21 Dec 2022 17:26:42 +0000
|
||||
Subject: Ensure clean destruction of network::WebTransport
|
||||
|
||||
Once the destruction of the object begins, we should not process any
|
||||
callbacks, nor should we attempt to reset the streams on a connection
|
||||
that is already being closed.
|
||||
|
||||
Bug: 1376354
|
||||
Change-Id: Ib49e0ce0b177062cccd0e52368782e291cf8166c
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/4117501
|
||||
Reviewed-by: Eric Orth <ericorth@chromium.org>
|
||||
Commit-Queue: Victor Vasiliev <vasilvv@chromium.org>
|
||||
Cr-Commit-Position: refs/heads/main@{#1085965}
|
||||
|
||||
diff --git a/services/network/web_transport.cc b/services/network/web_transport.cc
|
||||
index fd62b83d43052d9d588a211b59e46a6c25ffeb76..534954181abcd7c4cf11eade64a2aa97c62785cc 100644
|
||||
--- a/services/network/web_transport.cc
|
||||
+++ b/services/network/web_transport.cc
|
||||
@@ -177,7 +177,7 @@ class WebTransport::Stream final {
|
||||
|
||||
~Stream() {
|
||||
auto* stream = incoming_ ? incoming_.get() : outgoing_.get();
|
||||
- if (!stream) {
|
||||
+ if (!stream || transport_->closing_ || transport_->torn_down_) {
|
||||
return;
|
||||
}
|
||||
stream->MaybeResetDueToStreamObjectGone();
|
||||
@@ -399,7 +399,10 @@ WebTransport::WebTransport(
|
||||
transport_->Connect();
|
||||
}
|
||||
|
||||
-WebTransport::~WebTransport() = default;
|
||||
+WebTransport::~WebTransport() {
|
||||
+ // Ensure that we ignore all callbacks while mid-destruction.
|
||||
+ torn_down_ = true;
|
||||
+}
|
||||
|
||||
void WebTransport::SendDatagram(base::span<const uint8_t> data,
|
||||
base::OnceCallback<void(bool)> callback) {
|
||||
diff --git a/services/network/web_transport_unittest.cc b/services/network/web_transport_unittest.cc
|
||||
index ffac5c19f9d154b91eb6aeac1e19a62277e4e7e8..46deb561091232fe64950be01e9157c8d891f111 100644
|
||||
--- a/services/network/web_transport_unittest.cc
|
||||
+++ b/services/network/web_transport_unittest.cc
|
||||
@@ -611,6 +611,51 @@ TEST_F(WebTransportTest, EchoOnUnidirectionalStreams) {
|
||||
EXPECT_EQ(0u, resets_sent.size());
|
||||
}
|
||||
|
||||
+TEST_F(WebTransportTest, DeleteClientWithStreamsOpen) {
|
||||
+ base::RunLoop run_loop_for_handshake;
|
||||
+ mojo::PendingRemote<mojom::WebTransportHandshakeClient> handshake_client;
|
||||
+ TestHandshakeClient test_handshake_client(
|
||||
+ handshake_client.InitWithNewPipeAndPassReceiver(),
|
||||
+ run_loop_for_handshake.QuitClosure());
|
||||
+
|
||||
+ CreateWebTransport(GetURL("/echo"),
|
||||
+ url::Origin::Create(GURL("https://example.org/")),
|
||||
+ std::move(handshake_client));
|
||||
+
|
||||
+ run_loop_for_handshake.Run();
|
||||
+
|
||||
+ ASSERT_TRUE(test_handshake_client.has_seen_connection_establishment());
|
||||
+
|
||||
+ TestClient client(test_handshake_client.PassClientReceiver());
|
||||
+ mojo::Remote<mojom::WebTransport> transport_remote(
|
||||
+ test_handshake_client.PassTransport());
|
||||
+
|
||||
+ constexpr int kNumStreams = 10;
|
||||
+ auto writable_for_outgoing =
|
||||
+ std::make_unique<mojo::ScopedDataPipeProducerHandle[]>(kNumStreams);
|
||||
+ for (int i = 0; i < kNumStreams; i++) {
|
||||
+ const MojoCreateDataPipeOptions options = {
|
||||
+ sizeof(options), MOJO_CREATE_DATA_PIPE_FLAG_NONE, 1, 4 * 1024};
|
||||
+ mojo::ScopedDataPipeConsumerHandle readable_for_outgoing;
|
||||
+ ASSERT_EQ(MOJO_RESULT_OK,
|
||||
+ mojo::CreateDataPipe(&options, writable_for_outgoing[i],
|
||||
+ readable_for_outgoing));
|
||||
+ base::RunLoop run_loop_for_stream_creation;
|
||||
+ bool stream_created;
|
||||
+ transport_remote->CreateStream(
|
||||
+ std::move(readable_for_outgoing),
|
||||
+ /*writable=*/{},
|
||||
+ base::BindLambdaForTesting([&](bool b, uint32_t /*id*/) {
|
||||
+ stream_created = b;
|
||||
+ run_loop_for_stream_creation.Quit();
|
||||
+ }));
|
||||
+ run_loop_for_stream_creation.Run();
|
||||
+ ASSERT_TRUE(stream_created);
|
||||
+ }
|
||||
+
|
||||
+ // Keep the streams open so that they are closed via destructor.
|
||||
+}
|
||||
+
|
||||
// crbug.com/1129847: disabled because it is flaky.
|
||||
TEST_F(WebTransportTest, DISABLED_EchoOnBidirectionalStream) {
|
||||
base::RunLoop run_loop_for_handshake;
|
||||
78
patches/chromium/cherry-pick-65ad70274d4b.patch
Normal file
78
patches/chromium/cherry-pick-65ad70274d4b.patch
Normal file
@@ -0,0 +1,78 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Ilya Nikolaevskiy <ilnik@chromium.org>
|
||||
Date: Mon, 14 Nov 2022 12:33:49 +0000
|
||||
Subject: Fix UAF in VideoCaptureDeviceWin::FrameReceived
|
||||
|
||||
(cherry picked from commit d08a3822658cb4ca4261659f1487069a14b51bd9)
|
||||
|
||||
Bug: 1381401
|
||||
Change-Id: Ib742ec7b86d3c419f37f12694bf9cd5f3f03305c
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/4013158
|
||||
Reviewed-by: Markus Handell <handellm@google.com>
|
||||
Commit-Queue: Ilya Nikolaevskiy <ilnik@chromium.org>
|
||||
Cr-Original-Commit-Position: refs/heads/main@{#1069054}
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/4023295
|
||||
Cr-Commit-Position: refs/branch-heads/5359@{#809}
|
||||
Cr-Branched-From: 27d3765d341b09369006d030f83f582a29eb57ae-refs/heads/main@{#1058933}
|
||||
|
||||
diff --git a/media/capture/video/win/video_capture_device_win.cc b/media/capture/video/win/video_capture_device_win.cc
|
||||
index f2380053969cbb5292eaec3b4b01e7358788ef54..898d66ce5d9ce43ff55b426dca933014918c9339 100644
|
||||
--- a/media/capture/video/win/video_capture_device_win.cc
|
||||
+++ b/media/capture/video/win/video_capture_device_win.cc
|
||||
@@ -872,34 +872,35 @@ void VideoCaptureDeviceWin::FrameReceived(const uint8_t* buffer,
|
||||
const VideoCaptureFormat& format,
|
||||
base::TimeDelta timestamp,
|
||||
bool flip_y) {
|
||||
+ // We always calculate camera rotation for the first frame. We also cache
|
||||
+ // the latest value to use when AutoRotation is turned off.
|
||||
+ // To avoid potential deadlock, do this without holding a lock.
|
||||
+ if (!camera_rotation_.has_value() || IsAutoRotationEnabled())
|
||||
+ camera_rotation_ = GetCameraRotation(device_descriptor_.facing);
|
||||
+
|
||||
{
|
||||
base::AutoLock lock(lock_);
|
||||
if (state_ != kCapturing)
|
||||
return;
|
||||
- }
|
||||
|
||||
- if (first_ref_time_.is_null())
|
||||
- first_ref_time_ = base::TimeTicks::Now();
|
||||
+ if (first_ref_time_.is_null())
|
||||
+ first_ref_time_ = base::TimeTicks::Now();
|
||||
|
||||
- // There is a chance that the platform does not provide us with the timestamp,
|
||||
- // in which case, we use reference time to calculate a timestamp.
|
||||
- if (timestamp == kNoTimestamp)
|
||||
- timestamp = base::TimeTicks::Now() - first_ref_time_;
|
||||
+ // There is a chance that the platform does not provide us with the
|
||||
+ // timestamp, in which case, we use reference time to calculate a timestamp.
|
||||
+ if (timestamp == kNoTimestamp)
|
||||
+ timestamp = base::TimeTicks::Now() - first_ref_time_;
|
||||
|
||||
- // We always calculate camera rotation for the first frame. We also cache the
|
||||
- // latest value to use when AutoRotation is turned off.
|
||||
- if (!camera_rotation_.has_value() || IsAutoRotationEnabled())
|
||||
- camera_rotation_ = GetCameraRotation(device_descriptor_.facing);
|
||||
-
|
||||
- // TODO(julien.isorce): retrieve the color space information using the
|
||||
- // DirectShow api, AM_MEDIA_TYPE::VIDEOINFOHEADER2::dwControlFlags. If
|
||||
- // AMCONTROL_COLORINFO_PRESENT, then reinterpret dwControlFlags as a
|
||||
- // DXVA_ExtendedFormat. Then use its fields DXVA_VideoPrimaries,
|
||||
- // DXVA_VideoTransferMatrix, DXVA_VideoTransferFunction and
|
||||
- // DXVA_NominalRangeto build a gfx::ColorSpace. See http://crbug.com/959992.
|
||||
- client_->OnIncomingCapturedData(buffer, length, format, gfx::ColorSpace(),
|
||||
- camera_rotation_.value(), flip_y,
|
||||
- base::TimeTicks::Now(), timestamp);
|
||||
+ // TODO(julien.isorce): retrieve the color space information using the
|
||||
+ // DirectShow api, AM_MEDIA_TYPE::VIDEOINFOHEADER2::dwControlFlags. If
|
||||
+ // AMCONTROL_COLORINFO_PRESENT, then reinterpret dwControlFlags as a
|
||||
+ // DXVA_ExtendedFormat. Then use its fields DXVA_VideoPrimaries,
|
||||
+ // DXVA_VideoTransferMatrix, DXVA_VideoTransferFunction and
|
||||
+ // DXVA_NominalRangeto build a gfx::ColorSpace. See http://crbug.com/959992.
|
||||
+ client_->OnIncomingCapturedData(buffer, length, format, gfx::ColorSpace(),
|
||||
+ camera_rotation_.value(), flip_y,
|
||||
+ base::TimeTicks::Now(), timestamp);
|
||||
+ }
|
||||
|
||||
while (!take_photo_callbacks_.empty()) {
|
||||
TakePhotoCallback cb = std::move(take_photo_callbacks_.front());
|
||||
115
patches/chromium/cherry-pick-65d46507a0c9.patch
Normal file
115
patches/chromium/cherry-pick-65d46507a0c9.patch
Normal file
@@ -0,0 +1,115 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: evliu <evliu@google.com>
|
||||
Date: Mon, 14 Nov 2022 20:05:12 +0000
|
||||
Subject: Replace raw pointer to LocalMuter with weak ptr
|
||||
|
||||
This CL replaces a raw pointer to LocalMuter with a weak ptr. Additional
|
||||
info about this bug here: http://crbug/1377783
|
||||
|
||||
(cherry picked from commit 9989b93eb12c93b9351d5bf2872c1069ef5f7d01)
|
||||
|
||||
Bug: 1377783
|
||||
Change-Id: Id821ea800ba12f1cfae4677fc591c12dec112852
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3997421
|
||||
Reviewed-by: Paul Semel <paulsemel@chromium.org>
|
||||
Reviewed-by: Olga Sharonova <olka@chromium.org>
|
||||
Commit-Queue: Evan Liu <evliu@google.com>
|
||||
Cr-Original-Commit-Position: refs/heads/main@{#1068776}
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/4024547
|
||||
Auto-Submit: Evan Liu <evliu@google.com>
|
||||
Owners-Override: Srinivas Sista <srinivassista@chromium.org>
|
||||
Bot-Commit: Rubber Stamper <rubber-stamper@appspot.gserviceaccount.com>
|
||||
Commit-Queue: Rubber Stamper <rubber-stamper@appspot.gserviceaccount.com>
|
||||
Reviewed-by: Evan Liu <evliu@google.com>
|
||||
Cr-Commit-Position: refs/branch-heads/5359@{#824}
|
||||
Cr-Branched-From: 27d3765d341b09369006d030f83f582a29eb57ae-refs/heads/main@{#1058933}
|
||||
|
||||
diff --git a/services/audio/local_muter.h b/services/audio/local_muter.h
|
||||
index a484c7dfd60883b07c8fc61da768edf508ac53af..b108e32306a264be4d51027c4419efc70a5dbe0c 100644
|
||||
--- a/services/audio/local_muter.h
|
||||
+++ b/services/audio/local_muter.h
|
||||
@@ -7,6 +7,7 @@
|
||||
|
||||
#include "base/callback.h"
|
||||
#include "base/memory/raw_ptr.h"
|
||||
+#include "base/memory/weak_ptr.h"
|
||||
#include "base/sequence_checker.h"
|
||||
#include "base/unguessable_token.h"
|
||||
#include "media/mojo/mojom/audio_stream_factory.mojom.h"
|
||||
@@ -46,6 +47,8 @@ class LocalMuter final : public media::mojom::LocalMuter,
|
||||
|
||||
bool HasReceivers() { return !receivers_.empty(); }
|
||||
|
||||
+ base::WeakPtr<LocalMuter> GetWeakPtr() { return weak_factory_.GetWeakPtr(); }
|
||||
+
|
||||
private:
|
||||
// Runs the |all_bindings_lost_callback_| when |bindings_| becomes empty.
|
||||
void OnBindingLost();
|
||||
@@ -57,6 +60,8 @@ class LocalMuter final : public media::mojom::LocalMuter,
|
||||
base::RepeatingClosure all_bindings_lost_callback_;
|
||||
|
||||
SEQUENCE_CHECKER(sequence_checker_);
|
||||
+
|
||||
+ base::WeakPtrFactory<LocalMuter> weak_factory_{this};
|
||||
};
|
||||
|
||||
} // namespace audio
|
||||
diff --git a/services/audio/stream_factory.cc b/services/audio/stream_factory.cc
|
||||
index 98fc82b48ff020c49fdeab1adae947a84873f6b2..dad6051bc712e6b923ec26b0abc56625d8dcbed5 100644
|
||||
--- a/services/audio/stream_factory.cc
|
||||
+++ b/services/audio/stream_factory.cc
|
||||
@@ -184,8 +184,9 @@ void StreamFactory::BindMuter(
|
||||
if (it == muters_.end()) {
|
||||
auto muter_ptr = std::make_unique<LocalMuter>(&coordinator_, group_id);
|
||||
muter = muter_ptr.get();
|
||||
- muter->SetAllBindingsLostCallback(base::BindRepeating(
|
||||
- &StreamFactory::DestroyMuter, base::Unretained(this), muter));
|
||||
+ muter->SetAllBindingsLostCallback(
|
||||
+ base::BindRepeating(&StreamFactory::DestroyMuter,
|
||||
+ base::Unretained(this), muter_ptr->GetWeakPtr()));
|
||||
muters_.emplace_back(std::move(muter_ptr));
|
||||
} else {
|
||||
muter = it->get();
|
||||
@@ -257,9 +258,10 @@ void StreamFactory::DestroyOutputStream(OutputStream* stream) {
|
||||
DCHECK_EQ(1u, erased);
|
||||
}
|
||||
|
||||
-void StreamFactory::DestroyMuter(LocalMuter* muter) {
|
||||
+void StreamFactory::DestroyMuter(base::WeakPtr<LocalMuter> muter) {
|
||||
DCHECK_CALLED_ON_VALID_SEQUENCE(owning_sequence_);
|
||||
- DCHECK(muter);
|
||||
+ if (!muter)
|
||||
+ return;
|
||||
|
||||
// Output streams have a task posting before destruction (see the OnError
|
||||
// function in output_stream.cc). To ensure that stream destruction and
|
||||
@@ -268,13 +270,11 @@ void StreamFactory::DestroyMuter(LocalMuter* muter) {
|
||||
// Otherwise, a "destroy all streams, then destroy the muter" sequence may
|
||||
// result in a brief blip of audio.
|
||||
auto do_destroy = [](base::WeakPtr<StreamFactory> weak_this,
|
||||
- LocalMuter* muter) {
|
||||
- if (weak_this) {
|
||||
-
|
||||
+ base::WeakPtr<LocalMuter> muter) {
|
||||
+ if (weak_this && muter) {
|
||||
const auto it =
|
||||
std::find_if(weak_this->muters_.begin(), weak_this->muters_.end(),
|
||||
- base::MatchesUniquePtr(muter));
|
||||
- DCHECK(it != weak_this->muters_.end());
|
||||
+ base::MatchesUniquePtr(muter.get()));
|
||||
|
||||
// The LocalMuter can still have receivers if a receiver was bound after
|
||||
// DestroyMuter is called but before the do_destroy task is run.
|
||||
diff --git a/services/audio/stream_factory.h b/services/audio/stream_factory.h
|
||||
index 2207c72cb39e666e5c207016035a9d295d708aa0..b6119025f043e433455b35ee71e2b130299d1d21 100644
|
||||
--- a/services/audio/stream_factory.h
|
||||
+++ b/services/audio/stream_factory.h
|
||||
@@ -110,7 +110,7 @@ class StreamFactory final : public media::mojom::AudioStreamFactory {
|
||||
|
||||
void DestroyInputStream(InputStream* stream);
|
||||
void DestroyOutputStream(OutputStream* stream);
|
||||
- void DestroyMuter(LocalMuter* muter);
|
||||
+ void DestroyMuter(base::WeakPtr<LocalMuter> muter);
|
||||
void DestroyLoopbackStream(LoopbackStream* stream);
|
||||
|
||||
SEQUENCE_CHECKER(owning_sequence_);
|
||||
680
patches/chromium/cherry-pick-67c9cbc784d6.patch
Normal file
680
patches/chromium/cherry-pick-67c9cbc784d6.patch
Normal file
@@ -0,0 +1,680 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Lukasz Anforowicz <lukasza@chromium.org>
|
||||
Date: Tue, 30 Aug 2022 19:18:15 +0000
|
||||
Subject: Validate `source_context` in ExtensionHostMsg_OpenChannelToNativeApp.
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
|
||||
After this CL, the Browser process will verify `source_context` in the
|
||||
IPC payload of the ExtensionHostMsg_OpenChannelToNativeApp message and
|
||||
avoid processing malformed or spoofed IPCs.
|
||||
|
||||
Change-Id: I9466dc076c4d07dbb4bec38973000dc0418565f6
|
||||
Bug: 1356234
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3854987
|
||||
Commit-Queue: Łukasz Anforowicz <lukasza@chromium.org>
|
||||
Reviewed-by: Devlin Cronin <rdevlin.cronin@chromium.org>
|
||||
Cr-Commit-Position: refs/heads/main@{#1041118}
|
||||
|
||||
diff --git a/chrome/browser/extensions/extension_security_exploit_browsertest.cc b/chrome/browser/extensions/extension_security_exploit_browsertest.cc
|
||||
index 0bbdc8c38a99986d5b8f70f5582f78c7f8be3fa0..7f8ed5f1e0eef6db0504ad3e075d76738bc07243 100644
|
||||
--- a/chrome/browser/extensions/extension_security_exploit_browsertest.cc
|
||||
+++ b/chrome/browser/extensions/extension_security_exploit_browsertest.cc
|
||||
@@ -10,6 +10,7 @@
|
||||
#include "base/memory/scoped_refptr.h"
|
||||
#include "base/memory/weak_ptr.h"
|
||||
#include "base/test/bind.h"
|
||||
+#include "build/build_config.h"
|
||||
#include "chrome/browser/chrome_content_browser_client.h"
|
||||
#include "chrome/browser/extensions/extension_browsertest.h"
|
||||
#include "chrome/browser/extensions/extension_tab_util.h"
|
||||
@@ -45,6 +46,10 @@
|
||||
#include "third_party/blink/public/mojom/service_worker/service_worker_database.mojom-forward.h"
|
||||
#include "url/gurl.h"
|
||||
|
||||
+#if !(BUILDFLAG(IS_FUCHSIA))
|
||||
+#include "chrome/browser/extensions/api/messaging/native_messaging_test_util.h"
|
||||
+#endif
|
||||
+
|
||||
namespace extensions {
|
||||
|
||||
// ExtensionFrameHostInterceptor is a helper for:
|
||||
@@ -280,6 +285,10 @@ class ExtensionSecurityExploitBrowserTest : public ExtensionBrowserTest {
|
||||
InstallTestExtensions();
|
||||
}
|
||||
|
||||
+ content::WebContents* active_web_contents() {
|
||||
+ return browser()->tab_strip_model()->GetActiveWebContents();
|
||||
+ }
|
||||
+
|
||||
// Asks the `extension_id` to inject `content_script` into `web_contents`.
|
||||
// Returns true if the content script execution started successfully.
|
||||
bool ExecuteProgrammaticContentScript(content::WebContents* web_contents,
|
||||
@@ -293,36 +302,63 @@ class ExtensionSecurityExploitBrowserTest : public ExtensionBrowserTest {
|
||||
browser()->profile(), extension_id, background_script);
|
||||
}
|
||||
|
||||
+ const Extension& active_extension() { return *active_extension_; }
|
||||
const ExtensionId& active_extension_id() { return active_extension_->id(); }
|
||||
const ExtensionId& spoofed_extension_id() { return spoofed_extension_->id(); }
|
||||
|
||||
private:
|
||||
+ // Installs an `active_extension` and a separate, but otherwise identical
|
||||
+ // `spoofed_extension` (the only difference will be the extension id).
|
||||
void InstallTestExtensions() {
|
||||
- // Install an `active_extension` and a separate, but otherwise identical
|
||||
- // `spoofed_extension` (the only difference will be the extension id).
|
||||
- auto install_extension = [this](TestExtensionDir& dir) -> const Extension* {
|
||||
+ auto install_extension =
|
||||
+ [this](TestExtensionDir& dir,
|
||||
+ const char* extra_manifest_bits) -> const Extension* {
|
||||
const char kManifestTemplate[] = R"(
|
||||
{
|
||||
+ %s
|
||||
"name": "ContentScriptTrackerBrowserTest - Programmatic",
|
||||
"version": "1.0",
|
||||
"manifest_version": 2,
|
||||
- "permissions": [ "tabs", "<all_urls>", "storage" ],
|
||||
+ "permissions": [
|
||||
+ "tabs",
|
||||
+ "<all_urls>",
|
||||
+ "nativeMessaging",
|
||||
+ "storage"
|
||||
+ ],
|
||||
"background": {"scripts": ["background_script.js"]}
|
||||
} )";
|
||||
- dir.WriteManifest(kManifestTemplate);
|
||||
+ dir.WriteManifest(
|
||||
+ base::StringPrintf(kManifestTemplate, extra_manifest_bits));
|
||||
dir.WriteFile(FILE_PATH_LITERAL("background_script.js"), "");
|
||||
+ dir.WriteFile(FILE_PATH_LITERAL("page.html"), "<p>page</p>");
|
||||
return LoadExtension(dir.UnpackedPath());
|
||||
};
|
||||
|
||||
- TestExtensionDir active_dir;
|
||||
- TestExtensionDir spoofed_dir;
|
||||
- active_extension_ = install_extension(active_dir);
|
||||
- spoofed_extension_ = install_extension(spoofed_dir);
|
||||
+#if !(BUILDFLAG(IS_FUCHSIA))
|
||||
+ // The key below corresponds to the extension ID used by
|
||||
+ // ScopedTestNativeMessagingHost::kExtensionId.
|
||||
+ const char kActiveExtensionKey[] = R"(
|
||||
+ "key": "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDcBHwzDvyBQ6bDppkIs9MP4ksKqCMyXQ/A52JivHZKh4YO/9vJsT3oaYhSpDCE9RPocOEQvwsHsFReW2nUEc6OLLyoCFFxIb7KkLGsmfakkut/fFdNJYh0xOTbSN8YvLWcqph09XAY2Y/f0AL7vfO1cuCqtkMt8hFrBGWxDdf9CQIDAQAB",
|
||||
+ )";
|
||||
+#else
|
||||
+ // Native messaging is not available on Fuchsia (i.e.
|
||||
+ // //chrome/browser/extensions/BUILD.gn excludes
|
||||
+ // api/messaging/native_messaging_test_util.h on Fuchsia).
|
||||
+ const char kActiveExtensionKey[] = "";
|
||||
+#endif
|
||||
+ active_extension_ = install_extension(active_dir_, kActiveExtensionKey);
|
||||
+ spoofed_extension_ = install_extension(spoofed_dir_, "");
|
||||
ASSERT_TRUE(active_extension_);
|
||||
ASSERT_TRUE(spoofed_extension_);
|
||||
+#if !(BUILDFLAG(IS_FUCHSIA))
|
||||
+ ASSERT_EQ(active_extension_id(),
|
||||
+ ScopedTestNativeMessagingHost::kExtensionId);
|
||||
+#endif
|
||||
ASSERT_NE(active_extension_id(), spoofed_extension_id());
|
||||
}
|
||||
|
||||
+ TestExtensionDir active_dir_;
|
||||
+ TestExtensionDir spoofed_dir_;
|
||||
raw_ptr<const Extension> active_extension_ = nullptr;
|
||||
raw_ptr<const Extension> spoofed_extension_ = nullptr;
|
||||
};
|
||||
@@ -333,48 +369,35 @@ class OpenChannelToExtensionExploitTest
|
||||
public:
|
||||
OpenChannelToExtensionExploitTest() = default;
|
||||
|
||||
+ using OpenChannelMessageWaiter =
|
||||
+ ExtensionMessageWaiter<ExtensionHostMsg_OpenChannelToExtension>;
|
||||
void SetUpOnMainThread() override {
|
||||
ExtensionSecurityExploitBrowserTest::SetUpOnMainThread();
|
||||
|
||||
- GURL test_page_url =
|
||||
- embedded_test_server()->GetURL("foo.com", "/title1.html");
|
||||
- ipc_message_waiter_ = StartInterceptingIpcs(test_page_url);
|
||||
- }
|
||||
-
|
||||
- // Waits for ExtensionHostMsg_OpenChannelToExtension IPC and returns its
|
||||
- // payload.
|
||||
- ExtensionHostMsg_OpenChannelToExtension::Param WaitForMessage() {
|
||||
- return ipc_message_waiter_->WaitForMessage();
|
||||
- }
|
||||
-
|
||||
- private:
|
||||
- using OpenChannelMessageWaiter =
|
||||
- ExtensionMessageWaiter<ExtensionHostMsg_OpenChannelToExtension>;
|
||||
- std::unique_ptr<OpenChannelMessageWaiter> StartInterceptingIpcs(
|
||||
- const GURL& test_page_url) {
|
||||
// Start capturing IPC messages in all future/new RenderProcessHosts.
|
||||
- auto ipc_message_waiter = std::make_unique<OpenChannelMessageWaiter>();
|
||||
+ ipc_message_waiter_ = std::make_unique<OpenChannelMessageWaiter>();
|
||||
|
||||
// Navigate to an arbitrary, mostly empty test page. Make sure that a new
|
||||
// RenderProcessHost is created to make sure it is covered by the
|
||||
- // `ipc_message_waiter`. (A WebUI -> http navigation should swap the
|
||||
+ // `ipc_message_waiter_`. (A WebUI -> http navigation should swap the
|
||||
// RenderProcessHost on all platforms.)
|
||||
- content::WebContents* web_contents =
|
||||
- browser()->tab_strip_model()->GetActiveWebContents();
|
||||
+ GURL test_page_url =
|
||||
+ embedded_test_server()->GetURL("foo.com", "/title1.html");
|
||||
int old_process_id =
|
||||
- web_contents->GetPrimaryMainFrame()->GetProcess()->GetID();
|
||||
+ active_web_contents()->GetPrimaryMainFrame()->GetProcess()->GetID();
|
||||
EXPECT_TRUE(
|
||||
ui_test_utils::NavigateToURL(browser(), GURL("chrome://version")));
|
||||
EXPECT_TRUE(ui_test_utils::NavigateToURL(browser(), test_page_url));
|
||||
int new_process_id =
|
||||
- web_contents->GetPrimaryMainFrame()->GetProcess()->GetID();
|
||||
+ active_web_contents()->GetPrimaryMainFrame()->GetProcess()->GetID();
|
||||
EXPECT_NE(old_process_id, new_process_id);
|
||||
|
||||
// Only intercept messages from `active_extension`'s content script running
|
||||
// in the main frame's process.
|
||||
ExtensionId matching_extension_id = active_extension_id();
|
||||
- int matching_process_id = new_process_id;
|
||||
- ipc_message_waiter->SetIpcMatcher(base::BindLambdaForTesting(
|
||||
+ int matching_process_id =
|
||||
+ active_web_contents()->GetPrimaryMainFrame()->GetProcess()->GetID();
|
||||
+ ipc_message_waiter_->SetIpcMatcher(base::BindLambdaForTesting(
|
||||
[matching_extension_id, matching_process_id](
|
||||
int captured_render_process_id,
|
||||
const ExtensionHostMsg_OpenChannelToExtension::Param& param) {
|
||||
@@ -391,14 +414,16 @@ class OpenChannelToExtensionExploitTest
|
||||
|
||||
return true;
|
||||
}));
|
||||
+ }
|
||||
|
||||
- return ipc_message_waiter;
|
||||
+ // Waits for ExtensionHostMsg_OpenChannelToExtension IPC and returns its
|
||||
+ // payload.
|
||||
+ ExtensionHostMsg_OpenChannelToExtension::Param WaitForMessage() {
|
||||
+ return ipc_message_waiter_->WaitForMessage();
|
||||
}
|
||||
|
||||
+ private:
|
||||
std::unique_ptr<OpenChannelMessageWaiter> ipc_message_waiter_;
|
||||
-
|
||||
- raw_ptr<const Extension> active_extension_ = nullptr;
|
||||
- raw_ptr<const Extension> spoofed_extension_ = nullptr;
|
||||
};
|
||||
|
||||
IN_PROC_BROWSER_TEST_F(OpenChannelToExtensionExploitTest,
|
||||
@@ -412,24 +437,22 @@ IN_PROC_BROWSER_TEST_F(OpenChannelToExtensionExploitTest,
|
||||
|
||||
// Trigger sending of a valid ExtensionHostMsg_OpenChannelToExtension IPC
|
||||
// from a content script of an `active_extension_id`.
|
||||
- content::WebContents* web_contents =
|
||||
- browser()->tab_strip_model()->GetActiveWebContents();
|
||||
ASSERT_TRUE(ExecuteProgrammaticContentScript(
|
||||
- web_contents, active_extension_id(),
|
||||
+ active_web_contents(), active_extension_id(),
|
||||
"chrome.runtime.sendMessage({greeting: 'hello'}, (response) => {});"));
|
||||
|
||||
// Capture the IPC.
|
||||
auto [source_context, info, channel_name, port_id] = WaitForMessage();
|
||||
-
|
||||
- // Mutate the IPC payload.
|
||||
EXPECT_EQ(MessagingEndpoint::Type::kTab, info.source_endpoint.type);
|
||||
EXPECT_EQ(active_extension_id(), info.source_endpoint.extension_id);
|
||||
+
|
||||
+ // Mutate the IPC payload.
|
||||
info.source_endpoint.extension_id = spoofed_extension_id();
|
||||
|
||||
// Inject the malformed/mutated IPC and verify that the renderer is terminated
|
||||
// as expected.
|
||||
content::RenderProcessHost* main_frame_process =
|
||||
- web_contents->GetPrimaryMainFrame()->GetProcess();
|
||||
+ active_web_contents()->GetPrimaryMainFrame()->GetProcess();
|
||||
RenderProcessHostBadIpcMessageWaiter kill_waiter(main_frame_process);
|
||||
IPC::IpcSecurityTestUtil::PwnMessageReceived(
|
||||
main_frame_process->GetChannel(),
|
||||
@@ -443,24 +466,22 @@ IN_PROC_BROWSER_TEST_F(OpenChannelToExtensionExploitTest,
|
||||
FromContentScript_UnexpectedNativeAppType) {
|
||||
// Trigger sending of a valid ExtensionHostMsg_OpenChannelToExtension IPC
|
||||
// from a content script of an `active_extension_id`.
|
||||
- content::WebContents* web_contents =
|
||||
- browser()->tab_strip_model()->GetActiveWebContents();
|
||||
ASSERT_TRUE(ExecuteProgrammaticContentScript(
|
||||
- web_contents, active_extension_id(),
|
||||
+ active_web_contents(), active_extension_id(),
|
||||
"chrome.runtime.sendMessage({greeting: 'hello'}, (response) => {});"));
|
||||
|
||||
// Capture the IPC.
|
||||
auto [source_context, info, channel_name, port_id] = WaitForMessage();
|
||||
-
|
||||
- // Mutate the IPC payload.
|
||||
EXPECT_EQ(MessagingEndpoint::Type::kTab, info.source_endpoint.type);
|
||||
EXPECT_EQ(active_extension_id(), info.source_endpoint.extension_id);
|
||||
+
|
||||
+ // Mutate the IPC payload.
|
||||
info.source_endpoint.type = MessagingEndpoint::Type::kNativeApp;
|
||||
|
||||
// Inject the malformed/mutated IPC and verify that the renderer is terminated
|
||||
// as expected.
|
||||
content::RenderProcessHost* main_frame_process =
|
||||
- web_contents->GetPrimaryMainFrame()->GetProcess();
|
||||
+ active_web_contents()->GetPrimaryMainFrame()->GetProcess();
|
||||
RenderProcessHostBadIpcMessageWaiter kill_waiter(main_frame_process);
|
||||
IPC::IpcSecurityTestUtil::PwnMessageReceived(
|
||||
main_frame_process->GetChannel(),
|
||||
@@ -473,24 +494,22 @@ IN_PROC_BROWSER_TEST_F(OpenChannelToExtensionExploitTest,
|
||||
FromContentScript_UnexpectedExtensionType) {
|
||||
// Trigger sending of a valid ExtensionHostMsg_OpenChannelToExtension IPC
|
||||
// from a content script of an `active_extension_id`.
|
||||
- content::WebContents* web_contents =
|
||||
- browser()->tab_strip_model()->GetActiveWebContents();
|
||||
ASSERT_TRUE(ExecuteProgrammaticContentScript(
|
||||
- web_contents, active_extension_id(),
|
||||
+ active_web_contents(), active_extension_id(),
|
||||
"chrome.runtime.sendMessage({greeting: 'hello'}, (response) => {});"));
|
||||
|
||||
// Capture the IPC.
|
||||
auto [source_context, info, channel_name, port_id] = WaitForMessage();
|
||||
-
|
||||
- // Mutate the IPC payload.
|
||||
EXPECT_EQ(MessagingEndpoint::Type::kTab, info.source_endpoint.type);
|
||||
EXPECT_EQ(active_extension_id(), info.source_endpoint.extension_id);
|
||||
+
|
||||
+ // Mutate the IPC payload.
|
||||
info.source_endpoint.type = MessagingEndpoint::Type::kExtension;
|
||||
|
||||
// Inject the malformed/mutated IPC and verify that the renderer is terminated
|
||||
// as expected.
|
||||
content::RenderProcessHost* main_frame_process =
|
||||
- web_contents->GetPrimaryMainFrame()->GetProcess();
|
||||
+ active_web_contents()->GetPrimaryMainFrame()->GetProcess();
|
||||
RenderProcessHostBadIpcMessageWaiter kill_waiter(main_frame_process);
|
||||
IPC::IpcSecurityTestUtil::PwnMessageReceived(
|
||||
main_frame_process->GetChannel(),
|
||||
@@ -504,25 +523,23 @@ IN_PROC_BROWSER_TEST_F(OpenChannelToExtensionExploitTest,
|
||||
FromContentScript_NoExtensionIdForExtensionType) {
|
||||
// Trigger sending of a valid ExtensionHostMsg_OpenChannelToExtension IPC
|
||||
// from a content script of an `active_extension_id`.
|
||||
- content::WebContents* web_contents =
|
||||
- browser()->tab_strip_model()->GetActiveWebContents();
|
||||
ASSERT_TRUE(ExecuteProgrammaticContentScript(
|
||||
- web_contents, active_extension_id(),
|
||||
+ active_web_contents(), active_extension_id(),
|
||||
"chrome.runtime.sendMessage({greeting: 'hello'}, (response) => {});"));
|
||||
|
||||
// Capture the IPC.
|
||||
auto [source_context, info, channel_name, port_id] = WaitForMessage();
|
||||
-
|
||||
- // Mutate the IPC payload.
|
||||
EXPECT_EQ(MessagingEndpoint::Type::kTab, info.source_endpoint.type);
|
||||
EXPECT_EQ(active_extension_id(), info.source_endpoint.extension_id);
|
||||
+
|
||||
+ // Mutate the IPC payload.
|
||||
info.source_endpoint.type = MessagingEndpoint::Type::kExtension;
|
||||
info.source_endpoint.extension_id = absl::nullopt;
|
||||
|
||||
// Inject the malformed/mutated IPC and verify that the renderer is terminated
|
||||
// as expected.
|
||||
content::RenderProcessHost* main_frame_process =
|
||||
- web_contents->GetPrimaryMainFrame()->GetProcess();
|
||||
+ active_web_contents()->GetPrimaryMainFrame()->GetProcess();
|
||||
RenderProcessHostBadIpcMessageWaiter kill_waiter(main_frame_process);
|
||||
IPC::IpcSecurityTestUtil::PwnMessageReceived(
|
||||
main_frame_process->GetChannel(),
|
||||
@@ -536,18 +553,16 @@ IN_PROC_BROWSER_TEST_F(OpenChannelToExtensionExploitTest,
|
||||
FromContentScript_UnexpectedWorkerContext) {
|
||||
// Trigger sending of a valid ExtensionHostMsg_OpenChannelToExtension IPC
|
||||
// from a content script of an `active_extension_id`.
|
||||
- content::WebContents* web_contents =
|
||||
- browser()->tab_strip_model()->GetActiveWebContents();
|
||||
ASSERT_TRUE(ExecuteProgrammaticContentScript(
|
||||
- web_contents, active_extension_id(),
|
||||
+ active_web_contents(), active_extension_id(),
|
||||
"chrome.runtime.sendMessage({greeting: 'hello'}, (response) => {});"));
|
||||
|
||||
// Capture the IPC.
|
||||
auto [source_context, info, channel_name, port_id] = WaitForMessage();
|
||||
-
|
||||
- // Mutate the IPC payload.
|
||||
EXPECT_TRUE(source_context.is_for_render_frame());
|
||||
EXPECT_FALSE(source_context.is_for_service_worker());
|
||||
+
|
||||
+ // Mutate the IPC payload.
|
||||
source_context.frame = absl::nullopt;
|
||||
source_context.worker = PortContext::WorkerContext(
|
||||
/* thread_id = */ 123, /* version_id = */ 456,
|
||||
@@ -556,7 +571,7 @@ IN_PROC_BROWSER_TEST_F(OpenChannelToExtensionExploitTest,
|
||||
// Inject the malformed/mutated IPC and verify that the renderer is terminated
|
||||
// as expected.
|
||||
content::RenderProcessHost* main_frame_process =
|
||||
- web_contents->GetPrimaryMainFrame()->GetProcess();
|
||||
+ active_web_contents()->GetPrimaryMainFrame()->GetProcess();
|
||||
RenderProcessHostBadIpcMessageWaiter kill_waiter(main_frame_process);
|
||||
IPC::IpcSecurityTestUtil::PwnMessageReceived(
|
||||
main_frame_process->GetChannel(),
|
||||
@@ -566,21 +581,115 @@ IN_PROC_BROWSER_TEST_F(OpenChannelToExtensionExploitTest,
|
||||
kill_waiter.Wait());
|
||||
}
|
||||
|
||||
+// Native messaging is not available on Fuchsia (i.e.
|
||||
+// //chrome/browser/extensions/BUILD.gn excludes
|
||||
+// api/messaging/native_messaging_test_util.h on Fuchsia).
|
||||
+#if !(BUILDFLAG(IS_FUCHSIA))
|
||||
+
|
||||
+// Test suite for covering ExtensionHostMsg_OpenChannelToNativeApp IPC.
|
||||
+class OpenChannelToNativeAppExploitTest
|
||||
+ : public ExtensionSecurityExploitBrowserTest {
|
||||
+ public:
|
||||
+ OpenChannelToNativeAppExploitTest() = default;
|
||||
+
|
||||
+ using OpenChannelMessageWaiter =
|
||||
+ ExtensionMessageWaiter<ExtensionHostMsg_OpenChannelToNativeApp>;
|
||||
+ void SetUpOnMainThread() override {
|
||||
+ // Set up ExtensionMessageWaiter *before* installing the extensions (i.e.
|
||||
+ // *before* the corresponding RenderProcessHost objects are created).
|
||||
+ ipc_message_waiter_ = std::make_unique<OpenChannelMessageWaiter>();
|
||||
+
|
||||
+ // SetUpOnMainThread in the base class will install the test extensions.
|
||||
+ ExtensionSecurityExploitBrowserTest::SetUpOnMainThread();
|
||||
+
|
||||
+ // Register a (fake, test-only) native messaging host.
|
||||
+ test_native_messaging_host_.RegisterTestHost(/* user_level= */ false);
|
||||
+
|
||||
+ // Navigate the test tab to an extension page.
|
||||
+ GURL test_page_url = active_extension().GetResourceURL("page.html");
|
||||
+ EXPECT_TRUE(ui_test_utils::NavigateToURL(browser(), test_page_url));
|
||||
+
|
||||
+ // Only intercept messages from the test process.
|
||||
+ int matching_process_id =
|
||||
+ active_web_contents()->GetPrimaryMainFrame()->GetProcess()->GetID();
|
||||
+ ipc_message_waiter_->SetIpcMatcher(base::BindLambdaForTesting(
|
||||
+ [matching_process_id](
|
||||
+ int captured_render_process_id,
|
||||
+ const ExtensionHostMsg_OpenChannelToNativeApp::Param& param) {
|
||||
+ if (captured_render_process_id != matching_process_id)
|
||||
+ return false;
|
||||
+
|
||||
+ return true;
|
||||
+ }));
|
||||
+ }
|
||||
+
|
||||
+ // Waits for ExtensionHostMsg_OpenChannelToNativeApp IPC and returns its
|
||||
+ // payload.
|
||||
+ ExtensionHostMsg_OpenChannelToNativeApp::Param WaitForMessage() {
|
||||
+ return ipc_message_waiter_->WaitForMessage();
|
||||
+ }
|
||||
+
|
||||
+ private:
|
||||
+ ScopedTestNativeMessagingHost test_native_messaging_host_;
|
||||
+ std::unique_ptr<OpenChannelMessageWaiter> ipc_message_waiter_;
|
||||
+};
|
||||
+
|
||||
+IN_PROC_BROWSER_TEST_F(OpenChannelToNativeAppExploitTest,
|
||||
+ SourceContextWithSpoofedExtensionId) {
|
||||
+ // Trigger sending of a valid ExtensionHostMsg_OpenChannelToNativeApp IPC
|
||||
+ // from a frame of an `active_extension`.
|
||||
+ const char kScript[] = R"(
|
||||
+ var message = {text: 'Hello!'};
|
||||
+ var host = $1;
|
||||
+ chrome.runtime.sendNativeMessage(host, message);
|
||||
+ )";
|
||||
+ ASSERT_EQ(
|
||||
+ active_extension().origin(),
|
||||
+ active_web_contents()->GetPrimaryMainFrame()->GetLastCommittedOrigin());
|
||||
+ ASSERT_TRUE(content::ExecuteScript(
|
||||
+ active_web_contents(),
|
||||
+ content::JsReplace(kScript, ScopedTestNativeMessagingHost::kHostName)));
|
||||
+
|
||||
+ // Capture the IPC.
|
||||
+ auto [source_context, native_app_name, port_id] = WaitForMessage();
|
||||
+ EXPECT_EQ(native_app_name, ScopedTestNativeMessagingHost::kHostName);
|
||||
+ EXPECT_TRUE(source_context.is_for_render_frame());
|
||||
+
|
||||
+ // Mutate the IPC payload.
|
||||
+ source_context = PortContext::ForWorker(123, // thread_id
|
||||
+ 456, // version_id
|
||||
+ spoofed_extension_id());
|
||||
+
|
||||
+ // Inject the malformed/mutated IPC and verify that the renderer is terminated
|
||||
+ // as expected.
|
||||
+ content::RenderProcessHost* main_frame_process =
|
||||
+ active_web_contents()->GetPrimaryMainFrame()->GetProcess();
|
||||
+ RenderProcessHostBadIpcMessageWaiter kill_waiter(main_frame_process);
|
||||
+ IPC::IpcSecurityTestUtil::PwnMessageReceived(
|
||||
+ main_frame_process->GetChannel(),
|
||||
+ ExtensionHostMsg_OpenChannelToNativeApp(source_context, native_app_name,
|
||||
+ port_id));
|
||||
+ EXPECT_EQ(bad_message::EMF_INVALID_EXTENSION_ID_FOR_WORKER_CONTEXT,
|
||||
+ kill_waiter.Wait());
|
||||
+}
|
||||
+
|
||||
+#endif // !(BUILDFLAG(IS_FUCHSIA)) - native messaging is available
|
||||
+
|
||||
IN_PROC_BROWSER_TEST_F(ExtensionSecurityExploitBrowserTest,
|
||||
SpoofedExtensionId_ExtensionFunctionDispatcher) {
|
||||
// Navigate to a test page.
|
||||
GURL test_page_url =
|
||||
embedded_test_server()->GetURL("foo.com", "/title1.html");
|
||||
ASSERT_TRUE(ui_test_utils::NavigateToURL(browser(), test_page_url));
|
||||
- content::WebContents* web_contents =
|
||||
- browser()->tab_strip_model()->GetActiveWebContents();
|
||||
- content::RenderFrameHost* main_frame = web_contents->GetPrimaryMainFrame();
|
||||
+ content::RenderFrameHost* main_frame =
|
||||
+ active_web_contents()->GetPrimaryMainFrame();
|
||||
|
||||
// Verify the test setup by checking if the non-intercepted `chrome.storage`
|
||||
// API call will succeed.
|
||||
{
|
||||
ExtensionTestMessageListener listener("Got chrome.storage response");
|
||||
- ExecuteProgrammaticContentScript(web_contents, active_extension_id(), R"(
|
||||
+ ExecuteProgrammaticContentScript(active_web_contents(),
|
||||
+ active_extension_id(), R"(
|
||||
chrome.storage.local.set(
|
||||
{ test_key: 'test value'},
|
||||
() => {
|
||||
@@ -607,7 +716,8 @@ IN_PROC_BROWSER_TEST_F(ExtensionSecurityExploitBrowserTest,
|
||||
// terminating the misbehaving renderer process.
|
||||
content::RenderProcessHostBadMojoMessageWaiter kill_waiter(
|
||||
main_frame->GetProcess());
|
||||
- ExecuteProgrammaticContentScript(web_contents, active_extension_id(), R"(
|
||||
+ ExecuteProgrammaticContentScript(active_web_contents(), active_extension_id(),
|
||||
+ R"(
|
||||
chrome.storage.local.set({ test_key: 'test value2'}, () => {}); )");
|
||||
EXPECT_EQ(
|
||||
"Received bad user message: LocalFrameHost::Request: renderer never "
|
||||
diff --git a/docs/security/compromised-renderers.md b/docs/security/compromised-renderers.md
|
||||
index b7e56be454f2d42dc4ae4ac875586a01f2354d9a..2155a399e0e432fedc2792b6893440efd7fca572 100644
|
||||
--- a/docs/security/compromised-renderers.md
|
||||
+++ b/docs/security/compromised-renderers.md
|
||||
@@ -213,14 +213,21 @@ Compromised renderers shouldn’t be able to:
|
||||
- Spoof the `MessageEvent.origin` seen by a recipient of a `postMessage`.
|
||||
- Bypass enforcement of the `targetOrigin` argument of `postMessage`.
|
||||
- Send or receive `BroadcastChannel` messages for another origin.
|
||||
-- Spoof the `MessageSender.origin` seen by a recipient of a
|
||||
- `chrome.runtime.sendMessage`
|
||||
- (see also [MessageSender documentation](https://developers.chrome.com/extensions/runtime#type-MessageSender) and [content script security guidance](https://groups.google.com/a/chromium.org/forum/#!topic/chromium-extensions/0ei-UCHNm34)).
|
||||
+- Spoof the `MessageSender.origin`, nor `MessageSender.id` (i.e. an
|
||||
+ extension id which can differ from the origin when the message is sent
|
||||
+ from a content script), as seen by a recipient of a
|
||||
+ `chrome.runtime.sendMessage`.
|
||||
+ See also [MessageSender documentation](https://developers.chrome.com/extensions/runtime#type-MessageSender) and [content script security guidance](https://groups.google.com/a/chromium.org/forum/#!topic/chromium-extensions/0ei-UCHNm34).
|
||||
+- Spoof the id of a Chrome extension initiating
|
||||
+ [native messaging](https://developer.chrome.com/docs/apps/nativeMessaging/)
|
||||
+ communication.
|
||||
|
||||
Protection techniques:
|
||||
- Using `CanAccessDataForOrigin` to verify IPCs sent by a renderer process
|
||||
(e.g. in `RenderFrameProxyHost::OnRouteMessageEvent` or
|
||||
`BroadcastChannelProvider::ConnectToChannel`).
|
||||
+- Using `ContentScriptTracker` to check if IPCs from a given renderer process
|
||||
+ can legitimately claim to act on behalf content scripts of a given extension.
|
||||
|
||||
**Known gaps in protection**:
|
||||
- Spoofing of `MessageSender.id` object
|
||||
diff --git a/extensions/browser/api/messaging/messaging_api_message_filter.cc b/extensions/browser/api/messaging/messaging_api_message_filter.cc
|
||||
index 25af213a4c02d7994eddb4dcb29a37871accd807..faf61a3b2bcb531934b8522b95b64930fff463dd 100644
|
||||
--- a/extensions/browser/api/messaging/messaging_api_message_filter.cc
|
||||
+++ b/extensions/browser/api/messaging/messaging_api_message_filter.cc
|
||||
@@ -146,6 +146,16 @@ bool IsValidSourceContext(RenderProcessHost& process,
|
||||
}
|
||||
}
|
||||
|
||||
+ // This function doesn't validate frame-flavoured `source_context`s, because
|
||||
+ // PortContext::FrameContext only contains frame's `routing_id` and therefore
|
||||
+ // inherently cannot spoof frames in another process (a frame is identified
|
||||
+ // by its `routing_id` *and* the `process_id` of the Renderer process hosting
|
||||
+ // the frame; the latter is trustworthy / doesn't come from an IPC payload).
|
||||
+
|
||||
+ // This function doesn't validate native app `source_context`s, because
|
||||
+ // `PortContext::ForNativeHost()` is called with trustoworthy inputs (e.g. it
|
||||
+ // doesn't take input from IPCs sent by a Renderer process).
|
||||
+
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -217,6 +227,18 @@ void MessagingAPIMessageFilter::Shutdown() {
|
||||
shutdown_notifier_subscription_ = {};
|
||||
}
|
||||
|
||||
+content::RenderProcessHost* MessagingAPIMessageFilter::GetRenderProcessHost() {
|
||||
+ DCHECK_CURRENTLY_ON(BrowserThread::UI);
|
||||
+ if (!browser_context_)
|
||||
+ return nullptr;
|
||||
+
|
||||
+ // The IPC might race with RenderProcessHost destruction. This may only
|
||||
+ // happen in scenarios that are already inherently racey, so returning nullptr
|
||||
+ // (and dropping the IPC) is okay and won't lead to any additional risk of
|
||||
+ // data loss.
|
||||
+ return content::RenderProcessHost::FromID(render_process_id_);
|
||||
+}
|
||||
+
|
||||
void MessagingAPIMessageFilter::OverrideThreadForMessage(
|
||||
const IPC::Message& message,
|
||||
BrowserThread::ID* thread) {
|
||||
@@ -262,19 +284,14 @@ void MessagingAPIMessageFilter::OnOpenChannelToExtension(
|
||||
const std::string& channel_name,
|
||||
const PortId& port_id) {
|
||||
DCHECK_CURRENTLY_ON(BrowserThread::UI);
|
||||
- if (!browser_context_)
|
||||
- return;
|
||||
-
|
||||
- // The IPC might race with RenderProcessHost destruction. This may only
|
||||
- // happen in scenarios that are already inherently racey, so dropping the IPC
|
||||
- // is okay and won't lead to any additional risk of data loss.
|
||||
- auto* process = content::RenderProcessHost::FromID(render_process_id_);
|
||||
+ auto* process = GetRenderProcessHost();
|
||||
if (!process)
|
||||
return;
|
||||
TRACE_EVENT("extensions", "MessageFilter::OnOpenChannelToExtension",
|
||||
ChromeTrackEvent::kRenderProcessHost, *process);
|
||||
|
||||
ScopedExternalConnectionInfoCrashKeys info_crash_keys(info);
|
||||
+ debug::ScopedPortContextCrashKeys port_context_crash_keys(source_context);
|
||||
if (!IsValidMessagingSource(*process, info.source_endpoint) ||
|
||||
!IsValidSourceContext(*process, source_context)) {
|
||||
return;
|
||||
@@ -293,7 +310,14 @@ void MessagingAPIMessageFilter::OnOpenChannelToNativeApp(
|
||||
const std::string& native_app_name,
|
||||
const PortId& port_id) {
|
||||
DCHECK_CURRENTLY_ON(BrowserThread::UI);
|
||||
- if (!browser_context_)
|
||||
+ auto* process = GetRenderProcessHost();
|
||||
+ if (!process)
|
||||
+ return;
|
||||
+ TRACE_EVENT("extensions", "MessageFilter::OnOpenChannelToNativeApp",
|
||||
+ ChromeTrackEvent::kRenderProcessHost, *process);
|
||||
+
|
||||
+ debug::ScopedPortContextCrashKeys port_context_crash_keys(source_context);
|
||||
+ if (!IsValidSourceContext(*process, source_context))
|
||||
return;
|
||||
|
||||
ChannelEndpoint source_endpoint(browser_context_, render_process_id_,
|
||||
diff --git a/extensions/browser/api/messaging/messaging_api_message_filter.h b/extensions/browser/api/messaging/messaging_api_message_filter.h
|
||||
index 6a0ccd698629f650d68f2b4ee168aa2b3b3a116c..3358187387cd9a5765a7bd4e522aeecfd787e06b 100644
|
||||
--- a/extensions/browser/api/messaging/messaging_api_message_filter.h
|
||||
+++ b/extensions/browser/api/messaging/messaging_api_message_filter.h
|
||||
@@ -14,6 +14,7 @@ struct ExtensionMsg_TabTargetConnectionInfo;
|
||||
|
||||
namespace content {
|
||||
class BrowserContext;
|
||||
+class RenderProcessHost;
|
||||
}
|
||||
|
||||
namespace extensions {
|
||||
@@ -40,6 +41,11 @@ class MessagingAPIMessageFilter : public content::BrowserMessageFilter {
|
||||
|
||||
void Shutdown();
|
||||
|
||||
+ // Returns the process that the IPC came from, or `nullptr` if the IPC should
|
||||
+ // be dropped (in case the IPC arrived racily after the process or its
|
||||
+ // BrowserContext already got destructed).
|
||||
+ content::RenderProcessHost* GetRenderProcessHost();
|
||||
+
|
||||
// content::BrowserMessageFilter implementation:
|
||||
void OverrideThreadForMessage(const IPC::Message& message,
|
||||
content::BrowserThread::ID* thread) override;
|
||||
diff --git a/extensions/common/api/messaging/port_context.cc b/extensions/common/api/messaging/port_context.cc
|
||||
index 6872179450d8295de7f15dc1437e9d6edefe4fde..319e2f34eca730c5eb7cf94ef8cdede0ddc3f8e1 100644
|
||||
--- a/extensions/common/api/messaging/port_context.cc
|
||||
+++ b/extensions/common/api/messaging/port_context.cc
|
||||
@@ -40,4 +40,27 @@ PortContext PortContext::ForNativeHost() {
|
||||
return PortContext();
|
||||
}
|
||||
|
||||
+namespace debug {
|
||||
+
|
||||
+namespace {
|
||||
+
|
||||
+base::debug::CrashKeyString* GetServiceWorkerExtensionIdCrashKey() {
|
||||
+ static auto* crash_key = base::debug::AllocateCrashKeyString(
|
||||
+ "PortContext-worker-extension_id", base::debug::CrashKeySize::Size64);
|
||||
+ return crash_key;
|
||||
+}
|
||||
+
|
||||
+} // namespace
|
||||
+
|
||||
+ScopedPortContextCrashKeys::ScopedPortContextCrashKeys(
|
||||
+ const PortContext& port_context) {
|
||||
+ if (port_context.is_for_service_worker()) {
|
||||
+ extension_id_.emplace(GetServiceWorkerExtensionIdCrashKey(),
|
||||
+ port_context.worker->extension_id);
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+ScopedPortContextCrashKeys::~ScopedPortContextCrashKeys() = default;
|
||||
+
|
||||
+} // namespace debug
|
||||
} // namespace extensions
|
||||
diff --git a/extensions/common/api/messaging/port_context.h b/extensions/common/api/messaging/port_context.h
|
||||
index b2e9f057b531d90dc256773959cd586953e4915c..53d94c2ad73c58d45b186a32989e2f4864e67d79 100644
|
||||
--- a/extensions/common/api/messaging/port_context.h
|
||||
+++ b/extensions/common/api/messaging/port_context.h
|
||||
@@ -9,6 +9,7 @@
|
||||
|
||||
#include <string>
|
||||
|
||||
+#include "base/debug/crash_logging.h"
|
||||
#include "third_party/abseil-cpp/absl/types/optional.h"
|
||||
|
||||
namespace extensions {
|
||||
@@ -59,6 +60,19 @@ struct PortContext {
|
||||
absl::optional<WorkerContext> worker;
|
||||
};
|
||||
|
||||
+namespace debug {
|
||||
+
|
||||
+class ScopedPortContextCrashKeys {
|
||||
+ public:
|
||||
+ explicit ScopedPortContextCrashKeys(const PortContext& port_context);
|
||||
+ ~ScopedPortContextCrashKeys();
|
||||
+
|
||||
+ private:
|
||||
+ absl::optional<base::debug::ScopedCrashKeyString> extension_id_;
|
||||
+};
|
||||
+
|
||||
+} // namespace debug
|
||||
+
|
||||
} // namespace extensions
|
||||
|
||||
#endif // EXTENSIONS_COMMON_API_MESSAGING_PORT_CONTEXT_H_
|
||||
42
patches/chromium/cherry-pick-77208afba04d.patch
Normal file
42
patches/chromium/cherry-pick-77208afba04d.patch
Normal file
@@ -0,0 +1,42 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Jaroslav Sevcik <jarin@chromium.org>
|
||||
Date: Thu, 1 Dec 2022 14:15:52 +0000
|
||||
Subject: Make WidgetBase::BeginMainFrame resilient to disposed 'this'
|
||||
|
||||
This patch makes sure that WidgetBase::BeginMainFrame can finish
|
||||
execution even if processing the RAF-throttled handlers
|
||||
(DispatchRafAlignedInput) destroys 'this' instance.
|
||||
|
||||
(cherry picked from commit af6e22c14bec7ad64115b24ece6d423f144214ca)
|
||||
|
||||
Bug: chromium:1381871
|
||||
Change-Id: I81aa4ba697f80f8666bb2a3b5542cac210b1efa9
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/4030809
|
||||
Reviewed-by: Dave Tapuska <dtapuska@chromium.org>
|
||||
Commit-Queue: Jaroslav Sevcik <jarin@chromium.org>
|
||||
Cr-Original-Commit-Position: refs/heads/main@{#1072864}
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/4068023
|
||||
Auto-Submit: Jaroslav Sevcik <jarin@chromium.org>
|
||||
Commit-Queue: Dave Tapuska <dtapuska@chromium.org>
|
||||
Cr-Commit-Position: refs/branch-heads/5359@{#1053}
|
||||
Cr-Branched-From: 27d3765d341b09369006d030f83f582a29eb57ae-refs/heads/main@{#1058933}
|
||||
|
||||
diff --git a/third_party/blink/renderer/platform/widget/widget_base.cc b/third_party/blink/renderer/platform/widget/widget_base.cc
|
||||
index 115f0e5774a3adde821bd34e5fac6645989e400e..4255884857a8d869a7a1e4f262f0f487dde16e24 100644
|
||||
--- a/third_party/blink/renderer/platform/widget/widget_base.cc
|
||||
+++ b/third_party/blink/renderer/platform/widget/widget_base.cc
|
||||
@@ -893,8 +893,14 @@ void WidgetBase::BeginMainFrame(base::TimeTicks frame_time) {
|
||||
if (ShouldRecordBeginMainFrameMetrics()) {
|
||||
raf_aligned_input_start_time = base::TimeTicks::Now();
|
||||
}
|
||||
+
|
||||
+ auto weak_this = weak_ptr_factory_.GetWeakPtr();
|
||||
widget_input_handler_manager_->input_event_queue()->DispatchRafAlignedInput(
|
||||
frame_time);
|
||||
+ // DispatchRafAlignedInput could have detached the frame.
|
||||
+ if (!weak_this)
|
||||
+ return;
|
||||
+
|
||||
if (ShouldRecordBeginMainFrameMetrics()) {
|
||||
client_->RecordDispatchRafAlignedInputTime(raf_aligned_input_start_time);
|
||||
}
|
||||
43
patches/chromium/cherry-pick-819d876e1bb8.patch
Normal file
43
patches/chromium/cherry-pick-819d876e1bb8.patch
Normal file
@@ -0,0 +1,43 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Ted Meyer <tmathmeyer@chromium.org>
|
||||
Date: Sat, 3 Dec 2022 00:09:22 +0000
|
||||
Subject: Fix UAF caused by vector operations during iteration
|
||||
|
||||
MediaInspectorContextImpl::CullPlayers iterates through dead_players_
|
||||
to remove their events, but this can cause a GC event which can
|
||||
end up adding more players to the |dead_players_| vector, causing
|
||||
it to get re-allocated and it's iterators invalidated.
|
||||
|
||||
We can fix this simply by not using an iterator, and removing elements
|
||||
from the vector before we trigger any GC operations that might cause
|
||||
other changes to the vector.
|
||||
|
||||
Bug: 1383991
|
||||
|
||||
Change-Id: I59f5824c156ff58cf6b55ac9b942c8efdb1ed65a
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/4064295
|
||||
Reviewed-by: Andrey Kosyakov <caseq@chromium.org>
|
||||
Commit-Queue: Ted (Chromium) Meyer <tmathmeyer@chromium.org>
|
||||
Reviewed-by: Thomas Guilbert <tguilbert@chromium.org>
|
||||
Cr-Commit-Position: refs/heads/main@{#1078842}
|
||||
|
||||
diff --git a/third_party/blink/renderer/core/inspector/inspector_media_context_impl.cc b/third_party/blink/renderer/core/inspector/inspector_media_context_impl.cc
|
||||
index c0965693783d5cc0eade67fc78f026cec2942792..6e89262ca229b89407c3f6fff2ab5bf74be460e0 100644
|
||||
--- a/third_party/blink/renderer/core/inspector/inspector_media_context_impl.cc
|
||||
+++ b/third_party/blink/renderer/core/inspector/inspector_media_context_impl.cc
|
||||
@@ -109,9 +109,13 @@ void MediaInspectorContextImpl::TrimPlayer(const WebString& playerId) {
|
||||
|
||||
void MediaInspectorContextImpl::CullPlayers(const WebString& prefer_keep) {
|
||||
// Erase all the dead players, but only erase the required number of others.
|
||||
- for (const auto& playerId : dead_players_)
|
||||
+ while (!dead_players_.IsEmpty()) {
|
||||
+ auto playerId = dead_players_.back();
|
||||
+ // remove it first, since |RemovePlayer| can cause a GC event which can
|
||||
+ // potentially caues more players to get added to |dead_players_|.
|
||||
+ dead_players_.pop_back();
|
||||
RemovePlayer(playerId);
|
||||
- dead_players_.clear();
|
||||
+ }
|
||||
|
||||
while (!expendable_players_.IsEmpty()) {
|
||||
if (total_event_count_ <= kMaxCachedPlayerEvents)
|
||||
323
patches/chromium/cherry-pick-933cc81c6bad.patch
Normal file
323
patches/chromium/cherry-pick-933cc81c6bad.patch
Normal file
@@ -0,0 +1,323 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Xiaocheng Hu <xiaochengh@chromium.org>
|
||||
Date: Sat, 10 Sep 2022 05:53:49 +0000
|
||||
Subject: Remove symlinks from FileChooserImpl folder upload result
|
||||
|
||||
FileChooserImpl is the browser-side implementation of
|
||||
<input type=file>. When uploading a whole folder, it
|
||||
currently uses DirectoryLister to list all the files in a
|
||||
directory. The result also includes resolved symbolic links
|
||||
(which may even hide deep in some subfolder), which is not a
|
||||
desired behavior.
|
||||
|
||||
Therefore, this patch removes all symbolic links from the
|
||||
result by checking each file against `base::IsLink()`. Since
|
||||
the function needs blocking calls to access file data, the
|
||||
job is sent to a worker pool thread.
|
||||
|
||||
Fixed: 1345275
|
||||
Change-Id: I8ab58214c87944408c64b177e915247a7485925b
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3866767
|
||||
Reviewed-by: Austin Sullivan <asully@chromium.org>
|
||||
Commit-Queue: Xiaocheng Hu <xiaochengh@chromium.org>
|
||||
Reviewed-by: Mason Freed <masonf@chromium.org>
|
||||
Reviewed-by: Alex Moshchuk <alexmos@chromium.org>
|
||||
Cr-Commit-Position: refs/heads/main@{#1045491}
|
||||
|
||||
diff --git a/content/browser/web_contents/file_chooser_impl.cc b/content/browser/web_contents/file_chooser_impl.cc
|
||||
index 7a3ea45d32c97980c141662f6a071cc517a15ad8..1aa19f7a735b444f2c33d5084edcdd14e3c2f5c5 100644
|
||||
--- a/content/browser/web_contents/file_chooser_impl.cc
|
||||
+++ b/content/browser/web_contents/file_chooser_impl.cc
|
||||
@@ -4,8 +4,11 @@
|
||||
|
||||
#include "content/browser/web_contents/file_chooser_impl.h"
|
||||
|
||||
+#include "base/files/file_util.h"
|
||||
#include "base/logging.h"
|
||||
#include "base/memory/ptr_util.h"
|
||||
+#include "base/ranges/algorithm.h"
|
||||
+#include "base/task/thread_pool.h"
|
||||
#include "content/browser/child_process_security_policy_impl.h"
|
||||
#include "content/browser/renderer_host/back_forward_cache_disable.h"
|
||||
#include "content/browser/renderer_host/render_frame_host_delegate.h"
|
||||
@@ -18,6 +21,19 @@
|
||||
|
||||
namespace content {
|
||||
|
||||
+namespace {
|
||||
+
|
||||
+std::vector<blink::mojom::FileChooserFileInfoPtr> RemoveSymlinks(
|
||||
+ std::vector<blink::mojom::FileChooserFileInfoPtr> files) {
|
||||
+ auto new_end = base::ranges::remove_if(
|
||||
+ files, &base::IsLink,
|
||||
+ [](const auto& file) { return file->get_native_file()->file_path; });
|
||||
+ files.erase(new_end, files.end());
|
||||
+ return files;
|
||||
+}
|
||||
+
|
||||
+} // namespace
|
||||
+
|
||||
FileChooserImpl::FileSelectListenerImpl::~FileSelectListenerImpl() {
|
||||
#if DCHECK_IS_ON()
|
||||
if (!was_file_select_listener_function_called_) {
|
||||
@@ -51,8 +67,20 @@ void FileChooserImpl::FileSelectListenerImpl::FileSelected(
|
||||
"FileSelectListener::FileSelectionCanceled()";
|
||||
was_file_select_listener_function_called_ = true;
|
||||
#endif
|
||||
- if (owner_)
|
||||
- owner_->FileSelected(std::move(files), base_dir, mode);
|
||||
+ if (!owner_)
|
||||
+ return;
|
||||
+
|
||||
+ if (mode != blink::mojom::FileChooserParams::Mode::kUploadFolder) {
|
||||
+ owner_->FileSelected(base_dir, mode, std::move(files));
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
+ base::ThreadPool::PostTaskAndReplyWithResult(
|
||||
+ FROM_HERE,
|
||||
+ {base::MayBlock(), base::TaskShutdownBehavior::CONTINUE_ON_SHUTDOWN},
|
||||
+ base::BindOnce(&RemoveSymlinks, std::move(files)),
|
||||
+ base::BindOnce(&FileChooserImpl::FileSelected, owner_->GetWeakPtr(),
|
||||
+ base_dir, mode));
|
||||
}
|
||||
|
||||
void FileChooserImpl::FileSelectListenerImpl::FileSelectionCanceled() {
|
||||
@@ -162,9 +190,9 @@ void FileChooserImpl::EnumerateChosenDirectory(
|
||||
}
|
||||
|
||||
void FileChooserImpl::FileSelected(
|
||||
- std::vector<blink::mojom::FileChooserFileInfoPtr> files,
|
||||
const base::FilePath& base_dir,
|
||||
- blink::mojom::FileChooserParams::Mode mode) {
|
||||
+ blink::mojom::FileChooserParams::Mode mode,
|
||||
+ std::vector<blink::mojom::FileChooserFileInfoPtr> files) {
|
||||
listener_impl_ = nullptr;
|
||||
if (!render_frame_host_) {
|
||||
std::move(callback_).Run(nullptr);
|
||||
diff --git a/content/browser/web_contents/file_chooser_impl.h b/content/browser/web_contents/file_chooser_impl.h
|
||||
index b9f11f9e6a0b548cb5ab8ca721ae823e079ce6fa..b628b29a5f84264e62bb3fa9e92550787b8342de 100644
|
||||
--- a/content/browser/web_contents/file_chooser_impl.h
|
||||
+++ b/content/browser/web_contents/file_chooser_impl.h
|
||||
@@ -37,6 +37,8 @@ class CONTENT_EXPORT FileChooserImpl : public blink::mojom::FileChooser,
|
||||
|
||||
// FileSelectListener overrides:
|
||||
|
||||
+ // TODO(xiaochengh): Move |file| to the end of the argument list to match
|
||||
+ // the argument ordering of FileChooserImpl::FileSelected().
|
||||
void FileSelected(std::vector<blink::mojom::FileChooserFileInfoPtr> files,
|
||||
const base::FilePath& base_dir,
|
||||
blink::mojom::FileChooserParams::Mode mode) override;
|
||||
@@ -68,9 +70,9 @@ class CONTENT_EXPORT FileChooserImpl : public blink::mojom::FileChooser,
|
||||
|
||||
~FileChooserImpl() override;
|
||||
|
||||
- void FileSelected(std::vector<blink::mojom::FileChooserFileInfoPtr> files,
|
||||
- const base::FilePath& base_dir,
|
||||
- blink::mojom::FileChooserParams::Mode mode);
|
||||
+ void FileSelected(const base::FilePath& base_dir,
|
||||
+ blink::mojom::FileChooserParams::Mode mode,
|
||||
+ std::vector<blink::mojom::FileChooserFileInfoPtr> files);
|
||||
|
||||
void FileSelectionCanceled();
|
||||
|
||||
@@ -82,6 +84,10 @@ class CONTENT_EXPORT FileChooserImpl : public blink::mojom::FileChooser,
|
||||
const base::FilePath& directory_path,
|
||||
EnumerateChosenDirectoryCallback callback) override;
|
||||
|
||||
+ base::WeakPtr<FileChooserImpl> GetWeakPtr() {
|
||||
+ return weak_factory_.GetWeakPtr();
|
||||
+ }
|
||||
+
|
||||
private:
|
||||
explicit FileChooserImpl(RenderFrameHostImpl* render_frame_host);
|
||||
|
||||
@@ -95,6 +101,8 @@ class CONTENT_EXPORT FileChooserImpl : public blink::mojom::FileChooser,
|
||||
raw_ptr<RenderFrameHostImpl> render_frame_host_;
|
||||
scoped_refptr<FileSelectListenerImpl> listener_impl_;
|
||||
base::OnceCallback<void(blink::mojom::FileChooserResultPtr)> callback_;
|
||||
+
|
||||
+ base::WeakPtrFactory<FileChooserImpl> weak_factory_{this};
|
||||
};
|
||||
|
||||
} // namespace content
|
||||
diff --git a/content/browser/web_contents/file_chooser_impl_browsertest.cc b/content/browser/web_contents/file_chooser_impl_browsertest.cc
|
||||
index 5aa120cd2e9fab1492f5d0993adbb2f80a4aa732..2acd2216331bd9be56eb9705f0e9c0d3bceb9e93 100644
|
||||
--- a/content/browser/web_contents/file_chooser_impl_browsertest.cc
|
||||
+++ b/content/browser/web_contents/file_chooser_impl_browsertest.cc
|
||||
@@ -5,14 +5,18 @@
|
||||
#include "content/browser/web_contents/file_chooser_impl.h"
|
||||
|
||||
#include "base/bind.h"
|
||||
+#include "base/files/file_util.h"
|
||||
+#include "base/path_service.h"
|
||||
#include "base/run_loop.h"
|
||||
#include "content/browser/renderer_host/render_frame_host_impl.h"
|
||||
#include "content/public/browser/web_contents_delegate.h"
|
||||
+#include "content/public/common/content_paths.h"
|
||||
#include "content/public/test/browser_test.h"
|
||||
#include "content/public/test/browser_test_utils.h"
|
||||
#include "content/public/test/content_browser_test.h"
|
||||
#include "content/public/test/content_browser_test_utils.h"
|
||||
#include "content/shell/browser/shell.h"
|
||||
+#include "content/test/content_browser_test_utils_internal.h"
|
||||
#include "url/gurl.h"
|
||||
#include "url/url_constants.h"
|
||||
|
||||
@@ -143,11 +147,52 @@ IN_PROC_BROWSER_TEST_F(FileChooserImplBrowserTest,
|
||||
->SetListenerFunctionCalledTrueForTesting();
|
||||
std::vector<blink::mojom::FileChooserFileInfoPtr> files;
|
||||
files.emplace_back(blink::mojom::FileChooserFileInfoPtr(nullptr));
|
||||
- chooser->FileSelected(std::move(files), base::FilePath(),
|
||||
- blink::mojom::FileChooserParams::Mode::kOpen);
|
||||
+ chooser->FileSelected(base::FilePath(),
|
||||
+ blink::mojom::FileChooserParams::Mode::kOpen,
|
||||
+ std::move(files));
|
||||
|
||||
// Test passes if this run_loop.Run() returns instead of timing out.
|
||||
run_loop.Run();
|
||||
}
|
||||
|
||||
+// https://crbug.com/1345275
|
||||
+IN_PROC_BROWSER_TEST_F(FileChooserImplBrowserTest, UploadFolderWithSymlink) {
|
||||
+ EXPECT_TRUE(NavigateToURL(
|
||||
+ shell(), GetTestUrl(".", "file_input_webkitdirectory.html")));
|
||||
+
|
||||
+ // The folder contains a regular file and a symbolic link.
|
||||
+ // When uploading the folder, the symbolic link should be excluded.
|
||||
+ base::FilePath dir_test_data;
|
||||
+ ASSERT_TRUE(base::PathService::Get(DIR_TEST_DATA, &dir_test_data));
|
||||
+ base::FilePath folder_to_upload =
|
||||
+ dir_test_data.AppendASCII("file_chooser").AppendASCII("dir_with_symlink");
|
||||
+
|
||||
+ base::FilePath text_file = folder_to_upload.AppendASCII("text_file.txt");
|
||||
+ base::FilePath symlink_file = folder_to_upload.AppendASCII("symlink");
|
||||
+
|
||||
+ // Skip the test if symbolic links are not supported.
|
||||
+ {
|
||||
+ base::ScopedAllowBlockingForTesting allow_blocking;
|
||||
+ if (!base::IsLink(symlink_file))
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
+ std::unique_ptr<FileChooserDelegate> delegate(
|
||||
+ new FileChooserDelegate({text_file, symlink_file}, base::OnceClosure()));
|
||||
+ shell()->web_contents()->SetDelegate(delegate.get());
|
||||
+ EXPECT_TRUE(ExecJs(shell(),
|
||||
+ "(async () => {"
|
||||
+ " let listener = new Promise("
|
||||
+ " resolve => fileinput.onchange = resolve);"
|
||||
+ " fileinput.click();"
|
||||
+ " await listener;"
|
||||
+ "})()"));
|
||||
+
|
||||
+ EXPECT_EQ(
|
||||
+ 1, EvalJs(shell(), "document.getElementById('fileinput').files.length;"));
|
||||
+ EXPECT_EQ(
|
||||
+ "text_file.txt",
|
||||
+ EvalJs(shell(), "document.getElementById('fileinput').files[0].name;"));
|
||||
+}
|
||||
+
|
||||
} // namespace content
|
||||
diff --git a/content/test/content_browser_test_utils_internal.cc b/content/test/content_browser_test_utils_internal.cc
|
||||
index 8183cb7e6547f42b27afc323fe136e2157e4dd03..dbdf244571956645c6494c4cdab514dd42dbb6c2 100644
|
||||
--- a/content/test/content_browser_test_utils_internal.cc
|
||||
+++ b/content/test/content_browser_test_utils_internal.cc
|
||||
@@ -447,9 +447,14 @@ Shell* OpenPopup(const ToRenderFrameHost& opener,
|
||||
return new_shell_observer.GetShell();
|
||||
}
|
||||
|
||||
+FileChooserDelegate::FileChooserDelegate(std::vector<base::FilePath> files,
|
||||
+ base::OnceClosure callback)
|
||||
+ : files_(std::move(files)), callback_(std::move(callback)) {}
|
||||
+
|
||||
FileChooserDelegate::FileChooserDelegate(const base::FilePath& file,
|
||||
base::OnceClosure callback)
|
||||
- : file_(file), callback_(std::move(callback)) {}
|
||||
+ : FileChooserDelegate(std::vector<base::FilePath>(1, file),
|
||||
+ std::move(callback)) {}
|
||||
|
||||
FileChooserDelegate::~FileChooserDelegate() = default;
|
||||
|
||||
@@ -457,16 +462,18 @@ void FileChooserDelegate::RunFileChooser(
|
||||
RenderFrameHost* render_frame_host,
|
||||
scoped_refptr<content::FileSelectListener> listener,
|
||||
const blink::mojom::FileChooserParams& params) {
|
||||
- // Send the selected file to the renderer process.
|
||||
- auto file_info = blink::mojom::FileChooserFileInfo::NewNativeFile(
|
||||
- blink::mojom::NativeFileInfo::New(file_, std::u16string()));
|
||||
+ // Send the selected files to the renderer process.
|
||||
std::vector<blink::mojom::FileChooserFileInfoPtr> files;
|
||||
- files.push_back(std::move(file_info));
|
||||
- listener->FileSelected(std::move(files), base::FilePath(),
|
||||
- blink::mojom::FileChooserParams::Mode::kOpen);
|
||||
+ for (const auto& file : files_) {
|
||||
+ auto file_info = blink::mojom::FileChooserFileInfo::NewNativeFile(
|
||||
+ blink::mojom::NativeFileInfo::New(file, std::u16string()));
|
||||
+ files.push_back(std::move(file_info));
|
||||
+ }
|
||||
+ listener->FileSelected(std::move(files), base::FilePath(), params.mode);
|
||||
|
||||
params_ = params.Clone();
|
||||
- std::move(callback_).Run();
|
||||
+ if (callback_)
|
||||
+ std::move(callback_).Run();
|
||||
}
|
||||
|
||||
FrameTestNavigationManager::FrameTestNavigationManager(
|
||||
diff --git a/content/test/content_browser_test_utils_internal.h b/content/test/content_browser_test_utils_internal.h
|
||||
index 6ae5e8f81a189702d5ed9bef003696f34c525dd3..3bf1bb93e15b0a5270262837802e140ad72a9231 100644
|
||||
--- a/content/test/content_browser_test_utils_internal.h
|
||||
+++ b/content/test/content_browser_test_utils_internal.h
|
||||
@@ -176,9 +176,11 @@ Shell* OpenPopup(const ToRenderFrameHost& opener,
|
||||
class FileChooserDelegate : public WebContentsDelegate {
|
||||
public:
|
||||
// Constructs a WebContentsDelegate that mocks a file dialog.
|
||||
- // The mocked file dialog will always reply that the user selected |file|.
|
||||
- // |callback| is invoked when RunFileChooser() is called.
|
||||
+ // The mocked file dialog will always reply that the user selected |file| or
|
||||
+ // |files|. |callback| is invoked when RunFileChooser() is called.
|
||||
FileChooserDelegate(const base::FilePath& file, base::OnceClosure callback);
|
||||
+ FileChooserDelegate(std::vector<base::FilePath> files,
|
||||
+ base::OnceClosure callback);
|
||||
~FileChooserDelegate() override;
|
||||
|
||||
// Implementation of WebContentsDelegate::RunFileChooser.
|
||||
@@ -190,7 +192,7 @@ class FileChooserDelegate : public WebContentsDelegate {
|
||||
const blink::mojom::FileChooserParams& params() const { return *params_; }
|
||||
|
||||
private:
|
||||
- base::FilePath file_;
|
||||
+ std::vector<base::FilePath> files_;
|
||||
base::OnceClosure callback_;
|
||||
blink::mojom::FileChooserParamsPtr params_;
|
||||
};
|
||||
diff --git a/content/test/data/file_chooser/dir_with_symlink/symlink b/content/test/data/file_chooser/dir_with_symlink/symlink
|
||||
new file mode 120000
|
||||
index 0000000000000000000000000000000000000000..7857c689f7043265b4e6d4dcdf6d40d0be2d3d60
|
||||
--- /dev/null
|
||||
+++ b/content/test/data/file_chooser/dir_with_symlink/symlink
|
||||
@@ -0,0 +1 @@
|
||||
+../linked_text_file.txt
|
||||
\ No newline at end of file
|
||||
diff --git a/content/test/data/file_chooser/dir_with_symlink/text_file.txt b/content/test/data/file_chooser/dir_with_symlink/text_file.txt
|
||||
new file mode 100644
|
||||
index 0000000000000000000000000000000000000000..8e27be7d6154a1f68ea9160ef0e18691d20560dc
|
||||
--- /dev/null
|
||||
+++ b/content/test/data/file_chooser/dir_with_symlink/text_file.txt
|
||||
@@ -0,0 +1 @@
|
||||
+text
|
||||
diff --git a/content/test/data/file_chooser/linked_text_file.txt b/content/test/data/file_chooser/linked_text_file.txt
|
||||
new file mode 100644
|
||||
index 0000000000000000000000000000000000000000..9a1f4bc60917c014eac1464ad664a0271c288b84
|
||||
--- /dev/null
|
||||
+++ b/content/test/data/file_chooser/linked_text_file.txt
|
||||
@@ -0,0 +1 @@
|
||||
+linked text file
|
||||
diff --git a/content/test/data/file_input_webkitdirectory.html b/content/test/data/file_input_webkitdirectory.html
|
||||
new file mode 100644
|
||||
index 0000000000000000000000000000000000000000..5b7bb501f7eb5d9f28751f36380e4ad01d2da0c7
|
||||
--- /dev/null
|
||||
+++ b/content/test/data/file_input_webkitdirectory.html
|
||||
@@ -0,0 +1 @@
|
||||
+<input type="file" id="fileinput" webkitdirectory />
|
||||
119
patches/chromium/cherry-pick-9b3d0e2f1aab.patch
Normal file
119
patches/chromium/cherry-pick-9b3d0e2f1aab.patch
Normal file
@@ -0,0 +1,119 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Corentin Wallez <cwallez@chromium.org>
|
||||
Date: Tue, 29 Nov 2022 14:07:46 +0000
|
||||
Subject: Keep a reference to the transfer buffer in Dawn read/write handles.
|
||||
|
||||
Previously the Dawn read/write handles in the GPU process only contained
|
||||
a pointer to the inside of a shmem region owned by a gpu::Buffer that
|
||||
had a different lifetime. This could allow a renderer process to
|
||||
deallocate the memory from underneath the handle which is bad.
|
||||
|
||||
Fix this by keepind a scoped_refptr to the gpu::Buffer inside the
|
||||
read/write handles to extend the lifetime of the shmem to be at least as
|
||||
big as the handle's.
|
||||
|
||||
Fixed: chromium:1393177
|
||||
Change-Id: I9d9c18d5155a46e0e3a01d385d221a6370bd2bea
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/4056276
|
||||
Reviewed-by: Austin Eng <enga@chromium.org>
|
||||
Commit-Queue: Corentin Wallez <cwallez@chromium.org>
|
||||
Cr-Commit-Position: refs/heads/main@{#1076828}
|
||||
|
||||
diff --git a/gpu/command_buffer/service/dawn_service_memory_transfer_service.cc b/gpu/command_buffer/service/dawn_service_memory_transfer_service.cc
|
||||
index a15b6f9b3b345079d8cf8251ca5f77b6e7ef647a..10941d9f65c66e50303cf7293180c29fced8ffe2 100644
|
||||
--- a/gpu/command_buffer/service/dawn_service_memory_transfer_service.cc
|
||||
+++ b/gpu/command_buffer/service/dawn_service_memory_transfer_service.cc
|
||||
@@ -6,6 +6,7 @@
|
||||
|
||||
#include "base/memory/raw_ptr.h"
|
||||
#include "gpu/command_buffer/common/dawn_memory_transfer_handle.h"
|
||||
+#include "gpu/command_buffer/service/command_buffer_service.h"
|
||||
#include "gpu/command_buffer/service/common_decoder.h"
|
||||
|
||||
namespace gpu {
|
||||
@@ -16,8 +17,8 @@ namespace {
|
||||
class ReadHandleImpl
|
||||
: public dawn::wire::server::MemoryTransferService::ReadHandle {
|
||||
public:
|
||||
- ReadHandleImpl(void* ptr, uint32_t size)
|
||||
- : ReadHandle(), ptr_(ptr), size_(size) {}
|
||||
+ ReadHandleImpl(scoped_refptr<Buffer> buffer, void* ptr, uint32_t size)
|
||||
+ : buffer_(std::move(buffer)), ptr_(ptr), size_(size) {}
|
||||
|
||||
~ReadHandleImpl() override = default;
|
||||
|
||||
@@ -44,6 +45,8 @@ class ReadHandleImpl
|
||||
}
|
||||
|
||||
private:
|
||||
+ scoped_refptr<gpu::Buffer> buffer_;
|
||||
+ // Pointer to client-visible shared memory owned by buffer_.
|
||||
raw_ptr<void> ptr_;
|
||||
uint32_t size_;
|
||||
};
|
||||
@@ -51,8 +54,8 @@ class ReadHandleImpl
|
||||
class WriteHandleImpl
|
||||
: public dawn::wire::server::MemoryTransferService::WriteHandle {
|
||||
public:
|
||||
- WriteHandleImpl(const void* ptr, uint32_t size)
|
||||
- : WriteHandle(), ptr_(ptr), size_(size) {}
|
||||
+ WriteHandleImpl(scoped_refptr<Buffer> buffer, const void* ptr, uint32_t size)
|
||||
+ : buffer_(std::move(buffer)), ptr_(ptr), size_(size) {}
|
||||
|
||||
~WriteHandleImpl() override = default;
|
||||
|
||||
@@ -82,7 +85,9 @@ class WriteHandleImpl
|
||||
}
|
||||
|
||||
private:
|
||||
- raw_ptr<const void> ptr_; // Pointer to client-visible shared memory.
|
||||
+ scoped_refptr<gpu::Buffer> buffer_;
|
||||
+ // Pointer to client-visible shared memory owned by buffer_.
|
||||
+ raw_ptr<const void> ptr_;
|
||||
uint32_t size_;
|
||||
};
|
||||
|
||||
@@ -111,13 +116,19 @@ bool DawnServiceMemoryTransferService::DeserializeReadHandle(
|
||||
int32_t shm_id = handle->shm_id;
|
||||
uint32_t shm_offset = handle->shm_offset;
|
||||
|
||||
- void* ptr = decoder_->GetAddressAndCheckSize(shm_id, shm_offset, size);
|
||||
+ scoped_refptr<gpu::Buffer> buffer =
|
||||
+ decoder_->command_buffer_service()->GetTransferBuffer(shm_id);
|
||||
+ if (buffer == nullptr) {
|
||||
+ return false;
|
||||
+ }
|
||||
+
|
||||
+ void* ptr = buffer->GetDataAddress(shm_offset, size);
|
||||
if (ptr == nullptr) {
|
||||
return false;
|
||||
}
|
||||
|
||||
DCHECK(read_handle);
|
||||
- *read_handle = new ReadHandleImpl(ptr, size);
|
||||
+ *read_handle = new ReadHandleImpl(std::move(buffer), ptr, size);
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -139,13 +150,19 @@ bool DawnServiceMemoryTransferService::DeserializeWriteHandle(
|
||||
int32_t shm_id = handle->shm_id;
|
||||
uint32_t shm_offset = handle->shm_offset;
|
||||
|
||||
- void* ptr = decoder_->GetAddressAndCheckSize(shm_id, shm_offset, size);
|
||||
+ scoped_refptr<gpu::Buffer> buffer =
|
||||
+ decoder_->command_buffer_service()->GetTransferBuffer(shm_id);
|
||||
+ if (buffer == nullptr) {
|
||||
+ return false;
|
||||
+ }
|
||||
+
|
||||
+ const void* ptr = buffer->GetDataAddress(shm_offset, size);
|
||||
if (ptr == nullptr) {
|
||||
return false;
|
||||
}
|
||||
|
||||
DCHECK(write_handle);
|
||||
- *write_handle = new WriteHandleImpl(ptr, size);
|
||||
+ *write_handle = new WriteHandleImpl(std::move(buffer), ptr, size);
|
||||
|
||||
return true;
|
||||
}
|
||||
122
patches/chromium/cherry-pick-c83640db21b5.patch
Normal file
122
patches/chromium/cherry-pick-c83640db21b5.patch
Normal file
@@ -0,0 +1,122 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Samuel Attard <samuel.r.attard@gmail.com>
|
||||
Date: Wed, 5 Oct 2022 06:03:23 +0000
|
||||
Subject: build: set DTSDKBuild correctly when generating plist files
|
||||
|
||||
Currently we set DTSDKBuild to the version of the SDK used to build
|
||||
Chromium. This value is supposed to be the build version (this is
|
||||
what xcode sets it to for instance). We read this value out of the
|
||||
SDK directly and use it instead.
|
||||
|
||||
Change-Id: Ieb7990f13095683ad8c026f027b2605ae39523a4
|
||||
|
||||
diff --git a/build/config/mac/mac_sdk.gni b/build/config/mac/mac_sdk.gni
|
||||
index 43577925d2ef9cd79970d8307104e0abc1756583..0819d4cc1b17f216eae8c1a562b0301ba6298d57 100644
|
||||
--- a/build/config/mac/mac_sdk.gni
|
||||
+++ b/build/config/mac/mac_sdk.gni
|
||||
@@ -40,6 +40,11 @@ declare_args() {
|
||||
# will fail.
|
||||
mac_sdk_official_version = "12.3"
|
||||
|
||||
+ # The SDK build version used when making official builds. This is a single
|
||||
+ # exact version found at "System/Library/CoreServices/SystemVersion.plist"
|
||||
+ # inside the SDK.
|
||||
+ mac_sdk_official_build_version = "21E226"
|
||||
+
|
||||
# Production builds should use hermetic Xcode. If you want to do production
|
||||
# builds with system Xcode to test new SDKs, set this.
|
||||
# Don't set this on any bots.
|
||||
@@ -103,11 +108,13 @@ if (use_system_xcode) {
|
||||
find_sdk_args = [
|
||||
"--print_sdk_path",
|
||||
"--print_bin_path",
|
||||
+ "--print_sdk_build",
|
||||
mac_sdk_min,
|
||||
]
|
||||
find_sdk_lines =
|
||||
exec_script("//build/mac/find_sdk.py", find_sdk_args, "list lines")
|
||||
- mac_sdk_version = find_sdk_lines[2]
|
||||
+ mac_sdk_version = find_sdk_lines[3]
|
||||
+ mac_sdk_build_version = find_sdk_lines[2]
|
||||
if (mac_sdk_path == "") {
|
||||
mac_sdk_path = find_sdk_lines[0]
|
||||
mac_bin_path = find_sdk_lines[1]
|
||||
@@ -116,6 +123,7 @@ if (use_system_xcode) {
|
||||
}
|
||||
} else {
|
||||
mac_sdk_version = mac_sdk_official_version
|
||||
+ mac_sdk_build_version = mac_sdk_official_build_version
|
||||
_dev = _hermetic_xcode_path + "/Contents/Developer"
|
||||
_sdk = "MacOSX${mac_sdk_version}.sdk"
|
||||
mac_sdk_path = _dev + "/Platforms/MacOSX.platform/Developer/SDKs/$_sdk"
|
||||
diff --git a/build/config/mac/rules.gni b/build/config/mac/rules.gni
|
||||
index 03073f830401c4891376a3b59e2e7a870e3d34b7..04d403054c1a83fcbbc70be7cfd239ecbec315d3 100644
|
||||
--- a/build/config/mac/rules.gni
|
||||
+++ b/build/config/mac/rules.gni
|
||||
@@ -41,7 +41,7 @@ template("mac_info_plist") {
|
||||
apple_info_plist(target_name) {
|
||||
format = "xml1"
|
||||
extra_substitutions = [
|
||||
- "MAC_SDK_BUILD=$mac_sdk_version",
|
||||
+ "MAC_SDK_BUILD=$mac_sdk_build_version",
|
||||
"MAC_SDK_NAME=$mac_sdk_name$mac_sdk_version",
|
||||
"MACOSX_DEPLOYMENT_TARGET=$mac_deployment_target",
|
||||
"CHROMIUM_MIN_SYSTEM_VERSION=$mac_min_system_version",
|
||||
diff --git a/build/mac/find_sdk.py b/build/mac/find_sdk.py
|
||||
index d86f3109357a9246d570cb02992dc82552ba7c20..b2400c7e8c70957e364444f509880900ce3b641f 100755
|
||||
--- a/build/mac/find_sdk.py
|
||||
+++ b/build/mac/find_sdk.py
|
||||
@@ -24,6 +24,7 @@ Sample Output:
|
||||
from __future__ import print_function
|
||||
|
||||
import os
|
||||
+import plistlib
|
||||
import re
|
||||
import subprocess
|
||||
import sys
|
||||
@@ -51,6 +52,9 @@ def main():
|
||||
parser.add_option("--print_bin_path",
|
||||
action="store_true", dest="print_bin_path", default=False,
|
||||
help="Additionally print the path the toolchain bin dir.")
|
||||
+ parser.add_option("--print_sdk_build",
|
||||
+ action="store_true", dest="print_sdk_build", default=False,
|
||||
+ help="Additionally print the build version of the SDK.")
|
||||
options, args = parser.parse_args()
|
||||
if len(args) != 1:
|
||||
parser.error('Please specify a minimum SDK version')
|
||||
@@ -80,20 +84,30 @@ def main():
|
||||
if not sdks:
|
||||
raise Exception('No %s+ SDK found' % min_sdk_version)
|
||||
best_sdk = sorted(sdks, key=parse_version)[0]
|
||||
+ sdk_name = 'MacOSX' + best_sdk + '.sdk'
|
||||
+ sdk_path = os.path.join(sdk_dir, sdk_name)
|
||||
|
||||
if options.print_sdk_path:
|
||||
- sdk_name = 'MacOSX' + best_sdk + '.sdk'
|
||||
- print(os.path.join(sdk_dir, sdk_name))
|
||||
+ print(sdk_path)
|
||||
|
||||
if options.print_bin_path:
|
||||
bin_path = 'Toolchains/XcodeDefault.xctoolchain/usr/bin/'
|
||||
print(os.path.join(dev_dir, bin_path))
|
||||
|
||||
- return best_sdk
|
||||
+ if options.print_sdk_build:
|
||||
+ system_version_plist = os.path.join(sdk_path,
|
||||
+ 'System/Library/CoreServices/SystemVersion.plist')
|
||||
+ with open(system_version_plist, 'rb') as f:
|
||||
+ system_version_info = plistlib.load(f)
|
||||
+ if 'ProductBuildVersion' not in system_version_info:
|
||||
+ raise Exception('Failed to determine ProductBuildVersion' +
|
||||
+ 'for SDK at path %s' % system_version_plist)
|
||||
+ print(system_version_info['ProductBuildVersion'])
|
||||
+
|
||||
+ print(best_sdk)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
if sys.platform != 'darwin':
|
||||
raise Exception("This script only runs on Mac")
|
||||
- print(main())
|
||||
- sys.exit(0)
|
||||
+ sys.exit(main())
|
||||
116
patches/chromium/cherry-pick-ca2b108a0f1f.patch
Normal file
116
patches/chromium/cherry-pick-ca2b108a0f1f.patch
Normal file
@@ -0,0 +1,116 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Harald Alvestrand <hta@chromium.org>
|
||||
Date: Wed, 18 Jan 2023 08:02:48 +0000
|
||||
Subject: Delete PeerConnectionHandler in PeerConnection finalizer
|
||||
|
||||
Also guard against removal of PC during PeerConnectionHandler
|
||||
call that may cause garbage collection.
|
||||
|
||||
(cherry picked from commit 5066dd66309d884762e5fb9be04b59582893d09a)
|
||||
|
||||
Bug: chromium:1405256
|
||||
Change-Id: I9adf7b219e2026e07ccc0868c1a85f3b35cd9d26
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/4154578
|
||||
Commit-Queue: Harald Alvestrand <hta@chromium.org>
|
||||
Reviewed-by: Guido Urdaneta <guidou@chromium.org>
|
||||
Commit-Queue: Guido Urdaneta <guidou@chromium.org>
|
||||
Cr-Original-Commit-Position: refs/heads/main@{#1091801}
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/4176372
|
||||
Auto-Submit: Harald Alvestrand <hta@chromium.org>
|
||||
Cr-Commit-Position: refs/branch-heads/5481@{#418}
|
||||
Cr-Branched-From: 130f3e4d850f4bc7387cfb8d08aa993d288a67a9-refs/heads/main@{#1084008}
|
||||
|
||||
diff --git a/third_party/blink/renderer/modules/peerconnection/rtc_peer_connection.cc b/third_party/blink/renderer/modules/peerconnection/rtc_peer_connection.cc
|
||||
index 6da9e3f038869f204074aabfd8ec8a0dbc659ab6..ec4b8985b5fb072ea98f4c36a3d0b341000d96ad 100644
|
||||
--- a/third_party/blink/renderer/modules/peerconnection/rtc_peer_connection.cc
|
||||
+++ b/third_party/blink/renderer/modules/peerconnection/rtc_peer_connection.cc
|
||||
@@ -741,10 +741,11 @@ RTCPeerConnection::~RTCPeerConnection() {
|
||||
}
|
||||
|
||||
void RTCPeerConnection::Dispose() {
|
||||
- // Promptly clears the handler's pointer to |this|
|
||||
+ // Promptly clears the handler
|
||||
// so that content/ doesn't access it in a lazy sweeping phase.
|
||||
+ // Other references to the handler use a weak pointer, preventing access.
|
||||
if (peer_handler_) {
|
||||
- peer_handler_->CloseAndUnregister();
|
||||
+ peer_handler_.reset();
|
||||
}
|
||||
}
|
||||
|
||||
diff --git a/third_party/blink/renderer/modules/peerconnection/rtc_peer_connection_handler.cc b/third_party/blink/renderer/modules/peerconnection/rtc_peer_connection_handler.cc
|
||||
index 8166a6fa6c9aff9d724200cbbfac189d3f887735..ee694f5820b4947dc5815a5dd2f41ecfd1c9cb4c 100644
|
||||
--- a/third_party/blink/renderer/modules/peerconnection/rtc_peer_connection_handler.cc
|
||||
+++ b/third_party/blink/renderer/modules/peerconnection/rtc_peer_connection_handler.cc
|
||||
@@ -806,6 +806,8 @@ class RTCPeerConnectionHandler::WebRtcSetDescriptionObserverImpl
|
||||
if (handler_) {
|
||||
handler_->OnModifySctpTransport(std::move(states.sctp_transport_state));
|
||||
}
|
||||
+ // Since OnSessionDescriptionsUpdated can fire events, it may cause
|
||||
+ // garbage collection. Ensure that handler_ is still valid.
|
||||
if (handler_) {
|
||||
handler_->OnModifyTransceivers(
|
||||
states.signaling_state, std::move(states.transceiver_states),
|
||||
@@ -1160,6 +1162,8 @@ bool RTCPeerConnectionHandler::Initialize(
|
||||
CHECK(!initialize_called_);
|
||||
initialize_called_ = true;
|
||||
|
||||
+ // Prevent garbage collection of client_ during processing.
|
||||
+ auto* client_on_stack = client_;
|
||||
peer_connection_tracker_ = PeerConnectionTracker::From(*frame);
|
||||
|
||||
configuration_ = server_configuration;
|
||||
@@ -1198,8 +1202,8 @@ bool RTCPeerConnectionHandler::Initialize(
|
||||
peer_connection_tracker_->RegisterPeerConnection(this, configuration_,
|
||||
frame_);
|
||||
}
|
||||
-
|
||||
- return true;
|
||||
+ // Gratuitous usage of client_on_stack to prevent compiler errors.
|
||||
+ return !!client_on_stack;
|
||||
}
|
||||
|
||||
bool RTCPeerConnectionHandler::InitializeForTest(
|
||||
@@ -2259,9 +2263,11 @@ void RTCPeerConnectionHandler::OnSessionDescriptionsUpdated(
|
||||
pending_remote_description,
|
||||
std::unique_ptr<webrtc::SessionDescriptionInterface>
|
||||
current_remote_description) {
|
||||
+ // Prevent garbage collection of client_ during processing.
|
||||
+ auto* client_on_stack = client_;
|
||||
if (!client_ || is_closed_)
|
||||
return;
|
||||
- client_->DidChangeSessionDescriptions(
|
||||
+ client_on_stack->DidChangeSessionDescriptions(
|
||||
pending_local_description
|
||||
? CreateWebKitSessionDescription(pending_local_description.get())
|
||||
: nullptr,
|
||||
@@ -2573,8 +2579,12 @@ void RTCPeerConnectionHandler::OnIceCandidate(const String& sdp,
|
||||
int sdp_mline_index,
|
||||
int component,
|
||||
int address_family) {
|
||||
+ // In order to ensure that the RTCPeerConnection is not garbage collected
|
||||
+ // from under the function, we keep a pointer to it on the stack.
|
||||
+ auto* client_on_stack = client_;
|
||||
DCHECK(task_runner_->RunsTasksInCurrentSequence());
|
||||
TRACE_EVENT0("webrtc", "RTCPeerConnectionHandler::OnIceCandidateImpl");
|
||||
+ // This line can cause garbage collection.
|
||||
auto* platform_candidate = MakeGarbageCollected<RTCIceCandidatePlatform>(
|
||||
sdp, sdp_mid, sdp_mline_index);
|
||||
if (peer_connection_tracker_) {
|
||||
@@ -2594,7 +2604,7 @@ void RTCPeerConnectionHandler::OnIceCandidate(const String& sdp,
|
||||
}
|
||||
}
|
||||
if (!is_closed_)
|
||||
- client_->DidGenerateICECandidate(platform_candidate);
|
||||
+ client_on_stack->DidGenerateICECandidate(platform_candidate);
|
||||
}
|
||||
|
||||
void RTCPeerConnectionHandler::OnIceCandidateError(
|
||||
@@ -2606,7 +2616,6 @@ void RTCPeerConnectionHandler::OnIceCandidateError(
|
||||
const String& error_text) {
|
||||
DCHECK(task_runner_->RunsTasksInCurrentSequence());
|
||||
TRACE_EVENT0("webrtc", "RTCPeerConnectionHandler::OnIceCandidateError");
|
||||
-
|
||||
if (peer_connection_tracker_) {
|
||||
peer_connection_tracker_->TrackIceCandidateError(
|
||||
this, address, port, host_candidate, url, error_code, error_text);
|
||||
38
patches/chromium/cherry-pick-d1d654d73222.patch
Normal file
38
patches/chromium/cherry-pick-d1d654d73222.patch
Normal file
@@ -0,0 +1,38 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Ken Rockot <rockot@google.com>
|
||||
Date: Wed, 7 Dec 2022 20:35:15 +0000
|
||||
Subject: Mojo: Fix potential UAF in IPC Channel
|
||||
|
||||
(cherry picked from commit 120b4b05ac7eaa9024f677394aa663c2702174ce)
|
||||
|
||||
Fixed: 1394692
|
||||
Change-Id: I1753b79eb6e9230ebb663eca47295d81dd859068
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/4066994
|
||||
Commit-Queue: Ken Rockot <rockot@google.com>
|
||||
Reviewed-by: Daniel Cheng <dcheng@chromium.org>
|
||||
Cr-Original-Commit-Position: refs/heads/main@{#1077742}
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/4085806
|
||||
Commit-Queue: Rubber Stamper <rubber-stamper@appspot.gserviceaccount.com>
|
||||
Auto-Submit: Ken Rockot <rockot@google.com>
|
||||
Bot-Commit: Rubber Stamper <rubber-stamper@appspot.gserviceaccount.com>
|
||||
Cr-Commit-Position: refs/branch-heads/5359@{#1115}
|
||||
Cr-Branched-From: 27d3765d341b09369006d030f83f582a29eb57ae-refs/heads/main@{#1058933}
|
||||
|
||||
diff --git a/ipc/ipc_mojo_bootstrap.cc b/ipc/ipc_mojo_bootstrap.cc
|
||||
index a0bd86951a20cf2d60c7805a3a7fa687d66ca329..eb8fa358b0a72eea2e294c531549da5fc81f394c 100644
|
||||
--- a/ipc/ipc_mojo_bootstrap.cc
|
||||
+++ b/ipc/ipc_mojo_bootstrap.cc
|
||||
@@ -629,9 +629,12 @@ class ChannelAssociatedGroupController
|
||||
void OnSyncMessageEventReady() {
|
||||
DCHECK(task_runner_->RunsTasksInCurrentSequence());
|
||||
|
||||
- scoped_refptr<Endpoint> keepalive(this);
|
||||
+ // SUBTLE: The order of these scoped_refptrs matters.
|
||||
+ // `controller_keepalive` MUST outlive `keepalive` because the Endpoint
|
||||
+ // holds raw pointer to the AssociatedGroupController.
|
||||
scoped_refptr<AssociatedGroupController> controller_keepalive(
|
||||
controller_.get());
|
||||
+ scoped_refptr<Endpoint> keepalive(this);
|
||||
base::AutoLock locker(controller_->lock_);
|
||||
bool more_to_process = false;
|
||||
if (!sync_messages_.empty()) {
|
||||
31
patches/chromium/cherry-pick-d652130c4bc2.patch
Normal file
31
patches/chromium/cherry-pick-d652130c4bc2.patch
Normal file
@@ -0,0 +1,31 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Vasiliy Telezhnikov <vasilyt@chromium.org>
|
||||
Date: Mon, 16 Jan 2023 17:43:34 +0000
|
||||
Subject: Remove NUM_COMMAND_BUFFER_NAMESPACES from SyncToken.mojom
|
||||
|
||||
Mojo validates input for allowed values, NUM_COMMAND_BUFFER_NAMESPACES
|
||||
is not valid value to send over ipc and is used only to know maximum
|
||||
value in code.
|
||||
|
||||
Bug: 1406115
|
||||
Change-Id: I8e5c3b6b2a9a9206fbeb377b27ceb1242a4f54e2
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/4167409
|
||||
Reviewed-by: danakj <danakj@chromium.org>
|
||||
Commit-Queue: Vasiliy Telezhnikov <vasilyt@chromium.org>
|
||||
Cr-Commit-Position: refs/heads/main@{#1093100}
|
||||
|
||||
diff --git a/gpu/ipc/common/sync_token.mojom b/gpu/ipc/common/sync_token.mojom
|
||||
index 7c957007e3a377bd1e9969f14d9edc80c7d76645..b24017647aa6a11080580dd48e4c3d1cd79d1cf3 100644
|
||||
--- a/gpu/ipc/common/sync_token.mojom
|
||||
+++ b/gpu/ipc/common/sync_token.mojom
|
||||
@@ -11,9 +11,7 @@ enum CommandBufferNamespace {
|
||||
GPU_IO,
|
||||
IN_PROCESS,
|
||||
MOJO,
|
||||
- MOJO_LOCAL,
|
||||
-
|
||||
- NUM_COMMAND_BUFFER_NAMESPACES
|
||||
+ MOJO_LOCAL
|
||||
};
|
||||
|
||||
// See gpu/command_buffer/common/sync_token.h
|
||||
58
patches/chromium/cherry-pick-e79b89b47dac.patch
Normal file
58
patches/chromium/cherry-pick-e79b89b47dac.patch
Normal file
@@ -0,0 +1,58 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Vasiliy Telezhnikov <vasilyt@chromium.org>
|
||||
Date: Fri, 10 Feb 2023 17:36:57 +0000
|
||||
Subject: CHECK that YUV readback finished synchronously
|
||||
|
||||
DoReadbackYUVImagePixelsINTERNAL is implemented using skia asynchronous
|
||||
readback and to make it synchronous we use sync cpu and gpu. In some
|
||||
edge cases on linux we saw that doesn't happen if readback triggered
|
||||
vulkan device lost.
|
||||
|
||||
To avoid use after free, CHECK that callback was actually called. In
|
||||
case of device-lost gpu process will restart anyway, so while this is
|
||||
not proper fix of the problem, it doesn't result in worse user visible
|
||||
behaviour.
|
||||
|
||||
(cherry picked from commit 081df1e7d3712131bcaa575bda2e37ec7f6aa83d)
|
||||
|
||||
Bug: 1399742
|
||||
Change-Id: Ie2172539bb907b9696ef62c70d398aca3967177c
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/4143606
|
||||
Reviewed-by: Peng Huang <penghuang@chromium.org>
|
||||
Commit-Queue: Vasiliy Telezhnikov <vasilyt@chromium.org>
|
||||
Cr-Original-Commit-Position: refs/heads/main@{#1093064}
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/4239960
|
||||
Cr-Commit-Position: refs/branch-heads/5481@{#1084}
|
||||
Cr-Branched-From: 130f3e4d850f4bc7387cfb8d08aa993d288a67a9-refs/heads/main@{#1084008}
|
||||
|
||||
diff --git a/gpu/command_buffer/service/raster_decoder.cc b/gpu/command_buffer/service/raster_decoder.cc
|
||||
index 23260eb92a8f09159dadb1167d8f2a90a6fd21c6..ecfbf5d92a8aa738aea5d26af82d3c1d2e7c04be 100644
|
||||
--- a/gpu/command_buffer/service/raster_decoder.cc
|
||||
+++ b/gpu/command_buffer/service/raster_decoder.cc
|
||||
@@ -2680,6 +2680,7 @@ void RasterDecoderImpl::DoReadbackARGBImagePixelsINTERNAL(
|
||||
namespace {
|
||||
struct YUVReadbackResult {
|
||||
std::unique_ptr<const SkImage::AsyncReadResult> async_result;
|
||||
+ bool finished = false;
|
||||
};
|
||||
|
||||
void OnReadYUVImagePixelsDone(
|
||||
@@ -2687,6 +2688,7 @@ void OnReadYUVImagePixelsDone(
|
||||
std::unique_ptr<const SkImage::AsyncReadResult> async_result) {
|
||||
YUVReadbackResult* context = reinterpret_cast<YUVReadbackResult*>(raw_ctx);
|
||||
context->async_result = std::move(async_result);
|
||||
+ context->finished = true;
|
||||
}
|
||||
} // namespace
|
||||
|
||||
@@ -2884,6 +2886,10 @@ void RasterDecoderImpl::DoReadbackYUVImagePixelsINTERNAL(
|
||||
// asynchronous by removing this flush and implementing a query that can
|
||||
// signal back to client process.
|
||||
gr_context()->flushAndSubmit(true);
|
||||
+
|
||||
+ // The call above will sync up gpu and CPU, resulting in callback being run
|
||||
+ // during flushAndSubmit. To prevent UAF make sure it indeed happened.
|
||||
+ CHECK(yuv_result.finished);
|
||||
if (!yuv_result.async_result) {
|
||||
LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, "glReadbackYUVImagePixels",
|
||||
"Failed to read pixels from SkImage");
|
||||
132
patches/chromium/cherry-pick-eed5a4de2c40.patch
Normal file
132
patches/chromium/cherry-pick-eed5a4de2c40.patch
Normal file
@@ -0,0 +1,132 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: David Yeung <dayeung@chromium.org>
|
||||
Date: Thu, 8 Dec 2022 17:56:44 +0000
|
||||
Subject: Fix UaF in ui::DropTargetEvent::DropTargetEvent.
|
||||
|
||||
There is an async operation in WebContentsViewAura that uses a ui::DropTargetEvent. DropTargetEvent has a pointer to OSExchangeData which gets destroyed before the async operation is called. This triggers the UaF because the operation attempts to reference a freed object (OSExchangeData).
|
||||
|
||||
Fix is for WebContentsViewAura::DragUpdatedCallback to use a DropMetadata struct instead of a ui::DropTargetEvent. This is the same pattern used by other callbacks in WebContentsViewAura.
|
||||
|
||||
(cherry picked from commit 9f4b5761c546a118b7187c0c7ddcb9ee5756f32c)
|
||||
|
||||
Bug: 1392661
|
||||
Change-Id: I3c62a7473ef9b6cdd223f75fbda50671f539f9eb
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/4070787
|
||||
Reviewed-by: Avi Drissman <avi@chromium.org>
|
||||
Commit-Queue: David Yeung <dayeung@chromium.org>
|
||||
Cr-Original-Commit-Position: refs/heads/main@{#1078218}
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/4085256
|
||||
Cr-Commit-Position: refs/branch-heads/5359@{#1125}
|
||||
Cr-Branched-From: 27d3765d341b09369006d030f83f582a29eb57ae-refs/heads/main@{#1058933}
|
||||
|
||||
diff --git a/content/browser/web_contents/web_contents_view_aura.cc b/content/browser/web_contents/web_contents_view_aura.cc
|
||||
index 351bee9cfcc31dc6ca06f1fc502b70617105191a..d98e590beccfb19730528d598e32df4b4d00942b 100644
|
||||
--- a/content/browser/web_contents/web_contents_view_aura.cc
|
||||
+++ b/content/browser/web_contents/web_contents_view_aura.cc
|
||||
@@ -365,6 +365,7 @@ aura::Window* GetHostWindow(aura::Window* window) {
|
||||
WebContentsViewAura::DropMetadata::DropMetadata(
|
||||
const ui::DropTargetEvent& event) {
|
||||
localized_location = event.location_f();
|
||||
+ root_location = event.root_location_f();
|
||||
source_operations = event.source_operations();
|
||||
flags = event.flags();
|
||||
}
|
||||
@@ -1461,7 +1462,7 @@ void WebContentsViewAura::OnDragEntered(const ui::DropTargetEvent& event) {
|
||||
}
|
||||
|
||||
void WebContentsViewAura::DragUpdatedCallback(
|
||||
- ui::DropTargetEvent event,
|
||||
+ DropMetadata drop_metadata,
|
||||
std::unique_ptr<DropData> drop_data,
|
||||
base::WeakPtr<RenderWidgetHostViewBase> target,
|
||||
absl::optional<gfx::PointF> transformed_pt) {
|
||||
@@ -1482,24 +1483,23 @@ void WebContentsViewAura::DragUpdatedCallback(
|
||||
aura::Window* root_window = GetNativeView()->GetRootWindow();
|
||||
aura::client::ScreenPositionClient* screen_position_client =
|
||||
aura::client::GetScreenPositionClient(root_window);
|
||||
- gfx::PointF screen_pt = event.root_location_f();
|
||||
+ gfx::PointF screen_pt = drop_metadata.root_location;
|
||||
if (screen_position_client)
|
||||
screen_position_client->ConvertPointToScreen(root_window, &screen_pt);
|
||||
|
||||
if (target_rwh != current_rwh_for_drag_.get()) {
|
||||
if (current_rwh_for_drag_) {
|
||||
- gfx::PointF transformed_leave_point = event.location_f();
|
||||
+ gfx::PointF transformed_leave_point = drop_metadata.localized_location;
|
||||
static_cast<RenderWidgetHostViewBase*>(
|
||||
web_contents_->GetRenderWidgetHostView())
|
||||
->TransformPointToCoordSpaceForView(
|
||||
- event.location_f(),
|
||||
+ drop_metadata.localized_location,
|
||||
static_cast<RenderWidgetHostViewBase*>(
|
||||
current_rwh_for_drag_->GetView()),
|
||||
&transformed_leave_point);
|
||||
current_rwh_for_drag_->DragTargetDragLeave(transformed_leave_point,
|
||||
screen_pt);
|
||||
}
|
||||
- DropMetadata drop_metadata(event);
|
||||
DragEnteredCallback(drop_metadata, std::move(drop_data), target,
|
||||
transformed_pt);
|
||||
}
|
||||
@@ -1510,10 +1510,11 @@ void WebContentsViewAura::DragUpdatedCallback(
|
||||
|
||||
DCHECK(transformed_pt.has_value());
|
||||
blink::DragOperationsMask op_mask =
|
||||
- ConvertToDragOperationsMask(event.source_operations());
|
||||
+ ConvertToDragOperationsMask(drop_metadata.source_operations);
|
||||
target_rwh->DragTargetDragOver(
|
||||
transformed_pt.value(), screen_pt, op_mask,
|
||||
- ui::EventFlagsToWebEventModifiers(event.flags()), base::DoNothing());
|
||||
+ ui::EventFlagsToWebEventModifiers(drop_metadata.flags),
|
||||
+ base::DoNothing());
|
||||
|
||||
if (drag_dest_delegate_)
|
||||
drag_dest_delegate_->OnDragOver();
|
||||
@@ -1523,7 +1524,6 @@ aura::client::DragUpdateInfo WebContentsViewAura::OnDragUpdated(
|
||||
const ui::DropTargetEvent& event) {
|
||||
if (web_contents_->ShouldIgnoreInputEvents())
|
||||
return aura::client::DragUpdateInfo();
|
||||
-
|
||||
aura::client::DragUpdateInfo drag_info;
|
||||
auto* focused_frame = web_contents_->GetFocusedFrame();
|
||||
if (focused_frame && !web_contents_->GetBrowserContext()->IsOffTheRecord()) {
|
||||
@@ -1534,13 +1534,13 @@ aura::client::DragUpdateInfo WebContentsViewAura::OnDragUpdated(
|
||||
std::unique_ptr<DropData> drop_data = std::make_unique<DropData>();
|
||||
// Calling this here as event.data might become invalid inside the callback.
|
||||
PrepareDropData(drop_data.get(), event.data());
|
||||
-
|
||||
+ DropMetadata drop_metadata(event);
|
||||
web_contents_->GetInputEventRouter()
|
||||
->GetRenderWidgetHostAtPointAsynchronously(
|
||||
web_contents_->GetRenderViewHost()->GetWidget()->GetView(),
|
||||
event.location_f(),
|
||||
base::BindOnce(&WebContentsViewAura::DragUpdatedCallback,
|
||||
- weak_ptr_factory_.GetWeakPtr(), event,
|
||||
+ weak_ptr_factory_.GetWeakPtr(), drop_metadata,
|
||||
std::move(drop_data)));
|
||||
|
||||
drag_info.drag_operation = static_cast<int>(current_drag_op_);
|
||||
diff --git a/content/browser/web_contents/web_contents_view_aura.h b/content/browser/web_contents/web_contents_view_aura.h
|
||||
index 17745664eda9832da61ec0150fe5085776c9c7bc..aaa42c930ef04d8f0d20d65fbb22d5fd06ba2d48 100644
|
||||
--- a/content/browser/web_contents/web_contents_view_aura.h
|
||||
+++ b/content/browser/web_contents/web_contents_view_aura.h
|
||||
@@ -84,6 +84,10 @@ class CONTENT_EXPORT WebContentsViewAura
|
||||
|
||||
// Location local to WebContentsViewAura.
|
||||
gfx::PointF localized_location;
|
||||
+
|
||||
+ // Root location of the drop target event.
|
||||
+ gfx::PointF root_location;
|
||||
+
|
||||
// The supported DnD operation of the source. A bitmask of
|
||||
// ui::mojom::DragOperations.
|
||||
int source_operations;
|
||||
@@ -263,7 +267,7 @@ class CONTENT_EXPORT WebContentsViewAura
|
||||
std::unique_ptr<DropData> drop_data,
|
||||
base::WeakPtr<RenderWidgetHostViewBase> target,
|
||||
absl::optional<gfx::PointF> transformed_pt);
|
||||
- void DragUpdatedCallback(ui::DropTargetEvent event,
|
||||
+ void DragUpdatedCallback(DropMetadata drop_metadata,
|
||||
std::unique_ptr<DropData> drop_data,
|
||||
base::WeakPtr<RenderWidgetHostViewBase> target,
|
||||
absl::optional<gfx::PointF> transformed_pt);
|
||||
218
patches/chromium/cherry-pick-f46db6aac3e9.patch
Normal file
218
patches/chromium/cherry-pick-f46db6aac3e9.patch
Normal file
@@ -0,0 +1,218 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Xiaocheng Hu <xiaochengh@chromium.org>
|
||||
Date: Mon, 14 Nov 2022 20:01:38 +0000
|
||||
Subject: Do not traverse directory symlinks when uploading folder
|
||||
|
||||
Previous patch crrev.com/c/3866767 removed symlink files when uploading
|
||||
a folder. However, while the remaining files are themselves not
|
||||
symlinks, they may be included as the result of traversing directory
|
||||
symlink.
|
||||
|
||||
This patch further excludes such files by checking if any parent
|
||||
directory is a symlink, all the way until the base directory (which is
|
||||
the directory chosen for upload).
|
||||
|
||||
(cherry picked from commit 4fa830d8af6b2fb293219edeb39eebccfd322305)
|
||||
|
||||
Fixed: 1378997
|
||||
Change-Id: I75a92df4cd50f9aba7824955a3de792583bc6154
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3997720
|
||||
Reviewed-by: Austin Sullivan <asully@chromium.org>
|
||||
Reviewed-by: Mason Freed <masonf@chromium.org>
|
||||
Reviewed-by: Alex Moshchuk <alexmos@chromium.org>
|
||||
Commit-Queue: Xiaocheng Hu <xiaochengh@chromium.org>
|
||||
Cr-Original-Commit-Position: refs/heads/main@{#1067310}
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/4025427
|
||||
Bot-Commit: Rubber Stamper <rubber-stamper@appspot.gserviceaccount.com>
|
||||
Commit-Queue: Srinivas Sista <srinivassista@chromium.org>
|
||||
Owners-Override: Srinivas Sista <srinivassista@chromium.org>
|
||||
Cr-Commit-Position: refs/branch-heads/5359@{#823}
|
||||
Cr-Branched-From: 27d3765d341b09369006d030f83f582a29eb57ae-refs/heads/main@{#1058933}
|
||||
|
||||
diff --git a/content/browser/web_contents/file_chooser_impl.cc b/content/browser/web_contents/file_chooser_impl.cc
|
||||
index 1aa19f7a735b444f2c33d5084edcdd14e3c2f5c5..f4fa1afda64bf0606d28d4accaec56e2624133db 100644
|
||||
--- a/content/browser/web_contents/file_chooser_impl.cc
|
||||
+++ b/content/browser/web_contents/file_chooser_impl.cc
|
||||
@@ -23,10 +23,24 @@ namespace content {
|
||||
|
||||
namespace {
|
||||
|
||||
+// Removes any file that is a symlink or is inside a directory symlink.
|
||||
+// For |kUploadFolder| mode only. |base_dir| is the folder being uploaded.
|
||||
std::vector<blink::mojom::FileChooserFileInfoPtr> RemoveSymlinks(
|
||||
- std::vector<blink::mojom::FileChooserFileInfoPtr> files) {
|
||||
+ std::vector<blink::mojom::FileChooserFileInfoPtr> files,
|
||||
+ base::FilePath base_dir) {
|
||||
+ DCHECK(!base_dir.empty());
|
||||
auto new_end = base::ranges::remove_if(
|
||||
- files, &base::IsLink,
|
||||
+ files,
|
||||
+ [&base_dir](const base::FilePath& file_path) {
|
||||
+ if (base::IsLink(file_path))
|
||||
+ return true;
|
||||
+ for (base::FilePath path = file_path.DirName(); base_dir.IsParent(path);
|
||||
+ path = path.DirName()) {
|
||||
+ if (base::IsLink(path))
|
||||
+ return true;
|
||||
+ }
|
||||
+ return false;
|
||||
+ },
|
||||
[](const auto& file) { return file->get_native_file()->file_path; });
|
||||
files.erase(new_end, files.end());
|
||||
return files;
|
||||
@@ -78,7 +92,7 @@ void FileChooserImpl::FileSelectListenerImpl::FileSelected(
|
||||
base::ThreadPool::PostTaskAndReplyWithResult(
|
||||
FROM_HERE,
|
||||
{base::MayBlock(), base::TaskShutdownBehavior::CONTINUE_ON_SHUTDOWN},
|
||||
- base::BindOnce(&RemoveSymlinks, std::move(files)),
|
||||
+ base::BindOnce(&RemoveSymlinks, std::move(files), base_dir),
|
||||
base::BindOnce(&FileChooserImpl::FileSelected, owner_->GetWeakPtr(),
|
||||
base_dir, mode));
|
||||
}
|
||||
diff --git a/content/browser/web_contents/file_chooser_impl_browsertest.cc b/content/browser/web_contents/file_chooser_impl_browsertest.cc
|
||||
index 2acd2216331bd9be56eb9705f0e9c0d3bceb9e93..d988e221688ee19493e43c0b5f736fa432843cd0 100644
|
||||
--- a/content/browser/web_contents/file_chooser_impl_browsertest.cc
|
||||
+++ b/content/browser/web_contents/file_chooser_impl_browsertest.cc
|
||||
@@ -177,8 +177,8 @@ IN_PROC_BROWSER_TEST_F(FileChooserImplBrowserTest, UploadFolderWithSymlink) {
|
||||
return;
|
||||
}
|
||||
|
||||
- std::unique_ptr<FileChooserDelegate> delegate(
|
||||
- new FileChooserDelegate({text_file, symlink_file}, base::OnceClosure()));
|
||||
+ std::unique_ptr<FileChooserDelegate> delegate(new FileChooserDelegate(
|
||||
+ {text_file, symlink_file}, folder_to_upload, base::OnceClosure()));
|
||||
shell()->web_contents()->SetDelegate(delegate.get());
|
||||
EXPECT_TRUE(ExecJs(shell(),
|
||||
"(async () => {"
|
||||
@@ -195,4 +195,45 @@ IN_PROC_BROWSER_TEST_F(FileChooserImplBrowserTest, UploadFolderWithSymlink) {
|
||||
EvalJs(shell(), "document.getElementById('fileinput').files[0].name;"));
|
||||
}
|
||||
|
||||
+// https://crbug.com/1378997
|
||||
+IN_PROC_BROWSER_TEST_F(FileChooserImplBrowserTest, UploadFolderWithDirSymlink) {
|
||||
+ EXPECT_TRUE(NavigateToURL(
|
||||
+ shell(), GetTestUrl(".", "file_input_webkitdirectory.html")));
|
||||
+
|
||||
+ // The folder contains a regular file and a directory symbolic link.
|
||||
+ // When uploading the folder, the symbolic link should not be followed.
|
||||
+ base::FilePath dir_test_data;
|
||||
+ ASSERT_TRUE(base::PathService::Get(DIR_TEST_DATA, &dir_test_data));
|
||||
+ base::FilePath folder_to_upload = dir_test_data.AppendASCII("file_chooser")
|
||||
+ .AppendASCII("dir_with_dir_symlink");
|
||||
+
|
||||
+ base::FilePath foo_file = folder_to_upload.AppendASCII("foo.txt");
|
||||
+ base::FilePath dir_symlink = folder_to_upload.AppendASCII("symlink");
|
||||
+ base::FilePath bar_file = dir_symlink.AppendASCII("bar.txt");
|
||||
+
|
||||
+ // Skip the test if symbolic links are not supported.
|
||||
+ {
|
||||
+ base::ScopedAllowBlockingForTesting allow_blocking;
|
||||
+ if (!base::IsLink(dir_symlink))
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
+ std::unique_ptr<FileChooserDelegate> delegate(new FileChooserDelegate(
|
||||
+ {foo_file, bar_file}, folder_to_upload, base::OnceClosure()));
|
||||
+ shell()->web_contents()->SetDelegate(delegate.get());
|
||||
+ EXPECT_TRUE(ExecJs(shell(),
|
||||
+ "(async () => {"
|
||||
+ " let listener = new Promise("
|
||||
+ " resolve => fileinput.onchange = resolve);"
|
||||
+ " fileinput.click();"
|
||||
+ " await listener;"
|
||||
+ "})()"));
|
||||
+
|
||||
+ EXPECT_EQ(
|
||||
+ 1, EvalJs(shell(), "document.getElementById('fileinput').files.length;"));
|
||||
+ EXPECT_EQ(
|
||||
+ "foo.txt",
|
||||
+ EvalJs(shell(), "document.getElementById('fileinput').files[0].name;"));
|
||||
+}
|
||||
+
|
||||
} // namespace content
|
||||
diff --git a/content/test/content_browser_test_utils_internal.cc b/content/test/content_browser_test_utils_internal.cc
|
||||
index dbdf244571956645c6494c4cdab514dd42dbb6c2..70166cf3470595c928b202325f56f17abd0a61ac 100644
|
||||
--- a/content/test/content_browser_test_utils_internal.cc
|
||||
+++ b/content/test/content_browser_test_utils_internal.cc
|
||||
@@ -448,12 +448,16 @@ Shell* OpenPopup(const ToRenderFrameHost& opener,
|
||||
}
|
||||
|
||||
FileChooserDelegate::FileChooserDelegate(std::vector<base::FilePath> files,
|
||||
+ const base::FilePath& base_dir,
|
||||
base::OnceClosure callback)
|
||||
- : files_(std::move(files)), callback_(std::move(callback)) {}
|
||||
+ : files_(std::move(files)),
|
||||
+ base_dir_(base_dir),
|
||||
+ callback_(std::move(callback)) {}
|
||||
|
||||
FileChooserDelegate::FileChooserDelegate(const base::FilePath& file,
|
||||
base::OnceClosure callback)
|
||||
: FileChooserDelegate(std::vector<base::FilePath>(1, file),
|
||||
+ base::FilePath(),
|
||||
std::move(callback)) {}
|
||||
|
||||
FileChooserDelegate::~FileChooserDelegate() = default;
|
||||
@@ -462,6 +466,9 @@ void FileChooserDelegate::RunFileChooser(
|
||||
RenderFrameHost* render_frame_host,
|
||||
scoped_refptr<content::FileSelectListener> listener,
|
||||
const blink::mojom::FileChooserParams& params) {
|
||||
+ // |base_dir_| should be set for and only for |kUploadFolder| mode.
|
||||
+ DCHECK(base_dir_.empty() ==
|
||||
+ (params.mode != blink::mojom::FileChooserParams::Mode::kUploadFolder));
|
||||
// Send the selected files to the renderer process.
|
||||
std::vector<blink::mojom::FileChooserFileInfoPtr> files;
|
||||
for (const auto& file : files_) {
|
||||
@@ -469,7 +476,7 @@ void FileChooserDelegate::RunFileChooser(
|
||||
blink::mojom::NativeFileInfo::New(file, std::u16string()));
|
||||
files.push_back(std::move(file_info));
|
||||
}
|
||||
- listener->FileSelected(std::move(files), base::FilePath(), params.mode);
|
||||
+ listener->FileSelected(std::move(files), base_dir_, params.mode);
|
||||
|
||||
params_ = params.Clone();
|
||||
if (callback_)
|
||||
diff --git a/content/test/content_browser_test_utils_internal.h b/content/test/content_browser_test_utils_internal.h
|
||||
index 3bf1bb93e15b0a5270262837802e140ad72a9231..6bd95d55add1c0da850be6078d02c3eae479ea62 100644
|
||||
--- a/content/test/content_browser_test_utils_internal.h
|
||||
+++ b/content/test/content_browser_test_utils_internal.h
|
||||
@@ -179,7 +179,10 @@ class FileChooserDelegate : public WebContentsDelegate {
|
||||
// The mocked file dialog will always reply that the user selected |file| or
|
||||
// |files|. |callback| is invoked when RunFileChooser() is called.
|
||||
FileChooserDelegate(const base::FilePath& file, base::OnceClosure callback);
|
||||
+ // |base_dir| must be set to the folder being uploaded in |kUploadFolder|
|
||||
+ // mode, and must be empty in all other modes.
|
||||
FileChooserDelegate(std::vector<base::FilePath> files,
|
||||
+ const base::FilePath& base_dir,
|
||||
base::OnceClosure callback);
|
||||
~FileChooserDelegate() override;
|
||||
|
||||
@@ -193,6 +196,7 @@ class FileChooserDelegate : public WebContentsDelegate {
|
||||
|
||||
private:
|
||||
std::vector<base::FilePath> files_;
|
||||
+ const base::FilePath base_dir_;
|
||||
base::OnceClosure callback_;
|
||||
blink::mojom::FileChooserParamsPtr params_;
|
||||
};
|
||||
diff --git a/content/test/data/file_chooser/dir_with_dir_symlink/foo.txt b/content/test/data/file_chooser/dir_with_dir_symlink/foo.txt
|
||||
new file mode 100644
|
||||
index 0000000000000000000000000000000000000000..257cc5642cb1a054f08cc83f2d943e56fd3ebe99
|
||||
--- /dev/null
|
||||
+++ b/content/test/data/file_chooser/dir_with_dir_symlink/foo.txt
|
||||
@@ -0,0 +1 @@
|
||||
+foo
|
||||
diff --git a/content/test/data/file_chooser/dir_with_dir_symlink/symlink b/content/test/data/file_chooser/dir_with_dir_symlink/symlink
|
||||
new file mode 120000
|
||||
index 0000000000000000000000000000000000000000..10f6d1ab9ba9ede59b719d4ba1581588e172abb6
|
||||
--- /dev/null
|
||||
+++ b/content/test/data/file_chooser/dir_with_dir_symlink/symlink
|
||||
@@ -0,0 +1 @@
|
||||
+../linked_dir/
|
||||
\ No newline at end of file
|
||||
diff --git a/content/test/data/file_chooser/linked_dir/bar.txt b/content/test/data/file_chooser/linked_dir/bar.txt
|
||||
new file mode 100644
|
||||
index 0000000000000000000000000000000000000000..5716ca5987cbf97d6bb54920bea6adde242d87e6
|
||||
--- /dev/null
|
||||
+++ b/content/test/data/file_chooser/linked_dir/bar.txt
|
||||
@@ -0,0 +1 @@
|
||||
+bar
|
||||
55
patches/chromium/cherry-pick-f98adc846aad.patch
Normal file
55
patches/chromium/cherry-pick-f98adc846aad.patch
Normal file
@@ -0,0 +1,55 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Austin Sullivan <asully@chromium.org>
|
||||
Date: Tue, 11 Oct 2022 20:53:22 +0000
|
||||
Subject: FSA: Block .url files in getFileHandle and getEntries
|
||||
|
||||
Fixed: 1354518
|
||||
Change-Id: I663d4481ccc2047c49d7466bbfe9751e8c140edf
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3945587
|
||||
Reviewed-by: Marijn Kruisselbrink <mek@chromium.org>
|
||||
Commit-Queue: Marijn Kruisselbrink <mek@chromium.org>
|
||||
Auto-Submit: Austin Sullivan <asully@chromium.org>
|
||||
Cr-Commit-Position: refs/heads/main@{#1057675}
|
||||
|
||||
diff --git a/content/browser/file_system_access/file_system_access_directory_handle_impl.cc b/content/browser/file_system_access/file_system_access_directory_handle_impl.cc
|
||||
index 7e673f903a71a309e8d92b966330875ef2772f84..13ce0b974268215f0e92ccedd2f56643c8a36679 100644
|
||||
--- a/content/browser/file_system_access/file_system_access_directory_handle_impl.cc
|
||||
+++ b/content/browser/file_system_access/file_system_access_directory_handle_impl.cc
|
||||
@@ -444,9 +444,12 @@ bool IsShellIntegratedExtension(const base::FilePath::StringType& extension) {
|
||||
|
||||
// .lnk and .scf files may be used to execute arbitrary code (see
|
||||
// https://nvd.nist.gov/vuln/detail/CVE-2010-2568 and
|
||||
- // https://crbug.com/1227995, respectively).
|
||||
+ // https://crbug.com/1227995, respectively). '.url' files can be used to read
|
||||
+ // arbitrary files (see https://crbug.com/1307930 and
|
||||
+ // https://crbug.com/1354518).
|
||||
if (extension_lower == FILE_PATH_LITERAL("lnk") ||
|
||||
- extension_lower == FILE_PATH_LITERAL("scf")) {
|
||||
+ extension_lower == FILE_PATH_LITERAL("scf") ||
|
||||
+ extension_lower == FILE_PATH_LITERAL("url")) {
|
||||
return true;
|
||||
}
|
||||
|
||||
diff --git a/content/browser/file_system_access/file_system_access_directory_handle_impl_unittest.cc b/content/browser/file_system_access/file_system_access_directory_handle_impl_unittest.cc
|
||||
index 606e34473296199317747fa949158f402b163ec0..9dd03ca412fdc69d7e6bb18b08a157ac9b69bf13 100644
|
||||
--- a/content/browser/file_system_access/file_system_access_directory_handle_impl_unittest.cc
|
||||
+++ b/content/browser/file_system_access/file_system_access_directory_handle_impl_unittest.cc
|
||||
@@ -150,6 +150,7 @@ TEST_F(FileSystemAccessDirectoryHandleImplTest, IsSafePathComponent) {
|
||||
"My Computer.{20D04FE0-3AEA-1069-A2D8-08002B30309D}",
|
||||
"a\\a",
|
||||
"a.lnk",
|
||||
+ "a.url",
|
||||
"a/a",
|
||||
"C:\\",
|
||||
"C:/",
|
||||
@@ -205,8 +206,8 @@ TEST_F(FileSystemAccessDirectoryHandleImplTest, GetEntries) {
|
||||
constexpr const char* kSafeNames[] = {"a", "a.txt", "My Computer", "lnk.txt",
|
||||
"a.local"};
|
||||
constexpr const char* kUnsafeNames[] = {
|
||||
- "con", "con.zip", "NUL", "a.",
|
||||
- "a\"a", "a . .", "a.lnk", "My Computer.{a}",
|
||||
+ "con", "con.zip", "NUL", "a.", "a\"a", "a . .",
|
||||
+ "a.lnk", "My Computer.{a}", "a.url",
|
||||
};
|
||||
for (const char* name : kSafeNames) {
|
||||
ASSERT_TRUE(base::WriteFile(dir_.GetPath().AppendASCII(name), "data"))
|
||||
@@ -0,0 +1,59 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Kyrylo Hrechykhin <khrechykhin@microsoft.com>
|
||||
Date: Thu, 6 Oct 2022 18:30:53 +0200
|
||||
Subject: fix: on-screen-keyboard hides on input blur in webview
|
||||
|
||||
Changes introduced by this patch fix issue where OSK does not hide on
|
||||
input rendered inside webview is blurred. This patch should be removed
|
||||
when proper fix in chromium repo is available.
|
||||
|
||||
Note: the issue still occurs if input rendered in webview blurred due
|
||||
to touch outside of webview. It is caused by webview implementation
|
||||
details. Specificaly due to webview has its own tree nodes and focused
|
||||
node does not change in this case.
|
||||
|
||||
chromium-bug: https://crbug.com/1369605
|
||||
|
||||
diff --git a/content/browser/renderer_host/render_widget_host_view_child_frame.cc b/content/browser/renderer_host/render_widget_host_view_child_frame.cc
|
||||
index 4e6d62be68d59c8a49159fda4d1e68f101a6f0a3..cfd5a01ea84a1f454a5172da3e96e66a50c82939 100644
|
||||
--- a/content/browser/renderer_host/render_widget_host_view_child_frame.cc
|
||||
+++ b/content/browser/renderer_host/render_widget_host_view_child_frame.cc
|
||||
@@ -992,6 +992,12 @@ RenderWidgetHostViewChildFrame::DidUpdateVisualProperties(
|
||||
return viz::ScopedSurfaceIdAllocator(std::move(allocation_task));
|
||||
}
|
||||
|
||||
+void RenderWidgetHostViewChildFrame::FocusedNodeChanged(
|
||||
+ bool is_editable_node,
|
||||
+ const gfx::Rect& node_bounds_in_screen) {
|
||||
+ NOTREACHED();
|
||||
+}
|
||||
+
|
||||
ui::TextInputType RenderWidgetHostViewChildFrame::GetTextInputType() const {
|
||||
if (!text_input_manager_)
|
||||
return ui::TEXT_INPUT_TYPE_NONE;
|
||||
diff --git a/content/browser/renderer_host/render_widget_host_view_child_frame.h b/content/browser/renderer_host/render_widget_host_view_child_frame.h
|
||||
index 70b151bcb8e3b1964d316bf2e169dbe0f28f24c7..c3857298974a0c2761efcd3924587607997e3117 100644
|
||||
--- a/content/browser/renderer_host/render_widget_host_view_child_frame.h
|
||||
+++ b/content/browser/renderer_host/render_widget_host_view_child_frame.h
|
||||
@@ -181,6 +181,8 @@ class CONTENT_EXPORT RenderWidgetHostViewChildFrame
|
||||
void DisableAutoResize(const gfx::Size& new_size) override;
|
||||
viz::ScopedSurfaceIdAllocator DidUpdateVisualProperties(
|
||||
const cc::RenderFrameMetadata& metadata) override;
|
||||
+ void FocusedNodeChanged(bool is_editable_node,
|
||||
+ const gfx::Rect& node_bounds_in_screen) override;
|
||||
|
||||
// RenderFrameMetadataProvider::Observer implementation.
|
||||
void OnRenderFrameMetadataChangedBeforeActivation(
|
||||
diff --git a/content/browser/web_contents/web_contents_impl.cc b/content/browser/web_contents/web_contents_impl.cc
|
||||
index 74993d461cbd0885a709cf8b663b9c69650aa3cf..940045d9bbb62676811f55f5d30a93a352f43ede 100644
|
||||
--- a/content/browser/web_contents/web_contents_impl.cc
|
||||
+++ b/content/browser/web_contents/web_contents_impl.cc
|
||||
@@ -7928,7 +7928,7 @@ void WebContentsImpl::OnFocusedElementChangedInFrame(
|
||||
"WebContentsImpl::OnFocusedElementChangedInFrame",
|
||||
"render_frame_host", frame);
|
||||
RenderWidgetHostViewBase* root_view =
|
||||
- static_cast<RenderWidgetHostViewBase*>(GetRenderWidgetHostView());
|
||||
+ static_cast<RenderWidgetHostViewBase*>(GetTopLevelRenderWidgetHostView());
|
||||
if (!root_view || !frame->GetView())
|
||||
return;
|
||||
// Convert to screen coordinates from window coordinates by adding the
|
||||
@@ -0,0 +1,85 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Peng Huang <penghuang@chromium.org>
|
||||
Date: Mon, 13 Feb 2023 22:10:44 +0000
|
||||
Subject: Fix UAF problem in AngleVulkanImageBacking
|
||||
|
||||
Right now, we use vulkan fence helper to release the backing.
|
||||
It is right, if the last usage of the backing is by skia.
|
||||
If the last usage is by gl, the fence helper(skia) isn't aware of
|
||||
the submitted work from ANGLE, skia may call flush finish callback
|
||||
to release the backing while the backing is still being referenced
|
||||
by works in ANGLE. Fix the problem by calling glFinish() if the last
|
||||
usage is GL.
|
||||
|
||||
Know issue: the finish callback of skia flush() is not always called
|
||||
in order. So in edge cases, the UAF problem can still happen.
|
||||
|
||||
(cherry picked from commit d5143b14a00807b40eada4dfb0bce610ffc1477a)
|
||||
|
||||
Bug: 1309035
|
||||
Change-Id: I3562043650dd2b27bde3a370bef45b1226cdd48c
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/4232858
|
||||
Reviewed-by: Vasiliy Telezhnikov <vasilyt@chromium.org>
|
||||
Commit-Queue: Peng Huang <penghuang@chromium.org>
|
||||
Cr-Original-Commit-Position: refs/heads/main@{#1102905}
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/4245959
|
||||
Cr-Commit-Position: refs/branch-heads/5481@{#1119}
|
||||
Cr-Branched-From: 130f3e4d850f4bc7387cfb8d08aa993d288a67a9-refs/heads/main@{#1084008}
|
||||
|
||||
diff --git a/gpu/command_buffer/service/shared_image/angle_vulkan_image_backing_factory.cc b/gpu/command_buffer/service/shared_image/angle_vulkan_image_backing_factory.cc
|
||||
index 84a64950db48dfa43f55793033dcf26af3b4a725..bfe2080e5ab844f3f9a7ccad8cfe7b4336ed68f1 100644
|
||||
--- a/gpu/command_buffer/service/shared_image/angle_vulkan_image_backing_factory.cc
|
||||
+++ b/gpu/command_buffer/service/shared_image/angle_vulkan_image_backing_factory.cc
|
||||
@@ -80,6 +80,11 @@ class AngleVulkanImageBacking : public ClearTrackingSharedImageBacking,
|
||||
|
||||
passthrough_texture_.reset();
|
||||
egl_image_.reset();
|
||||
+
|
||||
+ if (need_gl_finish_before_destroy_ && have_context()) {
|
||||
+ gl::GLApi* api = gl::g_current_gl_context;
|
||||
+ api->glFinishFn();
|
||||
+ }
|
||||
}
|
||||
if (vulkan_image_) {
|
||||
auto* fence_helper = context_state_->vk_context_provider()
|
||||
@@ -266,8 +271,9 @@ class AngleVulkanImageBacking : public ClearTrackingSharedImageBacking,
|
||||
--gl_reads_in_process_;
|
||||
|
||||
// For the last GL read access, release texture from ANGLE.
|
||||
- if (gl_reads_in_process_ == 0)
|
||||
+ if (gl_reads_in_process_ == 0) {
|
||||
ReleaseTextureANGLE();
|
||||
+ }
|
||||
|
||||
return;
|
||||
}
|
||||
@@ -299,6 +305,9 @@ class AngleVulkanImageBacking : public ClearTrackingSharedImageBacking,
|
||||
GLuint texture = passthrough_texture_->service_id();
|
||||
// Release the texture from ANGLE, so it can be used elsewhere.
|
||||
api->glReleaseTexturesANGLEFn(1, &texture, &layout_);
|
||||
+ // Releasing the texture will submit all related works to queue, so to be
|
||||
+ // safe, glFinish() should be called before releasing the VkImage.
|
||||
+ need_gl_finish_before_destroy_ = true;
|
||||
}
|
||||
|
||||
void PrepareBackendTexture() {
|
||||
@@ -383,6 +392,11 @@ class AngleVulkanImageBacking : public ClearTrackingSharedImageBacking,
|
||||
return;
|
||||
}
|
||||
|
||||
+ // The backing is used by skia, so skia should submit related work to the
|
||||
+ // queue, and we can use vulkan fence helper to release the VkImage.
|
||||
+ // glFinish() is not necessary anymore.
|
||||
+ need_gl_finish_before_destroy_ = false;
|
||||
+
|
||||
SyncImageLayoutFromBackendTexture();
|
||||
|
||||
if (gl_reads_in_process_ > 0) {
|
||||
@@ -449,6 +463,7 @@ class AngleVulkanImageBacking : public ClearTrackingSharedImageBacking,
|
||||
bool is_gl_write_in_process_ = false;
|
||||
int skia_reads_in_process_ = 0;
|
||||
int gl_reads_in_process_ = 0;
|
||||
+ bool need_gl_finish_before_destroy_ = false;
|
||||
};
|
||||
|
||||
class AngleVulkanImageBacking::SkiaAngleVulkanImageRepresentation
|
||||
@@ -0,0 +1,381 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Dale Curtis <dalecurtis@chromium.org>
|
||||
Date: Mon, 20 Feb 2023 13:16:32 +0000
|
||||
Subject: Further simplify WebMediaPlayerMSCompositor lifetime.
|
||||
|
||||
M108 merge issues:
|
||||
third_party/blink/renderer/modules/mediastream/webmediaplayer_ms.cc:
|
||||
- video_task_runner_ is named io_task_runner_ in 108
|
||||
|
||||
third_party/blink/renderer/modules/mediastream/webmediaplayer_ms_compositor.cc:
|
||||
- video_task_runner_ is named io_task_runner_ in 108 (conflict in ReplaceCurrentFrameWithACopy)
|
||||
|
||||
Due to the raw pointer held by VideoFrameSubmitter, there may be
|
||||
tasks pending on the compositor task runner after the RefCounted
|
||||
traits have "destructed" WebMediaPlayerMSCompositor. Through this
|
||||
raw pointer VFS was invoking OnContextLost which attempts to use
|
||||
the zero ref count compositor.
|
||||
|
||||
The solution here is again similar to VideoFrameCompositor, its
|
||||
destruction should be explicit instead of a tangle of RefCounted
|
||||
owners.
|
||||
|
||||
(cherry picked from commit 1622bffc6534a0cc4f53d07c43e0cd8f49975d10)
|
||||
|
||||
Fixed: 1407701, 1411601
|
||||
Change-Id: Ic77294d1113d54ab83bc0f5b625a997edf57bf7c
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/4210508
|
||||
Commit-Queue: Tony Herre <toprice@chromium.org>
|
||||
Auto-Submit: Dale Curtis <dalecurtis@chromium.org>
|
||||
Cr-Original-Commit-Position: refs/heads/main@{#1099726}
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/4225393
|
||||
Commit-Queue: Roger Felipe Zanoni da Silva <rzanoni@google.com>
|
||||
Reviewed-by: Oleh Lamzin <lamzin@google.com>
|
||||
Owners-Override: Oleh Lamzin <lamzin@google.com>
|
||||
Cr-Commit-Position: refs/branch-heads/5359@{#1392}
|
||||
Cr-Branched-From: 27d3765d341b09369006d030f83f582a29eb57ae-refs/heads/main@{#1058933}
|
||||
|
||||
diff --git a/third_party/blink/public/web/modules/mediastream/webmediaplayer_ms.h b/third_party/blink/public/web/modules/mediastream/webmediaplayer_ms.h
|
||||
index e67725f91f57ffbdf17e5830bd12c38010a9625c..0e8908e847a956f5e3a99f232e8db1131294b856 100644
|
||||
--- a/third_party/blink/public/web/modules/mediastream/webmediaplayer_ms.h
|
||||
+++ b/third_party/blink/public/web/modules/mediastream/webmediaplayer_ms.h
|
||||
@@ -207,6 +207,8 @@ class BLINK_MODULES_EXPORT WebMediaPlayerMS
|
||||
static const gfx::Size kUseGpuMemoryBufferVideoFramesMinResolution;
|
||||
#endif // BUILDFLAG(IS_WIN)
|
||||
|
||||
+ void ReplaceCurrentFrameWithACopy();
|
||||
+
|
||||
bool IsInPictureInPicture() const;
|
||||
|
||||
// Switch to SurfaceLayer, either initially or from VideoLayer.
|
||||
@@ -309,7 +311,7 @@ class BLINK_MODULES_EXPORT WebMediaPlayerMS
|
||||
// Used for DCHECKs to ensure methods calls executed in the correct thread.
|
||||
THREAD_CHECKER(thread_checker_);
|
||||
|
||||
- scoped_refptr<WebMediaPlayerMSCompositor> compositor_;
|
||||
+ std::unique_ptr<WebMediaPlayerMSCompositor> compositor_;
|
||||
|
||||
const WebString initial_audio_output_device_id_;
|
||||
|
||||
diff --git a/third_party/blink/renderer/modules/mediastream/webmediaplayer_ms.cc b/third_party/blink/renderer/modules/mediastream/webmediaplayer_ms.cc
|
||||
index 5b075cc0acecf71097549b0cbfb044fa4766e851..9dd6d360831647f9da3e04a54c7fc7828d6b5bbd 100644
|
||||
--- a/third_party/blink/renderer/modules/mediastream/webmediaplayer_ms.cc
|
||||
+++ b/third_party/blink/renderer/modules/mediastream/webmediaplayer_ms.cc
|
||||
@@ -399,8 +399,9 @@ WebMediaPlayerMS::~WebMediaPlayerMS() {
|
||||
SendLogMessage(
|
||||
String::Format("%s() [delegate_id=%d]", __func__, delegate_id_));
|
||||
|
||||
- if (!web_stream_.IsNull())
|
||||
+ if (!web_stream_.IsNull()) {
|
||||
web_stream_.RemoveObserver(this);
|
||||
+ }
|
||||
|
||||
// Destruct compositor resources in the proper order.
|
||||
get_client()->SetCcLayer(nullptr);
|
||||
@@ -409,14 +410,35 @@ WebMediaPlayerMS::~WebMediaPlayerMS() {
|
||||
video_layer_->StopUsingProvider();
|
||||
}
|
||||
|
||||
- if (frame_deliverer_)
|
||||
- io_task_runner_->DeleteSoon(FROM_HERE, frame_deliverer_.release());
|
||||
+ if (frame_deliverer_) {
|
||||
+ io_task_runner_->DeleteSoon(FROM_HERE, std::move(frame_deliverer_));
|
||||
+ }
|
||||
|
||||
- if (video_frame_provider_)
|
||||
+ if (video_frame_provider_) {
|
||||
video_frame_provider_->Stop();
|
||||
+ }
|
||||
|
||||
- if (audio_renderer_)
|
||||
+ // This must be destroyed before `compositor_` since it will grab a couple of
|
||||
+ // final metrics during destruction.
|
||||
+ watch_time_reporter_.reset();
|
||||
+
|
||||
+ if (compositor_) {
|
||||
+ // `compositor_` receives frames on `io_task_runner_` from
|
||||
+ // `frame_deliverer_` and operates on the `compositor_task_runner_`, so
|
||||
+ // must trampoline through both to ensure a safe destruction.
|
||||
+ PostCrossThreadTask(
|
||||
+ *io_task_runner_, FROM_HERE,
|
||||
+ WTF::CrossThreadBindOnce(
|
||||
+ [](scoped_refptr<base::SingleThreadTaskRunner> task_runner,
|
||||
+ std::unique_ptr<WebMediaPlayerMSCompositor> compositor) {
|
||||
+ task_runner->DeleteSoon(FROM_HERE, std::move(compositor));
|
||||
+ },
|
||||
+ compositor_task_runner_, std::move(compositor_)));
|
||||
+ }
|
||||
+
|
||||
+ if (audio_renderer_) {
|
||||
audio_renderer_->Stop();
|
||||
+ }
|
||||
|
||||
media_log_->AddEvent<media::MediaLogEvent::kWebMediaPlayerDestroyed>();
|
||||
|
||||
@@ -457,7 +479,7 @@ WebMediaPlayer::LoadTiming WebMediaPlayerMS::Load(
|
||||
|
||||
watch_time_reporter_.reset();
|
||||
|
||||
- compositor_ = base::MakeRefCounted<WebMediaPlayerMSCompositor>(
|
||||
+ compositor_ = std::make_unique<WebMediaPlayerMSCompositor>(
|
||||
compositor_task_runner_, io_task_runner_, web_stream_,
|
||||
std::move(submitter_), use_surface_layer_, weak_this_);
|
||||
|
||||
@@ -480,7 +502,7 @@ WebMediaPlayer::LoadTiming WebMediaPlayerMS::Load(
|
||||
frame_deliverer_ = std::make_unique<WebMediaPlayerMS::FrameDeliverer>(
|
||||
weak_this_,
|
||||
CrossThreadBindRepeating(&WebMediaPlayerMSCompositor::EnqueueFrame,
|
||||
- compositor_),
|
||||
+ CrossThreadUnretained(compositor_.get())),
|
||||
media_task_runner_, worker_task_runner_, gpu_factories_);
|
||||
video_frame_provider_ = renderer_factory_->GetVideoRenderer(
|
||||
web_stream_,
|
||||
@@ -823,7 +845,19 @@ void WebMediaPlayerMS::Pause() {
|
||||
video_frame_provider_->Pause();
|
||||
|
||||
compositor_->StopRendering();
|
||||
- compositor_->ReplaceCurrentFrameWithACopy();
|
||||
+
|
||||
+ // Bounce this call off of video task runner to since there might still be
|
||||
+ // frames passed on video task runner.
|
||||
+ PostCrossThreadTask(
|
||||
+ *io_task_runner_, FROM_HERE,
|
||||
+ WTF::CrossThreadBindOnce(
|
||||
+ [](scoped_refptr<base::SingleThreadTaskRunner> task_runner,
|
||||
+ WTF::CrossThreadOnceClosure copy_cb) {
|
||||
+ PostCrossThreadTask(*task_runner, FROM_HERE, std::move(copy_cb));
|
||||
+ },
|
||||
+ main_render_task_runner_,
|
||||
+ WTF::CrossThreadBindOnce(
|
||||
+ &WebMediaPlayerMS::ReplaceCurrentFrameWithACopy, weak_this_)));
|
||||
|
||||
if (audio_renderer_)
|
||||
audio_renderer_->Pause();
|
||||
@@ -838,6 +872,11 @@ void WebMediaPlayerMS::Pause() {
|
||||
paused_ = true;
|
||||
}
|
||||
|
||||
+void WebMediaPlayerMS::ReplaceCurrentFrameWithACopy() {
|
||||
+ DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
|
||||
+ compositor_->ReplaceCurrentFrameWithACopy();
|
||||
+}
|
||||
+
|
||||
void WebMediaPlayerMS::Seek(double seconds) {
|
||||
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
|
||||
}
|
||||
@@ -1184,7 +1223,8 @@ void WebMediaPlayerMS::ActivateSurfaceLayerForVideo(
|
||||
PostCrossThreadTask(
|
||||
*compositor_task_runner_, FROM_HERE,
|
||||
CrossThreadBindOnce(&WebMediaPlayerMSCompositor::EnableSubmission,
|
||||
- compositor_, bridge_->GetSurfaceId(), video_transform,
|
||||
+ CrossThreadUnretained(compositor_.get()),
|
||||
+ bridge_->GetSurfaceId(), video_transform,
|
||||
IsInPictureInPicture()));
|
||||
|
||||
// If the element is already in Picture-in-Picture mode, it means that it
|
||||
diff --git a/third_party/blink/renderer/modules/mediastream/webmediaplayer_ms_compositor.cc b/third_party/blink/renderer/modules/mediastream/webmediaplayer_ms_compositor.cc
|
||||
index 2be89c9104c493d2672436fb8d36d6f10e4f6939..51b5c56a7acc31643290f5a92cd416c81c0c507c 100644
|
||||
--- a/third_party/blink/renderer/modules/mediastream/webmediaplayer_ms_compositor.cc
|
||||
+++ b/third_party/blink/renderer/modules/mediastream/webmediaplayer_ms_compositor.cc
|
||||
@@ -195,18 +195,18 @@ WebMediaPlayerMSCompositor::WebMediaPlayerMSCompositor(
|
||||
dropped_frame_count_(0),
|
||||
stopped_(true),
|
||||
render_started_(!stopped_) {
|
||||
+ weak_this_ = weak_ptr_factory_.GetWeakPtr();
|
||||
if (use_surface_layer) {
|
||||
submitter_ = std::move(submitter);
|
||||
|
||||
PostCrossThreadTask(
|
||||
*video_frame_compositor_task_runner_, FROM_HERE,
|
||||
CrossThreadBindOnce(&WebMediaPlayerMSCompositor::InitializeSubmitter,
|
||||
- weak_ptr_factory_.GetWeakPtr()));
|
||||
+ weak_this_));
|
||||
update_submission_state_callback_ = base::BindPostTask(
|
||||
video_frame_compositor_task_runner_,
|
||||
ConvertToBaseRepeatingCallback(CrossThreadBindRepeating(
|
||||
- &WebMediaPlayerMSCompositor::SetIsSurfaceVisible,
|
||||
- weak_ptr_factory_.GetWeakPtr())));
|
||||
+ &WebMediaPlayerMSCompositor::SetIsSurfaceVisible, weak_this_)));
|
||||
}
|
||||
|
||||
HeapVector<Member<MediaStreamComponent>> video_components;
|
||||
@@ -234,27 +234,12 @@ WebMediaPlayerMSCompositor::WebMediaPlayerMSCompositor(
|
||||
}
|
||||
|
||||
WebMediaPlayerMSCompositor::~WebMediaPlayerMSCompositor() {
|
||||
- // Ensured by destructor traits.
|
||||
DCHECK(video_frame_compositor_task_runner_->BelongsToCurrentThread());
|
||||
if (video_frame_provider_client_) {
|
||||
video_frame_provider_client_->StopUsingProvider();
|
||||
}
|
||||
}
|
||||
|
||||
-// static
|
||||
-void WebMediaPlayerMSCompositorTraits::Destruct(
|
||||
- const WebMediaPlayerMSCompositor* compositor) {
|
||||
- if (!compositor->video_frame_compositor_task_runner_
|
||||
- ->BelongsToCurrentThread()) {
|
||||
- PostCrossThreadTask(
|
||||
- *compositor->video_frame_compositor_task_runner_, FROM_HERE,
|
||||
- CrossThreadBindOnce(&WebMediaPlayerMSCompositorTraits::Destruct,
|
||||
- CrossThreadUnretained(compositor)));
|
||||
- return;
|
||||
- }
|
||||
- delete compositor;
|
||||
-}
|
||||
-
|
||||
void WebMediaPlayerMSCompositor::InitializeSubmitter() {
|
||||
DCHECK(video_frame_compositor_task_runner_->BelongsToCurrentThread());
|
||||
submitter_->Initialize(this, /*is_media_stream=*/true);
|
||||
@@ -300,7 +285,7 @@ void WebMediaPlayerMSCompositor::SetForceBeginFrames(bool enable) {
|
||||
PostCrossThreadTask(
|
||||
*video_frame_compositor_task_runner_, FROM_HERE,
|
||||
CrossThreadBindOnce(&WebMediaPlayerMSCompositor::SetForceBeginFrames,
|
||||
- weak_ptr_factory_.GetWeakPtr(), enable));
|
||||
+ weak_this_, enable));
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -602,7 +587,7 @@ void WebMediaPlayerMSCompositor::StartRendering() {
|
||||
PostCrossThreadTask(
|
||||
*video_frame_compositor_task_runner_, FROM_HERE,
|
||||
CrossThreadBindOnce(&WebMediaPlayerMSCompositor::StartRenderingInternal,
|
||||
- WrapRefCounted(this)));
|
||||
+ weak_this_));
|
||||
}
|
||||
|
||||
void WebMediaPlayerMSCompositor::StopRendering() {
|
||||
@@ -610,18 +595,7 @@ void WebMediaPlayerMSCompositor::StopRendering() {
|
||||
PostCrossThreadTask(
|
||||
*video_frame_compositor_task_runner_, FROM_HERE,
|
||||
CrossThreadBindOnce(&WebMediaPlayerMSCompositor::StopRenderingInternal,
|
||||
- WrapRefCounted(this)));
|
||||
-}
|
||||
-
|
||||
-void WebMediaPlayerMSCompositor::ReplaceCurrentFrameWithACopy() {
|
||||
- DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
|
||||
- // Bounce this call off of IO thread to since there might still be frames
|
||||
- // passed on IO thread.
|
||||
- io_task_runner_->PostTask(
|
||||
- FROM_HERE,
|
||||
- media::BindToCurrentLoop(WTF::Bind(
|
||||
- &WebMediaPlayerMSCompositor::ReplaceCurrentFrameWithACopyInternal,
|
||||
- WrapRefCounted(this))));
|
||||
+ weak_this_));
|
||||
}
|
||||
|
||||
bool WebMediaPlayerMSCompositor::MapTimestampsToRenderTimeTicks(
|
||||
@@ -691,7 +665,7 @@ void WebMediaPlayerMSCompositor::RenderWithoutAlgorithm(
|
||||
*video_frame_compositor_task_runner_, FROM_HERE,
|
||||
CrossThreadBindOnce(
|
||||
&WebMediaPlayerMSCompositor::RenderWithoutAlgorithmOnCompositor,
|
||||
- WrapRefCounted(this), std::move(frame), is_copy));
|
||||
+ weak_this_, std::move(frame), is_copy));
|
||||
}
|
||||
|
||||
void WebMediaPlayerMSCompositor::RenderWithoutAlgorithmOnCompositor(
|
||||
@@ -791,9 +765,8 @@ void WebMediaPlayerMSCompositor::SetCurrentFrame(
|
||||
PostCrossThreadTask(
|
||||
*video_frame_compositor_task_runner_, FROM_HERE,
|
||||
CrossThreadBindOnce(&WebMediaPlayerMSCompositor::CheckForFrameChanges,
|
||||
- WrapRefCounted(this), is_first_frame,
|
||||
- has_frame_size_changed, std::move(new_transform),
|
||||
- std::move(new_opacity)));
|
||||
+ weak_this_, is_first_frame, has_frame_size_changed,
|
||||
+ std::move(new_transform), std::move(new_opacity)));
|
||||
}
|
||||
|
||||
void WebMediaPlayerMSCompositor::CheckForFrameChanges(
|
||||
@@ -860,7 +833,7 @@ void WebMediaPlayerMSCompositor::StopRenderingInternal() {
|
||||
video_frame_provider_client_->StopRendering();
|
||||
}
|
||||
|
||||
-void WebMediaPlayerMSCompositor::ReplaceCurrentFrameWithACopyInternal() {
|
||||
+void WebMediaPlayerMSCompositor::ReplaceCurrentFrameWithACopy() {
|
||||
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
|
||||
scoped_refptr<media::VideoFrame> current_frame_ref;
|
||||
{
|
||||
diff --git a/third_party/blink/renderer/modules/mediastream/webmediaplayer_ms_compositor.h b/third_party/blink/renderer/modules/mediastream/webmediaplayer_ms_compositor.h
|
||||
index a8565180d57a80f596bbd28690c7c6ceefe6474b..915933b75dc957ab84643ac1b5d1db2f3296d767 100644
|
||||
--- a/third_party/blink/renderer/modules/mediastream/webmediaplayer_ms_compositor.h
|
||||
+++ b/third_party/blink/renderer/modules/mediastream/webmediaplayer_ms_compositor.h
|
||||
@@ -24,7 +24,6 @@
|
||||
#include "third_party/blink/renderer/modules/mediastream/video_renderer_algorithm_wrapper.h"
|
||||
#include "third_party/blink/renderer/modules/modules_export.h"
|
||||
#include "third_party/blink/renderer/platform/wtf/cross_thread_functional.h"
|
||||
-#include "third_party/blink/renderer/platform/wtf/thread_safe_ref_counted.h"
|
||||
|
||||
namespace base {
|
||||
class SingleThreadTaskRunner;
|
||||
@@ -46,7 +45,6 @@ class SurfaceId;
|
||||
namespace blink {
|
||||
class MediaStreamDescriptor;
|
||||
class WebMediaPlayerMS;
|
||||
-struct WebMediaPlayerMSCompositorTraits;
|
||||
|
||||
// This class is designed to handle the work load on compositor thread for
|
||||
// WebMediaPlayerMS. It will be instantiated on the main thread, but destroyed
|
||||
@@ -58,9 +56,7 @@ struct WebMediaPlayerMSCompositorTraits;
|
||||
// Otherwise, WebMediaPlayerMSCompositor will simply store the most recent
|
||||
// frame, and submit it whenever asked by the compositor.
|
||||
class MODULES_EXPORT WebMediaPlayerMSCompositor
|
||||
- : public cc::VideoFrameProvider,
|
||||
- public WTF::ThreadSafeRefCounted<WebMediaPlayerMSCompositor,
|
||||
- WebMediaPlayerMSCompositorTraits> {
|
||||
+ : public cc::VideoFrameProvider {
|
||||
public:
|
||||
using OnNewFramePresentedCB = base::OnceClosure;
|
||||
|
||||
@@ -76,6 +72,7 @@ class MODULES_EXPORT WebMediaPlayerMSCompositor
|
||||
std::unique_ptr<WebVideoFrameSubmitter> submitter,
|
||||
bool use_surface_layer,
|
||||
const base::WeakPtr<WebMediaPlayerMS>& player);
|
||||
+ ~WebMediaPlayerMSCompositor() override;
|
||||
|
||||
WebMediaPlayerMSCompositor(const WebMediaPlayerMSCompositor&) = delete;
|
||||
WebMediaPlayerMSCompositor& operator=(const WebMediaPlayerMSCompositor&) =
|
||||
@@ -143,10 +140,7 @@ class MODULES_EXPORT WebMediaPlayerMSCompositor
|
||||
Metadata GetMetadata();
|
||||
|
||||
private:
|
||||
- friend class WTF::ThreadSafeRefCounted<WebMediaPlayerMSCompositor,
|
||||
- WebMediaPlayerMSCompositorTraits>;
|
||||
friend class WebMediaPlayerMSTest;
|
||||
- friend struct WebMediaPlayerMSCompositorTraits;
|
||||
|
||||
// Struct used to keep information about frames pending in
|
||||
// |rendering_frame_buffer_|.
|
||||
@@ -157,8 +151,6 @@ class MODULES_EXPORT WebMediaPlayerMSCompositor
|
||||
bool is_copy;
|
||||
};
|
||||
|
||||
- ~WebMediaPlayerMSCompositor() override;
|
||||
-
|
||||
// Ran on the |video_frame_compositor_task_runner_| to initialize
|
||||
// |submitter_|
|
||||
void InitializeSubmitter();
|
||||
@@ -204,7 +196,6 @@ class MODULES_EXPORT WebMediaPlayerMSCompositor
|
||||
|
||||
void StartRenderingInternal();
|
||||
void StopRenderingInternal();
|
||||
- void ReplaceCurrentFrameWithACopyInternal();
|
||||
|
||||
void SetAlgorithmEnabledForTesting(bool algorithm_enabled);
|
||||
void RecordFrameDisplayedStats(base::TimeTicks frame_displayed_time);
|
||||
@@ -314,15 +305,10 @@ class MODULES_EXPORT WebMediaPlayerMSCompositor
|
||||
// |dropped_frame_count_|, |current_metadata_| and |render_started_|.
|
||||
base::Lock current_frame_lock_;
|
||||
|
||||
+ base::WeakPtr<WebMediaPlayerMSCompositor> weak_this_;
|
||||
base::WeakPtrFactory<WebMediaPlayerMSCompositor> weak_ptr_factory_{this};
|
||||
};
|
||||
|
||||
-struct WebMediaPlayerMSCompositorTraits {
|
||||
- // Ensure destruction occurs on main thread so that "Web" and other resources
|
||||
- // are destroyed on the correct thread.
|
||||
- static void Destruct(const WebMediaPlayerMSCompositor* player);
|
||||
-};
|
||||
-
|
||||
} // namespace blink
|
||||
|
||||
#endif // THIRD_PARTY_BLINK_RENDERER_MODULES_MEDIASTREAM_WEBMEDIAPLAYER_MS_COMPOSITOR_H_
|
||||
@@ -0,0 +1,124 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Dale Curtis <dalecurtis@chromium.org>
|
||||
Date: Mon, 20 Feb 2023 10:08:49 +0000
|
||||
Subject: Simplify WebMediaPlayerMSCompositor destruction.
|
||||
|
||||
The code was only sometimes calling StopUsingProvider() and posted
|
||||
the submitter destruction unnecessarily.
|
||||
|
||||
Destruction now works the same as in VideoFrameCompositor, where the
|
||||
class itself is responsible for calling StopUsingProvider() during
|
||||
its own destruction.
|
||||
|
||||
(cherry picked from commit cbd238e85903b7d94910bd2c6362ff9abf9908cc)
|
||||
|
||||
Fixed: 1407701
|
||||
Disallow-Recycled-Builds: test-failures
|
||||
Change-Id: Ia649cb5532519468eea34e12745ed9c990580d82
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/4195824
|
||||
Auto-Submit: Dale Curtis <dalecurtis@chromium.org>
|
||||
Commit-Queue: Tony Herre <toprice@chromium.org>
|
||||
Cr-Original-Commit-Position: refs/heads/main@{#1098505}
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/4225498
|
||||
Reviewed-by: Oleh Lamzin <lamzin@google.com>
|
||||
Owners-Override: Oleh Lamzin <lamzin@google.com>
|
||||
Commit-Queue: Roger Felipe Zanoni da Silva <rzanoni@google.com>
|
||||
Cr-Commit-Position: refs/branch-heads/5359@{#1391}
|
||||
Cr-Branched-From: 27d3765d341b09369006d030f83f582a29eb57ae-refs/heads/main@{#1058933}
|
||||
|
||||
diff --git a/third_party/blink/renderer/modules/mediastream/webmediaplayer_ms.cc b/third_party/blink/renderer/modules/mediastream/webmediaplayer_ms.cc
|
||||
index 6079ca1dd6248654e3cdf7aa52bcd39c9f15ed08..5b075cc0acecf71097549b0cbfb044fa4766e851 100644
|
||||
--- a/third_party/blink/renderer/modules/mediastream/webmediaplayer_ms.cc
|
||||
+++ b/third_party/blink/renderer/modules/mediastream/webmediaplayer_ms.cc
|
||||
@@ -412,9 +412,6 @@ WebMediaPlayerMS::~WebMediaPlayerMS() {
|
||||
if (frame_deliverer_)
|
||||
io_task_runner_->DeleteSoon(FROM_HERE, frame_deliverer_.release());
|
||||
|
||||
- if (compositor_)
|
||||
- compositor_->StopUsingProvider();
|
||||
-
|
||||
if (video_frame_provider_)
|
||||
video_frame_provider_->Stop();
|
||||
|
||||
diff --git a/third_party/blink/renderer/modules/mediastream/webmediaplayer_ms_compositor.cc b/third_party/blink/renderer/modules/mediastream/webmediaplayer_ms_compositor.cc
|
||||
index 146613e57db9a5747e45b686336eae3a8b2f7978..2be89c9104c493d2672436fb8d36d6f10e4f6939 100644
|
||||
--- a/third_party/blink/renderer/modules/mediastream/webmediaplayer_ms_compositor.cc
|
||||
+++ b/third_party/blink/renderer/modules/mediastream/webmediaplayer_ms_compositor.cc
|
||||
@@ -236,13 +236,8 @@ WebMediaPlayerMSCompositor::WebMediaPlayerMSCompositor(
|
||||
WebMediaPlayerMSCompositor::~WebMediaPlayerMSCompositor() {
|
||||
// Ensured by destructor traits.
|
||||
DCHECK(video_frame_compositor_task_runner_->BelongsToCurrentThread());
|
||||
-
|
||||
- if (submitter_) {
|
||||
- video_frame_compositor_task_runner_->DeleteSoon(FROM_HERE,
|
||||
- std::move(submitter_));
|
||||
- } else {
|
||||
- DCHECK(!video_frame_provider_client_)
|
||||
- << "Must call StopUsingProvider() before dtor!";
|
||||
+ if (video_frame_provider_client_) {
|
||||
+ video_frame_provider_client_->StopUsingProvider();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -262,7 +257,7 @@ void WebMediaPlayerMSCompositorTraits::Destruct(
|
||||
|
||||
void WebMediaPlayerMSCompositor::InitializeSubmitter() {
|
||||
DCHECK(video_frame_compositor_task_runner_->BelongsToCurrentThread());
|
||||
- submitter_->Initialize(this, /* is_media_stream = */ true);
|
||||
+ submitter_->Initialize(this, /*is_media_stream=*/true);
|
||||
}
|
||||
|
||||
void WebMediaPlayerMSCompositor::SetIsSurfaceVisible(
|
||||
@@ -629,15 +624,6 @@ void WebMediaPlayerMSCompositor::ReplaceCurrentFrameWithACopy() {
|
||||
WrapRefCounted(this))));
|
||||
}
|
||||
|
||||
-void WebMediaPlayerMSCompositor::StopUsingProvider() {
|
||||
- DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
|
||||
- PostCrossThreadTask(
|
||||
- *video_frame_compositor_task_runner_, FROM_HERE,
|
||||
- CrossThreadBindOnce(
|
||||
- &WebMediaPlayerMSCompositor::StopUsingProviderInternal,
|
||||
- WrapRefCounted(this)));
|
||||
-}
|
||||
-
|
||||
bool WebMediaPlayerMSCompositor::MapTimestampsToRenderTimeTicks(
|
||||
const std::vector<base::TimeDelta>& timestamps,
|
||||
std::vector<base::TimeTicks>* wall_clock_times) {
|
||||
@@ -874,13 +860,6 @@ void WebMediaPlayerMSCompositor::StopRenderingInternal() {
|
||||
video_frame_provider_client_->StopRendering();
|
||||
}
|
||||
|
||||
-void WebMediaPlayerMSCompositor::StopUsingProviderInternal() {
|
||||
- DCHECK(video_frame_compositor_task_runner_->BelongsToCurrentThread());
|
||||
- if (video_frame_provider_client_)
|
||||
- video_frame_provider_client_->StopUsingProvider();
|
||||
- video_frame_provider_client_ = nullptr;
|
||||
-}
|
||||
-
|
||||
void WebMediaPlayerMSCompositor::ReplaceCurrentFrameWithACopyInternal() {
|
||||
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
|
||||
scoped_refptr<media::VideoFrame> current_frame_ref;
|
||||
diff --git a/third_party/blink/renderer/modules/mediastream/webmediaplayer_ms_compositor.h b/third_party/blink/renderer/modules/mediastream/webmediaplayer_ms_compositor.h
|
||||
index 603f9c50cc8383dcba68b522231dfa493c0d179e..a8565180d57a80f596bbd28690c7c6ceefe6474b 100644
|
||||
--- a/third_party/blink/renderer/modules/mediastream/webmediaplayer_ms_compositor.h
|
||||
+++ b/third_party/blink/renderer/modules/mediastream/webmediaplayer_ms_compositor.h
|
||||
@@ -119,10 +119,6 @@ class MODULES_EXPORT WebMediaPlayerMSCompositor
|
||||
void StopRendering();
|
||||
void ReplaceCurrentFrameWithACopy();
|
||||
|
||||
- // Tell |video_frame_provider_client_| to stop using this instance in
|
||||
- // preparation for dtor.
|
||||
- void StopUsingProvider();
|
||||
-
|
||||
// Sets a hook to be notified when a new frame is presented, to fulfill a
|
||||
// prending video.requestAnimationFrame() request.
|
||||
// Can be called from any thread.
|
||||
@@ -208,7 +204,6 @@ class MODULES_EXPORT WebMediaPlayerMSCompositor
|
||||
|
||||
void StartRenderingInternal();
|
||||
void StopRenderingInternal();
|
||||
- void StopUsingProviderInternal();
|
||||
void ReplaceCurrentFrameWithACopyInternal();
|
||||
|
||||
void SetAlgorithmEnabledForTesting(bool algorithm_enabled);
|
||||
@@ -0,0 +1,536 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Ken Rockot <rockot@google.com>
|
||||
Date: Thu, 10 Nov 2022 03:24:17 +0000
|
||||
Subject: Mojo: Disable sync call interrupts in the browser
|
||||
|
||||
This changes the default Mojo sync call behavior in the browser process
|
||||
to prevent any blocking sync calls from being interrupted by other
|
||||
incoming sync IPC dispatches.
|
||||
|
||||
(cherry picked from commit b6f921260e0e763db7a72de9c7a3f0f78a99f21f)
|
||||
|
||||
Bug: 1376099
|
||||
Change-Id: I53681ef379fdd3c2bfc37d7e16b3de17acad5d20
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3989408
|
||||
Commit-Queue: Ken Rockot <rockot@google.com>
|
||||
Reviewed-by: Daniel Cheng <dcheng@chromium.org>
|
||||
Cr-Original-Commit-Position: refs/heads/main@{#1065369}
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/4018257
|
||||
Commit-Queue: Daniel Cheng <dcheng@chromium.org>
|
||||
Auto-Submit: Daniel Cheng <dcheng@chromium.org>
|
||||
Reviewed-by: Ken Rockot <rockot@google.com>
|
||||
Commit-Queue: Rubber Stamper <rubber-stamper@appspot.gserviceaccount.com>
|
||||
Bot-Commit: Rubber Stamper <rubber-stamper@appspot.gserviceaccount.com>
|
||||
Cr-Commit-Position: refs/branch-heads/5359@{#719}
|
||||
Cr-Branched-From: 27d3765d341b09369006d030f83f582a29eb57ae-refs/heads/main@{#1058933}
|
||||
|
||||
diff --git a/content/app/content_main_runner_impl.cc b/content/app/content_main_runner_impl.cc
|
||||
index a3e5764a1920c8a6bf1ce21e02d0ac743b027a40..ce8b70cc792b2ae45624840e0f71270f85f00836 100644
|
||||
--- a/content/app/content_main_runner_impl.cc
|
||||
+++ b/content/app/content_main_runner_impl.cc
|
||||
@@ -93,6 +93,7 @@
|
||||
#include "media/media_buildflags.h"
|
||||
#include "mojo/core/embedder/embedder.h"
|
||||
#include "mojo/public/cpp/bindings/self_owned_receiver.h"
|
||||
+#include "mojo/public/cpp/bindings/sync_call_restrictions.h"
|
||||
#include "mojo/public/cpp/platform/platform_channel.h"
|
||||
#include "mojo/public/cpp/system/dynamic_library_support.h"
|
||||
#include "mojo/public/cpp/system/invitation.h"
|
||||
@@ -1083,6 +1084,11 @@ int ContentMainRunnerImpl::RunBrowser(MainFunctionParams main_params,
|
||||
if (is_browser_main_loop_started_)
|
||||
return -1;
|
||||
|
||||
+ if (!base::CommandLine::ForCurrentProcess()->HasSwitch(
|
||||
+ switches::kSingleProcess)) {
|
||||
+ mojo::SyncCallRestrictions::DisableSyncCallInterrupts();
|
||||
+ }
|
||||
+
|
||||
if (!mojo_ipc_support_) {
|
||||
const ContentMainDelegate::InvokedInBrowserProcess invoked_in_browser{
|
||||
.is_running_test = !main_params.ui_task.is_null()};
|
||||
diff --git a/ipc/ipc_mojo_bootstrap.cc b/ipc/ipc_mojo_bootstrap.cc
|
||||
index eb8fa358b0a72eea2e294c531549da5fc81f394c..8c13ef236ba6f7cf05584cffba522a3cb54536c9 100644
|
||||
--- a/ipc/ipc_mojo_bootstrap.cc
|
||||
+++ b/ipc/ipc_mojo_bootstrap.cc
|
||||
@@ -16,13 +16,15 @@
|
||||
#include "base/bind.h"
|
||||
#include "base/callback.h"
|
||||
#include "base/check_op.h"
|
||||
+#include "base/containers/circular_deque.h"
|
||||
#include "base/containers/contains.h"
|
||||
-#include "base/containers/queue.h"
|
||||
#include "base/memory/ptr_util.h"
|
||||
#include "base/memory/raw_ptr.h"
|
||||
#include "base/no_destructor.h"
|
||||
+#include "base/ranges/algorithm.h"
|
||||
#include "base/strings/stringprintf.h"
|
||||
#include "base/synchronization/lock.h"
|
||||
+#include "base/synchronization/waitable_event.h"
|
||||
#include "base/task/common/task_annotator.h"
|
||||
#include "base/task/sequenced_task_runner.h"
|
||||
#include "base/task/single_thread_task_runner.h"
|
||||
@@ -48,6 +50,7 @@
|
||||
#include "mojo/public/cpp/bindings/pipe_control_message_proxy.h"
|
||||
#include "mojo/public/cpp/bindings/sequence_local_sync_event_watcher.h"
|
||||
#include "mojo/public/cpp/bindings/tracing_helpers.h"
|
||||
+#include "third_party/abseil-cpp/absl/types/optional.h"
|
||||
|
||||
namespace IPC {
|
||||
|
||||
@@ -466,6 +469,11 @@ class ChannelAssociatedGroupController
|
||||
return *this;
|
||||
}
|
||||
|
||||
+ bool HasRequestId(uint64_t request_id) {
|
||||
+ return !value_.IsNull() && value_.version() >= 1 &&
|
||||
+ value_.header_v1()->request_id == request_id;
|
||||
+ }
|
||||
+
|
||||
mojo::Message& value() { return value_; }
|
||||
|
||||
private:
|
||||
@@ -557,10 +565,15 @@ class ChannelAssociatedGroupController
|
||||
sync_watcher_.reset();
|
||||
}
|
||||
|
||||
- uint32_t EnqueueSyncMessage(MessageWrapper message) {
|
||||
+ absl::optional<uint32_t> EnqueueSyncMessage(MessageWrapper message) {
|
||||
controller_->lock_.AssertAcquired();
|
||||
+ if (exclusive_wait_ && exclusive_wait_->TryFulfillingWith(message)) {
|
||||
+ exclusive_wait_ = nullptr;
|
||||
+ return absl::nullopt;
|
||||
+ }
|
||||
+
|
||||
uint32_t id = GenerateSyncMessageId();
|
||||
- sync_messages_.emplace(id, std::move(message));
|
||||
+ sync_messages_.emplace_back(id, std::move(message));
|
||||
SignalSyncMessageEvent();
|
||||
return id;
|
||||
}
|
||||
@@ -577,7 +590,7 @@ class ChannelAssociatedGroupController
|
||||
if (sync_messages_.empty() || sync_messages_.front().first != id)
|
||||
return MessageWrapper();
|
||||
MessageWrapper message = std::move(sync_messages_.front().second);
|
||||
- sync_messages_.pop();
|
||||
+ sync_messages_.pop_front();
|
||||
return message;
|
||||
}
|
||||
|
||||
@@ -607,10 +620,38 @@ class ChannelAssociatedGroupController
|
||||
return sync_watcher_->SyncWatch(&should_stop);
|
||||
}
|
||||
|
||||
+ MessageWrapper WaitForIncomingSyncReply(uint64_t request_id) {
|
||||
+ absl::optional<ExclusiveSyncWait> wait;
|
||||
+ {
|
||||
+ base::AutoLock lock(controller_->lock_);
|
||||
+ for (auto& [id, message] : sync_messages_) {
|
||||
+ if (message.HasRequestId(request_id)) {
|
||||
+ return std::move(message);
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ DCHECK(!exclusive_wait_);
|
||||
+ wait.emplace(request_id);
|
||||
+ exclusive_wait_ = &wait.value();
|
||||
+ }
|
||||
+
|
||||
+ wait->event.Wait();
|
||||
+ return std::move(wait->message);
|
||||
+ }
|
||||
+
|
||||
bool SyncWatchExclusive(uint64_t request_id) override {
|
||||
- // We don't support exclusive waits on Channel-associated interfaces.
|
||||
- NOTREACHED();
|
||||
- return false;
|
||||
+ MessageWrapper message = WaitForIncomingSyncReply(request_id);
|
||||
+ if (message.value().IsNull() || !client_) {
|
||||
+ return false;
|
||||
+ }
|
||||
+
|
||||
+ if (!client_->HandleIncomingMessage(&message.value())) {
|
||||
+ base::AutoLock locker(controller_->lock_);
|
||||
+ controller_->RaiseError();
|
||||
+ return false;
|
||||
+ }
|
||||
+
|
||||
+ return true;
|
||||
}
|
||||
|
||||
void RegisterExternalSyncWaiter(uint64_t request_id) override {}
|
||||
@@ -624,6 +665,9 @@ class ChannelAssociatedGroupController
|
||||
DCHECK(closed_);
|
||||
DCHECK(peer_closed_);
|
||||
DCHECK(!sync_watcher_);
|
||||
+ if (exclusive_wait_) {
|
||||
+ exclusive_wait_->event.Signal();
|
||||
+ }
|
||||
}
|
||||
|
||||
void OnSyncMessageEventReady() {
|
||||
@@ -640,7 +684,7 @@ class ChannelAssociatedGroupController
|
||||
if (!sync_messages_.empty()) {
|
||||
MessageWrapper message_wrapper =
|
||||
std::move(sync_messages_.front().second);
|
||||
- sync_messages_.pop();
|
||||
+ sync_messages_.pop_front();
|
||||
|
||||
bool dispatch_succeeded;
|
||||
mojo::InterfaceEndpointClient* client = client_;
|
||||
@@ -688,6 +732,28 @@ class ChannelAssociatedGroupController
|
||||
return id;
|
||||
}
|
||||
|
||||
+ // Tracks the state of a pending sync wait which excludes all other incoming
|
||||
+ // IPC on the waiting thread.
|
||||
+ struct ExclusiveSyncWait {
|
||||
+ explicit ExclusiveSyncWait(uint64_t request_id)
|
||||
+ : request_id(request_id) {}
|
||||
+ ~ExclusiveSyncWait() = default;
|
||||
+
|
||||
+ bool TryFulfillingWith(MessageWrapper& wrapper) {
|
||||
+ if (!wrapper.HasRequestId(request_id)) {
|
||||
+ return false;
|
||||
+ }
|
||||
+
|
||||
+ message = std::move(wrapper);
|
||||
+ event.Signal();
|
||||
+ return true;
|
||||
+ }
|
||||
+
|
||||
+ uint64_t request_id;
|
||||
+ base::WaitableEvent event;
|
||||
+ MessageWrapper message;
|
||||
+ };
|
||||
+
|
||||
const raw_ptr<ChannelAssociatedGroupController> controller_;
|
||||
const mojo::InterfaceId id_;
|
||||
|
||||
@@ -699,7 +765,8 @@ class ChannelAssociatedGroupController
|
||||
raw_ptr<mojo::InterfaceEndpointClient> client_ = nullptr;
|
||||
scoped_refptr<base::SequencedTaskRunner> task_runner_;
|
||||
std::unique_ptr<mojo::SequenceLocalSyncEventWatcher> sync_watcher_;
|
||||
- base::queue<std::pair<uint32_t, MessageWrapper>> sync_messages_;
|
||||
+ base::circular_deque<std::pair<uint32_t, MessageWrapper>> sync_messages_;
|
||||
+ ExclusiveSyncWait* exclusive_wait_ = nullptr;
|
||||
uint32_t next_sync_message_id_ = 0;
|
||||
};
|
||||
|
||||
@@ -932,12 +999,15 @@ class ChannelAssociatedGroupController
|
||||
// sync message queue. If the endpoint was blocking, it will dequeue the
|
||||
// message and dispatch it. Otherwise the posted |AcceptSyncMessage()|
|
||||
// call will dequeue the message and dispatch it.
|
||||
- uint32_t message_id =
|
||||
+ absl::optional<uint32_t> message_id =
|
||||
endpoint->EnqueueSyncMessage(std::move(message_wrapper));
|
||||
- task_runner->PostTask(
|
||||
- FROM_HERE,
|
||||
- base::BindOnce(&ChannelAssociatedGroupController::AcceptSyncMessage,
|
||||
- this, id, message_id));
|
||||
+ if (message_id) {
|
||||
+ task_runner->PostTask(
|
||||
+ FROM_HERE,
|
||||
+ base::BindOnce(
|
||||
+ &ChannelAssociatedGroupController::AcceptSyncMessage, this,
|
||||
+ id, *message_id));
|
||||
+ }
|
||||
return true;
|
||||
}
|
||||
|
||||
diff --git a/mojo/public/cpp/bindings/interface_endpoint_controller.h b/mojo/public/cpp/bindings/interface_endpoint_controller.h
|
||||
index 89dbe39994620148e0ef33910b7cc7baacd7cc2e..8649abe1ac9c4b964c2bf833b850aa6f898b7103 100644
|
||||
--- a/mojo/public/cpp/bindings/interface_endpoint_controller.h
|
||||
+++ b/mojo/public/cpp/bindings/interface_endpoint_controller.h
|
||||
@@ -36,6 +36,10 @@ class InterfaceEndpointController {
|
||||
// Watches the endpoint for a specific incoming sync reply. This method only
|
||||
// returns true once the reply is received, or false if the endpoint is
|
||||
// detached or destroyed beforehand.
|
||||
+ //
|
||||
+ // Unlike with SyncWatch(), no other IPCs (not even other sync IPCs) can be
|
||||
+ // dispatched to the calling thread while SyncWatchExclusive() is waiting on
|
||||
+ // the reply for `request_id`.
|
||||
virtual bool SyncWatchExclusive(uint64_t request_id) = 0;
|
||||
|
||||
// Notifies the controller that a specific in-flight sync message identified
|
||||
diff --git a/mojo/public/cpp/bindings/lib/interface_endpoint_client.cc b/mojo/public/cpp/bindings/lib/interface_endpoint_client.cc
|
||||
index 1830df7354d7dfa007cca97ddc346db0165098b7..c4ddc89cd9d0894814d64856179539f0d757a388 100644
|
||||
--- a/mojo/public/cpp/bindings/lib/interface_endpoint_client.cc
|
||||
+++ b/mojo/public/cpp/bindings/lib/interface_endpoint_client.cc
|
||||
@@ -389,7 +389,9 @@ void ThreadSafeInterfaceEndpointClientProxy::SendMessageWithResponder(
|
||||
}
|
||||
|
||||
// If the Remote is bound on another sequence, post the call.
|
||||
- const bool allow_interrupt = !message.has_flag(Message::kFlagNoInterrupt);
|
||||
+ const bool allow_interrupt =
|
||||
+ SyncCallRestrictions::AreSyncCallInterruptsEnabled() &&
|
||||
+ !message.has_flag(Message::kFlagNoInterrupt);
|
||||
auto response = base::MakeRefCounted<SyncResponseInfo>();
|
||||
auto response_signaler = std::make_unique<SyncResponseSignaler>(response);
|
||||
task_runner_->PostTask(
|
||||
@@ -627,7 +629,9 @@ bool InterfaceEndpointClient::SendMessageWithResponder(
|
||||
|
||||
const uint32_t message_name = message->name();
|
||||
const bool is_sync = message->has_flag(Message::kFlagIsSync);
|
||||
- const bool exclusive_wait = message->has_flag(Message::kFlagNoInterrupt);
|
||||
+ const bool exclusive_wait =
|
||||
+ message->has_flag(Message::kFlagNoInterrupt) ||
|
||||
+ !SyncCallRestrictions::AreSyncCallInterruptsEnabled();
|
||||
if (!controller_->SendMessage(message))
|
||||
return false;
|
||||
|
||||
diff --git a/mojo/public/cpp/bindings/lib/sync_call_restrictions.cc b/mojo/public/cpp/bindings/lib/sync_call_restrictions.cc
|
||||
index 329901dec12572e8d8833eba33ad1cc793919084..6242391074ee6279cfea29cf1e73ac4ef874445a 100644
|
||||
--- a/mojo/public/cpp/bindings/lib/sync_call_restrictions.cc
|
||||
+++ b/mojo/public/cpp/bindings/lib/sync_call_restrictions.cc
|
||||
@@ -4,8 +4,6 @@
|
||||
|
||||
#include "mojo/public/cpp/bindings/sync_call_restrictions.h"
|
||||
|
||||
-#if ENABLE_SYNC_CALL_RESTRICTIONS
|
||||
-
|
||||
#include "base/check_op.h"
|
||||
#include "base/debug/leak_annotations.h"
|
||||
#include "base/logging.h"
|
||||
@@ -19,6 +17,11 @@ namespace mojo {
|
||||
|
||||
namespace {
|
||||
|
||||
+// Sync call interrupts are enabled by default.
|
||||
+bool g_enable_sync_call_interrupts = true;
|
||||
+
|
||||
+#if ENABLE_SYNC_CALL_RESTRICTIONS
|
||||
+
|
||||
class GlobalSyncCallSettings {
|
||||
public:
|
||||
GlobalSyncCallSettings() = default;
|
||||
@@ -61,8 +64,12 @@ bool SyncCallRestrictionsEnforceable() {
|
||||
return base::internal::SequenceLocalStorageMap::IsSetForCurrentThread();
|
||||
}
|
||||
|
||||
+#endif // ENABLE_SYNC_CALL_RESTRICTIONS
|
||||
+
|
||||
} // namespace
|
||||
|
||||
+#if ENABLE_SYNC_CALL_RESTRICTIONS
|
||||
+
|
||||
// static
|
||||
void SyncCallRestrictions::AssertSyncCallAllowed() {
|
||||
if (GetGlobalSettings().sync_call_allowed_by_default() ||
|
||||
@@ -102,6 +109,21 @@ void SyncCallRestrictions::DecreaseScopedAllowCount() {
|
||||
--GetSequenceLocalScopedAllowCount();
|
||||
}
|
||||
|
||||
-} // namespace mojo
|
||||
-
|
||||
#endif // ENABLE_SYNC_CALL_RESTRICTIONS
|
||||
+
|
||||
+// static
|
||||
+void SyncCallRestrictions::DisableSyncCallInterrupts() {
|
||||
+ g_enable_sync_call_interrupts = false;
|
||||
+}
|
||||
+
|
||||
+// static
|
||||
+void SyncCallRestrictions::EnableSyncCallInterruptsForTesting() {
|
||||
+ g_enable_sync_call_interrupts = true;
|
||||
+}
|
||||
+
|
||||
+// static
|
||||
+bool SyncCallRestrictions::AreSyncCallInterruptsEnabled() {
|
||||
+ return g_enable_sync_call_interrupts;
|
||||
+}
|
||||
+
|
||||
+} // namespace mojo
|
||||
diff --git a/mojo/public/cpp/bindings/sync_call_restrictions.h b/mojo/public/cpp/bindings/sync_call_restrictions.h
|
||||
index e7e67ee824b2a87eb14b45a3f2d76d471ff864fb..1653fd63033383b40b643c03500b26bdc65a44a6 100644
|
||||
--- a/mojo/public/cpp/bindings/sync_call_restrictions.h
|
||||
+++ b/mojo/public/cpp/bindings/sync_call_restrictions.h
|
||||
@@ -86,6 +86,20 @@ class COMPONENT_EXPORT(MOJO_CPP_BINDINGS) SyncCallRestrictions {
|
||||
static void DisallowSyncCall() {}
|
||||
#endif
|
||||
|
||||
+ // Globally disables sync call interrupts. This means that all sync calls in
|
||||
+ // the current process will be strictly blocking until a reply is received,
|
||||
+ // and no incoming sync calls can dispatch on the blocking thread in interim.
|
||||
+ static void DisableSyncCallInterrupts();
|
||||
+
|
||||
+ // Used only in tests to re-enable sync call interrupts after disabling them.
|
||||
+ static void EnableSyncCallInterruptsForTesting();
|
||||
+
|
||||
+ // Indicates whether sync call interrupts are enabled in the calling process.
|
||||
+ // They're enabled by default, so any sync message that isn't marked [Sync]
|
||||
+ // may have its blocking call interrupted to dispatch other incoming sync
|
||||
+ // IPCs which target the blocking thread.
|
||||
+ static bool AreSyncCallInterruptsEnabled();
|
||||
+
|
||||
private:
|
||||
// DO NOT ADD ANY OTHER FRIEND STATEMENTS, talk to mojo/OWNERS first.
|
||||
// BEGIN ALLOWED USAGE.
|
||||
diff --git a/mojo/public/cpp/bindings/tests/sync_method_unittest.cc b/mojo/public/cpp/bindings/tests/sync_method_unittest.cc
|
||||
index cfac737af29e653d788eb1ce7669f73ae7b320d4..d794d29df07d289d34b3b1aae9f8574fc914c050 100644
|
||||
--- a/mojo/public/cpp/bindings/tests/sync_method_unittest.cc
|
||||
+++ b/mojo/public/cpp/bindings/tests/sync_method_unittest.cc
|
||||
@@ -25,6 +25,7 @@
|
||||
#include "mojo/public/cpp/bindings/self_owned_receiver.h"
|
||||
#include "mojo/public/cpp/bindings/shared_associated_remote.h"
|
||||
#include "mojo/public/cpp/bindings/shared_remote.h"
|
||||
+#include "mojo/public/cpp/bindings/sync_call_restrictions.h"
|
||||
#include "mojo/public/cpp/bindings/tests/bindings_test_base.h"
|
||||
#include "mojo/public/cpp/bindings/tests/sync_method_unittest.test-mojom.h"
|
||||
#include "mojo/public/interfaces/bindings/tests/test_sync_methods.mojom.h"
|
||||
@@ -1563,7 +1564,144 @@ TEST_P(SyncInterruptTest, SharedAssociatedRemoteNoInterrupt) {
|
||||
EXPECT_EQ(0, same_pipe_ponger().num_sync_pongs());
|
||||
}
|
||||
|
||||
+class SyncService : public mojom::SyncService {
|
||||
+ public:
|
||||
+ explicit SyncService(PendingReceiver<mojom::SyncService> receiver)
|
||||
+ : receiver_(this, std::move(receiver)) {}
|
||||
+
|
||||
+ void SetCallHandler(base::OnceClosure call_handler) {
|
||||
+ call_handler_ = std::move(call_handler);
|
||||
+ }
|
||||
+
|
||||
+ // mojom::SyncService:
|
||||
+ void SyncCall(SyncCallCallback callback) override {
|
||||
+ std::move(callback).Run();
|
||||
+ if (call_handler_) {
|
||||
+ std::move(call_handler_).Run();
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ private:
|
||||
+ Receiver<mojom::SyncService> receiver_;
|
||||
+ base::OnceClosure call_handler_;
|
||||
+};
|
||||
+
|
||||
+class DisableSyncInterruptTest : public BindingsTestBase {
|
||||
+ public:
|
||||
+ void SetUp() override {
|
||||
+ mojo::SyncCallRestrictions::DisableSyncCallInterrupts();
|
||||
+ }
|
||||
+
|
||||
+ void TearDown() override {
|
||||
+ mojo::SyncCallRestrictions::EnableSyncCallInterruptsForTesting();
|
||||
+ }
|
||||
+};
|
||||
+
|
||||
+TEST_P(DisableSyncInterruptTest, NoInterruptWhenDisabled) {
|
||||
+ PendingRemote<mojom::SyncService> interrupter;
|
||||
+ SyncService service(interrupter.InitWithNewPipeAndPassReceiver());
|
||||
+
|
||||
+ base::RunLoop wait_for_main_thread_service_call;
|
||||
+ bool main_thread_service_called = false;
|
||||
+ service.SetCallHandler(base::BindLambdaForTesting([&] {
|
||||
+ main_thread_service_called = true;
|
||||
+ wait_for_main_thread_service_call.Quit();
|
||||
+ }));
|
||||
+
|
||||
+ Remote<mojom::SyncService> caller;
|
||||
+ base::Thread background_service_thread("SyncService");
|
||||
+ background_service_thread.Start();
|
||||
+ base::SequenceBound<SyncService> background_service{
|
||||
+ background_service_thread.task_runner(),
|
||||
+ caller.BindNewPipeAndPassReceiver()};
|
||||
+
|
||||
+ base::Thread interrupter_thread("Interrupter");
|
||||
+ interrupter_thread.Start();
|
||||
+ interrupter_thread.task_runner()->PostTask(
|
||||
+ FROM_HERE, base::BindLambdaForTesting([&interrupter] {
|
||||
+ // Issue a sync call to the SyncService on the main thread. This should
|
||||
+ // never be dispatched until *after* the sync call *from* the main
|
||||
+ // thread completes below.
|
||||
+ Remote<mojom::SyncService>(std::move(interrupter))->SyncCall();
|
||||
+ }));
|
||||
+
|
||||
+ // The key test expectation here is that `main_thread_service_called` cannot
|
||||
+ // be set to true until after SyncCall() returns and we can pump the thread's
|
||||
+ // message loop. If sync interrupts are not properly disabled, this
|
||||
+ // expectation can fail flakily (and often.)
|
||||
+ caller->SyncCall();
|
||||
+ EXPECT_FALSE(main_thread_service_called);
|
||||
+
|
||||
+ // Now the incoming sync call can be dispatched.
|
||||
+ wait_for_main_thread_service_call.Run();
|
||||
+ EXPECT_TRUE(main_thread_service_called);
|
||||
+
|
||||
+ background_service.SynchronouslyResetForTest();
|
||||
+ interrupter_thread.Stop();
|
||||
+ background_service_thread.Stop();
|
||||
+}
|
||||
+
|
||||
+TEST_P(DisableSyncInterruptTest, SharedRemoteNoInterruptWhenDisabled) {
|
||||
+ PendingRemote<mojom::SyncService> interrupter;
|
||||
+ SyncService service(interrupter.InitWithNewPipeAndPassReceiver());
|
||||
+
|
||||
+ base::RunLoop wait_for_main_thread_service_call;
|
||||
+ bool main_thread_service_called = false;
|
||||
+ service.SetCallHandler(base::BindLambdaForTesting([&] {
|
||||
+ main_thread_service_called = true;
|
||||
+ wait_for_main_thread_service_call.Quit();
|
||||
+ }));
|
||||
+
|
||||
+ // Bind a SharedRemote to another background thread so that we exercise
|
||||
+ // SharedRemote's own sync wait codepath when called into from the main
|
||||
+ // thread.
|
||||
+ base::Thread background_client_thread("Client");
|
||||
+ background_client_thread.Start();
|
||||
+
|
||||
+ base::Thread background_service_thread("Service");
|
||||
+ background_service_thread.Start();
|
||||
+
|
||||
+ SharedRemote<mojom::SyncService> caller;
|
||||
+ base::SequenceBound<SyncService> background_service{
|
||||
+ background_service_thread.task_runner(),
|
||||
+ caller.BindNewPipeAndPassReceiver(
|
||||
+ background_client_thread.task_runner())};
|
||||
+
|
||||
+ base::Thread interrupter_thread("Interrupter");
|
||||
+ interrupter_thread.Start();
|
||||
+ interrupter_thread.task_runner()->PostTask(
|
||||
+ FROM_HERE, base::BindLambdaForTesting([&interrupter] {
|
||||
+ // Issue a sync call to the SyncService on the main thread. This should
|
||||
+ // never be dispatched until *after* the sync call *from* the main
|
||||
+ // thread completes below.
|
||||
+ Remote<mojom::SyncService>(std::move(interrupter))->SyncCall();
|
||||
+ }));
|
||||
+
|
||||
+ // The key test expectation here is that `main_thread_service_called` cannot
|
||||
+ // be set to true until after SyncCall() returns and we can pump the thread's
|
||||
+ // message loop. If sync interrupts are not properly disabled, this
|
||||
+ // expectation can fail flakily (and often.)
|
||||
+ caller->SyncCall();
|
||||
+ EXPECT_FALSE(main_thread_service_called);
|
||||
+
|
||||
+ // Now the incoming sync call can be dispatched.
|
||||
+ wait_for_main_thread_service_call.Run();
|
||||
+ EXPECT_TRUE(main_thread_service_called);
|
||||
+
|
||||
+ background_service.SynchronouslyResetForTest();
|
||||
+
|
||||
+ // We need to reset the SharedRemote before the client thread is stopped, to
|
||||
+ // ensure the necessary teardown work is executed on that thread. Otherwise
|
||||
+ // the underlying pipe and related state will leak, and ASan will complain.
|
||||
+ caller.reset();
|
||||
+
|
||||
+ interrupter_thread.Stop();
|
||||
+ background_service_thread.Stop();
|
||||
+ background_client_thread.Stop();
|
||||
+}
|
||||
+
|
||||
INSTANTIATE_MOJO_BINDINGS_TEST_SUITE_P(SyncInterruptTest);
|
||||
+INSTANTIATE_MOJO_BINDINGS_TEST_SUITE_P(DisableSyncInterruptTest);
|
||||
|
||||
} // namespace
|
||||
} // namespace sync_method_unittest
|
||||
diff --git a/mojo/public/cpp/bindings/tests/sync_method_unittest.test-mojom b/mojo/public/cpp/bindings/tests/sync_method_unittest.test-mojom
|
||||
index 383b54f3ab654d664192522c061058b29fd0509a..951442b3585ad22f936568e211ad41f8ae358705 100644
|
||||
--- a/mojo/public/cpp/bindings/tests/sync_method_unittest.test-mojom
|
||||
+++ b/mojo/public/cpp/bindings/tests/sync_method_unittest.test-mojom
|
||||
@@ -45,3 +45,7 @@ interface Ponger {
|
||||
[Sync] Pong() => ();
|
||||
PongAsync();
|
||||
};
|
||||
+
|
||||
+interface SyncService {
|
||||
+ [Sync] SyncCall() => ();
|
||||
+};
|
||||
@@ -0,0 +1,946 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Daniel Cheng <dcheng@chromium.org>
|
||||
Date: Sat, 12 Nov 2022 00:27:56 +0000
|
||||
Subject: Validate that a message is allowed to use the sync flag.
|
||||
|
||||
This changes consists of several coordinated changes:
|
||||
- The C++ bindings generator now emits an array of method ordinals that
|
||||
are allowed to use sync calls, but only if any method has a [Sync]
|
||||
annotation. This is intended to minimize the code cost to interfaces
|
||||
that do not have any sync methods (i.e. most of them).
|
||||
- The C++ binding endpoints (mojo::Receiver, et cetera) now plumb the
|
||||
array of sync-allowed ordinals to the InterfaceEndpointClient.
|
||||
- Processing an incoming message checks if the incoming message is
|
||||
allowed to use the sync flag by filtering it against the array of
|
||||
sync-allowed ordinals that was previously passed to the
|
||||
InterfaceEndpointClient.
|
||||
|
||||
This also fixes an incorrect forward declaration of ValidationContext in
|
||||
the generated bindings that discovered in the process of writing the
|
||||
test.
|
||||
|
||||
(cherry picked from commit 4365dddb49847a422bce674383b4aa4f38ff9e89)
|
||||
|
||||
Bug: 1376099
|
||||
Change-Id: Icb5864dcab96ccd18c98b4cc6ade7cdef39e209f
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3994146
|
||||
Reviewed-by: Ken Rockot <rockot@google.com>
|
||||
Commit-Queue: Daniel Cheng <dcheng@chromium.org>
|
||||
Cr-Original-Commit-Position: refs/heads/main@{#1067894}
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/4018151
|
||||
Auto-Submit: Daniel Cheng <dcheng@chromium.org>
|
||||
Commit-Queue: Ken Rockot <rockot@google.com>
|
||||
Cr-Commit-Position: refs/branch-heads/5359@{#774}
|
||||
Cr-Branched-From: 27d3765d341b09369006d030f83f582a29eb57ae-refs/heads/main@{#1058933}
|
||||
|
||||
diff --git a/mojo/public/cpp/bindings/BUILD.gn b/mojo/public/cpp/bindings/BUILD.gn
|
||||
index 2c27474d1200f80ff7abc773eaafdc9d30494f58..de587d8759f2e850ef9de355551c4be12f3ca6e7 100644
|
||||
--- a/mojo/public/cpp/bindings/BUILD.gn
|
||||
+++ b/mojo/public/cpp/bindings/BUILD.gn
|
||||
@@ -183,6 +183,7 @@ component("bindings") {
|
||||
"lib/sync_event_watcher.cc",
|
||||
"lib/sync_handle_registry.cc",
|
||||
"lib/sync_handle_watcher.cc",
|
||||
+ "lib/sync_method_traits.h",
|
||||
"lib/task_runner_helper.cc",
|
||||
"lib/task_runner_helper.h",
|
||||
"lib/thread_safe_forwarder_base.cc",
|
||||
diff --git a/mojo/public/cpp/bindings/associated_receiver.h b/mojo/public/cpp/bindings/associated_receiver.h
|
||||
index 8731b179fecfa212c3c802fb5e57189e97d782e6..220c0355a45362bdb018e335a1cb0e8e4a4abd96 100644
|
||||
--- a/mojo/public/cpp/bindings/associated_receiver.h
|
||||
+++ b/mojo/public/cpp/bindings/associated_receiver.h
|
||||
@@ -5,15 +5,19 @@
|
||||
#ifndef MOJO_PUBLIC_CPP_BINDINGS_ASSOCIATED_RECEIVER_H_
|
||||
#define MOJO_PUBLIC_CPP_BINDINGS_ASSOCIATED_RECEIVER_H_
|
||||
|
||||
+#include <stdint.h>
|
||||
+
|
||||
#include <memory>
|
||||
#include <utility>
|
||||
|
||||
#include "base/check.h"
|
||||
+#include "base/containers/span.h"
|
||||
#include "base/memory/ptr_util.h"
|
||||
#include "base/memory/scoped_refptr.h"
|
||||
#include "base/memory/weak_ptr.h"
|
||||
#include "base/strings/string_piece.h"
|
||||
#include "base/task/sequenced_task_runner.h"
|
||||
+#include "mojo/public/cpp/bindings/lib/sync_method_traits.h"
|
||||
#include "mojo/public/cpp/bindings/pending_associated_receiver.h"
|
||||
#include "mojo/public/cpp/bindings/pending_associated_remote.h"
|
||||
#include "mojo/public/cpp/bindings/raw_ptr_impl_ref_traits.h"
|
||||
@@ -60,7 +64,7 @@ class COMPONENT_EXPORT(MOJO_CPP_BINDINGS) AssociatedReceiverBase {
|
||||
void BindImpl(ScopedInterfaceEndpointHandle handle,
|
||||
MessageReceiverWithResponderStatus* receiver,
|
||||
std::unique_ptr<MessageReceiver> payload_validator,
|
||||
- bool expect_sync_requests,
|
||||
+ base::span<const uint32_t> sync_method_ordinals,
|
||||
scoped_refptr<base::SequencedTaskRunner> runner,
|
||||
uint32_t interface_version,
|
||||
const char* interface_name,
|
||||
@@ -201,8 +205,8 @@ class AssociatedReceiver : public internal::AssociatedReceiverBase {
|
||||
if (pending_receiver) {
|
||||
BindImpl(pending_receiver.PassHandle(), &stub_,
|
||||
base::WrapUnique(new typename Interface::RequestValidator_()),
|
||||
- Interface::HasSyncMethods_, std::move(task_runner),
|
||||
- Interface::Version_, Interface::Name_,
|
||||
+ internal::SyncMethodTraits<Interface>::GetOrdinals(),
|
||||
+ std::move(task_runner), Interface::Version_, Interface::Name_,
|
||||
Interface::MessageToMethodInfo_,
|
||||
Interface::MessageToMethodName_);
|
||||
} else {
|
||||
diff --git a/mojo/public/cpp/bindings/interface_endpoint_client.h b/mojo/public/cpp/bindings/interface_endpoint_client.h
|
||||
index cd79a5edb3f939623b874db36542ee651113c164..d746b1473d95a367f47e309049e85241bdba095b 100644
|
||||
--- a/mojo/public/cpp/bindings/interface_endpoint_client.h
|
||||
+++ b/mojo/public/cpp/bindings/interface_endpoint_client.h
|
||||
@@ -13,6 +13,7 @@
|
||||
|
||||
#include "base/callback.h"
|
||||
#include "base/component_export.h"
|
||||
+#include "base/containers/span.h"
|
||||
#include "base/dcheck_is_on.h"
|
||||
#include "base/location.h"
|
||||
#include "base/memory/raw_ptr.h"
|
||||
@@ -56,7 +57,7 @@ class COMPONENT_EXPORT(MOJO_CPP_BINDINGS) InterfaceEndpointClient
|
||||
InterfaceEndpointClient(ScopedInterfaceEndpointHandle handle,
|
||||
MessageReceiverWithResponderStatus* receiver,
|
||||
std::unique_ptr<MessageReceiver> payload_validator,
|
||||
- bool expect_sync_requests,
|
||||
+ base::span<const uint32_t> sync_method_ordinals,
|
||||
scoped_refptr<base::SequencedTaskRunner> task_runner,
|
||||
uint32_t interface_version,
|
||||
const char* interface_name,
|
||||
@@ -220,6 +221,10 @@ class COMPONENT_EXPORT(MOJO_CPP_BINDINGS) InterfaceEndpointClient
|
||||
// The router lock must be held when calling this.
|
||||
void ForgetAsyncRequest(uint64_t request_id);
|
||||
|
||||
+ base::span<const uint32_t> sync_method_ordinals() const {
|
||||
+ return sync_method_ordinals_;
|
||||
+ }
|
||||
+
|
||||
private:
|
||||
struct PendingAsyncResponse {
|
||||
public:
|
||||
@@ -281,7 +286,7 @@ class COMPONENT_EXPORT(MOJO_CPP_BINDINGS) InterfaceEndpointClient
|
||||
|
||||
bool HandleValidatedMessage(Message* message);
|
||||
|
||||
- const bool expect_sync_requests_ = false;
|
||||
+ const base::span<const uint32_t> sync_method_ordinals_;
|
||||
|
||||
// The callback to invoke when our peer endpoint sends us NotifyIdle and we
|
||||
// have no outstanding unacked messages. If null, no callback has been set and
|
||||
diff --git a/mojo/public/cpp/bindings/lib/associated_interface_ptr_state.cc b/mojo/public/cpp/bindings/lib/associated_interface_ptr_state.cc
|
||||
index 0be4148158a0d779770cba9c6cc2204d957e753d..5a23491320fbcf28db67511309dde641c4439837 100644
|
||||
--- a/mojo/public/cpp/bindings/lib/associated_interface_ptr_state.cc
|
||||
+++ b/mojo/public/cpp/bindings/lib/associated_interface_ptr_state.cc
|
||||
@@ -4,6 +4,11 @@
|
||||
|
||||
#include "mojo/public/cpp/bindings/lib/associated_interface_ptr_state.h"
|
||||
|
||||
+#include <stdint.h>
|
||||
+
|
||||
+#include <utility>
|
||||
+
|
||||
+#include "base/containers/span.h"
|
||||
#include "mojo/public/cpp/bindings/lib/task_runner_helper.h"
|
||||
|
||||
namespace mojo {
|
||||
@@ -70,7 +75,8 @@ void AssociatedInterfacePtrStateBase::Bind(
|
||||
// The version is only queried from the client so the value passed here
|
||||
// will not be used.
|
||||
endpoint_client_ = std::make_unique<InterfaceEndpointClient>(
|
||||
- std::move(handle), nullptr, std::move(validator), false,
|
||||
+ std::move(handle), nullptr, std::move(validator),
|
||||
+ /*sync_method_ordinals=*/base::span<const uint32_t>(),
|
||||
GetTaskRunnerToUseFromUserProvidedTaskRunner(std::move(runner)), 0u,
|
||||
interface_name, method_info_callback, method_name_callback);
|
||||
}
|
||||
diff --git a/mojo/public/cpp/bindings/lib/associated_interface_ptr_state.h b/mojo/public/cpp/bindings/lib/associated_interface_ptr_state.h
|
||||
index 5ac4091604df3054f5f678f97c39c1fb133346d3..67cc5b07c18375ea7f58cda223766b9fe8c5e4e0 100644
|
||||
--- a/mojo/public/cpp/bindings/lib/associated_interface_ptr_state.h
|
||||
+++ b/mojo/public/cpp/bindings/lib/associated_interface_ptr_state.h
|
||||
@@ -141,6 +141,10 @@ class AssociatedInterfacePtrState : public AssociatedInterfacePtrStateBase {
|
||||
return info;
|
||||
}
|
||||
|
||||
+ InterfaceEndpointClient* endpoint_client_for_test() {
|
||||
+ return endpoint_client();
|
||||
+ }
|
||||
+
|
||||
private:
|
||||
std::unique_ptr<Proxy> proxy_;
|
||||
};
|
||||
diff --git a/mojo/public/cpp/bindings/lib/associated_receiver.cc b/mojo/public/cpp/bindings/lib/associated_receiver.cc
|
||||
index a25df8c6127e0c0f2fd398bb5e7dafe4be23aa94..c450ef2d9d0e66ba0ce66458c29d1ce616c5740e 100644
|
||||
--- a/mojo/public/cpp/bindings/lib/associated_receiver.cc
|
||||
+++ b/mojo/public/cpp/bindings/lib/associated_receiver.cc
|
||||
@@ -64,7 +64,7 @@ void AssociatedReceiverBase::BindImpl(
|
||||
ScopedInterfaceEndpointHandle handle,
|
||||
MessageReceiverWithResponderStatus* receiver,
|
||||
std::unique_ptr<MessageReceiver> payload_validator,
|
||||
- bool expect_sync_requests,
|
||||
+ base::span<const uint32_t> sync_method_ordinals,
|
||||
scoped_refptr<base::SequencedTaskRunner> runner,
|
||||
uint32_t interface_version,
|
||||
const char* interface_name,
|
||||
@@ -74,7 +74,7 @@ void AssociatedReceiverBase::BindImpl(
|
||||
|
||||
endpoint_client_ = std::make_unique<InterfaceEndpointClient>(
|
||||
std::move(handle), receiver, std::move(payload_validator),
|
||||
- expect_sync_requests,
|
||||
+ sync_method_ordinals,
|
||||
internal::GetTaskRunnerToUseFromUserProvidedTaskRunner(std::move(runner)),
|
||||
interface_version, interface_name, method_info_callback,
|
||||
method_name_callback);
|
||||
diff --git a/mojo/public/cpp/bindings/lib/binding_state.cc b/mojo/public/cpp/bindings/lib/binding_state.cc
|
||||
index 227727f170964cc761a358323272bb1e3123951d..e0c926b04d10364815f270a4f0e1dc542fa8370a 100644
|
||||
--- a/mojo/public/cpp/bindings/lib/binding_state.cc
|
||||
+++ b/mojo/public/cpp/bindings/lib/binding_state.cc
|
||||
@@ -107,7 +107,7 @@ void BindingStateBase::BindInternal(
|
||||
const char* interface_name,
|
||||
std::unique_ptr<MessageReceiver> request_validator,
|
||||
bool passes_associated_kinds,
|
||||
- bool has_sync_methods,
|
||||
+ base::span<const uint32_t> sync_method_ordinals,
|
||||
MessageReceiverWithResponderStatus* stub,
|
||||
uint32_t interface_version,
|
||||
MessageToMethodInfoCallback method_info_callback,
|
||||
@@ -121,7 +121,7 @@ void BindingStateBase::BindInternal(
|
||||
MultiplexRouter::Config config =
|
||||
passes_associated_kinds
|
||||
? MultiplexRouter::MULTI_INTERFACE
|
||||
- : (has_sync_methods
|
||||
+ : (!sync_method_ordinals.empty()
|
||||
? MultiplexRouter::SINGLE_INTERFACE_WITH_SYNC_METHODS
|
||||
: MultiplexRouter::SINGLE_INTERFACE);
|
||||
router_ = MultiplexRouter::CreateAndStartReceiving(
|
||||
@@ -131,7 +131,7 @@ void BindingStateBase::BindInternal(
|
||||
|
||||
endpoint_client_ = std::make_unique<InterfaceEndpointClient>(
|
||||
router_->CreateLocalEndpointHandle(kPrimaryInterfaceId), stub,
|
||||
- std::move(request_validator), has_sync_methods,
|
||||
+ std::move(request_validator), sync_method_ordinals,
|
||||
std::move(sequenced_runner), interface_version, interface_name,
|
||||
method_info_callback, method_name_callback);
|
||||
endpoint_client_->SetIdleTrackingEnabledCallback(
|
||||
diff --git a/mojo/public/cpp/bindings/lib/binding_state.h b/mojo/public/cpp/bindings/lib/binding_state.h
|
||||
index 1b33aa78a952dcfeb39c466ecd47f840896c41c4..cf1f3f377e5e6662d86720fbd7121ed69e6c9b42 100644
|
||||
--- a/mojo/public/cpp/bindings/lib/binding_state.h
|
||||
+++ b/mojo/public/cpp/bindings/lib/binding_state.h
|
||||
@@ -5,6 +5,8 @@
|
||||
#ifndef MOJO_PUBLIC_CPP_BINDINGS_LIB_BINDING_STATE_H_
|
||||
#define MOJO_PUBLIC_CPP_BINDINGS_LIB_BINDING_STATE_H_
|
||||
|
||||
+#include <stdint.h>
|
||||
+
|
||||
#include <memory>
|
||||
#include <utility>
|
||||
|
||||
@@ -12,6 +14,7 @@
|
||||
#include "base/callback.h"
|
||||
#include "base/check.h"
|
||||
#include "base/component_export.h"
|
||||
+#include "base/containers/span.h"
|
||||
#include "base/memory/ptr_util.h"
|
||||
#include "base/memory/ref_counted.h"
|
||||
#include "base/strings/string_piece.h"
|
||||
@@ -23,6 +26,7 @@
|
||||
#include "mojo/public/cpp/bindings/interface_id.h"
|
||||
#include "mojo/public/cpp/bindings/lib/multiplex_router.h"
|
||||
#include "mojo/public/cpp/bindings/lib/pending_receiver_state.h"
|
||||
+#include "mojo/public/cpp/bindings/lib/sync_method_traits.h"
|
||||
#include "mojo/public/cpp/bindings/message_header_validator.h"
|
||||
#include "mojo/public/cpp/bindings/pending_flush.h"
|
||||
#include "mojo/public/cpp/bindings/pending_receiver.h"
|
||||
@@ -90,7 +94,7 @@ class COMPONENT_EXPORT(MOJO_CPP_BINDINGS) BindingStateBase {
|
||||
const char* interface_name,
|
||||
std::unique_ptr<MessageReceiver> request_validator,
|
||||
bool passes_associated_kinds,
|
||||
- bool has_sync_methods,
|
||||
+ base::span<const uint32_t> sync_method_ordinals,
|
||||
MessageReceiverWithResponderStatus* stub,
|
||||
uint32_t interface_version,
|
||||
MessageToMethodInfoCallback method_info_callback,
|
||||
@@ -121,9 +125,9 @@ class BindingState : public BindingStateBase {
|
||||
BindingStateBase::BindInternal(
|
||||
std::move(receiver_state), runner, Interface::Name_,
|
||||
std::make_unique<typename Interface::RequestValidator_>(),
|
||||
- Interface::PassesAssociatedKinds_, Interface::HasSyncMethods_, &stub_,
|
||||
- Interface::Version_, Interface::MessageToMethodInfo_,
|
||||
- Interface::MessageToMethodName_);
|
||||
+ Interface::PassesAssociatedKinds_,
|
||||
+ SyncMethodTraits<Interface>::GetOrdinals(), &stub_, Interface::Version_,
|
||||
+ Interface::MessageToMethodInfo_, Interface::MessageToMethodName_);
|
||||
}
|
||||
|
||||
PendingReceiver<Interface> Unbind() {
|
||||
diff --git a/mojo/public/cpp/bindings/lib/interface_endpoint_client.cc b/mojo/public/cpp/bindings/lib/interface_endpoint_client.cc
|
||||
index c4ddc89cd9d0894814d64856179539f0d757a388..1a2799f11b987b17994aa4c85bd77af571cf73e9 100644
|
||||
--- a/mojo/public/cpp/bindings/lib/interface_endpoint_client.cc
|
||||
+++ b/mojo/public/cpp/bindings/lib/interface_endpoint_client.cc
|
||||
@@ -441,13 +441,13 @@ InterfaceEndpointClient::InterfaceEndpointClient(
|
||||
ScopedInterfaceEndpointHandle handle,
|
||||
MessageReceiverWithResponderStatus* receiver,
|
||||
std::unique_ptr<MessageReceiver> payload_validator,
|
||||
- bool expect_sync_requests,
|
||||
+ base::span<const uint32_t> sync_method_ordinals,
|
||||
scoped_refptr<base::SequencedTaskRunner> task_runner,
|
||||
uint32_t interface_version,
|
||||
const char* interface_name,
|
||||
MessageToMethodInfoCallback method_info_callback,
|
||||
MessageToMethodNameCallback method_name_callback)
|
||||
- : expect_sync_requests_(expect_sync_requests),
|
||||
+ : sync_method_ordinals_(sync_method_ordinals),
|
||||
handle_(std::move(handle)),
|
||||
incoming_receiver_(receiver),
|
||||
dispatcher_(&thunk_),
|
||||
@@ -857,7 +857,8 @@ void InterfaceEndpointClient::InitControllerIfNecessary() {
|
||||
|
||||
controller_ = handle_.group_controller()->AttachEndpointClient(handle_, this,
|
||||
task_runner_);
|
||||
- if (expect_sync_requests_ && task_runner_->RunsTasksInCurrentSequence())
|
||||
+ if (!sync_method_ordinals_.empty() &&
|
||||
+ task_runner_->RunsTasksInCurrentSequence())
|
||||
controller_->AllowWokenUpBySyncWatchOnSameThread();
|
||||
}
|
||||
|
||||
diff --git a/mojo/public/cpp/bindings/lib/interface_ptr_state.cc b/mojo/public/cpp/bindings/lib/interface_ptr_state.cc
|
||||
index 66bfb042c8c67644c2b94dd2dc7759aaf91088c6..1a9e45fd825c8ae867f36e03698176a15600ca0d 100644
|
||||
--- a/mojo/public/cpp/bindings/lib/interface_ptr_state.cc
|
||||
+++ b/mojo/public/cpp/bindings/lib/interface_ptr_state.cc
|
||||
@@ -4,6 +4,11 @@
|
||||
|
||||
#include "mojo/public/cpp/bindings/lib/interface_ptr_state.h"
|
||||
|
||||
+#include <stdint.h>
|
||||
+
|
||||
+#include <utility>
|
||||
+
|
||||
+#include "base/containers/span.h"
|
||||
#include "mojo/public/cpp/bindings/lib/task_runner_helper.h"
|
||||
|
||||
namespace mojo {
|
||||
@@ -100,7 +105,9 @@ bool InterfacePtrStateBase::InitializeEndpointClient(
|
||||
interface_name);
|
||||
endpoint_client_ = std::make_unique<InterfaceEndpointClient>(
|
||||
router_->CreateLocalEndpointHandle(kPrimaryInterfaceId), nullptr,
|
||||
- std::move(payload_validator), false, std::move(runner_),
|
||||
+ std::move(payload_validator),
|
||||
+ /* sync_method_ordinals= */ base::span<const uint32_t>(),
|
||||
+ std::move(runner_),
|
||||
// The version is only queried from the client so the value passed here
|
||||
// will not be used.
|
||||
0u, interface_name, method_info_callback, method_name_callback);
|
||||
diff --git a/mojo/public/cpp/bindings/lib/interface_ptr_state.h b/mojo/public/cpp/bindings/lib/interface_ptr_state.h
|
||||
index 3e4a5f87422f40143c631123153b7b1138cdfb8f..b3921a464b96aa33d2a7d98309c9745008b4aae1 100644
|
||||
--- a/mojo/public/cpp/bindings/lib/interface_ptr_state.h
|
||||
+++ b/mojo/public/cpp/bindings/lib/interface_ptr_state.h
|
||||
@@ -25,6 +25,7 @@
|
||||
#include "mojo/public/cpp/bindings/interface_endpoint_client.h"
|
||||
#include "mojo/public/cpp/bindings/lib/multiplex_router.h"
|
||||
#include "mojo/public/cpp/bindings/lib/pending_remote_state.h"
|
||||
+#include "mojo/public/cpp/bindings/lib/sync_method_traits.h"
|
||||
#include "mojo/public/cpp/bindings/pending_flush.h"
|
||||
#include "mojo/public/cpp/bindings/thread_safe_proxy.h"
|
||||
#include "mojo/public/cpp/system/message_pipe.h"
|
||||
@@ -249,6 +250,10 @@ class InterfacePtrState : public InterfacePtrStateBase {
|
||||
endpoint_client()->RaiseError();
|
||||
}
|
||||
|
||||
+ InterfaceEndpointClient* endpoint_client_for_test() {
|
||||
+ return endpoint_client();
|
||||
+ }
|
||||
+
|
||||
private:
|
||||
void ConfigureProxyIfNecessary() {
|
||||
// The proxy has been configured.
|
||||
@@ -259,7 +264,8 @@ class InterfacePtrState : public InterfacePtrStateBase {
|
||||
}
|
||||
|
||||
if (InitializeEndpointClient(
|
||||
- Interface::PassesAssociatedKinds_, Interface::HasSyncMethods_,
|
||||
+ Interface::PassesAssociatedKinds_,
|
||||
+ !SyncMethodTraits<Interface>::GetOrdinals().empty(),
|
||||
Interface::HasUninterruptableMethods_,
|
||||
std::make_unique<typename Interface::ResponseValidator_>(),
|
||||
Interface::Name_, Interface::MessageToMethodInfo_,
|
||||
diff --git a/mojo/public/cpp/bindings/lib/multiplex_router.cc b/mojo/public/cpp/bindings/lib/multiplex_router.cc
|
||||
index b9c92d5ec9eab57972cf870efff51fe09e381623..c04999f0ac8881cc86ed34761ddeb8e8dfc83164 100644
|
||||
--- a/mojo/public/cpp/bindings/lib/multiplex_router.cc
|
||||
+++ b/mojo/public/cpp/bindings/lib/multiplex_router.cc
|
||||
@@ -1067,6 +1067,12 @@ bool MultiplexRouter::ProcessIncomingMessage(
|
||||
|
||||
bool can_direct_call;
|
||||
if (message->has_flag(Message::kFlagIsSync)) {
|
||||
+ if (!message->has_flag(Message::kFlagIsResponse) &&
|
||||
+ !base::Contains(endpoint->client()->sync_method_ordinals(),
|
||||
+ message->name())) {
|
||||
+ RaiseErrorInNonTestingMode();
|
||||
+ return true;
|
||||
+ }
|
||||
can_direct_call = client_call_behavior != NO_DIRECT_CLIENT_CALLS &&
|
||||
endpoint->task_runner()->RunsTasksInCurrentSequence();
|
||||
} else {
|
||||
diff --git a/mojo/public/cpp/bindings/lib/sync_method_traits.h b/mojo/public/cpp/bindings/lib/sync_method_traits.h
|
||||
new file mode 100644
|
||||
index 0000000000000000000000000000000000000000..2b334f8d01c2edb7c3e6b98fb8d35925aded11ab
|
||||
--- /dev/null
|
||||
+++ b/mojo/public/cpp/bindings/lib/sync_method_traits.h
|
||||
@@ -0,0 +1,31 @@
|
||||
+// Copyright 2022 The Chromium Authors
|
||||
+// Use of this source code is governed by a BSD-style license that can be
|
||||
+// found in the LICENSE file.
|
||||
+
|
||||
+#ifndef MOJO_PUBLIC_CPP_BINDINGS_LIB_SYNC_METHOD_TRAITS_H_
|
||||
+#define MOJO_PUBLIC_CPP_BINDINGS_LIB_SYNC_METHOD_TRAITS_H_
|
||||
+
|
||||
+#include <stdint.h>
|
||||
+
|
||||
+#include <type_traits>
|
||||
+
|
||||
+#include "base/containers/span.h"
|
||||
+
|
||||
+namespace mojo::internal {
|
||||
+
|
||||
+template <typename Interface, typename SFINAE = void>
|
||||
+struct SyncMethodTraits {
|
||||
+ static constexpr base::span<const uint32_t> GetOrdinals() { return {}; }
|
||||
+};
|
||||
+
|
||||
+template <typename Interface>
|
||||
+struct SyncMethodTraits<Interface,
|
||||
+ std::void_t<decltype(Interface::kSyncMethodOrdinals)>> {
|
||||
+ static constexpr base::span<const uint32_t> GetOrdinals() {
|
||||
+ return Interface::kSyncMethodOrdinals;
|
||||
+ }
|
||||
+};
|
||||
+
|
||||
+} // namespace mojo::internal
|
||||
+
|
||||
+#endif // MOJO_PUBLIC_CPP_BINDINGS_LIB_SYNC_METHOD_TRAITS_H_
|
||||
diff --git a/mojo/public/cpp/bindings/tests/BUILD.gn b/mojo/public/cpp/bindings/tests/BUILD.gn
|
||||
index 248176f6f350b57bb5138924c68c4393ba1c11a8..25cfe56438d099ddcb4ed04a4e83b9abb89b8d14 100644
|
||||
--- a/mojo/public/cpp/bindings/tests/BUILD.gn
|
||||
+++ b/mojo/public/cpp/bindings/tests/BUILD.gn
|
||||
@@ -65,6 +65,7 @@ source_set("tests") {
|
||||
":mojo_public_bindings_test_utils",
|
||||
":test_extra_cpp_template_mojom",
|
||||
":test_mojom",
|
||||
+ ":test_mojom__generate_message_ids",
|
||||
"//base/test:test_support",
|
||||
"//mojo/core/test:test_support",
|
||||
"//mojo/public/cpp/bindings",
|
||||
diff --git a/mojo/public/cpp/bindings/tests/bindings_perftest.cc b/mojo/public/cpp/bindings/tests/bindings_perftest.cc
|
||||
index 173c6c801853fc9b19ca123d8cd1f580894d3e8e..383072ead95d459f62c2adf2a937edfc81681597 100644
|
||||
--- a/mojo/public/cpp/bindings/tests/bindings_perftest.cc
|
||||
+++ b/mojo/public/cpp/bindings/tests/bindings_perftest.cc
|
||||
@@ -212,12 +212,12 @@ TEST_F(MojoBindingsPerftest, MultiplexRouterPingPong) {
|
||||
|
||||
InterfaceEndpointClient client0(
|
||||
router0->CreateLocalEndpointHandle(kPrimaryInterfaceId), &paddle0,
|
||||
- nullptr, false, base::ThreadTaskRunnerHandle::Get(), 0u,
|
||||
- kTestInterfaceName, MessageToMethodInfo, MessageToMethodName);
|
||||
+ nullptr, {}, base::ThreadTaskRunnerHandle::Get(), 0u, kTestInterfaceName,
|
||||
+ MessageToMethodInfo, MessageToMethodName);
|
||||
InterfaceEndpointClient client1(
|
||||
router1->CreateLocalEndpointHandle(kPrimaryInterfaceId), &paddle1,
|
||||
- nullptr, false, base::ThreadTaskRunnerHandle::Get(), 0u,
|
||||
- kTestInterfaceName, MessageToMethodInfo, MessageToMethodName);
|
||||
+ nullptr, {}, base::ThreadTaskRunnerHandle::Get(), 0u, kTestInterfaceName,
|
||||
+ MessageToMethodInfo, MessageToMethodName);
|
||||
|
||||
paddle0.set_sender(&client0);
|
||||
paddle1.set_sender(&client1);
|
||||
@@ -264,8 +264,8 @@ TEST_F(MojoBindingsPerftest, MultiplexRouterDispatchCost) {
|
||||
CounterReceiver receiver;
|
||||
InterfaceEndpointClient client(
|
||||
router->CreateLocalEndpointHandle(kPrimaryInterfaceId), &receiver,
|
||||
- nullptr, false, base::ThreadTaskRunnerHandle::Get(), 0u,
|
||||
- kTestInterfaceName, MessageToMethodInfo, MessageToMethodName);
|
||||
+ nullptr, {}, base::ThreadTaskRunnerHandle::Get(), 0u, kTestInterfaceName,
|
||||
+ MessageToMethodInfo, MessageToMethodName);
|
||||
|
||||
static const uint32_t kIterations[] = {1000, 3000000};
|
||||
|
||||
diff --git a/mojo/public/cpp/bindings/tests/multiplex_router_unittest.cc b/mojo/public/cpp/bindings/tests/multiplex_router_unittest.cc
|
||||
index c04c3867a9629c28ec45c5d376c5688760c463c9..e340a28a0ea1536187386e3764fe019119e53f12 100644
|
||||
--- a/mojo/public/cpp/bindings/tests/multiplex_router_unittest.cc
|
||||
+++ b/mojo/public/cpp/bindings/tests/multiplex_router_unittest.cc
|
||||
@@ -74,13 +74,13 @@ class MultiplexRouterTest : public testing::Test {
|
||||
|
||||
TEST_F(MultiplexRouterTest, BasicRequestResponse) {
|
||||
InterfaceEndpointClient client0(
|
||||
- std::move(endpoint0_), nullptr, std::make_unique<PassThroughFilter>(),
|
||||
- false, base::ThreadTaskRunnerHandle::Get(), 0u, kTestInterfaceName,
|
||||
+ std::move(endpoint0_), nullptr, std::make_unique<PassThroughFilter>(), {},
|
||||
+ base::ThreadTaskRunnerHandle::Get(), 0u, kTestInterfaceName,
|
||||
MessageToMethodInfo, MessageToMethodName);
|
||||
ResponseGenerator generator;
|
||||
InterfaceEndpointClient client1(
|
||||
std::move(endpoint1_), &generator, std::make_unique<PassThroughFilter>(),
|
||||
- false, base::ThreadTaskRunnerHandle::Get(), 0u, kTestInterfaceName,
|
||||
+ {}, base::ThreadTaskRunnerHandle::Get(), 0u, kTestInterfaceName,
|
||||
MessageToMethodInfo, MessageToMethodName);
|
||||
|
||||
Message request;
|
||||
@@ -123,13 +123,13 @@ TEST_F(MultiplexRouterTest, BasicRequestResponse) {
|
||||
|
||||
TEST_F(MultiplexRouterTest, BasicRequestResponse_Synchronous) {
|
||||
InterfaceEndpointClient client0(
|
||||
- std::move(endpoint0_), nullptr, std::make_unique<PassThroughFilter>(),
|
||||
- false, base::ThreadTaskRunnerHandle::Get(), 0u, kTestInterfaceName,
|
||||
+ std::move(endpoint0_), nullptr, std::make_unique<PassThroughFilter>(), {},
|
||||
+ base::ThreadTaskRunnerHandle::Get(), 0u, kTestInterfaceName,
|
||||
MessageToMethodInfo, MessageToMethodName);
|
||||
ResponseGenerator generator;
|
||||
InterfaceEndpointClient client1(
|
||||
std::move(endpoint1_), &generator, std::make_unique<PassThroughFilter>(),
|
||||
- false, base::ThreadTaskRunnerHandle::Get(), 0u, kTestInterfaceName,
|
||||
+ {}, base::ThreadTaskRunnerHandle::Get(), 0u, kTestInterfaceName,
|
||||
MessageToMethodInfo, MessageToMethodName);
|
||||
|
||||
Message request;
|
||||
@@ -173,14 +173,14 @@ TEST_F(MultiplexRouterTest, BasicRequestResponse_Synchronous) {
|
||||
TEST_F(MultiplexRouterTest, LazyResponses) {
|
||||
InterfaceEndpointClient client0(
|
||||
std::move(endpoint0_), nullptr, base::WrapUnique(new PassThroughFilter()),
|
||||
- false, base::ThreadTaskRunnerHandle::Get(), 0u, kTestInterfaceName,
|
||||
+ {}, base::ThreadTaskRunnerHandle::Get(), 0u, kTestInterfaceName,
|
||||
MessageToMethodInfo, MessageToMethodName);
|
||||
base::RunLoop run_loop;
|
||||
LazyResponseGenerator generator(run_loop.QuitClosure());
|
||||
InterfaceEndpointClient client1(std::move(endpoint1_), &generator,
|
||||
- base::WrapUnique(new PassThroughFilter()),
|
||||
- false, base::ThreadTaskRunnerHandle::Get(),
|
||||
- 0u, kTestInterfaceName, MessageToMethodInfo,
|
||||
+ base::WrapUnique(new PassThroughFilter()), {},
|
||||
+ base::ThreadTaskRunnerHandle::Get(), 0u,
|
||||
+ kTestInterfaceName, MessageToMethodInfo,
|
||||
MessageToMethodName);
|
||||
|
||||
Message request;
|
||||
@@ -247,7 +247,7 @@ TEST_F(MultiplexRouterTest, MissingResponses) {
|
||||
base::RunLoop run_loop0, run_loop1;
|
||||
InterfaceEndpointClient client0(
|
||||
std::move(endpoint0_), nullptr, base::WrapUnique(new PassThroughFilter()),
|
||||
- false, base::ThreadTaskRunnerHandle::Get(), 0u, kTestInterfaceName,
|
||||
+ {}, base::ThreadTaskRunnerHandle::Get(), 0u, kTestInterfaceName,
|
||||
MessageToMethodInfo, MessageToMethodName);
|
||||
bool error_handler_called0 = false;
|
||||
client0.set_connection_error_handler(base::BindOnce(
|
||||
@@ -256,9 +256,9 @@ TEST_F(MultiplexRouterTest, MissingResponses) {
|
||||
base::RunLoop run_loop3;
|
||||
LazyResponseGenerator generator(run_loop3.QuitClosure());
|
||||
InterfaceEndpointClient client1(std::move(endpoint1_), &generator,
|
||||
- base::WrapUnique(new PassThroughFilter()),
|
||||
- false, base::ThreadTaskRunnerHandle::Get(),
|
||||
- 0u, kTestInterfaceName, MessageToMethodInfo,
|
||||
+ base::WrapUnique(new PassThroughFilter()), {},
|
||||
+ base::ThreadTaskRunnerHandle::Get(), 0u,
|
||||
+ kTestInterfaceName, MessageToMethodInfo,
|
||||
MessageToMethodName);
|
||||
bool error_handler_called1 = false;
|
||||
client1.set_connection_error_handler(base::BindOnce(
|
||||
@@ -306,12 +306,12 @@ TEST_F(MultiplexRouterTest, LateResponse) {
|
||||
{
|
||||
InterfaceEndpointClient client0(
|
||||
std::move(endpoint0_), nullptr, std::make_unique<PassThroughFilter>(),
|
||||
- false, base::ThreadTaskRunnerHandle::Get(), 0u, kTestInterfaceName,
|
||||
+ {}, base::ThreadTaskRunnerHandle::Get(), 0u, kTestInterfaceName,
|
||||
MessageToMethodInfo, MessageToMethodName);
|
||||
InterfaceEndpointClient client1(std::move(endpoint1_), &generator,
|
||||
- std::make_unique<PassThroughFilter>(),
|
||||
- false, base::ThreadTaskRunnerHandle::Get(),
|
||||
- 0u, kTestInterfaceName, MessageToMethodInfo,
|
||||
+ std::make_unique<PassThroughFilter>(), {},
|
||||
+ base::ThreadTaskRunnerHandle::Get(), 0u,
|
||||
+ kTestInterfaceName, MessageToMethodInfo,
|
||||
MessageToMethodName);
|
||||
|
||||
Message request;
|
||||
diff --git a/mojo/public/cpp/bindings/tests/sync_method_unittest.cc b/mojo/public/cpp/bindings/tests/sync_method_unittest.cc
|
||||
index d794d29df07d289d34b3b1aae9f8574fc914c050..6de90c8ec9619358e97d50726d7c8c6820df7990 100644
|
||||
--- a/mojo/public/cpp/bindings/tests/sync_method_unittest.cc
|
||||
+++ b/mojo/public/cpp/bindings/tests/sync_method_unittest.cc
|
||||
@@ -2,6 +2,7 @@
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
+#include <tuple>
|
||||
#include <utility>
|
||||
|
||||
#include "base/barrier_closure.h"
|
||||
@@ -9,15 +10,21 @@
|
||||
#include "base/check.h"
|
||||
#include "base/run_loop.h"
|
||||
#include "base/sequence_token.h"
|
||||
+#include "base/task/sequenced_task_runner.h"
|
||||
#include "base/task/thread_pool.h"
|
||||
#include "base/test/bind.h"
|
||||
#include "base/test/task_environment.h"
|
||||
#include "base/threading/sequence_bound.h"
|
||||
+#include "base/threading/sequenced_task_runner_handle.h"
|
||||
#include "base/threading/thread.h"
|
||||
#include "base/time/time.h"
|
||||
#include "mojo/public/cpp/bindings/associated_receiver.h"
|
||||
#include "mojo/public/cpp/bindings/associated_receiver_set.h"
|
||||
#include "mojo/public/cpp/bindings/associated_remote.h"
|
||||
+#include "mojo/public/cpp/bindings/lib/message_fragment.h"
|
||||
+#include "mojo/public/cpp/bindings/lib/send_message_helper.h"
|
||||
+#include "mojo/public/cpp/bindings/lib/serialization_util.h"
|
||||
+#include "mojo/public/cpp/bindings/message.h"
|
||||
#include "mojo/public/cpp/bindings/receiver.h"
|
||||
#include "mojo/public/cpp/bindings/receiver_set.h"
|
||||
#include "mojo/public/cpp/bindings/remote.h"
|
||||
@@ -27,10 +34,16 @@
|
||||
#include "mojo/public/cpp/bindings/shared_remote.h"
|
||||
#include "mojo/public/cpp/bindings/sync_call_restrictions.h"
|
||||
#include "mojo/public/cpp/bindings/tests/bindings_test_base.h"
|
||||
+#include "mojo/public/cpp/bindings/tests/sync_method_unittest.test-mojom-shared-message-ids.h"
|
||||
#include "mojo/public/cpp/bindings/tests/sync_method_unittest.test-mojom.h"
|
||||
#include "mojo/public/interfaces/bindings/tests/test_sync_methods.mojom.h"
|
||||
#include "testing/gtest/include/gtest/gtest.h"
|
||||
|
||||
+// This needs to be included last, since it forward declares a bunch of classes
|
||||
+// but depends on those definitions to be included by headers that sort
|
||||
+// lexicographically after.
|
||||
+#include "mojo/public/cpp/bindings/tests/sync_method_unittest.test-mojom-params-data.h"
|
||||
+
|
||||
namespace mojo {
|
||||
namespace test {
|
||||
namespace sync_method_unittest {
|
||||
@@ -1703,6 +1716,237 @@ TEST_P(DisableSyncInterruptTest, SharedRemoteNoInterruptWhenDisabled) {
|
||||
INSTANTIATE_MOJO_BINDINGS_TEST_SUITE_P(SyncInterruptTest);
|
||||
INSTANTIATE_MOJO_BINDINGS_TEST_SUITE_P(DisableSyncInterruptTest);
|
||||
|
||||
+class OneSyncImpl;
|
||||
+
|
||||
+class NoSyncImpl : public mojom::NoSync {
|
||||
+ public:
|
||||
+ explicit NoSyncImpl(PendingReceiver<mojom::NoSync> receiver)
|
||||
+ : receiver_(this, std::move(receiver)) {}
|
||||
+
|
||||
+ explicit NoSyncImpl(
|
||||
+ PendingAssociatedReceiver<mojom::NoSync> associated_receiver)
|
||||
+ : associated_receiver_(this, std::move(associated_receiver)) {}
|
||||
+
|
||||
+ // mojom::NoSync implementation:
|
||||
+ void Method(MethodCallback callback) override;
|
||||
+ void BindNoSync(PendingAssociatedReceiver<mojom::NoSync> receiver) override;
|
||||
+ void BindOneSync(PendingAssociatedReceiver<mojom::OneSync> receiver) override;
|
||||
+
|
||||
+ private:
|
||||
+ Receiver<mojom::NoSync> receiver_{this};
|
||||
+ AssociatedReceiver<mojom::NoSync> associated_receiver_{this};
|
||||
+
|
||||
+ std::unique_ptr<NoSyncImpl> associated_no_sync_;
|
||||
+ std::unique_ptr<OneSyncImpl> associated_one_sync_;
|
||||
+};
|
||||
+
|
||||
+class OneSyncImpl : public mojom::OneSync {
|
||||
+ public:
|
||||
+ explicit OneSyncImpl(PendingReceiver<mojom::OneSync> receiver)
|
||||
+ : receiver_(this, std::move(receiver)) {}
|
||||
+
|
||||
+ explicit OneSyncImpl(
|
||||
+ PendingAssociatedReceiver<mojom::OneSync> associated_receiver)
|
||||
+ : associated_receiver_(this, std::move(associated_receiver)) {}
|
||||
+
|
||||
+ // mojom::OneSync implementation:
|
||||
+ void Method(MethodCallback callback) override;
|
||||
+ void SyncMethod(SyncMethodCallback callback) override;
|
||||
+ void BindNoSync(PendingAssociatedReceiver<mojom::NoSync> receiver) override;
|
||||
+ void BindOneSync(PendingAssociatedReceiver<mojom::OneSync> receiver) override;
|
||||
+
|
||||
+ private:
|
||||
+ Receiver<mojom::OneSync> receiver_{this};
|
||||
+ AssociatedReceiver<mojom::OneSync> associated_receiver_{this};
|
||||
+
|
||||
+ std::unique_ptr<NoSyncImpl> associated_no_sync_;
|
||||
+ std::unique_ptr<OneSyncImpl> associated_one_sync_;
|
||||
+};
|
||||
+
|
||||
+void NoSyncImpl::Method(MethodCallback callback) {
|
||||
+ EXPECT_TRUE(false);
|
||||
+ std::move(callback).Run();
|
||||
+}
|
||||
+
|
||||
+void NoSyncImpl::BindNoSync(PendingAssociatedReceiver<mojom::NoSync> receiver) {
|
||||
+ associated_no_sync_ = std::make_unique<NoSyncImpl>(std::move(receiver));
|
||||
+}
|
||||
+
|
||||
+void NoSyncImpl::BindOneSync(
|
||||
+ PendingAssociatedReceiver<mojom::OneSync> receiver) {
|
||||
+ associated_one_sync_ = std::make_unique<OneSyncImpl>(std::move(receiver));
|
||||
+}
|
||||
+
|
||||
+void OneSyncImpl::Method(MethodCallback callback) {
|
||||
+ EXPECT_TRUE(false);
|
||||
+ std::move(callback).Run();
|
||||
+}
|
||||
+
|
||||
+void OneSyncImpl::SyncMethod(MethodCallback callback) {
|
||||
+ std::move(callback).Run();
|
||||
+}
|
||||
+
|
||||
+void OneSyncImpl::BindNoSync(
|
||||
+ PendingAssociatedReceiver<mojom::NoSync> receiver) {
|
||||
+ associated_no_sync_ = std::make_unique<NoSyncImpl>(std::move(receiver));
|
||||
+}
|
||||
+
|
||||
+void OneSyncImpl::BindOneSync(
|
||||
+ PendingAssociatedReceiver<mojom::OneSync> receiver) {
|
||||
+ associated_one_sync_ = std::make_unique<OneSyncImpl>(std::move(receiver));
|
||||
+}
|
||||
+
|
||||
+class NoResponseExpectedResponder : public MessageReceiver {
|
||||
+ public:
|
||||
+ explicit NoResponseExpectedResponder() = default;
|
||||
+
|
||||
+ // MessageReceiver implementation:
|
||||
+ bool Accept(Message* message) override {
|
||||
+ EXPECT_TRUE(false);
|
||||
+ return true;
|
||||
+ }
|
||||
+};
|
||||
+
|
||||
+class SyncFlagValidationTest : public ::testing::TestWithParam<uint32_t> {
|
||||
+ protected:
|
||||
+ Message MakeNoSyncMethodMessage() {
|
||||
+ const uint32_t flags =
|
||||
+ // Always set the sync flag, as that's the primary point of the test.
|
||||
+ Message::kFlagIsSync |
|
||||
+ // InterfaceEndpointClient requires this flag if sending a message with
|
||||
+ // a responder.
|
||||
+ Message::kFlagExpectsResponse | GetParam();
|
||||
+ Message message(mojom::internal::kNoSync_Method_Name, flags, 0, 0, nullptr);
|
||||
+ ::mojo::internal::MessageFragment<
|
||||
+ mojom::internal::NoSync_Method_Params_Data>
|
||||
+ params(message);
|
||||
+ params.Allocate();
|
||||
+ return message;
|
||||
+ }
|
||||
+
|
||||
+ Message MakeOneSyncMethodMessage() {
|
||||
+ const uint32_t flags =
|
||||
+ // Always set the sync flag, as that's the primary point of the test.
|
||||
+ Message::kFlagIsSync |
|
||||
+ // InterfaceEndpointClient requires this flag if sending a message with
|
||||
+ // a responder.
|
||||
+ Message::kFlagExpectsResponse | GetParam();
|
||||
+ Message message(mojom::internal::kOneSync_Method_Name, flags, 0, 0,
|
||||
+ nullptr);
|
||||
+ ::mojo::internal::MessageFragment<
|
||||
+ mojom::internal::NoSync_Method_Params_Data>
|
||||
+ params(message);
|
||||
+ params.Allocate();
|
||||
+ return message;
|
||||
+ }
|
||||
+
|
||||
+ void FlushPostedTasks() {
|
||||
+ base::RunLoop run_loop;
|
||||
+ base::SequencedTaskRunnerHandle::Get()->PostTask(FROM_HERE,
|
||||
+ run_loop.QuitClosure());
|
||||
+ run_loop.Run();
|
||||
+ }
|
||||
+
|
||||
+ private:
|
||||
+ base::test::SingleThreadTaskEnvironment task_environment;
|
||||
+};
|
||||
+
|
||||
+TEST_P(SyncFlagValidationTest, NonSync) {
|
||||
+ Remote<mojom::NoSync> remote;
|
||||
+ NoSyncImpl impl(remote.BindNewPipeAndPassReceiver());
|
||||
+
|
||||
+ Message message = MakeNoSyncMethodMessage();
|
||||
+ auto responder = std::make_unique<NoResponseExpectedResponder>();
|
||||
+ ASSERT_TRUE(remote.internal_state()->endpoint_client_for_test());
|
||||
+ ::mojo::internal::SendMojoMessage(
|
||||
+ *remote.internal_state()->endpoint_client_for_test(), message,
|
||||
+ std::move(responder));
|
||||
+}
|
||||
+
|
||||
+TEST_P(SyncFlagValidationTest, OneSync) {
|
||||
+ Remote<mojom::OneSync> remote;
|
||||
+ OneSyncImpl impl(remote.BindNewPipeAndPassReceiver());
|
||||
+
|
||||
+ Message message = MakeOneSyncMethodMessage();
|
||||
+ auto responder = std::make_unique<NoResponseExpectedResponder>();
|
||||
+ ASSERT_TRUE(remote.internal_state()->endpoint_client_for_test());
|
||||
+ ::mojo::internal::SendMojoMessage(
|
||||
+ *remote.internal_state()->endpoint_client_for_test(), message,
|
||||
+ std::move(responder));
|
||||
+}
|
||||
+
|
||||
+TEST_P(SyncFlagValidationTest, NoSyncAssociatedWithNoSync) {
|
||||
+ Remote<mojom::NoSync> remote;
|
||||
+ NoSyncImpl impl(remote.BindNewPipeAndPassReceiver());
|
||||
+
|
||||
+ AssociatedRemote<mojom::NoSync> associated_remote;
|
||||
+ remote->BindNoSync(associated_remote.BindNewEndpointAndPassReceiver());
|
||||
+
|
||||
+ FlushPostedTasks();
|
||||
+
|
||||
+ Message message = MakeNoSyncMethodMessage();
|
||||
+ auto responder = std::make_unique<NoResponseExpectedResponder>();
|
||||
+ ASSERT_TRUE(remote.internal_state()->endpoint_client_for_test());
|
||||
+ ::mojo::internal::SendMojoMessage(
|
||||
+ *associated_remote.internal_state()->endpoint_client_for_test(), message,
|
||||
+ std::move(responder));
|
||||
+}
|
||||
+
|
||||
+TEST_P(SyncFlagValidationTest, OneSyncAssociatedWithNoSync) {
|
||||
+ Remote<mojom::NoSync> remote;
|
||||
+ NoSyncImpl impl(remote.BindNewPipeAndPassReceiver());
|
||||
+
|
||||
+ AssociatedRemote<mojom::OneSync> associated_remote;
|
||||
+ remote->BindOneSync(associated_remote.BindNewEndpointAndPassReceiver());
|
||||
+
|
||||
+ FlushPostedTasks();
|
||||
+
|
||||
+ Message message = MakeOneSyncMethodMessage();
|
||||
+ auto responder = std::make_unique<NoResponseExpectedResponder>();
|
||||
+ ASSERT_TRUE(remote.internal_state()->endpoint_client_for_test());
|
||||
+ ::mojo::internal::SendMojoMessage(
|
||||
+ *associated_remote.internal_state()->endpoint_client_for_test(), message,
|
||||
+ std::move(responder));
|
||||
+}
|
||||
+
|
||||
+TEST_P(SyncFlagValidationTest, NoSyncAssociatedWithOneSync) {
|
||||
+ Remote<mojom::OneSync> remote;
|
||||
+ OneSyncImpl impl(remote.BindNewPipeAndPassReceiver());
|
||||
+
|
||||
+ AssociatedRemote<mojom::NoSync> associated_remote;
|
||||
+ remote->BindNoSync(associated_remote.BindNewEndpointAndPassReceiver());
|
||||
+
|
||||
+ FlushPostedTasks();
|
||||
+
|
||||
+ Message message = MakeNoSyncMethodMessage();
|
||||
+ auto responder = std::make_unique<NoResponseExpectedResponder>();
|
||||
+ ASSERT_TRUE(remote.internal_state()->endpoint_client_for_test());
|
||||
+ ::mojo::internal::SendMojoMessage(
|
||||
+ *associated_remote.internal_state()->endpoint_client_for_test(), message,
|
||||
+ std::move(responder));
|
||||
+}
|
||||
+
|
||||
+TEST_P(SyncFlagValidationTest, OneSyncAssociatedWithOneSync) {
|
||||
+ Remote<mojom::OneSync> remote;
|
||||
+ OneSyncImpl impl(remote.BindNewPipeAndPassReceiver());
|
||||
+
|
||||
+ AssociatedRemote<mojom::OneSync> associated_remote;
|
||||
+ remote->BindOneSync(associated_remote.BindNewEndpointAndPassReceiver());
|
||||
+
|
||||
+ FlushPostedTasks();
|
||||
+
|
||||
+ Message message = MakeOneSyncMethodMessage();
|
||||
+ auto responder = std::make_unique<NoResponseExpectedResponder>();
|
||||
+ ASSERT_TRUE(remote.internal_state()->endpoint_client_for_test());
|
||||
+ ::mojo::internal::SendMojoMessage(
|
||||
+ *associated_remote.internal_state()->endpoint_client_for_test(), message,
|
||||
+ std::move(responder));
|
||||
+}
|
||||
+
|
||||
+INSTANTIATE_TEST_SUITE_P(,
|
||||
+ SyncFlagValidationTest,
|
||||
+ ::testing::Values(0, Message::kFlagIsResponse));
|
||||
+
|
||||
} // namespace
|
||||
} // namespace sync_method_unittest
|
||||
} // namespace test
|
||||
diff --git a/mojo/public/cpp/bindings/tests/sync_method_unittest.test-mojom b/mojo/public/cpp/bindings/tests/sync_method_unittest.test-mojom
|
||||
index 951442b3585ad22f936568e211ad41f8ae358705..0cc5f7c6d288f988b6114ff6b5b80546558eb378 100644
|
||||
--- a/mojo/public/cpp/bindings/tests/sync_method_unittest.test-mojom
|
||||
+++ b/mojo/public/cpp/bindings/tests/sync_method_unittest.test-mojom
|
||||
@@ -49,3 +49,20 @@ interface Ponger {
|
||||
interface SyncService {
|
||||
[Sync] SyncCall() => ();
|
||||
};
|
||||
+
|
||||
+interface NoSync {
|
||||
+ Method() => ();
|
||||
+
|
||||
+ BindNoSync(pending_associated_receiver<NoSync> no_sync);
|
||||
+ BindOneSync(pending_associated_receiver<OneSync> one_sync);
|
||||
+};
|
||||
+
|
||||
+interface OneSync {
|
||||
+ Method() => ();
|
||||
+
|
||||
+ [Sync]
|
||||
+ SyncMethod() => ();
|
||||
+
|
||||
+ BindNoSync(pending_associated_receiver<NoSync> no_sync);
|
||||
+ BindOneSync(pending_associated_receiver<OneSync> one_sync);
|
||||
+};
|
||||
diff --git a/mojo/public/tools/bindings/generators/cpp_templates/interface_declaration.tmpl b/mojo/public/tools/bindings/generators/cpp_templates/interface_declaration.tmpl
|
||||
index c53d4eac2ee4c0c0134f25b3f7a1c2275c545f55..6e02107bd623def01aed76b85d58e932f92ef03f 100644
|
||||
--- a/mojo/public/tools/bindings/generators/cpp_templates/interface_declaration.tmpl
|
||||
+++ b/mojo/public/tools/bindings/generators/cpp_templates/interface_declaration.tmpl
|
||||
@@ -32,7 +32,12 @@ class {{export_attribute}} {{interface.name}}
|
||||
{%- endif %}
|
||||
static constexpr uint32_t Version_ = {{interface.version}};
|
||||
static constexpr bool PassesAssociatedKinds_ = {% if interface|passes_associated_kinds %}true{% else %}false{% endif %};
|
||||
- static constexpr bool HasSyncMethods_ = {% if interface|has_sync_methods %}true{% else %}false{% endif %};
|
||||
+{%- set sync_method_ordinals = interface|get_sync_method_ordinals -%}
|
||||
+{%- if sync_method_ordinals %}
|
||||
+ static inline constexpr uint32_t kSyncMethodOrdinals[] = {
|
||||
+ {{sync_method_ordinals|sort|join(', \n')|indent(4)}}
|
||||
+ };
|
||||
+{%- endif %}
|
||||
static constexpr bool HasUninterruptableMethods_ =
|
||||
{%- if interface|has_uninterruptable_methods %} true
|
||||
{%- else %} false{% endif %};
|
||||
diff --git a/mojo/public/tools/bindings/generators/cpp_templates/module-params-data.h.tmpl b/mojo/public/tools/bindings/generators/cpp_templates/module-params-data.h.tmpl
|
||||
index af3bc5168beb5f9e5b9cfe63354dbdb6b29ff8a1..ab71e91dab403f4c552165eba5da7e32a61b1b83 100644
|
||||
--- a/mojo/public/tools/bindings/generators/cpp_templates/module-params-data.h.tmpl
|
||||
+++ b/mojo/public/tools/bindings/generators/cpp_templates/module-params-data.h.tmpl
|
||||
@@ -17,13 +17,15 @@
|
||||
#pragma clang diagnostic ignored "-Wunused-private-field"
|
||||
#endif
|
||||
|
||||
+namespace mojo::internal {
|
||||
+class ValidationContext;
|
||||
+}
|
||||
+
|
||||
{%- for namespace in namespaces_as_array %}
|
||||
namespace {{namespace}} {
|
||||
{%- endfor %}
|
||||
namespace internal {
|
||||
|
||||
-class ValidationContext;
|
||||
-
|
||||
{#--- Interface parameter definitions #}
|
||||
{%- for interface in interfaces %}
|
||||
{%- for method in interface.methods %}
|
||||
diff --git a/mojo/public/tools/bindings/generators/mojom_cpp_generator.py b/mojo/public/tools/bindings/generators/mojom_cpp_generator.py
|
||||
index 014f2bf04da4f2e11a13d57d910ecc8a8b489113..add5a877cb7e38da4599d3ae76ea0bd9486637da 100644
|
||||
--- a/mojo/public/tools/bindings/generators/mojom_cpp_generator.py
|
||||
+++ b/mojo/public/tools/bindings/generators/mojom_cpp_generator.py
|
||||
@@ -403,7 +403,7 @@ class Generator(generator.Generator):
|
||||
"get_qualified_name_for_kind": self._GetQualifiedNameForKind,
|
||||
"has_callbacks": mojom.HasCallbacks,
|
||||
"has_packed_method_ordinals": HasPackedMethodOrdinals,
|
||||
- "has_sync_methods": mojom.HasSyncMethods,
|
||||
+ "get_sync_method_ordinals": mojom.GetSyncMethodOrdinals,
|
||||
"has_uninterruptable_methods": mojom.HasUninterruptableMethods,
|
||||
"method_supports_lazy_serialization":
|
||||
self._MethodSupportsLazySerialization,
|
||||
diff --git a/mojo/public/tools/mojom/mojom/generate/module.py b/mojo/public/tools/mojom/mojom/generate/module.py
|
||||
index eff9376b78b20dfa39efc60f7548a965a38700f1..b952ada97535aa2da8a29bc6275f738dfb0c70db 100644
|
||||
--- a/mojo/public/tools/mojom/mojom/generate/module.py
|
||||
+++ b/mojo/public/tools/mojom/mojom/generate/module.py
|
||||
@@ -1729,11 +1729,8 @@ def MethodPassesInterfaces(method):
|
||||
return _AnyMethodParameterRecursive(method, IsInterfaceKind)
|
||||
|
||||
|
||||
-def HasSyncMethods(interface):
|
||||
- for method in interface.methods:
|
||||
- if method.sync:
|
||||
- return True
|
||||
- return False
|
||||
+def GetSyncMethodOrdinals(interface):
|
||||
+ return [method.ordinal for method in interface.methods if method.sync]
|
||||
|
||||
|
||||
def HasUninterruptableMethods(interface):
|
||||
@@ -67,12 +67,12 @@ index ad34b6230f57ad906bae515aa73ea2aaf1bfeede..b5cff1fee2d14c02f2d67cf012b7ba24
|
||||
const WebSecurityOrigin& script_origin) {
|
||||
return false;
|
||||
diff --git a/third_party/blink/renderer/core/workers/worker_thread.cc b/third_party/blink/renderer/core/workers/worker_thread.cc
|
||||
index 20d674166c78e316751bfa3ec7aed74656eea9b4..d289cfca8d8a9b093d8d30427e594c46b2f56c79 100644
|
||||
index 156d8d8184c4a69a9d8b8603027d7b398e2790bf..98fa13b35b0328eb436f2d146a8cda87438e6519 100644
|
||||
--- a/third_party/blink/renderer/core/workers/worker_thread.cc
|
||||
+++ b/third_party/blink/renderer/core/workers/worker_thread.cc
|
||||
@@ -744,6 +744,12 @@ void WorkerThread::PrepareForShutdownOnWorkerThread() {
|
||||
nested_runner_->QuitNow();
|
||||
@@ -746,6 +746,12 @@ void WorkerThread::PrepareForShutdownOnWorkerThread() {
|
||||
}
|
||||
pause_handle_.reset();
|
||||
|
||||
+ {
|
||||
+ v8::HandleScope handle_scope(GetIsolate());
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
{
|
||||
"src/electron/patches/chromium": "src",
|
||||
|
||||
"src/electron/patches/angle": "src/third_party/angle",
|
||||
|
||||
"src/electron/patches/boringssl": "src/third_party/boringssl/src",
|
||||
|
||||
"src/electron/patches/devtools_frontend": "src/third_party/devtools-frontend/src",
|
||||
@@ -21,5 +23,7 @@
|
||||
|
||||
"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/libaom": "src/third_party/libaom/source/libaom"
|
||||
}
|
||||
|
||||
1
patches/libaom/.patches
Normal file
1
patches/libaom/.patches
Normal file
@@ -0,0 +1 @@
|
||||
rtc_avoid_scene_detection_on_resize.patch
|
||||
72
patches/libaom/rtc_avoid_scene_detection_on_resize.patch
Normal file
72
patches/libaom/rtc_avoid_scene_detection_on_resize.patch
Normal file
@@ -0,0 +1,72 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Marco Paniconi <marpan@google.com>
|
||||
Date: Mon, 28 Nov 2022 14:25:08 -0800
|
||||
Subject: rtc: Avoid scene detection on resize
|
||||
|
||||
Don't enter scene detection under external resize.
|
||||
Add rc->prev_coded_width/height to track the
|
||||
previous encoded frame eweight/height.
|
||||
The rc is part of layer context so this will be
|
||||
per spatial layer for SVC.
|
||||
|
||||
This fixes the buffer overflow issue below.
|
||||
|
||||
Bug: chromium:1393384
|
||||
Change-Id: I4b11818a27c439c2d2c42036dff7b8777f70a86e
|
||||
(cherry picked from commit bee1caded272127a6d6b70ac79479083d183d5d0)
|
||||
|
||||
diff --git a/av1/encoder/ratectrl.c b/av1/encoder/ratectrl.c
|
||||
index 3e6939c5e1a5fbb1c52069a03c0317fa3e05aaf2..3c9498b8889bf0352aa0b640a82556daf36c62cc 100644
|
||||
--- a/av1/encoder/ratectrl.c
|
||||
+++ b/av1/encoder/ratectrl.c
|
||||
@@ -2136,6 +2136,9 @@ void av1_rc_postencode_update(AV1_COMP *cpi, uint64_t bytes_used) {
|
||||
}
|
||||
#endif
|
||||
if (current_frame->frame_type == KEY_FRAME) rc->frames_since_key = 0;
|
||||
+
|
||||
+ rc->prev_coded_width = cm->width;
|
||||
+ rc->prev_coded_height = cm->height;
|
||||
// if (current_frame->frame_number == 1 && cm->show_frame)
|
||||
/*
|
||||
rc->this_frame_target =
|
||||
@@ -2152,6 +2155,8 @@ void av1_rc_postencode_update_drop_frame(AV1_COMP *cpi) {
|
||||
cpi->rc.rc_2_frame = 0;
|
||||
cpi->rc.rc_1_frame = 0;
|
||||
cpi->rc.prev_avg_frame_bandwidth = cpi->rc.avg_frame_bandwidth;
|
||||
+ cpi->rc.prev_coded_width = cpi->common.width;
|
||||
+ cpi->rc.prev_coded_height = cpi->common.height;
|
||||
}
|
||||
|
||||
int av1_find_qindex(double desired_q, aom_bit_depth_t bit_depth,
|
||||
@@ -3096,8 +3101,15 @@ void av1_get_one_pass_rt_params(AV1_COMP *cpi,
|
||||
}
|
||||
}
|
||||
// Check for scene change: for SVC check on base spatial layer only.
|
||||
- if (cpi->sf.rt_sf.check_scene_detection && svc->spatial_layer_id == 0)
|
||||
- rc_scene_detection_onepass_rt(cpi);
|
||||
+ if (cpi->sf.rt_sf.check_scene_detection && svc->spatial_layer_id == 0) {
|
||||
+ if (rc->prev_coded_width == cm->width &&
|
||||
+ rc->prev_coded_height == cm->height) {
|
||||
+ rc_scene_detection_onepass_rt(cpi);
|
||||
+ } else if (cpi->src_sad_blk_64x64) {
|
||||
+ aom_free(cpi->src_sad_blk_64x64);
|
||||
+ cpi->src_sad_blk_64x64 = NULL;
|
||||
+ }
|
||||
+ }
|
||||
// Check for dynamic resize, for single spatial layer for now.
|
||||
// For temporal layers only check on base temporal layer.
|
||||
if (cpi->oxcf.resize_cfg.resize_mode == RESIZE_DYNAMIC) {
|
||||
diff --git a/av1/encoder/ratectrl.h b/av1/encoder/ratectrl.h
|
||||
index 486fda38036226d0e92c0bb69a029b196f44b6c9..f9e9b8b0a506970f79bf1799d50f45abf9ecb684 100644
|
||||
--- a/av1/encoder/ratectrl.h
|
||||
+++ b/av1/encoder/ratectrl.h
|
||||
@@ -253,6 +253,9 @@ typedef struct {
|
||||
int frame_level_fast_extra_bits;
|
||||
|
||||
double frame_level_rate_correction_factors[RATE_FACTOR_LEVELS];
|
||||
+
|
||||
+ int prev_coded_width;
|
||||
+ int prev_coded_height;
|
||||
/*!\endcond */
|
||||
} RATE_CONTROL;
|
||||
|
||||
@@ -49,3 +49,6 @@ fix_override_createjob_in_node_platform.patch
|
||||
buffer_fix_atob_input_validation.patch
|
||||
v8_api_advance_api_deprecation.patch
|
||||
enable_-wunqualified-std-cast-call.patch
|
||||
fix_expose_the_built-in_electron_module_via_the_esm_loader.patch
|
||||
chore_enable_c_17_for_native_modules.patch
|
||||
cherry-pick-09ae62b.patch
|
||||
|
||||
236
patches/node/cherry-pick-09ae62b.patch
Normal file
236
patches/node/cherry-pick-09ae62b.patch
Normal file
@@ -0,0 +1,236 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Michael Dawson <mdawson@devrus.com>
|
||||
Date: Tue, 25 Oct 2022 17:39:41 -0400
|
||||
Subject: node-api: handle no support for external buffers
|
||||
|
||||
Refs: https://github.com/electron/electron/issues/35801
|
||||
Refs: https://github.com/nodejs/abi-stable-node/issues/441
|
||||
|
||||
Electron recently dropped support for external
|
||||
buffers. Provide a way for addon authors to:
|
||||
- hide the methods to create external buffers so they can
|
||||
avoid using them if they want the broadest compatibility.
|
||||
- call the methods that create external buffers at runtime
|
||||
to check if external buffers are supported and either
|
||||
use them or not based on the return code.
|
||||
|
||||
Signed-off-by: Michael Dawson <mdawson@devrus.com>
|
||||
|
||||
PR-URL: https://github.com/nodejs/node/pull/45181
|
||||
Reviewed-By: Chengzhong Wu <legendecas@gmail.com>
|
||||
Reviewed-By: Minwoo Jung <nodecorelab@gmail.com>
|
||||
|
||||
diff --git a/doc/api/n-api.md b/doc/api/n-api.md
|
||||
index 3d1741bad82359af6a258fb2a059656f1528bba0..d64f80e2635074df7f8ecd72d1fde7d1747786fa 100644
|
||||
--- a/doc/api/n-api.md
|
||||
+++ b/doc/api/n-api.md
|
||||
@@ -579,6 +579,7 @@ typedef enum {
|
||||
napi_arraybuffer_expected,
|
||||
napi_detachable_arraybuffer_expected,
|
||||
napi_would_deadlock, /* unused */
|
||||
+ napi_no_external_buffers_allowed
|
||||
} napi_status;
|
||||
```
|
||||
|
||||
@@ -2394,6 +2395,19 @@ napi_create_external_arraybuffer(napi_env env,
|
||||
|
||||
Returns `napi_ok` if the API succeeded.
|
||||
|
||||
+**Some runtimes other than Node.js have dropped support for external buffers**.
|
||||
+On runtimes other than Node.js this method may return
|
||||
+`napi_no_external_buffers_allowed` to indicate that external
|
||||
+buffers are not supported. One such runtime is Electron as
|
||||
+described in this issue
|
||||
+[electron/issues/35801](https://github.com/electron/electron/issues/35801).
|
||||
+
|
||||
+In order to maintain broadest compatibility with all runtimes
|
||||
+you may define `NODE_API_NO_EXTERNAL_BUFFERS_ALLOWED` in your addon before
|
||||
+includes for the node-api headers. Doing so will hide the 2 functions
|
||||
+that create external buffers. This will ensure a compilation error
|
||||
+occurs if you accidentally use one of these methods.
|
||||
+
|
||||
This API returns a Node-API value corresponding to a JavaScript `ArrayBuffer`.
|
||||
The underlying byte buffer of the `ArrayBuffer` is externally allocated and
|
||||
managed. The caller must ensure that the byte buffer remains valid until the
|
||||
@@ -2438,6 +2452,19 @@ napi_status napi_create_external_buffer(napi_env env,
|
||||
|
||||
Returns `napi_ok` if the API succeeded.
|
||||
|
||||
+**Some runtimes other than Node.js have dropped support for external buffers**.
|
||||
+On runtimes other than Node.js this method may return
|
||||
+`napi_no_external_buffers_allowed` to indicate that external
|
||||
+buffers are not supported. One such runtime is Electron as
|
||||
+described in this issue
|
||||
+[electron/issues/35801](https://github.com/electron/electron/issues/35801).
|
||||
+
|
||||
+In order to maintain broadest compatibility with all runtimes
|
||||
+you may define `NODE_API_NO_EXTERNAL_BUFFERS_ALLOWED` in your addon before
|
||||
+includes for the node-api headers. Doing so will hide the 2 functions
|
||||
+that create external buffers. This will ensure a compilation error
|
||||
+occurs if you accidentally use one of these methods.
|
||||
+
|
||||
This API allocates a `node::Buffer` object and initializes it with data
|
||||
backed by the passed in buffer. While this is still a fully-supported data
|
||||
structure, in most cases using a `TypedArray` will suffice.
|
||||
diff --git a/src/js_native_api.h b/src/js_native_api.h
|
||||
index 50ccf11e2405802f1c48764067b4010e8b9a0815..2ddf3780e8bde8df59b202c0913cf6434a6581ce 100644
|
||||
--- a/src/js_native_api.h
|
||||
+++ b/src/js_native_api.h
|
||||
@@ -404,6 +404,7 @@ NAPI_EXTERN napi_status napi_create_arraybuffer(napi_env env,
|
||||
size_t byte_length,
|
||||
void** data,
|
||||
napi_value* result);
|
||||
+#ifndef NODE_API_NO_EXTERNAL_BUFFERS_ALLOWED
|
||||
NAPI_EXTERN napi_status
|
||||
napi_create_external_arraybuffer(napi_env env,
|
||||
void* external_data,
|
||||
@@ -411,6 +412,7 @@ napi_create_external_arraybuffer(napi_env env,
|
||||
napi_finalize finalize_cb,
|
||||
void* finalize_hint,
|
||||
napi_value* result);
|
||||
+#endif // NODE_API_NO_EXTERNAL_BUFFERS_ALLOWED
|
||||
NAPI_EXTERN napi_status napi_get_arraybuffer_info(napi_env env,
|
||||
napi_value arraybuffer,
|
||||
void** data,
|
||||
diff --git a/src/js_native_api_types.h b/src/js_native_api_types.h
|
||||
index 6aba06629b31543c13698dbb02b82db309587c4a..7529b853655a25dd6f945df77c9dd024a0403b26 100644
|
||||
--- a/src/js_native_api_types.h
|
||||
+++ b/src/js_native_api_types.h
|
||||
@@ -92,7 +92,8 @@ typedef enum {
|
||||
napi_date_expected,
|
||||
napi_arraybuffer_expected,
|
||||
napi_detachable_arraybuffer_expected,
|
||||
- napi_would_deadlock // unused
|
||||
+ napi_would_deadlock, // unused
|
||||
+ napi_no_external_buffers_allowed
|
||||
} napi_status;
|
||||
// Note: when adding a new enum value to `napi_status`, please also update
|
||||
// * `const int last_status` in the definition of `napi_get_last_error_info()'
|
||||
diff --git a/src/js_native_api_v8.cc b/src/js_native_api_v8.cc
|
||||
index 1c29c43836a0c35a832e494f8eaebbbe1eee8ea4..108ba4bedbd1684b9a69834ae12347faf4670a27 100644
|
||||
--- a/src/js_native_api_v8.cc
|
||||
+++ b/src/js_native_api_v8.cc
|
||||
@@ -721,29 +721,30 @@ void Reference::SecondPassCallback(
|
||||
} // end of namespace v8impl
|
||||
|
||||
// Warning: Keep in-sync with napi_status enum
|
||||
-static
|
||||
-const char* error_messages[] = {nullptr,
|
||||
- "Invalid argument",
|
||||
- "An object was expected",
|
||||
- "A string was expected",
|
||||
- "A string or symbol was expected",
|
||||
- "A function was expected",
|
||||
- "A number was expected",
|
||||
- "A boolean was expected",
|
||||
- "An array was expected",
|
||||
- "Unknown failure",
|
||||
- "An exception is pending",
|
||||
- "The async work item was cancelled",
|
||||
- "napi_escape_handle already called on scope",
|
||||
- "Invalid handle scope usage",
|
||||
- "Invalid callback scope usage",
|
||||
- "Thread-safe function queue is full",
|
||||
- "Thread-safe function handle is closing",
|
||||
- "A bigint was expected",
|
||||
- "A date was expected",
|
||||
- "An arraybuffer was expected",
|
||||
- "A detachable arraybuffer was expected",
|
||||
- "Main thread would deadlock",
|
||||
+static const char* error_messages[] = {
|
||||
+ nullptr,
|
||||
+ "Invalid argument",
|
||||
+ "An object was expected",
|
||||
+ "A string was expected",
|
||||
+ "A string or symbol was expected",
|
||||
+ "A function was expected",
|
||||
+ "A number was expected",
|
||||
+ "A boolean was expected",
|
||||
+ "An array was expected",
|
||||
+ "Unknown failure",
|
||||
+ "An exception is pending",
|
||||
+ "The async work item was cancelled",
|
||||
+ "napi_escape_handle already called on scope",
|
||||
+ "Invalid handle scope usage",
|
||||
+ "Invalid callback scope usage",
|
||||
+ "Thread-safe function queue is full",
|
||||
+ "Thread-safe function handle is closing",
|
||||
+ "A bigint was expected",
|
||||
+ "A date was expected",
|
||||
+ "An arraybuffer was expected",
|
||||
+ "A detachable arraybuffer was expected",
|
||||
+ "Main thread would deadlock",
|
||||
+ "External buffers are not allowed",
|
||||
};
|
||||
|
||||
napi_status napi_get_last_error_info(napi_env env,
|
||||
@@ -755,7 +756,7 @@ napi_status napi_get_last_error_info(napi_env env,
|
||||
// message in the `napi_status` enum each time a new error message is added.
|
||||
// We don't have a napi_status_last as this would result in an ABI
|
||||
// change each time a message was added.
|
||||
- const int last_status = napi_would_deadlock;
|
||||
+ const int last_status = napi_no_external_buffers_allowed;
|
||||
|
||||
static_assert(
|
||||
NAPI_ARRAYSIZE(error_messages) == last_status + 1,
|
||||
diff --git a/src/node_api.cc b/src/node_api.cc
|
||||
index 60fbe96b8ef272768736ce029bac3ff72f3c84a5..6f8575bb8f289aab041bc126b2fd5f53b1116af5 100644
|
||||
--- a/src/node_api.cc
|
||||
+++ b/src/node_api.cc
|
||||
@@ -929,6 +929,10 @@ napi_status napi_create_external_buffer(napi_env env,
|
||||
NAPI_PREAMBLE(env);
|
||||
CHECK_ARG(env, result);
|
||||
|
||||
+#if defined(V8_ENABLE_SANDBOX)
|
||||
+ return napi_set_last_error(env, napi_no_external_buffers_allowed);
|
||||
+#endif
|
||||
+
|
||||
v8::Isolate* isolate = env->isolate;
|
||||
|
||||
// The finalizer object will delete itself after invoking the callback.
|
||||
diff --git a/src/node_api.h b/src/node_api.h
|
||||
index 1772c67c15afb2d2712b1900a584f627852e3d7e..47703198fed09a61c3e9e06fa5781d340cc39cf9 100644
|
||||
--- a/src/node_api.h
|
||||
+++ b/src/node_api.h
|
||||
@@ -138,12 +138,14 @@ NAPI_EXTERN napi_status napi_create_buffer(napi_env env,
|
||||
size_t length,
|
||||
void** data,
|
||||
napi_value* result);
|
||||
+#ifndef NODE_API_NO_EXTERNAL_BUFFERS_ALLOWED
|
||||
NAPI_EXTERN napi_status napi_create_external_buffer(napi_env env,
|
||||
size_t length,
|
||||
void* data,
|
||||
napi_finalize finalize_cb,
|
||||
void* finalize_hint,
|
||||
napi_value* result);
|
||||
+#endif // NODE_API_NO_EXTERNAL_BUFFERS_ALLOWED
|
||||
NAPI_EXTERN napi_status napi_create_buffer_copy(napi_env env,
|
||||
size_t length,
|
||||
const void* data,
|
||||
diff --git a/test/js-native-api/test_general/test_general.c b/test/js-native-api/test_general/test_general.c
|
||||
index 7b755ce9a9f202eaf91e5103d6c0204925f99cac..b474ab442cb763cb84ec77901da91a6f1471c946 100644
|
||||
--- a/test/js-native-api/test_general/test_general.c
|
||||
+++ b/test/js-native-api/test_general/test_general.c
|
||||
@@ -1,3 +1,8 @@
|
||||
+// we define NODE_API_NO_EXTERNAL_BUFFERS_ALLOWED here to
|
||||
+// validate that it can be used as a form of test itself. It is
|
||||
+// not related to any of the other tests
|
||||
+// defined in the file
|
||||
+#define NODE_API_NO_EXTERNAL_BUFFERS_ALLOWED
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdint.h>
|
||||
diff --git a/test/node-api/test_general/test_general.c b/test/node-api/test_general/test_general.c
|
||||
index d430e2df4f3520fddbc5ce8d260adba565e6c3c9..b8d837d5e45650fcb9ba04030721b0f51377f078 100644
|
||||
--- a/test/node-api/test_general/test_general.c
|
||||
+++ b/test/node-api/test_general/test_general.c
|
||||
@@ -1,4 +1,9 @@
|
||||
#define NAPI_EXPERIMENTAL
|
||||
+// we define NODE_API_NO_EXTERNAL_BUFFERS_ALLOWED here to validate that it can
|
||||
+// be used as a form of test itself. It is
|
||||
+// not related to any of the other tests
|
||||
+// defined in the file
|
||||
+#define NODE_API_NO_EXTERNAL_BUFFERS_ALLOWED
|
||||
#include <node_api.h>
|
||||
#include <stdlib.h>
|
||||
#include "../../js-native-api/common.h"
|
||||
54
patches/node/chore_enable_c_17_for_native_modules.patch
Normal file
54
patches/node/chore_enable_c_17_for_native_modules.patch
Normal file
@@ -0,0 +1,54 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: deepak1556 <hop2deep@gmail.com>
|
||||
Date: Wed, 16 Nov 2022 13:18:23 +0900
|
||||
Subject: chore: enable c++17 for native modules
|
||||
|
||||
V8 headers shipped since 10.4 use C++17 featuers, update the compile flags
|
||||
correspondinly for native addons. C++ version in this file should be updated
|
||||
following the version bump in upstream.
|
||||
|
||||
Next update: crbug.com/1284275
|
||||
|
||||
diff --git a/common.gypi b/common.gypi
|
||||
index c68cf1eb0f9cdd2a8fe314237c1e790fe3690272..b5f33411c68d56ae2a582b0defaa55bf10a830e0 100644
|
||||
--- a/common.gypi
|
||||
+++ b/common.gypi
|
||||
@@ -308,7 +308,10 @@
|
||||
],
|
||||
'msvs_settings': {
|
||||
'VCCLCompilerTool': {
|
||||
- 'AdditionalOptions': ['/Zc:__cplusplus'],
|
||||
+ 'AdditionalOptions': [
|
||||
+ '/Zc:__cplusplus',
|
||||
+ '-std:c++17',
|
||||
+ ],
|
||||
'BufferSecurityCheck': 'true',
|
||||
'DebugInformationFormat': 1, # /Z7 embed info in .obj files
|
||||
'ExceptionHandling': 0, # /EHsc
|
||||
@@ -440,7 +443,7 @@
|
||||
}],
|
||||
[ 'OS in "linux freebsd openbsd solaris android aix cloudabi"', {
|
||||
'cflags': [ '-Wall', '-Wextra', '-Wno-unused-parameter', ],
|
||||
- 'cflags_cc': [ '-fno-rtti', '-fno-exceptions', '-std=gnu++14' ],
|
||||
+ 'cflags_cc': [ '-fno-rtti', '-fno-exceptions', '-std=gnu++17' ],
|
||||
'defines': [ '__STDC_FORMAT_MACROS' ],
|
||||
'ldflags': [ '-rdynamic' ],
|
||||
'target_conditions': [
|
||||
@@ -580,7 +583,7 @@
|
||||
['clang==1', {
|
||||
'xcode_settings': {
|
||||
'GCC_VERSION': 'com.apple.compilers.llvm.clang.1_0',
|
||||
- 'CLANG_CXX_LANGUAGE_STANDARD': 'gnu++14', # -std=gnu++14
|
||||
+ 'CLANG_CXX_LANGUAGE_STANDARD': 'gnu++17', # -std=gnu++17
|
||||
'CLANG_CXX_LIBRARY': 'libc++',
|
||||
},
|
||||
}],
|
||||
@@ -653,7 +656,7 @@
|
||||
'-qASM',
|
||||
],
|
||||
'cflags_cc': [
|
||||
- '-qxclang=-std=c++14',
|
||||
+ '-qxclang=-std=c++17',
|
||||
],
|
||||
'ldflags': [
|
||||
'-q64',
|
||||
@@ -0,0 +1,87 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Samuel Attard <sattard@salesforce.com>
|
||||
Date: Thu, 6 Oct 2022 04:09:16 -0700
|
||||
Subject: fix: expose the built-in electron module via the ESM loader
|
||||
|
||||
This allows usage of `import { app } from 'electron'` and `import('electron')` natively in the browser + non-sandboxed renderer
|
||||
|
||||
diff --git a/lib/internal/modules/esm/get_format.js b/lib/internal/modules/esm/get_format.js
|
||||
index 5ae0e17dcfb5e24a1a117c33c4d42891686e693f..619fe6cef3b02eb575410225f41d3e7d51f37b93 100644
|
||||
--- a/lib/internal/modules/esm/get_format.js
|
||||
+++ b/lib/internal/modules/esm/get_format.js
|
||||
@@ -31,6 +31,7 @@ const protocolHandlers = ObjectAssign(ObjectCreate(null), {
|
||||
'http:': getHttpProtocolModuleFormat,
|
||||
'https:': getHttpProtocolModuleFormat,
|
||||
'node:'() { return 'builtin'; },
|
||||
+ 'electron:'() { return 'commonjs'; },
|
||||
});
|
||||
|
||||
function getDataProtocolModuleFormat(parsed) {
|
||||
diff --git a/lib/internal/modules/esm/resolve.js b/lib/internal/modules/esm/resolve.js
|
||||
index 3576f75f0a40a64dceb7e2649b344b83ebc04b39..314fbb78931eef154a1e47c655e2d4bafe11bac3 100644
|
||||
--- a/lib/internal/modules/esm/resolve.js
|
||||
+++ b/lib/internal/modules/esm/resolve.js
|
||||
@@ -888,6 +888,8 @@ function parsePackageName(specifier, base) {
|
||||
return { packageName, packageSubpath, isScoped };
|
||||
}
|
||||
|
||||
+const electronSpecifiers = new SafeSet(['electron', 'electron/main', 'electron/common', 'electron/renderer']);
|
||||
+
|
||||
/**
|
||||
* @param {string} specifier
|
||||
* @param {string | URL | undefined} base
|
||||
@@ -898,6 +900,10 @@ function packageResolve(specifier, base, conditions) {
|
||||
if (NativeModule.canBeRequiredByUsers(specifier))
|
||||
return new URL('node:' + specifier);
|
||||
|
||||
+ if (electronSpecifiers.has(specifier)) {
|
||||
+ return new URL('electron:electron');
|
||||
+ }
|
||||
+
|
||||
const { packageName, packageSubpath, isScoped } =
|
||||
parsePackageName(specifier, base);
|
||||
|
||||
@@ -1099,7 +1105,7 @@ function checkIfDisallowedImport(specifier, parsed, parsedParentURL) {
|
||||
|
||||
function throwIfUnsupportedURLProtocol(url) {
|
||||
if (url.protocol !== 'file:' && url.protocol !== 'data:' &&
|
||||
- url.protocol !== 'node:') {
|
||||
+ url.protocol !== 'node:' && url.protocol !== 'electron:') {
|
||||
throw new ERR_UNSUPPORTED_ESM_URL_SCHEME(url);
|
||||
}
|
||||
}
|
||||
diff --git a/lib/internal/modules/esm/translators.js b/lib/internal/modules/esm/translators.js
|
||||
index d7f4c7edec63d3ce500955a37c6eac00e3e524fd..b97cac53365b121f8e232f0085ff166511c3dda3 100644
|
||||
--- a/lib/internal/modules/esm/translators.js
|
||||
+++ b/lib/internal/modules/esm/translators.js
|
||||
@@ -155,7 +155,7 @@ translators.set('commonjs', async function commonjsStrategy(url, source,
|
||||
|
||||
if (!cjsParse) await initCJSParse();
|
||||
const { module, exportNames } = cjsPreparseModuleExports(filename);
|
||||
- const namesWithDefault = exportNames.has('default') ?
|
||||
+ const namesWithDefault = filename === 'electron' ? ['default', ...Object.keys(module.exports)] : exportNames.has('default') ?
|
||||
[...exportNames] : ['default', ...exportNames];
|
||||
|
||||
return new ModuleWrap(url, undefined, namesWithDefault, function() {
|
||||
@@ -174,7 +174,7 @@ translators.set('commonjs', async function commonjsStrategy(url, source,
|
||||
}
|
||||
}
|
||||
|
||||
- for (const exportName of exportNames) {
|
||||
+ for (const exportName of namesWithDefault) {
|
||||
if (!ObjectPrototypeHasOwnProperty(exports, exportName) ||
|
||||
exportName === 'default')
|
||||
continue;
|
||||
diff --git a/lib/internal/url.js b/lib/internal/url.js
|
||||
index 939374a495856cf2b9c573fa98dc1895eee5e143..c37258ac29e8b7558c1f9a2af7ba6bdd0eab1355 100644
|
||||
--- a/lib/internal/url.js
|
||||
+++ b/lib/internal/url.js
|
||||
@@ -1418,6 +1418,8 @@ function fileURLToPath(path) {
|
||||
path = new URL(path);
|
||||
else if (!isURLInstance(path))
|
||||
throw new ERR_INVALID_ARG_TYPE('path', ['string', 'URL'], path);
|
||||
+ if (path.protocol === 'electron:')
|
||||
+ return 'electron';
|
||||
if (path.protocol !== 'file:')
|
||||
throw new ERR_INVALID_URL_SCHEME('file');
|
||||
return isWindows ? getPathFromURLWin32(path) : getPathFromURLPosix(path);
|
||||
@@ -9,3 +9,7 @@ fix_disable_implies_dcheck_for_node_stream_array_buffers.patch
|
||||
revert_fix_cppgc_removed_deleted_cstors_in_cppheapcreateparams.patch
|
||||
revert_runtime_dhceck_terminating_exception_in_microtasks.patch
|
||||
chore_disable_is_execution_terminating_dcheck.patch
|
||||
cherry-pick-27fa951ae4a3.patch
|
||||
cherry-pick-c79148742421.patch
|
||||
cherry-pick-0f481c9ddf2a.patch
|
||||
cherry-pick-28b9c1c04e78.patch
|
||||
|
||||
@@ -9,7 +9,7 @@ necessary for native modules to load.
|
||||
Also, some fixes relating to mksnapshot on ARM.
|
||||
|
||||
diff --git a/BUILD.gn b/BUILD.gn
|
||||
index 83082271b8b76179b41e943190303e31fa639a95..0a23171a391606bb3408dcf8a488d075a148443a 100644
|
||||
index 7b41a7500e55a5dbbef512dd8bfcc7dbc65e982c..8039c91f8800b516a64b84a1d7a9701932decae2 100644
|
||||
--- a/BUILD.gn
|
||||
+++ b/BUILD.gn
|
||||
@@ -663,7 +663,7 @@ config("internal_config") {
|
||||
@@ -21,7 +21,7 @@ index 83082271b8b76179b41e943190303e31fa639a95..0a23171a391606bb3408dcf8a488d075
|
||||
defines += [ "BUILDING_V8_SHARED" ]
|
||||
}
|
||||
|
||||
@@ -6166,7 +6166,7 @@ if (current_toolchain == v8_generator_toolchain) {
|
||||
@@ -6169,7 +6169,7 @@ if (current_toolchain == v8_generator_toolchain) {
|
||||
"src/interpreter/bytecodes.h",
|
||||
]
|
||||
|
||||
|
||||
69
patches/v8/cherry-pick-0f481c9ddf2a.patch
Normal file
69
patches/v8/cherry-pick-0f481c9ddf2a.patch
Normal file
@@ -0,0 +1,69 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Clemens Backes <clemensb@chromium.org>
|
||||
Date: Thu, 15 Dec 2022 11:58:50 +0100
|
||||
Subject: Merged: [wasm][turbofan] Load 32-bit values more efficiently
|
||||
|
||||
When loading a 32-bit value from the stack, just load 32 bit and
|
||||
zero-extend them into the target register, instead of loading the full
|
||||
64 bits.
|
||||
|
||||
As there are things to fix (see https://crbug.com/1356461), we only
|
||||
enable this optimization for Wasm for now.
|
||||
|
||||
Also include the related fix https://crrev.com/c/4096985.
|
||||
|
||||
R=mslekova@chromium.org
|
||||
|
||||
(cherry picked from commit 2ee52447c878721c89a55a780eb689ecba6817d3)
|
||||
(cherry picked from commit a38209949fcbf045231c316e2d790b8b70ccb7ef)
|
||||
|
||||
Bug: chromium:1395604
|
||||
Change-Id: I54a2182ada6fadbfcf5565f0dc8d4f477ecff393
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/4110897
|
||||
Reviewed-by: Maya Lekova <mslekova@chromium.org>
|
||||
Commit-Queue: Clemens Backes <clemensb@chromium.org>
|
||||
Cr-Commit-Position: refs/branch-heads/10.8@{#46}
|
||||
Cr-Branched-From: f1bc03fd6b4c201abd9f0fd9d51fb989150f97b9-refs/heads/10.8.168@{#1}
|
||||
Cr-Branched-From: 237de893e1c0a0628a57d0f5797483d3add7f005-refs/heads/main@{#83672}
|
||||
|
||||
diff --git a/src/compiler/backend/x64/code-generator-x64.cc b/src/compiler/backend/x64/code-generator-x64.cc
|
||||
index 3a882f8c7938820b787d0a59c1208ea9517dde15..87ac836d59a1901a5513cb14dc0c0d2e25922be3 100644
|
||||
--- a/src/compiler/backend/x64/code-generator-x64.cc
|
||||
+++ b/src/compiler/backend/x64/code-generator-x64.cc
|
||||
@@ -5215,7 +5215,22 @@ void CodeGenerator::AssembleMove(InstructionOperand* source,
|
||||
case MoveType::kStackToRegister: {
|
||||
Operand src = g.ToOperand(source);
|
||||
if (source->IsStackSlot()) {
|
||||
- __ movq(g.ToRegister(destination), src);
|
||||
+ MachineRepresentation mr =
|
||||
+ LocationOperand::cast(source)->representation();
|
||||
+ const bool is_32_bit = mr == MachineRepresentation::kWord32 ||
|
||||
+ mr == MachineRepresentation::kCompressed ||
|
||||
+ mr == MachineRepresentation::kCompressedPointer;
|
||||
+ // TODO(13581): Fix this for other code kinds (see
|
||||
+ // https://crbug.com/1356461).
|
||||
+ if (code_kind() == CodeKind::WASM_FUNCTION && is_32_bit) {
|
||||
+ // When we need only 32 bits, move only 32 bits. Benefits:
|
||||
+ // - Save a byte here and there (depending on the destination
|
||||
+ // register; "movl eax, ..." is smaller than "movq rax, ...").
|
||||
+ // - Safeguard against accidental decompression of compressed slots.
|
||||
+ __ movl(g.ToRegister(destination), src);
|
||||
+ } else {
|
||||
+ __ movq(g.ToRegister(destination), src);
|
||||
+ }
|
||||
} else {
|
||||
DCHECK(source->IsFPStackSlot());
|
||||
XMMRegister dst = g.ToDoubleRegister(destination);
|
||||
diff --git a/src/wasm/graph-builder-interface.cc b/src/wasm/graph-builder-interface.cc
|
||||
index 31a06d5a138ac610b10f5eea6b338d44eac3373a..ca8394e5055889c81b57892c4efed53cc6bfa3bc 100644
|
||||
--- a/src/wasm/graph-builder-interface.cc
|
||||
+++ b/src/wasm/graph-builder-interface.cc
|
||||
@@ -2060,7 +2060,7 @@ class WasmGraphBuildingInterface {
|
||||
if (exception_value != nullptr) {
|
||||
// TODO(manoskouk): Can we assign a wasm type to the exception value?
|
||||
*exception_value = builder_->LoopExitValue(
|
||||
- *exception_value, MachineRepresentation::kWord32);
|
||||
+ *exception_value, MachineRepresentation::kTaggedPointer);
|
||||
}
|
||||
if (wrap_exit_values) {
|
||||
WrapLocalsAtLoopExit(decoder, control);
|
||||
209
patches/v8/cherry-pick-27fa951ae4a3.patch
Normal file
209
patches/v8/cherry-pick-27fa951ae4a3.patch
Normal file
@@ -0,0 +1,209 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Toon Verwaest <verwaest@chromium.org>
|
||||
Date: Wed, 30 Nov 2022 15:07:26 +0100
|
||||
Subject: Fix eval tracking
|
||||
|
||||
Due to mismatch in strictness we otherwise invalidly mark scopes as
|
||||
calling sloppy eval.
|
||||
|
||||
Bug: chromium:1394403
|
||||
Change-Id: Iece45df87f171616a2917c2aba5540636880a7c6
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/4066044
|
||||
Reviewed-by: Igor Sheludko <ishell@chromium.org>
|
||||
Commit-Queue: Toon Verwaest <verwaest@chromium.org>
|
||||
Cr-Commit-Position: refs/heads/main@{#84575}
|
||||
|
||||
diff --git a/src/ast/scopes.cc b/src/ast/scopes.cc
|
||||
index 8d52d0792bcfc108141fc5d2016b5942ce93df07..7bf3bcc7796d60319c604e03d61a6c8a2b762581 100644
|
||||
--- a/src/ast/scopes.cc
|
||||
+++ b/src/ast/scopes.cc
|
||||
@@ -885,9 +885,8 @@ void DeclarationScope::AddLocal(Variable* var) {
|
||||
}
|
||||
|
||||
void Scope::Snapshot::Reparent(DeclarationScope* new_parent) {
|
||||
- DCHECK(!IsCleared());
|
||||
- DCHECK_EQ(new_parent, outer_scope_and_calls_eval_.GetPointer()->inner_scope_);
|
||||
- DCHECK_EQ(new_parent->outer_scope_, outer_scope_and_calls_eval_.GetPointer());
|
||||
+ DCHECK_EQ(new_parent, outer_scope_->inner_scope_);
|
||||
+ DCHECK_EQ(new_parent->outer_scope_, outer_scope_);
|
||||
DCHECK_EQ(new_parent, new_parent->GetClosureScope());
|
||||
DCHECK_NULL(new_parent->inner_scope_);
|
||||
DCHECK(new_parent->unresolved_list_.is_empty());
|
||||
@@ -912,12 +911,11 @@ void Scope::Snapshot::Reparent(DeclarationScope* new_parent) {
|
||||
new_parent->sibling_ = top_inner_scope_;
|
||||
}
|
||||
|
||||
- Scope* outer_scope = outer_scope_and_calls_eval_.GetPointer();
|
||||
- new_parent->unresolved_list_.MoveTail(&outer_scope->unresolved_list_,
|
||||
+ new_parent->unresolved_list_.MoveTail(&outer_scope_->unresolved_list_,
|
||||
top_unresolved_);
|
||||
|
||||
// Move temporaries allocated for complex parameter initializers.
|
||||
- DeclarationScope* outer_closure = outer_scope->GetClosureScope();
|
||||
+ DeclarationScope* outer_closure = outer_scope_->GetClosureScope();
|
||||
for (auto it = top_local_; it != outer_closure->locals()->end(); ++it) {
|
||||
Variable* local = *it;
|
||||
DCHECK_EQ(VariableMode::kTemporary, local->mode());
|
||||
@@ -929,16 +927,10 @@ void Scope::Snapshot::Reparent(DeclarationScope* new_parent) {
|
||||
outer_closure->locals_.Rewind(top_local_);
|
||||
|
||||
// Move eval calls since Snapshot's creation into new_parent.
|
||||
- if (outer_scope_and_calls_eval_->calls_eval_) {
|
||||
- new_parent->RecordDeclarationScopeEvalCall();
|
||||
- new_parent->inner_scope_calls_eval_ = true;
|
||||
+ if (outer_scope_->calls_eval_) {
|
||||
+ new_parent->RecordEvalCall();
|
||||
+ declaration_scope_->sloppy_eval_can_extend_vars_ = false;
|
||||
}
|
||||
-
|
||||
- // We are in the arrow function case. The calls eval we may have recorded
|
||||
- // is intended for the inner scope and we should simply restore the
|
||||
- // original "calls eval" flag of the outer scope.
|
||||
- RestoreEvalFlag();
|
||||
- Clear();
|
||||
}
|
||||
|
||||
void Scope::ReplaceOuterScope(Scope* outer) {
|
||||
@@ -2576,6 +2568,9 @@ void Scope::AllocateVariablesRecursively() {
|
||||
this->ForEach([](Scope* scope) -> Iteration {
|
||||
DCHECK(!scope->already_resolved_);
|
||||
if (WasLazilyParsed(scope)) return Iteration::kContinue;
|
||||
+ if (scope->sloppy_eval_can_extend_vars_) {
|
||||
+ scope->num_heap_slots_ = Context::MIN_CONTEXT_EXTENDED_SLOTS;
|
||||
+ }
|
||||
DCHECK_EQ(scope->ContextHeaderLength(), scope->num_heap_slots_);
|
||||
|
||||
// Allocate variables for this scope.
|
||||
diff --git a/src/ast/scopes.h b/src/ast/scopes.h
|
||||
index 32e16b80b261fbeffc1d4710f8a2119044cbf28e..3d062685643ad7bc31d9a45b92fa9dd924f83425 100644
|
||||
--- a/src/ast/scopes.h
|
||||
+++ b/src/ast/scopes.h
|
||||
@@ -110,12 +110,6 @@ class V8_EXPORT_PRIVATE Scope : public NON_EXPORTED_BASE(ZoneObject) {
|
||||
|
||||
class Snapshot final {
|
||||
public:
|
||||
- Snapshot()
|
||||
- : outer_scope_and_calls_eval_(nullptr, false),
|
||||
- top_unresolved_(),
|
||||
- top_local_() {
|
||||
- DCHECK(IsCleared());
|
||||
- }
|
||||
inline explicit Snapshot(Scope* scope);
|
||||
|
||||
// Disallow copy and move.
|
||||
@@ -123,45 +117,31 @@ class V8_EXPORT_PRIVATE Scope : public NON_EXPORTED_BASE(ZoneObject) {
|
||||
Snapshot(Snapshot&&) = delete;
|
||||
|
||||
~Snapshot() {
|
||||
- // If we're still active, there was no arrow function. In that case outer
|
||||
- // calls eval if it already called eval before this snapshot started, or
|
||||
- // if the code during the snapshot called eval.
|
||||
- if (!IsCleared() && outer_scope_and_calls_eval_.GetPayload()) {
|
||||
- RestoreEvalFlag();
|
||||
+ // Restore eval flags from before the scope was active.
|
||||
+ if (sloppy_eval_can_extend_vars_) {
|
||||
+ declaration_scope_->sloppy_eval_can_extend_vars_ = true;
|
||||
}
|
||||
- }
|
||||
-
|
||||
- void RestoreEvalFlag() {
|
||||
- if (outer_scope_and_calls_eval_.GetPayload()) {
|
||||
- // This recreates both calls_eval and sloppy_eval_can_extend_vars.
|
||||
- outer_scope_and_calls_eval_.GetPointer()->RecordEvalCall();
|
||||
+ if (calls_eval_) {
|
||||
+ outer_scope_->calls_eval_ = true;
|
||||
}
|
||||
}
|
||||
|
||||
void Reparent(DeclarationScope* new_parent);
|
||||
- bool IsCleared() const {
|
||||
- return outer_scope_and_calls_eval_.GetPointer() == nullptr;
|
||||
- }
|
||||
-
|
||||
- void Clear() {
|
||||
- outer_scope_and_calls_eval_.SetPointer(nullptr);
|
||||
-#ifdef DEBUG
|
||||
- outer_scope_and_calls_eval_.SetPayload(false);
|
||||
- top_inner_scope_ = nullptr;
|
||||
- top_local_ = base::ThreadedList<Variable>::Iterator();
|
||||
- top_unresolved_ = UnresolvedList::Iterator();
|
||||
-#endif
|
||||
- }
|
||||
|
||||
private:
|
||||
- // During tracking calls_eval caches whether the outer scope called eval.
|
||||
- // Upon move assignment we store whether the new inner scope calls eval into
|
||||
- // the move target calls_eval bit, and restore calls eval on the outer
|
||||
- // scope.
|
||||
- base::PointerWithPayload<Scope, bool, 1> outer_scope_and_calls_eval_;
|
||||
+ Scope* outer_scope_;
|
||||
+ Scope* declaration_scope_;
|
||||
Scope* top_inner_scope_;
|
||||
UnresolvedList::Iterator top_unresolved_;
|
||||
base::ThreadedList<Variable>::Iterator top_local_;
|
||||
+ // While the scope is active, the scope caches the flag values for
|
||||
+ // outer_scope_ / declaration_scope_ they can be used to know what happened
|
||||
+ // while parsing the arrow head. If this turns out to be an arrow head, new
|
||||
+ // values on the respective scopes will be cleared and moved to the inner
|
||||
+ // scope. Otherwise the cached flags will be merged with the flags from the
|
||||
+ // arrow head.
|
||||
+ bool calls_eval_;
|
||||
+ bool sloppy_eval_can_extend_vars_;
|
||||
};
|
||||
|
||||
enum class DeserializationMode { kIncludingVariables, kScopesOnly };
|
||||
@@ -907,8 +887,8 @@ class V8_EXPORT_PRIVATE DeclarationScope : public Scope {
|
||||
void RecordDeclarationScopeEvalCall() {
|
||||
calls_eval_ = true;
|
||||
|
||||
- // If this isn't a sloppy eval, we don't care about it.
|
||||
- if (language_mode() != LanguageMode::kSloppy) return;
|
||||
+ // The caller already checked whether we're in sloppy mode.
|
||||
+ CHECK(is_sloppy(language_mode()));
|
||||
|
||||
// Sloppy eval in script scopes can only introduce global variables anyway,
|
||||
// so we don't care that it calls sloppy eval.
|
||||
@@ -942,7 +922,6 @@ class V8_EXPORT_PRIVATE DeclarationScope : public Scope {
|
||||
}
|
||||
|
||||
sloppy_eval_can_extend_vars_ = true;
|
||||
- num_heap_slots_ = Context::MIN_CONTEXT_EXTENDED_SLOTS;
|
||||
}
|
||||
|
||||
bool sloppy_eval_can_extend_vars() const {
|
||||
@@ -1367,7 +1346,9 @@ class V8_EXPORT_PRIVATE DeclarationScope : public Scope {
|
||||
|
||||
void Scope::RecordEvalCall() {
|
||||
calls_eval_ = true;
|
||||
- GetDeclarationScope()->RecordDeclarationScopeEvalCall();
|
||||
+ if (is_sloppy(language_mode())) {
|
||||
+ GetDeclarationScope()->RecordDeclarationScopeEvalCall();
|
||||
+ }
|
||||
RecordInnerScopeEvalCall();
|
||||
// The eval contents might access "super" (if it's inside a function that
|
||||
// binds super).
|
||||
@@ -1380,14 +1361,18 @@ void Scope::RecordEvalCall() {
|
||||
}
|
||||
|
||||
Scope::Snapshot::Snapshot(Scope* scope)
|
||||
- : outer_scope_and_calls_eval_(scope, scope->calls_eval_),
|
||||
+ : outer_scope_(scope),
|
||||
+ declaration_scope_(scope->GetDeclarationScope()),
|
||||
top_inner_scope_(scope->inner_scope_),
|
||||
top_unresolved_(scope->unresolved_list_.end()),
|
||||
- top_local_(scope->GetClosureScope()->locals_.end()) {
|
||||
- // Reset in order to record eval calls during this Snapshot's lifetime.
|
||||
- outer_scope_and_calls_eval_.GetPointer()->calls_eval_ = false;
|
||||
- outer_scope_and_calls_eval_.GetPointer()->sloppy_eval_can_extend_vars_ =
|
||||
- false;
|
||||
+ top_local_(scope->GetClosureScope()->locals_.end()),
|
||||
+ calls_eval_(outer_scope_->calls_eval_),
|
||||
+ sloppy_eval_can_extend_vars_(
|
||||
+ declaration_scope_->sloppy_eval_can_extend_vars_) {
|
||||
+ // Reset in order to record (sloppy) eval calls during this Snapshot's
|
||||
+ // lifetime.
|
||||
+ outer_scope_->calls_eval_ = false;
|
||||
+ declaration_scope_->sloppy_eval_can_extend_vars_ = false;
|
||||
}
|
||||
|
||||
class ModuleScope final : public DeclarationScope {
|
||||
77
patches/v8/cherry-pick-28b9c1c04e78.patch
Normal file
77
patches/v8/cherry-pick-28b9c1c04e78.patch
Normal file
@@ -0,0 +1,77 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Clemens Backes <clemensb@chromium.org>
|
||||
Date: Tue, 13 Dec 2022 22:37:27 +0100
|
||||
Subject: Merged: [arm] Do not emit the constant pool before a branch
|
||||
|
||||
After computing the branch offset but before emitting the actual branch,
|
||||
we should not emit a constant pool. Otherwise the previously computed
|
||||
offset would be off.
|
||||
|
||||
Instead of handling this indirectly via the Assembler::branch_offset
|
||||
method, do this directly in the Assembler::b method (and friends), so it
|
||||
is not missed on other call sites.
|
||||
|
||||
R=nicohartmann@chromium.org
|
||||
|
||||
(cherry picked from commit 9be597d194e108ba718610b9a611fe19a0fbfde5)
|
||||
Bug: chromium:1399424
|
||||
|
||||
Change-Id: Ie30ba70508b4fb8913f79e049a33108608915704
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/4118864
|
||||
Reviewed-by: Nico Hartmann <nicohartmann@chromium.org>
|
||||
Commit-Queue: Clemens Backes <clemensb@chromium.org>
|
||||
Cr-Commit-Position: refs/branch-heads/10.8@{#48}
|
||||
Cr-Branched-From: f1bc03fd6b4c201abd9f0fd9d51fb989150f97b9-refs/heads/10.8.168@{#1}
|
||||
Cr-Branched-From: 237de893e1c0a0628a57d0f5797483d3add7f005-refs/heads/main@{#83672}
|
||||
|
||||
diff --git a/src/codegen/arm/assembler-arm.cc b/src/codegen/arm/assembler-arm.cc
|
||||
index 645edb17a4892aec70f0221cec889996a6868242..a95d4df308fd4651093a4911ad1c50226e059ebb 100644
|
||||
--- a/src/codegen/arm/assembler-arm.cc
|
||||
+++ b/src/codegen/arm/assembler-arm.cc
|
||||
@@ -1462,10 +1462,6 @@ int Assembler::branch_offset(Label* L) {
|
||||
L->link_to(pc_offset());
|
||||
}
|
||||
|
||||
- // Block the emission of the constant pool, since the branch instruction must
|
||||
- // be emitted at the pc offset recorded by the label.
|
||||
- if (!is_const_pool_blocked()) BlockConstPoolFor(1);
|
||||
-
|
||||
return target_pos - (pc_offset() + Instruction::kPcLoadDelta);
|
||||
}
|
||||
|
||||
@@ -1476,6 +1472,11 @@ void Assembler::b(int branch_offset, Condition cond, RelocInfo::Mode rmode) {
|
||||
int imm24 = branch_offset >> 2;
|
||||
const bool b_imm_check = is_int24(imm24);
|
||||
CHECK(b_imm_check);
|
||||
+
|
||||
+ // Block the emission of the constant pool before the next instruction.
|
||||
+ // Otherwise the passed-in branch offset would be off.
|
||||
+ BlockConstPoolFor(1);
|
||||
+
|
||||
emit(cond | B27 | B25 | (imm24 & kImm24Mask));
|
||||
|
||||
if (cond == al) {
|
||||
@@ -1490,6 +1491,11 @@ void Assembler::bl(int branch_offset, Condition cond, RelocInfo::Mode rmode) {
|
||||
int imm24 = branch_offset >> 2;
|
||||
const bool bl_imm_check = is_int24(imm24);
|
||||
CHECK(bl_imm_check);
|
||||
+
|
||||
+ // Block the emission of the constant pool before the next instruction.
|
||||
+ // Otherwise the passed-in branch offset would be off.
|
||||
+ BlockConstPoolFor(1);
|
||||
+
|
||||
emit(cond | B27 | B25 | B24 | (imm24 & kImm24Mask));
|
||||
}
|
||||
|
||||
@@ -1499,6 +1505,11 @@ void Assembler::blx(int branch_offset) {
|
||||
int imm24 = branch_offset >> 2;
|
||||
const bool blx_imm_check = is_int24(imm24);
|
||||
CHECK(blx_imm_check);
|
||||
+
|
||||
+ // Block the emission of the constant pool before the next instruction.
|
||||
+ // Otherwise the passed-in branch offset would be off.
|
||||
+ BlockConstPoolFor(1);
|
||||
+
|
||||
emit(kSpecialCondition | B27 | B25 | h | (imm24 & kImm24Mask));
|
||||
}
|
||||
|
||||
122
patches/v8/cherry-pick-c79148742421.patch
Normal file
122
patches/v8/cherry-pick-c79148742421.patch
Normal file
@@ -0,0 +1,122 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Shu-yu Guo <syg@chromium.org>
|
||||
Date: Fri, 28 Oct 2022 10:21:27 -0700
|
||||
Subject: Merged: Reland "[Promise.any] Fix errors allocation"
|
||||
|
||||
Bug: chromium:1379054
|
||||
|
||||
(cherry picked from commit 8b35091b2d244c975975e1c78e4cd09cb479b5dc)
|
||||
|
||||
Change-Id: Iec8f8bb51f4434d6ae86887cf742f2883a9b7bef
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/4004804
|
||||
Reviewed-by: Adam Klein <adamk@chromium.org>
|
||||
Commit-Queue: Shu-yu Guo <syg@chromium.org>
|
||||
Cr-Commit-Position: refs/branch-heads/10.8@{#34}
|
||||
Cr-Branched-From: f1bc03fd6b4c201abd9f0fd9d51fb989150f97b9-refs/heads/10.8.168@{#1}
|
||||
Cr-Branched-From: 237de893e1c0a0628a57d0f5797483d3add7f005-refs/heads/main@{#83672}
|
||||
|
||||
diff --git a/include/v8-version.h b/include/v8-version.h
|
||||
index 40515772ef03946510aee70bb5f2d5cca4c74818..aa72539443e9ad05f56bfe10002632e621a09b43 100644
|
||||
--- a/include/v8-version.h
|
||||
+++ b/include/v8-version.h
|
||||
@@ -11,7 +11,7 @@
|
||||
#define V8_MAJOR_VERSION 10
|
||||
#define V8_MINOR_VERSION 6
|
||||
#define V8_BUILD_NUMBER 194
|
||||
-#define V8_PATCH_LEVEL 26
|
||||
+#define V8_PATCH_LEVEL 27
|
||||
|
||||
// Use 1 for candidates and 0 otherwise.
|
||||
// (Boolean macro values are not supported by all preprocessors.)
|
||||
diff --git a/src/builtins/promise-any.tq b/src/builtins/promise-any.tq
|
||||
index ffb285a06a83557d8657aef6c04acc5c65513a62..7e707e649f11bc946a6d1173180d7293fe94d8ce 100644
|
||||
--- a/src/builtins/promise-any.tq
|
||||
+++ b/src/builtins/promise-any.tq
|
||||
@@ -119,7 +119,19 @@ PromiseAnyRejectElementClosure(
|
||||
kPromiseAnyRejectElementRemainingSlot);
|
||||
|
||||
// 9. Set errors[index] to x.
|
||||
- const newCapacity = IntPtrMax(SmiUntag(remainingElementsCount), index + 1);
|
||||
+
|
||||
+ // The max computation below is an optimization to avoid excessive allocations
|
||||
+ // in the case of input promises being asynchronously rejected in ascending
|
||||
+ // index order.
|
||||
+ //
|
||||
+ // Note that subtracting 1 from remainingElementsCount is intentional. The
|
||||
+ // value of remainingElementsCount is 1 larger than the actual value during
|
||||
+ // iteration. So in the case of synchronous rejection, newCapacity is the
|
||||
+ // correct size by subtracting 1. In the case of asynchronous rejection this
|
||||
+ // is 1 smaller than the correct size, but is not incorrect as it is maxed
|
||||
+ // with index + 1.
|
||||
+ const newCapacity =
|
||||
+ IntPtrMax(SmiUntag(remainingElementsCount) - 1, index + 1);
|
||||
if (newCapacity > errors.length_intptr) deferred {
|
||||
errors = ExtractFixedArray(errors, 0, errors.length_intptr, newCapacity);
|
||||
*ContextSlot(
|
||||
@@ -306,6 +318,7 @@ Reject(JSAny) {
|
||||
PromiseAnyRejectElementContextSlots::
|
||||
kPromiseAnyRejectElementErrorsSlot);
|
||||
|
||||
+ check(errors.length == index - 1);
|
||||
const error = ConstructAggregateError(errors);
|
||||
// 3. Return ThrowCompletion(error).
|
||||
goto Reject(error);
|
||||
diff --git a/tools/v8heapconst.py b/tools/v8heapconst.py
|
||||
index 925c866c9ac5c9377f8ee75a312ce2710eb88f1c..2764c00a5ce1563a30f5927f722b36b91901036c 100644
|
||||
--- a/tools/v8heapconst.py
|
||||
+++ b/tools/v8heapconst.py
|
||||
@@ -544,30 +544,30 @@ KNOWN_OBJECTS = {
|
||||
("old_space", 0x04625): "StringSplitCache",
|
||||
("old_space", 0x04a2d): "RegExpMultipleCache",
|
||||
("old_space", 0x04e35): "BuiltinsConstantsTable",
|
||||
- ("old_space", 0x05285): "AsyncFunctionAwaitRejectSharedFun",
|
||||
- ("old_space", 0x052a9): "AsyncFunctionAwaitResolveSharedFun",
|
||||
- ("old_space", 0x052cd): "AsyncGeneratorAwaitRejectSharedFun",
|
||||
- ("old_space", 0x052f1): "AsyncGeneratorAwaitResolveSharedFun",
|
||||
- ("old_space", 0x05315): "AsyncGeneratorYieldResolveSharedFun",
|
||||
- ("old_space", 0x05339): "AsyncGeneratorReturnResolveSharedFun",
|
||||
- ("old_space", 0x0535d): "AsyncGeneratorReturnClosedRejectSharedFun",
|
||||
- ("old_space", 0x05381): "AsyncGeneratorReturnClosedResolveSharedFun",
|
||||
- ("old_space", 0x053a5): "AsyncIteratorValueUnwrapSharedFun",
|
||||
- ("old_space", 0x053c9): "PromiseAllResolveElementSharedFun",
|
||||
- ("old_space", 0x053ed): "PromiseAllSettledResolveElementSharedFun",
|
||||
- ("old_space", 0x05411): "PromiseAllSettledRejectElementSharedFun",
|
||||
- ("old_space", 0x05435): "PromiseAnyRejectElementSharedFun",
|
||||
- ("old_space", 0x05459): "PromiseCapabilityDefaultRejectSharedFun",
|
||||
- ("old_space", 0x0547d): "PromiseCapabilityDefaultResolveSharedFun",
|
||||
- ("old_space", 0x054a1): "PromiseCatchFinallySharedFun",
|
||||
- ("old_space", 0x054c5): "PromiseGetCapabilitiesExecutorSharedFun",
|
||||
- ("old_space", 0x054e9): "PromiseThenFinallySharedFun",
|
||||
- ("old_space", 0x0550d): "PromiseThrowerFinallySharedFun",
|
||||
- ("old_space", 0x05531): "PromiseValueThunkFinallySharedFun",
|
||||
- ("old_space", 0x05555): "ProxyRevokeSharedFun",
|
||||
- ("old_space", 0x05579): "ShadowRealmImportValueFulfilledSFI",
|
||||
- ("old_space", 0x0559d): "SourceTextModuleExecuteAsyncModuleFulfilledSFI",
|
||||
- ("old_space", 0x055c1): "SourceTextModuleExecuteAsyncModuleRejectedSFI",
|
||||
+ ("old_space", 0x05289): "AsyncFunctionAwaitRejectSharedFun",
|
||||
+ ("old_space", 0x052ad): "AsyncFunctionAwaitResolveSharedFun",
|
||||
+ ("old_space", 0x052d1): "AsyncGeneratorAwaitRejectSharedFun",
|
||||
+ ("old_space", 0x052f5): "AsyncGeneratorAwaitResolveSharedFun",
|
||||
+ ("old_space", 0x05319): "AsyncGeneratorYieldResolveSharedFun",
|
||||
+ ("old_space", 0x0533d): "AsyncGeneratorReturnResolveSharedFun",
|
||||
+ ("old_space", 0x05361): "AsyncGeneratorReturnClosedRejectSharedFun",
|
||||
+ ("old_space", 0x05385): "AsyncGeneratorReturnClosedResolveSharedFun",
|
||||
+ ("old_space", 0x053a9): "AsyncIteratorValueUnwrapSharedFun",
|
||||
+ ("old_space", 0x053cd): "PromiseAllResolveElementSharedFun",
|
||||
+ ("old_space", 0x053f1): "PromiseAllSettledResolveElementSharedFun",
|
||||
+ ("old_space", 0x05415): "PromiseAllSettledRejectElementSharedFun",
|
||||
+ ("old_space", 0x05439): "PromiseAnyRejectElementSharedFun",
|
||||
+ ("old_space", 0x0545d): "PromiseCapabilityDefaultRejectSharedFun",
|
||||
+ ("old_space", 0x05481): "PromiseCapabilityDefaultResolveSharedFun",
|
||||
+ ("old_space", 0x054a5): "PromiseCatchFinallySharedFun",
|
||||
+ ("old_space", 0x054c9): "PromiseGetCapabilitiesExecutorSharedFun",
|
||||
+ ("old_space", 0x054ed): "PromiseThenFinallySharedFun",
|
||||
+ ("old_space", 0x05511): "PromiseThrowerFinallySharedFun",
|
||||
+ ("old_space", 0x05535): "PromiseValueThunkFinallySharedFun",
|
||||
+ ("old_space", 0x05559): "ProxyRevokeSharedFun",
|
||||
+ ("old_space", 0x0557d): "ShadowRealmImportValueFulfilledSFI",
|
||||
+ ("old_space", 0x055a1): "SourceTextModuleExecuteAsyncModuleFulfilledSFI",
|
||||
+ ("old_space", 0x055c5): "SourceTextModuleExecuteAsyncModuleRejectedSFI",
|
||||
}
|
||||
|
||||
# Lower 32 bits of first page addresses for various heap spaces.
|
||||
@@ -12,7 +12,7 @@ This patch can be safely removed if, when it is removed, `node.lib` does not
|
||||
contain any standard C++ library exports (e.g. `std::ostringstream`).
|
||||
|
||||
diff --git a/BUILD.gn b/BUILD.gn
|
||||
index b0c6d08bf50a3443e2589f09b6f1f5b7734c000c..7728123805054064d5acecacf6cbf8d1fe4a56c1 100644
|
||||
index 8b98f871341fed2186d0bc2de42912e76bbc04e1..6d3b542d781ad1a71c4b966aa05d5f51b1b3d45e 100644
|
||||
--- a/BUILD.gn
|
||||
+++ b/BUILD.gn
|
||||
@@ -663,6 +663,10 @@ config("internal_config") {
|
||||
|
||||
@@ -6,10 +6,10 @@ Subject: expose_mksnapshot.patch
|
||||
Needed in order to target mksnapshot for mksnapshot zip.
|
||||
|
||||
diff --git a/BUILD.gn b/BUILD.gn
|
||||
index 0a23171a391606bb3408dcf8a488d075a148443a..b0c6d08bf50a3443e2589f09b6f1f5b7734c000c 100644
|
||||
index 8039c91f8800b516a64b84a1d7a9701932decae2..8b98f871341fed2186d0bc2de42912e76bbc04e1 100644
|
||||
--- a/BUILD.gn
|
||||
+++ b/BUILD.gn
|
||||
@@ -6178,7 +6178,6 @@ if (current_toolchain == v8_generator_toolchain) {
|
||||
@@ -6181,7 +6181,6 @@ if (current_toolchain == v8_generator_toolchain) {
|
||||
|
||||
if (current_toolchain == v8_snapshot_toolchain) {
|
||||
v8_executable("mksnapshot") {
|
||||
|
||||
@@ -1 +1,4 @@
|
||||
add_thread_local_to_x_error_trap_cc.patch
|
||||
cherry-pick-136ef25acbf7.patch
|
||||
cherry-pick-e0efbd45ea74.patch
|
||||
cherry-pick-218b56e51638.patch
|
||||
|
||||
59
patches/webrtc/cherry-pick-136ef25acbf7.patch
Normal file
59
patches/webrtc/cherry-pick-136ef25acbf7.patch
Normal file
@@ -0,0 +1,59 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Jakob Ivarsson <jakobi@webrtc.org>
|
||||
Date: Fri, 23 Sep 2022 22:03:09 +0200
|
||||
Subject: Fix crash when appending empty array to AudioMultiVector.
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
|
||||
Bug: webrtc:14442,chromium:1367993
|
||||
Change-Id: I9453e300a6d3d78571d08cc65770787e13d43885
|
||||
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/276620
|
||||
Commit-Queue: Jakob Ivarsson <jakobi@webrtc.org>
|
||||
Reviewed-by: Henrik Lundin <henrik.lundin@webrtc.org>
|
||||
Cr-Commit-Position: refs/heads/main@{#38208}
|
||||
|
||||
diff --git a/modules/audio_coding/neteq/audio_multi_vector.cc b/modules/audio_coding/neteq/audio_multi_vector.cc
|
||||
index 220d5a17d7d1d4e1ed7577d4a044af29f358f88b..14ae94649b52278656eb73d91b1e73cb5307a92d 100644
|
||||
--- a/modules/audio_coding/neteq/audio_multi_vector.cc
|
||||
+++ b/modules/audio_coding/neteq/audio_multi_vector.cc
|
||||
@@ -69,6 +69,9 @@ void AudioMultiVector::CopyTo(AudioMultiVector* copy_to) const {
|
||||
void AudioMultiVector::PushBackInterleaved(
|
||||
rtc::ArrayView<const int16_t> append_this) {
|
||||
RTC_DCHECK_EQ(append_this.size() % num_channels_, 0);
|
||||
+ if (append_this.empty()) {
|
||||
+ return;
|
||||
+ }
|
||||
if (num_channels_ == 1) {
|
||||
// Special case to avoid extra allocation and data shuffling.
|
||||
channels_[0]->PushBack(append_this.data(), append_this.size());
|
||||
@@ -78,11 +81,8 @@ void AudioMultiVector::PushBackInterleaved(
|
||||
int16_t* temp_array = new int16_t[length_per_channel]; // Temporary storage.
|
||||
for (size_t channel = 0; channel < num_channels_; ++channel) {
|
||||
// Copy elements to `temp_array`.
|
||||
- // Set `source_ptr` to first element of this channel.
|
||||
- const int16_t* source_ptr = &append_this[channel];
|
||||
for (size_t i = 0; i < length_per_channel; ++i) {
|
||||
- temp_array[i] = *source_ptr;
|
||||
- source_ptr += num_channels_; // Jump to next element of this channel.
|
||||
+ temp_array[i] = append_this[channel + i * num_channels_];
|
||||
}
|
||||
channels_[channel]->PushBack(temp_array, length_per_channel);
|
||||
}
|
||||
diff --git a/modules/audio_coding/neteq/audio_multi_vector_unittest.cc b/modules/audio_coding/neteq/audio_multi_vector_unittest.cc
|
||||
index 329377a18edc2259dfc24dbaf82218ff69180916..386c3d48a398521730afad6642df355e29550d79 100644
|
||||
--- a/modules/audio_coding/neteq/audio_multi_vector_unittest.cc
|
||||
+++ b/modules/audio_coding/neteq/audio_multi_vector_unittest.cc
|
||||
@@ -309,6 +309,12 @@ TEST_P(AudioMultiVectorTest, CopyChannel) {
|
||||
}
|
||||
}
|
||||
|
||||
+TEST_P(AudioMultiVectorTest, PushBackEmptyArray) {
|
||||
+ AudioMultiVector vec(num_channels_);
|
||||
+ vec.PushBackInterleaved({});
|
||||
+ EXPECT_TRUE(vec.Empty());
|
||||
+}
|
||||
+
|
||||
INSTANTIATE_TEST_SUITE_P(TestNumChannels,
|
||||
AudioMultiVectorTest,
|
||||
::testing::Values(static_cast<size_t>(1),
|
||||
59
patches/webrtc/cherry-pick-218b56e51638.patch
Normal file
59
patches/webrtc/cherry-pick-218b56e51638.patch
Normal file
@@ -0,0 +1,59 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Alexander Cooper <alcooper@chromium.org>
|
||||
Date: Wed, 8 Feb 2023 14:16:01 -0800
|
||||
Subject: Fix Destruction inside WGC Callback
|
||||
|
||||
If we are notified of the destruction of the window before a
|
||||
CaptureFrame call can fail, then we may end up attempting to destroy the
|
||||
underlying WGC object inside it's own event handler. This can be
|
||||
problematic, as the class itself may want to run other code. Instead,
|
||||
we just unsubscribe and signal that any future CaptureFrame calls should
|
||||
reject.
|
||||
|
||||
This also removes setting "is_capture_started_=false" in the item closed
|
||||
handler, as all that served to do is cause the WgcCapturerWin code to
|
||||
attempt to restart the capturer, and somewhat muddies up our metrics.
|
||||
|
||||
(cherry picked from commit 318cf28945d80a0ac6f09382e507c95e649cc4c1)
|
||||
|
||||
Bug: chromium:1413005
|
||||
No-Try: True
|
||||
Change-Id: Ibccb7a2e7ce531ba80b4b331b9bc2cda0ff75f4e
|
||||
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/292762
|
||||
Auto-Submit: Alexander Cooper <alcooper@chromium.org>
|
||||
Reviewed-by: Mark Foltz <mfoltz@chromium.org>
|
||||
Commit-Queue: Mark Foltz <mfoltz@chromium.org>
|
||||
Commit-Queue: Alexander Cooper <alcooper@chromium.org>
|
||||
Cr-Original-Commit-Position: refs/heads/main@{#39275}
|
||||
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/293246
|
||||
Bot-Commit: rubber-stamper@appspot.gserviceaccount.com <rubber-stamper@appspot.gserviceaccount.com>
|
||||
Cr-Commit-Position: refs/branch-heads/5481@{#5}
|
||||
Cr-Branched-From: 2e1a9a4ae0234d4b1ea7a6fd4188afa1fb20379d-refs/heads/main@{#38901}
|
||||
|
||||
diff --git a/modules/desktop_capture/win/wgc_capture_session.cc b/modules/desktop_capture/win/wgc_capture_session.cc
|
||||
index 0ff2db27c7c82a59265eed16c672fe5afe57f501..68400415cec228c7a3c50be497e6aa6b437b5ace 100644
|
||||
--- a/modules/desktop_capture/win/wgc_capture_session.cc
|
||||
+++ b/modules/desktop_capture/win/wgc_capture_session.cc
|
||||
@@ -388,17 +388,14 @@ HRESULT WgcCaptureSession::OnItemClosed(WGC::IGraphicsCaptureItem* sender,
|
||||
|
||||
RTC_LOG(LS_INFO) << "Capture target has been closed.";
|
||||
item_closed_ = true;
|
||||
- is_capture_started_ = false;
|
||||
|
||||
RemoveEventHandlers();
|
||||
|
||||
- mapped_texture_ = nullptr;
|
||||
- session_ = nullptr;
|
||||
- frame_pool_ = nullptr;
|
||||
- direct3d_device_ = nullptr;
|
||||
- item_ = nullptr;
|
||||
- d3d11_device_ = nullptr;
|
||||
-
|
||||
+ // Do not attempt to free resources in the OnItemClosed handler, as this
|
||||
+ // causes a race where we try to delete the item that is calling us. Removing
|
||||
+ // the event handlers and setting `item_closed_` above is sufficient to ensure
|
||||
+ // that the resources are no longer used, and the next time the capturer tries
|
||||
+ // to get a frame, we will report a permanent failure and be destroyed.
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
60
patches/webrtc/cherry-pick-e0efbd45ea74.patch
Normal file
60
patches/webrtc/cherry-pick-e0efbd45ea74.patch
Normal file
@@ -0,0 +1,60 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: =?UTF-8?q?Henrik=20Bostr=C3=B6m?= <hbos@webrtc.org>
|
||||
Date: Fri, 20 Jan 2023 10:48:31 +0100
|
||||
Subject: =?UTF-8?q?=C2=A0[Stats]=20Handle=20the=20case=20of=20missing=20ce?=
|
||||
=?UTF-8?q?rtificates.?=
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
|
||||
Certificates being missing is a sign of a bug (e.g. webrtc:14844, to be
|
||||
fixed separately) which is why we have a DCHECK. But this DCHECK does
|
||||
not protect against accessing the invalid iterator if it is a release
|
||||
build. This CL makes that safe.
|
||||
|
||||
# Mobile bots not running properly
|
||||
NOTRY=True
|
||||
|
||||
(cherry picked from commit 124d7c3fe5bdc79a355c9df02d07f25331631a68)
|
||||
|
||||
Bug: chromium:1408392
|
||||
Change-Id: I97a82786028e41c58ef8ef15002c3f959bbec7f1
|
||||
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/291109
|
||||
Reviewed-by: Mirko Bonadei <mbonadei@webrtc.org>
|
||||
Commit-Queue: Henrik Boström <hbos@webrtc.org>
|
||||
Cr-Original-Commit-Position: refs/heads/main@{#39159}
|
||||
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/291380
|
||||
Cr-Commit-Position: refs/branch-heads/5481@{#2}
|
||||
Cr-Branched-From: 2e1a9a4ae0234d4b1ea7a6fd4188afa1fb20379d-refs/heads/main@{#38901}
|
||||
|
||||
diff --git a/pc/rtc_stats_collector.cc b/pc/rtc_stats_collector.cc
|
||||
index be6c23e8430cb2b19839c5b2cb7eebaa576a92cb..0c0bb1c5540c1196dc45cd4e2e2c91941a9a16ac 100644
|
||||
--- a/pc/rtc_stats_collector.cc
|
||||
+++ b/pc/rtc_stats_collector.cc
|
||||
@@ -2106,16 +2106,17 @@ void RTCStatsCollector::ProduceTransportStats_n(
|
||||
// exist.
|
||||
const auto& certificate_stats_it =
|
||||
transport_cert_stats.find(transport_name);
|
||||
+ std::string local_certificate_id, remote_certificate_id;
|
||||
RTC_DCHECK(certificate_stats_it != transport_cert_stats.cend());
|
||||
- std::string local_certificate_id;
|
||||
- if (certificate_stats_it->second.local) {
|
||||
- local_certificate_id = RTCCertificateIDFromFingerprint(
|
||||
- certificate_stats_it->second.local->fingerprint);
|
||||
- }
|
||||
- std::string remote_certificate_id;
|
||||
- if (certificate_stats_it->second.remote) {
|
||||
- remote_certificate_id = RTCCertificateIDFromFingerprint(
|
||||
- certificate_stats_it->second.remote->fingerprint);
|
||||
+ if (certificate_stats_it != transport_cert_stats.cend()) {
|
||||
+ if (certificate_stats_it->second.local) {
|
||||
+ local_certificate_id = RTCCertificateIDFromFingerprint(
|
||||
+ certificate_stats_it->second.local->fingerprint);
|
||||
+ }
|
||||
+ if (certificate_stats_it->second.remote) {
|
||||
+ remote_certificate_id = RTCCertificateIDFromFingerprint(
|
||||
+ certificate_stats_it->second.remote->fingerprint);
|
||||
+ }
|
||||
}
|
||||
|
||||
// There is one transport stats for each channel.
|
||||
@@ -4,11 +4,11 @@ import argparse
|
||||
import os
|
||||
import sys
|
||||
|
||||
from lib.config import LINUX_BINARIES, PLATFORM
|
||||
from lib.util import execute, get_out_dir
|
||||
from lib.config import PLATFORM
|
||||
from lib.util import execute, get_linux_binaries, get_out_dir
|
||||
|
||||
def add_debug_link_into_binaries(directory, target_cpu, debug_dir):
|
||||
for binary in LINUX_BINARIES:
|
||||
for binary in get_linux_binaries():
|
||||
binary_path = os.path.join(directory, binary)
|
||||
if os.path.isfile(binary_path):
|
||||
add_debug_link_into_binary(binary_path, target_cpu, debug_dir)
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user