mirror of
https://github.com/electron/electron.git
synced 2026-02-19 03:14:51 -05:00
Compare commits
58 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
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 |
@@ -484,7 +484,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 +496,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
|
||||
|
||||
@@ -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
|
||||
|
||||
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.179',
|
||||
'108.0.5359.215',
|
||||
'node_version':
|
||||
'v16.17.1',
|
||||
'nan_version':
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
|
||||
version: 1.0.{build}
|
||||
build_cloud: electronhq-16-core
|
||||
image: e-111.0.5518.0
|
||||
image: e-111.0.5560.0-node18
|
||||
environment:
|
||||
GIT_CACHE_PATH: C:\Users\appveyor\libcc_cache
|
||||
ELECTRON_OUT_DIR: Default
|
||||
@@ -16,17 +16,61 @@ environment:
|
||||
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:
|
||||
- ps: Resize-Partition -DriveLetter C -Size (256GB) # ensure initial partition size
|
||||
- ps: Get-Partition -DriveLetter C
|
||||
# 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
|
||||
- cd ..
|
||||
- mkdir src
|
||||
- ps: git clone --depth=1 https://chromium.googlesource.com/chromium/tools/depot_tools.git
|
||||
- ps: $env:PATH="$pwd\depot_tools;$env:PATH"
|
||||
- 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
|
||||
- ps: Move-Item $env:APPVEYOR_BUILD_FOLDER -Destination src\electron
|
||||
- src\electron\script\setup-win-for-dev.bat
|
||||
# Uncomment the following line if windows deps change
|
||||
# - src\electron\script\setup-win-for-dev.bat
|
||||
- >-
|
||||
gclient config
|
||||
--name "src\electron"
|
||||
@@ -40,13 +84,25 @@ build_script:
|
||||
- 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 $pwd\depot_tools
|
||||
- ps: Remove-Item -Recurse -Force $pwd\src\electron
|
||||
# Uncomment these lines to enable RDP
|
||||
#on_finish:
|
||||
# - ps: >-
|
||||
# $env:APPVEYOR_RDP_PASSWORD = "electron"
|
||||
# $blockRdp = $true; iex ((new-object net.webclient).DownloadString('https://raw.githubusercontent.com/appveyor/ci/master/scripts/enable-rdp.ps1'))
|
||||
- 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'))
|
||||
|
||||
@@ -29,7 +29,7 @@
|
||||
|
||||
version: 1.0.{build}
|
||||
build_cloud: electronhq-16-core
|
||||
image: e-108.0.5359.179
|
||||
image: e-108.0.5359.215
|
||||
environment:
|
||||
GIT_CACHE_PATH: C:\Users\appveyor\libcc_cache
|
||||
ELECTRON_OUT_DIR: Default
|
||||
@@ -51,6 +51,8 @@ environment:
|
||||
|
||||
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
|
||||
@@ -80,7 +82,7 @@ for:
|
||||
if (Test-Path -Path "$pwd\build-tools") {
|
||||
Remove-Item -Recurse -Force $pwd\build-tools
|
||||
}
|
||||
- ps: git clone --depth=1 https://chromium.googlesource.com/chromium/tools/depot_tools.git
|
||||
- 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") {
|
||||
@@ -130,6 +132,7 @@ for:
|
||||
}
|
||||
- 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
|
||||
|
||||
@@ -29,7 +29,7 @@
|
||||
|
||||
version: 1.0.{build}
|
||||
build_cloud: electronhq-16-core
|
||||
image: e-108.0.5359.179
|
||||
image: e-108.0.5359.215-node18
|
||||
environment:
|
||||
GIT_CACHE_PATH: C:\Users\appveyor\libcc_cache
|
||||
ELECTRON_OUT_DIR: Default
|
||||
@@ -49,6 +49,8 @@ environment:
|
||||
|
||||
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
|
||||
@@ -78,7 +80,7 @@ for:
|
||||
if (Test-Path -Path "$pwd\build-tools") {
|
||||
Remove-Item -Recurse -Force $pwd\build-tools
|
||||
}
|
||||
- ps: git clone --depth=1 https://chromium.googlesource.com/chromium/tools/depot_tools.git
|
||||
- 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") {
|
||||
@@ -128,6 +130,7 @@ for:
|
||||
}
|
||||
- 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
|
||||
|
||||
@@ -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
|
||||
@@ -1562,5 +1560,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.
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -443,7 +439,7 @@ Returns `Promise<boolean>` - A promise that resolves with `true` if consent was
|
||||
|
||||
**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).
|
||||
|
||||
|
||||
@@ -1416,8 +1416,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.
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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...
|
||||
|
||||
@@ -33,4 +33,4 @@ template and submit a new issue.
|
||||
[(publish)]: https://www.electronforge.io/cli#publish
|
||||
[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}`)
|
||||
})
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
@@ -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.
|
||||
|
||||
|
||||
@@ -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",
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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/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",
|
||||
|
||||
@@ -1 +1,2 @@
|
||||
fix_rename_webswapcgllayer_to_webswapcgllayerchromium.patch
|
||||
cherry-pick-55e2b6daba9d.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());
|
||||
|
||||
@@ -126,3 +126,13 @@ 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-38de42d2bbc3.patch
|
||||
cherry-pick-8731bd8a30f6.patch
|
||||
cherry-pick-26bfa5807606.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}}
|
||||
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);
|
||||
}
|
||||
}
|
||||
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>
|
||||
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);
|
||||
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.
|
||||
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
|
||||
58
patches/chromium/cherry-pick-e79b89b47dac.patch
Normal file
58
patches/chromium/cherry-pick-e79b89b47dac.patch
Normal file
@@ -0,0 +1,58 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Vasiliy Telezhnikov <vasilyt@chromium.org>
|
||||
Date: Fri, 10 Feb 2023 17:36:57 +0000
|
||||
Subject: CHECK that YUV readback finished synchronously
|
||||
|
||||
DoReadbackYUVImagePixelsINTERNAL is implemented using skia asynchronous
|
||||
readback and to make it synchronous we use sync cpu and gpu. In some
|
||||
edge cases on linux we saw that doesn't happen if readback triggered
|
||||
vulkan device lost.
|
||||
|
||||
To avoid use after free, CHECK that callback was actually called. In
|
||||
case of device-lost gpu process will restart anyway, so while this is
|
||||
not proper fix of the problem, it doesn't result in worse user visible
|
||||
behaviour.
|
||||
|
||||
(cherry picked from commit 081df1e7d3712131bcaa575bda2e37ec7f6aa83d)
|
||||
|
||||
Bug: 1399742
|
||||
Change-Id: Ie2172539bb907b9696ef62c70d398aca3967177c
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/4143606
|
||||
Reviewed-by: Peng Huang <penghuang@chromium.org>
|
||||
Commit-Queue: Vasiliy Telezhnikov <vasilyt@chromium.org>
|
||||
Cr-Original-Commit-Position: refs/heads/main@{#1093064}
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/4239960
|
||||
Cr-Commit-Position: refs/branch-heads/5481@{#1084}
|
||||
Cr-Branched-From: 130f3e4d850f4bc7387cfb8d08aa993d288a67a9-refs/heads/main@{#1084008}
|
||||
|
||||
diff --git a/gpu/command_buffer/service/raster_decoder.cc b/gpu/command_buffer/service/raster_decoder.cc
|
||||
index d2ac0ac70902d68b95417d2a95da153a7fc38128..ef79b5cbcc83d5ed12a9627ce76692476ace10a0 100644
|
||||
--- a/gpu/command_buffer/service/raster_decoder.cc
|
||||
+++ b/gpu/command_buffer/service/raster_decoder.cc
|
||||
@@ -2485,6 +2485,7 @@ void RasterDecoderImpl::DoReadbackARGBImagePixelsINTERNAL(
|
||||
namespace {
|
||||
struct YUVReadbackResult {
|
||||
std::unique_ptr<const SkImage::AsyncReadResult> async_result;
|
||||
+ bool finished = false;
|
||||
};
|
||||
|
||||
void OnReadYUVImagePixelsDone(
|
||||
@@ -2492,6 +2493,7 @@ void OnReadYUVImagePixelsDone(
|
||||
std::unique_ptr<const SkImage::AsyncReadResult> async_result) {
|
||||
YUVReadbackResult* context = reinterpret_cast<YUVReadbackResult*>(raw_ctx);
|
||||
context->async_result = std::move(async_result);
|
||||
+ context->finished = true;
|
||||
}
|
||||
} // namespace
|
||||
|
||||
@@ -2689,6 +2691,10 @@ void RasterDecoderImpl::DoReadbackYUVImagePixelsINTERNAL(
|
||||
// asynchronous by removing this flush and implementing a query that can
|
||||
// signal back to client process.
|
||||
gr_context()->flushAndSubmit(true);
|
||||
+
|
||||
+ // The call above will sync up gpu and CPU, resulting in callback being run
|
||||
+ // during flushAndSubmit. To prevent UAF make sure it indeed happened.
|
||||
+ CHECK(yuv_result.finished);
|
||||
if (!yuv_result.async_result) {
|
||||
LOCAL_SET_GL_ERROR(GL_INVALID_OPERATION, "glReadbackYUVImagePixels",
|
||||
"Failed to read pixels from SkImage");
|
||||
@@ -0,0 +1,55 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Cheng Zhao <zcbenz@gmail.com>
|
||||
Date: Wed, 15 Feb 2023 11:30:56 +0900
|
||||
Subject: fix: restoring a X11 window should not remove its previous maximized
|
||||
state
|
||||
|
||||
On Linux after minimizing a maximized window, it will have both the
|
||||
"maximized" and "hidden" states, and restoring the window should only remove
|
||||
the "hidden" state, which makes it back a maximized window.
|
||||
|
||||
However in the implementation of `X11Window::Restore`, both "maximized" and
|
||||
"hidden" states are removed, and a maximized window that was minimized will
|
||||
be resized to its normal size after calling Restore, while the correct
|
||||
behavior should be going back to the maximized state.
|
||||
|
||||
Backported from:
|
||||
https://chromium-review.googlesource.com/c/chromium/src/+/4252946
|
||||
|
||||
diff --git a/ui/ozone/platform/x11/x11_window.cc b/ui/ozone/platform/x11/x11_window.cc
|
||||
index 45e0a75a643c2d7a70af37cbf38dcbde52fdd0cf..b229800eafabb0c810430d615cc165ff1e356491 100644
|
||||
--- a/ui/ozone/platform/x11/x11_window.cc
|
||||
+++ b/ui/ozone/platform/x11/x11_window.cc
|
||||
@@ -729,11 +729,16 @@ void X11Window::Minimize() {
|
||||
}
|
||||
|
||||
void X11Window::Restore() {
|
||||
- should_maximize_after_map_ = false;
|
||||
- restore_in_flight_ = true;
|
||||
- SetWMSpecState(false, x11::GetAtom("_NET_WM_STATE_MAXIMIZED_VERT"),
|
||||
- x11::GetAtom("_NET_WM_STATE_MAXIMIZED_HORZ"));
|
||||
- SetWMSpecState(false, x11::GetAtom("_NET_WM_STATE_HIDDEN"), x11::Atom::None);
|
||||
+ if (IsMinimized()) {
|
||||
+ restore_in_flight_ = true;
|
||||
+ SetWMSpecState(false, x11::GetAtom("_NET_WM_STATE_HIDDEN"),
|
||||
+ x11::Atom::None);
|
||||
+ } else if (IsMaximized()) {
|
||||
+ restore_in_flight_ = true;
|
||||
+ should_maximize_after_map_ = false;
|
||||
+ SetWMSpecState(false, x11::GetAtom("_NET_WM_STATE_MAXIMIZED_VERT"),
|
||||
+ x11::GetAtom("_NET_WM_STATE_MAXIMIZED_HORZ"));
|
||||
+ }
|
||||
}
|
||||
|
||||
PlatformWindowState X11Window::GetPlatformWindowState() const {
|
||||
@@ -1884,6 +1889,10 @@ bool X11Window::IsMinimized() const {
|
||||
}
|
||||
|
||||
bool X11Window::IsMaximized() const {
|
||||
+ // In X11, if a maximized window is minimized, it will have both the "hidden"
|
||||
+ // and "maximized" states.
|
||||
+ if (IsMinimized())
|
||||
+ return false;
|
||||
return (HasWMSpecProperty(window_properties_,
|
||||
x11::GetAtom("_NET_WM_STATE_MAXIMIZED_VERT")) &&
|
||||
HasWMSpecProperty(window_properties_,
|
||||
@@ -0,0 +1,381 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Dale Curtis <dalecurtis@chromium.org>
|
||||
Date: Mon, 20 Feb 2023 13:16:32 +0000
|
||||
Subject: Further simplify WebMediaPlayerMSCompositor lifetime.
|
||||
|
||||
M108 merge issues:
|
||||
third_party/blink/renderer/modules/mediastream/webmediaplayer_ms.cc:
|
||||
- video_task_runner_ is named io_task_runner_ in 108
|
||||
|
||||
third_party/blink/renderer/modules/mediastream/webmediaplayer_ms_compositor.cc:
|
||||
- video_task_runner_ is named io_task_runner_ in 108 (conflict in ReplaceCurrentFrameWithACopy)
|
||||
|
||||
Due to the raw pointer held by VideoFrameSubmitter, there may be
|
||||
tasks pending on the compositor task runner after the RefCounted
|
||||
traits have "destructed" WebMediaPlayerMSCompositor. Through this
|
||||
raw pointer VFS was invoking OnContextLost which attempts to use
|
||||
the zero ref count compositor.
|
||||
|
||||
The solution here is again similar to VideoFrameCompositor, its
|
||||
destruction should be explicit instead of a tangle of RefCounted
|
||||
owners.
|
||||
|
||||
(cherry picked from commit 1622bffc6534a0cc4f53d07c43e0cd8f49975d10)
|
||||
|
||||
Fixed: 1407701, 1411601
|
||||
Change-Id: Ic77294d1113d54ab83bc0f5b625a997edf57bf7c
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/4210508
|
||||
Commit-Queue: Tony Herre <toprice@chromium.org>
|
||||
Auto-Submit: Dale Curtis <dalecurtis@chromium.org>
|
||||
Cr-Original-Commit-Position: refs/heads/main@{#1099726}
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/4225393
|
||||
Commit-Queue: Roger Felipe Zanoni da Silva <rzanoni@google.com>
|
||||
Reviewed-by: Oleh Lamzin <lamzin@google.com>
|
||||
Owners-Override: Oleh Lamzin <lamzin@google.com>
|
||||
Cr-Commit-Position: refs/branch-heads/5359@{#1392}
|
||||
Cr-Branched-From: 27d3765d341b09369006d030f83f582a29eb57ae-refs/heads/main@{#1058933}
|
||||
|
||||
diff --git a/third_party/blink/public/web/modules/mediastream/webmediaplayer_ms.h b/third_party/blink/public/web/modules/mediastream/webmediaplayer_ms.h
|
||||
index f8c640d4f866afafa6fab82d67fe5f866810f828..955f867cc24152fa88dd6c20de006425a20b77c5 100644
|
||||
--- a/third_party/blink/public/web/modules/mediastream/webmediaplayer_ms.h
|
||||
+++ b/third_party/blink/public/web/modules/mediastream/webmediaplayer_ms.h
|
||||
@@ -211,6 +211,8 @@ class BLINK_MODULES_EXPORT WebMediaPlayerMS
|
||||
static const gfx::Size kUseGpuMemoryBufferVideoFramesMinResolution;
|
||||
#endif // BUILDFLAG(IS_WIN)
|
||||
|
||||
+ void ReplaceCurrentFrameWithACopy();
|
||||
+
|
||||
bool IsInPictureInPicture() const;
|
||||
|
||||
// Switch to SurfaceLayer, either initially or from VideoLayer.
|
||||
@@ -313,7 +315,7 @@ class BLINK_MODULES_EXPORT WebMediaPlayerMS
|
||||
// Used for DCHECKs to ensure methods calls executed in the correct thread.
|
||||
THREAD_CHECKER(thread_checker_);
|
||||
|
||||
- scoped_refptr<WebMediaPlayerMSCompositor> compositor_;
|
||||
+ std::unique_ptr<WebMediaPlayerMSCompositor> compositor_;
|
||||
|
||||
const WebString initial_audio_output_device_id_;
|
||||
|
||||
diff --git a/third_party/blink/renderer/modules/mediastream/webmediaplayer_ms.cc b/third_party/blink/renderer/modules/mediastream/webmediaplayer_ms.cc
|
||||
index e4eb2b0053384d3e89545928c22bc2e1a12580fa..a85406d39037a8003eaffd1a91c8021ad38e0267 100644
|
||||
--- a/third_party/blink/renderer/modules/mediastream/webmediaplayer_ms.cc
|
||||
+++ b/third_party/blink/renderer/modules/mediastream/webmediaplayer_ms.cc
|
||||
@@ -399,8 +399,9 @@ WebMediaPlayerMS::~WebMediaPlayerMS() {
|
||||
SendLogMessage(
|
||||
String::Format("%s() [delegate_id=%d]", __func__, delegate_id_));
|
||||
|
||||
- if (!web_stream_.IsNull())
|
||||
+ if (!web_stream_.IsNull()) {
|
||||
web_stream_.RemoveObserver(this);
|
||||
+ }
|
||||
|
||||
// Destruct compositor resources in the proper order.
|
||||
get_client()->SetCcLayer(nullptr);
|
||||
@@ -409,14 +410,35 @@ WebMediaPlayerMS::~WebMediaPlayerMS() {
|
||||
video_layer_->StopUsingProvider();
|
||||
}
|
||||
|
||||
- if (frame_deliverer_)
|
||||
- io_task_runner_->DeleteSoon(FROM_HERE, frame_deliverer_.release());
|
||||
+ if (frame_deliverer_) {
|
||||
+ io_task_runner_->DeleteSoon(FROM_HERE, std::move(frame_deliverer_));
|
||||
+ }
|
||||
|
||||
- if (video_frame_provider_)
|
||||
+ if (video_frame_provider_) {
|
||||
video_frame_provider_->Stop();
|
||||
+ }
|
||||
|
||||
- if (audio_renderer_)
|
||||
+ // This must be destroyed before `compositor_` since it will grab a couple of
|
||||
+ // final metrics during destruction.
|
||||
+ watch_time_reporter_.reset();
|
||||
+
|
||||
+ if (compositor_) {
|
||||
+ // `compositor_` receives frames on `io_task_runner_` from
|
||||
+ // `frame_deliverer_` and operates on the `compositor_task_runner_`, so
|
||||
+ // must trampoline through both to ensure a safe destruction.
|
||||
+ PostCrossThreadTask(
|
||||
+ *io_task_runner_, FROM_HERE,
|
||||
+ WTF::CrossThreadBindOnce(
|
||||
+ [](scoped_refptr<base::SingleThreadTaskRunner> task_runner,
|
||||
+ std::unique_ptr<WebMediaPlayerMSCompositor> compositor) {
|
||||
+ task_runner->DeleteSoon(FROM_HERE, std::move(compositor));
|
||||
+ },
|
||||
+ compositor_task_runner_, std::move(compositor_)));
|
||||
+ }
|
||||
+
|
||||
+ if (audio_renderer_) {
|
||||
audio_renderer_->Stop();
|
||||
+ }
|
||||
|
||||
media_log_->AddEvent<media::MediaLogEvent::kWebMediaPlayerDestroyed>();
|
||||
|
||||
@@ -457,7 +479,7 @@ WebMediaPlayer::LoadTiming WebMediaPlayerMS::Load(
|
||||
|
||||
watch_time_reporter_.reset();
|
||||
|
||||
- compositor_ = base::MakeRefCounted<WebMediaPlayerMSCompositor>(
|
||||
+ compositor_ = std::make_unique<WebMediaPlayerMSCompositor>(
|
||||
compositor_task_runner_, io_task_runner_, web_stream_,
|
||||
std::move(submitter_), use_surface_layer_, weak_this_);
|
||||
|
||||
@@ -480,7 +502,7 @@ WebMediaPlayer::LoadTiming WebMediaPlayerMS::Load(
|
||||
frame_deliverer_ = std::make_unique<WebMediaPlayerMS::FrameDeliverer>(
|
||||
weak_this_,
|
||||
CrossThreadBindRepeating(&WebMediaPlayerMSCompositor::EnqueueFrame,
|
||||
- compositor_),
|
||||
+ CrossThreadUnretained(compositor_.get())),
|
||||
media_task_runner_, worker_task_runner_, gpu_factories_);
|
||||
video_frame_provider_ = renderer_factory_->GetVideoRenderer(
|
||||
web_stream_,
|
||||
@@ -826,7 +848,19 @@ void WebMediaPlayerMS::Pause() {
|
||||
video_frame_provider_->Pause();
|
||||
|
||||
compositor_->StopRendering();
|
||||
- compositor_->ReplaceCurrentFrameWithACopy();
|
||||
+
|
||||
+ // Bounce this call off of video task runner to since there might still be
|
||||
+ // frames passed on video task runner.
|
||||
+ PostCrossThreadTask(
|
||||
+ *io_task_runner_, FROM_HERE,
|
||||
+ WTF::CrossThreadBindOnce(
|
||||
+ [](scoped_refptr<base::SingleThreadTaskRunner> task_runner,
|
||||
+ WTF::CrossThreadOnceClosure copy_cb) {
|
||||
+ PostCrossThreadTask(*task_runner, FROM_HERE, std::move(copy_cb));
|
||||
+ },
|
||||
+ main_render_task_runner_,
|
||||
+ WTF::CrossThreadBindOnce(
|
||||
+ &WebMediaPlayerMS::ReplaceCurrentFrameWithACopy, weak_this_)));
|
||||
|
||||
if (audio_renderer_)
|
||||
audio_renderer_->Pause();
|
||||
@@ -841,6 +875,11 @@ void WebMediaPlayerMS::Pause() {
|
||||
paused_ = true;
|
||||
}
|
||||
|
||||
+void WebMediaPlayerMS::ReplaceCurrentFrameWithACopy() {
|
||||
+ DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
|
||||
+ compositor_->ReplaceCurrentFrameWithACopy();
|
||||
+}
|
||||
+
|
||||
void WebMediaPlayerMS::Seek(double seconds) {
|
||||
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
|
||||
}
|
||||
@@ -1192,7 +1231,8 @@ void WebMediaPlayerMS::ActivateSurfaceLayerForVideo(
|
||||
PostCrossThreadTask(
|
||||
*compositor_task_runner_, FROM_HERE,
|
||||
CrossThreadBindOnce(&WebMediaPlayerMSCompositor::EnableSubmission,
|
||||
- compositor_, bridge_->GetSurfaceId(), video_transform,
|
||||
+ CrossThreadUnretained(compositor_.get()),
|
||||
+ bridge_->GetSurfaceId(), video_transform,
|
||||
IsInPictureInPicture()));
|
||||
|
||||
// If the element is already in Picture-in-Picture mode, it means that it
|
||||
diff --git a/third_party/blink/renderer/modules/mediastream/webmediaplayer_ms_compositor.cc b/third_party/blink/renderer/modules/mediastream/webmediaplayer_ms_compositor.cc
|
||||
index acbdf1c64f0efed4c665de270d712bf446eb2106..67f0c200d85073ecd677e467bc1d624b1817dde0 100644
|
||||
--- a/third_party/blink/renderer/modules/mediastream/webmediaplayer_ms_compositor.cc
|
||||
+++ b/third_party/blink/renderer/modules/mediastream/webmediaplayer_ms_compositor.cc
|
||||
@@ -197,18 +197,18 @@ WebMediaPlayerMSCompositor::WebMediaPlayerMSCompositor(
|
||||
dropped_frame_count_(0),
|
||||
stopped_(true),
|
||||
render_started_(!stopped_) {
|
||||
+ weak_this_ = weak_ptr_factory_.GetWeakPtr();
|
||||
if (use_surface_layer) {
|
||||
submitter_ = std::move(submitter);
|
||||
|
||||
PostCrossThreadTask(
|
||||
*video_frame_compositor_task_runner_, FROM_HERE,
|
||||
CrossThreadBindOnce(&WebMediaPlayerMSCompositor::InitializeSubmitter,
|
||||
- weak_ptr_factory_.GetWeakPtr()));
|
||||
+ weak_this_));
|
||||
update_submission_state_callback_ = base::BindPostTask(
|
||||
video_frame_compositor_task_runner_,
|
||||
ConvertToBaseRepeatingCallback(CrossThreadBindRepeating(
|
||||
- &WebMediaPlayerMSCompositor::SetIsSurfaceVisible,
|
||||
- weak_ptr_factory_.GetWeakPtr())));
|
||||
+ &WebMediaPlayerMSCompositor::SetIsSurfaceVisible, weak_this_)));
|
||||
}
|
||||
|
||||
HeapVector<Member<MediaStreamComponent>> video_components;
|
||||
@@ -236,27 +236,12 @@ WebMediaPlayerMSCompositor::WebMediaPlayerMSCompositor(
|
||||
}
|
||||
|
||||
WebMediaPlayerMSCompositor::~WebMediaPlayerMSCompositor() {
|
||||
- // Ensured by destructor traits.
|
||||
DCHECK(video_frame_compositor_task_runner_->BelongsToCurrentThread());
|
||||
if (video_frame_provider_client_) {
|
||||
video_frame_provider_client_->StopUsingProvider();
|
||||
}
|
||||
}
|
||||
|
||||
-// static
|
||||
-void WebMediaPlayerMSCompositorTraits::Destruct(
|
||||
- const WebMediaPlayerMSCompositor* compositor) {
|
||||
- if (!compositor->video_frame_compositor_task_runner_
|
||||
- ->BelongsToCurrentThread()) {
|
||||
- PostCrossThreadTask(
|
||||
- *compositor->video_frame_compositor_task_runner_, FROM_HERE,
|
||||
- CrossThreadBindOnce(&WebMediaPlayerMSCompositorTraits::Destruct,
|
||||
- CrossThreadUnretained(compositor)));
|
||||
- return;
|
||||
- }
|
||||
- delete compositor;
|
||||
-}
|
||||
-
|
||||
void WebMediaPlayerMSCompositor::InitializeSubmitter() {
|
||||
DCHECK(video_frame_compositor_task_runner_->BelongsToCurrentThread());
|
||||
submitter_->Initialize(this, /*is_media_stream=*/true);
|
||||
@@ -302,7 +287,7 @@ void WebMediaPlayerMSCompositor::SetForceBeginFrames(bool enable) {
|
||||
PostCrossThreadTask(
|
||||
*video_frame_compositor_task_runner_, FROM_HERE,
|
||||
CrossThreadBindOnce(&WebMediaPlayerMSCompositor::SetForceBeginFrames,
|
||||
- weak_ptr_factory_.GetWeakPtr(), enable));
|
||||
+ weak_this_, enable));
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -604,7 +589,7 @@ void WebMediaPlayerMSCompositor::StartRendering() {
|
||||
PostCrossThreadTask(
|
||||
*video_frame_compositor_task_runner_, FROM_HERE,
|
||||
CrossThreadBindOnce(&WebMediaPlayerMSCompositor::StartRenderingInternal,
|
||||
- WrapRefCounted(this)));
|
||||
+ weak_this_));
|
||||
}
|
||||
|
||||
void WebMediaPlayerMSCompositor::StopRendering() {
|
||||
@@ -612,18 +597,7 @@ void WebMediaPlayerMSCompositor::StopRendering() {
|
||||
PostCrossThreadTask(
|
||||
*video_frame_compositor_task_runner_, FROM_HERE,
|
||||
CrossThreadBindOnce(&WebMediaPlayerMSCompositor::StopRenderingInternal,
|
||||
- WrapRefCounted(this)));
|
||||
-}
|
||||
-
|
||||
-void WebMediaPlayerMSCompositor::ReplaceCurrentFrameWithACopy() {
|
||||
- DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
|
||||
- // Bounce this call off of IO thread to since there might still be frames
|
||||
- // passed on IO thread.
|
||||
- io_task_runner_->PostTask(
|
||||
- FROM_HERE,
|
||||
- media::BindToCurrentLoop(WTF::BindOnce(
|
||||
- &WebMediaPlayerMSCompositor::ReplaceCurrentFrameWithACopyInternal,
|
||||
- WrapRefCounted(this))));
|
||||
+ weak_this_));
|
||||
}
|
||||
|
||||
bool WebMediaPlayerMSCompositor::MapTimestampsToRenderTimeTicks(
|
||||
@@ -690,7 +664,7 @@ void WebMediaPlayerMSCompositor::RenderWithoutAlgorithm(
|
||||
*video_frame_compositor_task_runner_, FROM_HERE,
|
||||
CrossThreadBindOnce(
|
||||
&WebMediaPlayerMSCompositor::RenderWithoutAlgorithmOnCompositor,
|
||||
- WrapRefCounted(this), std::move(frame), is_copy));
|
||||
+ weak_this_, std::move(frame), is_copy));
|
||||
}
|
||||
|
||||
void WebMediaPlayerMSCompositor::RenderWithoutAlgorithmOnCompositor(
|
||||
@@ -790,9 +764,8 @@ void WebMediaPlayerMSCompositor::SetCurrentFrame(
|
||||
PostCrossThreadTask(
|
||||
*video_frame_compositor_task_runner_, FROM_HERE,
|
||||
CrossThreadBindOnce(&WebMediaPlayerMSCompositor::CheckForFrameChanges,
|
||||
- WrapRefCounted(this), is_first_frame,
|
||||
- has_frame_size_changed, std::move(new_transform),
|
||||
- std::move(new_opacity)));
|
||||
+ weak_this_, is_first_frame, has_frame_size_changed,
|
||||
+ std::move(new_transform), std::move(new_opacity)));
|
||||
}
|
||||
|
||||
void WebMediaPlayerMSCompositor::CheckForFrameChanges(
|
||||
@@ -859,7 +832,7 @@ void WebMediaPlayerMSCompositor::StopRenderingInternal() {
|
||||
video_frame_provider_client_->StopRendering();
|
||||
}
|
||||
|
||||
-void WebMediaPlayerMSCompositor::ReplaceCurrentFrameWithACopyInternal() {
|
||||
+void WebMediaPlayerMSCompositor::ReplaceCurrentFrameWithACopy() {
|
||||
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
|
||||
scoped_refptr<media::VideoFrame> current_frame_ref;
|
||||
{
|
||||
diff --git a/third_party/blink/renderer/modules/mediastream/webmediaplayer_ms_compositor.h b/third_party/blink/renderer/modules/mediastream/webmediaplayer_ms_compositor.h
|
||||
index ffeb448be295223f1f997b47eddff37d04bc8f16..197a0f0d02e84378f7f697213aa613e73c9f79f7 100644
|
||||
--- a/third_party/blink/renderer/modules/mediastream/webmediaplayer_ms_compositor.h
|
||||
+++ b/third_party/blink/renderer/modules/mediastream/webmediaplayer_ms_compositor.h
|
||||
@@ -24,7 +24,6 @@
|
||||
#include "third_party/blink/renderer/modules/mediastream/video_renderer_algorithm_wrapper.h"
|
||||
#include "third_party/blink/renderer/modules/modules_export.h"
|
||||
#include "third_party/blink/renderer/platform/wtf/cross_thread_functional.h"
|
||||
-#include "third_party/blink/renderer/platform/wtf/thread_safe_ref_counted.h"
|
||||
|
||||
namespace base {
|
||||
class SingleThreadTaskRunner;
|
||||
@@ -46,7 +45,6 @@ class SurfaceId;
|
||||
namespace blink {
|
||||
class MediaStreamDescriptor;
|
||||
class WebMediaPlayerMS;
|
||||
-struct WebMediaPlayerMSCompositorTraits;
|
||||
|
||||
// This class is designed to handle the work load on compositor thread for
|
||||
// WebMediaPlayerMS. It will be instantiated on the main thread, but destroyed
|
||||
@@ -58,9 +56,7 @@ struct WebMediaPlayerMSCompositorTraits;
|
||||
// Otherwise, WebMediaPlayerMSCompositor will simply store the most recent
|
||||
// frame, and submit it whenever asked by the compositor.
|
||||
class MODULES_EXPORT WebMediaPlayerMSCompositor
|
||||
- : public cc::VideoFrameProvider,
|
||||
- public WTF::ThreadSafeRefCounted<WebMediaPlayerMSCompositor,
|
||||
- WebMediaPlayerMSCompositorTraits> {
|
||||
+ : public cc::VideoFrameProvider {
|
||||
public:
|
||||
using OnNewFramePresentedCB = base::OnceClosure;
|
||||
|
||||
@@ -76,6 +72,7 @@ class MODULES_EXPORT WebMediaPlayerMSCompositor
|
||||
std::unique_ptr<WebVideoFrameSubmitter> submitter,
|
||||
bool use_surface_layer,
|
||||
const base::WeakPtr<WebMediaPlayerMS>& player);
|
||||
+ ~WebMediaPlayerMSCompositor() override;
|
||||
|
||||
WebMediaPlayerMSCompositor(const WebMediaPlayerMSCompositor&) = delete;
|
||||
WebMediaPlayerMSCompositor& operator=(const WebMediaPlayerMSCompositor&) =
|
||||
@@ -143,10 +140,7 @@ class MODULES_EXPORT WebMediaPlayerMSCompositor
|
||||
Metadata GetMetadata();
|
||||
|
||||
private:
|
||||
- friend class WTF::ThreadSafeRefCounted<WebMediaPlayerMSCompositor,
|
||||
- WebMediaPlayerMSCompositorTraits>;
|
||||
friend class WebMediaPlayerMSTest;
|
||||
- friend struct WebMediaPlayerMSCompositorTraits;
|
||||
|
||||
// Struct used to keep information about frames pending in
|
||||
// |rendering_frame_buffer_|.
|
||||
@@ -157,8 +151,6 @@ class MODULES_EXPORT WebMediaPlayerMSCompositor
|
||||
bool is_copy;
|
||||
};
|
||||
|
||||
- ~WebMediaPlayerMSCompositor() override;
|
||||
-
|
||||
// Ran on the |video_frame_compositor_task_runner_| to initialize
|
||||
// |submitter_|
|
||||
void InitializeSubmitter();
|
||||
@@ -204,7 +196,6 @@ class MODULES_EXPORT WebMediaPlayerMSCompositor
|
||||
|
||||
void StartRenderingInternal();
|
||||
void StopRenderingInternal();
|
||||
- void ReplaceCurrentFrameWithACopyInternal();
|
||||
|
||||
void SetAlgorithmEnabledForTesting(bool algorithm_enabled);
|
||||
void RecordFrameDisplayedStats(base::TimeTicks frame_displayed_time);
|
||||
@@ -314,15 +305,10 @@ class MODULES_EXPORT WebMediaPlayerMSCompositor
|
||||
// |dropped_frame_count_|, |current_metadata_| and |render_started_|.
|
||||
base::Lock current_frame_lock_;
|
||||
|
||||
+ base::WeakPtr<WebMediaPlayerMSCompositor> weak_this_;
|
||||
base::WeakPtrFactory<WebMediaPlayerMSCompositor> weak_ptr_factory_{this};
|
||||
};
|
||||
|
||||
-struct WebMediaPlayerMSCompositorTraits {
|
||||
- // Ensure destruction occurs on main thread so that "Web" and other resources
|
||||
- // are destroyed on the correct thread.
|
||||
- static void Destruct(const WebMediaPlayerMSCompositor* player);
|
||||
-};
|
||||
-
|
||||
} // namespace blink
|
||||
|
||||
#endif // THIRD_PARTY_BLINK_RENDERER_MODULES_MEDIASTREAM_WEBMEDIAPLAYER_MS_COMPOSITOR_H_
|
||||
@@ -0,0 +1,124 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Dale Curtis <dalecurtis@chromium.org>
|
||||
Date: Mon, 20 Feb 2023 10:08:49 +0000
|
||||
Subject: Simplify WebMediaPlayerMSCompositor destruction.
|
||||
|
||||
The code was only sometimes calling StopUsingProvider() and posted
|
||||
the submitter destruction unnecessarily.
|
||||
|
||||
Destruction now works the same as in VideoFrameCompositor, where the
|
||||
class itself is responsible for calling StopUsingProvider() during
|
||||
its own destruction.
|
||||
|
||||
(cherry picked from commit cbd238e85903b7d94910bd2c6362ff9abf9908cc)
|
||||
|
||||
Fixed: 1407701
|
||||
Disallow-Recycled-Builds: test-failures
|
||||
Change-Id: Ia649cb5532519468eea34e12745ed9c990580d82
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/4195824
|
||||
Auto-Submit: Dale Curtis <dalecurtis@chromium.org>
|
||||
Commit-Queue: Tony Herre <toprice@chromium.org>
|
||||
Cr-Original-Commit-Position: refs/heads/main@{#1098505}
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/4225498
|
||||
Reviewed-by: Oleh Lamzin <lamzin@google.com>
|
||||
Owners-Override: Oleh Lamzin <lamzin@google.com>
|
||||
Commit-Queue: Roger Felipe Zanoni da Silva <rzanoni@google.com>
|
||||
Cr-Commit-Position: refs/branch-heads/5359@{#1391}
|
||||
Cr-Branched-From: 27d3765d341b09369006d030f83f582a29eb57ae-refs/heads/main@{#1058933}
|
||||
|
||||
diff --git a/third_party/blink/renderer/modules/mediastream/webmediaplayer_ms.cc b/third_party/blink/renderer/modules/mediastream/webmediaplayer_ms.cc
|
||||
index 01b3e059e339341995deb9c27e248ab272acd1b2..e4eb2b0053384d3e89545928c22bc2e1a12580fa 100644
|
||||
--- a/third_party/blink/renderer/modules/mediastream/webmediaplayer_ms.cc
|
||||
+++ b/third_party/blink/renderer/modules/mediastream/webmediaplayer_ms.cc
|
||||
@@ -412,9 +412,6 @@ WebMediaPlayerMS::~WebMediaPlayerMS() {
|
||||
if (frame_deliverer_)
|
||||
io_task_runner_->DeleteSoon(FROM_HERE, frame_deliverer_.release());
|
||||
|
||||
- if (compositor_)
|
||||
- compositor_->StopUsingProvider();
|
||||
-
|
||||
if (video_frame_provider_)
|
||||
video_frame_provider_->Stop();
|
||||
|
||||
diff --git a/third_party/blink/renderer/modules/mediastream/webmediaplayer_ms_compositor.cc b/third_party/blink/renderer/modules/mediastream/webmediaplayer_ms_compositor.cc
|
||||
index 63957929facc933c23eef3fc200f140b73cb3f50..acbdf1c64f0efed4c665de270d712bf446eb2106 100644
|
||||
--- a/third_party/blink/renderer/modules/mediastream/webmediaplayer_ms_compositor.cc
|
||||
+++ b/third_party/blink/renderer/modules/mediastream/webmediaplayer_ms_compositor.cc
|
||||
@@ -238,13 +238,8 @@ WebMediaPlayerMSCompositor::WebMediaPlayerMSCompositor(
|
||||
WebMediaPlayerMSCompositor::~WebMediaPlayerMSCompositor() {
|
||||
// Ensured by destructor traits.
|
||||
DCHECK(video_frame_compositor_task_runner_->BelongsToCurrentThread());
|
||||
-
|
||||
- if (submitter_) {
|
||||
- video_frame_compositor_task_runner_->DeleteSoon(FROM_HERE,
|
||||
- std::move(submitter_));
|
||||
- } else {
|
||||
- DCHECK(!video_frame_provider_client_)
|
||||
- << "Must call StopUsingProvider() before dtor!";
|
||||
+ if (video_frame_provider_client_) {
|
||||
+ video_frame_provider_client_->StopUsingProvider();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -264,7 +259,7 @@ void WebMediaPlayerMSCompositorTraits::Destruct(
|
||||
|
||||
void WebMediaPlayerMSCompositor::InitializeSubmitter() {
|
||||
DCHECK(video_frame_compositor_task_runner_->BelongsToCurrentThread());
|
||||
- submitter_->Initialize(this, /* is_media_stream = */ true);
|
||||
+ submitter_->Initialize(this, /*is_media_stream=*/true);
|
||||
}
|
||||
|
||||
void WebMediaPlayerMSCompositor::SetIsSurfaceVisible(
|
||||
@@ -631,15 +626,6 @@ void WebMediaPlayerMSCompositor::ReplaceCurrentFrameWithACopy() {
|
||||
WrapRefCounted(this))));
|
||||
}
|
||||
|
||||
-void WebMediaPlayerMSCompositor::StopUsingProvider() {
|
||||
- DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
|
||||
- PostCrossThreadTask(
|
||||
- *video_frame_compositor_task_runner_, FROM_HERE,
|
||||
- CrossThreadBindOnce(
|
||||
- &WebMediaPlayerMSCompositor::StopUsingProviderInternal,
|
||||
- WrapRefCounted(this)));
|
||||
-}
|
||||
-
|
||||
bool WebMediaPlayerMSCompositor::MapTimestampsToRenderTimeTicks(
|
||||
const std::vector<base::TimeDelta>& timestamps,
|
||||
std::vector<base::TimeTicks>* wall_clock_times) {
|
||||
@@ -873,13 +859,6 @@ void WebMediaPlayerMSCompositor::StopRenderingInternal() {
|
||||
video_frame_provider_client_->StopRendering();
|
||||
}
|
||||
|
||||
-void WebMediaPlayerMSCompositor::StopUsingProviderInternal() {
|
||||
- DCHECK(video_frame_compositor_task_runner_->BelongsToCurrentThread());
|
||||
- if (video_frame_provider_client_)
|
||||
- video_frame_provider_client_->StopUsingProvider();
|
||||
- video_frame_provider_client_ = nullptr;
|
||||
-}
|
||||
-
|
||||
void WebMediaPlayerMSCompositor::ReplaceCurrentFrameWithACopyInternal() {
|
||||
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
|
||||
scoped_refptr<media::VideoFrame> current_frame_ref;
|
||||
diff --git a/third_party/blink/renderer/modules/mediastream/webmediaplayer_ms_compositor.h b/third_party/blink/renderer/modules/mediastream/webmediaplayer_ms_compositor.h
|
||||
index a82497399be7588298f4c740ef67e18ee429967d..ffeb448be295223f1f997b47eddff37d04bc8f16 100644
|
||||
--- a/third_party/blink/renderer/modules/mediastream/webmediaplayer_ms_compositor.h
|
||||
+++ b/third_party/blink/renderer/modules/mediastream/webmediaplayer_ms_compositor.h
|
||||
@@ -119,10 +119,6 @@ class MODULES_EXPORT WebMediaPlayerMSCompositor
|
||||
void StopRendering();
|
||||
void ReplaceCurrentFrameWithACopy();
|
||||
|
||||
- // Tell |video_frame_provider_client_| to stop using this instance in
|
||||
- // preparation for dtor.
|
||||
- void StopUsingProvider();
|
||||
-
|
||||
// Sets a hook to be notified when a new frame is presented, to fulfill a
|
||||
// prending video.requestAnimationFrame() request.
|
||||
// Can be called from any thread.
|
||||
@@ -208,7 +204,6 @@ class MODULES_EXPORT WebMediaPlayerMSCompositor
|
||||
|
||||
void StartRenderingInternal();
|
||||
void StopRenderingInternal();
|
||||
- void StopUsingProviderInternal();
|
||||
void ReplaceCurrentFrameWithACopyInternal();
|
||||
|
||||
void SetAlgorithmEnabledForTesting(bool algorithm_enabled);
|
||||
@@ -796,10 +796,10 @@ index 51a5497b809cda82b223138f43507172a9f066ae..71227492fd87e577518f3bf55ded37b0
|
||||
#if BUILDFLAG(ENABLE_PRINT_PREVIEW)
|
||||
// Set options for print preset from source PDF document.
|
||||
diff --git a/content/browser/BUILD.gn b/content/browser/BUILD.gn
|
||||
index 18328bedfdd0dc735126f7541ee7ed3e736d94b0..e5e28db9a970b49ac5624c59cbaeed9aff5e52d8 100644
|
||||
index a73daeeb4b6397db6fff9a9b552007204a376fb5..61454cd1b6e1c3c1d1ee1b901c499d9c802aec81 100644
|
||||
--- a/content/browser/BUILD.gn
|
||||
+++ b/content/browser/BUILD.gn
|
||||
@@ -2821,8 +2821,9 @@ source_set("browser") {
|
||||
@@ -2823,8 +2823,9 @@ source_set("browser") {
|
||||
"//ppapi/shared_impl",
|
||||
]
|
||||
|
||||
|
||||
@@ -9,3 +9,6 @@ fix_disable_implies_dcheck_for_node_stream_array_buffers.patch
|
||||
revert_runtime_dhceck_terminating_exception_in_microtasks.patch
|
||||
chore_disable_is_execution_terminating_dcheck.patch
|
||||
force_cppheapcreateparams_to_be_noncopyable.patch
|
||||
cherry-pick-e17eee4894be.patch
|
||||
cherry-pick-546e00df97ac.patch
|
||||
cherry-pick-f6ddbf42b1ea.patch
|
||||
|
||||
75
patches/v8/cherry-pick-546e00df97ac.patch
Normal file
75
patches/v8/cherry-pick-546e00df97ac.patch
Normal file
@@ -0,0 +1,75 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Joyee Cheung <joyee@igalia.com>
|
||||
Date: Tue, 14 Feb 2023 00:58:04 +0100
|
||||
Subject: Merged: [ic] store slow stubs for objects with access checks in
|
||||
DefineNamedIC
|
||||
|
||||
The CheckIfCanDefine() used to check the attributes of the object
|
||||
as well as reporting to access check failure callbacks can update
|
||||
the lookup iterator, resulting in wrong store handlers being
|
||||
installed. Restart the lookup iterator in this case to make
|
||||
sure that slow handlers are installed.
|
||||
|
||||
Bug: chromium:1415249
|
||||
(cherry picked from commit da2df213bc70437ef76f47e0ab6995fa45f8014a)
|
||||
|
||||
Change-Id: I92d60af7ea798d80b1115e63b7fce8e2e8026ed9
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/4290868
|
||||
Reviewed-by: Leszek Swirski <leszeks@chromium.org>
|
||||
Commit-Queue: Igor Sheludko <ishell@chromium.org>
|
||||
Cr-Commit-Position: refs/branch-heads/11.0@{#33}
|
||||
Cr-Branched-From: 06097c6f0c5af54fd5d6965d37027efb72decd4f-refs/heads/11.0.226@{#1}
|
||||
Cr-Branched-From: 6bf3344f5d9940de1ab253f1817dcb99c641c9d3-refs/heads/main@{#84857}
|
||||
|
||||
diff --git a/src/ic/ic.cc b/src/ic/ic.cc
|
||||
index ae1dde1a8c587dfc80a0a62e96b7bbfe6ba5eea5..fff21e90bad3451e2d942ec327cb02f394fecc46 100644
|
||||
--- a/src/ic/ic.cc
|
||||
+++ b/src/ic/ic.cc
|
||||
@@ -1818,6 +1818,11 @@ MaybeHandle<Object> StoreIC::Store(Handle<Object> object, Handle<Name> name,
|
||||
if (!can_define.FromJust()) {
|
||||
return isolate()->factory()->undefined_value();
|
||||
}
|
||||
+ // Restart the lookup iterator updated by CheckIfCanDefine() for
|
||||
+ // UpdateCaches() to handle access checks.
|
||||
+ if (use_ic && object->IsAccessCheckNeeded()) {
|
||||
+ it.Restart();
|
||||
+ }
|
||||
}
|
||||
|
||||
if (use_ic) {
|
||||
diff --git a/test/mjsunit/regress/regress-crbug-1415249.js b/test/mjsunit/regress/regress-crbug-1415249.js
|
||||
new file mode 100644
|
||||
index 0000000000000000000000000000000000000000..5715e0107a4b6e9dded9ca92c7b766c4cce0af72
|
||||
--- /dev/null
|
||||
+++ b/test/mjsunit/regress/regress-crbug-1415249.js
|
||||
@@ -0,0 +1,30 @@
|
||||
+// Copyright 2023 the V8 project authors. All rights reserved.
|
||||
+// Use of this source code is governed by a BSD-style license that can be
|
||||
+// found in the LICENSE file.
|
||||
+
|
||||
+// Flags: --always-turbofan
|
||||
+{
|
||||
+ const realm = Realm.createAllowCrossRealmAccess();
|
||||
+ const global = Realm.global(realm);
|
||||
+ function Base() { return global; }
|
||||
+ let i = 0;
|
||||
+ class Klass extends Base {
|
||||
+ field = i++;
|
||||
+ }
|
||||
+ let a = new Klass();
|
||||
+ assertEquals(a.field, 0);
|
||||
+ a = new Klass();
|
||||
+ assertEquals(a.field, 1);
|
||||
+}
|
||||
+
|
||||
+{
|
||||
+ const realm = Realm.create();
|
||||
+ const global = Realm.global(realm);
|
||||
+ function Base() { return global; }
|
||||
+ let i = 0;
|
||||
+ class Klass extends Base {
|
||||
+ field = i++;
|
||||
+ }
|
||||
+ assertThrows(() => new Klass(), Error, /no access/);
|
||||
+ assertThrows(() => new Klass(), Error, /no access/);
|
||||
+}
|
||||
171
patches/v8/cherry-pick-e17eee4894be.patch
Normal file
171
patches/v8/cherry-pick-e17eee4894be.patch
Normal file
@@ -0,0 +1,171 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Clemens Backes <clemensb@chromium.org>
|
||||
Date: Thu, 22 Dec 2022 09:43:42 +0100
|
||||
Subject: Fix printing of wasm-to-js frames
|
||||
|
||||
After https://crrev.com/c/3859787 those frames would be printed like
|
||||
standard Wasm frames, but in the place of the WasmInstanceObject, they
|
||||
have a WasmApiFunctionRef object instead.
|
||||
So special-case the {WasmToJsFrame::instance()} to load the instance
|
||||
properly. Also special-case the {position()} accessor for imported
|
||||
functions.
|
||||
|
||||
R=victorgomes@chromium.org
|
||||
|
||||
Bug: chromium:1402270
|
||||
Change-Id: I39805805a50e7a73d7d8075c63c46bdf5a373a33
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/4116778
|
||||
Reviewed-by: Nico Hartmann <nicohartmann@chromium.org>
|
||||
Commit-Queue: Clemens Backes <clemensb@chromium.org>
|
||||
Reviewed-by: Victor Gomes <victorgomes@chromium.org>
|
||||
Cr-Commit-Position: refs/heads/main@{#84993}
|
||||
|
||||
diff --git a/src/compiler/backend/arm/code-generator-arm.cc b/src/compiler/backend/arm/code-generator-arm.cc
|
||||
index 4c5accd7a8f352a128499861d5d28a6d9b859f1a..d8a77d70bbd465035ee91dbc57058f83ccf7cf83 100644
|
||||
--- a/src/compiler/backend/arm/code-generator-arm.cc
|
||||
+++ b/src/compiler/backend/arm/code-generator-arm.cc
|
||||
@@ -3699,6 +3699,10 @@ void CodeGenerator::AssembleConstructFrame() {
|
||||
if (call_descriptor->IsWasmFunctionCall() ||
|
||||
call_descriptor->IsWasmImportWrapper() ||
|
||||
call_descriptor->IsWasmCapiFunction()) {
|
||||
+ // For import wrappers and C-API functions, this stack slot is only used
|
||||
+ // for printing stack traces in V8. Also, it holds a WasmApiFunctionRef
|
||||
+ // instead of the instance itself, which is taken care of in the frames
|
||||
+ // accessors.
|
||||
__ Push(kWasmInstanceRegister);
|
||||
}
|
||||
if (call_descriptor->IsWasmCapiFunction()) {
|
||||
diff --git a/src/compiler/backend/arm64/code-generator-arm64.cc b/src/compiler/backend/arm64/code-generator-arm64.cc
|
||||
index 60d19c79307529f13f64a1f5c41295d720f31dde..8ad2c88c12763106d7d279372d7f36933755f1e0 100644
|
||||
--- a/src/compiler/backend/arm64/code-generator-arm64.cc
|
||||
+++ b/src/compiler/backend/arm64/code-generator-arm64.cc
|
||||
@@ -3225,6 +3225,9 @@ void CodeGenerator::AssembleConstructFrame() {
|
||||
Register scratch = temps.AcquireX();
|
||||
__ Mov(scratch,
|
||||
StackFrame::TypeToMarker(info()->GetOutputStackFrameType()));
|
||||
+ // This stack slot is only used for printing stack traces in V8. Also,
|
||||
+ // it holds a WasmApiFunctionRef instead of the instance itself, which
|
||||
+ // is taken care of in the frames accessors.
|
||||
__ Push(scratch, kWasmInstanceRegister);
|
||||
int extra_slots =
|
||||
call_descriptor->kind() == CallDescriptor::kCallWasmImportWrapper
|
||||
diff --git a/src/compiler/backend/ia32/code-generator-ia32.cc b/src/compiler/backend/ia32/code-generator-ia32.cc
|
||||
index 5afd119ff506ddd07f719d539ad6e9592f967201..d13310cfcc244ea2c61766a9960dbab29779bf52 100644
|
||||
--- a/src/compiler/backend/ia32/code-generator-ia32.cc
|
||||
+++ b/src/compiler/backend/ia32/code-generator-ia32.cc
|
||||
@@ -4026,6 +4026,10 @@ void CodeGenerator::AssembleConstructFrame() {
|
||||
if (call_descriptor->IsWasmFunctionCall() ||
|
||||
call_descriptor->IsWasmImportWrapper() ||
|
||||
call_descriptor->IsWasmCapiFunction()) {
|
||||
+ // For import wrappers and C-API functions, this stack slot is only used
|
||||
+ // for printing stack traces in V8. Also, it holds a WasmApiFunctionRef
|
||||
+ // instead of the instance itself, which is taken care of in the frames
|
||||
+ // accessors.
|
||||
__ push(kWasmInstanceRegister);
|
||||
}
|
||||
if (call_descriptor->IsWasmCapiFunction()) {
|
||||
diff --git a/src/compiler/backend/x64/code-generator-x64.cc b/src/compiler/backend/x64/code-generator-x64.cc
|
||||
index e3f759f570050c183d133854f83d02d9b442d8f9..0e02c63ace62caf2fcb5642db82d0c07af2cc2ba 100644
|
||||
--- a/src/compiler/backend/x64/code-generator-x64.cc
|
||||
+++ b/src/compiler/backend/x64/code-generator-x64.cc
|
||||
@@ -4841,10 +4841,10 @@ void CodeGenerator::AssembleConstructFrame() {
|
||||
if (call_descriptor->IsWasmFunctionCall() ||
|
||||
call_descriptor->IsWasmImportWrapper() ||
|
||||
call_descriptor->IsWasmCapiFunction()) {
|
||||
- // We do not use this stack value in import wrappers and capi functions.
|
||||
- // We push it anyway to satisfy legacy assumptions about these frames'
|
||||
- // size and order.
|
||||
- // TODO(manoskouk): Consider fixing this.
|
||||
+ // For import wrappers and C-API functions, this stack slot is only used
|
||||
+ // for printing stack traces in V8. Also, it holds a WasmApiFunctionRef
|
||||
+ // instead of the instance itself, which is taken care of in the frames
|
||||
+ // accessors.
|
||||
__ pushq(kWasmInstanceRegister);
|
||||
}
|
||||
if (call_descriptor->IsWasmCapiFunction()) {
|
||||
diff --git a/src/diagnostics/objects-printer.cc b/src/diagnostics/objects-printer.cc
|
||||
index ce4d15b2c27e145be7e8dd2b98f1519ed11ce2f6..71604afa7a067e14a891057de4011416f45f4f19 100644
|
||||
--- a/src/diagnostics/objects-printer.cc
|
||||
+++ b/src/diagnostics/objects-printer.cc
|
||||
@@ -2137,6 +2137,7 @@ void WasmApiFunctionRef::WasmApiFunctionRefPrint(std::ostream& os) {
|
||||
os << "\n - isolate_root: " << reinterpret_cast<void*>(isolate_root());
|
||||
os << "\n - native_context: " << Brief(native_context());
|
||||
os << "\n - callable: " << Brief(callable());
|
||||
+ os << "\n - instance: " << Brief(instance());
|
||||
os << "\n - suspend: " << suspend();
|
||||
os << "\n";
|
||||
}
|
||||
diff --git a/src/execution/frames.cc b/src/execution/frames.cc
|
||||
index 0ca10a21e190f5113e0a84687ae6fa1d2882d3ee..c18ce06a87f94431c503997913e9c1993e6be804 100644
|
||||
--- a/src/execution/frames.cc
|
||||
+++ b/src/execution/frames.cc
|
||||
@@ -2500,7 +2500,7 @@ void WasmFrame::Print(StringStream* accumulator, PrintMode mode,
|
||||
return;
|
||||
}
|
||||
wasm::WasmCodeRefScope code_ref_scope;
|
||||
- accumulator->Add("Wasm [");
|
||||
+ accumulator->Add(is_wasm_to_js() ? "Wasm-to-JS [" : "Wasm [");
|
||||
accumulator->PrintName(script().name());
|
||||
Address instruction_start = wasm_code()->instruction_start();
|
||||
base::Vector<const uint8_t> raw_func_name =
|
||||
@@ -2631,6 +2631,15 @@ void WasmDebugBreakFrame::Print(StringStream* accumulator, PrintMode mode,
|
||||
if (mode != OVERVIEW) accumulator->Add("\n");
|
||||
}
|
||||
|
||||
+WasmInstanceObject WasmToJsFrame::wasm_instance() const {
|
||||
+ // WasmToJsFrames hold the {WasmApiFunctionRef} object in the instance slot.
|
||||
+ // Load the instance from there.
|
||||
+ const int offset = WasmFrameConstants::kWasmInstanceOffset;
|
||||
+ Object func_ref_obj(Memory<Address>(fp() + offset));
|
||||
+ WasmApiFunctionRef func_ref = WasmApiFunctionRef::cast(func_ref_obj);
|
||||
+ return WasmInstanceObject::cast(func_ref.instance());
|
||||
+}
|
||||
+
|
||||
void JsToWasmFrame::Iterate(RootVisitor* v) const {
|
||||
CodeLookupResult lookup_result = GetContainingCode(isolate(), pc());
|
||||
CHECK(lookup_result.IsFound());
|
||||
diff --git a/src/execution/frames.h b/src/execution/frames.h
|
||||
index c72b7acef4b532fec8c55b698711a4897b1494c9..f6cf5360ce94fe62ce9076abb929b42e13c60b6a 100644
|
||||
--- a/src/execution/frames.h
|
||||
+++ b/src/execution/frames.h
|
||||
@@ -1035,7 +1035,7 @@ class WasmFrame : public TypedFrame {
|
||||
void Iterate(RootVisitor* v) const override;
|
||||
|
||||
// Accessors.
|
||||
- V8_EXPORT_PRIVATE WasmInstanceObject wasm_instance() const;
|
||||
+ virtual V8_EXPORT_PRIVATE WasmInstanceObject wasm_instance() const;
|
||||
V8_EXPORT_PRIVATE wasm::NativeModule* native_module() const;
|
||||
wasm::WasmCode* wasm_code() const;
|
||||
int function_index() const;
|
||||
@@ -1101,6 +1101,9 @@ class WasmToJsFrame : public WasmFrame {
|
||||
public:
|
||||
Type type() const override { return WASM_TO_JS; }
|
||||
|
||||
+ int position() const override { return 0; }
|
||||
+ WasmInstanceObject wasm_instance() const override;
|
||||
+
|
||||
protected:
|
||||
inline explicit WasmToJsFrame(StackFrameIteratorBase* iterator);
|
||||
|
||||
diff --git a/test/mjsunit/regress/asm/regress-1402270.js b/test/mjsunit/regress/asm/regress-1402270.js
|
||||
new file mode 100644
|
||||
index 0000000000000000000000000000000000000000..77badd768f6f502ee3bacec73049f25cd8af40b7
|
||||
--- /dev/null
|
||||
+++ b/test/mjsunit/regress/asm/regress-1402270.js
|
||||
@@ -0,0 +1,16 @@
|
||||
+// Copyright 2022 the V8 project authors. All rights reserved.
|
||||
+// Use of this source code is governed by a BSD-style license that can be
|
||||
+// found in the LICENSE file.
|
||||
+
|
||||
+function print_stack(unused_arg) {
|
||||
+ console.trace();
|
||||
+}
|
||||
+function asm(_, imports) {
|
||||
+ 'use asm';
|
||||
+ var print_stack = imports.print_stack;
|
||||
+ function f() {
|
||||
+ print_stack(1);
|
||||
+ }
|
||||
+ return f;
|
||||
+}
|
||||
+asm({}, {'print_stack': print_stack})();
|
||||
109
patches/v8/cherry-pick-f6ddbf42b1ea.patch
Normal file
109
patches/v8/cherry-pick-f6ddbf42b1ea.patch
Normal file
@@ -0,0 +1,109 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Tobias Tebbi <tebbi@chromium.org>
|
||||
Date: Wed, 15 Feb 2023 16:35:18 +0100
|
||||
Subject: check if maps become deprecated during optimization
|
||||
|
||||
(cherry picked from commit f82d802a20aa62e42269f977302f26c5c3ed031b)
|
||||
|
||||
Bug: chromium:1417585
|
||||
No-Try: true
|
||||
No-Presubmit: true
|
||||
No-Tree-Checks: true
|
||||
Change-Id: Ie8eb76d2afb3ee4be66cf5d1c4bff8f745dc145b
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/4255648
|
||||
Commit-Queue: Tobias Tebbi <tebbi@chromium.org>
|
||||
Cr-Original-Commit-Position: refs/heads/main@{#85848}
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/4294983
|
||||
Reviewed-by: Tobias Tebbi <tebbi@chromium.org>
|
||||
Reviewed-by: Achuith Bhandarkar <achuith@chromium.org>
|
||||
Commit-Queue: Roger Felipe Zanoni da Silva <rzanoni@google.com>
|
||||
Reviewed-by: Leszek Swirski <leszeks@chromium.org>
|
||||
Cr-Commit-Position: refs/branch-heads/10.8@{#50}
|
||||
Cr-Branched-From: f1bc03fd6b4c201abd9f0fd9d51fb989150f97b9-refs/heads/10.8.168@{#1}
|
||||
Cr-Branched-From: 237de893e1c0a0628a57d0f5797483d3add7f005-refs/heads/main@{#83672}
|
||||
|
||||
diff --git a/src/codegen/bailout-reason.h b/src/codegen/bailout-reason.h
|
||||
index cdd9e123185d142dfeac1e422f345a6a5955658f..33a12a67e4464a907124bb2f45a224f43ed7ec3a 100644
|
||||
--- a/src/codegen/bailout-reason.h
|
||||
+++ b/src/codegen/bailout-reason.h
|
||||
@@ -94,19 +94,20 @@ namespace internal {
|
||||
V(kUnexpectedThreadInWasmSet, "thread_in_wasm flag was already set") \
|
||||
V(kUnexpectedThreadInWasmUnset, "thread_in_wasm flag was not set")
|
||||
|
||||
-#define BAILOUT_MESSAGES_LIST(V) \
|
||||
- V(kNoReason, "no reason") \
|
||||
- \
|
||||
- V(kBailedOutDueToDependencyChange, "Bailed out due to dependency change") \
|
||||
- V(kCodeGenerationFailed, "Code generation failed") \
|
||||
- V(kFunctionBeingDebugged, "Function is being debugged") \
|
||||
- V(kGraphBuildingFailed, "Optimized graph construction failed") \
|
||||
- V(kFunctionTooBig, "Function is too big to be optimized") \
|
||||
- V(kTooManyArguments, "Function contains a call with too many arguments") \
|
||||
- V(kLiveEdit, "LiveEdit") \
|
||||
- V(kNativeFunctionLiteral, "Native function literal") \
|
||||
- V(kOptimizationDisabled, "Optimization disabled") \
|
||||
- V(kHigherTierAvailable, "A higher tier is already available") \
|
||||
+#define BAILOUT_MESSAGES_LIST(V) \
|
||||
+ V(kNoReason, "no reason") \
|
||||
+ \
|
||||
+ V(kBailedOutDueToDependencyChange, "Bailed out due to dependency change") \
|
||||
+ V(kConcurrentMapDeprecation, "Maps became deprecated during optimization") \
|
||||
+ V(kCodeGenerationFailed, "Code generation failed") \
|
||||
+ V(kFunctionBeingDebugged, "Function is being debugged") \
|
||||
+ V(kGraphBuildingFailed, "Optimized graph construction failed") \
|
||||
+ V(kFunctionTooBig, "Function is too big to be optimized") \
|
||||
+ V(kTooManyArguments, "Function contains a call with too many arguments") \
|
||||
+ V(kLiveEdit, "LiveEdit") \
|
||||
+ V(kNativeFunctionLiteral, "Native function literal") \
|
||||
+ V(kOptimizationDisabled, "Optimization disabled") \
|
||||
+ V(kHigherTierAvailable, "A higher tier is already available") \
|
||||
V(kNeverOptimize, "Optimization is always disabled")
|
||||
|
||||
#define ERROR_MESSAGES_CONSTANTS(C, T) C,
|
||||
diff --git a/src/compiler/pipeline.cc b/src/compiler/pipeline.cc
|
||||
index a142d46a4760d65b09419211afa0972e1f5e6205..7e066adf0a0d04ca332e6b04a253937e51b1d367 100644
|
||||
--- a/src/compiler/pipeline.cc
|
||||
+++ b/src/compiler/pipeline.cc
|
||||
@@ -728,7 +728,10 @@ class PipelineImpl final {
|
||||
// Step D. Run the code finalization pass.
|
||||
MaybeHandle<Code> FinalizeCode(bool retire_broker = true);
|
||||
|
||||
- // Step E. Install any code dependencies.
|
||||
+ // Step E. Ensure all embedded maps are non-deprecated.
|
||||
+ bool CheckNoDeprecatedMaps(Handle<Code> code);
|
||||
+
|
||||
+ // Step F. Install any code dependencies.
|
||||
bool CommitDependencies(Handle<Code> code);
|
||||
|
||||
void VerifyGeneratedCodeIsIdempotent();
|
||||
@@ -1272,6 +1275,9 @@ PipelineCompilationJob::Status PipelineCompilationJob::FinalizeJobImpl(
|
||||
}
|
||||
return FAILED;
|
||||
}
|
||||
+ if (!pipeline_.CheckNoDeprecatedMaps(code)) {
|
||||
+ return RetryOptimization(BailoutReason::kConcurrentMapDeprecation);
|
||||
+ }
|
||||
if (!pipeline_.CommitDependencies(code)) {
|
||||
return RetryOptimization(BailoutReason::kBailedOutDueToDependencyChange);
|
||||
}
|
||||
@@ -3961,6 +3967,20 @@ MaybeHandle<Code> PipelineImpl::GenerateCode(CallDescriptor* call_descriptor) {
|
||||
return FinalizeCode();
|
||||
}
|
||||
|
||||
+// We must not embed deprecated maps, as we rely in the compiler on all explicit
|
||||
+// maps not being deprecated.
|
||||
+bool PipelineImpl::CheckNoDeprecatedMaps(Handle<Code> code) {
|
||||
+ int mode_mask = RelocInfo::EmbeddedObjectModeMask();
|
||||
+ for (RelocIterator it(*code, mode_mask); !it.done(); it.next()) {
|
||||
+ DCHECK(RelocInfo::IsEmbeddedObjectMode(it.rinfo()->rmode()));
|
||||
+ HeapObject obj = it.rinfo()->target_object(data_->isolate());
|
||||
+ if (obj.IsMap() && Map::cast(obj).is_deprecated()) {
|
||||
+ return false;
|
||||
+ }
|
||||
+ }
|
||||
+ return true;
|
||||
+}
|
||||
+
|
||||
bool PipelineImpl::CommitDependencies(Handle<Code> code) {
|
||||
return data_->dependencies() == nullptr ||
|
||||
data_->dependencies()->Commit(code);
|
||||
@@ -0,0 +1,2 @@
|
||||
cherry-pick-e0efbd45ea74.patch
|
||||
cherry-pick-218b56e51638.patch
|
||||
|
||||
60
patches/webrtc/cherry-pick-218b56e51638.patch
Normal file
60
patches/webrtc/cherry-pick-218b56e51638.patch
Normal file
@@ -0,0 +1,60 @@
|
||||
From 218b56e516386cd57c7513197528c3124bcd7ef3 Mon Sep 17 00:00:00 2001
|
||||
From: Alexander Cooper <alcooper@chromium.org>
|
||||
Date: Wed, 08 Feb 2023 14:16:01 -0800
|
||||
Subject: [PATCH] Fix Destruction inside WGC Callback
|
||||
|
||||
If we are notified of the destruction of the window before a
|
||||
CaptureFrame call can fail, then we may end up attempting to destroy the
|
||||
underlying WGC object inside it's own event handler. This can be
|
||||
problematic, as the class itself may want to run other code. Instead,
|
||||
we just unsubscribe and signal that any future CaptureFrame calls should
|
||||
reject.
|
||||
|
||||
This also removes setting "is_capture_started_=false" in the item closed
|
||||
handler, as all that served to do is cause the WgcCapturerWin code to
|
||||
attempt to restart the capturer, and somewhat muddies up our metrics.
|
||||
|
||||
(cherry picked from commit 318cf28945d80a0ac6f09382e507c95e649cc4c1)
|
||||
|
||||
Bug: chromium:1413005
|
||||
No-Try: True
|
||||
Change-Id: Ibccb7a2e7ce531ba80b4b331b9bc2cda0ff75f4e
|
||||
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/292762
|
||||
Auto-Submit: Alexander Cooper <alcooper@chromium.org>
|
||||
Reviewed-by: Mark Foltz <mfoltz@chromium.org>
|
||||
Commit-Queue: Mark Foltz <mfoltz@chromium.org>
|
||||
Commit-Queue: Alexander Cooper <alcooper@chromium.org>
|
||||
Cr-Original-Commit-Position: refs/heads/main@{#39275}
|
||||
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/293246
|
||||
Bot-Commit: rubber-stamper@appspot.gserviceaccount.com <rubber-stamper@appspot.gserviceaccount.com>
|
||||
Cr-Commit-Position: refs/branch-heads/5481@{#5}
|
||||
Cr-Branched-From: 2e1a9a4ae0234d4b1ea7a6fd4188afa1fb20379d-refs/heads/main@{#38901}
|
||||
---
|
||||
|
||||
diff --git a/modules/desktop_capture/win/wgc_capture_session.cc b/modules/desktop_capture/win/wgc_capture_session.cc
|
||||
index e165291..ea5565c 100644
|
||||
--- a/modules/desktop_capture/win/wgc_capture_session.cc
|
||||
+++ b/modules/desktop_capture/win/wgc_capture_session.cc
|
||||
@@ -397,17 +397,14 @@
|
||||
|
||||
RTC_LOG(LS_INFO) << "Capture target has been closed.";
|
||||
item_closed_ = true;
|
||||
- is_capture_started_ = false;
|
||||
|
||||
RemoveEventHandlers();
|
||||
|
||||
- mapped_texture_ = nullptr;
|
||||
- session_ = nullptr;
|
||||
- frame_pool_ = nullptr;
|
||||
- direct3d_device_ = nullptr;
|
||||
- item_ = nullptr;
|
||||
- d3d11_device_ = nullptr;
|
||||
-
|
||||
+ // Do not attempt to free resources in the OnItemClosed handler, as this
|
||||
+ // causes a race where we try to delete the item that is calling us. Removing
|
||||
+ // the event handlers and setting `item_closed_` above is sufficient to ensure
|
||||
+ // that the resources are no longer used, and the next time the capturer tries
|
||||
+ // to get a frame, we will report a permanent failure and be destroyed.
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
57
patches/webrtc/cherry-pick-e0efbd45ea74.patch
Normal file
57
patches/webrtc/cherry-pick-e0efbd45ea74.patch
Normal file
@@ -0,0 +1,57 @@
|
||||
From e0efbd45ea7421fb944c7343254ac5dc22bee541 Mon Sep 17 00:00:00 2001
|
||||
From: Henrik Boström <hbos@webrtc.org>
|
||||
Date: Fri, 20 Jan 2023 10:48:31 +0100
|
||||
Subject: [PATCH] [Merge-110] [Stats] Handle the case of missing certificates.
|
||||
|
||||
Certificates being missing is a sign of a bug (e.g. webrtc:14844, to be
|
||||
fixed separately) which is why we have a DCHECK. But this DCHECK does
|
||||
not protect against accessing the invalid iterator if it is a release
|
||||
build. This CL makes that safe.
|
||||
|
||||
# Mobile bots not running properly
|
||||
NOTRY=True
|
||||
|
||||
(cherry picked from commit 124d7c3fe5bdc79a355c9df02d07f25331631a68)
|
||||
|
||||
Bug: chromium:1408392
|
||||
Change-Id: I97a82786028e41c58ef8ef15002c3f959bbec7f1
|
||||
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/291109
|
||||
Reviewed-by: Mirko Bonadei <mbonadei@webrtc.org>
|
||||
Commit-Queue: Henrik Boström <hbos@webrtc.org>
|
||||
Cr-Original-Commit-Position: refs/heads/main@{#39159}
|
||||
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/291380
|
||||
Cr-Commit-Position: refs/branch-heads/5481@{#2}
|
||||
Cr-Branched-From: 2e1a9a4ae0234d4b1ea7a6fd4188afa1fb20379d-refs/heads/main@{#38901}
|
||||
---
|
||||
|
||||
diff --git a/pc/rtc_stats_collector.cc b/pc/rtc_stats_collector.cc
|
||||
index d500a7b..1d88566 100644
|
||||
--- a/pc/rtc_stats_collector.cc
|
||||
+++ b/pc/rtc_stats_collector.cc
|
||||
@@ -2192,16 +2192,17 @@
|
||||
// exist.
|
||||
const auto& certificate_stats_it =
|
||||
transport_cert_stats.find(transport_name);
|
||||
+ std::string local_certificate_id, remote_certificate_id;
|
||||
RTC_DCHECK(certificate_stats_it != transport_cert_stats.cend());
|
||||
- std::string local_certificate_id;
|
||||
- if (certificate_stats_it->second.local) {
|
||||
- local_certificate_id = RTCCertificateIDFromFingerprint(
|
||||
- certificate_stats_it->second.local->fingerprint);
|
||||
- }
|
||||
- std::string remote_certificate_id;
|
||||
- if (certificate_stats_it->second.remote) {
|
||||
- remote_certificate_id = RTCCertificateIDFromFingerprint(
|
||||
- certificate_stats_it->second.remote->fingerprint);
|
||||
+ if (certificate_stats_it != transport_cert_stats.cend()) {
|
||||
+ if (certificate_stats_it->second.local) {
|
||||
+ local_certificate_id = RTCCertificateIDFromFingerprint(
|
||||
+ certificate_stats_it->second.local->fingerprint);
|
||||
+ }
|
||||
+ if (certificate_stats_it->second.remote) {
|
||||
+ remote_certificate_id = RTCCertificateIDFromFingerprint(
|
||||
+ certificate_stats_it->second.remote->fingerprint);
|
||||
+ }
|
||||
}
|
||||
|
||||
// There is one transport stats for each channel.
|
||||
@@ -21,6 +21,10 @@ def run_node_configure(target_cpu):
|
||||
# Work around "No acceptable ASM compiler found" error on some System,
|
||||
# it breaks nothing since Electron does not use OpenSSL.
|
||||
args += ['--openssl-no-asm']
|
||||
|
||||
# Enable whole-program optimization for electron native modules.
|
||||
if sys.platform == "win32":
|
||||
args += ['--with-ltcg']
|
||||
subprocess.check_call([sys.executable, configure] + args)
|
||||
|
||||
def read_node_config_gypi():
|
||||
|
||||
@@ -14,8 +14,8 @@ const ROLLER_BRANCH_PATTERN = /^roller\/chromium$/;
|
||||
|
||||
const DEFAULT_BUILD_CLOUD_ID = '1598';
|
||||
const DEFAULT_BUILD_CLOUD = 'electronhq-16-core';
|
||||
const DEFAULT_BAKE_BASE_IMAGE = 'Windows_Default_Appveyor';
|
||||
const DEFAULT_BUILD_IMAGE = 'Windows_Default_Appveyor';
|
||||
const DEFAULT_BAKE_BASE_IMAGE = 'e-111.0.5560.0-node18';
|
||||
const DEFAULT_BUILD_IMAGE = 'e-111.0.5560.0-node18';
|
||||
|
||||
const appveyorBakeJob = 'electron-bake-image';
|
||||
const appVeyorJobs = {
|
||||
|
||||
@@ -13,6 +13,7 @@ const fs = require('fs');
|
||||
const { execSync } = require('child_process');
|
||||
const got = require('got');
|
||||
const path = require('path');
|
||||
const semver = require('semver');
|
||||
const temp = require('temp').track();
|
||||
const { URL } = require('url');
|
||||
const { BlobServiceClient } = require('@azure/storage-blob');
|
||||
@@ -317,12 +318,20 @@ function saveShaSumFile (checksums, fileName) {
|
||||
}
|
||||
|
||||
async function publishRelease (release) {
|
||||
const currentLatest = await octokit.repos.getLatestRelease({
|
||||
owner: 'electron',
|
||||
repo: targetRepo
|
||||
});
|
||||
|
||||
const makeLatest = !release.prerelease && semver.gte(release.tag_name, currentLatest.data.tag_name);
|
||||
|
||||
return octokit.repos.updateRelease({
|
||||
owner: 'electron',
|
||||
repo: targetRepo,
|
||||
release_id: release.id,
|
||||
tag_name: release.tag_name,
|
||||
draft: false
|
||||
draft: false,
|
||||
make_latest: makeLatest ? 'true' : 'false'
|
||||
}).catch(err => {
|
||||
console.log(`${fail} Error publishing release:`, err);
|
||||
process.exit(1);
|
||||
|
||||
@@ -56,7 +56,8 @@ REM Install Windows SDK
|
||||
choco install windows-sdk-10-version-2104-all
|
||||
|
||||
REM Install nodejs python git and yarn needed dependencies
|
||||
choco install -y nodejs-lts python2 git yarn
|
||||
choco install -y --force nodejs --version=18.12.1
|
||||
choco install -y python2 git yarn
|
||||
choco install python --version 3.7.9
|
||||
call C:\ProgramData\chocolatey\bin\RefreshEnv.cmd
|
||||
SET PATH=C:\Python27\;C:\Python27\Scripts;C:\Python39\;C:\Python39\Scripts;%PATH%
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
#!/usr/bin/env node
|
||||
|
||||
const { ElectronVersions, Installer } = require('@electron/fiddle-core');
|
||||
const childProcess = require('child_process');
|
||||
const crypto = require('crypto');
|
||||
const fs = require('fs-extra');
|
||||
@@ -12,7 +13,7 @@ const pass = '✓'.green;
|
||||
const fail = '✗'.red;
|
||||
|
||||
const args = require('minimist')(process.argv, {
|
||||
string: ['runners', 'target'],
|
||||
string: ['runners', 'target', 'electronVersion'],
|
||||
boolean: ['buildNativeTests'],
|
||||
unknown: arg => unknownFlags.push(arg)
|
||||
});
|
||||
@@ -39,6 +40,15 @@ const runners = new Map([
|
||||
|
||||
const specHashPath = path.resolve(__dirname, '../spec/.hash');
|
||||
|
||||
if (args.electronVersion) {
|
||||
if (args.runners && args.runners !== 'main') {
|
||||
console.log(`${fail} only 'main' runner can be used with --electronVersion`);
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
args.runners = 'main';
|
||||
}
|
||||
|
||||
let runnersToRun = null;
|
||||
if (args.runners !== undefined) {
|
||||
runnersToRun = args.runners.split(',').filter(value => value);
|
||||
@@ -52,6 +62,14 @@ if (args.runners !== undefined) {
|
||||
}
|
||||
|
||||
async function main () {
|
||||
if (args.electronVersion) {
|
||||
const versions = await ElectronVersions.create();
|
||||
if (!versions.isVersion(args.electronVersion)) {
|
||||
console.log(`${fail} '${args.electronVersion}' is not a recognized Electron version`);
|
||||
process.exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
const [lastSpecHash, lastSpecInstallHash] = loadLastSpecHash();
|
||||
const [currentSpecHash, currentSpecInstallHash] = await getSpecHash();
|
||||
const somethingChanged = (currentSpecHash !== lastSpecHash) ||
|
||||
@@ -122,7 +140,13 @@ async function runElectronTests () {
|
||||
}
|
||||
|
||||
async function runTestUsingElectron (specDir, testName) {
|
||||
let exe = path.resolve(BASE, utils.getElectronExec());
|
||||
let exe;
|
||||
if (args.electronVersion) {
|
||||
const installer = new Installer();
|
||||
exe = await installer.install(args.electronVersion);
|
||||
} else {
|
||||
exe = path.resolve(BASE, utils.getElectronExec());
|
||||
}
|
||||
const runnerArgs = [`electron/${specDir}`, ...unknownArgs.slice(2)];
|
||||
if (process.platform === 'linux') {
|
||||
runnerArgs.unshift(path.resolve(__dirname, 'dbus_mock.py'), exe);
|
||||
@@ -212,14 +236,20 @@ async function installSpecModules (dir) {
|
||||
// but don't clobber any other CXXFLAGS that were passed into spec-runner.js
|
||||
const CXXFLAGS = ['-std=c++17', process.env.CXXFLAGS].filter(x => !!x).join(' ');
|
||||
|
||||
const nodeDir = path.resolve(BASE, `out/${utils.getOutDir({ shouldLog: true })}/gen/node_headers`);
|
||||
const env = {
|
||||
...process.env,
|
||||
CXXFLAGS,
|
||||
npm_config_nodedir: nodeDir,
|
||||
npm_config_msvs_version: '2019',
|
||||
npm_config_yes: 'true'
|
||||
};
|
||||
if (args.electronVersion) {
|
||||
env.npm_config_target = args.electronVersion;
|
||||
env.npm_config_disturl = 'https://electronjs.org/headers';
|
||||
env.npm_config_runtime = 'electron';
|
||||
env.npm_config_build_from_source = 'true';
|
||||
} else {
|
||||
env.npm_config_nodedir = path.resolve(BASE, `out/${utils.getOutDir({ shouldLog: true })}/gen/node_headers`);
|
||||
}
|
||||
if (fs.existsSync(path.resolve(dir, 'node_modules'))) {
|
||||
await fs.remove(path.resolve(dir, 'node_modules'));
|
||||
}
|
||||
|
||||
@@ -15,7 +15,6 @@
|
||||
#include "base/strings/sys_string_conversions.h"
|
||||
#include "content/common/mac_helpers.h"
|
||||
#include "content/public/common/content_paths.h"
|
||||
#include "ppapi/buildflags/buildflags.h"
|
||||
#include "shell/browser/mac/electron_application.h"
|
||||
#include "shell/common/application_info.h"
|
||||
#include "shell/common/mac/main_application_bundle.h"
|
||||
@@ -41,11 +40,9 @@ base::FilePath GetHelperAppPath(const base::FilePath& frameworks_path,
|
||||
} else if (base::EndsWith(path.value(), content::kMacHelperSuffix_gpu,
|
||||
base::CompareCase::SENSITIVE)) {
|
||||
helper_name += content::kMacHelperSuffix_gpu;
|
||||
#if BUILDFLAG(ENABLE_PLUGINS)
|
||||
} else if (base::EndsWith(path.value(), content::kMacHelperSuffix_plugin,
|
||||
base::CompareCase::SENSITIVE)) {
|
||||
helper_name += content::kMacHelperSuffix_plugin;
|
||||
#endif
|
||||
}
|
||||
|
||||
return frameworks_path.Append(name + " " + helper_name + ".app")
|
||||
|
||||
@@ -246,37 +246,9 @@ int NodeMain(int argc, char* argv[]) {
|
||||
v8::HandleScope scope(isolate);
|
||||
node::LoadEnvironment(env, node::StartExecutionCallback{});
|
||||
|
||||
env->set_trace_sync_io(env->options()->trace_sync_io);
|
||||
|
||||
{
|
||||
v8::SealHandleScope seal(isolate);
|
||||
bool more;
|
||||
env->performance_state()->Mark(
|
||||
node::performance::NODE_PERFORMANCE_MILESTONE_LOOP_START);
|
||||
do {
|
||||
uv_run(env->event_loop(), UV_RUN_DEFAULT);
|
||||
|
||||
gin_env.platform()->DrainTasks(isolate);
|
||||
|
||||
more = uv_loop_alive(env->event_loop());
|
||||
if (more && !env->is_stopping())
|
||||
continue;
|
||||
|
||||
if (!uv_loop_alive(env->event_loop())) {
|
||||
EmitBeforeExit(env);
|
||||
}
|
||||
|
||||
// Emit `beforeExit` if the loop became alive either after emitting
|
||||
// event, or after running some callbacks.
|
||||
more = uv_loop_alive(env->event_loop());
|
||||
} while (more && !env->is_stopping());
|
||||
env->performance_state()->Mark(
|
||||
node::performance::NODE_PERFORMANCE_MILESTONE_LOOP_EXIT);
|
||||
}
|
||||
|
||||
env->set_trace_sync_io(false);
|
||||
|
||||
exit_code = node::EmitExit(env);
|
||||
// Potential reasons we get Nothing here may include: the env
|
||||
// is stopping, or the user hooks process.emit('exit').
|
||||
exit_code = node::SpinEventLoop(env).FromMaybe(1);
|
||||
|
||||
node::ResetStdio();
|
||||
|
||||
|
||||
@@ -881,6 +881,16 @@ gfx::Point BaseWindow::GetTrafficLightPosition() const {
|
||||
}
|
||||
#endif
|
||||
|
||||
#if BUILDFLAG(IS_MAC)
|
||||
bool BaseWindow::IsHiddenInMissionControl() {
|
||||
return window_->IsHiddenInMissionControl();
|
||||
}
|
||||
|
||||
void BaseWindow::SetHiddenInMissionControl(bool hidden) {
|
||||
window_->SetHiddenInMissionControl(hidden);
|
||||
}
|
||||
#endif
|
||||
|
||||
void BaseWindow::SetTouchBar(
|
||||
std::vector<gin_helper::PersistentDictionary> items) {
|
||||
window_->SetTouchBar(std::move(items));
|
||||
@@ -1256,6 +1266,14 @@ void BaseWindow::BuildPrototype(v8::Isolate* isolate,
|
||||
.SetMethod("getTrafficLightPosition",
|
||||
&BaseWindow::GetTrafficLightPosition)
|
||||
#endif
|
||||
|
||||
#if BUILDFLAG(IS_MAC)
|
||||
.SetMethod("isHiddenInMissionControl",
|
||||
&BaseWindow::IsHiddenInMissionControl)
|
||||
.SetMethod("setHiddenInMissionControl",
|
||||
&BaseWindow::SetHiddenInMissionControl)
|
||||
#endif
|
||||
|
||||
.SetMethod("_setTouchBarItems", &BaseWindow::SetTouchBar)
|
||||
.SetMethod("_refreshTouchBarItem", &BaseWindow::RefreshTouchBarItem)
|
||||
.SetMethod("_setEscapeTouchBarItem", &BaseWindow::SetEscapeTouchBarItem)
|
||||
|
||||
@@ -198,6 +198,11 @@ class BaseWindow : public gin_helper::TrackableObject<BaseWindow>,
|
||||
gfx::Point GetTrafficLightPosition() const;
|
||||
#endif
|
||||
|
||||
#if BUILDFLAG(IS_MAC)
|
||||
bool IsHiddenInMissionControl();
|
||||
void SetHiddenInMissionControl(bool hidden);
|
||||
#endif
|
||||
|
||||
void SetTouchBar(std::vector<gin_helper::PersistentDictionary> items);
|
||||
void RefreshTouchBarItem(const std::string& item_id);
|
||||
void SetEscapeTouchBarItem(gin_helper::PersistentDictionary item);
|
||||
|
||||
@@ -127,7 +127,6 @@ BrowserWindow::~BrowserWindow() {
|
||||
api_web_contents_->RemoveObserver(this);
|
||||
// Destroy the WebContents.
|
||||
OnCloseContents();
|
||||
api_web_contents_->Destroy();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -155,6 +154,7 @@ void BrowserWindow::WebContentsDestroyed() {
|
||||
|
||||
void BrowserWindow::OnCloseContents() {
|
||||
BaseWindow::ResetBrowserViews();
|
||||
api_web_contents_->Destroy();
|
||||
}
|
||||
|
||||
void BrowserWindow::OnRendererResponsive(content::RenderProcessHost*) {
|
||||
|
||||
@@ -128,10 +128,10 @@ bool MatchesCookie(const base::Value::Dict& filter,
|
||||
!MatchesDomain(*str, cookie.Domain()))
|
||||
return false;
|
||||
absl::optional<bool> secure_filter = filter.FindBool("secure");
|
||||
if (secure_filter && *secure_filter == cookie.IsSecure())
|
||||
if (secure_filter && *secure_filter != cookie.IsSecure())
|
||||
return false;
|
||||
absl::optional<bool> session_filter = filter.FindBool("session");
|
||||
if (session_filter && *session_filter != !cookie.IsPersistent())
|
||||
if (session_filter && *session_filter == cookie.IsPersistent())
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
@@ -177,7 +177,7 @@ std::string InclusionStatusToString(net::CookieInclusionStatus status) {
|
||||
return "Failed to parse cookie";
|
||||
if (status.HasExclusionReason(
|
||||
net::CookieInclusionStatus::EXCLUDE_INVALID_DOMAIN))
|
||||
return "Failed to get cookie domain";
|
||||
return "Failed to set cookie with an invalid domain attribute";
|
||||
if (status.HasExclusionReason(
|
||||
net::CookieInclusionStatus::EXCLUDE_INVALID_PREFIX))
|
||||
return "Failed because the cookie violated prefix rules.";
|
||||
@@ -315,19 +315,24 @@ v8::Local<v8::Promise> Cookies::Set(v8::Isolate* isolate,
|
||||
return handle;
|
||||
}
|
||||
|
||||
net::CookieInclusionStatus status;
|
||||
auto canonical_cookie = net::CanonicalCookie::CreateSanitizedCookie(
|
||||
url, name ? *name : "", value ? *value : "", domain ? *domain : "",
|
||||
path ? *path : "", ParseTimeProperty(details.FindDouble("creationDate")),
|
||||
ParseTimeProperty(details.FindDouble("expirationDate")),
|
||||
ParseTimeProperty(details.FindDouble("lastAccessDate")), secure,
|
||||
http_only, same_site, net::COOKIE_PRIORITY_DEFAULT, same_party,
|
||||
absl::nullopt);
|
||||
absl::nullopt, &status);
|
||||
|
||||
if (!canonical_cookie || !canonical_cookie->IsCanonical()) {
|
||||
promise.RejectWithErrorMessage(
|
||||
InclusionStatusToString(net::CookieInclusionStatus(
|
||||
net::CookieInclusionStatus::EXCLUDE_FAILURE_TO_STORE)));
|
||||
promise.RejectWithErrorMessage(InclusionStatusToString(
|
||||
!status.IsInclude()
|
||||
? status
|
||||
: net::CookieInclusionStatus(
|
||||
net::CookieInclusionStatus::EXCLUDE_FAILURE_TO_STORE)));
|
||||
return handle;
|
||||
}
|
||||
|
||||
net::CookieOptions options;
|
||||
if (http_only) {
|
||||
options.set_include_httponly();
|
||||
|
||||
@@ -1221,7 +1221,9 @@ void WebContents::CloseContents(content::WebContents* source) {
|
||||
for (ExtendedWebContentsObserver& observer : observers_)
|
||||
observer.OnCloseContents();
|
||||
|
||||
Destroy();
|
||||
// If there are observers, OnCloseContents will call Destroy()
|
||||
if (observers_.empty())
|
||||
Destroy();
|
||||
}
|
||||
|
||||
void WebContents::ActivateContents(content::WebContents* source) {
|
||||
@@ -1520,13 +1522,15 @@ void WebContents::HandleNewRenderFrame(
|
||||
// Set the background color of RenderWidgetHostView.
|
||||
auto* web_preferences = WebContentsPreferences::From(web_contents());
|
||||
if (web_preferences) {
|
||||
absl::optional<SkColor> maybe_color = web_preferences->GetBackgroundColor();
|
||||
web_contents()->SetPageBaseBackgroundColor(maybe_color);
|
||||
|
||||
auto maybe_color = web_preferences->GetBackgroundColor();
|
||||
bool guest = IsGuest() || type_ == Type::kBrowserView;
|
||||
SkColor color =
|
||||
|
||||
// If webPreferences has no color stored we need to explicitly set guest
|
||||
// webContents background color to transparent.
|
||||
auto bg_color =
|
||||
maybe_color.value_or(guest ? SK_ColorTRANSPARENT : SK_ColorWHITE);
|
||||
SetBackgroundColor(rwhv, color);
|
||||
web_contents()->SetPageBaseBackgroundColor(bg_color);
|
||||
SetBackgroundColor(rwhv, bg_color);
|
||||
}
|
||||
|
||||
if (!background_throttling_)
|
||||
@@ -3524,18 +3528,26 @@ v8::Local<v8::Promise> WebContents::TakeHeapSnapshot(
|
||||
base::File file(file_path,
|
||||
base::File::FLAG_CREATE_ALWAYS | base::File::FLAG_WRITE);
|
||||
if (!file.IsValid()) {
|
||||
promise.RejectWithErrorMessage("takeHeapSnapshot failed");
|
||||
promise.RejectWithErrorMessage(
|
||||
"Failed to take heap snapshot with invalid file path " +
|
||||
#if BUILDFLAG(IS_WIN)
|
||||
base::WideToUTF8(file_path.value()));
|
||||
#else
|
||||
file_path.value());
|
||||
#endif
|
||||
return handle;
|
||||
}
|
||||
|
||||
auto* frame_host = web_contents()->GetPrimaryMainFrame();
|
||||
if (!frame_host) {
|
||||
promise.RejectWithErrorMessage("takeHeapSnapshot failed");
|
||||
promise.RejectWithErrorMessage(
|
||||
"Failed to take heap snapshot with invalid webContents main frame");
|
||||
return handle;
|
||||
}
|
||||
|
||||
if (!frame_host->IsRenderFrameLive()) {
|
||||
promise.RejectWithErrorMessage("takeHeapSnapshot failed");
|
||||
promise.RejectWithErrorMessage(
|
||||
"Failed to take heap snapshot with nonexistent render frame");
|
||||
return handle;
|
||||
}
|
||||
|
||||
@@ -3555,7 +3567,7 @@ v8::Local<v8::Promise> WebContents::TakeHeapSnapshot(
|
||||
if (success) {
|
||||
promise.Resolve();
|
||||
} else {
|
||||
promise.RejectWithErrorMessage("takeHeapSnapshot failed");
|
||||
promise.RejectWithErrorMessage("Failed to take heap snapshot");
|
||||
}
|
||||
},
|
||||
base::Owned(std::move(electron_renderer)), std::move(promise)));
|
||||
|
||||
@@ -120,10 +120,6 @@
|
||||
#include "ui/native_theme/native_theme.h"
|
||||
#include "v8/include/v8.h"
|
||||
|
||||
#if BUILDFLAG(IS_WIN)
|
||||
#include "sandbox/win/src/sandbox_policy.h"
|
||||
#endif
|
||||
|
||||
#if BUILDFLAG(USE_NSS_CERTS)
|
||||
#include "net/ssl/client_cert_store_nss.h"
|
||||
#elif BUILDFLAG(IS_WIN)
|
||||
@@ -475,15 +471,10 @@ void ElectronBrowserClient::AppendExtraCommandLineSwitches(
|
||||
content::ChildProcessHost::CHILD_RENDERER);
|
||||
auto gpu_child_path = content::ChildProcessHost::GetChildPath(
|
||||
content::ChildProcessHost::CHILD_GPU);
|
||||
#if BUILDFLAG(ENABLE_PLUGINS)
|
||||
auto plugin_child_path = content::ChildProcessHost::GetChildPath(
|
||||
content::ChildProcessHost::CHILD_PLUGIN);
|
||||
#endif
|
||||
if (program != renderer_child_path && program != gpu_child_path
|
||||
#if BUILDFLAG(ENABLE_PLUGINS)
|
||||
&& program != plugin_child_path
|
||||
#endif
|
||||
) {
|
||||
if (program != renderer_child_path && program != gpu_child_path &&
|
||||
program != plugin_child_path) {
|
||||
child_path = content::ChildProcessHost::GetChildPath(
|
||||
content::ChildProcessHost::CHILD_NORMAL);
|
||||
CHECK_EQ(program, child_path)
|
||||
@@ -1464,19 +1455,6 @@ void ElectronBrowserClient::OverrideURLLoaderFactoryParams(
|
||||
browser_context, origin, is_for_isolated_world, factory_params);
|
||||
}
|
||||
|
||||
#if BUILDFLAG(IS_WIN)
|
||||
bool ElectronBrowserClient::PreSpawnChild(sandbox::TargetPolicy* policy,
|
||||
sandbox::mojom::Sandbox sandbox_type,
|
||||
ChildSpawnFlags flags) {
|
||||
sandbox::ResultCode result = policy->GetConfig()->AddRule(
|
||||
sandbox::SubSystem::kFiles, sandbox::Semantics::kFilesAllowAny,
|
||||
L"\\??\\pipe\\crashpad_*");
|
||||
if (result != sandbox::SBOX_ALL_OK)
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
#endif // BUILDFLAG(IS_WIN)
|
||||
|
||||
void ElectronBrowserClient::
|
||||
RegisterAssociatedInterfaceBindersForRenderFrameHost(
|
||||
content::RenderFrameHost&
|
||||
|
||||
@@ -245,11 +245,6 @@ class ElectronBrowserClient : public content::ContentBrowserClient,
|
||||
const url::Origin& origin,
|
||||
bool is_for_isolated_world,
|
||||
network::mojom::URLLoaderFactoryParams* factory_params) override;
|
||||
#if BUILDFLAG(IS_WIN)
|
||||
bool PreSpawnChild(sandbox::TargetPolicy* policy,
|
||||
sandbox::mojom::Sandbox sandbox_type,
|
||||
ChildSpawnFlags flags) override;
|
||||
#endif
|
||||
void RegisterAssociatedInterfaceBindersForRenderFrameHost(
|
||||
content::RenderFrameHost& render_frame_host,
|
||||
blink::AssociatedInterfaceRegistry& associated_registry) override;
|
||||
|
||||
@@ -279,7 +279,7 @@ void ElectronBrowserMainParts::PostEarlyInitialization() {
|
||||
env->set_trace_sync_io(env->options()->trace_sync_io);
|
||||
|
||||
// We do not want to crash the main process on unhandled rejections.
|
||||
env->options()->unhandled_rejections = "warn";
|
||||
env->options()->unhandled_rejections = "warn-with-error-code";
|
||||
|
||||
// Add Electron extended APIs.
|
||||
electron_bindings_->BindTo(js_env_->isolate(), env->process_object());
|
||||
|
||||
@@ -193,6 +193,18 @@ inline void dispatch_sync_main(dispatch_block_t block) {
|
||||
return [super accessibilitySetValue:value forAttribute:attribute];
|
||||
}
|
||||
|
||||
- (NSAccessibilityRole)accessibilityRole {
|
||||
// For non-VoiceOver AT, such as Voice Control, Apple recommends turning on
|
||||
// a11y when an AT accesses the 'accessibilityRole' property. This function
|
||||
// is accessed frequently so we only change the accessibility state when
|
||||
// accessibility is disabled.
|
||||
auto* ax_state = content::BrowserAccessibilityState::GetInstance();
|
||||
if (!ax_state->GetAccessibilityMode().has_mode(ui::kAXModeBasic.mode())) {
|
||||
ax_state->AddAccessibilityModeFlags(ui::kAXModeBasic);
|
||||
}
|
||||
return [super accessibilityRole];
|
||||
}
|
||||
|
||||
- (void)orderFrontStandardAboutPanel:(id)sender {
|
||||
electron::Browser::Get()->ShowAboutPanel();
|
||||
}
|
||||
|
||||
@@ -172,7 +172,11 @@ void NativeWindow::InitFromOptions(const gin_helper::Dictionary& options) {
|
||||
int max_width = max_size.width() > 0 ? max_size.width() : INT_MAX;
|
||||
int max_height = max_size.height() > 0 ? max_size.height() : INT_MAX;
|
||||
bool have_max_width = options.Get(options::kMaxWidth, &max_width);
|
||||
if (have_max_width && max_width <= 0)
|
||||
max_width = INT_MAX;
|
||||
bool have_max_height = options.Get(options::kMaxHeight, &max_height);
|
||||
if (have_max_height && max_height <= 0)
|
||||
max_height = INT_MAX;
|
||||
|
||||
// By default the window has a default maximum size that prevents it
|
||||
// from being resized larger than the screen, so we should only set this
|
||||
|
||||
@@ -219,6 +219,12 @@ class NativeWindow : public base::SupportsUserData,
|
||||
virtual void UpdateFrame() = 0;
|
||||
#endif
|
||||
|
||||
// whether windows should be ignored by mission control
|
||||
#if BUILDFLAG(IS_MAC)
|
||||
virtual bool IsHiddenInMissionControl() = 0;
|
||||
virtual void SetHiddenInMissionControl(bool hidden) = 0;
|
||||
#endif
|
||||
|
||||
// Touchbar API
|
||||
virtual void SetTouchBar(std::vector<gin_helper::PersistentDictionary> items);
|
||||
virtual void RefreshTouchBarItem(const std::string& item_id);
|
||||
|
||||
@@ -102,6 +102,8 @@ class NativeWindowMac : public NativeWindow,
|
||||
void SetDocumentEdited(bool edited) override;
|
||||
bool IsDocumentEdited() override;
|
||||
void SetIgnoreMouseEvents(bool ignore, bool forward) override;
|
||||
bool IsHiddenInMissionControl() override;
|
||||
void SetHiddenInMissionControl(bool hidden) override;
|
||||
void SetContentProtection(bool enable) override;
|
||||
void SetFocusable(bool focusable) override;
|
||||
bool IsFocusable() override;
|
||||
|
||||
@@ -22,6 +22,7 @@
|
||||
#include "content/public/browser/browser_task_traits.h"
|
||||
#include "content/public/browser/browser_thread.h"
|
||||
#include "content/public/browser/desktop_media_id.h"
|
||||
#include "shell/browser/browser.h"
|
||||
#include "shell/browser/javascript_environment.h"
|
||||
#include "shell/browser/native_browser_view_mac.h"
|
||||
#include "shell/browser/ui/cocoa/electron_native_widget_mac.h"
|
||||
@@ -280,6 +281,9 @@ NativeWindowMac::NativeWindowMac(const gin_helper::Dictionary& options,
|
||||
std::string windowType;
|
||||
options.Get(options::kType, &windowType);
|
||||
|
||||
bool hiddenInMissionControl = false;
|
||||
options.Get(options::kHiddenInMissionControl, &hiddenInMissionControl);
|
||||
|
||||
bool useStandardWindow = true;
|
||||
// eventually deprecate separate "standardWindow" option in favor of
|
||||
// standard / textured window types
|
||||
@@ -418,6 +422,8 @@ NativeWindowMac::NativeWindowMac(const gin_helper::Dictionary& options,
|
||||
options.Get(options::kDisableAutoHideCursor, &disableAutoHideCursor);
|
||||
[window_ setDisableAutoHideCursor:disableAutoHideCursor];
|
||||
|
||||
SetHiddenInMissionControl(hiddenInMissionControl);
|
||||
|
||||
// Set maximizable state last to ensure zoom button does not get reset
|
||||
// by calls to other APIs.
|
||||
SetMaximizable(maximizable);
|
||||
@@ -1159,9 +1165,17 @@ bool NativeWindowMac::IsDocumentEdited() {
|
||||
return [window_ isDocumentEdited];
|
||||
}
|
||||
|
||||
bool NativeWindowMac::IsHiddenInMissionControl() {
|
||||
NSUInteger collectionBehavior = [window_ collectionBehavior];
|
||||
return collectionBehavior & NSWindowCollectionBehaviorTransient;
|
||||
}
|
||||
|
||||
void NativeWindowMac::SetHiddenInMissionControl(bool hidden) {
|
||||
SetCollectionBehavior(hidden, NSWindowCollectionBehaviorTransient);
|
||||
}
|
||||
|
||||
void NativeWindowMac::SetIgnoreMouseEvents(bool ignore, bool forward) {
|
||||
[window_ setIgnoresMouseEvents:ignore];
|
||||
|
||||
if (!ignore) {
|
||||
SetForwardMouseMessages(NO);
|
||||
} else {
|
||||
@@ -1335,18 +1349,15 @@ void NativeWindowMac::SetOverlayIcon(const gfx::Image& overlay,
|
||||
void NativeWindowMac::SetVisibleOnAllWorkspaces(bool visible,
|
||||
bool visibleOnFullScreen,
|
||||
bool skipTransformProcessType) {
|
||||
// In order for NSWindows to be visible on fullscreen we need to functionally
|
||||
// mimic app.dock.hide() since Apple changed the underlying functionality of
|
||||
// In order for NSWindows to be visible on fullscreen we need to invoke
|
||||
// app.dock.hide() since Apple changed the underlying functionality of
|
||||
// NSWindows starting with 10.14 to disallow NSWindows from floating on top of
|
||||
// fullscreen apps.
|
||||
if (!skipTransformProcessType) {
|
||||
ProcessSerialNumber psn = {0, kCurrentProcess};
|
||||
if (visibleOnFullScreen) {
|
||||
[window_ setCanHide:NO];
|
||||
TransformProcessType(&psn, kProcessTransformToUIElementApplication);
|
||||
Browser::Get()->DockHide();
|
||||
} else {
|
||||
[window_ setCanHide:YES];
|
||||
TransformProcessType(&psn, kProcessTransformToForegroundApplication);
|
||||
Browser::Get()->DockShow(JavascriptEnvironment::GetIsolate());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -58,7 +58,11 @@ void CocoaNotification::Show(const NotificationOptions& options) {
|
||||
[notification_ setSoundName:base::SysUTF16ToNSString(options.sound)];
|
||||
}
|
||||
|
||||
[notification_ setHasActionButton:false];
|
||||
if (options.has_reply) {
|
||||
[notification_ setHasReplyButton:true];
|
||||
[notification_ setResponsePlaceholder:base::SysUTF16ToNSString(
|
||||
options.reply_placeholder)];
|
||||
}
|
||||
|
||||
int i = 0;
|
||||
action_index_ = UINT_MAX;
|
||||
@@ -66,7 +70,10 @@ void CocoaNotification::Show(const NotificationOptions& options) {
|
||||
[[[NSMutableArray alloc] init] autorelease];
|
||||
for (const auto& action : options.actions) {
|
||||
if (action.type == u"button") {
|
||||
if (action_index_ == UINT_MAX) {
|
||||
// If the notification has both a reply and actions,
|
||||
// the reply takes precedence and the actions all
|
||||
// become additional actions.
|
||||
if (!options.has_reply && action_index_ == UINT_MAX) {
|
||||
// First button observed is the displayed action
|
||||
[notification_ setHasActionButton:true];
|
||||
[notification_
|
||||
@@ -86,16 +93,11 @@ void CocoaNotification::Show(const NotificationOptions& options) {
|
||||
}
|
||||
i++;
|
||||
}
|
||||
|
||||
if ([additionalActions count] > 0) {
|
||||
[notification_ setAdditionalActions:additionalActions];
|
||||
}
|
||||
|
||||
if (options.has_reply) {
|
||||
[notification_ setResponsePlaceholder:base::SysUTF16ToNSString(
|
||||
options.reply_placeholder)];
|
||||
[notification_ setHasReplyButton:true];
|
||||
}
|
||||
|
||||
if (!options.close_button_text.empty()) {
|
||||
[notification_ setOtherButtonTitle:base::SysUTF16ToNSString(
|
||||
options.close_button_text)];
|
||||
|
||||
@@ -185,12 +185,10 @@ int ScopedDisableResize::disable_resize_ = 0;
|
||||
}
|
||||
|
||||
- (void)beginPreviewPanelControl:(QLPreviewPanel*)panel {
|
||||
panel.delegate = [self delegate];
|
||||
panel.dataSource = static_cast<id<QLPreviewPanelDataSource>>([self delegate]);
|
||||
}
|
||||
|
||||
- (void)endPreviewPanelControl:(QLPreviewPanel*)panel {
|
||||
panel.delegate = nil;
|
||||
panel.dataSource = nil;
|
||||
}
|
||||
|
||||
|
||||
@@ -128,16 +128,17 @@ using FullScreenTransitionState =
|
||||
- (NSSize)windowWillResize:(NSWindow*)sender toSize:(NSSize)frameSize {
|
||||
NSSize newSize = frameSize;
|
||||
double aspectRatio = shell_->GetAspectRatio();
|
||||
NSWindow* window = shell_->GetNativeWindow().GetNativeNSWindow();
|
||||
|
||||
if (aspectRatio > 0.0) {
|
||||
gfx::Size windowSize = shell_->GetSize();
|
||||
gfx::Size contentSize = shell_->GetContentSize();
|
||||
gfx::Size extraSize = shell_->GetAspectRatioExtraSize();
|
||||
|
||||
double titleBarHeight = windowSize.height() - contentSize.height();
|
||||
double extraWidthPlusFrame =
|
||||
windowSize.width() - contentSize.width() + extraSize.width();
|
||||
double extraHeightPlusFrame =
|
||||
windowSize.height() - contentSize.height() + extraSize.height();
|
||||
double extraHeightPlusFrame = titleBarHeight + extraSize.height();
|
||||
|
||||
newSize.width =
|
||||
roundf((frameSize.height - extraHeightPlusFrame) * aspectRatio +
|
||||
@@ -145,10 +146,44 @@ using FullScreenTransitionState =
|
||||
newSize.height =
|
||||
roundf((newSize.width - extraWidthPlusFrame) / aspectRatio +
|
||||
extraHeightPlusFrame);
|
||||
|
||||
// Clamp to minimum width/height while ensuring aspect ratio remains.
|
||||
NSSize minSize = [window minSize];
|
||||
NSSize zeroSize =
|
||||
shell_->has_frame() ? NSMakeSize(0, titleBarHeight) : NSZeroSize;
|
||||
if (!NSEqualSizes(minSize, zeroSize)) {
|
||||
double minWidthForAspectRatio =
|
||||
(minSize.height - titleBarHeight) * aspectRatio;
|
||||
bool atMinHeight =
|
||||
minSize.height > zeroSize.height && newSize.height <= minSize.height;
|
||||
newSize.width = atMinHeight ? minWidthForAspectRatio
|
||||
: std::max(newSize.width, minSize.width);
|
||||
|
||||
double minHeightForAspectRatio = minSize.width / aspectRatio;
|
||||
bool atMinWidth =
|
||||
minSize.width > zeroSize.width && newSize.width <= minSize.width;
|
||||
newSize.height = atMinWidth ? minHeightForAspectRatio
|
||||
: std::max(newSize.height, minSize.height);
|
||||
}
|
||||
|
||||
// Clamp to maximum width/height while ensuring aspect ratio remains.
|
||||
NSSize maxSize = [window maxSize];
|
||||
if (!NSEqualSizes(maxSize, NSMakeSize(FLT_MAX, FLT_MAX))) {
|
||||
double maxWidthForAspectRatio = maxSize.height * aspectRatio;
|
||||
bool atMaxHeight =
|
||||
maxSize.height < FLT_MAX && newSize.height >= maxSize.height;
|
||||
newSize.width = atMaxHeight ? maxWidthForAspectRatio
|
||||
: std::min(newSize.width, maxSize.width);
|
||||
|
||||
double maxHeightForAspectRatio = maxSize.width / aspectRatio;
|
||||
bool atMaxWidth =
|
||||
maxSize.width < FLT_MAX && newSize.width >= maxSize.width;
|
||||
newSize.height = atMaxWidth ? maxHeightForAspectRatio
|
||||
: std::min(newSize.height, maxSize.height);
|
||||
}
|
||||
}
|
||||
|
||||
if (!resizingHorizontally_) {
|
||||
NSWindow* window = shell_->GetNativeWindow().GetNativeNSWindow();
|
||||
const auto widthDelta = frameSize.width - [window frame].size.width;
|
||||
const auto heightDelta = frameSize.height - [window frame].size.height;
|
||||
resizingHorizontally_ = std::abs(widthDelta) > std::abs(heightDelta);
|
||||
|
||||
70
shell/browser/ui/gtk/menu_gtk.cc
Normal file
70
shell/browser/ui/gtk/menu_gtk.cc
Normal file
@@ -0,0 +1,70 @@
|
||||
// Copyright 2014 The Chromium Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#include "shell/browser/ui/gtk/menu_gtk.h"
|
||||
|
||||
#include <gtk/gtk.h>
|
||||
|
||||
#include "shell/browser/ui/gtk/menu_util.h"
|
||||
#include "ui/base/models/menu_model.h"
|
||||
|
||||
namespace electron {
|
||||
|
||||
namespace gtkui {
|
||||
|
||||
MenuGtk::MenuGtk(ui::MenuModel* model)
|
||||
: menu_model_(model), gtk_menu_(TakeGObject(gtk_menu_new())) {
|
||||
if (menu_model_) {
|
||||
BuildSubmenuFromModel(menu_model_, gtk_menu_,
|
||||
G_CALLBACK(OnMenuItemActivatedThunk),
|
||||
&block_activation_, this);
|
||||
Refresh();
|
||||
}
|
||||
}
|
||||
|
||||
MenuGtk::~MenuGtk() {
|
||||
gtk_widget_destroy(gtk_menu_);
|
||||
}
|
||||
|
||||
void MenuGtk::Refresh() {
|
||||
gtk_container_foreach(GTK_CONTAINER(gtk_menu_.get()), SetMenuItemInfo,
|
||||
&block_activation_);
|
||||
}
|
||||
|
||||
GtkMenu* MenuGtk::GetGtkMenu() {
|
||||
return GTK_MENU(gtk_menu_.get());
|
||||
}
|
||||
|
||||
void MenuGtk::OnMenuItemActivated(GtkWidget* menu_item) {
|
||||
if (block_activation_)
|
||||
return;
|
||||
|
||||
ui::MenuModel* model = ModelForMenuItem(GTK_MENU_ITEM(menu_item));
|
||||
if (!model) {
|
||||
// There won't be a model for "native" submenus like the "Input Methods"
|
||||
// context menu. We don't need to handle activation messages for submenus
|
||||
// anyway, so we can just return here.
|
||||
DCHECK(gtk_menu_item_get_submenu(GTK_MENU_ITEM(menu_item)));
|
||||
return;
|
||||
}
|
||||
|
||||
// The activate signal is sent to radio items as they get deselected;
|
||||
// ignore it in this case.
|
||||
if (GTK_IS_RADIO_MENU_ITEM(menu_item) &&
|
||||
!gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(menu_item))) {
|
||||
return;
|
||||
}
|
||||
|
||||
int id;
|
||||
if (!GetMenuItemID(menu_item, &id))
|
||||
return;
|
||||
|
||||
// The menu item can still be activated by hotkeys even if it is disabled.
|
||||
if (model->IsEnabledAt(id))
|
||||
ExecuteCommand(model, id);
|
||||
}
|
||||
|
||||
} // namespace gtkui
|
||||
|
||||
} // namespace electron
|
||||
48
shell/browser/ui/gtk/menu_gtk.h
Normal file
48
shell/browser/ui/gtk/menu_gtk.h
Normal file
@@ -0,0 +1,48 @@
|
||||
// Copyright 2014 The Chromium Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#ifndef ELECTRON_SHELL_BROWSER_UI_GTK_MENU_GTK_H_
|
||||
#define ELECTRON_SHELL_BROWSER_UI_GTK_MENU_GTK_H_
|
||||
|
||||
#include "base/callback.h"
|
||||
#include "base/memory/raw_ptr.h"
|
||||
#include "ui/base/glib/glib_signal.h"
|
||||
#include "ui/base/glib/scoped_gobject.h"
|
||||
|
||||
typedef struct _GtkMenu GtkMenu;
|
||||
typedef struct _GtkWidget GtkWidget;
|
||||
|
||||
namespace ui {
|
||||
class MenuModel;
|
||||
}
|
||||
|
||||
namespace electron {
|
||||
|
||||
namespace gtkui {
|
||||
|
||||
class MenuGtk {
|
||||
public:
|
||||
explicit MenuGtk(ui::MenuModel* model);
|
||||
virtual ~MenuGtk();
|
||||
|
||||
// Refreshes all the menu item labels and menu item checked/enabled states.
|
||||
void Refresh();
|
||||
|
||||
GtkMenu* GetGtkMenu();
|
||||
|
||||
private:
|
||||
// Callback for when a menu item is activated.
|
||||
CHROMEG_CALLBACK_0(MenuGtk, void, OnMenuItemActivated, GtkWidget*);
|
||||
|
||||
raw_ptr<ui::MenuModel> menu_model_; // not owned
|
||||
ScopedGObject<GtkWidget> gtk_menu_;
|
||||
|
||||
bool block_activation_ = false;
|
||||
};
|
||||
|
||||
} // namespace gtkui
|
||||
|
||||
} // namespace electron
|
||||
|
||||
#endif // ELECTRON_SHELL_BROWSER_UI_GTK_MENU_GTK_H_
|
||||
68
shell/browser/ui/status_icon_gtk.cc
Normal file
68
shell/browser/ui/status_icon_gtk.cc
Normal file
@@ -0,0 +1,68 @@
|
||||
// Copyright (c) 2023 Microsoft, Inc.
|
||||
// Copyright (c) 2011 The Chromium Authors.
|
||||
// Use of this source code is governed by the MIT license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#include "shell/browser/ui/status_icon_gtk.h"
|
||||
|
||||
#include <gtk/gtk.h>
|
||||
|
||||
#include "base/strings/utf_string_conversions.h"
|
||||
#include "shell/browser/ui/gtk/menu_gtk.h"
|
||||
#include "shell/browser/ui/gtk_util.h"
|
||||
#include "ui/gfx/image/image_skia.h"
|
||||
|
||||
namespace electron {
|
||||
|
||||
StatusIconGtk::StatusIconGtk() : icon_(TakeGObject(gtk_status_icon_new())) {
|
||||
g_signal_connect(icon_, "activate", G_CALLBACK(OnClickThunk), this);
|
||||
g_signal_connect(icon_, "popup_menu", G_CALLBACK(OnContextMenuRequestedThunk),
|
||||
this);
|
||||
}
|
||||
|
||||
StatusIconGtk::~StatusIconGtk() = default;
|
||||
|
||||
void StatusIconGtk::SetIcon(const gfx::ImageSkia& image) {
|
||||
if (image.isNull())
|
||||
return;
|
||||
|
||||
GdkPixbuf* pixbuf = gtk_util::GdkPixbufFromSkBitmap(*image.bitmap());
|
||||
gtk_status_icon_set_from_pixbuf(icon_, pixbuf);
|
||||
g_object_unref(pixbuf);
|
||||
}
|
||||
|
||||
void StatusIconGtk::SetToolTip(const std::u16string& tool_tip) {
|
||||
gtk_status_icon_set_tooltip_text(icon_, base::UTF16ToUTF8(tool_tip).c_str());
|
||||
}
|
||||
|
||||
void StatusIconGtk::UpdatePlatformContextMenu(ui::MenuModel* model) {
|
||||
if (model)
|
||||
menu_ = std::make_unique<gtkui::MenuGtk>(model);
|
||||
}
|
||||
|
||||
void StatusIconGtk::RefreshPlatformContextMenu() {
|
||||
if (menu_)
|
||||
menu_->Refresh();
|
||||
}
|
||||
|
||||
void StatusIconGtk::OnSetDelegate() {
|
||||
SetIcon(delegate_->GetImage());
|
||||
SetToolTip(delegate_->GetToolTip());
|
||||
UpdatePlatformContextMenu(delegate_->GetMenuModel());
|
||||
gtk_status_icon_set_visible(icon_, TRUE);
|
||||
}
|
||||
|
||||
void StatusIconGtk::OnClick(GtkStatusIcon* status_icon) {
|
||||
delegate_->OnClick();
|
||||
}
|
||||
|
||||
void StatusIconGtk::OnContextMenuRequested(GtkStatusIcon* status_icon,
|
||||
guint button,
|
||||
guint32 activate_time) {
|
||||
if (menu_.get()) {
|
||||
gtk_menu_popup(menu_->GetGtkMenu(), nullptr, nullptr,
|
||||
gtk_status_icon_position_menu, icon_, button, activate_time);
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace electron
|
||||
52
shell/browser/ui/status_icon_gtk.h
Normal file
52
shell/browser/ui/status_icon_gtk.h
Normal file
@@ -0,0 +1,52 @@
|
||||
// Copyright (c) 2023 Microsoft, Inc.
|
||||
// Use of this source code is governed by the MIT license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#ifndef ELECTRON_SHELL_BROWSER_UI_STATUS_ICON_GTK_H_
|
||||
#define ELECTRON_SHELL_BROWSER_UI_STATUS_ICON_GTK_H_
|
||||
|
||||
#include <memory>
|
||||
|
||||
#include "ui/base/glib/glib_integers.h"
|
||||
#include "ui/base/glib/glib_signal.h"
|
||||
#include "ui/base/glib/scoped_gobject.h"
|
||||
#include "ui/linux/status_icon_linux.h"
|
||||
|
||||
typedef struct _GtkStatusIcon GtkStatusIcon;
|
||||
|
||||
namespace electron {
|
||||
|
||||
namespace gtkui {
|
||||
class MenuGtk;
|
||||
}
|
||||
|
||||
class StatusIconGtk : public ui::StatusIconLinux {
|
||||
public:
|
||||
StatusIconGtk();
|
||||
StatusIconGtk(const StatusIconGtk&) = delete;
|
||||
StatusIconGtk& operator=(const StatusIconGtk&) = delete;
|
||||
~StatusIconGtk() override;
|
||||
|
||||
// ui::StatusIconLinux:
|
||||
void SetIcon(const gfx::ImageSkia& image) override;
|
||||
void SetToolTip(const std::u16string& tool_tip) override;
|
||||
void UpdatePlatformContextMenu(ui::MenuModel* model) override;
|
||||
void RefreshPlatformContextMenu() override;
|
||||
void OnSetDelegate() override;
|
||||
|
||||
private:
|
||||
CHROMEG_CALLBACK_0(StatusIconGtk, void, OnClick, GtkStatusIcon*);
|
||||
CHROMEG_CALLBACK_2(StatusIconGtk,
|
||||
void,
|
||||
OnContextMenuRequested,
|
||||
GtkStatusIcon*,
|
||||
guint,
|
||||
guint);
|
||||
|
||||
std::unique_ptr<gtkui::MenuGtk> menu_;
|
||||
ScopedGObject<GtkStatusIcon> icon_;
|
||||
};
|
||||
|
||||
} // namespace electron
|
||||
|
||||
#endif // ELECTRON_SHELL_BROWSER_UI_STATUS_ICON_GTK_H_
|
||||
@@ -1,95 +0,0 @@
|
||||
// Copyright (c) 2014 GitHub, Inc.
|
||||
// Use of this source code is governed by the MIT license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#include "shell/browser/ui/tray_icon_gtk.h"
|
||||
|
||||
#include "base/strings/utf_string_conversions.h"
|
||||
#include "chrome/browser/ui/views/status_icons/status_icon_linux_dbus.h"
|
||||
#include "ui/gfx/image/image_skia_rep.h"
|
||||
|
||||
namespace electron {
|
||||
|
||||
namespace {
|
||||
|
||||
gfx::ImageSkia GetBestImageRep(const gfx::ImageSkia& image) {
|
||||
image.EnsureRepsForSupportedScales();
|
||||
float best_scale = 0.0f;
|
||||
SkBitmap best_rep;
|
||||
for (const auto& rep : image.image_reps()) {
|
||||
if (rep.scale() > best_scale) {
|
||||
best_scale = rep.scale();
|
||||
best_rep = rep.GetBitmap();
|
||||
}
|
||||
}
|
||||
// All status icon implementations want the image in pixel coordinates, so use
|
||||
// a scale factor of 1.
|
||||
return gfx::ImageSkia::CreateFromBitmap(best_rep, 1.0f);
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
TrayIconGtk::TrayIconGtk()
|
||||
: status_icon_(new StatusIconLinuxDbus), status_icon_type_(kTypeDbus) {
|
||||
status_icon_->SetDelegate(this);
|
||||
}
|
||||
|
||||
TrayIconGtk::~TrayIconGtk() = default;
|
||||
|
||||
void TrayIconGtk::SetImage(const gfx::Image& image) {
|
||||
image_ = GetBestImageRep(image.AsImageSkia());
|
||||
if (status_icon_)
|
||||
status_icon_->SetIcon(image_);
|
||||
}
|
||||
|
||||
void TrayIconGtk::SetToolTip(const std::string& tool_tip) {
|
||||
tool_tip_ = base::UTF8ToUTF16(tool_tip);
|
||||
if (status_icon_)
|
||||
status_icon_->SetToolTip(tool_tip_);
|
||||
}
|
||||
|
||||
void TrayIconGtk::SetContextMenu(ElectronMenuModel* menu_model) {
|
||||
menu_model_ = menu_model;
|
||||
if (status_icon_)
|
||||
status_icon_->UpdatePlatformContextMenu(menu_model_);
|
||||
}
|
||||
|
||||
const gfx::ImageSkia& TrayIconGtk::GetImage() const {
|
||||
return image_;
|
||||
}
|
||||
|
||||
const std::u16string& TrayIconGtk::GetToolTip() const {
|
||||
return tool_tip_;
|
||||
}
|
||||
|
||||
ui::MenuModel* TrayIconGtk::GetMenuModel() const {
|
||||
return menu_model_;
|
||||
}
|
||||
|
||||
void TrayIconGtk::OnImplInitializationFailed() {
|
||||
switch (status_icon_type_) {
|
||||
case kTypeDbus:
|
||||
status_icon_ = nullptr;
|
||||
status_icon_type_ = kTypeNone;
|
||||
return;
|
||||
case kTypeNone:
|
||||
NOTREACHED();
|
||||
}
|
||||
}
|
||||
|
||||
void TrayIconGtk::OnClick() {
|
||||
NotifyClicked();
|
||||
}
|
||||
|
||||
bool TrayIconGtk::HasClickAction() {
|
||||
// Returning true will make the tooltip show as an additional context menu
|
||||
// item, which makes sense in Chrome but not in most Electron apps.
|
||||
return false;
|
||||
}
|
||||
|
||||
// static
|
||||
TrayIcon* TrayIcon::Create(absl::optional<UUID> guid) {
|
||||
return new TrayIconGtk;
|
||||
}
|
||||
|
||||
} // namespace electron
|
||||
115
shell/browser/ui/tray_icon_linux.cc
Normal file
115
shell/browser/ui/tray_icon_linux.cc
Normal file
@@ -0,0 +1,115 @@
|
||||
// Copyright (c) 2014 GitHub, Inc.
|
||||
// Use of this source code is governed by the MIT license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#include "shell/browser/ui/tray_icon_linux.h"
|
||||
|
||||
#include "base/strings/utf_string_conversions.h"
|
||||
#include "chrome/browser/ui/views/status_icons/status_icon_linux_dbus.h"
|
||||
#include "shell/browser/ui/status_icon_gtk.h"
|
||||
#include "ui/gfx/image/image_skia_rep.h"
|
||||
|
||||
namespace electron {
|
||||
|
||||
namespace {
|
||||
|
||||
gfx::ImageSkia GetBestImageRep(const gfx::ImageSkia& image) {
|
||||
image.EnsureRepsForSupportedScales();
|
||||
float best_scale = 0.0f;
|
||||
SkBitmap best_rep;
|
||||
for (const auto& rep : image.image_reps()) {
|
||||
if (rep.scale() > best_scale) {
|
||||
best_scale = rep.scale();
|
||||
best_rep = rep.GetBitmap();
|
||||
}
|
||||
}
|
||||
// All status icon implementations want the image in pixel coordinates, so use
|
||||
// a scale factor of 1.
|
||||
return gfx::ImageSkia::CreateFromBitmap(best_rep, 1.0f);
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
TrayIconLinux::TrayIconLinux()
|
||||
: status_icon_dbus_(new StatusIconLinuxDbus),
|
||||
status_icon_type_(StatusIconType::kDbus) {
|
||||
status_icon_dbus_->SetDelegate(this);
|
||||
}
|
||||
|
||||
TrayIconLinux::~TrayIconLinux() = default;
|
||||
|
||||
void TrayIconLinux::SetImage(const gfx::Image& image) {
|
||||
image_ = GetBestImageRep(image.AsImageSkia());
|
||||
if (auto* status_icon = GetStatusIcon())
|
||||
status_icon->SetIcon(image_);
|
||||
}
|
||||
|
||||
void TrayIconLinux::SetToolTip(const std::string& tool_tip) {
|
||||
tool_tip_ = base::UTF8ToUTF16(tool_tip);
|
||||
if (auto* status_icon = GetStatusIcon())
|
||||
status_icon->SetToolTip(tool_tip_);
|
||||
}
|
||||
|
||||
void TrayIconLinux::SetContextMenu(ElectronMenuModel* menu_model) {
|
||||
menu_model_ = menu_model;
|
||||
if (auto* status_icon = GetStatusIcon())
|
||||
status_icon->UpdatePlatformContextMenu(menu_model_);
|
||||
}
|
||||
|
||||
const gfx::ImageSkia& TrayIconLinux::GetImage() const {
|
||||
return image_;
|
||||
}
|
||||
|
||||
const std::u16string& TrayIconLinux::GetToolTip() const {
|
||||
return tool_tip_;
|
||||
}
|
||||
|
||||
ui::MenuModel* TrayIconLinux::GetMenuModel() const {
|
||||
return menu_model_;
|
||||
}
|
||||
|
||||
void TrayIconLinux::OnImplInitializationFailed() {
|
||||
switch (status_icon_type_) {
|
||||
case StatusIconType::kDbus:
|
||||
status_icon_dbus_.reset();
|
||||
status_icon_gtk_ = std::make_unique<StatusIconGtk>();
|
||||
status_icon_type_ = StatusIconType::kGtk;
|
||||
status_icon_gtk_->SetDelegate(this);
|
||||
return;
|
||||
case StatusIconType::kGtk:
|
||||
status_icon_gtk_.reset();
|
||||
status_icon_type_ = StatusIconType::kNone;
|
||||
menu_model_ = nullptr;
|
||||
return;
|
||||
case StatusIconType::kNone:
|
||||
NOTREACHED();
|
||||
}
|
||||
}
|
||||
|
||||
void TrayIconLinux::OnClick() {
|
||||
NotifyClicked();
|
||||
}
|
||||
|
||||
bool TrayIconLinux::HasClickAction() {
|
||||
// Returning true will make the tooltip show as an additional context menu
|
||||
// item, which makes sense in Chrome but not in most Electron apps.
|
||||
return false;
|
||||
}
|
||||
|
||||
ui::StatusIconLinux* TrayIconLinux::GetStatusIcon() {
|
||||
switch (status_icon_type_) {
|
||||
case StatusIconType::kDbus:
|
||||
return status_icon_dbus_.get();
|
||||
case StatusIconType::kGtk:
|
||||
return status_icon_gtk_.get();
|
||||
case StatusIconType::kNone:
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
// static
|
||||
TrayIcon* TrayIcon::Create(absl::optional<UUID> guid) {
|
||||
return new TrayIconLinux;
|
||||
}
|
||||
|
||||
} // namespace electron
|
||||
@@ -2,8 +2,8 @@
|
||||
// Use of this source code is governed by the MIT license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#ifndef ELECTRON_SHELL_BROWSER_UI_TRAY_ICON_GTK_H_
|
||||
#define ELECTRON_SHELL_BROWSER_UI_TRAY_ICON_GTK_H_
|
||||
#ifndef ELECTRON_SHELL_BROWSER_UI_TRAY_ICON_LINUX_H_
|
||||
#define ELECTRON_SHELL_BROWSER_UI_TRAY_ICON_LINUX_H_
|
||||
|
||||
#include <memory>
|
||||
#include <string>
|
||||
@@ -15,10 +15,12 @@ class StatusIconLinuxDbus;
|
||||
|
||||
namespace electron {
|
||||
|
||||
class TrayIconGtk : public TrayIcon, public ui::StatusIconLinux::Delegate {
|
||||
class StatusIconGtk;
|
||||
|
||||
class TrayIconLinux : public TrayIcon, public ui::StatusIconLinux::Delegate {
|
||||
public:
|
||||
TrayIconGtk();
|
||||
~TrayIconGtk() override;
|
||||
TrayIconLinux();
|
||||
~TrayIconLinux() override;
|
||||
|
||||
// TrayIcon:
|
||||
void SetImage(const gfx::Image& image) override;
|
||||
@@ -28,20 +30,22 @@ class TrayIconGtk : public TrayIcon, public ui::StatusIconLinux::Delegate {
|
||||
// ui::StatusIconLinux::Delegate
|
||||
void OnClick() override;
|
||||
bool HasClickAction() override;
|
||||
// The following four methods are only used by StatusIconLinuxDbus, which we
|
||||
// aren't yet using, so they are given stub implementations.
|
||||
const gfx::ImageSkia& GetImage() const override;
|
||||
const std::u16string& GetToolTip() const override;
|
||||
ui::MenuModel* GetMenuModel() const override;
|
||||
void OnImplInitializationFailed() override;
|
||||
|
||||
private:
|
||||
enum StatusIconType {
|
||||
kTypeDbus,
|
||||
kTypeNone,
|
||||
enum class StatusIconType {
|
||||
kDbus,
|
||||
kGtk,
|
||||
kNone,
|
||||
};
|
||||
|
||||
scoped_refptr<StatusIconLinuxDbus> status_icon_;
|
||||
ui::StatusIconLinux* GetStatusIcon();
|
||||
|
||||
scoped_refptr<StatusIconLinuxDbus> status_icon_dbus_;
|
||||
std::unique_ptr<StatusIconGtk> status_icon_gtk_;
|
||||
StatusIconType status_icon_type_;
|
||||
|
||||
gfx::ImageSkia image_;
|
||||
@@ -51,4 +55,4 @@ class TrayIconGtk : public TrayIcon, public ui::StatusIconLinux::Delegate {
|
||||
|
||||
} // namespace electron
|
||||
|
||||
#endif // ELECTRON_SHELL_BROWSER_UI_TRAY_ICON_GTK_H_
|
||||
#endif // ELECTRON_SHELL_BROWSER_UI_TRAY_ICON_LINUX_H_
|
||||
@@ -144,6 +144,7 @@ v8::Local<v8::Value> Converter<display::Display>::ToV8(
|
||||
gin_helper::Dictionary dict = gin::Dictionary::CreateEmpty(isolate);
|
||||
dict.SetHidden("simple", true);
|
||||
dict.Set("id", val.id());
|
||||
dict.Set("label", val.label());
|
||||
dict.Set("bounds", val.bounds());
|
||||
dict.Set("workArea", val.work_area());
|
||||
dict.Set("accelerometerSupport", val.accelerometer_support());
|
||||
|
||||
@@ -11,7 +11,6 @@
|
||||
#include "base/path_service.h"
|
||||
#include "base/strings/string_util.h"
|
||||
#include "content/common/mac_helpers.h"
|
||||
#include "ppapi/buildflags/buildflags.h"
|
||||
|
||||
namespace electron {
|
||||
|
||||
@@ -33,10 +32,8 @@ base::FilePath MainApplicationBundlePath() {
|
||||
// Up to Contents.
|
||||
if (!HasMainProcessKey() &&
|
||||
(base::EndsWith(path.value(), " Helper", base::CompareCase::SENSITIVE) ||
|
||||
#if BUILDFLAG(ENABLE_PLUGINS)
|
||||
base::EndsWith(path.value(), content::kMacHelperSuffix_plugin,
|
||||
base::CompareCase::SENSITIVE) ||
|
||||
#endif
|
||||
base::EndsWith(path.value(), content::kMacHelperSuffix_renderer,
|
||||
base::CompareCase::SENSITIVE) ||
|
||||
base::EndsWith(path.value(), content::kMacHelperSuffix_gpu,
|
||||
|
||||
@@ -24,6 +24,7 @@
|
||||
#include "base/trace_event/trace_event.h"
|
||||
#include "content/public/browser/browser_thread.h"
|
||||
#include "content/public/common/content_paths.h"
|
||||
#include "content/public/common/content_switches.h"
|
||||
#include "electron/buildflags/buildflags.h"
|
||||
#include "electron/fuses.h"
|
||||
#include "shell/browser/api/electron_api_app.h"
|
||||
@@ -43,7 +44,7 @@
|
||||
#include "shell/common/crash_keys.h"
|
||||
#endif
|
||||
|
||||
#define ELECTRON_BUILTIN_MODULES(V) \
|
||||
#define ELECTRON_BROWSER_MODULES(V) \
|
||||
V(electron_browser_app) \
|
||||
V(electron_browser_auto_updater) \
|
||||
V(electron_browser_browser_view) \
|
||||
@@ -76,21 +77,26 @@
|
||||
V(electron_browser_web_contents_view) \
|
||||
V(electron_browser_web_frame_main) \
|
||||
V(electron_browser_web_view_manager) \
|
||||
V(electron_browser_window) \
|
||||
V(electron_common_asar) \
|
||||
V(electron_common_clipboard) \
|
||||
V(electron_common_command_line) \
|
||||
V(electron_common_crashpad_support) \
|
||||
V(electron_common_environment) \
|
||||
V(electron_common_features) \
|
||||
V(electron_common_native_image) \
|
||||
V(electron_common_shell) \
|
||||
V(electron_common_v8_util) \
|
||||
V(electron_renderer_context_bridge) \
|
||||
V(electron_renderer_crash_reporter) \
|
||||
V(electron_renderer_ipc) \
|
||||
V(electron_renderer_web_frame) \
|
||||
V(electron_utility_parent_port)
|
||||
V(electron_browser_window)
|
||||
|
||||
#define ELECTRON_COMMON_MODULES(V) \
|
||||
V(electron_common_asar) \
|
||||
V(electron_common_clipboard) \
|
||||
V(electron_common_command_line) \
|
||||
V(electron_common_crashpad_support) \
|
||||
V(electron_common_environment) \
|
||||
V(electron_common_features) \
|
||||
V(electron_common_native_image) \
|
||||
V(electron_common_shell) \
|
||||
V(electron_common_v8_util)
|
||||
|
||||
#define ELECTRON_RENDERER_MODULES(V) \
|
||||
V(electron_renderer_context_bridge) \
|
||||
V(electron_renderer_crash_reporter) \
|
||||
V(electron_renderer_ipc) \
|
||||
V(electron_renderer_web_frame)
|
||||
|
||||
#define ELECTRON_UTILITY_MODULES(V) V(electron_utility_parent_port)
|
||||
|
||||
#define ELECTRON_VIEWS_MODULES(V) V(electron_browser_image_view)
|
||||
|
||||
@@ -104,7 +110,10 @@
|
||||
// forward declaration. The definitions are in each module's
|
||||
// implementation when calling the NODE_LINKED_MODULE_CONTEXT_AWARE.
|
||||
#define V(modname) void _register_##modname();
|
||||
ELECTRON_BUILTIN_MODULES(V)
|
||||
ELECTRON_BROWSER_MODULES(V)
|
||||
ELECTRON_COMMON_MODULES(V)
|
||||
ELECTRON_RENDERER_MODULES(V)
|
||||
ELECTRON_UTILITY_MODULES(V)
|
||||
#if BUILDFLAG(ENABLE_VIEWS_API)
|
||||
ELECTRON_VIEWS_MODULES(V)
|
||||
#endif
|
||||
@@ -370,13 +379,25 @@ NodeBindings::~NodeBindings() {
|
||||
|
||||
void NodeBindings::RegisterBuiltinModules() {
|
||||
#define V(modname) _register_##modname();
|
||||
ELECTRON_BUILTIN_MODULES(V)
|
||||
auto* command_line = base::CommandLine::ForCurrentProcess();
|
||||
std::string process_type =
|
||||
command_line->GetSwitchValueASCII(::switches::kProcessType);
|
||||
if (process_type.empty()) {
|
||||
ELECTRON_BROWSER_MODULES(V)
|
||||
#if BUILDFLAG(ENABLE_VIEWS_API)
|
||||
ELECTRON_VIEWS_MODULES(V)
|
||||
ELECTRON_VIEWS_MODULES(V)
|
||||
#endif
|
||||
#if BUILDFLAG(ENABLE_DESKTOP_CAPTURER)
|
||||
ELECTRON_DESKTOP_CAPTURER_MODULE(V)
|
||||
ELECTRON_DESKTOP_CAPTURER_MODULE(V)
|
||||
#endif
|
||||
}
|
||||
ELECTRON_COMMON_MODULES(V)
|
||||
if (process_type == ::switches::kRendererProcess) {
|
||||
ELECTRON_RENDERER_MODULES(V)
|
||||
}
|
||||
if (process_type == ::switches::kUtilityProcess) {
|
||||
ELECTRON_UTILITY_MODULES(V)
|
||||
}
|
||||
#if DCHECK_IS_ON()
|
||||
ELECTRON_TESTING_MODULE(V)
|
||||
#endif
|
||||
|
||||
@@ -39,6 +39,8 @@ const char kOverlaySymbolColor[] = "symbolColor";
|
||||
// The custom height for Window Controls Overlay.
|
||||
const char kOverlayHeight[] = "height";
|
||||
|
||||
// whether to keep the window out of mission control
|
||||
const char kHiddenInMissionControl[] = "hiddenInMissionControl";
|
||||
// Whether the window should show in taskbar.
|
||||
const char kSkipTaskbar[] = "skipTaskbar";
|
||||
|
||||
|
||||
@@ -30,6 +30,7 @@ extern const char kMinimizable[];
|
||||
extern const char kMaximizable[];
|
||||
extern const char kFullScreenable[];
|
||||
extern const char kClosable[];
|
||||
extern const char kHiddenInMissionControl[];
|
||||
extern const char kFullscreen[];
|
||||
extern const char kSkipTaskbar[];
|
||||
extern const char kKiosk[];
|
||||
|
||||
@@ -96,7 +96,7 @@ void ElectronRendererClient::DidCreateScriptContext(
|
||||
env->options()->force_context_aware = true;
|
||||
|
||||
// We do not want to crash the renderer process on unhandled rejections.
|
||||
env->options()->unhandled_rejections = "warn";
|
||||
env->options()->unhandled_rejections = "warn-with-error-code";
|
||||
|
||||
environments_.insert(env);
|
||||
|
||||
|
||||
@@ -85,8 +85,7 @@ ElectronContentUtilityClient::ElectronContentUtilityClient() = default;
|
||||
ElectronContentUtilityClient::~ElectronContentUtilityClient() = default;
|
||||
|
||||
// The guts of this came from the chromium implementation
|
||||
// https://cs.chromium.org/chromium/src/chrome/utility/
|
||||
// chrome_content_utility_client.cc?sq=package:chromium&dr=CSs&g=0&l=142
|
||||
// https://source.chromium.org/chromium/chromium/src/+/main:chrome/utility/chrome_content_utility_client.cc
|
||||
void ElectronContentUtilityClient::ExposeInterfacesToBrowser(
|
||||
mojo::BinderMap* binders) {
|
||||
#if BUILDFLAG(IS_WIN)
|
||||
|
||||
@@ -3977,6 +3977,24 @@ describe('BrowserWindow module', () => {
|
||||
w.hide();
|
||||
w.show();
|
||||
});
|
||||
|
||||
// TODO(zcbenz):
|
||||
// This test does not run on Linux CI. See:
|
||||
// https://github.com/electron/electron/issues/28699
|
||||
ifit(process.platform === 'linux' && !process.env.CI)('should bring a minimized maximized window back to maximized state', async () => {
|
||||
const w = new BrowserWindow({});
|
||||
const maximize = emittedOnce(w, 'maximize');
|
||||
w.maximize();
|
||||
await maximize;
|
||||
const minimize = emittedOnce(w, 'minimize');
|
||||
w.minimize();
|
||||
await minimize;
|
||||
expect(w.isMaximized()).to.equal(false);
|
||||
const restore = emittedOnce(w, 'restore');
|
||||
w.restore();
|
||||
await restore;
|
||||
expect(w.isMaximized()).to.equal(true);
|
||||
});
|
||||
});
|
||||
|
||||
// TODO(dsanders11): Enable once maximize event works on Linux again on CI
|
||||
@@ -4774,6 +4792,24 @@ describe('BrowserWindow module', () => {
|
||||
});
|
||||
});
|
||||
|
||||
ifdescribe(process.platform === 'darwin')('isHiddenInMissionControl state', () => {
|
||||
it('with functions', () => {
|
||||
it('can be set with ignoreMissionControl constructor option', () => {
|
||||
const w = new BrowserWindow({ show: false, hiddenInMissionControl: true });
|
||||
expect(w.isHiddenInMissionControl()).to.be.true('isHiddenInMissionControl');
|
||||
});
|
||||
|
||||
it('can be changed', () => {
|
||||
const w = new BrowserWindow({ show: false });
|
||||
expect(w.isHiddenInMissionControl()).to.be.false('isHiddenInMissionControl');
|
||||
w.setHiddenInMissionControl(true);
|
||||
expect(w.isHiddenInMissionControl()).to.be.true('isHiddenInMissionControl');
|
||||
w.setHiddenInMissionControl(false);
|
||||
expect(w.isHiddenInMissionControl()).to.be.false('isHiddenInMissionControl');
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
// fullscreen events are dispatched eagerly and twiddling things too fast can confuse poor Electron
|
||||
|
||||
ifdescribe(process.platform === 'darwin')('kiosk state', () => {
|
||||
@@ -5166,6 +5202,22 @@ describe('BrowserWindow module', () => {
|
||||
w.closeFilePreview();
|
||||
}).to.not.throw();
|
||||
});
|
||||
|
||||
it('should not call BrowserWindow show event', async () => {
|
||||
const w = new BrowserWindow({ show: false });
|
||||
const shown = emittedOnce(w, 'show');
|
||||
w.show();
|
||||
await shown;
|
||||
|
||||
let showCalled = false;
|
||||
w.on('show', () => {
|
||||
showCalled = true;
|
||||
});
|
||||
|
||||
w.previewFile(__filename);
|
||||
await delay(500);
|
||||
expect(showCalled).to.equal(false, 'should not have called show twice');
|
||||
});
|
||||
});
|
||||
|
||||
// TODO (jkleinsc) renable these tests on mas arm64
|
||||
|
||||
@@ -80,7 +80,7 @@ describe('dialog module', () => {
|
||||
afterEach(closeAllWindows);
|
||||
|
||||
// parentless message boxes are synchronous on macOS
|
||||
// dangling message boxes on windows cause a DCHECK: https://cs.chromium.org/chromium/src/base/win/message_window.cc?l=68&rcl=7faa4bf236a866d007dc5672c9ce42660e67a6a6
|
||||
// dangling message boxes on windows cause a DCHECK: https://source.chromium.org/chromium/chromium/src/+/main:base/win/message_window.cc;drc=7faa4bf236a866d007dc5672c9ce42660e67a6a6;l=68
|
||||
ifit(process.platform !== 'darwin' && process.platform !== 'win32')('should not throw for a parentless message box', () => {
|
||||
expect(() => {
|
||||
dialog.showMessageBox({ message: 'i am message' });
|
||||
|
||||
@@ -796,6 +796,81 @@ describe('net module', () => {
|
||||
});
|
||||
}
|
||||
|
||||
it('should be able correctly filter out cookies that are secure', async () => {
|
||||
const sess = session.fromPartition(`cookie-tests-${Math.random()}`);
|
||||
|
||||
await Promise.all([
|
||||
sess.cookies.set({
|
||||
url: 'https://electronjs.org',
|
||||
domain: 'electronjs.org',
|
||||
name: 'cookie1',
|
||||
value: '1',
|
||||
secure: true
|
||||
}),
|
||||
sess.cookies.set({
|
||||
url: 'https://electronjs.org',
|
||||
domain: 'electronjs.org',
|
||||
name: 'cookie2',
|
||||
value: '2',
|
||||
secure: false
|
||||
})
|
||||
]);
|
||||
|
||||
const secureCookies = await sess.cookies.get({
|
||||
secure: true
|
||||
});
|
||||
expect(secureCookies).to.have.lengthOf(1);
|
||||
expect(secureCookies[0].name).to.equal('cookie1');
|
||||
|
||||
const cookies = await sess.cookies.get({
|
||||
secure: false
|
||||
});
|
||||
expect(cookies).to.have.lengthOf(1);
|
||||
expect(cookies[0].name).to.equal('cookie2');
|
||||
});
|
||||
|
||||
it('throws when an invalid domain is passed', async () => {
|
||||
const sess = session.fromPartition(`cookie-tests-${Math.random()}`);
|
||||
|
||||
await expect(sess.cookies.set({
|
||||
url: 'https://electronjs.org',
|
||||
domain: 'wssss.iamabaddomain.fun',
|
||||
name: 'cookie1'
|
||||
})).to.eventually.be.rejectedWith(/Failed to set cookie with an invalid domain attribute/);
|
||||
});
|
||||
|
||||
it('should be able correctly filter out cookies that are session', async () => {
|
||||
const sess = session.fromPartition(`cookie-tests-${Math.random()}`);
|
||||
|
||||
await Promise.all([
|
||||
sess.cookies.set({
|
||||
url: 'https://electronjs.org',
|
||||
domain: 'electronjs.org',
|
||||
name: 'cookie1',
|
||||
value: '1'
|
||||
}),
|
||||
sess.cookies.set({
|
||||
url: 'https://electronjs.org',
|
||||
domain: 'electronjs.org',
|
||||
name: 'cookie2',
|
||||
value: '2',
|
||||
expirationDate: Math.round(Date.now() / 1000) + 10000
|
||||
})
|
||||
]);
|
||||
|
||||
const sessionCookies = await sess.cookies.get({
|
||||
session: true
|
||||
});
|
||||
expect(sessionCookies).to.have.lengthOf(1);
|
||||
expect(sessionCookies[0].name).to.equal('cookie1');
|
||||
|
||||
const cookies = await sess.cookies.get({
|
||||
session: false
|
||||
});
|
||||
expect(cookies).to.have.lengthOf(1);
|
||||
expect(cookies[0].name).to.equal('cookie2');
|
||||
});
|
||||
|
||||
describe('when {"credentials":"omit"}', () => {
|
||||
it('should not send cookies');
|
||||
it('should not store cookies');
|
||||
|
||||
@@ -34,6 +34,7 @@ describe('screen module', () => {
|
||||
|
||||
expect(display).to.have.property('scaleFactor').that.is.a('number');
|
||||
expect(display).to.have.property('id').that.is.a('number');
|
||||
expect(display).to.have.property('label').that.is.a('string');
|
||||
expect(display).to.have.property('rotation').that.is.a('number');
|
||||
expect(display).to.have.property('touchSupport').that.is.a('string');
|
||||
expect(display).to.have.property('accelerometerSupport').that.is.a('string');
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user