mirror of
https://github.com/electron/electron.git
synced 2026-02-19 03:14:51 -05:00
Compare commits
141 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
b07f2f0f42 | ||
|
|
df6f23bbd1 | ||
|
|
900459e1b1 | ||
|
|
5af5b42422 | ||
|
|
de3a8a5389 | ||
|
|
8c172f2e95 | ||
|
|
6820094f8e | ||
|
|
f907c18bac | ||
|
|
27575566c9 | ||
|
|
518d3e490d | ||
|
|
29cdcb443a | ||
|
|
4c435b27e0 | ||
|
|
85317c3109 | ||
|
|
ea7e3c80ee | ||
|
|
f0685b60a7 | ||
|
|
7fd1f3da64 | ||
|
|
c6b44676e6 | ||
|
|
69d1434bcc | ||
|
|
f843f23363 | ||
|
|
fcbd88f8aa | ||
|
|
ee668f1472 | ||
|
|
c875adf7cf | ||
|
|
3cd2f2ede9 | ||
|
|
e2c4acd505 | ||
|
|
620bdcbb2a | ||
|
|
ae7b2ae3cb | ||
|
|
ffff96e33f | ||
|
|
7a4a94b18c | ||
|
|
62dddd12ed | ||
|
|
0b17a20119 | ||
|
|
f557f99631 | ||
|
|
4b5998e51a | ||
|
|
de3bc8cb4c | ||
|
|
ba1a2f3d0f | ||
|
|
352ab57670 | ||
|
|
4a7bf76fa1 | ||
|
|
978cc7bd7d | ||
|
|
94c7ad9ee2 | ||
|
|
be71423d32 | ||
|
|
565c4fe9a7 | ||
|
|
c0caa61022 | ||
|
|
f19e6d516a | ||
|
|
3931d5a84f | ||
|
|
8a2e936053 | ||
|
|
c43eed8782 | ||
|
|
f89e3e37de | ||
|
|
550b0d5a43 | ||
|
|
f2719edd1d | ||
|
|
cedf0014f6 | ||
|
|
2d1ba5626b | ||
|
|
c8fea8abcf | ||
|
|
bb88e69ccc | ||
|
|
14707ad2b5 | ||
|
|
24ce94856c | ||
|
|
a831d69dfd | ||
|
|
432eba9406 | ||
|
|
e4800bab86 | ||
|
|
d44fd39272 | ||
|
|
8352346fff | ||
|
|
76f5059db4 | ||
|
|
0b52938852 | ||
|
|
5d3eea5934 | ||
|
|
0384c57eb5 | ||
|
|
7e02e1d6da | ||
|
|
87ec774248 | ||
|
|
1df44118af | ||
|
|
9db65bac75 | ||
|
|
5f115c8967 | ||
|
|
03a1deb25c | ||
|
|
54436d2048 | ||
|
|
da55d6bfda | ||
|
|
a7bd733462 | ||
|
|
5692fd89d6 | ||
|
|
72984eb31b | ||
|
|
d6bcc07688 | ||
|
|
299756c5b1 | ||
|
|
2a4aed7f7a | ||
|
|
b0c7515e6a | ||
|
|
1ae86b3bec | ||
|
|
62e9ffab9b | ||
|
|
fc2261f159 | ||
|
|
dcc99ecb19 | ||
|
|
0e508d9c98 | ||
|
|
dfa48d673f | ||
|
|
120fd04f7f | ||
|
|
ab5a5b616f | ||
|
|
1106ca998b | ||
|
|
fe3baa83d6 | ||
|
|
21082ae2fb | ||
|
|
5ed0f95d8f | ||
|
|
4f5432e986 | ||
|
|
ef164e7e8d | ||
|
|
786350c22e | ||
|
|
19b85bb74e | ||
|
|
95772e1feb | ||
|
|
a73332fd9f | ||
|
|
153abeb351 | ||
|
|
e5690f1353 | ||
|
|
71e1d8eea1 | ||
|
|
b6eef90604 | ||
|
|
57f2eecb28 | ||
|
|
72bdd5cd4c | ||
|
|
37267d1beb | ||
|
|
9519ec3afa | ||
|
|
06132f5aa3 | ||
|
|
751ba53a6b | ||
|
|
312c681adc | ||
|
|
69b5723d8c | ||
|
|
eb59cb1e11 | ||
|
|
887595e861 | ||
|
|
8f5a8c684d | ||
|
|
1245e23a74 | ||
|
|
5e7ae98bec | ||
|
|
d6e58ec020 | ||
|
|
147c24208f | ||
|
|
470a365743 | ||
|
|
a07c34e420 | ||
|
|
effff34416 | ||
|
|
e65fc9116a | ||
|
|
a35de7e89f | ||
|
|
d225809cc4 | ||
|
|
763daa8707 | ||
|
|
0bd4cea3a0 | ||
|
|
02949a7e6f | ||
|
|
f05b54bdd3 | ||
|
|
f49f0d4cd7 | ||
|
|
a63ea46ab2 | ||
|
|
0b9206213c | ||
|
|
14fade2915 | ||
|
|
a7f80017cf | ||
|
|
64b514472d | ||
|
|
09430e27a9 | ||
|
|
896aa1adb9 | ||
|
|
32f71c118f | ||
|
|
dcce07dcd8 | ||
|
|
7949645606 | ||
|
|
38eb414298 | ||
|
|
27ce311a20 | ||
|
|
99c0e1cde2 | ||
|
|
5f030bdd2c | ||
|
|
38fa55d54e |
@@ -243,14 +243,27 @@ step-depot-tools-get: &step-depot-tools-get
|
||||
sed -i '/ninjalog_uploader_wrapper.py/d' ./depot_tools/autoninja
|
||||
# Remove swift-format dep from cipd on macOS until we send a patch upstream.
|
||||
cd depot_tools
|
||||
patch gclient.py -R \<<'EOF'
|
||||
676,677c676
|
||||
< packages = dep_value.get('packages', [])
|
||||
< for package in (x for x in packages if "infra/3pp/tools/swift-format" not in x.get('package')):
|
||||
---
|
||||
> for package in dep_value.get('packages', []):
|
||||
cat > gclient.diff \<< 'EOF'
|
||||
diff --git a/gclient.py b/gclient.py
|
||||
index 3a9c5c6..f222043 100755
|
||||
--- a/gclient.py
|
||||
+++ b/gclient.py
|
||||
@@ -712,7 +712,8 @@ class Dependency(gclient_utils.WorkItem, DependencySettings):
|
||||
|
||||
if dep_type == 'cipd':
|
||||
cipd_root = self.GetCipdRoot()
|
||||
- for package in dep_value.get('packages', []):
|
||||
+ packages = dep_value.get('packages', [])
|
||||
+ for package in (x for x in packages if "infra/3pp/tools/swift-format" not in x.get('package')):
|
||||
deps_to_add.append(
|
||||
CipdDependency(
|
||||
parent=self,
|
||||
EOF
|
||||
git apply --3way gclient.diff
|
||||
fi
|
||||
# Ensure depot_tools does not update.
|
||||
test -d depot_tools && cd depot_tools
|
||||
touch .disable_auto_update
|
||||
|
||||
step-depot-tools-add-to-path: &step-depot-tools-add-to-path
|
||||
run:
|
||||
@@ -355,14 +368,14 @@ step-restore-brew-cache: &step-restore-brew-cache
|
||||
- /usr/local/Cellar/gnu-tar
|
||||
- /usr/local/bin/gtar
|
||||
keys:
|
||||
- v5-brew-cache-{{ arch }}
|
||||
- v6-brew-cache-{{ arch }}
|
||||
|
||||
step-save-brew-cache: &step-save-brew-cache
|
||||
save_cache:
|
||||
paths:
|
||||
- /usr/local/Cellar/gnu-tar
|
||||
- /usr/local/bin/gtar
|
||||
key: v5-brew-cache-{{ arch }}
|
||||
key: v6-brew-cache-{{ arch }}
|
||||
name: Persisting brew cache
|
||||
|
||||
step-get-more-space-on-mac: &step-get-more-space-on-mac
|
||||
@@ -484,7 +497,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
|
||||
@@ -494,13 +509,16 @@ step-fix-sync: &step-fix-sync
|
||||
# Remove extra output from calling gclient getdep which always calls update_depot_tools
|
||||
sed -i '' "s/Updating depot_tools... //g" esbuild_ensure_file
|
||||
cipd ensure --root src/third_party/devtools-frontend/src/third_party/esbuild -ensure-file esbuild_ensure_file
|
||||
|
||||
# Fix ninja (wrong binary)
|
||||
echo 'infra/3pp/tools/ninja/${platform}' `gclient getdep --deps-file=src/DEPS -r 'src/third_party/ninja:infra/3pp/tools/ninja/${platform}'` > ninja_ensure_file
|
||||
sed -i '' "s/Updating depot_tools... //g" ninja_ensure_file
|
||||
cipd ensure --root src/third_party/ninja -ensure-file ninja_ensure_file
|
||||
fi
|
||||
|
||||
# Make sure we are using the right ninja
|
||||
echo 'infra/3pp/tools/ninja/${platform}' `gclient getdep --deps-file=src/DEPS -r 'src/third_party/ninja:infra/3pp/tools/ninja/${platform}'` > ninja_ensure_file
|
||||
sed $SEDOPTION "s/Updating depot_tools... //g" ninja_ensure_file
|
||||
cipd ensure --root src/third_party/ninja -ensure-file ninja_ensure_file
|
||||
|
||||
# Explicitly add ninja to the path
|
||||
echo 'export PATH="$PATH:'"$PWD"'/src/third_party/ninja"' >> $BASH_ENV
|
||||
|
||||
cd src/third_party/angle
|
||||
rm .git/objects/info/alternates
|
||||
git remote set-url origin https://chromium.googlesource.com/angle/angle.git
|
||||
@@ -575,7 +593,7 @@ step-electron-build: &step-electron-build
|
||||
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=
|
||||
SEDOPTION="-i"
|
||||
if [ "`uname`" == "Darwin" ]; then
|
||||
SEDOPTION="-i ''"
|
||||
fi
|
||||
@@ -772,7 +790,7 @@ step-mksnapshot-build: &step-mksnapshot-build
|
||||
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=
|
||||
SEDOPTION="-i"
|
||||
if [ "`uname`" == "Darwin" ]; then
|
||||
SEDOPTION="-i ''"
|
||||
fi
|
||||
@@ -1006,26 +1024,13 @@ step-ts-compile: &step-ts-compile
|
||||
# List of all steps.
|
||||
steps-electron-gn-check: &steps-electron-gn-check
|
||||
steps:
|
||||
- *step-checkout-electron
|
||||
- *step-depot-tools-get
|
||||
- *step-depot-tools-add-to-path
|
||||
- install-python2-mac
|
||||
- *step-setup-env-for-build
|
||||
- *step-setup-goma-for-build
|
||||
- *step-generate-deps-hash
|
||||
- *step-touch-sync-done
|
||||
- maybe-restore-portaled-src-cache
|
||||
- run:
|
||||
name: Ensure src checkout worked
|
||||
command: |
|
||||
if [ ! -d "src/third_party/blink" ]; then
|
||||
echo src cache was not restored for an unknown reason
|
||||
exit 1
|
||||
fi
|
||||
- run:
|
||||
name: Wipe Electron
|
||||
command: rm -rf src/electron
|
||||
- *step-checkout-electron
|
||||
- checkout-from-cache
|
||||
- *step-setup-env-for-build
|
||||
- *step-wait-for-goma
|
||||
- *step-gn-gen-default
|
||||
- *step-gn-check
|
||||
|
||||
steps-electron-ts-compile-for-doc-change: &steps-electron-ts-compile-for-doc-change
|
||||
steps:
|
||||
@@ -2209,4 +2214,4 @@ workflows:
|
||||
jobs:
|
||||
- lint
|
||||
|
||||
# VS Code Extension Version: 1.1.1
|
||||
# VS Code Extension Version: 1.4.0
|
||||
163
.github/workflows/electron_woa_testing.yml
vendored
163
.github/workflows/electron_woa_testing.yml
vendored
@@ -1,163 +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: 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 }}"}
|
||||
@@ -8,24 +8,26 @@ env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
jobs:
|
||||
check_tag:
|
||||
trigger_chromedriver:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- name: Check Tag
|
||||
- uses: actions/checkout@93ea575cb5d8a053eaa0ac8fa3b40d7e05a33cc8 # tag: v3
|
||||
- name: Trigger New chromedriver Release
|
||||
run: |
|
||||
if [[ ${{ github.event.release.tag_name }} =~ ^v[0-9]+\.0\.0$ ]]; then
|
||||
echo ::set-output name=should_release::true
|
||||
fi
|
||||
trigger:
|
||||
runs-on: ubuntu-latest
|
||||
needs: check_tag
|
||||
if: needs.check_tag.outputs.should_release == 'true'
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- name: Trigger New chromedriver Release
|
||||
run: |
|
||||
if [[ ${{ github.event.release.tag_name }} =~ ^v\d+\.\d+\.\d+$ ]]; then
|
||||
gh api /repos/:owner/chromedriver/actions/workflows/release.yml/dispatches --input - <<< '{"ref":"main","inputs":{"version":"${{ github.event.release.tag_name }}"}}'
|
||||
else
|
||||
echo "Not releasing for version ${{ github.event.release.tag_name }}"
|
||||
fi
|
||||
|
||||
trigger_mksnapshot:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@93ea575cb5d8a053eaa0ac8fa3b40d7e05a33cc8 # tag: v3
|
||||
- name: Trigger New mksnapshot Release
|
||||
run: |
|
||||
gh api /repos/:owner/mksnapshot/actions/workflows/release.yml/dispatches --input - <<< '{"ref":"main","inputs":{"version":"${{ github.event.release.tag_name }}"}}'
|
||||
if [[ ${{ github.event.release.tag_name }} =~ ^v\d+\.\d+\.\d+$ ]]; then
|
||||
gh api /repos/:owner/mksnapshot/actions/workflows/release.yml/dispatches --input - <<< '{"ref":"main","inputs":{"version":"${{ github.event.release.tag_name }}"}}'
|
||||
else
|
||||
echo "Not releasing for version ${{ github.event.release.tag_name }}"
|
||||
fi
|
||||
|
||||
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@93ea575cb5d8a053eaa0ac8fa3b40d7e05a33cc8 # v3.1.0
|
||||
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@1c7dc0e88aad311c89889bc5ce5d8f96931a1bd0 # 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@2b011faafdcbc9ceb11414d64d0573f37c774b04 # v4.2.3
|
||||
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 }}.
|
||||
2
BUILD.gn
2
BUILD.gn
@@ -631,8 +631,6 @@ source_set("electron_lib") {
|
||||
sources += [
|
||||
"shell/browser/certificate_manager_model.cc",
|
||||
"shell/browser/certificate_manager_model.h",
|
||||
"shell/browser/ui/gtk/menu_util.cc",
|
||||
"shell/browser/ui/gtk/menu_util.h",
|
||||
"shell/browser/ui/gtk_util.cc",
|
||||
"shell/browser/ui/gtk_util.h",
|
||||
]
|
||||
|
||||
2
DEPS
2
DEPS
@@ -2,7 +2,7 @@ gclient_gn_args_from = 'src'
|
||||
|
||||
vars = {
|
||||
'chromium_version':
|
||||
'108.0.5359.62',
|
||||
'108.0.5359.215',
|
||||
'node_version':
|
||||
'v16.17.1',
|
||||
'nan_version':
|
||||
|
||||
108
appveyor-bake.yml
Normal file
108
appveyor-bake.yml
Normal file
@@ -0,0 +1,108 @@
|
||||
# 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-node18
|
||||
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'))
|
||||
279
appveyor-woa.yml
Normal file
279
appveyor-woa.yml
Normal file
@@ -0,0 +1,279 @@
|
||||
# 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-108.0.5359.215
|
||||
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: $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 )
|
||||
374
appveyor.yml
374
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,193 +28,153 @@
|
||||
# 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-108.0.5359.215-node18
|
||||
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
|
||||
DEPOT_TOOLS_WIN_TOOLCHAIN: 0
|
||||
PYTHONIOENCODING: UTF-8
|
||||
|
||||
matrix:
|
||||
|
||||
- job_name: Build
|
||||
|
||||
- job_name: Test
|
||||
job_depends_on: Build
|
||||
- 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:
|
||||
- matrix:
|
||||
only:
|
||||
- job_name: Build
|
||||
|
||||
init:
|
||||
- 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
|
||||
}
|
||||
|
||||
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 tests for doc only change"; Exit-AppveyorBuild
|
||||
}
|
||||
$global:LASTEXITCODE = 0
|
||||
- cd ..
|
||||
- ps: Write-Host "Building $env:GN_CONFIG build"
|
||||
- git config --global core.longpaths true
|
||||
- update_depot_tools.bat
|
||||
- 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: |
|
||||
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
|
||||
}
|
||||
}
|
||||
- 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=14 -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"
|
||||
}
|
||||
$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: $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 {
|
||||
# update angle
|
||||
cd src\third_party\angle
|
||||
git remote set-url origin https://chromium.googlesource.com/angle/angle.git
|
||||
git fetch
|
||||
cd ..\..\..
|
||||
Write-warning "WARNING!!!!!! Goma authentication is incorrect; please update Goma auth token.";
|
||||
$host.SetShouldExit(1)
|
||||
}
|
||||
} else {
|
||||
# file does not exist, gclient sync, then zip
|
||||
}
|
||||
- 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 ($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"
|
||||
- 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
|
||||
}
|
||||
# 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"
|
||||
- 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
|
||||
}
|
||||
# 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/default_mksnapshot_args
|
||||
- ps: >-
|
||||
# Remove unused args from mksnapshot_args
|
||||
- python3 electron/script/zip_manifests/check-zip-manifest.py out/Default/dist.zip electron/script/zip_manifests/dist_zip.win.%TARGET_ARCH%.manifest
|
||||
|
||||
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
|
||||
- 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: >-
|
||||
@@ -222,12 +186,10 @@ for:
|
||||
Write-Output "Uploading Electron release distribution to github releases"
|
||||
& python3 script\release\uploaders\upload.py --verbose
|
||||
}
|
||||
} elseif (Test-Path Env:\TEST_WOA) {
|
||||
node script/release/ci-release-build.js --job=electron-woa-testing --ci=GHA --appveyorJobId=$env:APPVEYOR_JOB_ID $env:APPVEYOR_REPO_BRANCH
|
||||
}
|
||||
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'))
|
||||
# - 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)
|
||||
@@ -241,57 +203,52 @@ for:
|
||||
- ps: >-
|
||||
if ((Test-Path "pdb.zip") -And ($env:GN_CONFIG -ne 'release')) {
|
||||
appveyor-retry appveyor PushArtifact pdb.zip
|
||||
}
|
||||
|
||||
-
|
||||
matrix:
|
||||
}
|
||||
- matrix:
|
||||
only:
|
||||
- job_name: Test
|
||||
|
||||
init:
|
||||
- ps: |
|
||||
if ($env:RUN_TESTS -ne 'true') {
|
||||
Write-warning "Skipping tests for $env:APPVEYOR_PROJECT_NAME"; Exit-AppveyorBuild
|
||||
}
|
||||
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
|
||||
}
|
||||
- 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 tests for doc only change"; Exit-AppveyorBuild
|
||||
}
|
||||
$global:LASTEXITCODE = 0
|
||||
- ps: |
|
||||
cd ..
|
||||
mkdir out\Default
|
||||
cd ..
|
||||
# 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
|
||||
- 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
|
||||
}
|
||||
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
|
||||
- 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
|
||||
@@ -301,15 +258,22 @@ for:
|
||||
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 & python3 electron\script\verify-ffmpeg.py --build-dir out\Default --source-root %cd% --ffmpeg-path out\ffmpeg
|
||||
- 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 & python3 electron\script\verify-mksnapshot.py --build-dir out\Default --source-root %cd%
|
||||
- echo Verifying mksnapshot & python electron\script\verify-mksnapshot.py --build-dir out\Default --source-root %cd%
|
||||
- echo "Done verifying mksnapshot"
|
||||
- echo Verifying chromedriver & python3 electron\script\verify-chromedriver.py --build-dir out\Default --source-root %cd%
|
||||
- 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 )
|
||||
@@ -48,3 +48,5 @@ is_cfi = false
|
||||
|
||||
# TODO: fix this once sysroots have been updated.
|
||||
use_qt = false
|
||||
|
||||
v8_builtins_profiling_log_file = ""
|
||||
|
||||
@@ -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():
|
||||
|
||||
@@ -42,7 +42,7 @@ an issue:
|
||||
* [Web embeds in Electron](tutorial/web-embeds.md)
|
||||
* [Boilerplates and CLIs](tutorial/boilerplates-and-clis.md)
|
||||
* [Boilerplate vs CLI](tutorial/boilerplates-and-clis.md#boilerplate-vs-cli)
|
||||
* [electron-forge](tutorial/boilerplates-and-clis.md#electron-forge)
|
||||
* [Electron Forge](tutorial/boilerplates-and-clis.md#electron-forge)
|
||||
* [electron-builder](tutorial/boilerplates-and-clis.md#electron-builder)
|
||||
* [electron-react-boilerplate](tutorial/boilerplates-and-clis.md#electron-react-boilerplate)
|
||||
* [Other Tools and Boilerplates](tutorial/boilerplates-and-clis.md#other-tools-and-boilerplates)
|
||||
|
||||
@@ -128,8 +128,6 @@ Emitted when the user wants to open a URL with the application. Your application
|
||||
`Info.plist` file must define the URL scheme within the `CFBundleURLTypes` key, and
|
||||
set `NSPrincipalClass` to `AtomApplication`.
|
||||
|
||||
You should call `event.preventDefault()` if you want to handle this event.
|
||||
|
||||
As with the `open-file` event, be sure to register a listener for the `open-url`
|
||||
event early in your application startup to detect if the the application being
|
||||
is being opened to handle a URL. If you register the listener in response to a
|
||||
@@ -750,14 +748,21 @@ This API can be used for purposes such as deciding what language to present the
|
||||
|
||||
Here are some examples of return values of the various language and locale APIs with different configurations:
|
||||
|
||||
* For Windows, where the application locale is German, the regional format is Finnish (Finland), and the preferred system languages from most to least preferred are French (Canada), English (US), Simplified Chinese (China), Finnish, and Spanish (Latin America):
|
||||
* `app.getLocale()` returns `'de'`
|
||||
* `app.getSystemLocale()` returns `'fi-FI'`
|
||||
* `app.getPreferredSystemLanguages()` returns `['fr-CA', 'en-US', 'zh-Hans-CN', 'fi', 'es-419']`
|
||||
* On macOS, where the application locale is German, the region is Finland, and the preferred system languages from most to least preferred are French (Canada), English (US), Simplified Chinese, and Spanish (Latin America):
|
||||
* `app.getLocale()` returns `'de'`
|
||||
* `app.getSystemLocale()` returns `'fr-FI'`
|
||||
* `app.getPreferredSystemLanguages()` returns `['fr-CA', 'en-US', 'zh-Hans-FI', 'es-419']`
|
||||
On Windows, given application locale is German, the regional format is Finnish (Finland), and the preferred system languages from most to least preferred are French (Canada), English (US), Simplified Chinese (China), Finnish, and Spanish (Latin America):
|
||||
|
||||
```js
|
||||
app.getLocale() // 'de'
|
||||
app.getSystemLocale() // 'fi-FI'
|
||||
app.getPreferredSystemLanguages() // ['fr-CA', 'en-US', 'zh-Hans-CN', 'fi', 'es-419']
|
||||
```
|
||||
|
||||
On macOS, given the application locale is German, the region is Finland, and the preferred system languages from most to least preferred are French (Canada), English (US), Simplified Chinese, and Spanish (Latin America):
|
||||
|
||||
```js
|
||||
app.getLocale() // 'de'
|
||||
app.getSystemLocale() // 'fr-FI'
|
||||
app.getPreferredSystemLanguages() // ['fr-CA', 'en-US', 'zh-Hans-FI', 'es-419']
|
||||
```
|
||||
|
||||
Both the available languages and regions and the possible return values differ between the two operating systems.
|
||||
|
||||
@@ -1509,7 +1514,6 @@ dock on macOS.
|
||||
|
||||
A `boolean` property that returns `true` if the app is packaged, `false` otherwise. For many apps, this property can be used to distinguish development and production environments.
|
||||
|
||||
[dock-menu]:https://developer.apple.com/macos/human-interface-guidelines/menus/dock-menus/
|
||||
[tasks]:https://msdn.microsoft.com/en-us/library/windows/desktop/dd378460(v=vs.85).aspx#tasks
|
||||
[app-user-model-id]: https://msdn.microsoft.com/en-us/library/windows/desktop/dd378459(v=vs.85).aspx
|
||||
[electron-forge]: https://www.electronforge.io/
|
||||
@@ -1563,5 +1567,4 @@ an ARM64 translator (like the macOS
|
||||
or Windows [WOW](https://en.wikipedia.org/wiki/Windows_on_Windows)).
|
||||
|
||||
You can use this property to prompt users to download the arm64 version of
|
||||
your application when they are running the x64 version under Rosetta
|
||||
incorrectly.
|
||||
your application when they are mistakenly running the x64 version under Rosetta or WOW.
|
||||
|
||||
@@ -32,9 +32,9 @@ This is a requirement of `Squirrel.Mac`.
|
||||
|
||||
On Windows, you have to install your app into a user's machine before you can
|
||||
use the `autoUpdater`, so it is recommended that you use the
|
||||
[electron-winstaller][installer-lib], [electron-forge][electron-forge-lib] or the [grunt-electron-installer][installer] package to generate a Windows installer.
|
||||
[electron-winstaller][installer-lib], [Electron Forge][electron-forge-lib] or the [grunt-electron-installer][installer] package to generate a Windows installer.
|
||||
|
||||
When using [electron-winstaller][installer-lib] or [electron-forge][electron-forge-lib] make sure you do not try to update your app [the first time it runs](https://github.com/electron/windows-installer#handling-squirrel-events) (Also see [this issue for more info](https://github.com/electron/electron/issues/7155)). It's also recommended to use [electron-squirrel-startup](https://github.com/mongodb-js/electron-squirrel-startup) to get desktop shortcuts for your app.
|
||||
When using [electron-winstaller][installer-lib] or [Electron Forge][electron-forge-lib] make sure you do not try to update your app [the first time it runs](https://github.com/electron/windows-installer#handling-squirrel-events) (Also see [this issue for more info](https://github.com/electron/electron/issues/7155)). It's also recommended to use [electron-squirrel-startup](https://github.com/mongodb-js/electron-squirrel-startup) to get desktop shortcuts for your app.
|
||||
|
||||
The installer generated with Squirrel will create a shortcut icon with an
|
||||
[Application User Model ID][app-user-model-id] in the format of
|
||||
@@ -139,6 +139,6 @@ application starts.
|
||||
[squirrel-windows]: https://github.com/Squirrel/Squirrel.Windows
|
||||
[installer]: https://github.com/electron/grunt-electron-installer
|
||||
[installer-lib]: https://github.com/electron/windows-installer
|
||||
[electron-forge-lib]: https://github.com/electron-userland/electron-forge
|
||||
[electron-forge-lib]: https://github.com/electron/forge
|
||||
[app-user-model-id]: https://msdn.microsoft.com/en-us/library/windows/desktop/dd378459(v=vs.85).aspx
|
||||
[event-emitter]: https://nodejs.org/api/events.html#events_class_eventemitter
|
||||
|
||||
@@ -192,6 +192,7 @@ It creates a new `BrowserWindow` with native properties as set by the `options`.
|
||||
macOS. Default is `false`.
|
||||
* `skipTaskbar` boolean (optional) _macOS_ _Windows_ - Whether to show the window in taskbar.
|
||||
Default is `false`.
|
||||
* `hiddenInMissionControl` boolean (optional) _macOS_ - Whether window should be hidden when the user toggles into mission control.
|
||||
* `kiosk` boolean (optional) - Whether the window is in kiosk mode. Default is `false`.
|
||||
* `title` string (optional) - Default window title. Default is `"Electron"`. If the HTML tag `<title>` is defined in the HTML file loaded by `loadURL()`, this property will be ignored.
|
||||
* `icon` ([NativeImage](native-image.md) | string) (optional) - The window icon. On Windows it is
|
||||
@@ -268,7 +269,7 @@ It creates a new `BrowserWindow` with native properties as set by the `options`.
|
||||
zoom to the width of the screen. This will also affect the behavior when
|
||||
calling `maximize()` directly. Default is `false`.
|
||||
* `tabbingIdentifier` string (optional) _macOS_ - Tab group name, allows
|
||||
opening the window as a native tab on macOS 10.12+. Windows with the same
|
||||
opening the window as a native tab. Windows with the same
|
||||
tabbing identifier will be grouped together. This also adds a native new
|
||||
tab button to your window's tab bar and allows your `app` and window to
|
||||
receive the `new-window-for-tab` event.
|
||||
@@ -1255,6 +1256,16 @@ Returns `boolean` - Whether the window can be manually closed by user.
|
||||
|
||||
On Linux always returns `true`.
|
||||
|
||||
#### `win.setHiddenInMissionControl(hidden)` _macOS_
|
||||
|
||||
* `hidden` boolean
|
||||
|
||||
Sets whether the window will be hidden when the user toggles into mission control.
|
||||
|
||||
#### `win.isHiddenInMissionControl()` _macOS_
|
||||
|
||||
Returns `boolean` - Whether the window will be hidden when the user toggles into mission control.
|
||||
|
||||
#### `win.setAlwaysOnTop(flag[, level][, relativeLevel])`
|
||||
|
||||
* `flag` boolean
|
||||
@@ -1753,7 +1764,7 @@ On macOS it does not remove the focus from the window.
|
||||
|
||||
#### `win.isFocusable()` _macOS_ _Windows_
|
||||
|
||||
Returns whether the window can be focused.
|
||||
Returns `boolean` - Whether the window can be focused.
|
||||
|
||||
#### `win.setParentWindow(parent)`
|
||||
|
||||
@@ -1836,7 +1847,7 @@ frameless window.
|
||||
|
||||
Sets the touchBar layout for the current window. Specifying `null` or
|
||||
`undefined` clears the touch bar. This method only has an effect if the
|
||||
machine has a touch bar and is running on macOS 10.12.1+.
|
||||
machine has a touch bar.
|
||||
|
||||
**Note:** The TouchBar API is currently experimental and may change or be
|
||||
removed in future Electron releases.
|
||||
@@ -1887,7 +1898,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
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
> Perform copy and paste operations on the system clipboard.
|
||||
|
||||
Process: [Main](../glossary.md#main-process), [Renderer](../glossary.md#renderer-process)
|
||||
Process: [Main](../glossary.md#main-process), [Renderer](../glossary.md#renderer-process) (non-sandboxed only)
|
||||
|
||||
On Linux, there is also a `selection` clipboard. To manipulate it
|
||||
you need to pass `selection` to each method:
|
||||
|
||||
@@ -79,3 +79,5 @@ Returns `Menu | null` - The application's [dock menu][dock-menu].
|
||||
* `image` ([NativeImage](native-image.md) | string)
|
||||
|
||||
Sets the `image` associated with this dock icon.
|
||||
|
||||
[dock-menu]: https://developer.apple.com/macos/human-interface-guidelines/menus/dock-menus/
|
||||
|
||||
@@ -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 }) => {
|
||||
// ...
|
||||
})
|
||||
```
|
||||
|
||||
@@ -51,7 +51,7 @@ See [`Menu`](menu.md) for examples.
|
||||
the placement of their containing group after the containing group of the item
|
||||
with the specified label.
|
||||
|
||||
**Note:** `acceleratorWorksWhenHidden` is specified as being macOS-only because accelerators always work when items are hidden on Windows and Linux. The option is exposed to users to give them the option to turn it off, as this is possible in native macOS development. This property is only usable on macOS High Sierra 10.13 or newer.
|
||||
**Note:** `acceleratorWorksWhenHidden` is specified as being macOS-only because accelerators always work when items are hidden on Windows and Linux. The option is exposed to users to give them the option to turn it off, as this is possible in native macOS development.
|
||||
|
||||
### Roles
|
||||
|
||||
|
||||
@@ -56,3 +56,4 @@ Emitted when the remote end of a MessagePortMain object becomes disconnected.
|
||||
|
||||
[`MessagePort`]: https://developer.mozilla.org/en-US/docs/Web/API/MessagePort
|
||||
[Channel Messaging API]: https://developer.mozilla.org/en-US/docs/Web/API/Channel_Messaging_API
|
||||
[event-emitter]: https://nodejs.org/api/events.html#events_class_eventemitter
|
||||
|
||||
@@ -54,7 +54,7 @@ The `net` module has the following methods:
|
||||
|
||||
### `net.request(options)`
|
||||
|
||||
* `options` (ClientRequestConstructorOptions | string) - The `ClientRequest` constructor options.
|
||||
* `options` ([ClientRequestConstructorOptions](client-request.md#new-clientrequestoptions) | string) - The `ClientRequest` constructor options.
|
||||
|
||||
Returns [`ClientRequest`](./client-request.md)
|
||||
|
||||
|
||||
@@ -44,3 +44,5 @@ event.
|
||||
* `message` any
|
||||
|
||||
Sends a message from the process to its parent.
|
||||
|
||||
[event-emitter]: https://nodejs.org/api/events.html#events_class_eventemitter
|
||||
|
||||
@@ -449,7 +449,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:
|
||||
@@ -672,6 +672,7 @@ win.webContents.session.setCertificateVerifyProc((request, callback) => {
|
||||
* `webContents` [WebContents](web-contents.md) - WebContents requesting the permission. Please note that if the request comes from a subframe you should use `requestingUrl` to check the request origin.
|
||||
* `permission` string - The type of requested permission.
|
||||
* `clipboard-read` - Request access to read from the clipboard.
|
||||
* `clipboard-sanitized-write` - Request access to write to the clipboard.
|
||||
* `media` - Request access to media devices such as camera, microphone and speakers.
|
||||
* `display-capture` - Request access to capture the screen.
|
||||
* `mediaKeySystem` - Request access to DRM protected content.
|
||||
@@ -682,6 +683,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.
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
* `id` string - The identifier of a window or screen that can be used as a
|
||||
`chromeMediaSourceId` constraint when calling
|
||||
[`navigator.webkitGetUserMedia`]. The format of the identifier will be
|
||||
[`navigator.getUserMedia`](https://developer.mozilla.org/en-US/docs/Web/API/Navigator/getUserMedia). The format of the identifier will be
|
||||
`window:XX:YY` or `screen:ZZ:0`. XX is the windowID/handle. YY is 1 for
|
||||
the current process, and 0 for all others. ZZ is a sequential number
|
||||
that represents the screen, and it does not equal to the index in the
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -394,8 +394,6 @@ system default and override the value of `getEffectiveAppearance`.
|
||||
|
||||
Returns `boolean` - whether or not this device has the ability to use Touch ID.
|
||||
|
||||
**NOTE:** This API will return `false` on macOS systems older than Sierra 10.12.2.
|
||||
|
||||
### `systemPreferences.promptTouchID(reason)` _macOS_
|
||||
|
||||
* `reason` string - The reason you are asking for Touch ID authentication
|
||||
@@ -414,8 +412,6 @@ systemPreferences.promptTouchID('To get consent for a Security-Gated Thing').the
|
||||
|
||||
This API itself will not protect your user data; rather, it is a mechanism to allow you to do so. Native apps will need to set [Access Control Constants](https://developer.apple.com/documentation/security/secaccesscontrolcreateflags?language=objc) like [`kSecAccessControlUserPresence`](https://developer.apple.com/documentation/security/secaccesscontrolcreateflags/ksecaccesscontroluserpresence?language=objc) on their keychain entry so that reading it would auto-prompt for Touch ID biometric consent. This could be done with [`node-keytar`](https://github.com/atom/node-keytar), such that one would store an encryption key with `node-keytar` and only fetch it if `promptTouchID()` resolves.
|
||||
|
||||
**NOTE:** This API will return a rejected Promise on macOS systems older than Sierra 10.12.2.
|
||||
|
||||
### `systemPreferences.isTrustedAccessibilityClient(prompt)` _macOS_
|
||||
|
||||
* `prompt` boolean - whether or not the user will be informed via prompt if the current process is untrusted.
|
||||
@@ -428,7 +424,7 @@ Returns `boolean` - `true` if the current process is a trusted accessibility cli
|
||||
|
||||
Returns `string` - Can be `not-determined`, `granted`, `denied`, `restricted` or `unknown`.
|
||||
|
||||
This user consent was not required on macOS 10.13 High Sierra or lower so this method will always return `granted`.
|
||||
This user consent was not required on macOS 10.13 High Sierra so this method will always return `granted`.
|
||||
macOS 10.14 Mojave or higher requires consent for `microphone` and `camera` access.
|
||||
macOS 10.15 Catalina or higher requires consent for `screen` access.
|
||||
|
||||
@@ -441,9 +437,9 @@ It will always return `granted` for `screen` and for all media types on older ve
|
||||
|
||||
Returns `Promise<boolean>` - A promise that resolves with `true` if consent was granted and `false` if it was denied. If an invalid `mediaType` is passed, the promise will be rejected. If an access request was denied and later is changed through the System Preferences pane, a restart of the app will be required for the new permissions to take effect. If access has already been requested and denied, it _must_ be changed through the preference pane; an alert will not pop up and the promise will resolve with the existing access status.
|
||||
|
||||
**Important:** In order to properly leverage this API, you [must set](https://developer.apple.com/documentation/avfoundation/cameras_and_media_capture/requesting_authorization_for_media_capture_on_macos?language=objc) the `NSMicrophoneUsageDescription` and `NSCameraUsageDescription` strings in your app's `Info.plist` file. The values for these keys will be used to populate the permission dialogs so that the user will be properly informed as to the purpose of the permission request. See [Electron Application Distribution](../tutorial/application-distribution.md#macos) for more information about how to set these in the context of Electron.
|
||||
**Important:** In order to properly leverage this API, you [must set](https://developer.apple.com/documentation/avfoundation/cameras_and_media_capture/requesting_authorization_for_media_capture_on_macos?language=objc) the `NSMicrophoneUsageDescription` and `NSCameraUsageDescription` strings in your app's `Info.plist` file. The values for these keys will be used to populate the permission dialogs so that the user will be properly informed as to the purpose of the permission request. See [Electron Application Distribution](../tutorial/application-distribution.md#rebranding-with-downloaded-binaries) for more information about how to set these in the context of Electron.
|
||||
|
||||
This user consent was not required until macOS 10.14 Mojave, so this method will always return `true` if your system is running 10.13 High Sierra or lower.
|
||||
This user consent was not required until macOS 10.14 Mojave, so this method will always return `true` if your system is running 10.13 High Sierra.
|
||||
|
||||
### `systemPreferences.getAnimationSettings()`
|
||||
|
||||
|
||||
@@ -29,8 +29,9 @@ __Platform Considerations__
|
||||
|
||||
__Linux__
|
||||
|
||||
* Tray icon requires support of [StatusNotifierItem](https://www.freedesktop.org/wiki/Specifications/StatusNotifierItem/)
|
||||
in user's desktop environment.
|
||||
* Tray icon uses [StatusNotifierItem](https://www.freedesktop.org/wiki/Specifications/StatusNotifierItem/)
|
||||
by default, when it is not available in user's desktop environment the
|
||||
`GtkStatusIcon` will be used instead.
|
||||
* The `click` event is emitted when the tray icon receives activation from
|
||||
user, however the StatusNotifierItem spec does not specify which action would
|
||||
cause an activation, for some environments it is left mouse click, but for
|
||||
@@ -234,7 +235,7 @@ Sets the hover text for this tray icon.
|
||||
|
||||
* `title` string
|
||||
* `options` Object (optional)
|
||||
* `fontType` string (optional) - The font family variant to display, can be `monospaced` or `monospacedDigit`. `monospaced` is available in macOS 10.15+ and `monospacedDigit` is available in macOS 10.11+. When left blank, the title uses the default system font.
|
||||
* `fontType` string (optional) - The font family variant to display, can be `monospaced` or `monospacedDigit`. `monospaced` is available in macOS 10.15+ When left blank, the title uses the default system font.
|
||||
|
||||
Sets the title displayed next to the tray icon in the status bar (Support ANSI colors).
|
||||
|
||||
|
||||
@@ -132,6 +132,7 @@ Returns:
|
||||
Emitted when the child process sends a message using [`process.parentPort.postMessage()`](process.md#processparentport).
|
||||
|
||||
[`child_process.fork`]: https://nodejs.org/dist/latest-v16.x/docs/api/child_process.html#child_processforkmodulepath-args-options
|
||||
[Services API]: https://chromium.googlesource.com/chromium/src/+/master/docs/mojo_and_services.md
|
||||
[Services API]: https://chromium.googlesource.com/chromium/src/+/main/docs/mojo_and_services.md
|
||||
[stdio]: https://nodejs.org/dist/latest/docs/api/child_process.html#optionsstdio
|
||||
[event-emitter]: https://nodejs.org/api/events.html#events_class_eventemitter
|
||||
[`MessagePortMain`]: message-port-main.md
|
||||
|
||||
@@ -713,20 +713,24 @@ Returns:
|
||||
* `callback` Function
|
||||
* `deviceId` string
|
||||
|
||||
Emitted when bluetooth device needs to be selected on call to
|
||||
`navigator.bluetooth.requestDevice`. To use `navigator.bluetooth` api
|
||||
`webBluetooth` should be enabled. If `event.preventDefault` is not called,
|
||||
first available device will be selected. `callback` should be called with
|
||||
`deviceId` to be selected, passing empty string to `callback` will
|
||||
cancel the request.
|
||||
Emitted when a bluetooth device needs to be selected when a call to
|
||||
`navigator.bluetooth.requestDevice` is made. `callback` should be called with
|
||||
the `deviceId` of the device to be selected. Passing an empty string to
|
||||
`callback` will cancel the request.
|
||||
|
||||
If no event listener is added for this event, all bluetooth requests will be cancelled.
|
||||
If an event listener is not added for this event, or if `event.preventDefault`
|
||||
is not called when handling this event, the first available device will be
|
||||
automatically selected.
|
||||
|
||||
Due to the nature of bluetooth, scanning for devices when
|
||||
`navigator.bluetooth.requestDevice` is called may take time and will cause
|
||||
`select-bluetooth-device` to fire multiple times until `callback` is called
|
||||
with either a device id or an empty string to cancel the request.
|
||||
|
||||
```javascript
|
||||
const { app, BrowserWindow } = require('electron')
|
||||
|
||||
let win = null
|
||||
app.commandLine.appendSwitch('enable-experimental-web-platform-features')
|
||||
|
||||
app.whenReady().then(() => {
|
||||
win = new BrowserWindow({ width: 800, height: 600 })
|
||||
@@ -736,6 +740,9 @@ app.whenReady().then(() => {
|
||||
return device.deviceName === 'test'
|
||||
})
|
||||
if (!result) {
|
||||
// The device wasn't found so we need to either wait longer (eg until the
|
||||
// device is turned on) or cancel the request by calling the callback
|
||||
// with an empty string.
|
||||
callback('')
|
||||
} else {
|
||||
callback(result.deviceId)
|
||||
@@ -1155,7 +1162,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()`
|
||||
@@ -1170,8 +1177,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'}`.
|
||||
@@ -1413,8 +1423,8 @@ Returns `Promise<PrinterInfo[]>` - Resolves with a [`PrinterInfo[]`](structures/
|
||||
* `vertical` number (optional) - The vertical dpi.
|
||||
* `header` string (optional) - string to be printed as page header.
|
||||
* `footer` string (optional) - string to be printed as page footer.
|
||||
* `pageSize` string | Size (optional) - Specify page size of the printed document. Can be `A3`,
|
||||
`A4`, `A5`, `Legal`, `Letter`, `Tabloid` or an Object containing `height` and `width`.
|
||||
* `pageSize` string | Size (optional) - Specify page size of the printed document. Can be `A0`, `A1`, `A2`, `A3`,
|
||||
`A4`, `A5`, `A6`, `Legal`, `Letter`, `Tabloid` or an Object containing `height` and `width`.
|
||||
* `callback` Function (optional)
|
||||
* `success` boolean - Indicates success of the print call.
|
||||
* `failureReason` string - Error description called back if the print fails.
|
||||
@@ -2070,3 +2080,4 @@ with open(), or by navigating a link with a target attribute.
|
||||
[event-emitter]: https://nodejs.org/api/events.html#events_class_eventemitter
|
||||
[SCA]: https://developer.mozilla.org/en-US/docs/Web/API/Web_Workers_API/Structured_clone_algorithm
|
||||
[`postMessage`]: https://developer.mozilla.org/en-US/docs/Web/API/Window/postMessage
|
||||
[`MessagePortMain`]: message-port-main.md
|
||||
|
||||
@@ -233,3 +233,4 @@ See also how the [Page Visibility API](browser-window.md#page-visibility) is aff
|
||||
|
||||
[SCA]: https://developer.mozilla.org/en-US/docs/Web/API/Web_Workers_API/Structured_clone_algorithm
|
||||
[`postMessage`]: https://developer.mozilla.org/en-US/docs/Web/API/Window/postMessage
|
||||
[`MessagePortMain`]: message-port-main.md
|
||||
|
||||
@@ -993,7 +993,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'
|
||||
|
||||
@@ -146,6 +146,13 @@ webContents.printToPDF({
|
||||
|
||||
## Planned Breaking API Changes (20.0)
|
||||
|
||||
### Removed: macOS 10.11 / 10.12 support
|
||||
|
||||
macOS 10.11 (El Capitan) and macOS 10.12 (Sierra) are no longer supported by [Chromium](https://chromium-review.googlesource.com/c/chromium/src/+/3646050).
|
||||
|
||||
Older versions of Electron will continue to run on these operating systems, but macOS 10.13 (High Sierra)
|
||||
or later will be required to run Electron v20.0.0 and higher.
|
||||
|
||||
### Default Changed: renderers without `nodeIntegration: true` are sandboxed by default
|
||||
|
||||
Previously, renderers that specified a preload script defaulted to being
|
||||
@@ -170,7 +177,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)
|
||||
|
||||
@@ -7,13 +7,12 @@ Follow the guidelines below for building **Electron itself** on Windows, for the
|
||||
## Prerequisites
|
||||
|
||||
* Windows 10 / Server 2012 R2 or higher
|
||||
* Visual Studio 2017 15.7.2 or higher - [download VS 2019 Community Edition for
|
||||
free](https://www.visualstudio.com/vs/)
|
||||
* Visual Studio 2019 (>=16.0.0) to build, but Visual Studio 2022 (>=17.0.0) is preferred - [download VS 2022 Community Edition for free](https://www.visualstudio.com/vs/)
|
||||
* See [the Chromium build documentation](https://chromium.googlesource.com/chromium/src/+/main/docs/windows_build_instructions.md#visual-studio) for more details on which Visual Studio
|
||||
components are required.
|
||||
* If your Visual Studio is installed in a directory other than the default, you'll need to
|
||||
set a few environment variables to point the toolchains to your installation path.
|
||||
* `vs2019_install = DRIVE:\path\to\Microsoft Visual Studio\2019\Community`, replacing `2019` and `Community` with your installed versions and replacing `DRIVE:` with the drive that Visual Studio is on. Often, this will be `C:`.
|
||||
* `vs2022_install = DRIVE:\path\to\Microsoft Visual Studio\2022\Community`, replacing `2022` and `Community` with your installed versions and replacing `DRIVE:` with the drive that Visual Studio is on. Often, this will be `C:`.
|
||||
* `WINDOWSSDKDIR = DRIVE:\path\to\Windows Kits\10`, replacing `DRIVE:` with the drive that Windows Kits is on. Often, this will be `C:`.
|
||||
* [Node.js](https://nodejs.org/download/)
|
||||
* [Git](https://git-scm.com)
|
||||
|
||||
@@ -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})
|
||||
```
|
||||
|
||||
|
||||
@@ -15,7 +15,7 @@ calls, and other compiler optimizations. The only workaround is to build an
|
||||
unoptimized local build.
|
||||
|
||||
The official symbol server URL for Electron is
|
||||
https://symbols.electronjs.org.
|
||||
<https://symbols.electronjs.org>.
|
||||
You cannot visit this URL directly, you must add it to the symbol path of your
|
||||
debugging tool. In the examples below, a local cache directory is used to avoid
|
||||
repeatedly fetching the PDB from the server. Replace `c:\code\symbols` with an
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
<h1>Web Bluetooth API</h1>
|
||||
|
||||
<button id="clickme">Test Bluetooth</button>
|
||||
<button id="cancel">Cancel Bluetooth Request</button>
|
||||
|
||||
<p>Currently selected bluetooth device: <strong id="device-name""></strong></p>
|
||||
|
||||
|
||||
@@ -1,22 +1,37 @@
|
||||
const {app, BrowserWindow, ipcMain} = require('electron')
|
||||
const path = require('path')
|
||||
|
||||
let bluetoothPinCallback
|
||||
let selectBluetoothCallback
|
||||
|
||||
function createWindow () {
|
||||
const mainWindow = new BrowserWindow({
|
||||
width: 800,
|
||||
height: 600,
|
||||
webPreferences: {
|
||||
preload: path.join(__dirname, 'preload.js')
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
mainWindow.webContents.on('select-bluetooth-device', (event, deviceList, callback) => {
|
||||
event.preventDefault()
|
||||
if (deviceList && deviceList.length > 0) {
|
||||
callback(deviceList[0].deviceId)
|
||||
}
|
||||
selectBluetoothCallback = callback
|
||||
const result = deviceList.find((device) => {
|
||||
return device.deviceName === 'test'
|
||||
})
|
||||
if (result) {
|
||||
callback(result.deviceId)
|
||||
} else {
|
||||
// The device wasn't found so we need to either wait longer (eg until the
|
||||
// device is turned on) or until the user cancels the request
|
||||
}
|
||||
})
|
||||
|
||||
ipcMain.on('cancel-bluetooth-request', (event) => {
|
||||
selectBluetoothCallback('')
|
||||
})
|
||||
|
||||
|
||||
// Listen for a message from the renderer to get the response for the Bluetooth pairing.
|
||||
ipcMain.on('bluetooth-pairing-response', (event, response) => {
|
||||
bluetoothPinCallback(response)
|
||||
@@ -27,14 +42,14 @@ function createWindow () {
|
||||
bluetoothPinCallback = callback
|
||||
// Send a message to the renderer to prompt the user to confirm the pairing.
|
||||
mainWindow.webContents.send('bluetooth-pairing-request', details)
|
||||
})
|
||||
})
|
||||
|
||||
mainWindow.loadFile('index.html')
|
||||
}
|
||||
|
||||
app.whenReady().then(() => {
|
||||
createWindow()
|
||||
|
||||
|
||||
app.on('activate', function () {
|
||||
if (BrowserWindow.getAllWindows().length === 0) createWindow()
|
||||
})
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
const { contextBridge, ipcRenderer } = require('electron')
|
||||
|
||||
contextBridge.exposeInMainWorld('electronAPI', {
|
||||
cancelBluetoothRequest: (callback) => ipcRenderer.send('cancel-bluetooth-request', callback),
|
||||
bluetoothPairingRequest: (callback) => ipcRenderer.on('bluetooth-pairing-request', callback),
|
||||
bluetoothPairingResponse: (response) => ipcRenderer.send('bluetooth-pairing-response', response)
|
||||
})
|
||||
@@ -7,9 +7,15 @@ async function testIt() {
|
||||
|
||||
document.getElementById('clickme').addEventListener('click',testIt)
|
||||
|
||||
function cancelRequest() {
|
||||
window.electronAPI.cancelBluetoothRequest()
|
||||
}
|
||||
|
||||
document.getElementById('cancel').addEventListener('click', cancelRequest)
|
||||
|
||||
window.electronAPI.bluetoothPairingRequest((event, details) => {
|
||||
const response = {}
|
||||
|
||||
|
||||
switch (details.pairingKind) {
|
||||
case 'confirm': {
|
||||
response.confirmed = confirm(`Do you want to connect to device ${details.deviceId}?`)
|
||||
@@ -31,4 +37,4 @@ window.electronAPI.bluetoothPairingRequest((event, details) => {
|
||||
}
|
||||
|
||||
window.electronAPI.bluetoothPairingResponse(response)
|
||||
})
|
||||
})
|
||||
|
||||
@@ -2,12 +2,13 @@
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta http-equiv="Content-Security-Policy" content="script-src 'self' 'unsafe-inline';" />
|
||||
</head>
|
||||
<body>
|
||||
<div>
|
||||
<div>
|
||||
<h1>Clipboard copy</h1>
|
||||
<i>Supports: Win, macOS, Linux <span>|</span> Process: Both</i>
|
||||
<i>Supports: Win, macOS, Linux <span>|</span> Process: Main, Renderer (non-sandboxed only)</i>
|
||||
<div>
|
||||
<div>
|
||||
<button id="copy-to">Copy</button>
|
||||
@@ -17,8 +18,6 @@
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<script src="./renderer.js"></script>
|
||||
</body>
|
||||
<script>
|
||||
require('./renderer.js')
|
||||
</script>
|
||||
</html>
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
const { app, BrowserWindow } = require('electron')
|
||||
const { app, BrowserWindow, ipcMain, clipboard } = require('electron')
|
||||
const path = require('path')
|
||||
|
||||
let mainWindow = null
|
||||
|
||||
@@ -8,7 +9,7 @@ function createWindow () {
|
||||
height: 400,
|
||||
title: 'Clipboard copy',
|
||||
webPreferences: {
|
||||
nodeIntegration: true
|
||||
preload: path.join(__dirname, 'preload.js')
|
||||
}
|
||||
}
|
||||
|
||||
@@ -20,6 +21,18 @@ function createWindow () {
|
||||
})
|
||||
}
|
||||
|
||||
ipcMain.handle('clipboard:writeText', (event, text) => {
|
||||
clipboard.writeText(text)
|
||||
})
|
||||
|
||||
app.whenReady().then(() => {
|
||||
createWindow()
|
||||
|
||||
app.on('activate', function () {
|
||||
if (BrowserWindow.getAllWindows().length === 0) createWindow()
|
||||
})
|
||||
})
|
||||
|
||||
app.on('window-all-closed', function () {
|
||||
if (process.platform !== 'darwin') app.quit()
|
||||
})
|
||||
|
||||
5
docs/fiddles/system/clipboard/copy/preload.js
Normal file
5
docs/fiddles/system/clipboard/copy/preload.js
Normal file
@@ -0,0 +1,5 @@
|
||||
const { contextBridge, ipcRenderer } = require('electron')
|
||||
|
||||
contextBridge.exposeInMainWorld('clipboard', {
|
||||
writeText: (text) => ipcRenderer.invoke('clipboard:writeText', text)
|
||||
})
|
||||
@@ -1,5 +1,3 @@
|
||||
const { clipboard } = require('electron')
|
||||
|
||||
const copyBtn = document.getElementById('copy-to')
|
||||
const copyInput = document.getElementById('copy-to-input')
|
||||
|
||||
|
||||
@@ -2,12 +2,13 @@
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta http-equiv="Content-Security-Policy" content="script-src 'self' 'unsafe-inline';" />
|
||||
</head>
|
||||
<body>
|
||||
<div>
|
||||
<div>
|
||||
<h1>Clipboard paste</h1>
|
||||
<i>Supports: Win, macOS, Linux <span>|</span> Process: Both</i>
|
||||
<i>Supports: Win, macOS, Linux <span>|</span> Process: Main, Renderer (non-sandboxed only)</i>
|
||||
<div>
|
||||
<div>
|
||||
<button id="paste-to">Paste</button>
|
||||
@@ -17,8 +18,6 @@
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<script src="./renderer.js"></script>
|
||||
</body>
|
||||
<script>
|
||||
require('./renderer.js')
|
||||
</script>
|
||||
</html>
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
const { app, BrowserWindow } = require('electron')
|
||||
const { app, BrowserWindow, ipcMain, clipboard } = require('electron')
|
||||
const path = require('path')
|
||||
|
||||
let mainWindow = null
|
||||
|
||||
@@ -8,7 +9,7 @@ function createWindow () {
|
||||
height: 400,
|
||||
title: 'Clipboard paste',
|
||||
webPreferences: {
|
||||
nodeIntegration: true
|
||||
preload: path.join(__dirname, 'preload.js')
|
||||
}
|
||||
}
|
||||
|
||||
@@ -20,6 +21,22 @@ function createWindow () {
|
||||
})
|
||||
}
|
||||
|
||||
ipcMain.handle('clipboard:readText', () => {
|
||||
return clipboard.readText()
|
||||
})
|
||||
|
||||
ipcMain.handle('clipboard:writeText', (event, text) => {
|
||||
clipboard.writeText(text)
|
||||
})
|
||||
|
||||
app.whenReady().then(() => {
|
||||
createWindow()
|
||||
|
||||
app.on('activate', function () {
|
||||
if (BrowserWindow.getAllWindows().length === 0) createWindow()
|
||||
})
|
||||
})
|
||||
|
||||
app.on('window-all-closed', function () {
|
||||
if (process.platform !== 'darwin') app.quit()
|
||||
})
|
||||
|
||||
6
docs/fiddles/system/clipboard/paste/preload.js
Normal file
6
docs/fiddles/system/clipboard/paste/preload.js
Normal file
@@ -0,0 +1,6 @@
|
||||
const { contextBridge, ipcRenderer } = require('electron')
|
||||
|
||||
contextBridge.exposeInMainWorld('clipboard', {
|
||||
readText: () => ipcRenderer.invoke('clipboard:readText'),
|
||||
writeText: (text) => ipcRenderer.invoke('clipboard:writeText', text)
|
||||
})
|
||||
@@ -1,9 +1,7 @@
|
||||
const { clipboard } = require('electron')
|
||||
|
||||
const pasteBtn = document.getElementById('paste-to')
|
||||
|
||||
pasteBtn.addEventListener('click', () => {
|
||||
clipboard.writeText('What a demo!')
|
||||
const message = `Clipboard contents: ${clipboard.readText()}`
|
||||
pasteBtn.addEventListener('click', async () => {
|
||||
await clipboard.writeText('What a demo!')
|
||||
const message = `Clipboard contents: ${await clipboard.readText()}`
|
||||
document.getElementById('paste-from').innerHTML = message
|
||||
})
|
||||
|
||||
@@ -23,6 +23,8 @@ if (!gotTheLock) {
|
||||
if (mainWindow.isMinimized()) mainWindow.restore()
|
||||
mainWindow.focus()
|
||||
}
|
||||
|
||||
dialog.showErrorBox('Welcome Back', `You arrived from: ${commandLine.pop().slice(0,-1)}`)
|
||||
})
|
||||
|
||||
// Create mainWindow, load the rest of the app, etc...
|
||||
|
||||
@@ -132,7 +132,7 @@ OSR (offscreen rendering) can be used for loading heavy page in
|
||||
background and then displaying it after (it will be much faster).
|
||||
It allows you to render page without showing it on screen.
|
||||
|
||||
For more information, read the [Offscreen Rendering][osr] tutorial.
|
||||
For more information, read the [Offscreen Rendering] tutorial.
|
||||
|
||||
### preload script
|
||||
|
||||
@@ -235,10 +235,10 @@ embedded content.
|
||||
[mac app store submission guide]: tutorial/mac-app-store-submission-guide.md
|
||||
[main]: #main-process
|
||||
[msi]: https://docs.microsoft.com/en-us/windows/win32/msi/windows-installer-portal
|
||||
[Native Node Modules]: tutorial/using-native-node-modules.md
|
||||
[offscreen rendering]: tutorial/offscreen-rendering.md
|
||||
[process sandboxing]: tutorial/sandbox.md
|
||||
[renderer]: #renderer-process
|
||||
[userland]: #userland
|
||||
[using native node modules]: tutorial/using-native-node-modules.md
|
||||
[UtilityProcess]: api/utility-process.md
|
||||
[v8]: #v8
|
||||
|
||||
@@ -24,7 +24,7 @@ development and release. They are more helpful and supportive but enforce
|
||||
guidelines on how your code should be structured and built. *Especially for
|
||||
beginners, using a command line tool is likely to be helpful*.
|
||||
|
||||
## electron-forge
|
||||
## Electron Forge
|
||||
|
||||
Electron Forge is a tool for packaging and publishing Electron applications. It unifies Electron's tooling ecosystem
|
||||
into a single extensible interface so that anyone can jump right into making Electron apps.
|
||||
|
||||
@@ -13,7 +13,7 @@ from the OS.
|
||||
|
||||
If your app has its own dark mode, you should toggle it on and off in sync with
|
||||
the system's dark mode setting. You can do this by using the
|
||||
[prefer-color-scheme] CSS media query.
|
||||
[prefers-color-scheme] CSS media query.
|
||||
|
||||
### Manually update your own interfaces
|
||||
|
||||
|
||||
@@ -15,7 +15,7 @@ NPM package that does just that.
|
||||
If you don't want to use the tooling approach, you can also do all of the necessary
|
||||
operations by hand. To load an extension in Electron, you need to download it via Chrome,
|
||||
locate its filesystem path, and then load it into your [Session][session] by calling the
|
||||
[`ses.loadExtension`] API.
|
||||
[`ses.loadExtension`][load-extension] API.
|
||||
|
||||
Using the [React Developer Tools][react-devtools] as an example:
|
||||
|
||||
|
||||
@@ -9,10 +9,11 @@ check out our [Electron Versioning](./electron-versioning.md) doc.
|
||||
|
||||
| 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 | ✅ |
|
||||
| 23.0.0 | 2022-Dec-01 | 2023-Jan-10 | 2023-Feb-07 | TBD | M110 | TBD | ✅ |
|
||||
| 22.0.0 | 2022-Sep-29 | 2022-Oct-25 | 2022-Nov-29 | TBD | M108 | v16.17 | ✅ |
|
||||
| 21.0.0 | 2022-Aug-04 | 2022-Aug-30 | 2022-Sep-27 | TBD | M106 | v16.16 | ✅ |
|
||||
| 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 | ✅ |
|
||||
| 19.0.0 | 2022-Mar-31 | 2022-Apr-26 | 2022-May-24 | 2022-Nov-29 | 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 | 🚫 |
|
||||
|
||||
@@ -52,5 +52,6 @@ You can find the full list of "How to?" in the sidebar. If there is
|
||||
something that you would like to do that is not documented, please join
|
||||
our [Discord server][discord] and let us know!
|
||||
|
||||
[app]: ../api/app.md
|
||||
[discord]: https://discord.gg/electronjs
|
||||
[fiddle]: https://www.electronjs.org/fiddle
|
||||
|
||||
@@ -31,6 +31,6 @@ template and submit a new issue.
|
||||
[(package)]: https://www.electronforge.io/cli#package
|
||||
[(make)]: https://www.electronforge.io/cli#make
|
||||
[(publish)]: https://www.electronforge.io/cli#publish
|
||||
[GitHub issue tracker]: https://github.com/electron-userland/electron-forge/issues
|
||||
[GitHub issue tracker]: https://github.com/electron/forge/issues
|
||||
[discord]: https://discord.gg/APGC3k5yaH
|
||||
[tutorial]: https://www.electronjs.org/docs/latest/tutorial/tutorial-prerequisites
|
||||
[tutorial]: ./tutorial-1-prerequisites.md
|
||||
|
||||
@@ -12,7 +12,7 @@ hide_title: true
|
||||
<!-- ✍ Update this section if you want to provide more details -->
|
||||
|
||||
This guide will take you through the process of setting your Electron app as the default
|
||||
handler for a specific [protocol](https://www.electronjs.org/docs/api/protocol).
|
||||
handler for a specific [protocol](../api/protocol.md).
|
||||
|
||||
By the end of this tutorial, we will have set our app to intercept and handle
|
||||
any clicked URLs that start with a specific protocol. In this guide, the protocol
|
||||
@@ -61,7 +61,7 @@ const createWindow = () => {
|
||||
|
||||
In this next step, we will create our `BrowserWindow` and tell our application how to handle an event in which an external protocol is clicked.
|
||||
|
||||
This code will be different in Windows compared to MacOS and Linux. This is due to Windows requiring additional code in order to open the contents of the protocol link within the same Electron instance. Read more about this [here](https://www.electronjs.org/docs/api/app#apprequestsingleinstancelock).
|
||||
This code will be different in Windows compared to MacOS and Linux. This is due to Windows requiring additional code in order to open the contents of the protocol link within the same Electron instance. Read more about this [here](../api/app.md#apprequestsingleinstancelockadditionaldata).
|
||||
|
||||
#### Windows code:
|
||||
|
||||
@@ -77,17 +77,15 @@ if (!gotTheLock) {
|
||||
if (mainWindow.isMinimized()) mainWindow.restore()
|
||||
mainWindow.focus()
|
||||
}
|
||||
// the commandLine is array of strings in which last element is deep link url
|
||||
// the url str ends with /
|
||||
dialog.showErrorBox('Welcome Back', `You arrived from: ${commandLine.pop().slice(0, -1)}`)
|
||||
})
|
||||
|
||||
// Create mainWindow, load the rest of the app, etc...
|
||||
app.whenReady().then(() => {
|
||||
createWindow()
|
||||
})
|
||||
|
||||
// Handle the protocol. In this case, we choose to show an Error Box.
|
||||
app.on('open-url', (event, url) => {
|
||||
dialog.showErrorBox('Welcome Back', `You arrived from: ${url}`)
|
||||
})
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
@@ -149,4 +149,4 @@ GNOME, KDE.
|
||||
[notification-spec]: https://developer-old.gnome.org/notification-spec/
|
||||
[app-user-model-id]: https://msdn.microsoft.com/en-us/library/windows/desktop/dd378459(v=vs.85).aspx
|
||||
[set-app-user-model-id]: ../api/app.md#appsetappusermodelidid-windows
|
||||
[squirrel-events]: https://github.com/electron/windows-installer/blob/master/README.md#handling-squirrel-events
|
||||
[squirrel-events]: https://github.com/electron/windows-installer/blob/main/README.md#handling-squirrel-events
|
||||
|
||||
@@ -438,7 +438,7 @@ Call `Menu.setApplicationMenu(null)` before `app.on("ready")`. This will prevent
|
||||
[request-idle-callback]: https://developer.mozilla.org/en-US/docs/Web/API/Window/requestIdleCallback
|
||||
[multithreading]: ./multithreading.md
|
||||
[caniuse]: https://caniuse.com/
|
||||
[jquery-need]: http://youmightnotneedjquery.com/
|
||||
[jquery-need]: https://youmightnotneedjquery.com/
|
||||
[service-workers]: https://developer.mozilla.org/en-US/docs/Web/API/Service_Worker_API
|
||||
[webpack]: https://webpack.js.org/
|
||||
[parcel]: https://parceljs.org/
|
||||
|
||||
@@ -84,7 +84,7 @@ the `sandbox: false` preference in the [`BrowserWindow`][browser-window] constru
|
||||
app.whenReady().then(() => {
|
||||
const win = new BrowserWindow({
|
||||
webPreferences: {
|
||||
sandbox: true
|
||||
sandbox: false
|
||||
}
|
||||
})
|
||||
win.loadURL('https://google.com')
|
||||
|
||||
@@ -13,7 +13,7 @@ system modification.
|
||||
|
||||
There are three ways to create a `.snap` file:
|
||||
|
||||
1) Using [`electron-forge`][electron-forge] or
|
||||
1) Using [Electron Forge][electron-forge] or
|
||||
[`electron-builder`][electron-builder], both tools that come with `snap`
|
||||
support out of the box. This is the easiest option.
|
||||
2) Using `electron-installer-snap`, which takes `electron-packager`'s output.
|
||||
@@ -162,7 +162,7 @@ building blocks.
|
||||
|
||||
If you do not already have a `.deb` package, using `electron-installer-snap`
|
||||
might be an easier path to create snap packages. However, multiple solutions
|
||||
for creating Debian packages exist, including [`electron-forge`][electron-forge],
|
||||
for creating Debian packages exist, including [Electron Forge][electron-forge],
|
||||
[`electron-builder`][electron-builder] or
|
||||
[`electron-installer-debian`][electron-installer-debian].
|
||||
|
||||
@@ -239,7 +239,7 @@ apps:
|
||||
|
||||
[snapcraft-syntax]: https://docs.snapcraft.io/build-snaps/syntax
|
||||
[electron-packager]: https://github.com/electron/electron-packager
|
||||
[electron-forge]: https://github.com/electron-userland/electron-forge
|
||||
[electron-forge]: https://github.com/electron/forge
|
||||
[electron-builder]: https://github.com/electron-userland/electron-builder
|
||||
[electron-installer-debian]: https://github.com/unindented/electron-installer-debian
|
||||
[electron-winstaller]: https://github.com/electron/windows-installer
|
||||
|
||||
@@ -13,7 +13,7 @@ hide_title: true
|
||||
<!-- ✍ Update this section if you want to provide more details -->
|
||||
|
||||
This guide will take you through the process of creating a
|
||||
[Tray](https://www.electronjs.org/docs/api/tray) icon with
|
||||
[Tray](../api/tray.md) icon with
|
||||
its own context menu to the system's notification area.
|
||||
|
||||
On MacOS and Ubuntu, the Tray will be located on the top
|
||||
@@ -31,11 +31,11 @@ const { app, Tray, Menu, nativeImage } = require('electron')
|
||||
```
|
||||
|
||||
Next we will create our Tray. To do this, we will use a
|
||||
[`NativeImage`](https://www.electronjs.org/docs/api/native-image) icon,
|
||||
[`NativeImage`](../api/native-image.md) icon,
|
||||
which can be created through any one of these
|
||||
[methods](https://www.electronjs.org/docs/api/native-image#methods).
|
||||
[methods](../api/native-image.md#methods).
|
||||
Note that we wrap our Tray creation code within an
|
||||
[`app.whenReady`](https://www.electronjs.org/docs/api/app#appwhenready)
|
||||
[`app.whenReady`](../api/app.md#appwhenready)
|
||||
as we will need to wait for our electron app to finish initializing.
|
||||
|
||||
```js title='main.js'
|
||||
@@ -64,7 +64,7 @@ tray.setContextMenu(contextMenu)
|
||||
|
||||
The code above will create 4 separate radio-type items in the context menu.
|
||||
To read more about constructing native menus, click
|
||||
[here](https://www.electronjs.org/docs/api/menu#menubuildfromtemplatetemplate).
|
||||
[here](../api/menu.md#menubuildfromtemplatetemplate).
|
||||
|
||||
Finally, let's give our tray a tooltip and a title.
|
||||
|
||||
|
||||
@@ -81,7 +81,7 @@ contextBridge.exposeInMainWorld('versions', {
|
||||
To attach this script to your renderer process, pass its path to the
|
||||
`webPreferences.preload` option in the BrowserWindow constructor:
|
||||
|
||||
```js {8-10} title="main.js"
|
||||
```js {2,8-10} title="main.js"
|
||||
const { app, BrowserWindow } = require('electron')
|
||||
const path = require('path')
|
||||
|
||||
|
||||
@@ -63,7 +63,7 @@ into end users' hands.
|
||||
<!-- Link labels -->
|
||||
|
||||
[discord]: https://discord.gg/electronjs
|
||||
[github]: https://github.com/electron/electronjs.org-new/issues/new
|
||||
[github]: https://github.com/electron/website/issues/new
|
||||
[how-to]: ./examples.md
|
||||
[node-platform]: https://nodejs.org/api/process.html#process_process_platform
|
||||
|
||||
|
||||
@@ -222,12 +222,12 @@ rest of our docs and happy developing! If you have questions, please stop by our
|
||||
[code-signed]: ./code-signing.md
|
||||
[discord server]: https://discord.gg/electronjs
|
||||
[electron fiddle]: https://electronjs.org/fiddle
|
||||
[fiddle-build]: https://github.com/electron/fiddle/blob/master/.github/workflows/build.yaml
|
||||
[fiddle-forge-config]: https://github.com/electron/fiddle/blob/master/forge.config.js
|
||||
[fiddle-build]: https://github.com/electron/fiddle/blob/main/.github/workflows/build.yaml
|
||||
[fiddle-forge-config]: https://github.com/electron/fiddle/blob/main/forge.config.js
|
||||
[github actions]: https://github.com/features/actions
|
||||
[github publisher]: https://www.electronforge.io/config/publishers/github
|
||||
[github releases]: https://docs.github.com/en/repositories/releasing-projects-on-github/managing-releases-in-a-repository
|
||||
[git tag]: https://git-scm.com/book/en/v2/Git-Basics-Tagging
|
||||
[git-tag]: https://git-scm.com/book/en/v2/Git-Basics-Tagging
|
||||
[new-pat]: https://github.com/settings/tokens/new
|
||||
[publish command]: https://www.electronforge.io/cli#publish
|
||||
[publisher]: https://www.electronforge.io/config/publishers
|
||||
|
||||
@@ -67,7 +67,7 @@ Depending on your needs, you can choose from one of these:
|
||||
to minify server cost.
|
||||
|
||||
Once you've deployed your update server, you can instrument your app code to receive and
|
||||
apply the updates with Electron's [autoUpdater] module.
|
||||
apply the updates with Electron's [autoUpdater](../api/auto-updater.md) module.
|
||||
|
||||
### Step 2: Receiving updates in your app
|
||||
|
||||
|
||||
@@ -35,9 +35,15 @@ filenames = {
|
||||
"shell/browser/relauncher_linux.cc",
|
||||
"shell/browser/ui/electron_desktop_window_tree_host_linux.cc",
|
||||
"shell/browser/ui/file_dialog_gtk.cc",
|
||||
"shell/browser/ui/gtk/menu_gtk.cc",
|
||||
"shell/browser/ui/gtk/menu_gtk.h",
|
||||
"shell/browser/ui/gtk/menu_util.cc",
|
||||
"shell/browser/ui/gtk/menu_util.h",
|
||||
"shell/browser/ui/message_box_gtk.cc",
|
||||
"shell/browser/ui/tray_icon_gtk.cc",
|
||||
"shell/browser/ui/tray_icon_gtk.h",
|
||||
"shell/browser/ui/status_icon_gtk.cc",
|
||||
"shell/browser/ui/status_icon_gtk.h",
|
||||
"shell/browser/ui/tray_icon_linux.cc",
|
||||
"shell/browser/ui/tray_icon_linux.h",
|
||||
"shell/browser/ui/views/client_frame_view_linux.cc",
|
||||
"shell/browser/ui/views/client_frame_view_linux.h",
|
||||
"shell/common/application_info_linux.cc",
|
||||
|
||||
@@ -414,7 +414,14 @@ libcxx_headers = [
|
||||
"//buildtools/third_party/libc++/trunk/include/__memory/uninitialized_algorithms.h",
|
||||
"//buildtools/third_party/libc++/trunk/include/__memory/unique_ptr.h",
|
||||
"//buildtools/third_party/libc++/trunk/include/__memory/uses_allocator.h",
|
||||
"//buildtools/third_party/libc++/trunk/include/__memory/uses_allocator_construction.h",
|
||||
"//buildtools/third_party/libc++/trunk/include/__memory/voidify.h",
|
||||
"//buildtools/third_party/libc++/trunk/include/__memory_resource/memory_resource.h",
|
||||
"//buildtools/third_party/libc++/trunk/include/__memory_resource/monotonic_buffer_resource.h",
|
||||
"//buildtools/third_party/libc++/trunk/include/__memory_resource/polymorphic_allocator.h",
|
||||
"//buildtools/third_party/libc++/trunk/include/__memory_resource/pool_options.h",
|
||||
"//buildtools/third_party/libc++/trunk/include/__memory_resource/synchronized_pool_resource.h",
|
||||
"//buildtools/third_party/libc++/trunk/include/__memory_resource/unsynchronized_pool_resource.h",
|
||||
"//buildtools/third_party/libc++/trunk/include/__mutex_base",
|
||||
"//buildtools/third_party/libc++/trunk/include/__node_handle",
|
||||
"//buildtools/third_party/libc++/trunk/include/__numeric/accumulate.h",
|
||||
@@ -482,6 +489,7 @@ libcxx_headers = [
|
||||
"//buildtools/third_party/libc++/trunk/include/__ranges/enable_view.h",
|
||||
"//buildtools/third_party/libc++/trunk/include/__ranges/filter_view.h",
|
||||
"//buildtools/third_party/libc++/trunk/include/__ranges/iota_view.h",
|
||||
"//buildtools/third_party/libc++/trunk/include/__ranges/istream_view.h",
|
||||
"//buildtools/third_party/libc++/trunk/include/__ranges/join_view.h",
|
||||
"//buildtools/third_party/libc++/trunk/include/__ranges/lazy_split_view.h",
|
||||
"//buildtools/third_party/libc++/trunk/include/__ranges/non_propagating_cache.h",
|
||||
@@ -495,6 +503,7 @@ libcxx_headers = [
|
||||
"//buildtools/third_party/libc++/trunk/include/__ranges/size.h",
|
||||
"//buildtools/third_party/libc++/trunk/include/__ranges/subrange.h",
|
||||
"//buildtools/third_party/libc++/trunk/include/__ranges/take_view.h",
|
||||
"//buildtools/third_party/libc++/trunk/include/__ranges/take_while_view.h",
|
||||
"//buildtools/third_party/libc++/trunk/include/__ranges/transform_view.h",
|
||||
"//buildtools/third_party/libc++/trunk/include/__ranges/view_interface.h",
|
||||
"//buildtools/third_party/libc++/trunk/include/__ranges/views.h",
|
||||
@@ -775,6 +784,7 @@ libcxx_headers = [
|
||||
"//buildtools/third_party/libc++/trunk/include/map",
|
||||
"//buildtools/third_party/libc++/trunk/include/math.h",
|
||||
"//buildtools/third_party/libc++/trunk/include/memory",
|
||||
"//buildtools/third_party/libc++/trunk/include/memory_resource",
|
||||
"//buildtools/third_party/libc++/trunk/include/module.modulemap.in",
|
||||
"//buildtools/third_party/libc++/trunk/include/mutex",
|
||||
"//buildtools/third_party/libc++/trunk/include/new",
|
||||
|
||||
@@ -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?.withFileTypes) {
|
||||
const dirents = [];
|
||||
for (const file of files) {
|
||||
const childPath = path.join(filePath, file);
|
||||
|
||||
@@ -28,11 +28,47 @@ type PostData = LoadURLOptions['postData']
|
||||
|
||||
// Stock page sizes
|
||||
const PDFPageSizes: Record<string, ElectronInternal.MediaSize> = {
|
||||
A5: {
|
||||
custom_display_name: 'A5',
|
||||
height_microns: 210000,
|
||||
name: 'ISO_A5',
|
||||
width_microns: 148000
|
||||
Letter: {
|
||||
custom_display_name: 'Letter',
|
||||
height_microns: 279400,
|
||||
name: 'NA_LETTER',
|
||||
width_microns: 215900
|
||||
},
|
||||
Legal: {
|
||||
custom_display_name: 'Legal',
|
||||
height_microns: 355600,
|
||||
name: 'NA_LEGAL',
|
||||
width_microns: 215900
|
||||
},
|
||||
Tabloid: {
|
||||
height_microns: 431800,
|
||||
name: 'NA_LEDGER',
|
||||
width_microns: 279400,
|
||||
custom_display_name: 'Tabloid'
|
||||
},
|
||||
A0: {
|
||||
custom_display_name: 'A0',
|
||||
height_microns: 1189000,
|
||||
name: 'ISO_A0',
|
||||
width_microns: 841000
|
||||
},
|
||||
A1: {
|
||||
custom_display_name: 'A1',
|
||||
height_microns: 841000,
|
||||
name: 'ISO_A1',
|
||||
width_microns: 594000
|
||||
},
|
||||
A2: {
|
||||
custom_display_name: 'A2',
|
||||
height_microns: 594000,
|
||||
name: 'ISO_A2',
|
||||
width_microns: 420000
|
||||
},
|
||||
A3: {
|
||||
custom_display_name: 'A3',
|
||||
height_microns: 420000,
|
||||
name: 'ISO_A3',
|
||||
width_microns: 297000
|
||||
},
|
||||
A4: {
|
||||
custom_display_name: 'A4',
|
||||
@@ -41,29 +77,17 @@ const PDFPageSizes: Record<string, ElectronInternal.MediaSize> = {
|
||||
is_default: 'true',
|
||||
width_microns: 210000
|
||||
},
|
||||
A3: {
|
||||
custom_display_name: 'A3',
|
||||
height_microns: 420000,
|
||||
name: 'ISO_A3',
|
||||
width_microns: 297000
|
||||
A5: {
|
||||
custom_display_name: 'A5',
|
||||
height_microns: 210000,
|
||||
name: 'ISO_A5',
|
||||
width_microns: 148000
|
||||
},
|
||||
Legal: {
|
||||
custom_display_name: 'Legal',
|
||||
height_microns: 355600,
|
||||
name: 'NA_LEGAL',
|
||||
width_microns: 215900
|
||||
},
|
||||
Letter: {
|
||||
custom_display_name: 'Letter',
|
||||
height_microns: 279400,
|
||||
name: 'NA_LETTER',
|
||||
width_microns: 215900
|
||||
},
|
||||
Tabloid: {
|
||||
height_microns: 431800,
|
||||
name: 'NA_LEDGER',
|
||||
width_microns: 279400,
|
||||
custom_display_name: 'Tabloid'
|
||||
A6: {
|
||||
custom_display_name: 'A6',
|
||||
height_microns: 148000,
|
||||
name: 'ISO_A6',
|
||||
width_microns: 105000
|
||||
}
|
||||
} as const;
|
||||
|
||||
@@ -272,7 +296,7 @@ WebContents.prototype.printToPDF = async function (options) {
|
||||
|
||||
if (options.pageRanges !== undefined) {
|
||||
if (typeof options.pageRanges !== 'string') {
|
||||
return Promise.reject(new Error('printBackground must be a String'));
|
||||
return Promise.reject(new Error('pageRanges must be a String'));
|
||||
}
|
||||
printSettings.pageRanges = options.pageRanges;
|
||||
}
|
||||
|
||||
@@ -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.pathname[0] === '/' ? self?.location.pathname.substr(1) : self?.location.pathname;
|
||||
global.__filename = path.normalize(decodeURIComponent(pathname));
|
||||
global.__dirname = path.dirname(global.__filename);
|
||||
|
||||
|
||||
10
package.json
10
package.json
@@ -6,9 +6,10 @@
|
||||
"devDependencies": {
|
||||
"@azure/storage-blob": "^12.9.0",
|
||||
"@electron/docs-parser": "^1.0.0",
|
||||
"@electron/fiddle-core": "^1.0.4",
|
||||
"@electron/github-app-auth": "^1.5.0",
|
||||
"@electron/typescript-definitions": "^8.10.0",
|
||||
"@octokit/auth-app": "^2.10.0",
|
||||
"@octokit/rest": "^18.0.3",
|
||||
"@octokit/rest": "^19.0.7",
|
||||
"@primer/octicons": "^10.0.0",
|
||||
"@types/basic-auth": "^1.1.3",
|
||||
"@types/busboy": "^0.2.3",
|
||||
@@ -143,10 +144,11 @@
|
||||
"ts-node script/check-patch-diff.ts"
|
||||
],
|
||||
"DEPS": [
|
||||
"node script/gen-hunspell-filenames.js"
|
||||
"node script/gen-hunspell-filenames.js",
|
||||
"node script/gen-libc++-filenames.js"
|
||||
]
|
||||
},
|
||||
"resolutions": {
|
||||
"nan": "nodejs/nan#16fa32231e2ccd89d2804b3f765319128b20c4ac"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
4
patches/angle/.patches
Normal file
4
patches/angle/.patches
Normal file
@@ -0,0 +1,4 @@
|
||||
fix_rename_webswapcgllayer_to_webswapcgllayerchromium.patch
|
||||
cherry-pick-55e2b6daba9d.patch
|
||||
cherry-pick-ce029c91a662.patch
|
||||
cherry-pick-aed05b609629.patch
|
||||
136
patches/angle/cherry-pick-55e2b6daba9d.patch
Normal file
136
patches/angle/cherry-pick-55e2b6daba9d.patch
Normal file
@@ -0,0 +1,136 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Shahbaz Youssefi <syoussefi@chromium.org>
|
||||
Date: Thu, 16 Feb 2023 23:16:46 -0500
|
||||
Subject: Vulkan: Don't close render pass if rebind to same fbo
|
||||
|
||||
M108 merge issues:
|
||||
src/libANGLE/renderer/vulkan/ContextVk.cpp:
|
||||
- hasActiveRenderPass named hasStartedRenderPass in 108
|
||||
- getLastRenderPassQueueSerial named getLastRenderPassSerial in 108
|
||||
|
||||
In the Vulkan backend, the render pass can occasionally (and
|
||||
transiently) be in a state of "open but inactive". This is when the
|
||||
render pass is closed, but has the potential for future modifications
|
||||
(for example to add a resolve attachment). Under many circumstances, it
|
||||
is expected that an open render pass cannot be in such a state.
|
||||
|
||||
This assumption can be broken in this scenario:
|
||||
|
||||
- Open render pass, draw, etc
|
||||
- Change framebuffer binding
|
||||
- Change framebuffer binding back to original
|
||||
- Masked Clear
|
||||
|
||||
When ContextVk is synced before clear, it sees that the framebuffer
|
||||
binding is changed (though it hasn't really), and it closes the render
|
||||
passes and sets the render pass dirty bit. If a draw were to follow, a
|
||||
new render pass would have started (unnecessarily). However, in the
|
||||
case of a masked clear, UtilsVk notices that the render pass is started,
|
||||
assumes it must be active, and continues recording to it. While the
|
||||
operation itself succeeds, the assumption that the render pass is active
|
||||
is false (and fails assertion).
|
||||
|
||||
This change makes sure that framebuffer binding change is no-oped if the
|
||||
framebuffer is the same one that has opened the current render pass. If
|
||||
any application does unnecessary binding changes and back, it will be
|
||||
optimized by this change as well.
|
||||
|
||||
Bug: chromium:1411210
|
||||
Change-Id: I37a3a9f2eaa1a81a1b3393840b9458ec71a87377
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/4261215
|
||||
Commit-Queue: Shahbaz Youssefi <syoussefi@chromium.org>
|
||||
(cherry picked from commit 05e62f39412e8c6bfc98582f5e7a49041991c97b)
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/4303738
|
||||
Reviewed-by: Shahbaz Youssefi <syoussefi@chromium.org>
|
||||
|
||||
diff --git a/src/libANGLE/renderer/vulkan/ContextVk.cpp b/src/libANGLE/renderer/vulkan/ContextVk.cpp
|
||||
index f08877444f66ac2d61953c9c56d4c71d253d53c6..31e1882c8923b81bf5fd74fbe40d8233c7551ec9 100644
|
||||
--- a/src/libANGLE/renderer/vulkan/ContextVk.cpp
|
||||
+++ b/src/libANGLE/renderer/vulkan/ContextVk.cpp
|
||||
@@ -5022,6 +5022,15 @@ angle::Result ContextVk::syncState(const gl::Context *context,
|
||||
// as some optimizations in non-draw commands require the render pass to remain
|
||||
// open, such as invalidate or blit. Note that we always start a new command buffer
|
||||
// because we currently can only support one open RenderPass at a time.
|
||||
+ //
|
||||
+ // The render pass is not closed if binding is changed to the same framebuffer as
|
||||
+ // before.
|
||||
+ if (hasStartedRenderPass() &&
|
||||
+ hasStartedRenderPassWithSerial(drawFramebufferVk->getLastRenderPassSerial()))
|
||||
+ {
|
||||
+ break;
|
||||
+ }
|
||||
+
|
||||
onRenderPassFinished(RenderPassClosureReason::FramebufferBindingChange);
|
||||
if (getFeatures().preferSubmitAtFBOBoundary.enabled)
|
||||
{
|
||||
diff --git a/src/tests/gl_tests/ClearTest.cpp b/src/tests/gl_tests/ClearTest.cpp
|
||||
index 1a6b425da6be1e1c2526a8f5e5d84ea8049ee7ab..41e3ea7efe26d1aa0e0dd0e8e9d5bcd7b6472017 100644
|
||||
--- a/src/tests/gl_tests/ClearTest.cpp
|
||||
+++ b/src/tests/gl_tests/ClearTest.cpp
|
||||
@@ -2864,6 +2864,26 @@ TEST_P(ClearTest, DISABLED_ClearReachesWindow)
|
||||
angle::Sleep(2000);
|
||||
}
|
||||
|
||||
+// Tests that masked clear after a no-op framebuffer binding change with an open render pass works.
|
||||
+TEST_P(ClearTest, DrawThenChangeFBOBindingAndBackThenMaskedClear)
|
||||
+{
|
||||
+ ANGLE_GL_PROGRAM(blueProgram, essl1_shaders::vs::Simple(), essl1_shaders::fs::Blue());
|
||||
+
|
||||
+ // Draw blue.
|
||||
+ drawQuad(blueProgram, essl1_shaders::PositionAttrib(), 0.5f);
|
||||
+
|
||||
+ // Change framebuffer and back
|
||||
+ glBindFramebuffer(GL_FRAMEBUFFER, mFBOs[0]);
|
||||
+ glBindFramebuffer(GL_FRAMEBUFFER, 0);
|
||||
+
|
||||
+ // Masked clear
|
||||
+ glColorMask(1, 0, 0, 1);
|
||||
+ glClearColor(1.0f, 0.5f, 0.5f, 1.0f);
|
||||
+ glClear(GL_COLOR_BUFFER_BIT);
|
||||
+
|
||||
+ EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::magenta);
|
||||
+}
|
||||
+
|
||||
// Test that clearing slices of a 3D texture and reading them back works.
|
||||
TEST_P(ClearTestES3, ClearAndReadPixels3DTexture)
|
||||
{
|
||||
diff --git a/src/tests/gl_tests/VulkanPerformanceCounterTest.cpp b/src/tests/gl_tests/VulkanPerformanceCounterTest.cpp
|
||||
index 7268d08da90e27022f7139aa98b5972e1dfe62f1..6a91ecc2b4329696f573db3451dac35a0a795c8c 100644
|
||||
--- a/src/tests/gl_tests/VulkanPerformanceCounterTest.cpp
|
||||
+++ b/src/tests/gl_tests/VulkanPerformanceCounterTest.cpp
|
||||
@@ -5,7 +5,7 @@
|
||||
//
|
||||
// VulkanPerformanceCounterTest:
|
||||
// Validates specific GL call patterns with ANGLE performance counters.
|
||||
-// For example we can verify a certain call set doesn't break the RenderPass.
|
||||
+// For example we can verify a certain call set doesn't break the render pass.
|
||||
|
||||
#include "test_utils/ANGLETest.h"
|
||||
#include "test_utils/angle_test_instantiate.h"
|
||||
@@ -6991,6 +6991,26 @@ TEST_P(VulkanPerformanceCounterTest, EndXfbAfterRenderPassClosed)
|
||||
EXPECT_EQ(getPerfCounters().renderPasses, expectedRenderPassCount);
|
||||
}
|
||||
|
||||
+// Verify that changing framebuffer and back doesn't break the render pass.
|
||||
+TEST_P(VulkanPerformanceCounterTest, FBOChangeAndBackDoesNotBreakRenderPass)
|
||||
+{
|
||||
+ uint64_t expectedRenderPassCount = getPerfCounters().renderPasses + 1;
|
||||
+
|
||||
+ ANGLE_GL_PROGRAM(drawRed, essl3_shaders::vs::Simple(), essl3_shaders::fs::Red());
|
||||
+ drawQuad(drawRed, essl1_shaders::PositionAttrib(), 0);
|
||||
+
|
||||
+ GLFramebuffer fbo;
|
||||
+ glBindFramebuffer(GL_FRAMEBUFFER, fbo);
|
||||
+ glBindFramebuffer(GL_FRAMEBUFFER, 0);
|
||||
+
|
||||
+ drawQuad(drawRed, essl1_shaders::PositionAttrib(), 0);
|
||||
+
|
||||
+ // Verify render pass count.
|
||||
+ EXPECT_EQ(getPerfCounters().renderPasses, expectedRenderPassCount);
|
||||
+
|
||||
+ EXPECT_PIXEL_COLOR_EQ(0, 0, GLColor::red);
|
||||
+}
|
||||
+
|
||||
GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(VulkanPerformanceCounterTest);
|
||||
ANGLE_INSTANTIATE_TEST(VulkanPerformanceCounterTest, ES3_VULKAN(), ES3_VULKAN_SWIFTSHADER());
|
||||
|
||||
108
patches/angle/cherry-pick-aed05b609629.patch
Normal file
108
patches/angle/cherry-pick-aed05b609629.patch
Normal file
@@ -0,0 +1,108 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Geoff Lang <geofflang@chromium.org>
|
||||
Date: Fri, 31 Mar 2023 16:44:35 -0400
|
||||
Subject: M112: Mark RGBX and BGRX formats as having 8 unused bits.
|
||||
|
||||
This makes sure that pixelBytes ends up being 4 and fixes potential
|
||||
buffer size validation.
|
||||
|
||||
Fix EGL configs using pixelBytes to compute EGL_BUFFER_SIZE which
|
||||
is not supposed to include unused bits. This is covered by
|
||||
dEQP-EGL.functional.query_config.constraints.color_buffer_size
|
||||
|
||||
Bug: chromium:1404790
|
||||
Change-Id: Ie0480cbdc6229c4bb3a6c6242337eaed5a3ae3b7
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/4428752
|
||||
Reviewed-by: Amirali Abdolrashidi <abdolrashidi@google.com>
|
||||
|
||||
diff --git a/src/libANGLE/formatutils.cpp b/src/libANGLE/formatutils.cpp
|
||||
index 76273f3be3406a1c4be11c8fe564e3f703aed4b9..4014953311976b0f1ae2d1842e8fced75ffecfc9 100644
|
||||
--- a/src/libANGLE/formatutils.cpp
|
||||
+++ b/src/libANGLE/formatutils.cpp
|
||||
@@ -549,6 +549,21 @@ bool InternalFormat::isDepthOrStencil() const
|
||||
return depthBits != 0 || stencilBits != 0;
|
||||
}
|
||||
|
||||
+GLuint InternalFormat::getEGLConfigBufferSize() const
|
||||
+{
|
||||
+ // EGL config's EGL_BUFFER_SIZE is measured in bits and is the sum of all the color channels for
|
||||
+ // color formats or the luma channels for luma formats. It ignores unused bits so compute the
|
||||
+ // bit count by summing instead of using pixelBytes.
|
||||
+ if (isLUMA())
|
||||
+ {
|
||||
+ return luminanceBits + alphaBits;
|
||||
+ }
|
||||
+ else
|
||||
+ {
|
||||
+ return redBits + greenBits + blueBits + alphaBits;
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
Format::Format(GLenum internalFormat) : Format(GetSizedInternalFormatInfo(internalFormat)) {}
|
||||
|
||||
Format::Format(const InternalFormat &internalFormat) : info(&internalFormat) {}
|
||||
@@ -1141,10 +1156,10 @@ static InternalFormatInfoMap BuildInternalFormatInfoMap()
|
||||
AddRGBAFormat(&map, GL_BGR10_A2_ANGLEX, true, 10, 10, 10, 2, 0, GL_BGRA_EXT, GL_UNSIGNED_INT_2_10_10_10_REV, GL_UNSIGNED_NORMALIZED, false, NeverSupported, NeverSupported, NeverSupported, NeverSupported, NeverSupported);
|
||||
|
||||
// Special format to emulate RGB8 with RGBA8 within ANGLE.
|
||||
- AddRGBAFormat(&map, GL_RGBX8_ANGLE, true, 8, 8, 8, 0, 0, GL_RGB, GL_UNSIGNED_BYTE, GL_UNSIGNED_NORMALIZED, false, AlwaysSupported, AlwaysSupported, AlwaysSupported, AlwaysSupported, NeverSupported);
|
||||
+ AddRGBAXFormat(&map, GL_RGBX8_ANGLE, true, FB< 8, 8, 8, 0, 8, 0>(), GL_RGB, GL_UNSIGNED_BYTE, GL_UNSIGNED_NORMALIZED, false, AlwaysSupported, AlwaysSupported, AlwaysSupported, AlwaysSupported, NeverSupported);
|
||||
|
||||
// Special format to emulate BGR8 with BGRA8 within ANGLE.
|
||||
- AddRGBAFormat(&map, GL_BGRX8_ANGLEX, true, 8, 8, 8, 0, 0, GL_BGRA_EXT, GL_UNSIGNED_BYTE, GL_UNSIGNED_NORMALIZED, false, NeverSupported, AlwaysSupported, NeverSupported, NeverSupported, NeverSupported);
|
||||
+ AddRGBAXFormat(&map, GL_BGRX8_ANGLEX, true, FB< 8, 8, 8, 0, 8, 0>(), GL_BGRA_EXT, GL_UNSIGNED_BYTE, GL_UNSIGNED_NORMALIZED, false, NeverSupported, AlwaysSupported, NeverSupported, NeverSupported, NeverSupported);
|
||||
|
||||
// This format is supported on ES 2.0 with two extensions, so keep it out-of-line to not widen the table above even more.
|
||||
// | Internal format |sized| R | G | B | A |S | Format | Type | Component type | SRGB | Texture supported | Filterable | Texture attachment | Renderbuffer | Blend
|
||||
diff --git a/src/libANGLE/formatutils.h b/src/libANGLE/formatutils.h
|
||||
index 64cc42ec1f50ea017216063896ba2c07296cde37..e6154072365a8a253937a3f148ae12f7199c593c 100644
|
||||
--- a/src/libANGLE/formatutils.h
|
||||
+++ b/src/libANGLE/formatutils.h
|
||||
@@ -205,6 +205,8 @@ struct InternalFormat
|
||||
bool isInt() const;
|
||||
bool isDepthOrStencil() const;
|
||||
|
||||
+ GLuint getEGLConfigBufferSize() const;
|
||||
+
|
||||
bool operator==(const InternalFormat &other) const;
|
||||
bool operator!=(const InternalFormat &other) const;
|
||||
|
||||
diff --git a/src/libANGLE/renderer/d3d/d3d11/Renderer11.cpp b/src/libANGLE/renderer/d3d/d3d11/Renderer11.cpp
|
||||
index cc56e9868248a192b6c22e650528986c88722503..040623866da9b78ca66efb7de4f8678dd98f5f1c 100644
|
||||
--- a/src/libANGLE/renderer/d3d/d3d11/Renderer11.cpp
|
||||
+++ b/src/libANGLE/renderer/d3d/d3d11/Renderer11.cpp
|
||||
@@ -1242,7 +1242,7 @@ egl::ConfigSet Renderer11::generateConfigs()
|
||||
egl::Config config;
|
||||
config.renderTargetFormat = colorBufferInternalFormat;
|
||||
config.depthStencilFormat = depthStencilBufferInternalFormat;
|
||||
- config.bufferSize = colorBufferFormatInfo.pixelBytes * 8;
|
||||
+ config.bufferSize = colorBufferFormatInfo.getEGLConfigBufferSize();
|
||||
config.redSize = colorBufferFormatInfo.redBits;
|
||||
config.greenSize = colorBufferFormatInfo.greenBits;
|
||||
config.blueSize = colorBufferFormatInfo.blueBits;
|
||||
diff --git a/src/libANGLE/renderer/d3d/d3d9/Renderer9.cpp b/src/libANGLE/renderer/d3d/d3d9/Renderer9.cpp
|
||||
index d80997392d2d5d25cadc1381c84929401bce90a9..6979fe5445360e6703cdb35fd9a15a6e34d188c8 100644
|
||||
--- a/src/libANGLE/renderer/d3d/d3d9/Renderer9.cpp
|
||||
+++ b/src/libANGLE/renderer/d3d/d3d9/Renderer9.cpp
|
||||
@@ -523,7 +523,7 @@ egl::ConfigSet Renderer9::generateConfigs()
|
||||
egl::Config config;
|
||||
config.renderTargetFormat = colorBufferInternalFormat;
|
||||
config.depthStencilFormat = depthStencilBufferInternalFormat;
|
||||
- config.bufferSize = colorBufferFormatInfo.pixelBytes * 8;
|
||||
+ config.bufferSize = colorBufferFormatInfo.getEGLConfigBufferSize();
|
||||
config.redSize = colorBufferFormatInfo.redBits;
|
||||
config.greenSize = colorBufferFormatInfo.greenBits;
|
||||
config.blueSize = colorBufferFormatInfo.blueBits;
|
||||
diff --git a/src/libANGLE/renderer/vulkan/vk_caps_utils.cpp b/src/libANGLE/renderer/vulkan/vk_caps_utils.cpp
|
||||
index f49b24744682910ae5142f784c9e01ba1977c360..f601b516441fdb4db9e17db5ad22cb6198755e99 100644
|
||||
--- a/src/libANGLE/renderer/vulkan/vk_caps_utils.cpp
|
||||
+++ b/src/libANGLE/renderer/vulkan/vk_caps_utils.cpp
|
||||
@@ -1238,7 +1238,7 @@ egl::Config GenerateDefaultConfig(DisplayVk *display,
|
||||
|
||||
config.renderTargetFormat = colorFormat.internalFormat;
|
||||
config.depthStencilFormat = depthStencilFormat.internalFormat;
|
||||
- config.bufferSize = colorFormat.pixelBytes * 8;
|
||||
+ config.bufferSize = colorFormat.getEGLConfigBufferSize();
|
||||
config.redSize = colorFormat.redBits;
|
||||
config.greenSize = colorFormat.greenBits;
|
||||
config.blueSize = colorFormat.blueBits;
|
||||
158
patches/angle/cherry-pick-ce029c91a662.patch
Normal file
158
patches/angle/cherry-pick-ce029c91a662.patch
Normal file
@@ -0,0 +1,158 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Geoff Lang <geofflang@chromium.org>
|
||||
Date: Fri, 10 Mar 2023 13:48:03 -0500
|
||||
Subject: M110: D3D11: Add logic to disassociate EGL image storages.
|
||||
|
||||
The TextureStorage classes for External and EGLImages were missing the
|
||||
logic to disassociate from images. This lead to the images continuing
|
||||
to hold references to deleted storages.
|
||||
|
||||
Bug: chromium:1415330
|
||||
Change-Id: I8303f6751d87a9b0a52993c7d4e9509b086b93f3
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/4328347
|
||||
Reviewed-by: Peng Huang <penghuang@chromium.org>
|
||||
Commit-Queue: Geoff Lang <geofflang@chromium.org>
|
||||
(cherry picked from commit a8720455fda43167465c3d2f9a13fca60c21f56e)
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/4348335
|
||||
Reviewed-by: Shahbaz Youssefi <syoussefi@chromium.org>
|
||||
|
||||
diff --git a/src/libANGLE/renderer/d3d/d3d11/TextureStorage11.cpp b/src/libANGLE/renderer/d3d/d3d11/TextureStorage11.cpp
|
||||
index f1277462a929ed867a325f12db5fbf011b3f678e..c2fe439ca826e86b023dbe982ff44dd3bfb56470 100644
|
||||
--- a/src/libANGLE/renderer/d3d/d3d11/TextureStorage11.cpp
|
||||
+++ b/src/libANGLE/renderer/d3d/d3d11/TextureStorage11.cpp
|
||||
@@ -1652,7 +1652,8 @@ TextureStorage11_External::TextureStorage11_External(
|
||||
egl::Stream *stream,
|
||||
const egl::Stream::GLTextureDescription &glDesc,
|
||||
const std::string &label)
|
||||
- : TextureStorage11(renderer, D3D11_BIND_SHADER_RESOURCE, 0, glDesc.internalFormat, label)
|
||||
+ : TextureStorage11(renderer, D3D11_BIND_SHADER_RESOURCE, 0, glDesc.internalFormat, label),
|
||||
+ mAssociatedImage(nullptr)
|
||||
{
|
||||
ASSERT(stream->getProducerType() == egl::Stream::ProducerType::D3D11Texture);
|
||||
auto *producer = static_cast<StreamProducerD3DTexture *>(stream->getImplementation());
|
||||
@@ -1678,6 +1679,15 @@ angle::Result TextureStorage11_External::onDestroy(const gl::Context *context)
|
||||
mRenderer->getStateManager()->invalidateBoundViews();
|
||||
}
|
||||
|
||||
+ if (mAssociatedImage != nullptr)
|
||||
+ {
|
||||
+ mAssociatedImage->verifyAssociatedStorageValid(this);
|
||||
+
|
||||
+ // We must let the Images recover their data before we delete it from the
|
||||
+ // TextureStorage.
|
||||
+ ANGLE_TRY(mAssociatedImage->recoverFromAssociatedStorage(context));
|
||||
+ }
|
||||
+
|
||||
return angle::Result::Continue;
|
||||
}
|
||||
|
||||
@@ -1885,7 +1895,8 @@ TextureStorage11_EGLImage::TextureStorage11_EGLImage(Renderer11 *renderer,
|
||||
mImage(eglImage),
|
||||
mCurrentRenderTarget(0),
|
||||
mSwizzleTexture(),
|
||||
- mSwizzleRenderTargets(gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS)
|
||||
+ mSwizzleRenderTargets(gl::IMPLEMENTATION_MAX_TEXTURE_LEVELS),
|
||||
+ mAssociatedImage(nullptr)
|
||||
{
|
||||
mCurrentRenderTarget = reinterpret_cast<uintptr_t>(renderTarget11);
|
||||
|
||||
@@ -1897,6 +1908,20 @@ TextureStorage11_EGLImage::TextureStorage11_EGLImage(Renderer11 *renderer,
|
||||
|
||||
TextureStorage11_EGLImage::~TextureStorage11_EGLImage() {}
|
||||
|
||||
+angle::Result TextureStorage11_EGLImage::onDestroy(const gl::Context *context)
|
||||
+{
|
||||
+ if (mAssociatedImage != nullptr)
|
||||
+ {
|
||||
+ mAssociatedImage->verifyAssociatedStorageValid(this);
|
||||
+
|
||||
+ // We must let the Images recover their data before we delete it from the
|
||||
+ // TextureStorage.
|
||||
+ ANGLE_TRY(mAssociatedImage->recoverFromAssociatedStorage(context));
|
||||
+ }
|
||||
+
|
||||
+ return angle::Result::Continue;
|
||||
+}
|
||||
+
|
||||
angle::Result TextureStorage11_EGLImage::getSubresourceIndex(const gl::Context *context,
|
||||
const gl::ImageIndex &index,
|
||||
UINT *outSubresourceIndex) const
|
||||
@@ -2120,6 +2145,42 @@ void TextureStorage11_EGLImage::onLabelUpdate()
|
||||
}
|
||||
}
|
||||
|
||||
+void TextureStorage11_EGLImage::associateImage(Image11 *image, const gl::ImageIndex &index)
|
||||
+{
|
||||
+ ASSERT(index.getLevelIndex() == 0);
|
||||
+ mAssociatedImage = image;
|
||||
+}
|
||||
+
|
||||
+void TextureStorage11_EGLImage::verifyAssociatedImageValid(const gl::ImageIndex &index,
|
||||
+ Image11 *expectedImage)
|
||||
+{
|
||||
+ ASSERT(index.getLevelIndex() == 0 && mAssociatedImage == expectedImage);
|
||||
+}
|
||||
+
|
||||
+void TextureStorage11_EGLImage::disassociateImage(const gl::ImageIndex &index,
|
||||
+ Image11 *expectedImage)
|
||||
+{
|
||||
+ ASSERT(index.getLevelIndex() == 0);
|
||||
+ ASSERT(mAssociatedImage == expectedImage);
|
||||
+ mAssociatedImage = nullptr;
|
||||
+}
|
||||
+
|
||||
+angle::Result TextureStorage11_EGLImage::releaseAssociatedImage(const gl::Context *context,
|
||||
+ const gl::ImageIndex &index,
|
||||
+ Image11 *incomingImage)
|
||||
+{
|
||||
+ ASSERT(index.getLevelIndex() == 0);
|
||||
+
|
||||
+ if (mAssociatedImage != nullptr && mAssociatedImage != incomingImage)
|
||||
+ {
|
||||
+ mAssociatedImage->verifyAssociatedStorageValid(this);
|
||||
+
|
||||
+ ANGLE_TRY(mAssociatedImage->recoverFromAssociatedStorage(context));
|
||||
+ }
|
||||
+
|
||||
+ return angle::Result::Continue;
|
||||
+}
|
||||
+
|
||||
TextureStorage11_Cube::TextureStorage11_Cube(Renderer11 *renderer,
|
||||
GLenum internalformat,
|
||||
BindFlags bindFlags,
|
||||
diff --git a/src/libANGLE/renderer/d3d/d3d11/TextureStorage11.h b/src/libANGLE/renderer/d3d/d3d11/TextureStorage11.h
|
||||
index 72bc1b802c5d4f2befe7a440aae8e115d5b94c8a..7c5245acd8fcb7880f19905c0f69c7b7886e9e72 100644
|
||||
--- a/src/libANGLE/renderer/d3d/d3d11/TextureStorage11.h
|
||||
+++ b/src/libANGLE/renderer/d3d/d3d11/TextureStorage11.h
|
||||
@@ -492,6 +492,8 @@ class TextureStorage11_EGLImage final : public TextureStorage11ImmutableBase
|
||||
const std::string &label);
|
||||
~TextureStorage11_EGLImage() override;
|
||||
|
||||
+ angle::Result onDestroy(const gl::Context *context) override;
|
||||
+
|
||||
angle::Result getSubresourceIndex(const gl::Context *context,
|
||||
const gl::ImageIndex &index,
|
||||
UINT *outSubresourceIndex) const override;
|
||||
@@ -518,6 +520,13 @@ class TextureStorage11_EGLImage final : public TextureStorage11ImmutableBase
|
||||
bool useLevelZeroTexture) override;
|
||||
void onLabelUpdate() override;
|
||||
|
||||
+ void associateImage(Image11 *image, const gl::ImageIndex &index) override;
|
||||
+ void disassociateImage(const gl::ImageIndex &index, Image11 *expectedImage) override;
|
||||
+ void verifyAssociatedImageValid(const gl::ImageIndex &index, Image11 *expectedImage) override;
|
||||
+ angle::Result releaseAssociatedImage(const gl::Context *context,
|
||||
+ const gl::ImageIndex &index,
|
||||
+ Image11 *incomingImage) override;
|
||||
+
|
||||
protected:
|
||||
angle::Result getSwizzleTexture(const gl::Context *context,
|
||||
const TextureHelper11 **outTexture) override;
|
||||
@@ -545,6 +554,8 @@ class TextureStorage11_EGLImage final : public TextureStorage11ImmutableBase
|
||||
// Swizzle-related variables
|
||||
TextureHelper11 mSwizzleTexture;
|
||||
std::vector<d3d11::RenderTargetView> mSwizzleRenderTargets;
|
||||
+
|
||||
+ Image11 *mAssociatedImage;
|
||||
};
|
||||
|
||||
class TextureStorage11_Cube : public TextureStorage11
|
||||
@@ -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 7101cd271c07e604c6f5241d1a22f59f446c0033..98a89976f87e32a66bd504951698204fad938d57 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
|
||||
{
|
||||
@@ -89,7 +89,7 @@ class WindowSurfaceCGL : public SurfaceGL
|
||||
gl::Framebuffer *framebuffer) 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 27990e9c2facbbe0e30f4b275e0778a6474fb9ce..84f9fa9b6d31fb0e85a4c4270dff4d935f855c26 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
|
||||
@@ -220,9 +220,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]];
|
||||
|
||||
@@ -48,10 +48,10 @@ index a6ca0ab96266475384429e73970de18d4ba09912..c7e7bd02f2484f91bf55df1400e94804
|
||||
void SSL_CTX_set_tmp_rsa_callback(SSL_CTX *ctx,
|
||||
RSA *(*cb)(SSL *ssl, int is_export,
|
||||
diff --git a/ssl/ssl_test.cc b/ssl/ssl_test.cc
|
||||
index 3709a4694f3c9be67fd918f125f023b5aa660971..3507f4ef5bd4444c2499b06a5e312ab54f08bc3b 100644
|
||||
index 3515f602f192369bfc25b1df0bb8a71d3320afb7..5179b12f63740771312563391a1c348d611a8ba9 100644
|
||||
--- a/ssl/ssl_test.cc
|
||||
+++ b/ssl/ssl_test.cc
|
||||
@@ -8358,11 +8358,6 @@ TEST(SSLTest, ErrorSyscallAfterCloseNotify) {
|
||||
@@ -8360,11 +8360,6 @@ TEST(SSLTest, ErrorSyscallAfterCloseNotify) {
|
||||
EXPECT_EQ(ret, 0);
|
||||
EXPECT_EQ(SSL_get_error(client.get(), ret), SSL_ERROR_ZERO_RETURN);
|
||||
|
||||
@@ -63,7 +63,7 @@ index 3709a4694f3c9be67fd918f125f023b5aa660971..3507f4ef5bd4444c2499b06a5e312ab5
|
||||
// Although the client has seen close_notify, it should continue to report
|
||||
// |SSL_ERROR_SYSCALL| when its writes fail.
|
||||
ret = SSL_write(client.get(), data, sizeof(data));
|
||||
@@ -8370,22 +8365,6 @@ TEST(SSLTest, ErrorSyscallAfterCloseNotify) {
|
||||
@@ -8372,22 +8367,6 @@ TEST(SSLTest, ErrorSyscallAfterCloseNotify) {
|
||||
EXPECT_EQ(SSL_get_error(client.get(), ret), SSL_ERROR_SYSCALL);
|
||||
EXPECT_TRUE(write_failed);
|
||||
write_failed = false;
|
||||
|
||||
@@ -122,3 +122,40 @@ fix_remove_caption-removing_style_call.patch
|
||||
build_allow_electron_to_use_exec_script.patch
|
||||
cherry-pick-7196a42b42ce.patch
|
||||
fix_tray_icon_gone_on_lock_screen.patch
|
||||
cherry-pick-2611772cf0a0.patch
|
||||
cherry-pick-3235c1d1955b.patch
|
||||
expose_v8initializer_codegenerationcheckcallbackinmainthread.patch
|
||||
cherry-pick-43637378b14e.patch
|
||||
axselectedtextmarkerrange_should_not_be_backwards.patch
|
||||
fix_x11_window_restore_minimized_maximized_window.patch
|
||||
m108-lts_simplify_webmediaplayermscompositor_destruction.patch
|
||||
m108-lts_further_simplify_webmediaplayermscompositor_lifetime.patch
|
||||
cherry-pick-e79b89b47dac.patch
|
||||
cherry-pick-06851790480e.patch
|
||||
cherry-pick-aeec1ba5893d.patch
|
||||
cherry-pick-0407102d19b9.patch
|
||||
fix_crash_in_annotationagentimpl.patch
|
||||
cherry-pick-bfd926be8178.patch
|
||||
cherry-pick-9aa4c45f21b1.patch
|
||||
m108-lts_do_not_register_browser_watcher_activity_report_with.patch
|
||||
prevent_potential_integer_overflow_in_persistentmemoryallocator_1_2.patch
|
||||
m108-lts_prevent_potential_integer_overflow_in.patch
|
||||
cherry-pick-38de42d2bbc3.patch
|
||||
cherry-pick-8731bd8a30f6.patch
|
||||
cherry-pick-26bfa5807606.patch
|
||||
cherry-pick-b5c9e5efe5dd.patch
|
||||
cherry-pick-56bd20b295b4.patch
|
||||
cherry-pick-1235110fce18.patch
|
||||
cherry-pick-b041159d06ad.patch
|
||||
cherry-pick-d6946b70b431.patch
|
||||
cherry-pick-d9081493c4b2.patch
|
||||
cherry-pick-2b30a50d0e62.patch
|
||||
merge_m112_remove_the_second_weakptrfactory_from.patch
|
||||
merge_m112_check_spdyproxyclientsocket_is_alive_after_write.patch
|
||||
check_callback_availability_in.patch
|
||||
cherry-pick-63686953dc22.patch
|
||||
cherry-pick-f098ff0d1230.patch
|
||||
cherry-pick-f58218891f8c.patch
|
||||
wayland_ensure_dnd_buffer_size_is_a_multiple_of_scale.patch
|
||||
m112_cherry_pick_libxml_cve_fix.patch
|
||||
m112_fix_scopedobservation_uaf_in.patch
|
||||
|
||||
@@ -0,0 +1,57 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Valerie Young <spectranaut@igalia.com>
|
||||
Date: Mon, 14 Nov 2022 19:53:31 +0000
|
||||
Subject: AXSelectedTextMarkerRange should not be backwards
|
||||
|
||||
AXSelectedTextMarkerRange was changed to backwards in this commit:
|
||||
https://chromium-review.googlesource.com/c/chromium/src/+/2330812
|
||||
In response to this bug:
|
||||
https://bugs.chromium.org/p/chromium/issues/detail?id=1110480
|
||||
After switching the range back to forward, the bug above is not
|
||||
repeatable.
|
||||
|
||||
Fixed: 1172956
|
||||
Change-Id: I8f32e807e91514e3d74393b1ec54960ffdfacdcb
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3994770
|
||||
Reviewed-by: Aaron Leventhal <aleventhal@chromium.org>
|
||||
Commit-Queue: Valerie Young <spectranaut@igalia.com>
|
||||
Cr-Commit-Position: refs/heads/main@{#1071150}
|
||||
|
||||
diff --git a/content/browser/accessibility/ax_tree_formatter_mac_browsertest.mm b/content/browser/accessibility/ax_tree_formatter_mac_browsertest.mm
|
||||
index 46426469b3728f470c102812c454fd838b3f006f..250180222304766ca2b25d1dcd5df248f3087833 100644
|
||||
--- a/content/browser/accessibility/ax_tree_formatter_mac_browsertest.mm
|
||||
+++ b/content/browser/accessibility/ax_tree_formatter_mac_browsertest.mm
|
||||
@@ -206,7 +206,7 @@ AccessibilityNotificationWaiter waiter(shell()->web_contents(),
|
||||
</script>)~~",
|
||||
{":3;AXSelectedTextMarkerRange=*"}, R"~~(AXWebArea
|
||||
++AXGroup
|
||||
-++++AXStaticText AXSelectedTextMarkerRange={anchor: {:2, -1, down}, focus: {:3, 0, down}}
|
||||
+++++AXStaticText AXSelectedTextMarkerRange={anchor: {:3, 0, down}, focus: {:2, -1, down}}
|
||||
)~~");
|
||||
}
|
||||
|
||||
diff --git a/content/browser/accessibility/browser_accessibility_cocoa.mm b/content/browser/accessibility/browser_accessibility_cocoa.mm
|
||||
index 55cce7ff53b355cea2787abca6140f122f6a0369..202923773d7adb2fad5c15be4558bfd548ec6c7d 100644
|
||||
--- a/content/browser/accessibility/browser_accessibility_cocoa.mm
|
||||
+++ b/content/browser/accessibility/browser_accessibility_cocoa.mm
|
||||
@@ -1347,9 +1347,7 @@ - (id)selectedTextMarkerRange {
|
||||
if (ax_range.IsNull())
|
||||
return nil;
|
||||
|
||||
- // Voiceover expects this range to be backwards in order to read the selected
|
||||
- // words correctly.
|
||||
- return AXRangeToAXTextMarkerRange(ax_range.AsBackwardRange());
|
||||
+ return AXRangeToAXTextMarkerRange(std::move(ax_range));
|
||||
}
|
||||
|
||||
- (NSString*)sortDirection {
|
||||
diff --git a/content/test/data/accessibility/mac/selection/selectall-textarea-expected.txt b/content/test/data/accessibility/mac/selection/selectall-textarea-expected.txt
|
||||
index f2638c5d03b16266e781bb74cfc08c65f7c0a60d..34036471ad01d0fcfc7bd9b7213f1b4edcded719 100644
|
||||
--- a/content/test/data/accessibility/mac/selection/selectall-textarea-expected.txt
|
||||
+++ b/content/test/data/accessibility/mac/selection/selectall-textarea-expected.txt
|
||||
@@ -1,4 +1,4 @@
|
||||
textarea_range={anchor: {:3, 0, down}, focus: {:3, 19, down}}
|
||||
textarea.AXSelectedTextMarkerRange={anchor: {:3, 0, down}, focus: {:3, 19, down}}
|
||||
AXSelectedTextChanged on AXTextArea AXValue='The quick brown fox' AXTextSelectionDirection=AXTextSelectionDirectionUnknown AXTextSelectionGranularity=AXTextSelectionGranularityUnknown AXTextStateChangeType=AXTextStateChangeTypeSelectionMove
|
||||
-textarea.AXSelectedTextMarkerRange={anchor: {:3, 19, down}, focus: {:3, 0, down}}
|
||||
+textarea.AXSelectedTextMarkerRange={anchor: {:3, 0, down}, focus: {:3, 19, down}}
|
||||
@@ -9,7 +9,7 @@ potentially prevent a window from being created.
|
||||
TODO(loc): this patch is currently broken.
|
||||
|
||||
diff --git a/content/browser/renderer_host/render_frame_host_impl.cc b/content/browser/renderer_host/render_frame_host_impl.cc
|
||||
index e4e16ccdcd2070e56d9572b7d4bc22d685cb34bc..7484975281bf5c19b1640c56ea6ad5f8a1add54a 100644
|
||||
index 81ee9846e14c148be31170f0439b59b046c77244..a93ba154cd435c4a00f625c7cb887116df5b7c64 100644
|
||||
--- a/content/browser/renderer_host/render_frame_host_impl.cc
|
||||
+++ b/content/browser/renderer_host/render_frame_host_impl.cc
|
||||
@@ -7443,6 +7443,7 @@ void RenderFrameHostImpl::CreateNewWindow(
|
||||
|
||||
36
patches/chromium/check_callback_availability_in.patch
Normal file
36
patches/chromium/check_callback_availability_in.patch
Normal file
@@ -0,0 +1,36 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Kenichi Ishibashi <bashi@chromium.org>
|
||||
Date: Tue, 18 Apr 2023 05:58:29 +0000
|
||||
Subject: Check callback availability in
|
||||
SpdyProxyClientSocket::RunWriteCallback
|
||||
|
||||
OnClose() could consume `write_callback_` so it may not be available
|
||||
when RunWriteCallback() is invoked.
|
||||
|
||||
Bug: 1428820
|
||||
Change-Id: I9a5ade62d67f5bf15e12d0915d1ad6098657ffd4
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/4437791
|
||||
Code-Coverage: Findit <findit-for-me@appspot.gserviceaccount.com>
|
||||
Reviewed-by: Adam Rice <ricea@chromium.org>
|
||||
Commit-Queue: Kenichi Ishibashi <bashi@chromium.org>
|
||||
Cr-Commit-Position: refs/heads/main@{#1131689}
|
||||
|
||||
diff --git a/net/spdy/spdy_proxy_client_socket.cc b/net/spdy/spdy_proxy_client_socket.cc
|
||||
index d9b67febc27cc99e5b3383a372451345cec6daaa..bdcf24a1cb65f5df291bd91784d68aa9c05e7b0d 100644
|
||||
--- a/net/spdy/spdy_proxy_client_socket.cc
|
||||
+++ b/net/spdy/spdy_proxy_client_socket.cc
|
||||
@@ -278,10 +278,11 @@ int SpdyProxyClientSocket::GetLocalAddress(IPEndPoint* address) const {
|
||||
}
|
||||
|
||||
void SpdyProxyClientSocket::RunWriteCallback(int result) {
|
||||
- CHECK(write_callback_);
|
||||
-
|
||||
base::WeakPtr<SpdyProxyClientSocket> weak_ptr = weak_factory_.GetWeakPtr();
|
||||
- std::move(write_callback_).Run(result);
|
||||
+ // `write_callback_` might be consumed by OnClose().
|
||||
+ if (write_callback_) {
|
||||
+ std::move(write_callback_).Run(result);
|
||||
+ }
|
||||
if (!weak_ptr) {
|
||||
// `this` was already destroyed while running `write_callback_`. Must
|
||||
// return immediately without touching any field member.
|
||||
91
patches/chromium/cherry-pick-0407102d19b9.patch
Normal file
91
patches/chromium/cherry-pick-0407102d19b9.patch
Normal file
@@ -0,0 +1,91 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: =?UTF-8?q?Peter=20Bostr=C3=B6m?= <pbos@chromium.org>
|
||||
Date: Tue, 14 Mar 2023 16:49:10 +0000
|
||||
Subject: Convert known it != end() DCHECK failures to CHECK
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
|
||||
These have hit on DCHECK builds in the wild and precede erasing or
|
||||
dereferencing an iterator that is UB.
|
||||
|
||||
This CL excludes DCHECK failures that precede non-DCHECK handling of the
|
||||
it != end() failures. Those should probably be rewritten as CHECKs
|
||||
but are less urgent and semi-orthogonal.
|
||||
|
||||
Known crashes (one per file) are:
|
||||
|
||||
crash/dc49e3cadab36d4c
|
||||
crash/0ee3427d25937024
|
||||
crash/b89303e84d123019
|
||||
crash/cc35183b861a4992
|
||||
|
||||
(cherry picked from commit 1aec0b297900a7b59bd24314dff239f3c5697f45)
|
||||
|
||||
Bug: 1418734
|
||||
Change-Id: I81ed7b45be33769e250c65c8bb7334a34be4380e
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/4288168
|
||||
Commit-Queue: Peter Boström <pbos@chromium.org>
|
||||
Cr-Original-Commit-Position: refs/heads/main@{#1109350}
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/4296138
|
||||
Commit-Queue: Roger Felipe Zanoni da Silva <rzanoni@google.com>
|
||||
Reviewed-by: Achuith Bhandarkar <achuith@chromium.org>
|
||||
Owners-Override: Achuith Bhandarkar <achuith@chromium.org>
|
||||
Reviewed-by: Peter Boström <pbos@chromium.org>
|
||||
Cr-Commit-Position: refs/branch-heads/5359@{#1406}
|
||||
Cr-Branched-From: 27d3765d341b09369006d030f83f582a29eb57ae-refs/heads/main@{#1058933}
|
||||
|
||||
diff --git a/base/scoped_multi_source_observation.h b/base/scoped_multi_source_observation.h
|
||||
index 07ea3edd71246f02fe0044b33129f13699ce43b2..cd368c23956078acd6d5694f7f16c106f6461b31 100644
|
||||
--- a/base/scoped_multi_source_observation.h
|
||||
+++ b/base/scoped_multi_source_observation.h
|
||||
@@ -68,7 +68,7 @@ class ScopedMultiSourceObservation {
|
||||
// Remove the object passed to the constructor as an observer from |source|.
|
||||
void RemoveObservation(Source* source) {
|
||||
auto it = base::ranges::find(sources_, source);
|
||||
- DCHECK(it != sources_.end());
|
||||
+ CHECK(it != sources_.end());
|
||||
sources_.erase(it);
|
||||
(source->*RemoveObsFn)(observer_);
|
||||
}
|
||||
diff --git a/cc/tiles/gpu_image_decode_cache.cc b/cc/tiles/gpu_image_decode_cache.cc
|
||||
index 8a49e44647d8c6d35e7fa04dafbd32c06c153927..4ad050db8a3e590742501507d7777ba923ad3832 100644
|
||||
--- a/cc/tiles/gpu_image_decode_cache.cc
|
||||
+++ b/cc/tiles/gpu_image_decode_cache.cc
|
||||
@@ -1379,8 +1379,8 @@ Iterator GpuImageDecodeCache::RemoveFromPersistentCache(Iterator it) {
|
||||
}
|
||||
|
||||
auto entries_it = paint_image_entries_.find(it->second->paint_image_id);
|
||||
- DCHECK(entries_it != paint_image_entries_.end());
|
||||
- DCHECK_GT(entries_it->second.count, 0u);
|
||||
+ CHECK(entries_it != paint_image_entries_.end());
|
||||
+ CHECK_GT(entries_it->second.count, 0u);
|
||||
|
||||
// If this is the last entry for this image, remove its tracking.
|
||||
--entries_it->second.count;
|
||||
diff --git a/third_party/blink/renderer/core/annotation/annotation_agent_impl.cc b/third_party/blink/renderer/core/annotation/annotation_agent_impl.cc
|
||||
index 4f4fbb6c8775e1019a6c2938812f5535737433a3..9e9181677fb676100ff2a20890e902f298b16644 100644
|
||||
--- a/third_party/blink/renderer/core/annotation/annotation_agent_impl.cc
|
||||
+++ b/third_party/blink/renderer/core/annotation/annotation_agent_impl.cc
|
||||
@@ -117,7 +117,7 @@ void AnnotationAgentImpl::ScrollIntoView() const {
|
||||
|
||||
EphemeralRangeInFlatTree range = attached_range_->ToEphemeralRange();
|
||||
|
||||
- DCHECK(range.Nodes().begin() != range.Nodes().end());
|
||||
+ CHECK(range.Nodes().begin() != range.Nodes().end());
|
||||
|
||||
Node& first_node = *range.Nodes().begin();
|
||||
|
||||
diff --git a/ui/base/interaction/element_tracker_mac.mm b/ui/base/interaction/element_tracker_mac.mm
|
||||
index d3b8d98e499a074678d7e06efcc2146d92ae3eb4..b467aa234043ebc8537bb4576ce0eed713593597 100644
|
||||
--- a/ui/base/interaction/element_tracker_mac.mm
|
||||
+++ b/ui/base/interaction/element_tracker_mac.mm
|
||||
@@ -50,7 +50,7 @@ void AddElement(ElementIdentifier identifier,
|
||||
|
||||
void ActivateElement(ElementIdentifier identifier) {
|
||||
const auto it = elements_.find(identifier);
|
||||
- DCHECK(it != elements_.end());
|
||||
+ CHECK(it != elements_.end());
|
||||
ui::ElementTracker::GetFrameworkDelegate()->NotifyElementActivated(
|
||||
it->second.get());
|
||||
}
|
||||
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 2de150bbca0bf9032e207754203e60f2ee1f115f..b552f1d844e44b34eadaca850408754488b9d27b 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 61e7fabfed76c251ee2e3186ab60c56da54be551..824383536eed1560aa50b6892603e3a1aa601c53 100644
|
||||
--- a/components/search_engines/template_url_service.cc
|
||||
+++ b/components/search_engines/template_url_service.cc
|
||||
@@ -2175,7 +2175,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);
|
||||
}
|
||||
}
|
||||
43
patches/chromium/cherry-pick-1235110fce18.patch
Normal file
43
patches/chromium/cherry-pick-1235110fce18.patch
Normal file
@@ -0,0 +1,43 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Geoff Lang <geofflang@chromium.org>
|
||||
Date: Tue, 14 Mar 2023 21:15:46 +0000
|
||||
Subject: Disable glShaderBinary in the passthrough cmd decoder.
|
||||
|
||||
This matches the behaviour of the validating command decoder. The client
|
||||
does not use this function and it's not exposed to WebGL.
|
||||
|
||||
(cherry picked from commit 4a81311a62d853a43e002f45c6867f73c0accdab)
|
||||
|
||||
Bug: 1422594
|
||||
Change-Id: I87c670e4e80b0078fddb9f089b7ac7777a6debfa
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/4324998
|
||||
Reviewed-by: Kenneth Russell <kbr@chromium.org>
|
||||
Commit-Queue: Geoff Lang <geofflang@chromium.org>
|
||||
Cr-Original-Commit-Position: refs/heads/main@{#1115379}
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/4335184
|
||||
Cr-Commit-Position: refs/branch-heads/5481@{#1357}
|
||||
Cr-Branched-From: 130f3e4d850f4bc7387cfb8d08aa993d288a67a9-refs/heads/main@{#1084008}
|
||||
|
||||
diff --git a/gpu/command_buffer/service/gles2_cmd_decoder_passthrough_doers.cc b/gpu/command_buffer/service/gles2_cmd_decoder_passthrough_doers.cc
|
||||
index 9b09ddfe074ebe2786c7bc341b84a5eb5b7b73c9..373dab1c379152c45878faa60a5648bf0bc662e7 100644
|
||||
--- a/gpu/command_buffer/service/gles2_cmd_decoder_passthrough_doers.cc
|
||||
+++ b/gpu/command_buffer/service/gles2_cmd_decoder_passthrough_doers.cc
|
||||
@@ -2666,6 +2666,10 @@ error::Error GLES2DecoderPassthroughImpl::DoShaderBinary(GLsizei n,
|
||||
GLenum binaryformat,
|
||||
const void* binary,
|
||||
GLsizei length) {
|
||||
+#if 1 // No binary shader support.
|
||||
+ InsertError(GL_INVALID_ENUM, "Invalid enum.");
|
||||
+ return error::kNoError;
|
||||
+#else
|
||||
std::vector<GLuint> service_shaders(n, 0);
|
||||
for (GLsizei i = 0; i < n; i++) {
|
||||
service_shaders[i] = GetShaderServiceID(shaders[i], resources_);
|
||||
@@ -2673,6 +2677,7 @@ error::Error GLES2DecoderPassthroughImpl::DoShaderBinary(GLsizei n,
|
||||
api()->glShaderBinaryFn(n, service_shaders.data(), binaryformat, binary,
|
||||
length);
|
||||
return error::kNoError;
|
||||
+#endif
|
||||
}
|
||||
|
||||
error::Error GLES2DecoderPassthroughImpl::DoShaderSource(GLuint shader,
|
||||
44
patches/chromium/cherry-pick-2611772cf0a0.patch
Normal file
44
patches/chromium/cherry-pick-2611772cf0a0.patch
Normal file
@@ -0,0 +1,44 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Johannes Kron <kron@chromium.org>
|
||||
Date: Mon, 28 Nov 2022 10:17:22 +0000
|
||||
Subject: Add feature for window capturing with ScreenCaptureKit
|
||||
|
||||
Makes it possible to launch window capturing with
|
||||
ScreenCaptureKit individually.
|
||||
|
||||
Bug: chromium:1352405
|
||||
Change-Id: Ie58d15007667db887ebf5f6f3092ef323f925461
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/4047186
|
||||
Reviewed-by: Elad Alon <eladalon@chromium.org>
|
||||
Commit-Queue: Johannes Kron <kron@chromium.org>
|
||||
Cr-Commit-Position: refs/heads/main@{#1076120}
|
||||
|
||||
diff --git a/content/browser/renderer_host/media/in_process_video_capture_device_launcher.cc b/content/browser/renderer_host/media/in_process_video_capture_device_launcher.cc
|
||||
index 4e510e5199a62e536542088e79c9b825225664fa..21d8f08c5d7abf414f0ecc7a909a87d9d5ce0513 100644
|
||||
--- a/content/browser/renderer_host/media/in_process_video_capture_device_launcher.cc
|
||||
+++ b/content/browser/renderer_host/media/in_process_video_capture_device_launcher.cc
|
||||
@@ -98,6 +98,13 @@ BASE_FEATURE(kDesktopCaptureMacV2,
|
||||
BASE_FEATURE(kScreenCaptureKitMac,
|
||||
"ScreenCaptureKitMac",
|
||||
base::FEATURE_DISABLED_BY_DEFAULT);
|
||||
+
|
||||
+// If this feature is enabled, ScreenCaptureKit will be used for window
|
||||
+// capturing even if kScreenCaptureKitMac is disabled. Please note that this
|
||||
+// feature has no effect if kScreenCaptureKitMac is enabled.
|
||||
+BASE_FEATURE(kScreenCaptureKitMacWindow,
|
||||
+ "ScreenCaptureKitMacWindow",
|
||||
+ base::FEATURE_DISABLED_BY_DEFAULT);
|
||||
#endif
|
||||
|
||||
void IncrementDesktopCaptureCounters(const DesktopMediaID& device_id) {
|
||||
@@ -491,7 +498,9 @@ void InProcessVideoCaptureDeviceLauncher::DoStartDesktopCaptureOnDeviceThread(
|
||||
// Prefer using ScreenCaptureKit. After that try DesktopCaptureDeviceMac, and
|
||||
// if both fail, use the generic DesktopCaptureDevice.
|
||||
if (!video_capture_device &&
|
||||
- base::FeatureList::IsEnabled(kScreenCaptureKitMac)) {
|
||||
+ (base::FeatureList::IsEnabled(kScreenCaptureKitMac) ||
|
||||
+ (desktop_id.type == DesktopMediaID::TYPE_WINDOW &&
|
||||
+ base::FeatureList::IsEnabled(kScreenCaptureKitMacWindow)))) {
|
||||
if ((video_capture_device = CreateScreenCaptureKitDeviceMac(desktop_id)))
|
||||
implementation = kScreenCaptureKitDeviceMac;
|
||||
}
|
||||
61
patches/chromium/cherry-pick-26bfa5807606.patch
Normal file
61
patches/chromium/cherry-pick-26bfa5807606.patch
Normal file
@@ -0,0 +1,61 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: "Steinar H. Gunderson" <sesse@chromium.org>
|
||||
Date: Tue, 14 Mar 2023 15:53:57 +0000
|
||||
Subject: In Typed CSSOM, reject adding to something that is not a list.
|
||||
|
||||
M108 merge issues:
|
||||
third_party/blink/renderer/core/css/cssom/style_property_map.cc:
|
||||
The check before the added IsValueList check isn't present in 108
|
||||
|
||||
(cherry picked from commit 7301cf1e40fdd97594ea491676b867cf4e577edc)
|
||||
|
||||
Fixed: 1417176
|
||||
Change-Id: Idef1a81af46d334c181979778c28f19ce6369718
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/4293477
|
||||
Commit-Queue: Steinar H Gunderson <sesse@chromium.org>
|
||||
Cr-Original-Commit-Position: refs/heads/main@{#1110281}
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/4306796
|
||||
Commit-Queue: Zakhar Voit <voit@google.com>
|
||||
Reviewed-by: Steinar H Gunderson <sesse@chromium.org>
|
||||
Owners-Override: Achuith Bhandarkar <achuith@chromium.org>
|
||||
Reviewed-by: Achuith Bhandarkar <achuith@chromium.org>
|
||||
Cr-Commit-Position: refs/branch-heads/5359@{#1405}
|
||||
Cr-Branched-From: 27d3765d341b09369006d030f83f582a29eb57ae-refs/heads/main@{#1058933}
|
||||
|
||||
diff --git a/third_party/blink/renderer/core/css/cssom/style_property_map.cc b/third_party/blink/renderer/core/css/cssom/style_property_map.cc
|
||||
index 2c1bcba6022519c3a865ae8e3c2ffcd5bc385cf3..0cde402b49510514599201d2b3104e56ddd7b572 100644
|
||||
--- a/third_party/blink/renderer/core/css/cssom/style_property_map.cc
|
||||
+++ b/third_party/blink/renderer/core/css/cssom/style_property_map.cc
|
||||
@@ -365,6 +365,17 @@ void StylePropertyMap::append(
|
||||
|
||||
CSSValueList* current_value = nullptr;
|
||||
if (const CSSValue* css_value = GetProperty(property_id)) {
|
||||
+ if (!css_value->IsValueList()) {
|
||||
+ // The standard doesn't seem to cover this explicitly
|
||||
+ // (https://github.com/w3c/css-houdini-drafts/issues/823),
|
||||
+ // but the only really reasonable solution seems to be
|
||||
+ // to throw a TypeError.
|
||||
+ //
|
||||
+ // This covers e.g. system-wide CSS keywords, like inherit.
|
||||
+ exception_state.ThrowTypeError(
|
||||
+ "Cannot append to something that is not a list");
|
||||
+ return;
|
||||
+ }
|
||||
current_value = To<CSSValueList>(css_value)->Copy();
|
||||
} else {
|
||||
current_value = CssValueListForPropertyID(property_id);
|
||||
diff --git a/third_party/blink/web_tests/external/wpt/css/css-typed-om/the-stylepropertymap/inline/append.tentative.html b/third_party/blink/web_tests/external/wpt/css/css-typed-om/the-stylepropertymap/inline/append.tentative.html
|
||||
index ee9a9e4ddbcf78a7517d8d038d66844880719e63..f80875622366939f48a7471513fb6319f75be718 100644
|
||||
--- a/third_party/blink/web_tests/external/wpt/css/css-typed-om/the-stylepropertymap/inline/append.tentative.html
|
||||
+++ b/third_party/blink/web_tests/external/wpt/css/css-typed-om/the-stylepropertymap/inline/append.tentative.html
|
||||
@@ -56,4 +56,10 @@ test(t => {
|
||||
assert_style_value_array_equals(result, [CSS.s(5), CSS.s(10), CSS.s(1), CSS.s(2)]);
|
||||
}, 'StylePropertyMap.append is case-insensitive');
|
||||
|
||||
+// https://crbug.com/1417176
|
||||
+test(t => {
|
||||
+ let styleMap = createInlineStyleMap(t, 'transition-duration: inherit');
|
||||
+ assert_throws_js(TypeError, () => styleMap.append('transition-duration', '1s'));
|
||||
+}, 'StylePropertyMap.append rejects appending to CSS-wide keywords');
|
||||
+
|
||||
</script>
|
||||
91
patches/chromium/cherry-pick-2b30a50d0e62.patch
Normal file
91
patches/chromium/cherry-pick-2b30a50d0e62.patch
Normal file
@@ -0,0 +1,91 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Yoshisato Yanagisawa <yyanagisawa@chromium.org>
|
||||
Date: Mon, 10 Apr 2023 05:32:06 +0000
|
||||
Subject: Use ScriptState::Scope instead of setting HandleScope.
|
||||
|
||||
Since `GetEffectiveFunction` may call `Get` if the given v8 listener is
|
||||
an object, we need to prepare `v8::Context::Scope` before calling it.
|
||||
Blink already have a helper class to prepare the environment for the
|
||||
script execution, which has already been used used in other
|
||||
ServiceWorkerGlobalScope member functions. It is `ScriptState::Scope`
|
||||
This CL also use it instead.
|
||||
|
||||
(cherry picked from commit 299385e09d41d5ce3abd434879b5f9b0a8880cd7)
|
||||
|
||||
Bug: 1429197
|
||||
Change-Id: Idbcfdfa9c06160a18b57155a9540f72eed4ec0b8
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/4387655
|
||||
Commit-Queue: Yoshisato Yanagisawa <yyanagisawa@chromium.org>
|
||||
Commit-Queue: Kouhei Ueno <kouhei@chromium.org>
|
||||
Reviewed-by: Leszek Swirski <leszeks@chromium.org>
|
||||
Auto-Submit: Yoshisato Yanagisawa <yyanagisawa@chromium.org>
|
||||
Reviewed-by: Kouhei Ueno <kouhei@chromium.org>
|
||||
Cr-Original-Commit-Position: refs/heads/main@{#1125148}
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/4411454
|
||||
Reviewed-by: Shunya Shishido <sisidovski@chromium.org>
|
||||
Cr-Commit-Position: refs/branch-heads/5615@{#1191}
|
||||
Cr-Branched-From: 9c6408ef696e83a9936b82bbead3d41c93c82ee4-refs/heads/main@{#1109224}
|
||||
|
||||
diff --git a/content/browser/service_worker/service_worker_version_browsertest.cc b/content/browser/service_worker/service_worker_version_browsertest.cc
|
||||
index 5e1aeaa11cc99e9ac4c89be082e0b4254f6df000..0435c5a1850dd3ed16197bbc40c1e276e4613a60 100644
|
||||
--- a/content/browser/service_worker/service_worker_version_browsertest.cc
|
||||
+++ b/content/browser/service_worker/service_worker_version_browsertest.cc
|
||||
@@ -976,6 +976,18 @@ IN_PROC_BROWSER_TEST_F(ServiceWorkerVersionBrowserTest,
|
||||
version_->fetch_handler_type());
|
||||
}
|
||||
|
||||
+IN_PROC_BROWSER_TEST_F(ServiceWorkerVersionBrowserTest,
|
||||
+ NonFunctionFetchHandlerWithHandleEventProperty) {
|
||||
+ StartServerAndNavigateToSetup();
|
||||
+ ASSERT_EQ(
|
||||
+ Install("/service_worker/fetch_event_with_handle_event_property.js"),
|
||||
+ blink::ServiceWorkerStatusCode::kOk);
|
||||
+ EXPECT_EQ(ServiceWorkerVersion::FetchHandlerExistence::EXISTS,
|
||||
+ version_->fetch_handler_existence());
|
||||
+ EXPECT_EQ(ServiceWorkerVersion::FetchHandlerType::kNotSkippable,
|
||||
+ version_->fetch_handler_type());
|
||||
+}
|
||||
+
|
||||
// Check that fetch event handler added in the install event should result in a
|
||||
// service worker that doesn't count as having a fetch event handler.
|
||||
IN_PROC_BROWSER_TEST_F(ServiceWorkerVersionBrowserTest,
|
||||
diff --git a/content/test/data/service_worker/fetch_event_with_handle_event_property.js b/content/test/data/service_worker/fetch_event_with_handle_event_property.js
|
||||
new file mode 100644
|
||||
index 0000000000000000000000000000000000000000..2fe6153af242a10162f7ecb8eaab93c17d840211
|
||||
--- /dev/null
|
||||
+++ b/content/test/data/service_worker/fetch_event_with_handle_event_property.js
|
||||
@@ -0,0 +1,11 @@
|
||||
+// Copyright 2023 The Chromium Authors
|
||||
+// Use of this source code is governed by a BSD-style license that can be
|
||||
+// found in the LICENSE file.
|
||||
+
|
||||
+let obj = {};
|
||||
+Object.defineProperty(obj, "handleEvent", {
|
||||
+ get: () => {},
|
||||
+ configurable: true,
|
||||
+ enumerable: true,
|
||||
+});
|
||||
+self.addEventListener('fetch', obj);
|
||||
diff --git a/third_party/blink/renderer/modules/service_worker/service_worker_global_scope.cc b/third_party/blink/renderer/modules/service_worker/service_worker_global_scope.cc
|
||||
index c66d232a65535bf1c66d47c6d51bc56418e57f26..b3a9f691a0fabf14bf6f319173f400c31c664c12 100644
|
||||
--- a/third_party/blink/renderer/modules/service_worker/service_worker_global_scope.cc
|
||||
+++ b/third_party/blink/renderer/modules/service_worker/service_worker_global_scope.cc
|
||||
@@ -2602,12 +2602,15 @@ ServiceWorkerGlobalScope::FetchHandlerType() {
|
||||
if (!elv) {
|
||||
return mojom::blink::ServiceWorkerFetchHandlerType::kNoHandler;
|
||||
}
|
||||
- v8::Isolate* isolate = v8::Isolate::GetCurrent();
|
||||
- v8::HandleScope handle_scope(isolate);
|
||||
+
|
||||
+ ScriptState* script_state = ScriptController()->GetScriptState();
|
||||
+ // Do not remove this, |scope| is needed by `GetEffectiveFunction`.
|
||||
+ ScriptState::Scope scope(script_state);
|
||||
+
|
||||
// TODO(crbug.com/1349613): revisit the way to implement this.
|
||||
// The following code returns kEmptyFetchHandler if all handlers are nop.
|
||||
for (RegisteredEventListener& e : *elv) {
|
||||
- EventTarget* et = EventTarget::Create(ScriptController()->GetScriptState());
|
||||
+ EventTarget* et = EventTarget::Create(script_state);
|
||||
v8::Local<v8::Value> v =
|
||||
To<JSBasedEventListener>(e.Callback())->GetEffectiveFunction(*et);
|
||||
if (!v->IsFunction() ||
|
||||
376
patches/chromium/cherry-pick-3235c1d1955b.patch
Normal file
376
patches/chromium/cherry-pick-3235c1d1955b.patch
Normal file
@@ -0,0 +1,376 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Johannes Kron <kron@chromium.org>
|
||||
Date: Thu, 1 Dec 2022 01:52:27 +0000
|
||||
Subject: Set visible_rect for streams captured with ScreenCaptureKit
|
||||
|
||||
This is needed to make the window capturing code on macOS
|
||||
using the new ScreenCaptureKit API work, because the IOSurface
|
||||
may be larger than the actual content resulting in garbage
|
||||
unless the frame is cropped to |visible_rect|.
|
||||
|
||||
Bug: chromium:1352405
|
||||
Change-Id: I1ce3c13947b9b4f9b75a071800a84a27a7c2ee4a
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/4046582
|
||||
Reviewed-by: Mark Foltz <mfoltz@chromium.org>
|
||||
Commit-Queue: Johannes Kron <kron@chromium.org>
|
||||
Reviewed-by: ccameron chromium <ccameron@chromium.org>
|
||||
Reviewed-by: Ilya Nikolaevskiy <ilnik@chromium.org>
|
||||
Reviewed-by: Will Cassella <cassew@chromium.org>
|
||||
Cr-Commit-Position: refs/heads/main@{#1077752}
|
||||
|
||||
diff --git a/content/browser/media/capture/desktop_capture_device_mac.cc b/content/browser/media/capture/desktop_capture_device_mac.cc
|
||||
index 77eec733bed5cc6ba42ea77994b3a276279b0603..1807356bfad1d37ff09486db2e7cbe31b79ad6a8 100644
|
||||
--- a/content/browser/media/capture/desktop_capture_device_mac.cc
|
||||
+++ b/content/browser/media/capture/desktop_capture_device_mac.cc
|
||||
@@ -127,7 +127,8 @@ class DesktopCaptureDeviceMac : public IOSurfaceCaptureDeviceBase {
|
||||
|
||||
private:
|
||||
void OnFrame(gfx::ScopedInUseIOSurface io_surface) {
|
||||
- OnReceivedIOSurfaceFromStream(io_surface, requested_format_);
|
||||
+ OnReceivedIOSurfaceFromStream(io_surface, requested_format_,
|
||||
+ gfx::Rect(requested_format_.frame_size));
|
||||
}
|
||||
|
||||
const CGDirectDisplayID display_id_;
|
||||
diff --git a/content/browser/media/capture/io_surface_capture_device_base_mac.cc b/content/browser/media/capture/io_surface_capture_device_base_mac.cc
|
||||
index ae076bdd6fb9c1ebc72baa2f78a8568d859564ce..0bf2c58b6840c15d827a7b4a5888d1f56ff50943 100644
|
||||
--- a/content/browser/media/capture/io_surface_capture_device_base_mac.cc
|
||||
+++ b/content/browser/media/capture/io_surface_capture_device_base_mac.cc
|
||||
@@ -39,10 +39,12 @@ void IOSurfaceCaptureDeviceBase::RequestRefreshFrame() {
|
||||
|
||||
void IOSurfaceCaptureDeviceBase::OnReceivedIOSurfaceFromStream(
|
||||
gfx::ScopedInUseIOSurface io_surface,
|
||||
- const media::VideoCaptureFormat& capture_format) {
|
||||
+ const media::VideoCaptureFormat& capture_format,
|
||||
+ const gfx::Rect& visible_rect) {
|
||||
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
|
||||
last_received_io_surface_ = std::move(io_surface);
|
||||
last_received_capture_format_ = capture_format;
|
||||
+ last_visible_rect_ = visible_rect;
|
||||
|
||||
// Immediately send the new frame to the client.
|
||||
SendLastReceivedIOSurfaceToClient();
|
||||
@@ -66,7 +68,7 @@ void IOSurfaceCaptureDeviceBase::SendLastReceivedIOSurfaceToClient() {
|
||||
media::CapturedExternalVideoBuffer(std::move(handle),
|
||||
last_received_capture_format_,
|
||||
gfx::ColorSpace::CreateREC709()),
|
||||
- {}, now, now - first_frame_time_);
|
||||
+ {}, now, now - first_frame_time_, last_visible_rect_);
|
||||
}
|
||||
|
||||
void IOSurfaceCaptureDeviceBase::ComputeFrameSizeAndDestRect(
|
||||
diff --git a/content/browser/media/capture/io_surface_capture_device_base_mac.h b/content/browser/media/capture/io_surface_capture_device_base_mac.h
|
||||
index 2781f212d77c9361ff2e28d5e13bbaab14ab0750..8ac12480f663a74dfbdcf7128a582a81b4474d25 100644
|
||||
--- a/content/browser/media/capture/io_surface_capture_device_base_mac.h
|
||||
+++ b/content/browser/media/capture/io_surface_capture_device_base_mac.h
|
||||
@@ -10,6 +10,7 @@
|
||||
#include "base/timer/timer.h"
|
||||
#include "content/common/content_export.h"
|
||||
#include "media/capture/video/video_capture_device.h"
|
||||
+#include "ui/gfx/geometry/rect.h"
|
||||
#include "ui/gfx/mac/io_surface.h"
|
||||
|
||||
namespace content {
|
||||
@@ -35,7 +36,8 @@ class CONTENT_EXPORT IOSurfaceCaptureDeviceBase
|
||||
protected:
|
||||
void OnReceivedIOSurfaceFromStream(
|
||||
gfx::ScopedInUseIOSurface io_surface,
|
||||
- const media::VideoCaptureFormat& capture_format);
|
||||
+ const media::VideoCaptureFormat& capture_format,
|
||||
+ const gfx::Rect& visible_rect);
|
||||
void SendLastReceivedIOSurfaceToClient();
|
||||
|
||||
// Given a source frame size `source_size`, and `capture_params_`, compute the
|
||||
@@ -71,6 +73,7 @@ class CONTENT_EXPORT IOSurfaceCaptureDeviceBase
|
||||
// frames come in, then this will be repeatedly sent at `min_frame_rate_`.
|
||||
gfx::ScopedInUseIOSurface last_received_io_surface_;
|
||||
media::VideoCaptureFormat last_received_capture_format_;
|
||||
+ gfx::Rect last_visible_rect_;
|
||||
|
||||
base::WeakPtrFactory<IOSurfaceCaptureDeviceBase> weak_factory_base_{this};
|
||||
};
|
||||
diff --git a/content/browser/media/capture/screen_capture_kit_device_mac.mm b/content/browser/media/capture/screen_capture_kit_device_mac.mm
|
||||
index 5d640a372f1649e0e2cb7e1828dbb3c66eb1e4d7..cda6a78ca4c87b459252066189394817ea0c0890 100644
|
||||
--- a/content/browser/media/capture/screen_capture_kit_device_mac.mm
|
||||
+++ b/content/browser/media/capture/screen_capture_kit_device_mac.mm
|
||||
@@ -17,7 +17,8 @@
|
||||
#include "ui/gfx/native_widget_types.h"
|
||||
|
||||
using SampleCallback = base::RepeatingCallback<void(gfx::ScopedInUseIOSurface,
|
||||
- absl::optional<gfx::Size>)>;
|
||||
+ absl::optional<gfx::Size>,
|
||||
+ absl::optional<gfx::Rect>)>;
|
||||
using ErrorCallback = base::RepeatingClosure;
|
||||
|
||||
API_AVAILABLE(macos(12.3))
|
||||
@@ -49,9 +50,14 @@ - (void)stream:(SCStream*)stream
|
||||
if (!pixelBuffer)
|
||||
return;
|
||||
|
||||
- // Read out width, height and scaling from metadata to determine the captured
|
||||
- // content size.
|
||||
+ // Read out width, height and scaling from metadata to determine
|
||||
+ // |contentSize|, which is the size of the content on screen, and
|
||||
+ // |visibleRect|, which is the region of the IOSurface that contains the
|
||||
+ // captured content. |contentSize| is used to detect when a captured window is
|
||||
+ // resized so that the stream configuration can be updated and |visibleRect|
|
||||
+ // is needed because the IOSurface may be larger than the captured content.
|
||||
absl::optional<gfx::Size> contentSize;
|
||||
+ absl::optional<gfx::Rect> visibleRect;
|
||||
CFArrayRef attachmentsArray =
|
||||
CMSampleBufferGetSampleAttachmentsArray(sampleBuffer, false);
|
||||
if (attachmentsArray && CFArrayGetCount(attachmentsArray) > 0) {
|
||||
@@ -70,6 +76,7 @@ - (void)stream:(SCStream*)stream
|
||||
succeed &= CFNumberGetValue(contentScaleValue, kCFNumberFloatType,
|
||||
&contentScale);
|
||||
if (succeed) {
|
||||
+ visibleRect.emplace(contentRect);
|
||||
contentSize.emplace(round(contentRect.size.width / contentScale),
|
||||
round(contentRect.size.height / contentScale));
|
||||
}
|
||||
@@ -81,7 +88,7 @@ - (void)stream:(SCStream*)stream
|
||||
return;
|
||||
_sampleCallback.Run(
|
||||
gfx::ScopedInUseIOSurface(ioSurface, base::scoped_policy::RETAIN),
|
||||
- contentSize);
|
||||
+ contentSize, visibleRect);
|
||||
}
|
||||
|
||||
- (void)stream:(SCStream*)stream didStopWithError:(NSError*)error {
|
||||
@@ -248,7 +255,8 @@ void OnStreamStopped(bool error) {
|
||||
}
|
||||
}
|
||||
void OnStreamSample(gfx::ScopedInUseIOSurface io_surface,
|
||||
- absl::optional<gfx::Size> content_size) {
|
||||
+ absl::optional<gfx::Size> content_size,
|
||||
+ absl::optional<gfx::Rect> visible_rect) {
|
||||
if (requested_capture_format_) {
|
||||
// Does the size of io_surface match the requested format?
|
||||
size_t io_surface_width = IOSurfaceGetWidth(io_surface);
|
||||
@@ -310,9 +318,11 @@ void OnStreamSample(gfx::ScopedInUseIOSurface io_surface,
|
||||
}
|
||||
}
|
||||
}
|
||||
- // TODO(https://crbug.com/1352405): Set visible rect to make it possible to
|
||||
- // crop the frame when it's rendered/encoded.
|
||||
- OnReceivedIOSurfaceFromStream(io_surface, actual_capture_format_);
|
||||
+ // The IO surface may be larger than the actual content size. Pass on
|
||||
+ // visible rect to be able to render/encode the frame correctly.
|
||||
+ OnReceivedIOSurfaceFromStream(
|
||||
+ io_surface, actual_capture_format_,
|
||||
+ visible_rect.value_or(gfx::Rect(actual_capture_format_.frame_size)));
|
||||
}
|
||||
void OnStreamError() {
|
||||
client()->OnError(media::VideoCaptureError::kScreenCaptureKitStreamError,
|
||||
diff --git a/content/browser/renderer_host/media/video_capture_controller_unittest.cc b/content/browser/renderer_host/media/video_capture_controller_unittest.cc
|
||||
index 048eea2a9edc5e9ea0817d4ae43187e49188f087..44505aabec3d17c87702a946b4e59d371308b83c 100644
|
||||
--- a/content/browser/renderer_host/media/video_capture_controller_unittest.cc
|
||||
+++ b/content/browser/renderer_host/media/video_capture_controller_unittest.cc
|
||||
@@ -701,7 +701,8 @@ TEST_P(VideoCaptureControllerTest, CaptureWithScaledFrames) {
|
||||
|
||||
device_client_->OnIncomingCapturedExternalBuffer(
|
||||
std::move(external_buffer), std::move(scaled_external_buffers),
|
||||
- arbitrary_reference_time_, arbitrary_timestamp_);
|
||||
+ arbitrary_reference_time_, arbitrary_timestamp_,
|
||||
+ gfx::Rect(capture_format.frame_size));
|
||||
}
|
||||
|
||||
#endif
|
||||
diff --git a/media/capture/video/chromeos/mock_video_capture_client.cc b/media/capture/video/chromeos/mock_video_capture_client.cc
|
||||
index 7c295fa4daaeb837a82685aee7d1f8d0512a2b4d..fd38373927c3864806b60e564389d83ada585cb6 100644
|
||||
--- a/media/capture/video/chromeos/mock_video_capture_client.cc
|
||||
+++ b/media/capture/video/chromeos/mock_video_capture_client.cc
|
||||
@@ -71,7 +71,8 @@ void MockVideoCaptureClient::OnIncomingCapturedExternalBuffer(
|
||||
CapturedExternalVideoBuffer buffer,
|
||||
std::vector<CapturedExternalVideoBuffer> scaled_buffers,
|
||||
base::TimeTicks reference_time,
|
||||
- base::TimeDelta timestamp) {
|
||||
+ base::TimeDelta timestamp,
|
||||
+ gfx::Rect visible_rect) {
|
||||
if (frame_cb_)
|
||||
std::move(frame_cb_).Run();
|
||||
}
|
||||
diff --git a/media/capture/video/chromeos/mock_video_capture_client.h b/media/capture/video/chromeos/mock_video_capture_client.h
|
||||
index c4a3fba38054374927b342455d467f9fd555b79d..d4f6fa931b05bd50a4129301e18abf76617e2e93 100644
|
||||
--- a/media/capture/video/chromeos/mock_video_capture_client.h
|
||||
+++ b/media/capture/video/chromeos/mock_video_capture_client.h
|
||||
@@ -58,7 +58,8 @@ class MockVideoCaptureClient : public VideoCaptureDevice::Client {
|
||||
CapturedExternalVideoBuffer buffer,
|
||||
std::vector<CapturedExternalVideoBuffer> scaled_buffers,
|
||||
base::TimeTicks reference_time,
|
||||
- base::TimeDelta timestamp) override;
|
||||
+ base::TimeDelta timestamp,
|
||||
+ gfx::Rect visible_rect) override;
|
||||
// Trampoline methods to workaround GMOCK problems with std::unique_ptr<>.
|
||||
ReserveResult ReserveOutputBuffer(const gfx::Size& dimensions,
|
||||
VideoPixelFormat format,
|
||||
diff --git a/media/capture/video/fuchsia/video_capture_device_fuchsia_test.cc b/media/capture/video/fuchsia/video_capture_device_fuchsia_test.cc
|
||||
index 3039594560a2de51557b32b336ca2673b0decd4c..0518b3c4cf6bcdc90031c0857d653cd5a0accfdb 100644
|
||||
--- a/media/capture/video/fuchsia/video_capture_device_fuchsia_test.cc
|
||||
+++ b/media/capture/video/fuchsia/video_capture_device_fuchsia_test.cc
|
||||
@@ -162,7 +162,8 @@ class TestVideoCaptureClient final : public VideoCaptureDevice::Client {
|
||||
CapturedExternalVideoBuffer buffer,
|
||||
std::vector<CapturedExternalVideoBuffer> scaled_buffers,
|
||||
base::TimeTicks reference_time,
|
||||
- base::TimeDelta timestamp) override {
|
||||
+ base::TimeDelta timestamp,
|
||||
+ gfx::Rect visible_rect) override {
|
||||
NOTREACHED();
|
||||
}
|
||||
void OnIncomingCapturedBuffer(Buffer buffer,
|
||||
diff --git a/media/capture/video/mac/video_capture_device_mac.mm b/media/capture/video/mac/video_capture_device_mac.mm
|
||||
index 3fd0e0794c7fa1708b15fa5bd76502a000bcac91..1b6fa23748024058c0b2ccce6d211bd3978d5f3b 100644
|
||||
--- a/media/capture/video/mac/video_capture_device_mac.mm
|
||||
+++ b/media/capture/video/mac/video_capture_device_mac.mm
|
||||
@@ -827,9 +827,9 @@ ScopedIOUSBInterfaceInterface control_interface(
|
||||
", and expected " + capture_format_.frame_size.ToString());
|
||||
return;
|
||||
}
|
||||
- client_->OnIncomingCapturedExternalBuffer(std::move(frame),
|
||||
- std::move(scaled_frames),
|
||||
- base::TimeTicks::Now(), timestamp);
|
||||
+ client_->OnIncomingCapturedExternalBuffer(
|
||||
+ std::move(frame), std::move(scaled_frames), base::TimeTicks::Now(),
|
||||
+ timestamp, gfx::Rect(capture_format_.frame_size));
|
||||
}
|
||||
|
||||
void VideoCaptureDeviceMac::OnPhotoTaken(const uint8_t* image_data,
|
||||
diff --git a/media/capture/video/mock_video_capture_device_client.h b/media/capture/video/mock_video_capture_device_client.h
|
||||
index 49c2399f6d429e78032792134781f576c61ae15f..c65dcc3fa475090d9ca8e6890d523247c398780f 100644
|
||||
--- a/media/capture/video/mock_video_capture_device_client.h
|
||||
+++ b/media/capture/video/mock_video_capture_device_client.h
|
||||
@@ -35,11 +35,12 @@ class MockVideoCaptureDeviceClient : public VideoCaptureDevice::Client {
|
||||
base::TimeTicks reference_time,
|
||||
base::TimeDelta timestamp,
|
||||
int frame_feedback_id));
|
||||
- MOCK_METHOD4(OnIncomingCapturedExternalBuffer,
|
||||
+ MOCK_METHOD5(OnIncomingCapturedExternalBuffer,
|
||||
void(CapturedExternalVideoBuffer buffer,
|
||||
std::vector<CapturedExternalVideoBuffer> scaled_buffers,
|
||||
base::TimeTicks reference_time,
|
||||
- base::TimeDelta timestamp));
|
||||
+ base::TimeDelta timestamp,
|
||||
+ gfx::Rect visible_size));
|
||||
MOCK_METHOD4(ReserveOutputBuffer,
|
||||
ReserveResult(const gfx::Size&, VideoPixelFormat, int, Buffer*));
|
||||
MOCK_METHOD3(OnError,
|
||||
diff --git a/media/capture/video/video_capture_device.h b/media/capture/video/video_capture_device.h
|
||||
index 76c0a61b372dafbba62c2ec7c84bbd6854f2fa02..5ef13cc639d148023147f0be812c1b09b2cbc815 100644
|
||||
--- a/media/capture/video/video_capture_device.h
|
||||
+++ b/media/capture/video/video_capture_device.h
|
||||
@@ -191,18 +191,21 @@ class CAPTURE_EXPORT VideoCaptureDevice
|
||||
base::TimeDelta timestamp,
|
||||
int frame_feedback_id = 0) = 0;
|
||||
|
||||
- // Captured a new video frame. The data for this frame is in |handle|,
|
||||
- // which is owned by the platform-specific capture device. It is the
|
||||
- // responsibilty of the implementation to prevent the buffer in |handle|
|
||||
- // from being reused by the external capturer. In practice, this is used
|
||||
- // only on macOS, the external capturer maintains a CVPixelBufferPool, and
|
||||
- // gfx::ScopedInUseIOSurface is used to prevent reuse of buffers until all
|
||||
- // consumers have consumed them.
|
||||
+ // Captured a new video frame. The data for this frame is in
|
||||
+ // |buffer.handle|, which is owned by the platform-specific capture device.
|
||||
+ // It is the responsibility of the implementation to prevent the buffer in
|
||||
+ // |buffer.handle| from being reused by the external capturer. In practice,
|
||||
+ // this is used only on macOS, the external capturer maintains a
|
||||
+ // CVPixelBufferPool, and gfx::ScopedInUseIOSurface is used to prevent reuse
|
||||
+ // of buffers until all consumers have consumed them. |visible_rect|
|
||||
+ // specifies the region in the memory pointed to by |buffer.handle| that
|
||||
+ // contains the captured content.
|
||||
virtual void OnIncomingCapturedExternalBuffer(
|
||||
CapturedExternalVideoBuffer buffer,
|
||||
std::vector<CapturedExternalVideoBuffer> scaled_buffers,
|
||||
base::TimeTicks reference_time,
|
||||
- base::TimeDelta timestamp) = 0;
|
||||
+ base::TimeDelta timestamp,
|
||||
+ gfx::Rect visible_rect) = 0;
|
||||
|
||||
// Reserve an output buffer into which contents can be captured directly.
|
||||
// The returned |buffer| will always be allocated with a memory size
|
||||
diff --git a/media/capture/video/video_capture_device_client.cc b/media/capture/video/video_capture_device_client.cc
|
||||
index efa175865f53d5c187cbb65cb4c1b9b40be63614..6229529c8a5878aaec253d5acf1797ae3dcc139f 100644
|
||||
--- a/media/capture/video/video_capture_device_client.cc
|
||||
+++ b/media/capture/video/video_capture_device_client.cc
|
||||
@@ -468,14 +468,21 @@ void VideoCaptureDeviceClient::OnIncomingCapturedExternalBuffer(
|
||||
CapturedExternalVideoBuffer buffer,
|
||||
std::vector<CapturedExternalVideoBuffer> scaled_buffers,
|
||||
base::TimeTicks reference_time,
|
||||
- base::TimeDelta timestamp) {
|
||||
+ base::TimeDelta timestamp,
|
||||
+ gfx::Rect visible_rect) {
|
||||
auto ready_frame = CreateReadyFrameFromExternalBuffer(
|
||||
- std::move(buffer), reference_time, timestamp);
|
||||
+ std::move(buffer), reference_time, timestamp, visible_rect);
|
||||
std::vector<ReadyFrameInBuffer> scaled_ready_frames;
|
||||
scaled_ready_frames.reserve(scaled_buffers.size());
|
||||
for (auto& scaled_buffer : scaled_buffers) {
|
||||
+ // TODO(https://crbug.com/1191986): |visible_rect| is not set correctly for
|
||||
+ // |scaled_buffers|, but scaled buffers is deprecated and not used. It will
|
||||
+ // be removed in another CL.
|
||||
+ gfx::Rect scaled_buffer_visible_rect =
|
||||
+ gfx::Rect{scaled_buffer.format.frame_size};
|
||||
scaled_ready_frames.push_back(CreateReadyFrameFromExternalBuffer(
|
||||
- std::move(scaled_buffer), reference_time, timestamp));
|
||||
+ std::move(scaled_buffer), reference_time, timestamp,
|
||||
+ scaled_buffer_visible_rect));
|
||||
}
|
||||
receiver_->OnFrameReadyInBuffer(std::move(ready_frame),
|
||||
std::move(scaled_ready_frames));
|
||||
@@ -484,7 +491,8 @@ void VideoCaptureDeviceClient::OnIncomingCapturedExternalBuffer(
|
||||
ReadyFrameInBuffer VideoCaptureDeviceClient::CreateReadyFrameFromExternalBuffer(
|
||||
CapturedExternalVideoBuffer buffer,
|
||||
base::TimeTicks reference_time,
|
||||
- base::TimeDelta timestamp) {
|
||||
+ base::TimeDelta timestamp,
|
||||
+ gfx::Rect visible_rect) {
|
||||
// Reserve an ID for this buffer that will not conflict with any of the IDs
|
||||
// used by |buffer_pool_|.
|
||||
int buffer_id_to_drop = VideoCaptureBufferPool::kInvalidId;
|
||||
@@ -517,7 +525,7 @@ ReadyFrameInBuffer VideoCaptureDeviceClient::CreateReadyFrameFromExternalBuffer(
|
||||
info->pixel_format = buffer.format.pixel_format;
|
||||
info->color_space = buffer.color_space;
|
||||
info->coded_size = buffer.format.frame_size;
|
||||
- info->visible_rect = gfx::Rect(buffer.format.frame_size);
|
||||
+ info->visible_rect = visible_rect;
|
||||
info->metadata.frame_rate = buffer.format.frame_rate;
|
||||
info->metadata.reference_time = reference_time;
|
||||
|
||||
diff --git a/media/capture/video/video_capture_device_client.h b/media/capture/video/video_capture_device_client.h
|
||||
index d1c5b3db855d98f10cabcc71a09d40bbb2601296..56d432c99bcd16b221f574d312731f4c87706caf 100644
|
||||
--- a/media/capture/video/video_capture_device_client.h
|
||||
+++ b/media/capture/video/video_capture_device_client.h
|
||||
@@ -87,7 +87,8 @@ class CAPTURE_EXPORT VideoCaptureDeviceClient
|
||||
CapturedExternalVideoBuffer buffer,
|
||||
std::vector<CapturedExternalVideoBuffer> scaled_buffers,
|
||||
base::TimeTicks reference_time,
|
||||
- base::TimeDelta timestamp) override;
|
||||
+ base::TimeDelta timestamp,
|
||||
+ gfx::Rect visible_rect) override;
|
||||
ReserveResult ReserveOutputBuffer(const gfx::Size& dimensions,
|
||||
VideoPixelFormat format,
|
||||
int frame_feedback_id,
|
||||
@@ -116,7 +117,8 @@ class CAPTURE_EXPORT VideoCaptureDeviceClient
|
||||
ReadyFrameInBuffer CreateReadyFrameFromExternalBuffer(
|
||||
CapturedExternalVideoBuffer buffer,
|
||||
base::TimeTicks reference_time,
|
||||
- base::TimeDelta timestamp);
|
||||
+ base::TimeDelta timestamp,
|
||||
+ gfx::Rect visible_rect);
|
||||
|
||||
// A branch of OnIncomingCapturedData for Y16 frame_format.pixel_format.
|
||||
void OnIncomingCapturedY16Data(const uint8_t* data,
|
||||
diff --git a/media/capture/video/win/video_capture_device_mf_win_unittest.cc b/media/capture/video/win/video_capture_device_mf_win_unittest.cc
|
||||
index 1cffb468c33f6185bc656d19760854908e89aa65..293672feabe4172c2946a06ec54b2e67e5533afb 100644
|
||||
--- a/media/capture/video/win/video_capture_device_mf_win_unittest.cc
|
||||
+++ b/media/capture/video/win/video_capture_device_mf_win_unittest.cc
|
||||
@@ -83,7 +83,8 @@ class MockClient : public VideoCaptureDevice::Client {
|
||||
CapturedExternalVideoBuffer buffer,
|
||||
std::vector<CapturedExternalVideoBuffer> scaled_buffers,
|
||||
base::TimeTicks reference_time,
|
||||
- base::TimeDelta timestamp) override {}
|
||||
+ base::TimeDelta timestamp,
|
||||
+ gfx::Rect visible_rect) override {}
|
||||
|
||||
MOCK_METHOD4(ReserveOutputBuffer,
|
||||
ReserveResult(const gfx::Size&, VideoPixelFormat, int, Buffer*));
|
||||
37
patches/chromium/cherry-pick-38de42d2bbc3.patch
Normal file
37
patches/chromium/cherry-pick-38de42d2bbc3.patch
Normal file
@@ -0,0 +1,37 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Will Harris <wfh@chromium.org>
|
||||
Date: Thu, 2 Mar 2023 10:23:28 +0000
|
||||
Subject: Fix potential out of bounds write in base::SampleVectorBase
|
||||
|
||||
BUG=1417185
|
||||
|
||||
(cherry picked from commit 552939b035e724e022fedb90fd80cd008e441fcf)
|
||||
|
||||
Change-Id: I70719d0f9afb81dda373f88ab3a1c177397659ec
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/4265437
|
||||
Commit-Queue: Will Harris <wfh@chromium.org>
|
||||
Cr-Original-Commit-Position: refs/heads/main@{#1106984}
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/4289351
|
||||
Commit-Queue: Zakhar Voit <voit@google.com>
|
||||
Reviewed-by: Victor-Gabriel Savu <vsavu@google.com>
|
||||
Owners-Override: Victor-Gabriel Savu <vsavu@google.com>
|
||||
Cr-Commit-Position: refs/branch-heads/5359@{#1397}
|
||||
Cr-Branched-From: 27d3765d341b09369006d030f83f582a29eb57ae-refs/heads/main@{#1058933}
|
||||
|
||||
diff --git a/base/metrics/sample_vector.cc b/base/metrics/sample_vector.cc
|
||||
index cec7687eeeb3daea85f5bec24765bb5aed5f1c6a..a6995578515a292631dca6044e5ee23c14803e5a 100644
|
||||
--- a/base/metrics/sample_vector.cc
|
||||
+++ b/base/metrics/sample_vector.cc
|
||||
@@ -274,6 +274,12 @@ void SampleVectorBase::MoveSingleSampleToCounts() {
|
||||
if (sample.count == 0)
|
||||
return;
|
||||
|
||||
+ // Stop here if the sample bucket would be out of range for the AtomicCount
|
||||
+ // array.
|
||||
+ if (sample.bucket >= counts_size()) {
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
// Move the value into storage. Sum and redundant-count already account
|
||||
// for this entry so no need to call IncreaseSumAndCount().
|
||||
subtle::NoBarrier_AtomicIncrement(&counts()[sample.bucket], sample.count);
|
||||
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 8dd936e47c8c528ee2ca777788da5df98342dc7c..97063b8165027c1d9a5e09821f2b3056efc283dd 100644
|
||||
--- a/services/network/public/mojom/network_context.mojom
|
||||
+++ b/services/network/public/mojom/network_context.mojom
|
||||
@@ -563,11 +563,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 f620629af5ae78f22f893bc6edf0e6932c771b36..322c72a76f738b0b56674339701010d16a0d4fc5 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 9980dca6e06a02979d217ced4bb3a72ab2b7fce7..8390700f7c38780cdb038073a2645039adc12c99 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 a30a5c588c87c5810036d43e24ec67bdf51cfde4..abcd0c55b70c8de5ad3ad8377512ad42105a219c 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();
|
||||
130
patches/chromium/cherry-pick-56bd20b295b4.patch
Normal file
130
patches/chromium/cherry-pick-56bd20b295b4.patch
Normal file
@@ -0,0 +1,130 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Robert Sesek <rsesek@chromium.org>
|
||||
Date: Mon, 27 Feb 2023 21:25:11 +0000
|
||||
Subject: Update Crashpad to 3e8727238bae3c069bd71cfb3b2bbaa98b55f05b
|
||||
|
||||
3e8727238bae win: Only process up to EXCEPTION_MAXIMUM_PARAMETERS in an
|
||||
EXCEPTION_RECORD
|
||||
|
||||
(cherry picked from commit d05bea76b7ce72d66507ebbe00caf5e45afd587a)
|
||||
|
||||
Fixed: 1412658
|
||||
Change-Id: I7461602d1a18d44ea1a11ac19f1487fbdb92acf6
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/4285061
|
||||
Commit-Queue: Robert Sesek <rsesek@chromium.org>
|
||||
Commit-Queue: Alex Gough <ajgo@chromium.org>
|
||||
Reviewed-by: Alex Gough <ajgo@chromium.org>
|
||||
Auto-Submit: Robert Sesek <rsesek@chromium.org>
|
||||
Cr-Original-Commit-Position: refs/heads/main@{#1108722}
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/4295200
|
||||
Cr-Commit-Position: refs/branch-heads/5481@{#1298}
|
||||
Cr-Branched-From: 130f3e4d850f4bc7387cfb8d08aa993d288a67a9-refs/heads/main@{#1084008}
|
||||
|
||||
diff --git a/third_party/crashpad/README.chromium b/third_party/crashpad/README.chromium
|
||||
index 29ad402c3558b7c75b68339e0f07ad004170fe76..2be0ee4d29e445b5531fc3fddcc3efa28ef968f1 100644
|
||||
--- a/third_party/crashpad/README.chromium
|
||||
+++ b/third_party/crashpad/README.chromium
|
||||
@@ -2,7 +2,7 @@ Name: Crashpad
|
||||
Short Name: crashpad
|
||||
URL: https://crashpad.chromium.org/
|
||||
Version: unknown
|
||||
-Revision: 9f472e5a18d7611adaeb5df727b51102f35e109e
|
||||
+Revision: 9f472e5a18d7611adaeb5df727b51102f35e109e with 3e8727238bae3c069bd71cfb3b2bbaa98b55f05b cherry-picked
|
||||
License: Apache 2.0
|
||||
License File: crashpad/LICENSE
|
||||
Security Critical: yes
|
||||
diff --git a/third_party/crashpad/crashpad/snapshot/win/exception_snapshot_win.cc b/third_party/crashpad/crashpad/snapshot/win/exception_snapshot_win.cc
|
||||
index 2a70c5c0cea234ee1d81262738d7c4e48736b78e..b8931444ac8b11044a6fa7ce2a5ccf34aa4409c8 100644
|
||||
--- a/third_party/crashpad/crashpad/snapshot/win/exception_snapshot_win.cc
|
||||
+++ b/third_party/crashpad/crashpad/snapshot/win/exception_snapshot_win.cc
|
||||
@@ -14,6 +14,8 @@
|
||||
|
||||
#include "snapshot/win/exception_snapshot_win.h"
|
||||
|
||||
+#include <algorithm>
|
||||
+
|
||||
#include "base/logging.h"
|
||||
#include "snapshot/capture_memory.h"
|
||||
#include "snapshot/memory_snapshot.h"
|
||||
@@ -261,8 +263,12 @@ bool ExceptionSnapshotWin::InitializeFromExceptionPointers(
|
||||
exception_code_ = first_record.ExceptionCode;
|
||||
exception_flags_ = first_record.ExceptionFlags;
|
||||
exception_address_ = first_record.ExceptionAddress;
|
||||
- for (DWORD i = 0; i < first_record.NumberParameters; ++i)
|
||||
+
|
||||
+ const DWORD number_parameters = std::min<DWORD>(
|
||||
+ first_record.NumberParameters, EXCEPTION_MAXIMUM_PARAMETERS);
|
||||
+ for (DWORD i = 0; i < number_parameters; ++i) {
|
||||
codes_.push_back(first_record.ExceptionInformation[i]);
|
||||
+ }
|
||||
if (first_record.ExceptionRecord) {
|
||||
// https://crashpad.chromium.org/bug/43
|
||||
LOG(WARNING) << "dropping chained ExceptionRecord";
|
||||
diff --git a/third_party/crashpad/crashpad/snapshot/win/exception_snapshot_win_test.cc b/third_party/crashpad/crashpad/snapshot/win/exception_snapshot_win_test.cc
|
||||
index dcdc3cf4d6f4c1298905e5fba6580e73fca014e0..aa78e5579319341c08a6866fb7ae1272d403d23c 100644
|
||||
--- a/third_party/crashpad/crashpad/snapshot/win/exception_snapshot_win_test.cc
|
||||
+++ b/third_party/crashpad/crashpad/snapshot/win/exception_snapshot_win_test.cc
|
||||
@@ -14,11 +14,14 @@
|
||||
|
||||
#include "snapshot/win/exception_snapshot_win.h"
|
||||
|
||||
+#include <windows.h>
|
||||
+
|
||||
#include <string>
|
||||
|
||||
#include "base/files/file_path.h"
|
||||
#include "base/strings/utf_string_conversions.h"
|
||||
#include "gtest/gtest.h"
|
||||
+#include "snapshot/win/exception_snapshot_win.h"
|
||||
#include "snapshot/win/process_snapshot_win.h"
|
||||
#include "test/errors.h"
|
||||
#include "test/test_paths.h"
|
||||
@@ -315,6 +318,48 @@ TEST(SimulateCrash, ChildDumpWithoutCrashingWOW64) {
|
||||
}
|
||||
#endif // ARCH_CPU_64_BITS
|
||||
|
||||
+TEST(ExceptionSnapshot, TooManyExceptionParameters) {
|
||||
+ ProcessReaderWin process_reader;
|
||||
+ ASSERT_TRUE(process_reader.Initialize(GetCurrentProcess(),
|
||||
+ ProcessSuspensionState::kRunning));
|
||||
+
|
||||
+ // Construct a fake exception record and CPU context.
|
||||
+ auto exception_record = std::make_unique<EXCEPTION_RECORD>();
|
||||
+ exception_record->ExceptionCode = STATUS_FATAL_APP_EXIT;
|
||||
+ exception_record->ExceptionFlags = EXCEPTION_NONCONTINUABLE;
|
||||
+ exception_record->ExceptionAddress = reinterpret_cast<PVOID>(0xFA15E);
|
||||
+ // One more than is permitted in the struct.
|
||||
+ exception_record->NumberParameters = EXCEPTION_MAXIMUM_PARAMETERS + 1;
|
||||
+ for (int i = 0; i < EXCEPTION_MAXIMUM_PARAMETERS; ++i) {
|
||||
+ exception_record->ExceptionInformation[i] = 1000 + i;
|
||||
+ }
|
||||
+
|
||||
+ auto cpu_context = std::make_unique<internal::CPUContextUnion>();
|
||||
+
|
||||
+ auto exception_pointers = std::make_unique<EXCEPTION_POINTERS>();
|
||||
+ exception_pointers->ExceptionRecord =
|
||||
+ reinterpret_cast<PEXCEPTION_RECORD>(exception_record.get());
|
||||
+ exception_pointers->ContextRecord =
|
||||
+ reinterpret_cast<PCONTEXT>(cpu_context.get());
|
||||
+
|
||||
+ internal::ExceptionSnapshotWin snapshot;
|
||||
+ ASSERT_TRUE(snapshot.Initialize(
|
||||
+ &process_reader,
|
||||
+ GetCurrentThreadId(),
|
||||
+ reinterpret_cast<WinVMAddress>(exception_pointers.get()),
|
||||
+ nullptr));
|
||||
+
|
||||
+ EXPECT_EQ(STATUS_FATAL_APP_EXIT, snapshot.Exception());
|
||||
+ EXPECT_EQ(static_cast<uint32_t>(EXCEPTION_NONCONTINUABLE),
|
||||
+ snapshot.ExceptionInfo());
|
||||
+ EXPECT_EQ(0xFA15Eu, snapshot.ExceptionAddress());
|
||||
+ EXPECT_EQ(static_cast<size_t>(EXCEPTION_MAXIMUM_PARAMETERS),
|
||||
+ snapshot.Codes().size());
|
||||
+ for (size_t i = 0; i < EXCEPTION_MAXIMUM_PARAMETERS; ++i) {
|
||||
+ EXPECT_EQ(1000 + i, snapshot.Codes()[i]);
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
} // namespace
|
||||
} // namespace test
|
||||
} // namespace crashpad
|
||||
124
patches/chromium/cherry-pick-63686953dc22.patch
Normal file
124
patches/chromium/cherry-pick-63686953dc22.patch
Normal file
@@ -0,0 +1,124 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Florian Leimgruber <fleimgruber@google.com>
|
||||
Date: Thu, 6 Apr 2023 09:21:41 +0000
|
||||
Subject: Add lock to AlternativeStateNameMap.
|
||||
|
||||
To prevent the class from accessing its localized_state_names_map_ and
|
||||
localized_state_names_reverse_lookup_map_ members, a lock is added. It
|
||||
locks all reads/write from the aforementioned members.
|
||||
|
||||
(cherry picked from commit dd848883aa0d7d88520846bbf6735eaae9f2b60e)
|
||||
|
||||
Bug: 1360571, 1414241, 1425951
|
||||
Change-Id: Ic01b0cba3878748617863274deb04ec9e13645d4
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/4352658
|
||||
Reviewed-by: Christoph Schwering <schwering@google.com>
|
||||
Commit-Queue: Florian Leimgruber <fleimgruber@google.com>
|
||||
Cr-Original-Commit-Position: refs/heads/main@{#1119411}
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/4402262
|
||||
Auto-Submit: Florian Leimgruber <fleimgruber@google.com>
|
||||
Cr-Commit-Position: refs/branch-heads/5615@{#1147}
|
||||
Cr-Branched-From: 9c6408ef696e83a9936b82bbead3d41c93c82ee4-refs/heads/main@{#1109224}
|
||||
|
||||
diff --git a/components/autofill/core/browser/geo/alternative_state_name_map.cc b/components/autofill/core/browser/geo/alternative_state_name_map.cc
|
||||
index d217082a0faf23d2fd74dce8eec1043d83b5e509..ed22752c50f15e1f45e48b9ef561b0cb7134fba8 100644
|
||||
--- a/components/autofill/core/browser/geo/alternative_state_name_map.cc
|
||||
+++ b/components/autofill/core/browser/geo/alternative_state_name_map.cc
|
||||
@@ -53,7 +53,6 @@ AlternativeStateNameMap::GetCanonicalStateName(
|
||||
const CountryCode& country_code,
|
||||
const StateName& state_name,
|
||||
bool is_state_name_normalized) const {
|
||||
- DCHECK_CALLED_ON_VALID_SEQUENCE(alternative_state_name_map_sequence_checker_);
|
||||
// Example:
|
||||
// Entries in |localized_state_names_map_| are:
|
||||
// ("DE", "Bavaria") -> {
|
||||
@@ -73,6 +72,7 @@ AlternativeStateNameMap::GetCanonicalStateName(
|
||||
if (!is_state_name_normalized)
|
||||
normalized_state_name = NormalizeStateName(state_name);
|
||||
|
||||
+ base::AutoLock lock(lock_);
|
||||
auto it = localized_state_names_reverse_lookup_map_.find(
|
||||
{country_code, normalized_state_name});
|
||||
if (it != localized_state_names_reverse_lookup_map_.end())
|
||||
@@ -84,8 +84,6 @@ AlternativeStateNameMap::GetCanonicalStateName(
|
||||
absl::optional<StateEntry> AlternativeStateNameMap::GetEntry(
|
||||
const CountryCode& country_code,
|
||||
const StateName& state_string_from_profile) const {
|
||||
- DCHECK_CALLED_ON_VALID_SEQUENCE(alternative_state_name_map_sequence_checker_);
|
||||
-
|
||||
StateName normalized_state_string_from_profile =
|
||||
NormalizeStateName(state_string_from_profile);
|
||||
absl::optional<CanonicalStateName> canonical_state_name =
|
||||
@@ -93,6 +91,7 @@ absl::optional<StateEntry> AlternativeStateNameMap::GetEntry(
|
||||
/*is_state_name_normalized=*/true);
|
||||
|
||||
if (canonical_state_name) {
|
||||
+ base::AutoLock lock(lock_);
|
||||
auto it = localized_state_names_map_.find(
|
||||
{country_code, canonical_state_name.value()});
|
||||
if (it != localized_state_names_map_.end())
|
||||
@@ -108,8 +107,6 @@ void AlternativeStateNameMap::AddEntry(
|
||||
const StateEntry& state_entry,
|
||||
const std::vector<StateName>& normalized_alternative_state_names,
|
||||
const CanonicalStateName& normalized_canonical_state_name) {
|
||||
- DCHECK_CALLED_ON_VALID_SEQUENCE(alternative_state_name_map_sequence_checker_);
|
||||
-
|
||||
// Example:
|
||||
// AddEntry("DE", "Bavaria", {
|
||||
// "canonical_name": "Bayern",
|
||||
@@ -126,12 +123,15 @@ void AlternativeStateNameMap::AddEntry(
|
||||
// ("DE", "Bayern") -> "Bayern"
|
||||
// ("DE", "BY") -> "Bayern"
|
||||
// ("DE", "Bavaria") -> "Bayern"
|
||||
- if (localized_state_names_map_.size() == kMaxMapSize ||
|
||||
- GetCanonicalStateName(country_code, normalized_state_value_from_profile,
|
||||
+ if (GetCanonicalStateName(country_code, normalized_state_value_from_profile,
|
||||
/*is_state_name_normalized=*/true)) {
|
||||
return;
|
||||
}
|
||||
|
||||
+ base::AutoLock lock(lock_);
|
||||
+ if (localized_state_names_map_.size() == kMaxMapSize) {
|
||||
+ return;
|
||||
+ }
|
||||
localized_state_names_map_[{country_code, normalized_canonical_state_name}] =
|
||||
state_entry;
|
||||
for (const auto& alternative_name : normalized_alternative_state_names) {
|
||||
@@ -141,12 +141,12 @@ void AlternativeStateNameMap::AddEntry(
|
||||
}
|
||||
|
||||
bool AlternativeStateNameMap::IsLocalisedStateNamesMapEmpty() const {
|
||||
- DCHECK_CALLED_ON_VALID_SEQUENCE(alternative_state_name_map_sequence_checker_);
|
||||
+ base::AutoLock lock(lock_);
|
||||
return localized_state_names_map_.empty();
|
||||
}
|
||||
|
||||
void AlternativeStateNameMap::ClearAlternativeStateNameMap() {
|
||||
- DCHECK_CALLED_ON_VALID_SEQUENCE(alternative_state_name_map_sequence_checker_);
|
||||
+ base::AutoLock lock(lock_);
|
||||
localized_state_names_map_.clear();
|
||||
localized_state_names_reverse_lookup_map_.clear();
|
||||
}
|
||||
diff --git a/components/autofill/core/browser/geo/alternative_state_name_map.h b/components/autofill/core/browser/geo/alternative_state_name_map.h
|
||||
index d20cdf8a02fff5d3c3ea91ef3aa67c6522804692..58dd754bfbf39fd24c82e6d46ccb566008a4cd73 100644
|
||||
--- a/components/autofill/core/browser/geo/alternative_state_name_map.h
|
||||
+++ b/components/autofill/core/browser/geo/alternative_state_name_map.h
|
||||
@@ -9,7 +9,7 @@
|
||||
|
||||
#include "base/i18n/case_conversion.h"
|
||||
#include "base/no_destructor.h"
|
||||
-#include "base/sequence_checker.h"
|
||||
+#include "base/synchronization/lock.h"
|
||||
#include "base/types/strong_alias.h"
|
||||
#include "components/autofill/core/browser/proto/states.pb.h"
|
||||
#include "third_party/abseil-cpp/absl/types/optional.h"
|
||||
@@ -177,7 +177,8 @@ class AlternativeStateNameMap {
|
||||
CaseInsensitiveLessComparator>
|
||||
localized_state_names_reverse_lookup_map_;
|
||||
|
||||
- SEQUENCE_CHECKER(alternative_state_name_map_sequence_checker_);
|
||||
+ // TODO(crbug.com/1425951): Remove lock.
|
||||
+ mutable base::Lock lock_;
|
||||
};
|
||||
|
||||
} // namespace autofill
|
||||
595
patches/chromium/cherry-pick-8731bd8a30f6.patch
Normal file
595
patches/chromium/cherry-pick-8731bd8a30f6.patch
Normal file
@@ -0,0 +1,595 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Alex Moshchuk <alexmos@chromium.org>
|
||||
Date: Fri, 3 Mar 2023 22:17:24 +0000
|
||||
Subject: Use optional SafeRef to save RenderFrameHost in NavigationRequest
|
||||
|
||||
This prevents use-after-free if NavigationRequests somehow still
|
||||
points to an already-deleted RFH, which is currently possible (see bug).
|
||||
|
||||
Also converts usages of `render_frame_host_` to use the
|
||||
GetRenderFrameHost() function to ensure that they are all called after
|
||||
the final RenderFrameHost is picked for the navigation.
|
||||
|
||||
(cherry picked from commit 7b75ae34df6d15acf4e5a45f12c9dca4ce7f2586)
|
||||
|
||||
Bug: 1416916
|
||||
Change-Id: I45569e7bb1f160158dc3139fc9e49d7d6bb56738
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/4278923
|
||||
Reviewed-by: Hiroki Nakagawa <nhiroki@chromium.org>
|
||||
Commit-Queue: Rakina Zata Amni <rakina@chromium.org>
|
||||
Reviewed-by: Alex Moshchuk <alexmos@chromium.org>
|
||||
Cr-Original-Commit-Position: refs/heads/main@{#1112656}
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/4308070
|
||||
Reviewed-by: Charlie Reis <creis@chromium.org>
|
||||
Commit-Queue: Alex Moshchuk <alexmos@chromium.org>
|
||||
Cr-Commit-Position: refs/branch-heads/5481@{#1322}
|
||||
Cr-Branched-From: 130f3e4d850f4bc7387cfb8d08aa993d288a67a9-refs/heads/main@{#1084008}
|
||||
|
||||
diff --git a/content/browser/renderer_host/navigation_request.cc b/content/browser/renderer_host/navigation_request.cc
|
||||
index 1496adf92d0e0c7868869263eba5c7786bed6bd8..f6f25544bd36fceb60ada013178cc8fb67e7b10a 100644
|
||||
--- a/content/browser/renderer_host/navigation_request.cc
|
||||
+++ b/content/browser/renderer_host/navigation_request.cc
|
||||
@@ -1450,7 +1450,7 @@ NavigationRequest::CreateForSynchronousRendererCommit(
|
||||
subresource_web_bundle_navigation_info->token(),
|
||||
subresource_web_bundle_navigation_info->render_process_id()));
|
||||
}
|
||||
- navigation_request->render_frame_host_ = render_frame_host;
|
||||
+ navigation_request->render_frame_host_ = render_frame_host->GetSafeRef();
|
||||
navigation_request->coep_reporter_ = std::move(coep_reporter);
|
||||
navigation_request->isolation_info_for_subresources_ =
|
||||
isolation_info_for_subresources;
|
||||
@@ -1964,7 +1964,7 @@ NavigationRequest::GetCommitDeferringConditionForTesting() {
|
||||
void NavigationRequest::BeginNavigation() {
|
||||
EnterChildTraceEvent("BeginNavigation", this);
|
||||
DCHECK(!loader_);
|
||||
- DCHECK(!render_frame_host_);
|
||||
+ DCHECK(!HasRenderFrameHost());
|
||||
ScopedCrashKeys crash_keys(*this);
|
||||
|
||||
if (begin_navigation_callback_for_testing_) {
|
||||
@@ -2342,7 +2342,7 @@ void NavigationRequest::BeginNavigationImpl() {
|
||||
// expect us to use the current RenderFrameHost for this NavigationRequest,
|
||||
// and https://crbug.com/1125106.
|
||||
if (IsSameDocument()) {
|
||||
- render_frame_host_ = frame_tree_node_->current_frame_host();
|
||||
+ render_frame_host_ = frame_tree_node_->current_frame_host()->GetSafeRef();
|
||||
} else {
|
||||
// [spec]: https://html.spec.whatwg.org/C/#process-a-navigate-response
|
||||
// 4. if [...] the result of checking a navigation response's adherence to
|
||||
@@ -2368,11 +2368,12 @@ void NavigationRequest::BeginNavigationImpl() {
|
||||
origin, net::NetworkAnonymizationKey(site, site));
|
||||
|
||||
// Select an appropriate RenderFrameHost.
|
||||
- render_frame_host_ =
|
||||
- frame_tree_node_->render_manager()->GetFrameHostForNavigation(this);
|
||||
+ render_frame_host_ = frame_tree_node_->render_manager()
|
||||
+ ->GetFrameHostForNavigation(this)
|
||||
+ ->GetSafeRef();
|
||||
|
||||
CHECK(Navigator::CheckWebUIRendererDoesNotDisplayNormalURL(
|
||||
- render_frame_host_, GetUrlInfo(),
|
||||
+ &*render_frame_host_.value(), GetUrlInfo(),
|
||||
/*is_renderer_initiated_check=*/false));
|
||||
}
|
||||
|
||||
@@ -2601,8 +2602,8 @@ void NavigationRequest::ResetForCrossDocumentRestart() {
|
||||
|
||||
// Reset the previously selected RenderFrameHost. This is expected to be null
|
||||
// at the beginning of a new navigation. See https://crbug.com/936962.
|
||||
- DCHECK(render_frame_host_);
|
||||
- render_frame_host_ = nullptr;
|
||||
+ DCHECK(HasRenderFrameHost());
|
||||
+ render_frame_host_ = absl::nullopt;
|
||||
|
||||
// Convert the navigation type to the appropriate cross-document one.
|
||||
common_params_->navigation_type =
|
||||
@@ -2660,7 +2661,7 @@ mojom::NavigationClient* NavigationRequest::GetCommitNavigationClient() {
|
||||
|
||||
// Instantiate a new NavigationClient interface.
|
||||
commit_navigation_client_ =
|
||||
- render_frame_host_->GetNavigationClientFromInterfaceProvider();
|
||||
+ GetRenderFrameHost()->GetNavigationClientFromInterfaceProvider();
|
||||
HandleInterfaceDisconnection(
|
||||
&commit_navigation_client_,
|
||||
base::BindOnce(
|
||||
@@ -2731,7 +2732,7 @@ void NavigationRequest::CreateCoepReporter(
|
||||
common_params_->url,
|
||||
policies.cross_origin_embedder_policy.reporting_endpoint,
|
||||
policies.cross_origin_embedder_policy.report_only_reporting_endpoint,
|
||||
- render_frame_host_->GetFrameToken().value(),
|
||||
+ GetRenderFrameHost()->GetFrameToken().value(),
|
||||
isolation_info_for_subresources_.network_anonymization_key());
|
||||
}
|
||||
|
||||
@@ -3133,7 +3134,7 @@ void NavigationRequest::DetermineOriginAgentClusterEndResult() {
|
||||
? url::Origin::Create(common_params_->base_url_for_data_url)
|
||||
: url::Origin::Create(common_params_->url);
|
||||
const IsolationContext& isolation_context =
|
||||
- render_frame_host_->GetSiteInstance()->GetIsolationContext();
|
||||
+ GetRenderFrameHost()->GetSiteInstance()->GetIsolationContext();
|
||||
|
||||
bool is_requested = IsOriginAgentClusterOptInRequested();
|
||||
bool expects_origin_agent_cluster = is_requested || IsIsolationImplied();
|
||||
@@ -3241,7 +3242,7 @@ void NavigationRequest::ProcessOriginAgentClusterEndResult() {
|
||||
origin_agent_cluster_end_result_ ==
|
||||
OriginAgentClusterEndResult::kExplicitlyRequestedButNotOriginKeyed) {
|
||||
GetContentClient()->browser()->LogWebFeatureForCurrentPage(
|
||||
- render_frame_host_,
|
||||
+ GetRenderFrameHost(),
|
||||
blink::mojom::WebFeature::kOriginAgentClusterHeader);
|
||||
}
|
||||
|
||||
@@ -3251,7 +3252,7 @@ void NavigationRequest::ProcessOriginAgentClusterEndResult() {
|
||||
OriginAgentClusterEndResult::kRequestedButNotOriginKeyed ||
|
||||
origin_agent_cluster_end_result_ ==
|
||||
OriginAgentClusterEndResult::kExplicitlyRequestedButNotOriginKeyed) {
|
||||
- render_frame_host_->AddMessageToConsole(
|
||||
+ GetRenderFrameHost()->AddMessageToConsole(
|
||||
blink::mojom::ConsoleMessageLevel::kWarning,
|
||||
base::StringPrintf(
|
||||
"The page requested an origin-keyed agent cluster using the "
|
||||
@@ -3266,7 +3267,7 @@ void NavigationRequest::ProcessOriginAgentClusterEndResult() {
|
||||
OriginAgentClusterEndResult::kNotRequestedButOriginKeyed ||
|
||||
origin_agent_cluster_end_result_ ==
|
||||
OriginAgentClusterEndResult::kExplicitlyNotRequestedButOriginKeyed) {
|
||||
- render_frame_host_->AddMessageToConsole(
|
||||
+ GetRenderFrameHost()->AddMessageToConsole(
|
||||
blink::mojom::ConsoleMessageLevel::kWarning,
|
||||
base::StringPrintf(
|
||||
"The page did not request an origin-keyed agent cluster, but was "
|
||||
@@ -3281,7 +3282,7 @@ void NavigationRequest::PopulateDocumentTokenForCrossDocumentNavigation() {
|
||||
DCHECK(!IsSameDocument());
|
||||
DCHECK_GE(state_, READY_TO_COMMIT);
|
||||
const auto* token_to_reuse =
|
||||
- render_frame_host_->GetDocumentTokenForCrossDocumentNavigationReuse(
|
||||
+ GetRenderFrameHost()->GetDocumentTokenForCrossDocumentNavigationReuse(
|
||||
/* passkey */ {});
|
||||
document_token_.emplace(token_to_reuse ? *token_to_reuse
|
||||
: blink::DocumentToken());
|
||||
@@ -3805,45 +3806,47 @@ void NavigationRequest::OnResponseStarted(
|
||||
BackForwardCacheImpl::Entry* entry =
|
||||
controller->GetBackForwardCache().GetEntry(nav_entry_id_);
|
||||
CHECK(entry);
|
||||
- render_frame_host_ = entry->render_frame_host();
|
||||
- CHECK(render_frame_host_);
|
||||
+ CHECK(entry->render_frame_host());
|
||||
+ render_frame_host_ = entry->render_frame_host()->GetSafeRef();
|
||||
} else if (IsPrerenderedPageActivation()) {
|
||||
// Prerendering requires changing pages starting at the root node.
|
||||
DCHECK(IsInMainFrame());
|
||||
|
||||
- render_frame_host_ =
|
||||
- GetPrerenderHostRegistry().GetRenderFrameHostForReservedHost(
|
||||
- prerender_frame_tree_node_id_.value());
|
||||
- // TODO(https://crbug.com/1181712): Handle the cases when the prerender is
|
||||
- // cancelled and RFH is destroyed while NavigationRequest is alive.
|
||||
+ render_frame_host_ = GetPrerenderHostRegistry()
|
||||
+ .GetRenderFrameHostForReservedHost(
|
||||
+ prerender_frame_tree_node_id_.value())
|
||||
+ ->GetSafeRef();
|
||||
} else if (response_should_be_rendered_) {
|
||||
- render_frame_host_ =
|
||||
- frame_tree_node_->render_manager()->GetFrameHostForNavigation(this);
|
||||
+ render_frame_host_ = frame_tree_node_->render_manager()
|
||||
+ ->GetFrameHostForNavigation(this)
|
||||
+ ->GetSafeRef();
|
||||
|
||||
// Update the associated RenderFrameHost type, which could have changed
|
||||
// due to redirects during navigation.
|
||||
set_associated_rfh_type(
|
||||
- render_frame_host_ ==
|
||||
+ GetRenderFrameHost() ==
|
||||
frame_tree_node_->render_manager()->current_frame_host()
|
||||
? AssociatedRenderFrameHostType::CURRENT
|
||||
: AssociatedRenderFrameHostType::SPECULATIVE);
|
||||
|
||||
if (!Navigator::CheckWebUIRendererDoesNotDisplayNormalURL(
|
||||
- render_frame_host_, GetUrlInfo(),
|
||||
+ GetRenderFrameHost(), GetUrlInfo(),
|
||||
/* is_renderer_initiated_check */ false)) {
|
||||
CHECK(false);
|
||||
}
|
||||
} else {
|
||||
- render_frame_host_ = nullptr;
|
||||
+ render_frame_host_ = absl::nullopt;
|
||||
}
|
||||
- if (!render_frame_host_)
|
||||
+ if (!HasRenderFrameHost()) {
|
||||
DCHECK(!response_should_be_rendered_);
|
||||
+ }
|
||||
|
||||
- if (render_frame_host_)
|
||||
+ if (HasRenderFrameHost()) {
|
||||
DetermineOriginAgentClusterEndResult();
|
||||
+ }
|
||||
|
||||
- if (!commit_params_->is_browser_initiated && render_frame_host_ &&
|
||||
- render_frame_host_->GetProcess() !=
|
||||
+ if (!commit_params_->is_browser_initiated && HasRenderFrameHost() &&
|
||||
+ GetRenderFrameHost()->GetProcess() !=
|
||||
frame_tree_node_->current_frame_host()->GetProcess()) {
|
||||
// Allow the embedder to cancel the cross-process commit if needed.
|
||||
if (!frame_tree_node_->navigator()
|
||||
@@ -3864,12 +3867,12 @@ void NavigationRequest::OnResponseStarted(
|
||||
|
||||
subresource_loader_params_ = std::move(subresource_loader_params);
|
||||
|
||||
- if (render_frame_host_) {
|
||||
+ if (HasRenderFrameHost()) {
|
||||
// Set the site URL now if it hasn't been set already. If the site requires
|
||||
// a dedicated process, this will lock the process to that site, which will
|
||||
// prevent other sites from incorrectly reusing this process. See
|
||||
// https://crbug.com/738634.
|
||||
- SiteInstanceImpl* instance = render_frame_host_->GetSiteInstance();
|
||||
+ SiteInstanceImpl* instance = GetRenderFrameHost()->GetSiteInstance();
|
||||
if (!instance->HasSite() &&
|
||||
SiteInstanceImpl::ShouldAssignSiteForURL(common_params_->url)) {
|
||||
instance->ConvertToDefaultOrSetSite(GetUrlInfo());
|
||||
@@ -3891,7 +3894,7 @@ void NavigationRequest::OnResponseStarted(
|
||||
// navigation, and in the meantime another navigation reads the incorrect
|
||||
// IsUnused() value from the same process when making a process reuse
|
||||
// decision.
|
||||
- render_frame_host_->GetProcess()->SetIsUsed();
|
||||
+ GetRenderFrameHost()->GetProcess()->SetIsUsed();
|
||||
|
||||
// Now that we know the IsolationContext for the assigned SiteInstance, we
|
||||
// opt the origin into OAC here if needed. Note that this doesn't need to
|
||||
@@ -4005,7 +4008,7 @@ void NavigationRequest::OnResponseStarted(
|
||||
return;
|
||||
}
|
||||
|
||||
- if (render_frame_host_ &&
|
||||
+ if (HasRenderFrameHost() &&
|
||||
!CheckPermissionsPoliciesForFencedFrames(GetOriginToCommit())) {
|
||||
OnRequestFailedInternal(
|
||||
network::URLLoaderCompletionStatus(net::ERR_ABORTED),
|
||||
@@ -4035,7 +4038,7 @@ NavigationRequest::CreateNavigationEarlyHintsManagerParams(
|
||||
const network::mojom::EarlyHints& early_hints) {
|
||||
// Early Hints preloads should happen only before the final response is
|
||||
// received, and limited only in the main frame for now.
|
||||
- CHECK(!render_frame_host_);
|
||||
+ CHECK(!HasRenderFrameHost());
|
||||
CHECK(loader_);
|
||||
CHECK_LT(state_, WILL_PROCESS_RESPONSE);
|
||||
CHECK(!IsSameDocument());
|
||||
@@ -4178,12 +4181,12 @@ void NavigationRequest::OnRequestFailedInternal(
|
||||
// Sanity check that we haven't changed the RenderFrameHost picked for the
|
||||
// error page in OnRequestFailedInternal when running the WillFailRequest
|
||||
// checks.
|
||||
- CHECK(!render_frame_host_ || render_frame_host_ == render_frame_host);
|
||||
- render_frame_host_ = render_frame_host;
|
||||
+ CHECK(!HasRenderFrameHost() || GetRenderFrameHost() == render_frame_host);
|
||||
+ render_frame_host_ = render_frame_host->GetSafeRef();
|
||||
|
||||
// Update the associated RenderFrameHost type.
|
||||
set_associated_rfh_type(
|
||||
- render_frame_host_ ==
|
||||
+ GetRenderFrameHost() ==
|
||||
frame_tree_node_->render_manager()->current_frame_host()
|
||||
? AssociatedRenderFrameHostType::CURRENT
|
||||
: AssociatedRenderFrameHostType::SPECULATIVE);
|
||||
@@ -4191,17 +4194,17 @@ void NavigationRequest::OnRequestFailedInternal(
|
||||
// Set the site URL now if it hasn't been set already. It's possible to get
|
||||
// here if we navigate to an error out of an initial "blank" SiteInstance.
|
||||
// Also mark the process as used, since it will be hosting an error page.
|
||||
- SiteInstanceImpl* instance = render_frame_host_->GetSiteInstance();
|
||||
+ SiteInstanceImpl* instance = GetRenderFrameHost()->GetSiteInstance();
|
||||
if (!instance->HasSite())
|
||||
instance->ConvertToDefaultOrSetSite(GetUrlInfo());
|
||||
- render_frame_host_->GetProcess()->SetIsUsed();
|
||||
+ GetRenderFrameHost()->GetProcess()->SetIsUsed();
|
||||
|
||||
// The check for WebUI should be performed only if error page isolation is
|
||||
// enabled for this failed navigation. It is possible for subframe error page
|
||||
// to be committed in a WebUI process as shown in https://crbug.com/944086.
|
||||
if (frame_tree_node_->IsErrorPageIsolationEnabled()) {
|
||||
if (!Navigator::CheckWebUIRendererDoesNotDisplayNormalURL(
|
||||
- render_frame_host_, GetUrlInfo(),
|
||||
+ GetRenderFrameHost(), GetUrlInfo(),
|
||||
/* is_renderer_initiated_check */ false)) {
|
||||
CHECK(false);
|
||||
}
|
||||
@@ -4520,7 +4523,7 @@ void NavigationRequest::OnStartChecksComplete(
|
||||
->CreateURLLoaderNetworkObserverForNavigationRequest(*this),
|
||||
NetworkServiceDevToolsObserver::MakeSelfOwned(frame_tree_node_),
|
||||
std::move(cached_response_head), std::move(interceptor));
|
||||
- DCHECK(!render_frame_host_);
|
||||
+ DCHECK(!HasRenderFrameHost());
|
||||
|
||||
base::UmaHistogramTimes(
|
||||
base::StrCat({"Navigation.WillStartRequestToLoaderStart.",
|
||||
@@ -4792,7 +4795,10 @@ void NavigationRequest::OnWillProcessResponseChecksComplete(
|
||||
!response_should_be_rendered_) {
|
||||
// Reset the RenderFrameHost that had been computed for the commit of the
|
||||
// navigation.
|
||||
- render_frame_host_ = nullptr;
|
||||
+ // TODO(https://crbug.com/1416916): Reconsider if we really need to unset
|
||||
+ // the `render_frame_host_` here, as the NavigationRequest might stay alive
|
||||
+ // for a bit longer to commit an error page.
|
||||
+ render_frame_host_ = absl::nullopt;
|
||||
|
||||
// TODO(clamy): distinguish between CANCEL and CANCEL_AND_IGNORE.
|
||||
if (!response_should_be_rendered_) {
|
||||
@@ -4821,7 +4827,10 @@ void NavigationRequest::OnWillProcessResponseChecksComplete(
|
||||
DCHECK_EQ(net::ERR_BLOCKED_BY_RESPONSE, result.net_error_code());
|
||||
// Reset the RenderFrameHost that had been computed for the commit of the
|
||||
// navigation.
|
||||
- render_frame_host_ = nullptr;
|
||||
+ // TODO(https://crbug.com/1416916): Reconsider if we really need to unset
|
||||
+ // the `render_frame_host_` here, as the NavigationRequest might stay alive
|
||||
+ // for a bit longer to commit an error page.
|
||||
+ render_frame_host_ = absl::nullopt;
|
||||
OnRequestFailedInternal(
|
||||
network::URLLoaderCompletionStatus(result.net_error_code()),
|
||||
true /* skip_throttles */, result.error_page_content(),
|
||||
@@ -4894,7 +4903,7 @@ void NavigationRequest::CommitErrorPage(
|
||||
commit_params_->origin_to_commit =
|
||||
url::Origin::Create(common_params_->url).DeriveNewOpaqueOrigin();
|
||||
if (request_navigation_client_.is_bound()) {
|
||||
- if (render_frame_host_ == frame_tree_node()->current_frame_host()) {
|
||||
+ if (GetRenderFrameHost() == frame_tree_node()->current_frame_host()) {
|
||||
// Reuse the request NavigationClient for commit.
|
||||
commit_navigation_client_ = std::move(request_navigation_client_);
|
||||
} else {
|
||||
@@ -4909,7 +4918,7 @@ void NavigationRequest::CommitErrorPage(
|
||||
PopulateDocumentTokenForCrossDocumentNavigation();
|
||||
// Use a separate cache shard, and no cookies, for error pages.
|
||||
isolation_info_for_subresources_ = net::IsolationInfo::CreateTransient();
|
||||
- render_frame_host_->FailedNavigation(
|
||||
+ GetRenderFrameHost()->FailedNavigation(
|
||||
this, *common_params_, *commit_params_, has_stale_copy_in_cache_,
|
||||
net_error_, extended_error_code_, error_page_content, *document_token_);
|
||||
|
||||
@@ -4976,7 +4985,7 @@ void NavigationRequest::CommitNavigation() {
|
||||
// TODO(crbug.com/979296): Consider changing this code to copy an origin
|
||||
// instead of creating one from a URL which lacks opacity information.
|
||||
isolation_info_for_subresources_ =
|
||||
- render_frame_host_->ComputeIsolationInfoForSubresourcesForPendingCommit(
|
||||
+ GetRenderFrameHost()->ComputeIsolationInfoForSubresourcesForPendingCommit(
|
||||
origin, is_anonymous(), ComputeFencedFrameNonce());
|
||||
DCHECK(!isolation_info_for_subresources_.IsEmpty());
|
||||
|
||||
@@ -4984,9 +4993,9 @@ void NavigationRequest::CommitNavigation() {
|
||||
// moment. We will be able to use it once the browser can compute the origin
|
||||
// to commit.
|
||||
absl::optional<base::UnguessableToken> nonce =
|
||||
- render_frame_host_->ComputeNonce(is_anonymous(),
|
||||
+ GetRenderFrameHost()->ComputeNonce(is_anonymous(),
|
||||
ComputeFencedFrameNonce());
|
||||
- commit_params_->storage_key = render_frame_host_->CalculateStorageKey(
|
||||
+ commit_params_->storage_key = GetRenderFrameHost()->CalculateStorageKey(
|
||||
GetOriginToCommit(), base::OptionalToPtr(nonce));
|
||||
|
||||
if (IsServedFromBackForwardCache() || IsPrerenderedPageActivation()) {
|
||||
@@ -5007,13 +5016,13 @@ void NavigationRequest::CommitNavigation() {
|
||||
if (!weak_self)
|
||||
return;
|
||||
|
||||
- DCHECK(render_frame_host_ ==
|
||||
+ DCHECK(GetRenderFrameHost() ==
|
||||
frame_tree_node_->render_manager()->current_frame_host() ||
|
||||
- render_frame_host_ ==
|
||||
+ GetRenderFrameHost() ==
|
||||
frame_tree_node_->render_manager()->speculative_frame_host());
|
||||
|
||||
if (request_navigation_client_.is_bound()) {
|
||||
- if (render_frame_host_ == frame_tree_node()->current_frame_host()) {
|
||||
+ if (GetRenderFrameHost() == frame_tree_node()->current_frame_host()) {
|
||||
// Reuse the request NavigationClient for commit.
|
||||
commit_navigation_client_ = std::move(request_navigation_client_);
|
||||
} else {
|
||||
@@ -5023,9 +5032,9 @@ void NavigationRequest::CommitNavigation() {
|
||||
}
|
||||
}
|
||||
|
||||
- CreateCoepReporter(render_frame_host_->GetProcess()->GetStoragePartition());
|
||||
+ CreateCoepReporter(GetRenderFrameHost()->GetProcess()->GetStoragePartition());
|
||||
coop_status_.UpdateReporterStoragePartition(
|
||||
- render_frame_host_->GetProcess()->GetStoragePartition());
|
||||
+ GetRenderFrameHost()->GetProcess()->GetStoragePartition());
|
||||
|
||||
BrowserContext* browser_context =
|
||||
frame_tree_node_->navigator().controller().GetBrowserContext();
|
||||
@@ -5070,7 +5079,7 @@ void NavigationRequest::CommitNavigation() {
|
||||
// Notify the service worker navigation handle that navigation commit is
|
||||
// about to go.
|
||||
service_worker_handle_->OnBeginNavigationCommit(
|
||||
- render_frame_host_->GetGlobalId(),
|
||||
+ GetRenderFrameHost()->GetGlobalId(),
|
||||
policy_container_builder_->FinalPolicies(), std::move(reporter_remote),
|
||||
&service_worker_container_info, commit_params_->document_ukm_source_id);
|
||||
}
|
||||
@@ -5141,7 +5150,7 @@ void NavigationRequest::CommitNavigation() {
|
||||
std::move(subresource_loader_params_->prefetched_signed_exchanges);
|
||||
}
|
||||
|
||||
- render_frame_host_->CommitNavigation(
|
||||
+ GetRenderFrameHost()->CommitNavigation(
|
||||
this, std::move(common_params), std::move(commit_params),
|
||||
std::move(response_head), std::move(response_body_),
|
||||
std::move(url_loader_client_endpoints_),
|
||||
@@ -5154,7 +5163,7 @@ void NavigationRequest::CommitNavigation() {
|
||||
// BrowserContext. This is mostly needed to make sure the spare is warmed-up
|
||||
// if it wasn't done in RenderProcessHostImpl::GetProcessHostForSiteInstance.
|
||||
RenderProcessHostImpl::NotifySpareManagerAboutRecentlyUsedBrowserContext(
|
||||
- render_frame_host_->GetSiteInstance()->GetBrowserContext());
|
||||
+ GetRenderFrameHost()->GetSiteInstance()->GetBrowserContext());
|
||||
|
||||
SendDeferredConsoleMessages();
|
||||
}
|
||||
@@ -5831,14 +5840,14 @@ void NavigationRequest::OnRendererRequestedNavigationCancellation() {
|
||||
// The cancellation happens before READY_TO_COMMIT.
|
||||
frame_tree_node_->navigator().CancelNavigation(
|
||||
frame_tree_node_, NavigationDiscardReason::kCancelled);
|
||||
- } else if (render_frame_host_ ==
|
||||
+ } else if (GetRenderFrameHost() ==
|
||||
frame_tree_node_->render_manager()->current_frame_host() ||
|
||||
- !render_frame_host_->IsRenderFrameLive()) {
|
||||
+ !GetRenderFrameHost()->IsRenderFrameLive()) {
|
||||
// If the NavigationRequest has already reached READY_TO_COMMIT,
|
||||
// `render_frame_host_` owns `this`. Cache any needed state in stack
|
||||
// variables to avoid a use-after-free.
|
||||
FrameTreeNode* frame_tree_node = frame_tree_node_;
|
||||
- render_frame_host_->NavigationRequestCancelled(this);
|
||||
+ GetRenderFrameHost()->NavigationRequestCancelled(this);
|
||||
// Ensure that the speculative RFH, if any, is also cleaned up. In theory,
|
||||
// `ResetNavigationRequest()` should handle this; however, it early-returns
|
||||
// if there is no navigation request associated with the FrameTreeNode.
|
||||
@@ -6267,7 +6276,7 @@ void NavigationRequest::DidCommitNavigation(
|
||||
// Navigations in non-primary frame trees or portals don't appear in history.
|
||||
if ((should_update_history_ && IsSameDocument() && !HasUserGesture() &&
|
||||
params.url == previous_main_frame_url) ||
|
||||
- !render_frame_host_->GetPage().IsPrimary() ||
|
||||
+ !GetRenderFrameHost()->GetPage().IsPrimary() ||
|
||||
frame_tree_node()->frame_tree()->IsPortal()) {
|
||||
should_update_history_ = false;
|
||||
}
|
||||
@@ -6322,7 +6331,7 @@ void NavigationRequest::DidCommitNavigation(
|
||||
ui::PageTransition transition =
|
||||
ui::PageTransitionFromInt(common_params_->transition);
|
||||
absl::optional<bool> is_background =
|
||||
- render_frame_host_->GetProcess()->IsProcessBackgrounded();
|
||||
+ GetRenderFrameHost()->GetProcess()->IsProcessBackgrounded();
|
||||
|
||||
RecordStartToCommitMetrics(
|
||||
common_params_->navigation_start, transition, ready_to_commit_time_,
|
||||
@@ -6483,7 +6492,7 @@ void NavigationRequest::ReadyToCommitNavigation(bool is_error) {
|
||||
// disconnection from the renderer NavigationClient; but browser-initiated
|
||||
// navigations do not, so we must look explicitly. We should not proceed and
|
||||
// claim "ReadyToCommitNavigation" to the delegate if the renderer is gone.
|
||||
- if (!render_frame_host_->IsRenderFrameLive()) {
|
||||
+ if (!GetRenderFrameHost()->IsRenderFrameLive()) {
|
||||
OnRendererRequestedNavigationCancellation();
|
||||
// DO NOT ADD CODE AFTER THIS, as the NavigationHandle has been deleted
|
||||
// by the previous call.
|
||||
@@ -6496,20 +6505,20 @@ void NavigationRequest::ReadyToCommitNavigation(bool is_error) {
|
||||
// where the FrameTreeNode has no NavigationRequest, yet the
|
||||
// RenderFrameHostImpl is not marked as loading yet, causing
|
||||
// FrameTreeNode::IsLoading() to incorrectly return false.
|
||||
- frame_tree_node_->TransferNavigationRequestOwnership(render_frame_host_);
|
||||
+ frame_tree_node_->TransferNavigationRequestOwnership(GetRenderFrameHost());
|
||||
|
||||
// When a speculative RenderFrameHost reaches ReadyToCommitNavigation, the
|
||||
// browser process has asked the renderer to commit the navigation and is
|
||||
// waiting for confirmation of the commit. Update the LifecycleStateImpl to
|
||||
// kPendingCommit as RenderFrameHost isn't considered speculative anymore and
|
||||
// was chosen to commit as this navigation's final RenderFrameHost.
|
||||
- if (render_frame_host_->lifecycle_state() ==
|
||||
+ if (GetRenderFrameHost()->lifecycle_state() ==
|
||||
RenderFrameHostImpl::LifecycleStateImpl::kSpeculative) {
|
||||
// Only cross-RenderFrameHost navigations create speculative
|
||||
// RenderFrameHosts whereas SameDocument, BackForwardCache and
|
||||
// PrerenderedActivation navigations don't.
|
||||
DCHECK(!IsSameDocument() && !IsPageActivation());
|
||||
- render_frame_host_->SetLifecycleState(
|
||||
+ GetRenderFrameHost()->SetLifecycleState(
|
||||
RenderFrameHostImpl::LifecycleStateImpl::kPendingCommit);
|
||||
}
|
||||
|
||||
@@ -6531,11 +6540,11 @@ void NavigationRequest::ReadyToCommitNavigation(bool is_error) {
|
||||
// Record metrics for the time it takes to get to this state from the
|
||||
// beginning of the navigation.
|
||||
if (!IsSameDocument() && !is_error) {
|
||||
- is_same_process_ = render_frame_host_->GetProcess()->GetID() ==
|
||||
+ is_same_process_ = GetRenderFrameHost()->GetProcess()->GetID() ==
|
||||
previous_render_frame_host->GetProcess()->GetID();
|
||||
|
||||
RecordReadyToCommitMetrics(
|
||||
- previous_render_frame_host, render_frame_host_, *common_params_.get(),
|
||||
+ previous_render_frame_host, GetRenderFrameHost(), *common_params_.get(),
|
||||
ready_to_commit_time_, origin_agent_cluster_end_result_,
|
||||
did_receive_early_hints_before_cross_origin_redirect_);
|
||||
}
|
||||
@@ -6544,7 +6553,7 @@ void NavigationRequest::ReadyToCommitNavigation(bool is_error) {
|
||||
same_origin_ = (previous_render_frame_host->GetLastCommittedOrigin() ==
|
||||
GetOriginToCommit());
|
||||
|
||||
- SetExpectedProcess(render_frame_host_->GetProcess());
|
||||
+ SetExpectedProcess(GetRenderFrameHost()->GetProcess());
|
||||
|
||||
commit_params_->is_load_data_with_base_url = IsLoadDataWithBaseURL();
|
||||
|
||||
@@ -6568,7 +6577,7 @@ void NavigationRequest::ReadyToCommitNavigation(bool is_error) {
|
||||
NavigationEntry* entry = GetNavigationEntry();
|
||||
if (entry && entry->IsViewSourceMode()) {
|
||||
// Put the renderer in view source mode.
|
||||
- render_frame_host_->GetAssociatedLocalFrame()->EnableViewSourceMode();
|
||||
+ GetRenderFrameHost()->GetAssociatedLocalFrame()->EnableViewSourceMode();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6892,7 +6901,7 @@ NavigationRequest::MakeDidCommitProvisionalLoadParamsForActivation() {
|
||||
// Use the DidCommitProvisionalLoadParams last used to commit the frame being
|
||||
// restored as a starting point.
|
||||
mojom::DidCommitProvisionalLoadParamsPtr params =
|
||||
- render_frame_host_->TakeLastCommitParams();
|
||||
+ GetRenderFrameHost()->TakeLastCommitParams();
|
||||
|
||||
// Params must have been set when the RFH being restored from the cache last
|
||||
// navigated.
|
||||
@@ -7159,7 +7168,10 @@ RenderFrameHostImpl* NavigationRequest::GetRenderFrameHost() const {
|
||||
}
|
||||
static_assert(WILL_FAIL_REQUEST > WILL_PROCESS_RESPONSE,
|
||||
"WillFailRequest state should come after WillProcessResponse");
|
||||
- return render_frame_host_;
|
||||
+ if (HasRenderFrameHost()) {
|
||||
+ return &*render_frame_host_.value();
|
||||
+ }
|
||||
+ return nullptr;
|
||||
}
|
||||
|
||||
const net::HttpRequestHeaders& NavigationRequest::GetRequestHeaders() {
|
||||
@@ -7619,7 +7631,8 @@ bool NavigationRequest::CoopCoepSanityCheck() {
|
||||
// TODO(https://crbug.com/1278207) add other embedded cases if needed.
|
||||
network::mojom::CrossOriginOpenerPolicyValue coop_value =
|
||||
GetParentFrameOrOuterDocument()
|
||||
- ? render_frame_host_->GetOutermostMainFrame()
|
||||
+ ? GetRenderFrameHost()
|
||||
+ ->GetOutermostMainFrame()
|
||||
->cross_origin_opener_policy()
|
||||
.value
|
||||
: policies.cross_origin_opener_policy.value;
|
||||
@@ -8182,8 +8195,8 @@ void NavigationRequest::SendDeferredConsoleMessages() {
|
||||
for (auto& message : console_messages_) {
|
||||
// TODO(https://crbug.com/721329): We should have a way of sending console
|
||||
// messaged to devtools without going through the renderer.
|
||||
- render_frame_host_->AddMessageToConsole(message.level,
|
||||
- std::move(message.message));
|
||||
+ GetRenderFrameHost()->AddMessageToConsole(message.level,
|
||||
+ std::move(message.message));
|
||||
}
|
||||
console_messages_.clear();
|
||||
}
|
||||
diff --git a/content/browser/renderer_host/navigation_request.h b/content/browser/renderer_host/navigation_request.h
|
||||
index 8d6debbd09392d954d05c06c5e0b2d7a7be29bd3..6c715d5e85f2dc90dc17f9a237c69ede69c533e6 100644
|
||||
--- a/content/browser/renderer_host/navigation_request.h
|
||||
+++ b/content/browser/renderer_host/navigation_request.h
|
||||
@@ -459,6 +459,8 @@ class CONTENT_EXPORT NavigationRequest
|
||||
associated_rfh_type_ = type;
|
||||
}
|
||||
|
||||
+ bool HasRenderFrameHost() const { return render_frame_host_.has_value(); }
|
||||
+
|
||||
void set_was_discarded() { commit_params_->was_discarded = true; }
|
||||
|
||||
void set_net_error(net::Error net_error) { net_error_ = net_error; }
|
||||
@@ -1632,8 +1634,17 @@ class CONTENT_EXPORT NavigationRequest
|
||||
// - the synchronous about:blank navigation.
|
||||
const bool is_synchronous_renderer_commit_;
|
||||
|
||||
- // Invariant: At least one of |loader_| or |render_frame_host_| is null.
|
||||
- raw_ptr<RenderFrameHostImpl> render_frame_host_ = nullptr;
|
||||
+ // The RenderFrameHost that this navigation intends to commit in. The value
|
||||
+ // will be set when we know the final RenderFrameHost that the navigation will
|
||||
+ // commit in (i.e. when we receive the final network response for most
|
||||
+ // navigations). Note that currently this can be reset to absl::nullopt for
|
||||
+ // cross-document restarts and some failed navigations.
|
||||
+ // TODO(https://crbug.com/1416916): Don't reset this on failed navigations,
|
||||
+ // and ensure the NavigationRequest doesn't outlive the `render_frame_host_`
|
||||
+ // picked for failed Back/Forward Cache restores.
|
||||
+ // Invariant: At least one of |loader_| or |render_frame_host_| is
|
||||
+ // null/absl::nullopt.
|
||||
+ absl::optional<base::SafeRef<RenderFrameHostImpl>> render_frame_host_;
|
||||
|
||||
// Initialized on creation of the NavigationRequest. Sent to the renderer when
|
||||
// the navigation is ready to commit.
|
||||
88
patches/chromium/cherry-pick-9aa4c45f21b1.patch
Normal file
88
patches/chromium/cherry-pick-9aa4c45f21b1.patch
Normal file
@@ -0,0 +1,88 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: =?UTF-8?q?Henrik=20Bostr=C3=B6m?= <hbos@chromium.org>
|
||||
Date: Tue, 14 Mar 2023 13:07:19 +0000
|
||||
Subject: Shutdown RtpContributingSourceCache in Dispose().
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
|
||||
The cache is an off-heap object, but it is owned by an on-heap object
|
||||
(RTCPeerConnection). Dispoing the owning object poisons memory owned by
|
||||
it, but the cache may have in-flight tasks (cache doing ClearCache in a
|
||||
delayed microtask). This CL adds a Shutdown() method to ensure the
|
||||
cache isn't doing anything in the next microtask after disposal.
|
||||
|
||||
No reliable way to repro this has been found but the change should be
|
||||
safe so hoping we can land without tests.
|
||||
|
||||
(cherry picked from commit 4d450ecd6ec7776c7505dcf7d2f04157ff3ba0eb)
|
||||
|
||||
Bug: 1413628
|
||||
Change-Id: I479aace9859f4c10cd75d4aa5a34808b4726299d
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/4247023
|
||||
Commit-Queue: Henrik Boström <hbos@chromium.org>
|
||||
Cr-Original-Commit-Position: refs/heads/main@{#1105653}
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/4291513
|
||||
Reviewed-by: Achuith Bhandarkar <achuith@chromium.org>
|
||||
Owners-Override: Achuith Bhandarkar <achuith@chromium.org>
|
||||
Reviewed-by: Henrik Boström <hbos@chromium.org>
|
||||
Commit-Queue: Zakhar Voit <voit@google.com>
|
||||
Cr-Commit-Position: refs/branch-heads/5359@{#1404}
|
||||
Cr-Branched-From: 27d3765d341b09369006d030f83f582a29eb57ae-refs/heads/main@{#1058933}
|
||||
|
||||
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 e951bf3faa35a8634ae2c8b90446843d77e509a9..8aeb3497e7b036904a25e807bc2a6ca654cd3752 100644
|
||||
--- a/third_party/blink/renderer/modules/peerconnection/rtc_peer_connection.cc
|
||||
+++ b/third_party/blink/renderer/modules/peerconnection/rtc_peer_connection.cc
|
||||
@@ -643,12 +643,18 @@ RTCPeerConnection::~RTCPeerConnection() {
|
||||
}
|
||||
|
||||
void RTCPeerConnection::Dispose() {
|
||||
- // 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.
|
||||
+ // 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_.reset();
|
||||
}
|
||||
+ // Memory owned by RTCPeerConnection must not be touched after Dispose().
|
||||
+ // Shut down the cache to cancel any in-flight tasks that may otherwise have
|
||||
+ // used the cache.
|
||||
+ if (rtp_contributing_source_cache_.has_value()) {
|
||||
+ rtp_contributing_source_cache_.value().Shutdown();
|
||||
+ }
|
||||
}
|
||||
|
||||
ScriptPromise RTCPeerConnection::createOffer(ScriptState* script_state,
|
||||
diff --git a/third_party/blink/renderer/modules/peerconnection/rtp_contributing_source_cache.cc b/third_party/blink/renderer/modules/peerconnection/rtp_contributing_source_cache.cc
|
||||
index 1f91cf9c128a1bb19fb0a63ea9d869a5c4e6d07d..5ad457fae9bc62a252ca94297fc4231a886b62b9 100644
|
||||
--- a/third_party/blink/renderer/modules/peerconnection/rtp_contributing_source_cache.cc
|
||||
+++ b/third_party/blink/renderer/modules/peerconnection/rtp_contributing_source_cache.cc
|
||||
@@ -102,6 +102,10 @@ RtpContributingSourceCache::RtpContributingSourceCache(
|
||||
DCHECK(worker_thread_runner_);
|
||||
}
|
||||
|
||||
+void RtpContributingSourceCache::Shutdown() {
|
||||
+ weak_factory_.InvalidateWeakPtrs();
|
||||
+}
|
||||
+
|
||||
HeapVector<Member<RTCRtpSynchronizationSource>>
|
||||
RtpContributingSourceCache::getSynchronizationSources(
|
||||
ScriptState* script_state,
|
||||
diff --git a/third_party/blink/renderer/modules/peerconnection/rtp_contributing_source_cache.h b/third_party/blink/renderer/modules/peerconnection/rtp_contributing_source_cache.h
|
||||
index 0d0ef9d1c59328e04217d9fca3f4e59b01ecca96..3a42751ab02f5680758c2b3ebce8a599f751c1ca 100644
|
||||
--- a/third_party/blink/renderer/modules/peerconnection/rtp_contributing_source_cache.h
|
||||
+++ b/third_party/blink/renderer/modules/peerconnection/rtp_contributing_source_cache.h
|
||||
@@ -43,6 +43,10 @@ class RtpContributingSourceCache {
|
||||
RTCPeerConnection* pc,
|
||||
scoped_refptr<base::SingleThreadTaskRunner> worker_thread_runner);
|
||||
|
||||
+ // When the owner of this object is Disposed(), this method must be called to
|
||||
+ // cancel any in-flight tasks.
|
||||
+ void Shutdown();
|
||||
+
|
||||
HeapVector<Member<RTCRtpSynchronizationSource>> getSynchronizationSources(
|
||||
ScriptState* script_state,
|
||||
ExceptionState& exception_state,
|
||||
89
patches/chromium/cherry-pick-aeec1ba5893d.patch
Normal file
89
patches/chromium/cherry-pick-aeec1ba5893d.patch
Normal file
@@ -0,0 +1,89 @@
|
||||
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.cc b/gpu/command_buffer/service/shared_image/angle_vulkan_image_backing.cc
|
||||
index a2239f19b8d1002bbf511ba53a9eab6b39b84653..c8b53477a7e7dd5685be1b4aef725911e605825b 100644
|
||||
--- a/gpu/command_buffer/service/shared_image/angle_vulkan_image_backing.cc
|
||||
+++ b/gpu/command_buffer/service/shared_image/angle_vulkan_image_backing.cc
|
||||
@@ -161,6 +161,11 @@ AngleVulkanImageBacking::~AngleVulkanImageBacking() {
|
||||
|
||||
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_) {
|
||||
@@ -325,8 +330,9 @@ void AngleVulkanImageBacking::GLTextureImageRepresentationEndAccess(
|
||||
--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;
|
||||
}
|
||||
@@ -356,6 +362,9 @@ void AngleVulkanImageBacking::ReleaseTextureANGLE() {
|
||||
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 AngleVulkanImageBacking::PrepareBackendTexture() {
|
||||
@@ -435,6 +444,11 @@ void AngleVulkanImageBacking::EndAccessSkia() {
|
||||
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) {
|
||||
diff --git a/gpu/command_buffer/service/shared_image/angle_vulkan_image_backing.h b/gpu/command_buffer/service/shared_image/angle_vulkan_image_backing.h
|
||||
index e773aed4b20db46d7a12a10961d88ff643f9c8ec..9306868802d81af87b8a3d6a0e5ea69d57ac6685 100644
|
||||
--- a/gpu/command_buffer/service/shared_image/angle_vulkan_image_backing.h
|
||||
+++ b/gpu/command_buffer/service/shared_image/angle_vulkan_image_backing.h
|
||||
@@ -80,6 +80,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;
|
||||
};
|
||||
|
||||
} // namespace gpu
|
||||
506
patches/chromium/cherry-pick-b041159d06ad.patch
Normal file
506
patches/chromium/cherry-pick-b041159d06ad.patch
Normal file
@@ -0,0 +1,506 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Matt Reynolds <mattreynolds@google.com>
|
||||
Date: Wed, 8 Mar 2023 23:55:10 +0000
|
||||
Subject: hid: Handle empty input reports
|
||||
|
||||
It's possible for a HID device to define its report descriptor such that
|
||||
one or more reports have no data fields within the report. When receiving these reports, the report buffer should contain only the
|
||||
report ID byte and no other data.
|
||||
|
||||
Ensure that we do not read past the end of the buffer when handling
|
||||
zero-length input reports.
|
||||
|
||||
(cherry picked from commit c9d77da78bc66c135520ac77873d67b89cdcaee6)
|
||||
|
||||
Bug: 1419718
|
||||
Change-Id: I51d32c20f6b16f0d2b0172e0a165469b6b79748c
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/4296562
|
||||
Reviewed-by: Reilly Grant <reillyg@chromium.org>
|
||||
Commit-Queue: Matt Reynolds <mattreynolds@chromium.org>
|
||||
Cr-Original-Commit-Position: refs/heads/main@{#1112009}
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/4320692
|
||||
Commit-Queue: Reilly Grant <reillyg@chromium.org>
|
||||
Auto-Submit: Matt Reynolds <mattreynolds@chromium.org>
|
||||
Cr-Commit-Position: refs/branch-heads/5481@{#1341}
|
||||
Cr-Branched-From: 130f3e4d850f4bc7387cfb8d08aa993d288a67a9-refs/heads/main@{#1084008}
|
||||
|
||||
diff --git a/services/device/hid/hid_connection_impl.cc b/services/device/hid/hid_connection_impl.cc
|
||||
index c413123e12191c413ae327732c9e95caa696e0ff..adfaa66b7601dce4a267e0113c3e14cdc9445f3e 100644
|
||||
--- a/services/device/hid/hid_connection_impl.cc
|
||||
+++ b/services/device/hid/hid_connection_impl.cc
|
||||
@@ -54,11 +54,12 @@ void HidConnectionImpl::OnInputReport(
|
||||
scoped_refptr<base::RefCountedBytes> buffer,
|
||||
size_t size) {
|
||||
DCHECK(client_);
|
||||
- uint8_t report_id = buffer->data()[0];
|
||||
- uint8_t* begin = &buffer->data()[1];
|
||||
- uint8_t* end = buffer->data().data() + size;
|
||||
- std::vector<uint8_t> data(begin, end);
|
||||
- client_->OnInputReport(report_id, data);
|
||||
+ DCHECK_GE(size, 1u);
|
||||
+ std::vector<uint8_t> data;
|
||||
+ if (size > 1) {
|
||||
+ data = std::vector<uint8_t>(buffer->front() + 1, buffer->front() + size);
|
||||
+ }
|
||||
+ client_->OnInputReport(/*report_id=*/buffer->data()[0], data);
|
||||
}
|
||||
|
||||
void HidConnectionImpl::Read(ReadCallback callback) {
|
||||
diff --git a/services/device/hid/hid_connection_impl_unittest.cc b/services/device/hid/hid_connection_impl_unittest.cc
|
||||
index 25f715fa5bd0584228b5d6dd7c27103ce5a61885..3d2e74aeaa6676af88719d56fd9c889a296eccd3 100644
|
||||
--- a/services/device/hid/hid_connection_impl_unittest.cc
|
||||
+++ b/services/device/hid/hid_connection_impl_unittest.cc
|
||||
@@ -8,17 +8,28 @@
|
||||
#include "base/callback_helpers.h"
|
||||
#include "base/memory/raw_ptr.h"
|
||||
#include "base/memory/ref_counted_memory.h"
|
||||
+#include "base/test/repeating_test_future.h"
|
||||
+#include "base/test/test_future.h"
|
||||
#include "build/build_config.h"
|
||||
#include "mojo/public/cpp/bindings/pending_receiver.h"
|
||||
#include "mojo/public/cpp/bindings/receiver.h"
|
||||
#include "mojo/public/cpp/bindings/self_owned_receiver.h"
|
||||
#include "services/device/device_service_test_base.h"
|
||||
+#include "testing/gmock/include/gmock/gmock.h"
|
||||
#include "testing/gtest/include/gtest/gtest.h"
|
||||
|
||||
namespace device {
|
||||
|
||||
namespace {
|
||||
|
||||
+using ::testing::ElementsAre;
|
||||
+
|
||||
+using ReadFuture = base::test::
|
||||
+ TestFuture<bool, uint8_t, const absl::optional<std::vector<uint8_t>>&>;
|
||||
+using WriteFuture = base::test::TestFuture<bool>;
|
||||
+using GetFeatureFuture =
|
||||
+ base::test::TestFuture<bool, const absl::optional<std::vector<uint8_t>>&>;
|
||||
+
|
||||
#if BUILDFLAG(IS_MAC)
|
||||
const uint64_t kTestDeviceId = 123;
|
||||
#elif BUILDFLAG(IS_WIN)
|
||||
@@ -30,46 +41,37 @@ const char* kTestDeviceId = "123";
|
||||
// The report ID to use for reports sent to or received from the test device.
|
||||
const uint8_t kTestReportId = 0x42;
|
||||
|
||||
-// The max size of input and output reports for the test device. Feature reports
|
||||
-// are not used in this test.
|
||||
+// The max size of reports for the test device.
|
||||
const uint64_t kMaxReportSizeBytes = 10;
|
||||
|
||||
-// A fake HidConnection implementation that allows the test to simulate an
|
||||
-// input report.
|
||||
-class FakeHidConnection : public HidConnection {
|
||||
+// A mock HidConnection implementation that allows the test to simulate reports.
|
||||
+class MockHidConnection : public HidConnection {
|
||||
public:
|
||||
- explicit FakeHidConnection(scoped_refptr<HidDeviceInfo> device)
|
||||
+ explicit MockHidConnection(scoped_refptr<HidDeviceInfo> device)
|
||||
: HidConnection(device,
|
||||
/*allow_protected_reports=*/false,
|
||||
/*allow_fido_reports=*/false) {}
|
||||
- FakeHidConnection(const FakeHidConnection&) = delete;
|
||||
- FakeHidConnection& operator=(const FakeHidConnection&) = delete;
|
||||
+ MockHidConnection(const MockHidConnection&) = delete;
|
||||
+ MockHidConnection& operator=(const MockHidConnection&) = delete;
|
||||
|
||||
// HidConnection implementation.
|
||||
void PlatformClose() override {}
|
||||
- void PlatformWrite(scoped_refptr<base::RefCountedBytes> buffer,
|
||||
- WriteCallback callback) override {
|
||||
- std::move(callback).Run(true);
|
||||
- }
|
||||
- void PlatformGetFeatureReport(uint8_t report_id,
|
||||
- ReadCallback callback) override {
|
||||
- NOTIMPLEMENTED();
|
||||
- }
|
||||
- void PlatformSendFeatureReport(scoped_refptr<base::RefCountedBytes> buffer,
|
||||
- WriteCallback callback) override {
|
||||
- NOTIMPLEMENTED();
|
||||
- }
|
||||
+ MOCK_METHOD2(PlatformWrite,
|
||||
+ void(scoped_refptr<base::RefCountedBytes>, WriteCallback));
|
||||
+ MOCK_METHOD2(PlatformGetFeatureReport, void(uint8_t, ReadCallback));
|
||||
+ MOCK_METHOD2(PlatformSendFeatureReport,
|
||||
+ void(scoped_refptr<base::RefCountedBytes>, WriteCallback));
|
||||
|
||||
void SimulateInputReport(scoped_refptr<base::RefCountedBytes> buffer) {
|
||||
ProcessInputReport(buffer, buffer->size());
|
||||
}
|
||||
|
||||
private:
|
||||
- ~FakeHidConnection() override = default;
|
||||
+ ~MockHidConnection() override = default;
|
||||
};
|
||||
|
||||
-// A test implementation of HidConnectionClient that signals once an input
|
||||
-// report has been received. The contents of the input report are saved.
|
||||
+// An implementation of HidConnectionClient that enables the test to wait until
|
||||
+// an input report is received.
|
||||
class TestHidConnectionClient : public mojom::HidConnectionClient {
|
||||
public:
|
||||
TestHidConnectionClient() = default;
|
||||
@@ -81,76 +83,18 @@ class TestHidConnectionClient : public mojom::HidConnectionClient {
|
||||
receiver_.Bind(std::move(receiver));
|
||||
}
|
||||
|
||||
- // mojom::HidConnectionClient implementation.
|
||||
void OnInputReport(uint8_t report_id,
|
||||
const std::vector<uint8_t>& buffer) override {
|
||||
- report_id_ = report_id;
|
||||
- buffer_ = buffer;
|
||||
- run_loop_.Quit();
|
||||
- }
|
||||
-
|
||||
- void WaitForInputReport() { run_loop_.Run(); }
|
||||
-
|
||||
- uint8_t report_id() { return report_id_; }
|
||||
- const std::vector<uint8_t>& buffer() { return buffer_; }
|
||||
-
|
||||
- private:
|
||||
- base::RunLoop run_loop_;
|
||||
- mojo::Receiver<mojom::HidConnectionClient> receiver_{this};
|
||||
- uint8_t report_id_ = 0;
|
||||
- std::vector<uint8_t> buffer_;
|
||||
-};
|
||||
-
|
||||
-// A utility for capturing the state returned by mojom::HidConnection I/O
|
||||
-// callbacks.
|
||||
-class TestIoCallback {
|
||||
- public:
|
||||
- TestIoCallback() = default;
|
||||
- TestIoCallback(const TestIoCallback&) = delete;
|
||||
- TestIoCallback& operator=(const TestIoCallback&) = delete;
|
||||
- ~TestIoCallback() = default;
|
||||
-
|
||||
- void SetReadResult(bool result,
|
||||
- uint8_t report_id,
|
||||
- const absl::optional<std::vector<uint8_t>>& buffer) {
|
||||
- result_ = result;
|
||||
- report_id_ = report_id;
|
||||
- has_buffer_ = buffer.has_value();
|
||||
- if (has_buffer_)
|
||||
- buffer_ = *buffer;
|
||||
- run_loop_.Quit();
|
||||
- }
|
||||
-
|
||||
- void SetWriteResult(bool result) {
|
||||
- result_ = result;
|
||||
- run_loop_.Quit();
|
||||
- }
|
||||
-
|
||||
- bool WaitForResult() {
|
||||
- run_loop_.Run();
|
||||
- return result_;
|
||||
- }
|
||||
-
|
||||
- mojom::HidConnection::ReadCallback GetReadCallback() {
|
||||
- return base::BindOnce(&TestIoCallback::SetReadResult,
|
||||
- base::Unretained(this));
|
||||
+ future_.AddValue(report_id, buffer);
|
||||
}
|
||||
|
||||
- mojom::HidConnection::WriteCallback GetWriteCallback() {
|
||||
- return base::BindOnce(&TestIoCallback::SetWriteResult,
|
||||
- base::Unretained(this));
|
||||
+ std::pair<uint8_t, std::vector<uint8_t>> GetNextInputReport() {
|
||||
+ return future_.Take();
|
||||
}
|
||||
|
||||
- uint8_t report_id() { return report_id_; }
|
||||
- bool has_buffer() { return has_buffer_; }
|
||||
- const std::vector<uint8_t>& buffer() { return buffer_; }
|
||||
-
|
||||
private:
|
||||
- base::RunLoop run_loop_;
|
||||
- bool result_ = false;
|
||||
- uint8_t report_id_ = 0;
|
||||
- bool has_buffer_ = false;
|
||||
- std::vector<uint8_t> buffer_;
|
||||
+ mojo::Receiver<mojom::HidConnectionClient> receiver_{this};
|
||||
+ base::test::RepeatingTestFuture<uint8_t, std::vector<uint8_t>> future_;
|
||||
};
|
||||
|
||||
} // namespace
|
||||
@@ -158,8 +102,8 @@ class TestIoCallback {
|
||||
class HidConnectionImplTest : public DeviceServiceTestBase {
|
||||
public:
|
||||
HidConnectionImplTest() = default;
|
||||
- HidConnectionImplTest(HidConnectionImplTest&) = delete;
|
||||
- HidConnectionImplTest& operator=(HidConnectionImplTest&) = delete;
|
||||
+ HidConnectionImplTest(const HidConnectionImplTest&) = delete;
|
||||
+ HidConnectionImplTest& operator=(const HidConnectionImplTest&) = delete;
|
||||
|
||||
protected:
|
||||
void SetUp() override {
|
||||
@@ -167,18 +111,28 @@ class HidConnectionImplTest : public DeviceServiceTestBase {
|
||||
base::RunLoop().RunUntilIdle();
|
||||
}
|
||||
|
||||
- void CreateHidConnection(bool with_connection_client) {
|
||||
+ void TearDown() override {
|
||||
+ // HidConnectionImpl is self-owned and will self-destruct when its mojo pipe
|
||||
+ // is disconnected. Allow disconnect handlers to run so HidConnectionImpl
|
||||
+ // can self-destruct before the end of the test.
|
||||
+ base::RunLoop().RunUntilIdle();
|
||||
+ }
|
||||
+
|
||||
+ mojo::Remote<mojom::HidConnection> CreateHidConnection(
|
||||
+ bool with_connection_client) {
|
||||
mojo::PendingRemote<mojom::HidConnectionClient> hid_connection_client;
|
||||
if (with_connection_client) {
|
||||
connection_client_ = std::make_unique<TestHidConnectionClient>();
|
||||
connection_client_->Bind(
|
||||
hid_connection_client.InitWithNewPipeAndPassReceiver());
|
||||
}
|
||||
- fake_connection_ = new FakeHidConnection(CreateTestDevice());
|
||||
- hid_connection_impl_ = new HidConnectionImpl(
|
||||
- fake_connection_, hid_connection_.InitWithNewPipeAndPassReceiver(),
|
||||
- std::move(hid_connection_client),
|
||||
- /*watcher=*/mojo::NullRemote());
|
||||
+ mock_connection_ = new MockHidConnection(CreateTestDevice());
|
||||
+ mojo::Remote<mojom::HidConnection> hid_connection;
|
||||
+ HidConnectionImpl::Create(mock_connection_,
|
||||
+ hid_connection.BindNewPipeAndPassReceiver(),
|
||||
+ std::move(hid_connection_client),
|
||||
+ /*watcher=*/mojo::NullRemote());
|
||||
+ return hid_connection;
|
||||
}
|
||||
|
||||
scoped_refptr<HidDeviceInfo> CreateTestDevice() {
|
||||
@@ -190,7 +144,7 @@ class HidConnectionImplTest : public DeviceServiceTestBase {
|
||||
/*vendor_id=*/0x1234, /*product_id=*/0xabcd, "product name",
|
||||
"serial number", mojom::HidBusType::kHIDBusTypeUSB,
|
||||
std::move(collection), kMaxReportSizeBytes, kMaxReportSizeBytes,
|
||||
- /*max_feature_report_size=*/0);
|
||||
+ kMaxReportSizeBytes);
|
||||
}
|
||||
|
||||
std::vector<uint8_t> CreateTestReportBuffer(uint8_t report_id, size_t size) {
|
||||
@@ -201,37 +155,42 @@ class HidConnectionImplTest : public DeviceServiceTestBase {
|
||||
return buffer;
|
||||
}
|
||||
|
||||
- mojo::PendingRemote<mojom::HidConnection> hid_connection_;
|
||||
- raw_ptr<HidConnectionImpl>
|
||||
- hid_connection_impl_; // Owned by |hid_connection_|.
|
||||
- scoped_refptr<FakeHidConnection> fake_connection_;
|
||||
+ MockHidConnection& mock_connection() { return *mock_connection_.get(); }
|
||||
+ TestHidConnectionClient& connection_client() { return *connection_client_; }
|
||||
+
|
||||
+ private:
|
||||
+ scoped_refptr<MockHidConnection> mock_connection_;
|
||||
std::unique_ptr<TestHidConnectionClient> connection_client_;
|
||||
};
|
||||
|
||||
TEST_F(HidConnectionImplTest, ReadWrite) {
|
||||
- CreateHidConnection(/*with_connection_client=*/false);
|
||||
+ auto hid_connection = CreateHidConnection(/*with_connection_client=*/false);
|
||||
const size_t kTestBufferSize = kMaxReportSizeBytes;
|
||||
std::vector<uint8_t> buffer_vec =
|
||||
CreateTestReportBuffer(kTestReportId, kTestBufferSize);
|
||||
|
||||
// Simulate an output report (host to device).
|
||||
- TestIoCallback write_callback;
|
||||
- hid_connection_impl_->Write(kTestReportId, buffer_vec,
|
||||
- write_callback.GetWriteCallback());
|
||||
- ASSERT_TRUE(write_callback.WaitForResult());
|
||||
+ EXPECT_CALL(mock_connection(), PlatformWrite)
|
||||
+ .WillOnce([](scoped_refptr<base::RefCountedBytes> buffer,
|
||||
+ HidConnectionImpl::WriteCallback callback) {
|
||||
+ std::move(callback).Run(/*success=*/true);
|
||||
+ });
|
||||
+ WriteFuture write_future;
|
||||
+ hid_connection->Write(kTestReportId, buffer_vec, write_future.GetCallback());
|
||||
+ EXPECT_TRUE(write_future.Get());
|
||||
|
||||
// Simulate an input report (device to host).
|
||||
auto buffer = base::MakeRefCounted<base::RefCountedBytes>(buffer_vec);
|
||||
ASSERT_EQ(buffer->size(), kTestBufferSize);
|
||||
- fake_connection_->SimulateInputReport(buffer);
|
||||
+ mock_connection().SimulateInputReport(buffer);
|
||||
|
||||
// Simulate reading the input report.
|
||||
- TestIoCallback read_callback;
|
||||
- hid_connection_impl_->Read(read_callback.GetReadCallback());
|
||||
- ASSERT_TRUE(read_callback.WaitForResult());
|
||||
- EXPECT_EQ(read_callback.report_id(), kTestReportId);
|
||||
- ASSERT_TRUE(read_callback.has_buffer());
|
||||
- const auto& read_buffer = read_callback.buffer();
|
||||
+ ReadFuture read_future;
|
||||
+ hid_connection->Read(read_future.GetCallback());
|
||||
+ EXPECT_TRUE(read_future.Get<0>());
|
||||
+ EXPECT_EQ(read_future.Get<1>(), kTestReportId);
|
||||
+ ASSERT_TRUE(read_future.Get<2>().has_value());
|
||||
+ const auto& read_buffer = read_future.Get<2>().value();
|
||||
ASSERT_EQ(read_buffer.size(), kTestBufferSize - 1);
|
||||
for (size_t i = 1; i < kTestBufferSize; ++i) {
|
||||
EXPECT_EQ(read_buffer[i - 1], buffer_vec[i])
|
||||
@@ -240,26 +199,29 @@ TEST_F(HidConnectionImplTest, ReadWrite) {
|
||||
}
|
||||
|
||||
TEST_F(HidConnectionImplTest, ReadWriteWithConnectionClient) {
|
||||
- CreateHidConnection(/*with_connection_client=*/true);
|
||||
+ auto hid_connection = CreateHidConnection(/*with_connection_client=*/true);
|
||||
const size_t kTestBufferSize = kMaxReportSizeBytes;
|
||||
std::vector<uint8_t> buffer_vec =
|
||||
CreateTestReportBuffer(kTestReportId, kTestBufferSize);
|
||||
|
||||
// Simulate an output report (host to device).
|
||||
- TestIoCallback write_callback;
|
||||
- hid_connection_impl_->Write(kTestReportId, buffer_vec,
|
||||
- write_callback.GetWriteCallback());
|
||||
- ASSERT_TRUE(write_callback.WaitForResult());
|
||||
+ EXPECT_CALL(mock_connection(), PlatformWrite)
|
||||
+ .WillOnce([](scoped_refptr<base::RefCountedBytes> buffer,
|
||||
+ HidConnectionImpl::WriteCallback callback) {
|
||||
+ std::move(callback).Run(/*success=*/true);
|
||||
+ });
|
||||
+ WriteFuture write_future;
|
||||
+ hid_connection->Write(kTestReportId, buffer_vec, write_future.GetCallback());
|
||||
+ EXPECT_TRUE(write_future.Get());
|
||||
|
||||
// Simulate an input report (device to host).
|
||||
auto buffer = base::MakeRefCounted<base::RefCountedBytes>(buffer_vec);
|
||||
ASSERT_EQ(buffer->size(), kTestBufferSize);
|
||||
- fake_connection_->SimulateInputReport(buffer);
|
||||
- connection_client_->WaitForInputReport();
|
||||
+ mock_connection().SimulateInputReport(buffer);
|
||||
+ auto [report_id, in_buffer] = connection_client().GetNextInputReport();
|
||||
|
||||
// The connection client should have been notified.
|
||||
- EXPECT_EQ(connection_client_->report_id(), kTestReportId);
|
||||
- const std::vector<uint8_t>& in_buffer = connection_client_->buffer();
|
||||
+ EXPECT_EQ(report_id, kTestReportId);
|
||||
ASSERT_EQ(in_buffer.size(), kTestBufferSize - 1);
|
||||
for (size_t i = 1; i < kTestBufferSize; ++i) {
|
||||
EXPECT_EQ(in_buffer[i - 1], buffer_vec[i])
|
||||
@@ -268,7 +230,7 @@ TEST_F(HidConnectionImplTest, ReadWriteWithConnectionClient) {
|
||||
}
|
||||
|
||||
TEST_F(HidConnectionImplTest, DestroyWithPendingInputReport) {
|
||||
- CreateHidConnection(/*with_connection_client=*/false);
|
||||
+ auto hid_connection = CreateHidConnection(/*with_connection_client=*/false);
|
||||
const size_t kTestBufferSize = kMaxReportSizeBytes;
|
||||
std::vector<uint8_t> buffer_vec =
|
||||
CreateTestReportBuffer(kTestReportId, kTestBufferSize);
|
||||
@@ -276,21 +238,20 @@ TEST_F(HidConnectionImplTest, DestroyWithPendingInputReport) {
|
||||
// Simulate an input report (device to host).
|
||||
auto buffer = base::MakeRefCounted<base::RefCountedBytes>(buffer_vec);
|
||||
ASSERT_EQ(buffer->size(), kTestBufferSize);
|
||||
- fake_connection_->SimulateInputReport(buffer);
|
||||
+ mock_connection().SimulateInputReport(buffer);
|
||||
|
||||
// Destroy the connection without reading the report.
|
||||
- hid_connection_.reset();
|
||||
+ hid_connection.reset();
|
||||
}
|
||||
|
||||
TEST_F(HidConnectionImplTest, DestroyWithPendingRead) {
|
||||
- CreateHidConnection(/*with_connection_client=*/false);
|
||||
+ auto hid_connection = CreateHidConnection(/*with_connection_client=*/false);
|
||||
|
||||
// Simulate reading an input report.
|
||||
- TestIoCallback read_callback;
|
||||
- hid_connection_impl_->Read(read_callback.GetReadCallback());
|
||||
+ hid_connection->Read(base::DoNothing());
|
||||
|
||||
// Destroy the connection without receiving an input report.
|
||||
- hid_connection_.reset();
|
||||
+ hid_connection.reset();
|
||||
}
|
||||
|
||||
TEST_F(HidConnectionImplTest, WatcherClosedWhenHidConnectionClosed) {
|
||||
@@ -301,7 +262,7 @@ TEST_F(HidConnectionImplTest, WatcherClosedWhenHidConnectionClosed) {
|
||||
|
||||
mojo::Remote<mojom::HidConnection> hid_connection;
|
||||
HidConnectionImpl::Create(
|
||||
- base::MakeRefCounted<FakeHidConnection>(CreateTestDevice()),
|
||||
+ base::MakeRefCounted<MockHidConnection>(CreateTestDevice()),
|
||||
hid_connection.BindNewPipeAndPassReceiver(),
|
||||
/*connection_client=*/mojo::NullRemote(), std::move(watcher));
|
||||
|
||||
@@ -326,7 +287,7 @@ TEST_F(HidConnectionImplTest, HidConnectionClosedWhenWatcherClosed) {
|
||||
|
||||
mojo::Remote<mojom::HidConnection> hid_connection;
|
||||
HidConnectionImpl::Create(
|
||||
- base::MakeRefCounted<FakeHidConnection>(CreateTestDevice()),
|
||||
+ base::MakeRefCounted<MockHidConnection>(CreateTestDevice()),
|
||||
hid_connection.BindNewPipeAndPassReceiver(),
|
||||
/*connection_client=*/mojo::NullRemote(), std::move(watcher));
|
||||
|
||||
@@ -344,4 +305,74 @@ TEST_F(HidConnectionImplTest, HidConnectionClosedWhenWatcherClosed) {
|
||||
EXPECT_FALSE(hid_connection.is_connected());
|
||||
}
|
||||
|
||||
+TEST_F(HidConnectionImplTest, ReadZeroLengthInputReport) {
|
||||
+ auto hid_connection = CreateHidConnection(/*with_connection_client=*/false);
|
||||
+ mock_connection().SimulateInputReport(
|
||||
+ base::MakeRefCounted<base::RefCountedBytes>(
|
||||
+ CreateTestReportBuffer(kTestReportId, /*size=*/1u)));
|
||||
+ ReadFuture read_future;
|
||||
+ hid_connection->Read(read_future.GetCallback());
|
||||
+ EXPECT_TRUE(read_future.Get<0>());
|
||||
+ EXPECT_EQ(read_future.Get<1>(), kTestReportId);
|
||||
+ ASSERT_TRUE(read_future.Get<2>().has_value());
|
||||
+ EXPECT_EQ(read_future.Get<2>().value().size(), 0u);
|
||||
+}
|
||||
+
|
||||
+TEST_F(HidConnectionImplTest, ReadZeroLengthInputReportWithClient) {
|
||||
+ auto hid_connection = CreateHidConnection(/*with_connection_client=*/true);
|
||||
+ mock_connection().SimulateInputReport(
|
||||
+ base::MakeRefCounted<base::RefCountedBytes>(
|
||||
+ CreateTestReportBuffer(kTestReportId, /*size=*/1u)));
|
||||
+ auto [report_id, in_buffer] = connection_client().GetNextInputReport();
|
||||
+ EXPECT_EQ(report_id, kTestReportId);
|
||||
+ EXPECT_EQ(in_buffer.size(), 0u);
|
||||
+}
|
||||
+
|
||||
+TEST_F(HidConnectionImplTest, WriteZeroLengthOutputReport) {
|
||||
+ auto hid_connection = CreateHidConnection(/*with_connection_client=*/false);
|
||||
+ EXPECT_CALL(mock_connection(), PlatformWrite)
|
||||
+ .WillOnce([](scoped_refptr<base::RefCountedBytes> buffer,
|
||||
+ HidConnectionImpl::WriteCallback callback) {
|
||||
+ std::move(callback).Run(/*success=*/true);
|
||||
+ });
|
||||
+ WriteFuture write_future;
|
||||
+ hid_connection->Write(kTestReportId, /*buffer=*/{},
|
||||
+ write_future.GetCallback());
|
||||
+ EXPECT_TRUE(write_future.Get());
|
||||
+}
|
||||
+
|
||||
+TEST_F(HidConnectionImplTest, ReadZeroLengthFeatureReport) {
|
||||
+ auto hid_connection = CreateHidConnection(/*with_connection_client=*/false);
|
||||
+ EXPECT_CALL(mock_connection(), PlatformGetFeatureReport)
|
||||
+ .WillOnce([](uint8_t report_id, HidConnection::ReadCallback callback) {
|
||||
+ std::move(callback).Run(/*success=*/true,
|
||||
+ base::MakeRefCounted<base::RefCountedBytes>(
|
||||
+ std::vector<uint8_t>{report_id}),
|
||||
+ /*size=*/1u);
|
||||
+ });
|
||||
+ GetFeatureFuture get_feature_future;
|
||||
+ hid_connection->GetFeatureReport(kTestReportId,
|
||||
+ get_feature_future.GetCallback());
|
||||
+ EXPECT_TRUE(get_feature_future.Get<0>());
|
||||
+ ASSERT_TRUE(get_feature_future.Get<1>().has_value());
|
||||
+ EXPECT_EQ(get_feature_future.Get<1>().value().size(), 1u);
|
||||
+}
|
||||
+
|
||||
+TEST_F(HidConnectionImplTest, WriteZeroLengthFeatureReport) {
|
||||
+ auto hid_connection = CreateHidConnection(/*with_connection_client=*/false);
|
||||
+ scoped_refptr<base::RefCountedBytes> feature_buffer;
|
||||
+ EXPECT_CALL(mock_connection(), PlatformSendFeatureReport)
|
||||
+ .WillOnce([&feature_buffer](scoped_refptr<base::RefCountedBytes> buffer,
|
||||
+ HidConnectionImpl::WriteCallback callback) {
|
||||
+ feature_buffer = buffer;
|
||||
+ std::move(callback).Run(/*success=*/true);
|
||||
+ });
|
||||
+ WriteFuture write_future;
|
||||
+ hid_connection->SendFeatureReport(kTestReportId, /*buffer=*/{},
|
||||
+ write_future.GetCallback());
|
||||
+ EXPECT_TRUE(write_future.Get());
|
||||
+ ASSERT_TRUE(feature_buffer);
|
||||
+ EXPECT_THAT(feature_buffer->data(), ElementsAre(kTestReportId));
|
||||
+}
|
||||
+
|
||||
} // namespace device
|
||||
257
patches/chromium/cherry-pick-b5c9e5efe5dd.patch
Normal file
257
patches/chromium/cherry-pick-b5c9e5efe5dd.patch
Normal file
@@ -0,0 +1,257 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Dale Curtis <dalecurtis@chromium.org>
|
||||
Date: Wed, 15 Mar 2023 22:55:57 +0000
|
||||
Subject: Merge M110: "Improve checks for VideoFrame layouts."
|
||||
|
||||
Adds a `VideoFrameLayout::IsValidForSize(size)` method which clients can
|
||||
use to verify a VideoFrameLayout for their purpose. Updates a few call
|
||||
sites to use the new verifier and adds tests.
|
||||
|
||||
(cherry picked from commit 17f73200c066158330542c19d521c517586533a2)
|
||||
|
||||
Fixed: 1421268
|
||||
Change-Id: I51049ada6119eddb31cdd9b7edfe77ee65b1da7a
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/4307674
|
||||
Auto-Submit: Dale Curtis <dalecurtis@chromium.org>
|
||||
Reviewed-by: Hirokazu Honda <hiroh@chromium.org>
|
||||
Reviewed-by: Dominick Ng <dominickn@chromium.org>
|
||||
Commit-Queue: Dominick Ng <dominickn@chromium.org>
|
||||
Cr-Original-Commit-Position: refs/heads/main@{#1116233}
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/4342492
|
||||
Cr-Commit-Position: refs/branch-heads/5481@{#1361}
|
||||
Cr-Branched-From: 130f3e4d850f4bc7387cfb8d08aa993d288a67a9-refs/heads/main@{#1084008}
|
||||
|
||||
diff --git a/media/base/video_frame.cc b/media/base/video_frame.cc
|
||||
index 4aa077a567840545b59645ee5ae84194517226b4..4ec81d5c1fc9b26559914b56f48f3eea1fca6bad 100644
|
||||
--- a/media/base/video_frame.cc
|
||||
+++ b/media/base/video_frame.cc
|
||||
@@ -427,20 +427,9 @@ scoped_refptr<VideoFrame> VideoFrame::WrapExternalDataWithLayout(
|
||||
StorageType storage_type = STORAGE_UNOWNED_MEMORY;
|
||||
|
||||
if (!IsValidConfig(layout.format(), storage_type, layout.coded_size(),
|
||||
- visible_rect, natural_size)) {
|
||||
- DLOG(ERROR) << __func__ << " Invalid config."
|
||||
- << ConfigToString(layout.format(), storage_type,
|
||||
- layout.coded_size(), visible_rect,
|
||||
- natural_size);
|
||||
- return nullptr;
|
||||
- }
|
||||
-
|
||||
- const auto& last_plane = layout.planes()[layout.planes().size() - 1];
|
||||
- const size_t required_size = last_plane.offset + last_plane.size;
|
||||
- if (data_size < required_size) {
|
||||
- DLOG(ERROR) << __func__ << " Provided data size is too small. Provided "
|
||||
- << data_size << " bytes, but " << required_size
|
||||
- << " bytes are required."
|
||||
+ visible_rect, natural_size) ||
|
||||
+ !layout.FitsInContiguousBufferOfSize(data_size)) {
|
||||
+ DLOG(ERROR) << "Invalid config: "
|
||||
<< ConfigToString(layout.format(), storage_type,
|
||||
layout.coded_size(), visible_rect,
|
||||
natural_size);
|
||||
diff --git a/media/base/video_frame_layout.cc b/media/base/video_frame_layout.cc
|
||||
index b3307c302bfd678caf3c90c639d32659dd2cad21..1426adb193d92c4aeb658321a6d40cdaa34461ad 100644
|
||||
--- a/media/base/video_frame_layout.cc
|
||||
+++ b/media/base/video_frame_layout.cc
|
||||
@@ -9,6 +9,7 @@
|
||||
#include <sstream>
|
||||
|
||||
#include "base/notreached.h"
|
||||
+#include "base/numerics/checked_math.h"
|
||||
|
||||
namespace media {
|
||||
|
||||
@@ -173,6 +174,34 @@ bool VideoFrameLayout::operator!=(const VideoFrameLayout& rhs) const {
|
||||
return !(*this == rhs);
|
||||
}
|
||||
|
||||
+bool VideoFrameLayout::FitsInContiguousBufferOfSize(size_t data_size) const {
|
||||
+ if (is_multi_planar_) {
|
||||
+ return false;
|
||||
+ }
|
||||
+
|
||||
+ base::CheckedNumeric<size_t> required_size = 0;
|
||||
+ for (const auto& plane : planes_) {
|
||||
+ if (plane.offset > data_size || plane.size > data_size) {
|
||||
+ return false;
|
||||
+ }
|
||||
+
|
||||
+ // No individual plane should have a size + offset > data_size.
|
||||
+ base::CheckedNumeric<size_t> plane_end = plane.size;
|
||||
+ plane_end += plane.offset;
|
||||
+ if (!plane_end.IsValid() || plane_end.ValueOrDie() > data_size) {
|
||||
+ return false;
|
||||
+ }
|
||||
+
|
||||
+ required_size += plane.size;
|
||||
+ }
|
||||
+
|
||||
+ if (!required_size.IsValid() || required_size.ValueOrDie() > data_size) {
|
||||
+ return false;
|
||||
+ }
|
||||
+
|
||||
+ return true;
|
||||
+}
|
||||
+
|
||||
std::ostream& operator<<(std::ostream& ostream,
|
||||
const VideoFrameLayout& layout) {
|
||||
ostream << "VideoFrameLayout(format: " << layout.format()
|
||||
diff --git a/media/base/video_frame_layout.h b/media/base/video_frame_layout.h
|
||||
index d899c15d2d3f31bfac022d2900b62a53eccc1665..ae68bcfe5ab3669932344a6489fce76d8d9ccefa 100644
|
||||
--- a/media/base/video_frame_layout.h
|
||||
+++ b/media/base/video_frame_layout.h
|
||||
@@ -112,6 +112,13 @@ class MEDIA_EXPORT VideoFrameLayout {
|
||||
// Return the modifier of buffers.
|
||||
uint64_t modifier() const { return modifier_; }
|
||||
|
||||
+ // Any constructible layout is valid in and of itself, it can only be invalid
|
||||
+ // if the backing memory is too small to contain it.
|
||||
+ //
|
||||
+ // Returns true if this VideoFrameLayout can fit in a contiguous buffer of
|
||||
+ // size `data_size` -- always false for multi-planar layouts.
|
||||
+ bool FitsInContiguousBufferOfSize(size_t data_size) const;
|
||||
+
|
||||
private:
|
||||
VideoFrameLayout(VideoPixelFormat format,
|
||||
const gfx::Size& coded_size,
|
||||
diff --git a/media/base/video_frame_layout_unittest.cc b/media/base/video_frame_layout_unittest.cc
|
||||
index 71ef5d11d75de5693aa255b5d2400301ad3488c4..c11136eaee78b2cd35154d1a9cc10ec19835ac88 100644
|
||||
--- a/media/base/video_frame_layout_unittest.cc
|
||||
+++ b/media/base/video_frame_layout_unittest.cc
|
||||
@@ -308,4 +308,50 @@ TEST(VideoFrameLayout, EqualOperator) {
|
||||
EXPECT_NE(*layout, *different_layout);
|
||||
}
|
||||
|
||||
+TEST(VideoFrameLayout, FitsInContiguousBufferOfSize) {
|
||||
+ auto coded_size = gfx::Size(320, 180);
|
||||
+
|
||||
+ std::vector<int32_t> strides = {384, 192, 192};
|
||||
+ std::vector<size_t> offsets = {0, 200, 300};
|
||||
+ std::vector<size_t> sizes = {200, 100, 100};
|
||||
+ std::vector<ColorPlaneLayout> planes(strides.size());
|
||||
+ for (size_t i = 0; i < strides.size(); i++) {
|
||||
+ planes[i].stride = strides[i];
|
||||
+ planes[i].offset = offsets[i];
|
||||
+ planes[i].size = sizes[i];
|
||||
+ }
|
||||
+
|
||||
+ auto layout =
|
||||
+ VideoFrameLayout::CreateWithPlanes(PIXEL_FORMAT_I420, coded_size, planes);
|
||||
+ ASSERT_TRUE(layout.has_value());
|
||||
+
|
||||
+ EXPECT_TRUE(
|
||||
+ layout->FitsInContiguousBufferOfSize(sizes[0] + sizes[1] + sizes[2]));
|
||||
+
|
||||
+ // Validate single plane size exceeds data size.
|
||||
+ EXPECT_FALSE(layout->FitsInContiguousBufferOfSize(1));
|
||||
+
|
||||
+ // Validate sum of planes exceeds data size.
|
||||
+ EXPECT_FALSE(layout->FitsInContiguousBufferOfSize(sizes[0] + sizes[1]));
|
||||
+
|
||||
+ // Validate offset exceeds plane size.
|
||||
+ planes[2].offset = 301;
|
||||
+ layout =
|
||||
+ VideoFrameLayout::CreateWithPlanes(PIXEL_FORMAT_I420, coded_size, planes);
|
||||
+ ASSERT_TRUE(layout.has_value());
|
||||
+ EXPECT_TRUE(
|
||||
+ layout->FitsInContiguousBufferOfSize(sizes[0] + sizes[1] + sizes[2] + 1));
|
||||
+ EXPECT_FALSE(layout->FitsInContiguousBufferOfSize(sizes[0]));
|
||||
+
|
||||
+ // Validate overflow.
|
||||
+ planes[0].offset = 0;
|
||||
+ planes[0].size = planes[1].size = planes[2].size =
|
||||
+ std::numeric_limits<size_t>::max() / 2;
|
||||
+ layout =
|
||||
+ VideoFrameLayout::CreateWithPlanes(PIXEL_FORMAT_I420, coded_size, planes);
|
||||
+ ASSERT_TRUE(layout.has_value());
|
||||
+ EXPECT_FALSE(
|
||||
+ layout->FitsInContiguousBufferOfSize(std::numeric_limits<size_t>::max()));
|
||||
+}
|
||||
+
|
||||
} // namespace media
|
||||
diff --git a/media/base/video_frame_unittest.cc b/media/base/video_frame_unittest.cc
|
||||
index 2fb254e8315b57cad3ac743d7ecf4f7c11371823..9e2cd0878362ff4b6315338cc1a39816ffadf49c 100644
|
||||
--- a/media/base/video_frame_unittest.cc
|
||||
+++ b/media/base/video_frame_unittest.cc
|
||||
@@ -770,6 +770,46 @@ TEST(VideoFrame, AllocationSize_OddSize) {
|
||||
}
|
||||
}
|
||||
|
||||
+TEST(VideoFrame, WrapExternalDataWithInvalidLayout) {
|
||||
+ auto coded_size = gfx::Size(320, 180);
|
||||
+
|
||||
+ std::vector<int32_t> strides = {384, 192, 192};
|
||||
+ std::vector<size_t> offsets = {0, 200, 300};
|
||||
+ std::vector<size_t> sizes = {200, 100, 100};
|
||||
+ std::vector<ColorPlaneLayout> planes(strides.size());
|
||||
+ for (size_t i = 0; i < strides.size(); i++) {
|
||||
+ planes[i].stride = strides[i];
|
||||
+ planes[i].offset = offsets[i];
|
||||
+ planes[i].size = sizes[i];
|
||||
+ }
|
||||
+
|
||||
+ auto layout =
|
||||
+ VideoFrameLayout::CreateWithPlanes(PIXEL_FORMAT_I420, coded_size, planes);
|
||||
+ ASSERT_TRUE(layout.has_value());
|
||||
+
|
||||
+ // Validate single plane size exceeds data size.
|
||||
+ uint8_t data = 0;
|
||||
+ auto frame = VideoFrame::WrapExternalDataWithLayout(
|
||||
+ *layout, gfx::Rect(coded_size), coded_size, &data, sizeof(data),
|
||||
+ base::TimeDelta());
|
||||
+ ASSERT_FALSE(frame);
|
||||
+
|
||||
+ // Validate sum of planes exceeds data size.
|
||||
+ frame = VideoFrame::WrapExternalDataWithLayout(
|
||||
+ *layout, gfx::Rect(coded_size), coded_size, &data, sizes[0] + sizes[1],
|
||||
+ base::TimeDelta());
|
||||
+ ASSERT_FALSE(frame);
|
||||
+
|
||||
+ // Validate offset exceeds plane size.
|
||||
+ planes[0].offset = 201;
|
||||
+ layout =
|
||||
+ VideoFrameLayout::CreateWithPlanes(PIXEL_FORMAT_I420, coded_size, planes);
|
||||
+ frame = VideoFrame::WrapExternalDataWithLayout(*layout, gfx::Rect(coded_size),
|
||||
+ coded_size, &data, sizes[0],
|
||||
+ base::TimeDelta());
|
||||
+ ASSERT_FALSE(frame);
|
||||
+}
|
||||
+
|
||||
TEST(VideoFrameMetadata, MergeMetadata) {
|
||||
VideoFrameMetadata reference_metadata = GetFullVideoFrameMetadata();
|
||||
VideoFrameMetadata full_metadata = reference_metadata;
|
||||
diff --git a/media/mojo/mojom/video_frame_mojom_traits.cc b/media/mojo/mojom/video_frame_mojom_traits.cc
|
||||
index cdc4498f52873a6ba68271e4b373c5ace27f43c9..3a07ab5e7e877c9230df7f1a3bcd0df51a8940b6 100644
|
||||
--- a/media/mojo/mojom/video_frame_mojom_traits.cc
|
||||
+++ b/media/mojo/mojom/video_frame_mojom_traits.cc
|
||||
@@ -231,14 +231,17 @@ bool StructTraits<media::mojom::VideoFrameDataView,
|
||||
|
||||
auto layout = media::VideoFrameLayout::CreateWithPlanes(format, coded_size,
|
||||
std::move(planes));
|
||||
- if (!layout) {
|
||||
+ if (!layout || !layout->FitsInContiguousBufferOfSize(mapping.size())) {
|
||||
DLOG(ERROR) << "Invalid layout";
|
||||
return false;
|
||||
}
|
||||
+
|
||||
frame = media::VideoFrame::WrapExternalYuvDataWithLayout(
|
||||
*layout, visible_rect, natural_size, addr[0], addr[1], addr[2],
|
||||
timestamp);
|
||||
- frame->BackWithOwnedSharedMemory(std::move(region), std::move(mapping));
|
||||
+ if (frame) {
|
||||
+ frame->BackWithOwnedSharedMemory(std::move(region), std::move(mapping));
|
||||
+ }
|
||||
} else if (data.is_gpu_memory_buffer_data()) {
|
||||
media::mojom::GpuMemoryBufferVideoFrameDataDataView gpu_memory_buffer_data;
|
||||
data.GetGpuMemoryBufferDataDataView(&gpu_memory_buffer_data);
|
||||
@@ -313,8 +316,9 @@ bool StructTraits<media::mojom::VideoFrameDataView,
|
||||
return false;
|
||||
}
|
||||
|
||||
- if (!frame)
|
||||
+ if (!frame) {
|
||||
return false;
|
||||
+ }
|
||||
|
||||
media::VideoFrameMetadata metadata;
|
||||
if (!input.ReadMetadata(&metadata))
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user