mirror of
https://github.com/electron/electron.git
synced 2026-02-19 03:14:51 -05:00
Compare commits
219 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
776ee48330 | ||
|
|
8283f19403 | ||
|
|
316f0bc845 | ||
|
|
9b94d70194 | ||
|
|
ab94340567 | ||
|
|
ca112e2e4d | ||
|
|
fd4b311d7e | ||
|
|
a22cfb6bef | ||
|
|
bc669916bd | ||
|
|
4067ec6263 | ||
|
|
a6f04822d9 | ||
|
|
9961c7aa77 | ||
|
|
aa9d2dbef7 | ||
|
|
39d55f0b6a | ||
|
|
b07b268fd0 | ||
|
|
daa220f84e | ||
|
|
f22fb9c25d | ||
|
|
c804d638fa | ||
|
|
2ee43f9ece | ||
|
|
33b54d7a8f | ||
|
|
574ee7d219 | ||
|
|
4aa6b8d001 | ||
|
|
2dd1034146 | ||
|
|
14c533c256 | ||
|
|
f8ba210b21 | ||
|
|
2f645042c2 | ||
|
|
be34c32e38 | ||
|
|
a7f4e03e1b | ||
|
|
b09dc5c4a0 | ||
|
|
ac1f5b159f | ||
|
|
9fe4fe6725 | ||
|
|
51e4b47177 | ||
|
|
f2c078ecb6 | ||
|
|
930dde396d | ||
|
|
42aa56a575 | ||
|
|
d91e53e57c | ||
|
|
1f1d139f0e | ||
|
|
18b685e397 | ||
|
|
9d3baaae58 | ||
|
|
23713aa10b | ||
|
|
883f692dad | ||
|
|
cef7a28136 | ||
|
|
d552fa0c07 | ||
|
|
2727847aca | ||
|
|
072158bf8c | ||
|
|
a733074c8c | ||
|
|
bc25056770 | ||
|
|
f0b37841ea | ||
|
|
1caf4e695d | ||
|
|
bba04ea788 | ||
|
|
3b3430fba6 | ||
|
|
c53ffadb8a | ||
|
|
e714d729b1 | ||
|
|
627bf64263 | ||
|
|
a7bbb47ec2 | ||
|
|
cf9ae70dbc | ||
|
|
044c980e96 | ||
|
|
9a71ca545f | ||
|
|
e64966641c | ||
|
|
3bb36a62cb | ||
|
|
e58a04ea5a | ||
|
|
5e32f51cf6 | ||
|
|
75349f58ad | ||
|
|
879b98c922 | ||
|
|
9d34c83089 | ||
|
|
8d8949ac60 | ||
|
|
acb2209668 | ||
|
|
4bd655a093 | ||
|
|
9c976b4f3d | ||
|
|
d70c5d1e6a | ||
|
|
d93629321e | ||
|
|
b505de0765 | ||
|
|
4c4d29eb73 | ||
|
|
993ecb5bdd | ||
|
|
d0ba8d1f69 | ||
|
|
d03fd85a90 | ||
|
|
2387d10956 | ||
|
|
558350e4bf | ||
|
|
4d960873a4 | ||
|
|
dfcb2afffd | ||
|
|
221fd9d6ce | ||
|
|
ecad7c2441 | ||
|
|
a9acc050ee | ||
|
|
29311b7d1d | ||
|
|
949ec0c7c9 | ||
|
|
91b1c0162e | ||
|
|
e20eab42d3 | ||
|
|
fe44e01dbb | ||
|
|
bc987209f8 | ||
|
|
7c2889d93a | ||
|
|
fa46c67bd3 | ||
|
|
82679f4335 | ||
|
|
75f366f4d0 | ||
|
|
1d531f29ee | ||
|
|
f75b755f21 | ||
|
|
a2929226d2 | ||
|
|
6655694cc7 | ||
|
|
1ac4d27e22 | ||
|
|
681d02a77d | ||
|
|
14eefd58c1 | ||
|
|
2beec61a50 | ||
|
|
e1ae36210b | ||
|
|
e74eac61ae | ||
|
|
f8a5c3d8ee | ||
|
|
efd18b09ca | ||
|
|
cd062ac26e | ||
|
|
a3e47196f7 | ||
|
|
1930d972fc | ||
|
|
0c4ac78dea | ||
|
|
5771f3826a | ||
|
|
a55bc6a870 | ||
|
|
dcb311d5c9 | ||
|
|
e5935eaff9 | ||
|
|
d927f1dc02 | ||
|
|
ca1cae64d9 | ||
|
|
69df216a9c | ||
|
|
2917eb1589 | ||
|
|
ec282ff385 | ||
|
|
5d98e5e78a | ||
|
|
251e7bb227 | ||
|
|
d4881625b8 | ||
|
|
348f991563 | ||
|
|
6308fc4c4e | ||
|
|
7fb719f261 | ||
|
|
d7d9d58c8b | ||
|
|
acc861dbaf | ||
|
|
18de6be607 | ||
|
|
1ae50bbeff | ||
|
|
7d129ac5c9 | ||
|
|
2cca38c036 | ||
|
|
f616c85061 | ||
|
|
393045a7e5 | ||
|
|
4a7dd267ec | ||
|
|
f2275ec32e | ||
|
|
e70c39ed60 | ||
|
|
db12e7f08b | ||
|
|
6a1c6f8d7f | ||
|
|
7bd6479573 | ||
|
|
c2de2eaaa0 | ||
|
|
62b3a6b724 | ||
|
|
c3d8337058 | ||
|
|
b3eff8ef13 | ||
|
|
6cef0d9118 | ||
|
|
65d03deacd | ||
|
|
39e55225a0 | ||
|
|
bb83758378 | ||
|
|
2716a25fcf | ||
|
|
2745d70d25 | ||
|
|
b6ffa799c5 | ||
|
|
c9bb6cd134 | ||
|
|
ac2515dd0d | ||
|
|
49436f298b | ||
|
|
542874d13b | ||
|
|
2a8e1a6de1 | ||
|
|
f5bffae462 | ||
|
|
9f80f4aa76 | ||
|
|
736150672c | ||
|
|
7434547d97 | ||
|
|
0436a27d4f | ||
|
|
6627bebdbd | ||
|
|
4a24a28467 | ||
|
|
390ed798f0 | ||
|
|
cdd2176bb6 | ||
|
|
e57b74858f | ||
|
|
3805e3c0fc | ||
|
|
5fb34249c6 | ||
|
|
06997edc3a | ||
|
|
e2b961d73c | ||
|
|
867ea38cd0 | ||
|
|
2e8f2a2f51 | ||
|
|
4da1162ffe | ||
|
|
9d3ebb1888 | ||
|
|
0b8971dec2 | ||
|
|
c8ab43a766 | ||
|
|
64c6737bb2 | ||
|
|
30b6330189 | ||
|
|
177bdd207c | ||
|
|
77fbad0333 | ||
|
|
971ec77b96 | ||
|
|
1b0c15f742 | ||
|
|
52cddbcd92 | ||
|
|
6d0feb8b79 | ||
|
|
2e096ac6bc | ||
|
|
3afe390805 | ||
|
|
d5097dd2e6 | ||
|
|
257b214cb5 | ||
|
|
945ecdd709 | ||
|
|
cb614d15aa | ||
|
|
5fbcee074d | ||
|
|
dc14161a98 | ||
|
|
299fa3a3c4 | ||
|
|
d09e7f851b | ||
|
|
84eea6fa79 | ||
|
|
0cd80cd424 | ||
|
|
78f037f639 | ||
|
|
fc75bf0a9e | ||
|
|
ddc44e1af4 | ||
|
|
5ab2749acc | ||
|
|
642c458c31 | ||
|
|
2195890a46 | ||
|
|
3413e89572 | ||
|
|
7bf69ce4ee | ||
|
|
49f5006ef0 | ||
|
|
fea59c5601 | ||
|
|
6feed17387 | ||
|
|
ec0fa836d2 | ||
|
|
56a34d3b10 | ||
|
|
bde3d403a8 | ||
|
|
8779a3ac0f | ||
|
|
b465ee721e | ||
|
|
50b0750df3 | ||
|
|
1a3da54563 | ||
|
|
fa3767564a | ||
|
|
85db7e7077 | ||
|
|
9b1d2d5b88 | ||
|
|
e8621de3f5 | ||
|
|
9942b2ba80 | ||
|
|
2bf125f82a | ||
|
|
69493ac51e |
@@ -57,6 +57,16 @@ parameters:
|
||||
type: boolean
|
||||
default: false
|
||||
|
||||
# Executors
|
||||
executors:
|
||||
linux-arm:
|
||||
resource_class: electronjs/linux-arm
|
||||
machine: true
|
||||
|
||||
linux-arm64:
|
||||
resource_class: electronjs/linux-arm64
|
||||
machine: true
|
||||
|
||||
# The config expects the following environment variables to be set:
|
||||
# - "SLACK_WEBHOOK" Slack hook URL to send notifications.
|
||||
#
|
||||
@@ -239,7 +249,14 @@ step-maybe-cleanup-arm64-mac: &step-maybe-cleanup-arm64-mac
|
||||
killall Safari || echo "No Safari processes left running"
|
||||
rm -rf ~/Library/Application\ Support/Electron*
|
||||
rm -rf ~/Library/Application\ Support/electron*
|
||||
elif [ "$TARGET_ARCH" == "arm" ] || [ "$TARGET_ARCH" == "arm64" ]; then
|
||||
XVFB=/usr/bin/Xvfb
|
||||
/sbin/start-stop-daemon --stop --exec $XVFB || echo "Xvfb not running"
|
||||
pkill electron || echo "electron not running"
|
||||
rm -rf ~/.config/Electron*
|
||||
rm -rf ~/.config/electron*
|
||||
fi
|
||||
|
||||
when: always
|
||||
|
||||
step-checkout-electron: &step-checkout-electron
|
||||
@@ -325,6 +342,7 @@ step-setup-goma-for-build: &step-setup-goma-for-build
|
||||
npm install
|
||||
mkdir third_party
|
||||
node -e "require('./src/utils/goma.js').downloadAndPrepare({ gomaOneForAll: true })"
|
||||
export GOMA_FALLBACK_ON_AUTH_FAILURE=true
|
||||
third_party/goma/goma_ctl.py ensure_start
|
||||
echo 'export GN_GOMA_FILE='`node -e "console.log(require('./src/utils/goma.js').gnFilePath)"` >> $BASH_ENV
|
||||
echo 'export LOCAL_GOMA_DIR='`node -e "console.log(require('./src/utils/goma.js').dir)"` >> $BASH_ENV
|
||||
@@ -763,7 +781,7 @@ step-verify-mksnapshot: &step-verify-mksnapshot
|
||||
command: |
|
||||
if [ "$IS_ASAN" != "1" ]; then
|
||||
cd src
|
||||
if [ "$TARGET_ARCH" == "arm64" ] &&[ "`uname`" == "Darwin" ]; then
|
||||
if [ "$TARGET_ARCH" == "arm" ] || [ "$TARGET_ARCH" == "arm64" ]; then
|
||||
python electron/script/verify-mksnapshot.py --source-root "$PWD" --build-dir out/Default --snapshot-files-dir $PWD/cross-arch-snapshots
|
||||
else
|
||||
python electron/script/verify-mksnapshot.py --source-root "$PWD" --build-dir out/Default
|
||||
@@ -908,28 +926,6 @@ step-maybe-cross-arch-snapshot-store: &step-maybe-cross-arch-snapshot-store
|
||||
path: src/cross-arch-snapshots
|
||||
destination: cross-arch-snapshots
|
||||
|
||||
step-maybe-trigger-arm-test: &step-maybe-trigger-arm-test
|
||||
run:
|
||||
name: Trigger an arm test on VSTS if applicable
|
||||
command: |
|
||||
cd src
|
||||
# Only run for non-fork prs
|
||||
if [ "$TRIGGER_ARM_TEST" == "true" ] && [ -z "$CIRCLE_PR_NUMBER" ]; then
|
||||
#Trigger VSTS job, passing along CircleCI job number and branch to build
|
||||
if [ "`uname`" == "Darwin" ]; then
|
||||
if [ x"$MAS_BUILD" == x"true" ]; then
|
||||
export DEVOPS_BUILD="electron-mas-arm64-testing"
|
||||
else
|
||||
export DEVOPS_BUILD="electron-osx-arm64-testing"
|
||||
fi
|
||||
echo "Triggering $DEVOPS_BUILD build on Azure DevOps"
|
||||
node electron/script/release/ci-release-build.js --job=$DEVOPS_BUILD --ci=DevOps --armTest --circleBuildNum=$CIRCLE_BUILD_NUM $CIRCLE_BRANCH
|
||||
else
|
||||
echo "Triggering electron-$TARGET_ARCH-testing build on VSTS"
|
||||
node electron/script/release/ci-release-build.js --job=electron-$TARGET_ARCH-testing --ci=VSTS --armTest --circleBuildNum=$CIRCLE_BUILD_NUM $CIRCLE_BRANCH
|
||||
fi
|
||||
fi
|
||||
|
||||
step-maybe-generate-typescript-defs: &step-maybe-generate-typescript-defs
|
||||
run:
|
||||
name: Generate type declarations
|
||||
@@ -1344,7 +1340,7 @@ steps-tests: &steps-tests
|
||||
(cd electron && node script/yarn test --runners=main --trace-uncaught --enable-logging --files $(circleci tests glob spec-main/*-spec.ts | circleci tests split)) 2>&1 | $ASAN_SYMBOLIZE
|
||||
(cd electron && node script/yarn test --runners=remote --trace-uncaught --enable-logging --files $(circleci tests glob spec/*-spec.js | circleci tests split)) 2>&1 | $ASAN_SYMBOLIZE
|
||||
else
|
||||
if [ "$TARGET_ARCH" == "arm64" ] &&[ "`uname`" == "Darwin" ]; then
|
||||
if [ "$TARGET_ARCH" == "arm" ] || [ "$TARGET_ARCH" == "arm64" ]; then
|
||||
export ELECTRON_SKIP_NATIVE_MODULE_TESTS=true
|
||||
(cd electron && node script/yarn test --runners=main --trace-uncaught --enable-logging)
|
||||
(cd electron && node script/yarn test --runners=remote --trace-uncaught --enable-logging)
|
||||
@@ -1635,9 +1631,6 @@ commands:
|
||||
steps:
|
||||
- *step-save-out-cache
|
||||
|
||||
# Trigger tests on arm hardware if needed
|
||||
- *step-maybe-trigger-arm-test
|
||||
|
||||
- *step-maybe-notify-slack-failure
|
||||
|
||||
electron-publish:
|
||||
@@ -1981,7 +1974,7 @@ jobs:
|
||||
GCLIENT_EXTRA_ARGS: '--custom-var=checkout_arm=True --custom-var=checkout_arm64=True'
|
||||
steps:
|
||||
- electron-build:
|
||||
persist: false
|
||||
persist: true
|
||||
checkout: true
|
||||
use-out-cache: false
|
||||
|
||||
@@ -2040,7 +2033,7 @@ jobs:
|
||||
GCLIENT_EXTRA_ARGS: '--custom-var=checkout_arm=True --custom-var=checkout_arm64=True'
|
||||
steps:
|
||||
- electron-build:
|
||||
persist: false
|
||||
persist: true
|
||||
checkout: true
|
||||
use-out-cache: false
|
||||
|
||||
@@ -2437,6 +2430,24 @@ jobs:
|
||||
<<: *env-send-slack-notifications
|
||||
<<: *steps-verify-ffmpeg
|
||||
|
||||
linux-arm-testing-tests:
|
||||
executor: linux-arm
|
||||
environment:
|
||||
<<: *env-arm
|
||||
<<: *env-global
|
||||
<<: *env-headless-testing
|
||||
<<: *env-stack-dumping
|
||||
<<: *steps-tests
|
||||
|
||||
linux-arm64-testing-tests:
|
||||
executor: linux-arm64
|
||||
environment:
|
||||
<<: *env-arm64
|
||||
<<: *env-global
|
||||
<<: *env-headless-testing
|
||||
<<: *env-stack-dumping
|
||||
<<: *steps-tests
|
||||
|
||||
osx-testing-x64-tests:
|
||||
<<: *machine-mac-large
|
||||
environment:
|
||||
@@ -2689,8 +2700,23 @@ workflows:
|
||||
- linux-ia32-testing
|
||||
|
||||
- linux-arm-testing
|
||||
- linux-arm-testing-tests:
|
||||
filters:
|
||||
branches:
|
||||
# Do not run this on forked pull requests
|
||||
ignore: /pull\/[0-9]+/
|
||||
requires:
|
||||
- linux-arm-testing
|
||||
|
||||
- linux-arm64-testing
|
||||
- linux-arm64-testing-tests:
|
||||
filters:
|
||||
branches:
|
||||
# Do not run this on forked pull requests
|
||||
ignore: /pull\/[0-9]+/
|
||||
requires:
|
||||
- linux-arm64-testing
|
||||
|
||||
- linux-arm64-testing-gn-check:
|
||||
requires:
|
||||
- linux-checkout-fast
|
||||
|
||||
6
BUILD.gn
6
BUILD.gn
@@ -183,6 +183,12 @@ action("electron_js2c") {
|
||||
rebase_path(sources, root_build_dir)
|
||||
}
|
||||
|
||||
action("generate_config_gypi") {
|
||||
outputs = [ "$root_gen_dir/config.gypi" ]
|
||||
script = "script/generate-config-gypi.py"
|
||||
args = rebase_path(outputs) + [ target_cpu ]
|
||||
}
|
||||
|
||||
target_gen_default_app_js = "$target_gen_dir/js/default_app"
|
||||
|
||||
typescript_build("default_app_js") {
|
||||
|
||||
@@ -22,7 +22,7 @@ Issues are created [here](https://github.com/electron/electron/issues/new).
|
||||
|
||||
### Issue Closure
|
||||
|
||||
Bug reports will be closed if the issue has been inactive and the latest affected version no longer receives support. At the moment, Electron maintains its three latest major versions, with a new major version being released every 12 weeks. (For more information on Electron's release cadence, see [this blog post](https://electronjs.org/blog/12-week-cadence).)
|
||||
Bug reports will be closed if the issue has been inactive and the latest affected version no longer receives support. At the moment, Electron maintains its three latest major versions, with a new major version being released every 8 weeks. (For more information on Electron's release cadence, see [this blog post](https://electronjs.org/blog/8-week-cadence).)
|
||||
|
||||
_If an issue has been closed and you still feel it's relevant, feel free to ping a maintainer or add a comment!_
|
||||
|
||||
|
||||
5
DEPS
5
DEPS
@@ -10,11 +10,12 @@ gclient_gn_args = [
|
||||
'checkout_openxr',
|
||||
'checkout_google_benchmark',
|
||||
'mac_xcode_version',
|
||||
'generate_location_tags',
|
||||
]
|
||||
|
||||
vars = {
|
||||
'chromium_version':
|
||||
'91.0.4472.106',
|
||||
'91.0.4472.164',
|
||||
'node_version':
|
||||
'v14.16.0',
|
||||
'nan_version':
|
||||
@@ -52,6 +53,8 @@ vars = {
|
||||
|
||||
'mac_xcode_version': 'default',
|
||||
|
||||
'generate_location_tags': False,
|
||||
|
||||
# To allow running hooks without parsing the DEPS tree
|
||||
'process_deps': True,
|
||||
|
||||
|
||||
@@ -1 +1 @@
|
||||
13.1.3
|
||||
13.6.6
|
||||
@@ -16,5 +16,5 @@ try:
|
||||
subprocess.check_output(args, stderr=subprocess.STDOUT)
|
||||
except subprocess.CalledProcessError as e:
|
||||
error_msg = "NPM script '{}' failed with code '{}':\n".format(sys.argv[2], e.returncode)
|
||||
print(error_msg + e.output.decode('ascii'))
|
||||
print(error_msg + e.output.decode('utf8'))
|
||||
sys.exit(e.returncode)
|
||||
|
||||
@@ -66,8 +66,11 @@ static_library("chrome") {
|
||||
"//chrome/browser/extensions/global_shortcut_listener_win.cc",
|
||||
"//chrome/browser/extensions/global_shortcut_listener_win.h",
|
||||
"//chrome/browser/icon_loader_win.cc",
|
||||
"//chrome/browser/ui/frame/window_frame_util.h",
|
||||
"//chrome/browser/ui/view_ids.h",
|
||||
"//chrome/browser/win/chrome_process_finder.cc",
|
||||
"//chrome/browser/win/chrome_process_finder.h",
|
||||
"//chrome/browser/win/titlebar_config.h",
|
||||
"//chrome/child/v8_crashpad_support_win.cc",
|
||||
"//chrome/child/v8_crashpad_support_win.h",
|
||||
]
|
||||
@@ -347,17 +350,13 @@ source_set("plugins") {
|
||||
sources += [
|
||||
"//chrome/renderer/pepper/chrome_renderer_pepper_host_factory.cc",
|
||||
"//chrome/renderer/pepper/chrome_renderer_pepper_host_factory.h",
|
||||
"//chrome/renderer/pepper/pepper_flash_font_file_host.cc",
|
||||
"//chrome/renderer/pepper/pepper_flash_font_file_host.h",
|
||||
"//chrome/renderer/pepper/pepper_shared_memory_message_filter.cc",
|
||||
"//chrome/renderer/pepper/pepper_shared_memory_message_filter.h",
|
||||
]
|
||||
if (enable_pdf_viewer) {
|
||||
sources += [
|
||||
"//chrome/renderer/pepper/pepper_flash_font_file_host.cc",
|
||||
"//chrome/renderer/pepper/pepper_flash_font_file_host.h",
|
||||
]
|
||||
if (enable_pdf_viewer) {
|
||||
deps += [ "//components/pdf/renderer" ]
|
||||
}
|
||||
deps += [ "//components/pdf/renderer" ]
|
||||
}
|
||||
deps += [
|
||||
"//components/strings",
|
||||
|
||||
@@ -1193,8 +1193,8 @@ badge.
|
||||
|
||||
On macOS, it shows on the dock icon. On Linux, it only works for Unity launcher.
|
||||
|
||||
**Note:** Unity launcher requires the existence of a `.desktop` file to work,
|
||||
for more information please read [Desktop Environment Integration][unity-requirement].
|
||||
**Note:** Unity launcher requires a `.desktop` file to work. For more information,
|
||||
please read the [Unity integration documentation][unity-requirement].
|
||||
|
||||
### `app.getBadgeCount()` _Linux_ _macOS_
|
||||
|
||||
@@ -1432,8 +1432,8 @@ An `Integer` property that returns the badge count for current app. Setting the
|
||||
|
||||
On macOS, setting this with any nonzero integer shows on the dock icon. On Linux, this property only works for Unity launcher.
|
||||
|
||||
**Note:** Unity launcher requires the existence of a `.desktop` file to work,
|
||||
for more information please read [Desktop Environment Integration][unity-requirement].
|
||||
**Note:** Unity launcher requires a `.desktop` file to work. For more information,
|
||||
please read the [Unity integration documentation][unity-requirement].
|
||||
|
||||
**Note:** On macOS, you need to ensure that your application has the permission
|
||||
to display notifications for this property to take effect.
|
||||
@@ -1461,7 +1461,7 @@ A `Boolean` property that returns `true` if the app is packaged, `false` otherw
|
||||
[LSCopyDefaultHandlerForURLScheme]: https://developer.apple.com/library/mac/documentation/Carbon/Reference/LaunchServicesReference/#//apple_ref/c/func/LSCopyDefaultHandlerForURLScheme
|
||||
[handoff]: https://developer.apple.com/library/ios/documentation/UserExperience/Conceptual/Handoff/HandoffFundamentals/HandoffFundamentals.html
|
||||
[activity-type]: https://developer.apple.com/library/ios/documentation/Foundation/Reference/NSUserActivity_Class/index.html#//apple_ref/occ/instp/NSUserActivity/activityType
|
||||
[unity-requirement]: ../tutorial/desktop-environment-integration.md#unity-launcher
|
||||
[unity-requirement]: https://help.ubuntu.com/community/UnityLaunchersAndDesktopFiles#Adding_shortcuts_to_a_launcher
|
||||
[mas-builds]: ../tutorial/mac-app-store-submission-guide.md
|
||||
[Squirrel-Windows]: https://github.com/Squirrel/Squirrel.Windows
|
||||
[JumpListBeginListMSDN]: https://msdn.microsoft.com/en-us/library/windows/desktop/dd378398(v=vs.85).aspx
|
||||
|
||||
@@ -43,7 +43,7 @@ The installer generated with Squirrel will create a shortcut icon with an
|
||||
same ID for your app with `app.setAppUserModelId` API, otherwise Windows will
|
||||
not be able to pin your app properly in task bar.
|
||||
|
||||
Unlike Squirrel.Mac, Windows can host updates on S3 or any other static file host.
|
||||
Like Squirrel.Mac, Windows can host updates on S3 or any other static file host.
|
||||
You can read the documents of [Squirrel.Windows][squirrel-windows] to get more details
|
||||
about how Squirrel.Windows works.
|
||||
|
||||
|
||||
@@ -187,9 +187,9 @@ It creates a new `BrowserWindow` with native properties as set by the `options`.
|
||||
* `parent` BrowserWindow (optional) - Specify parent window. Default is `null`.
|
||||
* `modal` Boolean (optional) - Whether this is a modal window. This only works when the
|
||||
window is a child window. Default is `false`.
|
||||
* `acceptFirstMouse` Boolean (optional) - Whether the web view accepts a single
|
||||
mouse-down event that simultaneously activates the window. Default is
|
||||
`false`.
|
||||
* `acceptFirstMouse` Boolean (optional) - Whether clicking an inactive window will also
|
||||
click through to the web contents. Default is `false` on macOS. This option is not
|
||||
configurable on other platforms.
|
||||
* `disableAutoHideCursor` Boolean (optional) - Whether to hide cursor when typing.
|
||||
Default is `false`.
|
||||
* `autoHideMenuBar` Boolean (optional) - Auto hide the menu bar unless the `Alt`
|
||||
@@ -213,16 +213,13 @@ It creates a new `BrowserWindow` with native properties as set by the `options`.
|
||||
* `followWindow` - The backdrop should automatically appear active when the window is active, and inactive when it is not. This is the default.
|
||||
* `active` - The backdrop should always appear active.
|
||||
* `inactive` - The backdrop should always appear inactive.
|
||||
* `titleBarStyle` String (optional) - The style of window title bar.
|
||||
* `titleBarStyle` String (optional) _macOS_ _Windows_ - The style of window title bar.
|
||||
Default is `default`. Possible values are:
|
||||
* `default` - Results in the standard gray opaque Mac title
|
||||
bar.
|
||||
* `hidden` - Results in a hidden title bar and a full size content window, yet
|
||||
the title bar still has the standard window controls ("traffic lights") in
|
||||
the top left.
|
||||
* `hiddenInset` - Results in a hidden title bar with an alternative look
|
||||
* `default` - Results in the standard title bar for macOS or Windows respectively.
|
||||
* `hidden` - Results in a hidden title bar and a full size content window. On macOS, the window still has the standard window controls (“traffic lights”) in the top left. On Windows, when combined with `titleBarOverlay: true` it will activate the Window Controls Overlay (see `titleBarOverlay` for more information), otherwise no window controls will be shown.
|
||||
* `hiddenInset` - Only on macOS, results in a hidden title bar with an alternative look
|
||||
where the traffic light buttons are slightly more inset from the window edge.
|
||||
* `customButtonsOnHover` - Results in a hidden title bar and a full size
|
||||
* `customButtonsOnHover` - Only on macOS, results in a hidden title bar and a full size
|
||||
content window, the traffic light buttons will display when being hovered
|
||||
over in the top left of the window. **Note:** This option is currently
|
||||
experimental.
|
||||
@@ -403,6 +400,7 @@ It creates a new `BrowserWindow` with native properties as set by the `options`.
|
||||
contain the layout of the document—without requiring scrolling. Enabling
|
||||
this will cause the `preferred-size-changed` event to be emitted on the
|
||||
`WebContents` when the preferred size changes. Default is `false`.
|
||||
* `titleBarOverlay` [OverlayOptions](structures/overlay-options.md) | Boolean (optional) - When using a frameless window in conjuction with `win.setWindowButtonVisibility(true)` on macOS or using a `titleBarStyle` so that the standard window controls ("traffic lights" on macOS) are visible, this property enables the Window Controls Overlay [JavaScript APIs][overlay-javascript-apis] and [CSS Environment Variables][overlay-css-env-vars]. Specifying `true` will result in an overlay with default system colors. Default is `false`. On Windows, the [OverlayOptions](structures/overlay-options.md) can be used instead of a boolean to specify colors for the overlay.
|
||||
|
||||
When setting minimum or maximum window size with `minWidth`/`maxWidth`/
|
||||
`minHeight`/`maxHeight`, it only constrains the users. It won't prevent you from
|
||||
@@ -985,7 +983,7 @@ the player itself we would call this function with arguments of 16/9 and
|
||||
are within the content view--only that they exist. Sum any extra width and
|
||||
height areas you have within the overall content view.
|
||||
|
||||
The aspect ratio is not respected when window is resized programmingly with
|
||||
The aspect ratio is not respected when window is resized programmatically with
|
||||
APIs like `win.setSize`.
|
||||
|
||||
#### `win.setBackgroundColor(backgroundColor)`
|
||||
@@ -1689,7 +1687,7 @@ current window into a top-level window.
|
||||
|
||||
#### `win.getParentWindow()`
|
||||
|
||||
Returns `BrowserWindow` - The parent window.
|
||||
Returns `BrowserWindow | null` - The parent window or `null` if there is no parent.
|
||||
|
||||
#### `win.getChildWindows()`
|
||||
|
||||
@@ -1809,3 +1807,5 @@ removed in future Electron releases.
|
||||
[window-levels]: https://developer.apple.com/documentation/appkit/nswindow/level
|
||||
[chrome-content-scripts]: https://developer.chrome.com/extensions/content_scripts#execution-environment
|
||||
[event-emitter]: https://nodejs.org/api/events.html#events_class_eventemitter
|
||||
[overlay-javascript-apis]: https://github.com/WICG/window-controls-overlay/blob/main/explainer.md#javascript-apis
|
||||
[overlay-css-env-vars]: https://github.com/WICG/window-controls-overlay/blob/main/explainer.md#css-environment-variables
|
||||
|
||||
@@ -41,7 +41,7 @@ When `contextIsolation` is enabled in your `webPreferences` (this is the default
|
||||
|
||||
The `contextBridge` module has the following methods:
|
||||
|
||||
### `contextBridge.exposeInMainWorld(apiKey, api)` _Experimental_
|
||||
### `contextBridge.exposeInMainWorld(apiKey, api)`
|
||||
|
||||
* `apiKey` String - The key to inject the API onto `window` with. The API will be accessible on `window[apiKey]`.
|
||||
* `api` any - Your API, more information on what this API can be and how it works is available below.
|
||||
@@ -50,7 +50,7 @@ The `contextBridge` module has the following methods:
|
||||
|
||||
### API
|
||||
|
||||
The `api` provided to [`exposeInMainWorld`](#contextbridgeexposeinmainworldapikey-api-experimental) must be a `Function`, `String`, `Number`, `Array`, `Boolean`, or an object
|
||||
The `api` provided to [`exposeInMainWorld`](#contextbridgeexposeinmainworldapikey-api) must be a `Function`, `String`, `Number`, `Array`, `Boolean`, or an object
|
||||
whose keys are strings and values are a `Function`, `String`, `Number`, `Array`, `Boolean`, or another nested object that meets the same conditions.
|
||||
|
||||
`Function` values are proxied to the other context and all other values are **copied** and **frozen**. Any data / primitives sent in
|
||||
|
||||
@@ -24,7 +24,7 @@ The `dialog` module has the following methods:
|
||||
* `buttonLabel` String (optional) - Custom label for the confirmation button, when
|
||||
left empty the default label will be used.
|
||||
* `filters` [FileFilter[]](structures/file-filter.md) (optional)
|
||||
* `properties` String[] (optional) - Contains which features the dialog should
|
||||
* `properties` String[] (optional) - Contains which features the dialog should
|
||||
use. The following values are supported:
|
||||
* `openFile` - Allow files to be selected.
|
||||
* `openDirectory` - Allow directories to be selected.
|
||||
@@ -87,7 +87,7 @@ dialog.showOpenDialogSync(mainWindow, {
|
||||
* `buttonLabel` String (optional) - Custom label for the confirmation button, when
|
||||
left empty the default label will be used.
|
||||
* `filters` [FileFilter[]](structures/file-filter.md) (optional)
|
||||
* `properties` String[] (optional) - Contains which features the dialog should
|
||||
* `properties` String[] (optional) - Contains which features the dialog should
|
||||
use. The following values are supported:
|
||||
* `openFile` - Allow files to be selected.
|
||||
* `openDirectory` - Allow directories to be selected.
|
||||
@@ -112,7 +112,7 @@ Returns `Promise<Object>` - Resolve with an object containing the following:
|
||||
|
||||
* `canceled` Boolean - whether or not the dialog was canceled.
|
||||
* `filePaths` String[] - An array of file paths chosen by the user. If the dialog is cancelled this will be an empty array.
|
||||
* `bookmarks` String[] (optional) _macOS_ _mas_ - An array matching the `filePaths` array of base64 encoded strings which contains security scoped bookmark data. `securityScopedBookmarks` must be enabled for this to be populated. (For return values, see [table here](#bookmarks-array).)
|
||||
* `bookmarks` String[] (optional) _macOS_ _mas_ - An array matching the `filePaths` array of base64 encoded strings which contains security scoped bookmark data. `securityScopedBookmarks` must be enabled for this to be populated. (For return values, see [table here](#bookmarks-array).)
|
||||
|
||||
The `browserWindow` argument allows the dialog to attach itself to a parent window, making it modal.
|
||||
|
||||
@@ -165,7 +165,7 @@ dialog.showOpenDialog(mainWindow, {
|
||||
displayed in front of the filename text field.
|
||||
* `showsTagField` Boolean (optional) _macOS_ - Show the tags input box,
|
||||
defaults to `true`.
|
||||
* `properties` String[] (optional)
|
||||
* `properties` String[] (optional)
|
||||
* `showHiddenFiles` - Show hidden files in dialog.
|
||||
* `createDirectory` _macOS_ - Allow creating new directories from dialog.
|
||||
* `treatPackageAsDirectory` _macOS_ - Treat packages, such as `.app` folders,
|
||||
@@ -195,7 +195,7 @@ The `filters` specifies an array of file types that can be displayed, see
|
||||
* `nameFieldLabel` String (optional) _macOS_ - Custom label for the text
|
||||
displayed in front of the filename text field.
|
||||
* `showsTagField` Boolean (optional) _macOS_ - Show the tags input box, defaults to `true`.
|
||||
* `properties` String[] (optional)
|
||||
* `properties` String[] (optional)
|
||||
* `showHiddenFiles` - Show hidden files in dialog.
|
||||
* `createDirectory` _macOS_ - Allow creating new directories from dialog.
|
||||
* `treatPackageAsDirectory` _macOS_ - Treat packages, such as `.app` folders,
|
||||
@@ -227,7 +227,7 @@ expanding and collapsing the dialog.
|
||||
`"warning"`. On Windows, `"question"` displays the same icon as `"info"`, unless
|
||||
you set an icon using the `"icon"` option. On macOS, both `"warning"` and
|
||||
`"error"` display the same warning icon.
|
||||
* `buttons` String[] (optional) - Array of texts for buttons. On Windows, an empty array
|
||||
* `buttons` String[] (optional) - Array of texts for buttons. On Windows, an empty array
|
||||
will result in one button labeled "OK".
|
||||
* `defaultId` Integer (optional) - Index of the button in the buttons array which will
|
||||
be selected by default when the message box opens.
|
||||
@@ -273,7 +273,7 @@ If `browserWindow` is not shown dialog will not be attached to it. In such case
|
||||
`"warning"`. On Windows, `"question"` displays the same icon as `"info"`, unless
|
||||
you set an icon using the `"icon"` option. On macOS, both `"warning"` and
|
||||
`"error"` display the same warning icon.
|
||||
* `buttons` String[] (optional) - Array of texts for buttons. On Windows, an empty array
|
||||
* `buttons` String[] (optional) - Array of texts for buttons. On Windows, an empty array
|
||||
will result in one button labeled "OK".
|
||||
* `defaultId` Integer (optional) - Index of the button in the buttons array which will
|
||||
be selected by default when the message box opens.
|
||||
|
||||
@@ -18,17 +18,17 @@ const win = new BrowserWindow({ width: 800, height: 600, frame: false })
|
||||
win.show()
|
||||
```
|
||||
|
||||
### Alternatives on macOS
|
||||
### Alternatives
|
||||
|
||||
There's an alternative way to specify a chromeless window.
|
||||
There's an alternative way to specify a chromeless window on macOS and Windows.
|
||||
Instead of setting `frame` to `false` which disables both the titlebar and window controls,
|
||||
you may want to have the title bar hidden and your content extend to the full window size,
|
||||
yet still preserve the window controls ("traffic lights") for standard window actions.
|
||||
yet still preserve the window controls ("traffic lights" on macOS) for standard window actions.
|
||||
You can do so by specifying the `titleBarStyle` option:
|
||||
|
||||
#### `hidden`
|
||||
|
||||
Results in a hidden title bar and a full size content window, yet the title bar still has the standard window controls (“traffic lights”) in the top left.
|
||||
Results in a hidden title bar and a full size content window. On macOS, the title bar still has the standard window controls (“traffic lights”) in the top left.
|
||||
|
||||
```javascript
|
||||
const { BrowserWindow } = require('electron')
|
||||
@@ -36,6 +36,8 @@ const win = new BrowserWindow({ titleBarStyle: 'hidden' })
|
||||
win.show()
|
||||
```
|
||||
|
||||
### Alternatives on macOS
|
||||
|
||||
#### `hiddenInset`
|
||||
|
||||
Results in a hidden title bar with an alternative look where the traffic light buttons are slightly more inset from the window edge.
|
||||
@@ -61,6 +63,35 @@ const win = new BrowserWindow({ titleBarStyle: 'customButtonsOnHover', frame: fa
|
||||
win.show()
|
||||
```
|
||||
|
||||
## Windows Control Overlay
|
||||
|
||||
When using a frameless window in conjuction with `win.setWindowButtonVisibility(true)` on macOS, using one of the `titleBarStyle`s as described above so
|
||||
that the traffic lights are visible, or using `titleBarStyle: hidden` on Windows, you can access the Window Controls Overlay [JavaScript APIs][overlay-javascript-apis] and
|
||||
[CSS Environment Variables][overlay-css-env-vars] by setting the `titleBarOverlay` option to true. Specifying `true` will result in an overlay with default system colors.
|
||||
|
||||
On Windows, you can also specify the color of the overlay and its symbols by setting `titleBarOverlay` to an object with the options `color` and `symbolColor`. If an option is not specified, the color will default to its system color for the window control buttons:
|
||||
|
||||
```javascript
|
||||
const { BrowserWindow } = require('electron')
|
||||
const win = new BrowserWindow({
|
||||
titleBarStyle: 'hidden',
|
||||
titleBarOverlay: true
|
||||
})
|
||||
win.show()
|
||||
```
|
||||
|
||||
```javascript
|
||||
const { BrowserWindow } = require('electron')
|
||||
const win = new BrowserWindow({
|
||||
titleBarStyle: 'hidden',
|
||||
titleBarOverlay: {
|
||||
color: '#2f3241',
|
||||
symbolColor: '#74b1be'
|
||||
}
|
||||
})
|
||||
win.show()
|
||||
```
|
||||
|
||||
## Transparent window
|
||||
|
||||
By setting the `transparent` option to `true`, you can also make the frameless
|
||||
@@ -186,3 +217,5 @@ behave correctly on all platforms you should never use a custom context menu on
|
||||
draggable areas.
|
||||
|
||||
[ignore-mouse-events]: browser-window.md#winsetignoremouseeventsignore-options
|
||||
[overlay-javascript-apis]: https://github.com/WICG/window-controls-overlay/blob/main/explainer.md#javascript-apis
|
||||
[overlay-css-env-vars]: https://github.com/WICG/window-controls-overlay/blob/main/explainer.md#css-environment-variables
|
||||
|
||||
@@ -162,7 +162,7 @@ const template = [
|
||||
{ role: 'services' },
|
||||
{ type: 'separator' },
|
||||
{ role: 'hide' },
|
||||
{ role: 'hideothers' },
|
||||
{ role: 'hideOthers' },
|
||||
{ role: 'unhide' },
|
||||
{ type: 'separator' },
|
||||
{ role: 'quit' }
|
||||
|
||||
@@ -506,6 +506,7 @@ win.webContents.session.setCertificateVerifyProc((request, callback) => {
|
||||
* `permissionGranted` Boolean - Allow or deny the permission.
|
||||
* `details` Object - Some properties are only available on certain permission types.
|
||||
* `externalURL` String (optional) - The url of the `openExternal` request.
|
||||
* `securityOrigin` String (optional) - The security origin of the `media` request.
|
||||
* `mediaTypes` String[] (optional) - The types of media access being requested, elements can be `video`
|
||||
or `audio`
|
||||
* `requestingUrl` String - The last URL the requesting frame loaded
|
||||
@@ -531,7 +532,7 @@ session.fromPartition('some-partition').setPermissionRequestHandler((webContents
|
||||
#### `ses.setPermissionCheckHandler(handler)`
|
||||
|
||||
* `handler` Function\<Boolean> | null
|
||||
* `webContents` ([WebContents](web-contents.md) | null) - WebContents checking the permission. Please note that if the request comes from a subframe you should use `requestingUrl` to check the request origin. Cross origin sub frames making permission checks will pass a `null` webContents to this handler. You should use `embeddingOrigin` and `requestingOrigin` to determine what origin the owning frame and the requesting frame are on respectively.
|
||||
* `webContents` ([WebContents](web-contents.md) | null) - WebContents checking the permission. Please note that if the request comes from a subframe you should use `requestingUrl` to check the request origin. All cross origin sub frames making permission checks will pass a `null` webContents to this handler, while certain other permission checks such as `notifications` checks will always pass `null`. You should use `embeddingOrigin` and `requestingOrigin` to determine what origin the owning frame and the requesting frame are on respectively.
|
||||
* `permission` String - Type of permission check. Valid values are `midiSysex`, `notifications`, `geolocation`, `media`,`mediaKeySystem`,`midi`, `pointerLock`, `fullscreen`, `openExternal`, or `serial`.
|
||||
* `requestingOrigin` String - The origin URL of the permission check
|
||||
* `details` Object - Some properties are only available on certain permission types.
|
||||
|
||||
4
docs/api/structures/overlay-options.md
Normal file
4
docs/api/structures/overlay-options.md
Normal file
@@ -0,0 +1,4 @@
|
||||
# OverlayOptions Object
|
||||
|
||||
* `color` String (optional) _Windows_ - The CSS color of the Window Controls Overlay when enabled. Default is the system color.
|
||||
* `symbolColor` String (optional) _Windows_ - The CSS color of the symbols on the Window Controls Overlay when enabled. Default is the system color.
|
||||
@@ -14,7 +14,7 @@ Process: [Main](../glossary.md#main-process)
|
||||
* `highlightedIndex` Integer - The index of the item the user touched.
|
||||
* `selectedStyle` String (optional) - Selected item style. Can be `background`, `outline` or `none`. Defaults to `none`.
|
||||
* `overlayStyle` String (optional) - Selected overlay item style. Can be `background`, `outline` or `none`. Defaults to `none`.
|
||||
* `showArrowButtons` Boolean (optional) - Defaults to `false`.
|
||||
* `showArrowButtons` Boolean (optional) - Whether to show arrow buttons. Defaults to `false` and is only shown if `items` is non-empty.
|
||||
* `mode` String (optional) - Can be `fixed` or `free`. The default is `free`.
|
||||
* `continuous` Boolean (optional) - Defaults to `true`.
|
||||
|
||||
|
||||
@@ -45,6 +45,26 @@ returns `null`.
|
||||
Returns `WebContents` | undefined - A WebContents instance with the given ID, or
|
||||
`undefined` if there is no WebContents associated with the given ID.
|
||||
|
||||
### `webContents.fromDevToolsTargetId(targetId)`
|
||||
|
||||
* `targetId` String - The Chrome DevTools Protocol [TargetID](https://chromedevtools.github.io/devtools-protocol/tot/Target/#type-TargetID) associated with the WebContents instance.
|
||||
|
||||
Returns `WebContents` | undefined - A WebContents instance with the given TargetID, or
|
||||
`undefined` if there is no WebContents associated with the given TargetID.
|
||||
|
||||
When communicating with the [Chrome DevTools Protocol](https://chromedevtools.github.io/devtools-protocol/),
|
||||
it can be useful to lookup a WebContents instance based on its assigned TargetID.
|
||||
|
||||
```js
|
||||
async function lookupTargetId (browserWindow) {
|
||||
const wc = browserWindow.webContents
|
||||
await wc.debugger.attach('1.3')
|
||||
const { targetInfo } = await wc.debugger.sendCommand('Target.getTargetInfo')
|
||||
const { targetId } = targetInfo
|
||||
const targetWebContents = await webContents.fromDevToolsTargetId(targetId)
|
||||
}
|
||||
```
|
||||
|
||||
## Class: WebContents
|
||||
|
||||
> Render and control the contents of a BrowserWindow instance.
|
||||
@@ -710,6 +730,8 @@ first available device will be selected. `callback` should be called with
|
||||
`deviceId` to be selected, passing empty string to `callback` will
|
||||
cancel the request.
|
||||
|
||||
If no event listener is added for this event, all bluetooth requests will be cancelled.
|
||||
|
||||
```javascript
|
||||
const { app, BrowserWindow } = require('electron')
|
||||
|
||||
|
||||
@@ -154,7 +154,6 @@ response are visible by the time this listener is fired.
|
||||
* `timestamp` Double
|
||||
* `statusLine` String
|
||||
* `statusCode` Integer
|
||||
* `requestHeaders` Record<string, string>
|
||||
* `responseHeaders` Record<string, string[]> (optional)
|
||||
* `callback` Function
|
||||
* `headersReceivedResponse` Object
|
||||
|
||||
@@ -151,12 +151,16 @@ browser plugins. Plugins are disabled by default.
|
||||
### `preload`
|
||||
|
||||
```html
|
||||
<!-- from a file -->
|
||||
<webview src="https://www.github.com/" preload="./test.js"></webview>
|
||||
<!-- or if you want to load from an asar archive -->
|
||||
<webview src="https://www.github.com/" preload="./app.asar/test.js"></webview>
|
||||
```
|
||||
|
||||
A `String` that specifies a script that will be loaded before other scripts run in the guest
|
||||
page. The protocol of script's URL must be either `file:` or `asar:`, because it
|
||||
will be loaded by `require` in guest page under the hood.
|
||||
page. The protocol of script's URL must be `file:` (even when using `asar:` archives) because
|
||||
it will be loaded by Node's `require` under the hood, which treats `asar:` archives as virtual
|
||||
directories.
|
||||
|
||||
When the guest page doesn't have node integration this script will still have
|
||||
access to all Node APIs, but global objects injected by Node will be deleted
|
||||
@@ -718,6 +722,10 @@ Corresponds to the points in time when the spinner of the tab starts spinning.
|
||||
|
||||
Corresponds to the points in time when the spinner of the tab stops spinning.
|
||||
|
||||
### Event: 'did-attach'
|
||||
|
||||
Fired when attached to the embedder web contents.
|
||||
|
||||
### Event: 'dom-ready'
|
||||
|
||||
Fired when document in the given frame is loaded.
|
||||
@@ -838,6 +846,19 @@ this purpose.
|
||||
|
||||
Calling `event.preventDefault()` does __NOT__ have any effect.
|
||||
|
||||
### Event: 'did-start-navigation'
|
||||
|
||||
Returns:
|
||||
|
||||
* `url` String
|
||||
* `isInPlace` Boolean
|
||||
* `isMainFrame` Boolean
|
||||
* `frameProcessId` Integer
|
||||
* `frameRoutingId` Integer
|
||||
|
||||
Emitted when any frame (including main) starts navigating. `isInPlace` will be
|
||||
`true` for in-page navigations.
|
||||
|
||||
### Event: 'did-navigate'
|
||||
|
||||
Returns:
|
||||
@@ -850,6 +871,23 @@ This event is not emitted for in-page navigations, such as clicking anchor links
|
||||
or updating the `window.location.hash`. Use `did-navigate-in-page` event for
|
||||
this purpose.
|
||||
|
||||
### Event: 'did-frame-navigate'
|
||||
|
||||
Returns:
|
||||
|
||||
* `url` String
|
||||
* `httpResponseCode` Integer - -1 for non HTTP navigations
|
||||
* `httpStatusText` String - empty for non HTTP navigations,
|
||||
* `isMainFrame` Boolean
|
||||
* `frameProcessId` Integer
|
||||
* `frameRoutingId` Integer
|
||||
|
||||
Emitted when any frame navigation is done.
|
||||
|
||||
This event is not emitted for in-page navigations, such as clicking anchor links
|
||||
or updating the `window.location.hash`. Use `did-navigate-in-page` event for
|
||||
this purpose.
|
||||
|
||||
### Event: 'did-navigate-in-page'
|
||||
|
||||
Returns:
|
||||
@@ -966,3 +1004,78 @@ 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
|
||||
[chrome-webview]: https://developer.chrome.com/docs/extensions/reference/webviewTag/
|
||||
|
||||
### Event: 'context-menu'
|
||||
|
||||
Returns:
|
||||
|
||||
* `params` Object
|
||||
* `x` Integer - x coordinate.
|
||||
* `y` Integer - y coordinate.
|
||||
* `linkURL` String - URL of the link that encloses the node the context menu
|
||||
was invoked on.
|
||||
* `linkText` String - Text associated with the link. May be an empty
|
||||
string if the contents of the link are an image.
|
||||
* `pageURL` String - URL of the top level page that the context menu was
|
||||
invoked on.
|
||||
* `frameURL` String - URL of the subframe that the context menu was invoked
|
||||
on.
|
||||
* `srcURL` String - Source URL for the element that the context menu
|
||||
was invoked on. Elements with source URLs are images, audio and video.
|
||||
* `mediaType` String - Type of the node the context menu was invoked on. Can
|
||||
be `none`, `image`, `audio`, `video`, `canvas`, `file` or `plugin`.
|
||||
* `hasImageContents` Boolean - Whether the context menu was invoked on an image
|
||||
which has non-empty contents.
|
||||
* `isEditable` Boolean - Whether the context is editable.
|
||||
* `selectionText` String - Text of the selection that the context menu was
|
||||
invoked on.
|
||||
* `titleText` String - Title text of the selection that the context menu was
|
||||
invoked on.
|
||||
* `altText` String - Alt text of the selection that the context menu was
|
||||
invoked on.
|
||||
* `suggestedFilename` String - Suggested filename to be used when saving file through 'Save
|
||||
Link As' option of context menu.
|
||||
* `selectionRect` [Rectangle](structures/rectangle.md) - Rect representing the coordinates in the document space of the selection.
|
||||
* `selectionStartOffset` Number - Start position of the selection text.
|
||||
* `referrerPolicy` [Referrer](structures/referrer.md) - The referrer policy of the frame on which the menu is invoked.
|
||||
* `misspelledWord` String - The misspelled word under the cursor, if any.
|
||||
* `dictionarySuggestions` String[] - An array of suggested words to show the
|
||||
user to replace the `misspelledWord`. Only available if there is a misspelled
|
||||
word and spellchecker is enabled.
|
||||
* `frameCharset` String - The character encoding of the frame on which the
|
||||
menu was invoked.
|
||||
* `inputFieldType` String - If the context menu was invoked on an input
|
||||
field, the type of that field. Possible values are `none`, `plainText`,
|
||||
`password`, `other`.
|
||||
* `spellcheckEnabled` Boolean - If the context is editable, whether or not spellchecking is enabled.
|
||||
* `menuSourceType` String - Input source that invoked the context menu.
|
||||
Can be `none`, `mouse`, `keyboard`, `touch`, `touchMenu`, `longPress`, `longTap`, `touchHandle`, `stylus`, `adjustSelection`, or `adjustSelectionReset`.
|
||||
* `mediaFlags` Object - The flags for the media element the context menu was
|
||||
invoked on.
|
||||
* `inError` Boolean - Whether the media element has crashed.
|
||||
* `isPaused` Boolean - Whether the media element is paused.
|
||||
* `isMuted` Boolean - Whether the media element is muted.
|
||||
* `hasAudio` Boolean - Whether the media element has audio.
|
||||
* `isLooping` Boolean - Whether the media element is looping.
|
||||
* `isControlsVisible` Boolean - Whether the media element's controls are
|
||||
visible.
|
||||
* `canToggleControls` Boolean - Whether the media element's controls are
|
||||
toggleable.
|
||||
* `canPrint` Boolean - Whether the media element can be printed.
|
||||
* `canSave` Boolean - Whether or not the media element can be downloaded.
|
||||
* `canShowPictureInPicture` Boolean - Whether the media element can show picture-in-picture.
|
||||
* `isShowingPictureInPicture` Boolean - Whether the media element is currently showing picture-in-picture.
|
||||
* `canRotate` Boolean - Whether the media element can be rotated.
|
||||
* `canLoop` Boolean - Whether the media element can be looped.
|
||||
* `editFlags` Object - These flags indicate whether the renderer believes it
|
||||
is able to perform the corresponding action.
|
||||
* `canUndo` Boolean - Whether the renderer believes it can undo.
|
||||
* `canRedo` Boolean - Whether the renderer believes it can redo.
|
||||
* `canCut` Boolean - Whether the renderer believes it can cut.
|
||||
* `canCopy` Boolean - Whether the renderer believes it can copy.
|
||||
* `canPaste` Boolean - Whether the renderer believes it can paste.
|
||||
* `canDelete` Boolean - Whether the renderer believes it can delete.
|
||||
* `canSelectAll` Boolean - Whether the renderer believes it can select all.
|
||||
* `canEditRichly` Boolean - Whether the renderer believes it can edit text richly.
|
||||
|
||||
Emitted when there is a new context menu that needs to be handled.
|
||||
|
||||
@@ -26,7 +26,9 @@ you prefer a graphical interface.
|
||||
* **.lldbinit**: Create or edit `~/.lldbinit` to allow Chromium code to be properly source-mapped.
|
||||
|
||||
```text
|
||||
command script import ~/electron/src/tools/lldb/lldbinit.py
|
||||
# e.g: ['~/electron/src/tools/lldb']
|
||||
script sys.path[:0] = ['<...path/to/electron/src/tools/lldb>']
|
||||
script import lldbinit
|
||||
```
|
||||
|
||||
## Attaching to and Debugging Electron
|
||||
|
||||
@@ -1,92 +1,81 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>Hello World!</title>
|
||||
</head>
|
||||
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<!-- https://developer.mozilla.org/en-US/docs/Web/HTTP/CSP -->
|
||||
<meta http-equiv="Content-Security-Policy" content="default-src 'self'; script-src 'self'">
|
||||
<meta http-equiv="X-Content-Security-Policy" content="default-src 'self'; script-src 'self'">
|
||||
<title>app.setAsDefaultProtocol Demo</title>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<section>
|
||||
<header>
|
||||
<h1>
|
||||
Protocol Handler
|
||||
</h1>
|
||||
<h3>The <code>app</code> module provides methods for handling protocols.</h3>
|
||||
<p>These methods allow you to set and unset the protocols your app should be the default app for. Similar to when a browser asks to be your default for viewing web pages.</p>
|
||||
<h1>App Default Protocol Demo</h1>
|
||||
|
||||
<p>Open the <a href="https://electronjs.org/docs/api/app">full app API documentation<span class="u-visible-to-screen-reader">(opens in new window)</span></a> in your browser.</p>
|
||||
</header>
|
||||
<p>The protocol API allows us to register a custom protocol and intercept existing protocol requests.</p>
|
||||
<p>These methods allow you to set and unset the protocols your app should be the default app for. Similar to when a
|
||||
browser asks to be your default for viewing web pages.</p>
|
||||
|
||||
<div >
|
||||
<button id="open-in-browser" class="js-container-target demo-toggle-button">Launch current page in browser
|
||||
<div class="demo-meta u-avoid-clicks">Supports: Win, macOS <span class="demo-meta-divider">|</span> Process: Main</div>
|
||||
</button>
|
||||
<section id='open-app-link'>
|
||||
<a href="electron-api-demos://open">Now... launch the app from a web link</a>
|
||||
</section>
|
||||
<div >
|
||||
<p>You can set your app as the default app to open for a specific protocol. For instance, in this demo we set this app as the default for <code>electron-api-demos://</code>. The demo button above will launch a page in your default browser with a link. Click that link and it will re-launch this app.</p>
|
||||
<h5>Packaging</h5>
|
||||
<p>This feature will only work on macOS when your app is packaged. It will not work when you're launching it in development from the command-line. When you package your app you'll need to make sure the macOS <code>plist</code> for the app is updated to include the new protocol handler. If you're using <code>electron-packager</code> then you can add the flag <code>--extend-info</code> with a path to the <code>plist</code> you've created. The one for this app is below.</p>
|
||||
<h5>Renderer Process</h5>
|
||||
<pre><code>
|
||||
const {shell} = require('electron')
|
||||
const path = require('path')
|
||||
const protocolHandlerBtn = document.getElementById('protocol-handler')
|
||||
protocolHandlerBtn.addEventListener('click', () => {
|
||||
const pageDirectory = __dirname.replace('app.asar', 'app.asar.unpacked')
|
||||
const pagePath = path.join('file://', pageDirectory, '../../sections/system/protocol-link.html')
|
||||
shell.openExternal(pagePath)
|
||||
})
|
||||
</code></pre>
|
||||
<h5>Main Process</h5>
|
||||
<pre><code>
|
||||
const {app, dialog} = require('electron')
|
||||
const path = require('path')
|
||||
<p>Open the <a href="https://www.electronjs.org/docs/api/protocol">full protocol API documentation</a> in your
|
||||
browser.</p>
|
||||
|
||||
if (process.defaultApp) {
|
||||
if (process.argv.length >= 2) {
|
||||
app.setAsDefaultProtocolClient('electron-api-demos', process.execPath, [path.resolve(process.argv[1])])
|
||||
}
|
||||
} else {
|
||||
app.setAsDefaultProtocolClient('electron-api-demos')
|
||||
}
|
||||
-----
|
||||
|
||||
app.on('open-url', (event, url) => {
|
||||
dialog.showErrorBox('Welcome Back', `You arrived from: ${url}`)
|
||||
})
|
||||
<h3>Demo</h3>
|
||||
<p>
|
||||
First: Launch current page in browser
|
||||
<button id="open-in-browser" class="js-container-target demo-toggle-button">
|
||||
Click to Launch Browser
|
||||
</button>
|
||||
</p>
|
||||
|
||||
</code></pre>
|
||||
<h5>macOS plist</h5>
|
||||
<pre><code>
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>CFBundleURLTypes</key>
|
||||
<array>
|
||||
<dict>
|
||||
<key>CFBundleURLSchemes</key>
|
||||
<array>
|
||||
<string>electron-api-demos</string>
|
||||
</array>
|
||||
<key>CFBundleURLName</key>
|
||||
<string>Electron API Demos Protocol</string>
|
||||
</dict>
|
||||
</array>
|
||||
<key>ElectronTeamID</key>
|
||||
<string>VEKTX9H2N7</string>
|
||||
</dict>
|
||||
</plist>
|
||||
</code>
|
||||
</pre>
|
||||
</div>
|
||||
</div>
|
||||
<script type="text/javascript">
|
||||
require('./renderer.js')
|
||||
</script>
|
||||
</section>
|
||||
<p>
|
||||
Then: Launch the app from a web link!
|
||||
<a href="electron-fiddle://open">Click here to launch the app</a>
|
||||
</p>
|
||||
|
||||
----
|
||||
|
||||
<p>You can set your app as the default app to open for a specific protocol. For instance, in this demo we set this app
|
||||
as the default for <code>electron-fiddle://</code>. The demo button above will launch a page in your default
|
||||
browser with a link. Click that link and it will re-launch this app.</p>
|
||||
|
||||
|
||||
<h3>Packaging</h3>
|
||||
<p>This feature will only work on macOS when your app is packaged. It will not work when you're launching it in
|
||||
development from the command-line. When you package your app you'll need to make sure the macOS <code>plist</code>
|
||||
for the app is updated to include the new protocol handler. If you're using <code>electron-packager</code> then you
|
||||
can add the flag <code>--extend-info</code> with a path to the <code>plist</code> you've created. The one for this
|
||||
app is below:</p>
|
||||
|
||||
<p>
|
||||
<h5>macOS plist</h5>
|
||||
<pre><code>
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>CFBundleURLTypes</key>
|
||||
<array>
|
||||
<dict>
|
||||
<key>CFBundleURLSchemes</key>
|
||||
<array>
|
||||
<string>electron-api-demos</string>
|
||||
</array>
|
||||
<key>CFBundleURLName</key>
|
||||
<string>Electron API Demos Protocol</string>
|
||||
</dict>
|
||||
</array>
|
||||
<key>ElectronTeamID</key>
|
||||
<string>VEKTX9H2N7</string>
|
||||
</dict>
|
||||
</plist>
|
||||
</code>
|
||||
</pre>
|
||||
<p>
|
||||
|
||||
<!-- You can also require other files to run in this process -->
|
||||
<script src="./renderer.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
</html>
|
||||
@@ -1,10 +1,39 @@
|
||||
// Modules to control application life and create native browser window
|
||||
const { app, BrowserWindow, dialog } = require('electron')
|
||||
const { app, BrowserWindow, ipcMain, shell } = require('electron')
|
||||
const path = require('path')
|
||||
|
||||
// Keep a global reference of the window object, if you don't, the window will
|
||||
// be closed automatically when the JavaScript object is garbage collected.
|
||||
let mainWindow
|
||||
let mainWindow;
|
||||
|
||||
if (process.defaultApp) {
|
||||
if (process.argv.length >= 2) {
|
||||
app.setAsDefaultProtocolClient('electron-fiddle', process.execPath, [path.resolve(process.argv[1])])
|
||||
}
|
||||
} else {
|
||||
app.setAsDefaultProtocolClient('electron-fiddle')
|
||||
}
|
||||
|
||||
const gotTheLock = app.requestSingleInstanceLock()
|
||||
|
||||
if (!gotTheLock) {
|
||||
app.quit()
|
||||
} else {
|
||||
app.on('second-instance', (event, commandLine, workingDirectory) => {
|
||||
// Someone tried to run a second instance, we should focus our window.
|
||||
if (mainWindow) {
|
||||
if (mainWindow.isMinimized()) mainWindow.restore()
|
||||
mainWindow.focus()
|
||||
}
|
||||
})
|
||||
|
||||
// Create mainWindow, load the rest of the app, etc...
|
||||
app.whenReady().then(() => {
|
||||
createWindow()
|
||||
})
|
||||
|
||||
app.on('open-url', (event, url) => {
|
||||
dialog.showErrorBox('Welcome Back', `You arrived from: ${url}`)
|
||||
})
|
||||
}
|
||||
|
||||
function createWindow () {
|
||||
// Create the browser window.
|
||||
@@ -12,58 +41,23 @@ function createWindow () {
|
||||
width: 800,
|
||||
height: 600,
|
||||
webPreferences: {
|
||||
nodeIntegration: true
|
||||
preload: path.join(__dirname, 'preload.js'),
|
||||
}
|
||||
})
|
||||
|
||||
// and load the index.html of the app.
|
||||
mainWindow.loadFile('index.html')
|
||||
|
||||
// Open the DevTools.
|
||||
mainWindow.webContents.openDevTools()
|
||||
|
||||
// Emitted when the window is closed.
|
||||
mainWindow.on('closed', function () {
|
||||
// Dereference the window object, usually you would store windows
|
||||
// in an array if your app supports multi windows, this is the time
|
||||
// when you should delete the corresponding element.
|
||||
mainWindow = null
|
||||
})
|
||||
}
|
||||
|
||||
// This method will be called when Electron has finished
|
||||
// initialization and is ready to create browser windows.
|
||||
// Some APIs can only be used after this event occurs.
|
||||
app.whenReady().then(createWindow)
|
||||
|
||||
// Quit when all windows are closed.
|
||||
// Quit when all windows are closed, except on macOS. There, it's common
|
||||
// for applications and their menu bar to stay active until the user quits
|
||||
// explicitly with Cmd + Q.
|
||||
app.on('window-all-closed', function () {
|
||||
// On macOS it is common for applications and their menu bar
|
||||
// to stay active until the user quits explicitly with Cmd + Q
|
||||
if (process.platform !== 'darwin') {
|
||||
app.quit()
|
||||
}
|
||||
if (process.platform !== 'darwin') app.quit()
|
||||
})
|
||||
|
||||
app.on('activate', function () {
|
||||
// On macOS it is common to re-create a window in the app when the
|
||||
// dock icon is clicked and there are no other windows open.
|
||||
if (mainWindow === null) {
|
||||
createWindow()
|
||||
}
|
||||
})
|
||||
|
||||
// In this file you can include the rest of your app's specific main process
|
||||
// code. You can also put them in separate files and require them here.
|
||||
|
||||
if (process.defaultApp) {
|
||||
if (process.argv.length >= 2) {
|
||||
app.setAsDefaultProtocolClient('electron-api-demos', process.execPath, [path.resolve(process.argv[1])])
|
||||
}
|
||||
} else {
|
||||
app.setAsDefaultProtocolClient('electron-api-demos')
|
||||
}
|
||||
|
||||
app.on('open-url', (event, url) => {
|
||||
dialog.showErrorBox('Welcome Back', `You arrived from: ${url}`)
|
||||
// Handle window controls via IPC
|
||||
ipcMain.on('shell:open', () => {
|
||||
const pageDirectory = __dirname.replace('app.asar', 'app.asar.unpacked')
|
||||
const pagePath = path.join('file://', pageDirectory, 'index.html')
|
||||
shell.openExternal(pagePath)
|
||||
})
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
// All of the Node.js APIs are available in the preload process.
|
||||
// It has the same sandbox as a Chrome extension.
|
||||
const { contextBridge, ipcRenderer } = require('electron')
|
||||
|
||||
// Set up context bridge between the renderer process and the main process
|
||||
contextBridge.exposeInMainWorld(
|
||||
'shell',
|
||||
{
|
||||
open: () => ipcRenderer.send('shell:open'),
|
||||
}
|
||||
)
|
||||
@@ -1,14 +1,8 @@
|
||||
const { shell } = require('electron')
|
||||
const path = require('path')
|
||||
// This file is required by the index.html file and will
|
||||
// be executed in the renderer process for that window.
|
||||
// All APIs exposed by the context bridge are available here.
|
||||
|
||||
const openInBrowserButton = document.getElementById('open-in-browser')
|
||||
const openAppLink = document.getElementById('open-app-link')
|
||||
// Hides openAppLink when loaded inside Electron
|
||||
openAppLink.style.display = 'none'
|
||||
|
||||
openInBrowserButton.addEventListener('click', () => {
|
||||
console.log('clicked')
|
||||
const pageDirectory = __dirname.replace('app.asar', 'app.asar.unpacked')
|
||||
const pagePath = path.join('file://', pageDirectory, 'index.html')
|
||||
shell.openExternal(pagePath)
|
||||
})
|
||||
// Binds the buttons to the context bridge API.
|
||||
document.getElementById('open-in-browser').addEventListener('click', () => {
|
||||
shell.open();
|
||||
});
|
||||
@@ -88,14 +88,15 @@ without meaning any harm:
|
||||
<dict>
|
||||
<key>com.apple.security.cs.allow-jit</key>
|
||||
<true/>
|
||||
<key>com.apple.security.cs.allow-unsigned-executable-memory</key>
|
||||
<true/>
|
||||
<key>com.apple.security.cs.debugger</key>
|
||||
<true/>
|
||||
</dict>
|
||||
</plist>
|
||||
```
|
||||
|
||||
Note that up until Electron 12, the `com.apple.security.cs.allow-unsigned-executable-memory` entitlement was required
|
||||
as well. However, it should not be used anymore if it can be avoided.
|
||||
|
||||
To see all of this in action, check out Electron Fiddle's source code,
|
||||
[especially its `electron-forge` configuration
|
||||
file](https://github.com/electron/fiddle/blob/master/forge.config.js).
|
||||
@@ -133,7 +134,7 @@ are likely using [`electron-packager`], which includes [`electron-osx-sign`] and
|
||||
|
||||
If you're using Packager's API, you can pass [in configuration that both signs
|
||||
and notarizes your
|
||||
application](https://electron.github.io/electron-packager/master/interfaces/electronpackager.options.html).
|
||||
application](https://electron.github.io/electron-packager/main/interfaces/electronpackager.options.html).
|
||||
|
||||
```js
|
||||
const packager = require('electron-packager')
|
||||
@@ -165,14 +166,15 @@ without meaning any harm:
|
||||
<dict>
|
||||
<key>com.apple.security.cs.allow-jit</key>
|
||||
<true/>
|
||||
<key>com.apple.security.cs.allow-unsigned-executable-memory</key>
|
||||
<true/>
|
||||
<key>com.apple.security.cs.debugger</key>
|
||||
<true/>
|
||||
</dict>
|
||||
</plist>
|
||||
```
|
||||
|
||||
Up until Electron 12, the `com.apple.security.cs.allow-unsigned-executable-memory` entitlement was required
|
||||
as well. However, it should not be used anymore if it can be avoided.
|
||||
|
||||
## Mac App Store
|
||||
|
||||
See the [Mac App Store Guide].
|
||||
|
||||
@@ -200,6 +200,6 @@ Run the example using Electron Fiddle and then click the "Toggle Dark Mode" butt
|
||||
[system-wide-dark-mode]: https://developer.apple.com/design/human-interface-guidelines/macos/visual-design/dark-mode/
|
||||
[electron-forge]: https://www.electronforge.io/
|
||||
[electron-packager]: https://github.com/electron/electron-packager
|
||||
[packager-darwindarkmode-api]: https://electron.github.io/electron-packager/master/interfaces/electronpackager.options.html#darwindarkmodesupport
|
||||
[packager-darwindarkmode-api]: https://electron.github.io/electron-packager/main/interfaces/electronpackager.options.html#darwindarkmodesupport
|
||||
[prefers-color-scheme]: https://developer.mozilla.org/en-US/docs/Web/CSS/@media/prefers-color-scheme
|
||||
[event-listeners]: https://developer.mozilla.org/en-US/docs/Web/API/EventTarget/addEventListener
|
||||
|
||||
@@ -1,35 +0,0 @@
|
||||
# Desktop Environment Integration
|
||||
|
||||
Different operating systems provide different features for integrating desktop
|
||||
applications into their desktop environments. For example, on Windows,
|
||||
applications can put shortcuts in the JumpList of task bar, and on Mac,
|
||||
applications can put a custom menu in the dock menu.
|
||||
|
||||
This guide explains how to integrate your application into those desktop
|
||||
environments with Electron APIs.
|
||||
|
||||
## Notifications
|
||||
|
||||
See the [Notifications documentation](notifications.md).
|
||||
|
||||
## Recent Documents
|
||||
|
||||
See [Recent Documents documentation](recent-documents.md).
|
||||
|
||||
## Progress Bar
|
||||
|
||||
See the [Progress Bar documentation](progress-bar.md).
|
||||
|
||||
## Unity Launcher
|
||||
|
||||
See the [Unity Launcher documentation][unity-launcher].
|
||||
|
||||
## Represented File for macOS Window
|
||||
|
||||
See the [Represented File documentation](represented-file.md).
|
||||
|
||||
## Dragging files out of the window
|
||||
|
||||
See the [Native File Drag & Drop documentation](native-file-drag-drop.md).
|
||||
|
||||
[unity-launcher]: https://help.ubuntu.com/community/UnityLaunchersAndDesktopFiles#Adding_shortcuts_to_a_launcher
|
||||
@@ -1,23 +1,27 @@
|
||||
# Electron Release Timelines
|
||||
|
||||
Special notes:
|
||||
|
||||
* The `-beta.1` and `stable` dates are our solid release dates.
|
||||
* We strive for weekly beta releases, however we often release more betas than scheduled.
|
||||
* All dates are our goals but there may be reasons for adjusting the stable deadline, such as security bugs.
|
||||
* Take a look at the [5.0.0 Timeline blog post](https://electronjs.org/blog/electron-5-0-timeline) for info about publicizing our release dates.
|
||||
* Since Electron 6.0, we've been targeting every other Chromium version and releasing our stable on the same day as Chrome stable. You can reference Chromium's release schedule [here](https://chromiumdash.appspot.com/schedule). See [Electron's new release cadence blog post](https://www.electronjs.org/blog/12-week-cadence) for more details on our release schedule.
|
||||
* Electron 15.0 only will include a special Alpha release. Starting in Electron 16.0, we will release on an 8-week cadence. See [Electron's new 8-week cadence blog post](https://www.electronjs.org/blog/8-week-cadence) for more details.
|
||||
|
||||
| Version | -beta.1 | Stable | Chrome | Node |
|
||||
| ------- | ------- | ------ | ------ | ---- |
|
||||
| 2.0.0 | 2018-02-21 | 2018-05-01 | M61 | v8.9 |
|
||||
| 3.0.0 | 2018-06-21 | 2018-09-18 | M66 | v10.2 |
|
||||
| 4.0.0 | 2018-10-11 | 2018-12-20 | M69 | v10.11 |
|
||||
| 5.0.0 | 2019-01-22 | 2019-04-24 | M73 | v12.0 |
|
||||
| 6.0.0 | 2019-05-01 | 2019-07-30 | M76 | v12.4 |
|
||||
| 7.0.0 | 2019-08-01 | 2019-10-22 | M78 | v12.8 |
|
||||
| 8.0.0 | 2019-10-24 | 2020-02-04 | M80 | v12.13 |
|
||||
| 9.0.0 | 2020-02-06 | 2020-05-19 | M83 | v12.14 |
|
||||
| 10.0.0 | 2020-05-21 | 2020-08-25 | M85 | v12.16 |
|
||||
| 11.0.0 | 2020-08-27 | 2020-11-17 | M87 | v12.18 |
|
||||
| 12.0.0 | 2020-11-19 | 2021-03-02 | M89 | v14.16 |
|
||||
| 13.0.0 | 2021-03-04 | 2021-05-25 | M91 | v14.16 |
|
||||
| 14.0.0 | 2021-05-27 | 2021-08-31 | M93 | TBD |
|
||||
| Electron | Alpha | Beta | Stable | Chrome | Node |
|
||||
| ------- | ----- | ------- | ------ | ------ | ---- |
|
||||
| 2.0.0 | -- | 2018-Feb-21 | 2018-May-01 | M61 | v8.9 |
|
||||
| 3.0.0 | -- | 2018-Jun-21 | 2018-Sep-18 | M66 | v10.2 |
|
||||
| 4.0.0 | -- | 2018-Oct-11 | 2018-Dec-20 | M69 | v10.11 |
|
||||
| 5.0.0 | -- | 2019-Jan-22 | 2019-Apr-24 | M73 | v12.0 |
|
||||
| 6.0.0 | -- | 2019-May-01 | 2019-Jul-30 | M76 | v12.4 |
|
||||
| 7.0.0 | -- | 2019-Aug-01 | 2019-Oct-22 | M78 | v12.8 |
|
||||
| 8.0.0 | -- | 2019-Oct-24 | 2020-Feb-04 | M80 | v12.13 |
|
||||
| 9.0.0 | -- | 2020-Feb-06 | 2020-May-19 | M83 | v12.14 |
|
||||
| 10.0.0 | -- | 2020-May-21 | 2020-Aug-25 | M85 | v12.16 |
|
||||
| 11.0.0 | -- | 2020-Aug-27 | 2020-Nov-17 | M87 | v12.18 |
|
||||
| 12.0.0 | -- | 2020-Nov-19 | 2021-Mar-02 | M89 | v14.16 |
|
||||
| 13.0.0 | -- | 2021-Mar-04 | 2021-May-25 | M91 | v14.16 |
|
||||
| 14.0.0 | -- | 2021-May-27 | 2021-Aug-31 | M93 | TBD |
|
||||
| 15.0.0 | 2021-Jul-20 | 2021-Sep-01 | 2021-Sep-21 | M94 | TBD |
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
# In-App Purchase (macOS)
|
||||
# In-App Purchases (macOS)
|
||||
|
||||
## Preparing
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
# Installation
|
||||
# Advanced Installation Instructions
|
||||
|
||||
To install prebuilt Electron binaries, use [`npm`][npm].
|
||||
The preferred method is to install Electron as a development dependency in your
|
||||
|
||||
169
docs/tutorial/launch-app-from-url-in-another-app.md
Normal file
169
docs/tutorial/launch-app-from-url-in-another-app.md
Normal file
@@ -0,0 +1,169 @@
|
||||
---
|
||||
title: launch-app-from-URL-in-another-app
|
||||
description: This guide will take you through the process of setting your electron app as the default handler for a specific protocol.
|
||||
slug: launch-app-from-url-in-another-app
|
||||
hide_title: true
|
||||
---
|
||||
|
||||
# Launching Your Electron App From A URL In Another App
|
||||
|
||||
## Overview
|
||||
|
||||
<!-- ✍ 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).
|
||||
|
||||
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
|
||||
we will use will be "`electron-fiddle://`".
|
||||
|
||||
## Examples
|
||||
|
||||
### Main Process (main.js)
|
||||
|
||||
First we will import the required modules from `electron`. These modules help control our application life and create a native browser window.
|
||||
|
||||
```js
|
||||
const { app, BrowserWindow, shell } = require('electron')
|
||||
const path = require('path')
|
||||
```
|
||||
|
||||
Next, we will proceed to register our application to handle all "`electron-fiddle://`" protocols.
|
||||
|
||||
```js
|
||||
if (process.defaultApp) {
|
||||
if (process.argv.length >= 2) {
|
||||
app.setAsDefaultProtocolClient('electron-fiddle', process.execPath, [path.resolve(process.argv[1])])
|
||||
}
|
||||
} else {
|
||||
app.setAsDefaultProtocolClient('electron-fiddle')
|
||||
}
|
||||
```
|
||||
|
||||
We will now define the function in charge of creating our browser window and load our application's `index.html` file.
|
||||
|
||||
```js
|
||||
function createWindow () {
|
||||
// Create the browser window.
|
||||
mainWindow = new BrowserWindow({
|
||||
width: 800,
|
||||
height: 600,
|
||||
webPreferences: {
|
||||
preload: path.join(__dirname, 'preload.js')
|
||||
}
|
||||
})
|
||||
|
||||
mainWindow.loadFile('index.html')
|
||||
}
|
||||
```
|
||||
|
||||
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 WindowsOS 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).
|
||||
|
||||
### Windows code:
|
||||
|
||||
```js
|
||||
const gotTheLock = app.requestSingleInstanceLock()
|
||||
|
||||
if (!gotTheLock) {
|
||||
app.quit()
|
||||
} else {
|
||||
app.on('second-instance', (event, commandLine, workingDirectory) => {
|
||||
// Someone tried to run a second instance, we should focus our window.
|
||||
if (mainWindow) {
|
||||
if (mainWindow.isMinimized()) mainWindow.restore()
|
||||
mainWindow.focus()
|
||||
}
|
||||
})
|
||||
|
||||
// Create mainWindow, load the rest of the app, etc...
|
||||
app.whenReady().then(() => {
|
||||
createWindow()
|
||||
})
|
||||
|
||||
// handling 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}`)
|
||||
})
|
||||
}
|
||||
```
|
||||
|
||||
### MacOS and Linux code:
|
||||
|
||||
```js
|
||||
// This method will be called when Electron has finished
|
||||
// initialization and is ready to create browser windows.
|
||||
// Some APIs can only be used after this event occurs.
|
||||
app.whenReady().then(() => {
|
||||
createWindow()
|
||||
})
|
||||
|
||||
// handling 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}`)
|
||||
})
|
||||
```
|
||||
|
||||
Finally, we will add some additional code to handle when someone closes our application
|
||||
|
||||
```js
|
||||
// Quit when all windows are closed, except on macOS. There, it's common
|
||||
// for applications and their menu bar to stay active until the user quits
|
||||
// explicitly with Cmd + Q.
|
||||
app.on('window-all-closed', function () {
|
||||
if (process.platform !== 'darwin') app.quit()
|
||||
})
|
||||
```
|
||||
|
||||
## Important Note:
|
||||
|
||||
### Packaging
|
||||
|
||||
This feature will only work on macOS when your app is packaged. It will not work when you're launching it in development from the command-line. When you package your app you'll need to make sure the macOS `plist` for the app is updated to include the new protocol handler. If you're using [`electron-packager`](https://github.com/electron/electron-packager) then you
|
||||
can add the flag `--extend-info` with a path to the `plist` you've created. The one for this app is below:
|
||||
|
||||
### Plist
|
||||
|
||||
```XML
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>CFBundleURLTypes</key>
|
||||
<array>
|
||||
<dict>
|
||||
<key>CFBundleURLSchemes</key>
|
||||
<array>
|
||||
<string>electron-api-demos</string>
|
||||
</array>
|
||||
<key>CFBundleURLName</key>
|
||||
<string>Electron API Demos Protocol</string>
|
||||
</dict>
|
||||
</array>
|
||||
<key>ElectronTeamID</key>
|
||||
<string>VEKTX9H2N7</string>
|
||||
</dict>
|
||||
</plist>
|
||||
```
|
||||
|
||||
## Conclusion
|
||||
|
||||
After you start your electron app, you can now enter in a URL in your browser that contains the custom protocol, for example `"electron-fiddle://open"` and observe that the application will respond and show an error dialog box.
|
||||
|
||||
<!--
|
||||
Because Electron examples usually require multiple files (HTML, CSS, JS
|
||||
for the main and renderer process, etc.), we use this custom code block
|
||||
for Fiddle (https://www.electronjs.org/fiddle).
|
||||
Please modify any of the files in the referenced folder to fit your
|
||||
example.
|
||||
The content in this codeblock will not be rendered in the website so you
|
||||
can leave it empty.
|
||||
-->
|
||||
|
||||
```fiddle docs/fiddles/system/protocol-handler/launch-app-from-URL-in-another-app
|
||||
|
||||
```
|
||||
|
||||
<!-- ✍ Explanation of the code below -->
|
||||
@@ -1,4 +1,4 @@
|
||||
# Custom Linux Desktop Launcher Actions
|
||||
# Desktop Launcher Actions (Linux)
|
||||
|
||||
## Overview
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
# Configuring the macOS Dock
|
||||
# Dock (macOS)
|
||||
|
||||
Electron has APIs to configure the app's icon in the macOS Dock. A macOS-only
|
||||
API exists to create a custom dock menu, but Electron also uses the app dock
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
# Notifications (Windows, Linux, macOS)
|
||||
# Notifications
|
||||
|
||||
## Overview
|
||||
|
||||
@@ -130,14 +130,6 @@ if you exceed that limit.
|
||||
|
||||
[apple-notification-guidelines]: https://developer.apple.com/macos/human-interface-guidelines/system-capabilities/notifications/
|
||||
|
||||
#### Advanced Notifications
|
||||
|
||||
Later versions of macOS allow for notifications with an input field, allowing the user
|
||||
to quickly reply to a notification. In order to send notifications with an input field,
|
||||
use the userland module [node-mac-notifier][node-mac-notifier].
|
||||
|
||||
[node-mac-notifier]: https://github.com/CharlieHess/node-mac-notifier
|
||||
|
||||
#### Do not disturb / Session State
|
||||
|
||||
To detect whether or not you're allowed to send a notification, use the userland module
|
||||
|
||||
@@ -148,7 +148,9 @@ A preload script can be attached to the main process in the `BrowserWindow` cons
|
||||
const { BrowserWindow } = require('electron')
|
||||
//...
|
||||
const win = new BrowserWindow({
|
||||
preload: 'path/to/preload.js'
|
||||
webPreferences: {
|
||||
preload: 'path/to/preload.js'
|
||||
}
|
||||
})
|
||||
//...
|
||||
```
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
# Progress Bar in Taskbar (Windows, macOS, Unity)
|
||||
# Taskbar Progress Bar (Windows & macOS)
|
||||
|
||||
## Overview
|
||||
|
||||
|
||||
@@ -223,7 +223,7 @@ app.on('window-all-closed', function () {
|
||||
|
||||
[node-platform]: https://nodejs.org/api/process.html#process_process_platform
|
||||
[window-all-closed]: ../api/app.md#event-window-all-closed
|
||||
[window-all-closed]: ../api/app.md#appquit
|
||||
[app-quit]: ../api/app.md#appquit
|
||||
|
||||
#### Open a window if none are open (macOS)
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
# Represented File for macOS BrowserWindows
|
||||
# Representing Files in a BrowserWindow (macOS)
|
||||
|
||||
## Overview
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
# Snapcraft Guide (Ubuntu Software Center & More)
|
||||
# Snapcraft Guide (Linux)
|
||||
|
||||
This guide provides information on how to package your Electron application
|
||||
for any Snapcraft environment, including the Ubuntu Software Center.
|
||||
|
||||
@@ -37,6 +37,13 @@ tools and resources.
|
||||
|
||||
## Supported Versions
|
||||
|
||||
_**Note:** Beginning in September 2021 with Electron 15, the Electron team
|
||||
will temporarily support the latest **four** stable major versions. This
|
||||
extended support is intended to help Electron developers transition to
|
||||
the [new eight week release cadence](https://electronjs.org/blog/8-week-cadence), and will continue until May 2022, with
|
||||
the release of Electron 19. At that time, the Electron team will drop support
|
||||
back to the latest three stable major versions._
|
||||
|
||||
The latest three *stable* major versions are supported by the Electron team.
|
||||
For example, if the latest release is 6.1.x, then the 5.0.x as well
|
||||
as the 4.2.x series are supported. We only support the latest minor release
|
||||
|
||||
@@ -49,7 +49,7 @@ update server.
|
||||
Depending on your needs, you can choose from one of these:
|
||||
|
||||
- [Hazel][hazel] – Update server for private or open-source apps which can be
|
||||
deployed for free on [Now][now]. It pulls from [GitHub Releases][gh-releases]
|
||||
deployed for free on [Vercel][vercel]. It pulls from [GitHub Releases][gh-releases]
|
||||
and leverages the power of GitHub's CDN.
|
||||
- [Nuts][nuts] – Also uses [GitHub Releases][gh-releases], but caches app
|
||||
updates on disk and supports private repositories.
|
||||
@@ -64,7 +64,7 @@ to minify server cost.
|
||||
Once you've deployed your update server, continue with importing the required
|
||||
modules in your code. The following code might vary for different server
|
||||
software, but it works like described when using
|
||||
[Hazel](https://github.com/zeit/hazel).
|
||||
[Hazel][hazel].
|
||||
|
||||
**Important:** Please ensure that the code below will only be executed in
|
||||
your packaged app, and not in development. You can use
|
||||
@@ -136,8 +136,8 @@ autoUpdater.on('error', message => {
|
||||
|
||||
Because the requests made by Auto Update aren't under your direct control, you may find situations that are difficult to handle (such as if the update server is behind authentication). The `url` field does support files, which means that with some effort, you can sidestep the server-communication aspect of the process. [Here's an example of how this could work](https://github.com/electron/electron/issues/5020#issuecomment-477636990).
|
||||
|
||||
[now]: https://zeit.co/now
|
||||
[hazel]: https://github.com/zeit/hazel
|
||||
[vercel]: https://vercel.com
|
||||
[hazel]: https://github.com/vercel/hazel
|
||||
[nuts]: https://github.com/GitbookIO/nuts
|
||||
[gh-releases]: https://help.github.com/articles/creating-releases/
|
||||
[electron-release-server]: https://github.com/ArekSredzki/electron-release-server
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
# Using Native Node Modules
|
||||
# Native Node Modules
|
||||
|
||||
Native Node.js modules are supported by Electron, but since Electron has a different
|
||||
[application binary interface (ABI)][abi] from a given Node.js binary (due to
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
# Using Pepper Flash Plugin
|
||||
# Pepper Flash Plugin
|
||||
|
||||
Electron no longer supports the Pepper Flash plugin, as Chrome has removed support.
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
# Using Selenium and WebDriver
|
||||
# Selenium and WebDriver
|
||||
|
||||
From [ChromeDriver - WebDriver for Chrome][chrome-driver]:
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
# Web embeds
|
||||
# Web Embeds
|
||||
|
||||
## Overview
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
# Windows 10 on Arm
|
||||
# Windows on ARM
|
||||
|
||||
If your app runs with Electron 6.0.8 or later, you can now build it for Windows 10 on Arm. This considerably improves performance, but requires recompilation of any native modules used in your app. It may also require small fixups to your build and packaging scripts.
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
# Windows Taskbar
|
||||
# Taskbar Customization (Windows)
|
||||
|
||||
## Overview
|
||||
|
||||
|
||||
@@ -1,5 +1,19 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<grit-part>
|
||||
<!-- Windows Caption Buttons -->
|
||||
<message name="IDS_APP_ACCNAME_CLOSE" desc="The accessible name for the Close button.">
|
||||
Close
|
||||
</message>
|
||||
<message name="IDS_APP_ACCNAME_MINIMIZE" desc="The accessible name for the Minimize button.">
|
||||
Minimize
|
||||
</message>
|
||||
<message name="IDS_APP_ACCNAME_MAXIMIZE" desc="The accessible name for the Maximize button.">
|
||||
Maximize
|
||||
</message>
|
||||
<message name="IDS_APP_ACCNAME_RESTORE" desc="The accessible name for the Restore button.">
|
||||
Restore
|
||||
</message>
|
||||
|
||||
<!-- Printing Service -->
|
||||
<message name="IDS_UTILITY_PROCESS_PRINTING_SERVICE_NAME" desc="The name of the utility process used for printing conversions.">
|
||||
Printing Service
|
||||
|
||||
@@ -101,6 +101,7 @@ auto_filenames = {
|
||||
"docs/api/structures/new-window-web-contents-event.md",
|
||||
"docs/api/structures/notification-action.md",
|
||||
"docs/api/structures/notification-response.md",
|
||||
"docs/api/structures/overlay-options.md",
|
||||
"docs/api/structures/point.md",
|
||||
"docs/api/structures/post-body.md",
|
||||
"docs/api/structures/printer-info.md",
|
||||
|
||||
@@ -90,6 +90,10 @@ filenames = {
|
||||
"shell/browser/ui/views/electron_views_delegate_win.cc",
|
||||
"shell/browser/ui/views/win_frame_view.cc",
|
||||
"shell/browser/ui/views/win_frame_view.h",
|
||||
"shell/browser/ui/views/win_caption_button.cc",
|
||||
"shell/browser/ui/views/win_caption_button.h",
|
||||
"shell/browser/ui/views/win_caption_button_container.cc",
|
||||
"shell/browser/ui/views/win_caption_button_container.h",
|
||||
"shell/browser/ui/win/dialog_thread.cc",
|
||||
"shell/browser/ui/win/dialog_thread.h",
|
||||
"shell/browser/ui/win/electron_desktop_native_widget_aura.cc",
|
||||
@@ -180,8 +184,8 @@ filenames = {
|
||||
"shell/browser/ui/cocoa/root_view_mac.mm",
|
||||
"shell/browser/ui/cocoa/views_delegate_mac.h",
|
||||
"shell/browser/ui/cocoa/views_delegate_mac.mm",
|
||||
"shell/browser/ui/cocoa/window_buttons_view.h",
|
||||
"shell/browser/ui/cocoa/window_buttons_view.mm",
|
||||
"shell/browser/ui/cocoa/window_buttons_proxy.h",
|
||||
"shell/browser/ui/cocoa/window_buttons_proxy.mm",
|
||||
"shell/browser/ui/drag_util_mac.mm",
|
||||
"shell/browser/ui/file_dialog_mac.mm",
|
||||
"shell/browser/ui/inspectable_web_contents_view_mac.h",
|
||||
|
||||
@@ -20,20 +20,6 @@ BrowserWindow.prototype._init = function (this: BWT) {
|
||||
nativeSetBounds.call(this, bounds, ...opts);
|
||||
};
|
||||
|
||||
// Sometimes the webContents doesn't get focus when window is shown, so we
|
||||
// have to force focusing on webContents in this case. The safest way is to
|
||||
// focus it when we first start to load URL, if we do it earlier it won't
|
||||
// have effect, if we do it later we might move focus in the page.
|
||||
//
|
||||
// Though this hack is only needed on macOS when the app is launched from
|
||||
// Finder, we still do it on all platforms in case of other bugs we don't
|
||||
// know.
|
||||
if (this.webContents._initiallyShown) {
|
||||
this.webContents.once('load-url' as any, function (this: WebContents) {
|
||||
this.focus();
|
||||
});
|
||||
}
|
||||
|
||||
// Redirect focus/blur event to app instance too.
|
||||
this.on('blur', (event: Event) => {
|
||||
app.emit('browser-window-blur', event, this);
|
||||
|
||||
@@ -541,6 +541,9 @@ WebContents.prototype._init = function () {
|
||||
ipcMainInternal.emit(channel, event, ...args);
|
||||
} else {
|
||||
addReplyToEvent(event);
|
||||
if (this.listenerCount('ipc-message-sync') === 0 && ipcMain.listenerCount(channel) === 0) {
|
||||
console.warn(`WebContents #${this.id} called ipcRenderer.sendSync() with '${channel}' channel without listeners.`);
|
||||
}
|
||||
this.emit('ipc-message-sync', event, channel, ...args);
|
||||
ipcMain.emit(channel, event, ...args);
|
||||
}
|
||||
@@ -678,6 +681,14 @@ WebContents.prototype._init = function () {
|
||||
}
|
||||
});
|
||||
|
||||
this.on('select-bluetooth-device', (event, devices, callback) => {
|
||||
if (this.listenerCount('select-bluetooth-device') === 1) {
|
||||
// Cancel it if there are no handlers
|
||||
event.preventDefault();
|
||||
callback('');
|
||||
}
|
||||
});
|
||||
|
||||
const event = process._linkedBinding('electron_browser_event').createEmpty();
|
||||
app.emit('web-contents-created', event, this);
|
||||
|
||||
@@ -723,6 +734,10 @@ export function fromId (id: string) {
|
||||
return binding.fromId(id);
|
||||
}
|
||||
|
||||
export function fromDevToolsTargetId (targetId: string) {
|
||||
return binding.fromDevToolsTargetId(targetId);
|
||||
}
|
||||
|
||||
export function getFocusedWebContents () {
|
||||
let focused = null;
|
||||
for (const contents of binding.getAllWebContents()) {
|
||||
|
||||
@@ -7,7 +7,11 @@ WebFrameMain.prototype.send = function (channel, ...args) {
|
||||
throw new Error('Missing required channel argument');
|
||||
}
|
||||
|
||||
return this._send(false /* internal */, channel, args);
|
||||
try {
|
||||
return this._send(false /* internal */, channel, args);
|
||||
} catch (e) {
|
||||
console.error('Error sending from webFrameMain: ', e);
|
||||
}
|
||||
};
|
||||
|
||||
WebFrameMain.prototype._sendInternal = function (channel, ...args) {
|
||||
@@ -15,7 +19,11 @@ WebFrameMain.prototype._sendInternal = function (channel, ...args) {
|
||||
throw new Error('Missing required channel argument');
|
||||
}
|
||||
|
||||
return this._send(true /* internal */, channel, args);
|
||||
try {
|
||||
return this._send(true /* internal */, channel, args);
|
||||
} catch (e) {
|
||||
console.error('Error sending from webFrameMain: ', e);
|
||||
}
|
||||
};
|
||||
|
||||
WebFrameMain.prototype.postMessage = function (...args) {
|
||||
|
||||
@@ -76,6 +76,7 @@ ipcMainInternal.on(
|
||||
const referrer: Electron.Referrer = { url: '', policy: 'strict-origin-when-cross-origin' };
|
||||
const browserWindowOptions = event.sender._callWindowOpenHandler(event, { url, frameName, features, disposition: 'new-window', referrer });
|
||||
if (event.defaultPrevented) {
|
||||
event.returnValue = null;
|
||||
return;
|
||||
}
|
||||
const guest = openGuestWindow({
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { app } from 'electron/main';
|
||||
import type { WebContents } from 'electron/main';
|
||||
import { clipboard, nativeImage } from 'electron/common';
|
||||
import { clipboard } from 'electron/common';
|
||||
import * as fs from 'fs';
|
||||
import { ipcMainInternal } from '@electron/internal/browser/ipc-main-internal';
|
||||
import * as ipcMainUtils from '@electron/internal/browser/ipc-main-internal-utils';
|
||||
@@ -37,6 +37,10 @@ ipcMainInternal.handle(IPC_MESSAGES.BROWSER_GET_LAST_WEB_PREFERENCES, function (
|
||||
return event.sender.getLastWebPreferences();
|
||||
});
|
||||
|
||||
ipcMainInternal.handle(IPC_MESSAGES.BROWSER_GET_PROCESS_MEMORY_INFO, function (event) {
|
||||
return event.sender._getProcessMemoryInfo();
|
||||
});
|
||||
|
||||
// Methods not listed in this set are called directly in the renderer process.
|
||||
const allowedClipboardMethods = (() => {
|
||||
switch (process.platform) {
|
||||
@@ -119,7 +123,3 @@ ipcMainInternal.on(IPC_MESSAGES.NAVIGATION_CONTROLLER_LENGTH, function (event) {
|
||||
ipcMainInternal.on(IPC_MESSAGES.BROWSER_PRELOAD_ERROR, function (event, preloadPath: string, error: Error) {
|
||||
event.sender.emit('preload-error', event, preloadPath, error);
|
||||
});
|
||||
|
||||
ipcMainInternal.handle(IPC_MESSAGES.NATIVE_IMAGE_CREATE_THUMBNAIL_FROM_PATH, async (_, path: string, size: Electron.Size) => {
|
||||
return typeUtils.serialize(await nativeImage.createThumbnailFromPath(path, size));
|
||||
});
|
||||
|
||||
@@ -4,6 +4,7 @@ export const enum IPC_MESSAGES {
|
||||
BROWSER_PRELOAD_ERROR = 'BROWSER_PRELOAD_ERROR',
|
||||
BROWSER_SANDBOX_LOAD = 'BROWSER_SANDBOX_LOAD',
|
||||
BROWSER_WINDOW_CLOSE = 'BROWSER_WINDOW_CLOSE',
|
||||
BROWSER_GET_PROCESS_MEMORY_INFO = 'BROWSER_GET_PROCESS_MEMORY_INFO',
|
||||
|
||||
GUEST_INSTANCE_VISIBILITY_CHANGE = 'GUEST_INSTANCE_VISIBILITY_CHANGE',
|
||||
|
||||
@@ -39,5 +40,4 @@ export const enum IPC_MESSAGES {
|
||||
INSPECTOR_SELECT_FILE = 'INSPECTOR_SELECT_FILE',
|
||||
|
||||
DESKTOP_CAPTURER_GET_SOURCES = 'DESKTOP_CAPTURER_GET_SOURCES',
|
||||
NATIVE_IMAGE_CREATE_THUMBNAIL_FROM_PATH = 'NATIVE_IMAGE_CREATE_THUMBNAIL_FROM_PATH',
|
||||
}
|
||||
|
||||
@@ -1,11 +1,3 @@
|
||||
import { ipcRendererInternal } from '@electron/internal/renderer/ipc-renderer-internal';
|
||||
import { deserialize } from '@electron/internal/common/type-utils';
|
||||
import { IPC_MESSAGES } from '@electron/internal/common/ipc-messages';
|
||||
|
||||
const { nativeImage } = process._linkedBinding('electron_common_native_image');
|
||||
|
||||
nativeImage.createThumbnailFromPath = async (path: string, size: Electron.Size) => {
|
||||
return deserialize(await ipcRendererInternal.invoke(IPC_MESSAGES.NATIVE_IMAGE_CREATE_THUMBNAIL_FROM_PATH, path, size));
|
||||
};
|
||||
|
||||
export default nativeImage;
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import * as path from 'path';
|
||||
import { IPC_MESSAGES } from '@electron/internal/common/ipc-messages';
|
||||
import type * as ipcRendererInternalModule from '@electron/internal/renderer/ipc-renderer-internal';
|
||||
|
||||
const Module = require('module');
|
||||
|
||||
@@ -43,7 +44,7 @@ const v8Util = process._linkedBinding('electron_common_v8_util');
|
||||
const contextId = v8Util.getHiddenValue<string>(global, 'contextId');
|
||||
Object.defineProperty(process, 'contextId', { enumerable: true, value: contextId });
|
||||
|
||||
const { ipcRendererInternal } = require('@electron/internal/renderer/ipc-renderer-internal');
|
||||
const { ipcRendererInternal } = require('@electron/internal/renderer/ipc-renderer-internal') as typeof ipcRendererInternalModule;
|
||||
const ipcRenderer = require('@electron/internal/renderer/api/ipc-renderer').default;
|
||||
|
||||
v8Util.setHiddenValue(global, 'ipcNative', {
|
||||
@@ -57,6 +58,10 @@ v8Util.setHiddenValue(global, 'ipcNative', {
|
||||
}
|
||||
});
|
||||
|
||||
process.getProcessMemoryInfo = () => {
|
||||
return ipcRendererInternal.invoke<Electron.ProcessMemoryInfo>(IPC_MESSAGES.BROWSER_GET_PROCESS_MEMORY_INFO);
|
||||
};
|
||||
|
||||
// Use electron module after everything is ready.
|
||||
const { webFrameInit } = require('@electron/internal/renderer/web-frame-init');
|
||||
webFrameInit();
|
||||
|
||||
@@ -1,16 +1,32 @@
|
||||
import { internalContextBridge } from '@electron/internal/renderer/api/context-bridge';
|
||||
import { ipcRendererInternal } from '@electron/internal/renderer/ipc-renderer-internal';
|
||||
import * as ipcRendererUtils from '@electron/internal/renderer/ipc-renderer-internal-utils';
|
||||
import { webFrame } from 'electron/renderer';
|
||||
import { IPC_MESSAGES } from '../common/ipc-messages';
|
||||
|
||||
const { contextIsolationEnabled } = internalContextBridge;
|
||||
|
||||
/* Corrects for some Inspector adaptations needed in Electron.
|
||||
* 1) Use menu API to show context menu.
|
||||
* 2) Correct for Chromium returning undefined for filesystem.
|
||||
* 3) Use dialog API to override file chooser dialog.
|
||||
*/
|
||||
window.onload = function () {
|
||||
// Use menu API to show context menu.
|
||||
window.InspectorFrontendHost!.showContextMenuAtPoint = createMenu;
|
||||
|
||||
// correct for Chromium returning undefined for filesystem
|
||||
window.Persistence!.FileSystemWorkspaceBinding.completeURL = completeURL;
|
||||
|
||||
// Use dialog API to override file chooser dialog.
|
||||
window.UI!.createFileSelectorElement = createFileSelectorElement;
|
||||
if (contextIsolationEnabled) {
|
||||
internalContextBridge.overrideGlobalValueFromIsolatedWorld([
|
||||
'InspectorFrontendHost', 'showContextMenuAtPoint'
|
||||
], createMenu);
|
||||
internalContextBridge.overrideGlobalValueFromIsolatedWorld([
|
||||
'Persistence', 'FileSystemWorkspaceBinding', 'completeURL'
|
||||
], completeURL);
|
||||
internalContextBridge.overrideGlobalValueFromIsolatedWorld([
|
||||
'UI', 'createFileSelectorElement'
|
||||
], createFileSelectorElement);
|
||||
} else {
|
||||
window.InspectorFrontendHost!.showContextMenuAtPoint = createMenu;
|
||||
window.Persistence!.FileSystemWorkspaceBinding.completeURL = completeURL;
|
||||
window.UI!.createFileSelectorElement = createFileSelectorElement;
|
||||
}
|
||||
};
|
||||
|
||||
// Extra / is needed as a result of MacOS requiring absolute paths
|
||||
@@ -36,9 +52,10 @@ const createMenu = function (x: number, y: number, items: ContextMenuItem[]) {
|
||||
const isEditMenu = useEditMenuItems(x, y, items);
|
||||
ipcRendererInternal.invoke<number>(IPC_MESSAGES.INSPECTOR_CONTEXT_MENU, items, isEditMenu).then(id => {
|
||||
if (typeof id === 'number') {
|
||||
window.DevToolsAPI!.contextMenuItemSelected(id);
|
||||
webFrame.executeJavaScript(`window.DevToolsAPI.contextMenuItemSelected(${JSON.stringify(id)})`);
|
||||
}
|
||||
window.DevToolsAPI!.contextMenuCleared();
|
||||
|
||||
webFrame.executeJavaScript('window.DevToolsAPI.contextMenuCleared()');
|
||||
});
|
||||
};
|
||||
|
||||
|
||||
@@ -104,10 +104,14 @@ const warnAboutInsecureResources = function () {
|
||||
return;
|
||||
}
|
||||
|
||||
const isLocal = (url: URL): boolean =>
|
||||
['localhost', '127.0.0.1', '[::1]', ''].includes(url.hostname);
|
||||
const isInsecure = (url: URL): boolean =>
|
||||
['http:', 'ftp:'].includes(url.protocol) && !isLocal(url);
|
||||
|
||||
const resources = window.performance
|
||||
.getEntriesByType('resource')
|
||||
.filter(({ name }) => /^(http|ftp):/gi.test(name || ''))
|
||||
.filter(({ name }) => new URL(name).hostname !== 'localhost')
|
||||
.filter(({ name }) => isInsecure(new URL(name)))
|
||||
.map(({ name }) => `- ${name}`)
|
||||
.join('\n');
|
||||
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
/* global binding */
|
||||
import * as events from 'events';
|
||||
import { IPC_MESSAGES } from '@electron/internal/common/ipc-messages';
|
||||
import type * as ipcRendererInternalModule from '@electron/internal/renderer/ipc-renderer-internal';
|
||||
|
||||
const { EventEmitter } = events;
|
||||
|
||||
@@ -20,7 +21,7 @@ for (const prop of Object.keys(EventEmitter.prototype) as (keyof typeof process)
|
||||
}
|
||||
Object.setPrototypeOf(process, EventEmitter.prototype);
|
||||
|
||||
const { ipcRendererInternal } = require('@electron/internal/renderer/ipc-renderer-internal');
|
||||
const { ipcRendererInternal } = require('@electron/internal/renderer/ipc-renderer-internal') as typeof ipcRendererInternalModule;
|
||||
const ipcRendererUtils = require('@electron/internal/renderer/ipc-renderer-internal-utils');
|
||||
|
||||
const { preloadScripts, process: processProps } = ipcRendererUtils.invokeSync(IPC_MESSAGES.BROWSER_SANDBOX_LOAD);
|
||||
@@ -80,6 +81,10 @@ Object.assign(preloadProcess, processProps);
|
||||
Object.assign(process, binding.process);
|
||||
Object.assign(process, processProps);
|
||||
|
||||
process.getProcessMemoryInfo = preloadProcess.getProcessMemoryInfo = () => {
|
||||
return ipcRendererInternal.invoke<Electron.ProcessMemoryInfo>(IPC_MESSAGES.BROWSER_GET_PROCESS_MEMORY_INFO);
|
||||
};
|
||||
|
||||
Object.defineProperty(preloadProcess, 'noDeprecation', {
|
||||
get () {
|
||||
return process.noDeprecation;
|
||||
|
||||
@@ -12,6 +12,9 @@ require('../common/reset-search-paths');
|
||||
// Import common settings.
|
||||
require('@electron/internal/common/init');
|
||||
|
||||
// Process command line arguments.
|
||||
const { hasSwitch, getSwitchValue } = process._linkedBinding('electron_common_command_line');
|
||||
|
||||
// Export node bindings to global.
|
||||
const { makeRequireFunction } = __non_webpack_require__('internal/modules/cjs/helpers') // eslint-disable-line
|
||||
global.module = new Module('electron/js2c/worker_init');
|
||||
@@ -32,4 +35,10 @@ if (self.location.protocol === 'file:') {
|
||||
// For backwards compatibility we fake these two paths here
|
||||
global.__filename = path.join(process.resourcesPath, 'electron.asar', 'worker', 'init.js');
|
||||
global.__dirname = path.join(process.resourcesPath, 'electron.asar', 'worker');
|
||||
|
||||
const appPath = hasSwitch('app-path') ? getSwitchValue('app-path') : null;
|
||||
if (appPath) {
|
||||
// Search for module under the app directory.
|
||||
global.module.paths = Module._nodeModulePaths(appPath);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "electron",
|
||||
"version": "13.1.3",
|
||||
"version": "13.6.6",
|
||||
"repository": "https://github.com/electron/electron",
|
||||
"description": "Build cross platform desktop apps with JavaScript, HTML, and CSS",
|
||||
"devDependencies": {
|
||||
|
||||
5
patches/angle/.patches
Normal file
5
patches/angle/.patches
Normal file
@@ -0,0 +1,5 @@
|
||||
cherry-pick-d8cb996.patch
|
||||
cherry-pick-1fb846c.patch
|
||||
cherry-pick-72473550f6ff.patch
|
||||
webgl_make_unsuccessful_links_fail_subsequent_draw_calls.patch
|
||||
fix_integer_overflow_in_blocklayoutencoder.patch
|
||||
90
patches/angle/cherry-pick-1fb846c.patch
Normal file
90
patches/angle/cherry-pick-1fb846c.patch
Normal file
@@ -0,0 +1,90 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Alexey Knyazev <lexa.knyazev@gmail.com>
|
||||
Date: Tue, 3 Aug 2021 01:57:49 +0400
|
||||
Subject: Validate texStorage dimensions with compressed formats
|
||||
|
||||
Bug: angleproject:6230
|
||||
Change-Id: I501ec1e6974bdc7e6731dcb88045edb0aa22b888
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/3067329
|
||||
Commit-Queue: Alexey Knyazev <lexa.knyazev@gmail.com>
|
||||
Reviewed-by: Kenneth Russell <kbr@chromium.org>
|
||||
Reviewed-by: Jamie Madill <jmadill@chromium.org>
|
||||
|
||||
diff --git a/src/libANGLE/validationES3.cpp b/src/libANGLE/validationES3.cpp
|
||||
index 53e1afd6e26ef8cc099e51c66457a968ca82b1c8..5c69d568ee45b9e8bf1d4d0da7b9a48b123a47c0 100644
|
||||
--- a/src/libANGLE/validationES3.cpp
|
||||
+++ b/src/libANGLE/validationES3.cpp
|
||||
@@ -1339,17 +1339,26 @@ bool ValidateES3TexStorageParametersBase(const Context *context,
|
||||
return false;
|
||||
}
|
||||
|
||||
- if (formatInfo.compressed && target == TextureType::Rectangle)
|
||||
+ if (formatInfo.compressed)
|
||||
{
|
||||
- context->validationError(GL_INVALID_ENUM, kRectangleTextureCompressed);
|
||||
- return false;
|
||||
- }
|
||||
+ if (target == TextureType::Rectangle)
|
||||
+ {
|
||||
+ context->validationError(GL_INVALID_ENUM, kRectangleTextureCompressed);
|
||||
+ return false;
|
||||
+ }
|
||||
|
||||
- if (formatInfo.compressed && target == TextureType::_3D)
|
||||
- {
|
||||
- if (!ValidateES3CompressedFormatForTexture3D(context, formatInfo.internalFormat))
|
||||
+ if (target == TextureType::_3D)
|
||||
{
|
||||
- // Error already generated.
|
||||
+ if (!ValidateES3CompressedFormatForTexture3D(context, formatInfo.internalFormat))
|
||||
+ {
|
||||
+ // Error already generated.
|
||||
+ return false;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ if (!ValidCompressedImageSize(context, formatInfo.internalFormat, 0, width, height, depth))
|
||||
+ {
|
||||
+ context->validationError(GL_INVALID_OPERATION, kInvalidCompressedImageSize);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
diff --git a/src/tests/gl_tests/SRGBTextureTest.cpp b/src/tests/gl_tests/SRGBTextureTest.cpp
|
||||
index 271fe6dbaa1d5684f7c2e16bdef18bce30943e8b..a0eab1af9e34a5de75e226efef9c0af4a50c63ff 100644
|
||||
--- a/src/tests/gl_tests/SRGBTextureTest.cpp
|
||||
+++ b/src/tests/gl_tests/SRGBTextureTest.cpp
|
||||
@@ -340,7 +340,7 @@ TEST_P(SRGBTextureTestES3, SRGBOverrideFormats)
|
||||
{
|
||||
GLTexture tex;
|
||||
glBindTexture(GL_TEXTURE_2D, tex.get());
|
||||
- glTexStorage2D(GL_TEXTURE_2D, 1, format, 1, 1);
|
||||
+ glTexStorage2D(GL_TEXTURE_2D, 1, format, 4, 4);
|
||||
GLenum error = glGetError();
|
||||
if (error == GL_INVALID_ENUM)
|
||||
{
|
||||
diff --git a/src/tests/gl_tests/WebGLCompatibilityTest.cpp b/src/tests/gl_tests/WebGLCompatibilityTest.cpp
|
||||
index fabaefbe33c94a048ec7c974951ac9ef886826ef..efbd9ebdb2bb29cf9673750e1e3e7b492bfbf87e 100644
|
||||
--- a/src/tests/gl_tests/WebGLCompatibilityTest.cpp
|
||||
+++ b/src/tests/gl_tests/WebGLCompatibilityTest.cpp
|
||||
@@ -5073,6 +5073,21 @@ void WebGLCompatibilityTest::testCompressedTexLevelDimension(GLenum format,
|
||||
{
|
||||
EXPECT_GL_ERROR(expectedError) << explanation;
|
||||
}
|
||||
+
|
||||
+ if (level == 0 && width > 0 && getClientMajorVersion() >= 3)
|
||||
+ {
|
||||
+ GLTexture sourceTextureStorage;
|
||||
+ glBindTexture(GL_TEXTURE_2D, sourceTextureStorage);
|
||||
+ glTexStorage2D(GL_TEXTURE_2D, 1, format, width, height);
|
||||
+ if (expectedError == 0)
|
||||
+ {
|
||||
+ EXPECT_GL_NO_ERROR() << explanation << " (texStorage)";
|
||||
+ }
|
||||
+ else
|
||||
+ {
|
||||
+ EXPECT_GL_ERROR(expectedError) << explanation << " (texStorage)";
|
||||
+ }
|
||||
+ }
|
||||
}
|
||||
|
||||
void WebGLCompatibilityTest::testCompressedTexImage(GLenum format)
|
||||
69
patches/angle/cherry-pick-72473550f6ff.patch
Normal file
69
patches/angle/cherry-pick-72473550f6ff.patch
Normal file
@@ -0,0 +1,69 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Jamie Madill <jmadill@chromium.org>
|
||||
Date: Wed, 1 Sep 2021 12:17:26 -0400
|
||||
Subject: D3D11: Fix overflow in GenerateInitialTextureData.
|
||||
|
||||
Our use of unchecked math was causing OOB accesses with very large
|
||||
textures. Unfortunately it's not easy to make a passing test that
|
||||
reproduces this OOB access.
|
||||
|
||||
Bug: chromium:1241036
|
||||
Change-Id: Icd2749f5b3116bb51390ce769fef22c49a11f307
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/3136733
|
||||
Reviewed-by: Geoff Lang <geofflang@chromium.org>
|
||||
Commit-Queue: Jamie Madill <jmadill@chromium.org>
|
||||
(cherry picked from commit 794b13ce9f874d472729ebd69897bc7ab9340a4b)
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/3149277
|
||||
Reviewed-by: Jamie Madill <jmadill@chromium.org>
|
||||
|
||||
diff --git a/src/libANGLE/renderer/d3d/d3d11/renderer11_utils.cpp b/src/libANGLE/renderer/d3d/d3d11/renderer11_utils.cpp
|
||||
index 3915a89de6fd161fa72519d4b9b6e82db68c6c66..6d721bd6e72d21454a868965993d930fe138b58c 100644
|
||||
--- a/src/libANGLE/renderer/d3d/d3d11/renderer11_utils.cpp
|
||||
+++ b/src/libANGLE/renderer/d3d/d3d11/renderer11_utils.cpp
|
||||
@@ -2181,28 +2181,35 @@ angle::Result GenerateInitialTextureData(
|
||||
const d3d11::DXGIFormatSize &dxgiFormatInfo =
|
||||
d3d11::GetDXGIFormatSizeInfo(d3dFormatInfo.texFormat);
|
||||
|
||||
- unsigned int rowPitch = dxgiFormatInfo.pixelBytes * width;
|
||||
- unsigned int depthPitch = rowPitch * height;
|
||||
- unsigned int maxImageSize = depthPitch * depth;
|
||||
+ using CheckedSize = angle::CheckedNumeric<size_t>;
|
||||
+ CheckedSize rowPitch = CheckedSize(dxgiFormatInfo.pixelBytes) * CheckedSize(width);
|
||||
+ CheckedSize depthPitch = rowPitch * CheckedSize(height);
|
||||
+ CheckedSize maxImageSize = depthPitch * CheckedSize(depth);
|
||||
+
|
||||
+ Context11 *context11 = GetImplAs<Context11>(context);
|
||||
+ ANGLE_CHECK_GL_ALLOC(context11, maxImageSize.IsValid());
|
||||
|
||||
angle::MemoryBuffer *scratchBuffer = nullptr;
|
||||
- ANGLE_CHECK_GL_ALLOC(GetImplAs<Context11>(context),
|
||||
- context->getScratchBuffer(maxImageSize, &scratchBuffer));
|
||||
+ ANGLE_CHECK_GL_ALLOC(context11,
|
||||
+ context->getScratchBuffer(maxImageSize.ValueOrDie(), &scratchBuffer));
|
||||
|
||||
- d3dFormatInfo.dataInitializerFunction(width, height, depth, scratchBuffer->data(), rowPitch,
|
||||
- depthPitch);
|
||||
+ d3dFormatInfo.dataInitializerFunction(width, height, depth, scratchBuffer->data(),
|
||||
+ rowPitch.ValueOrDie(), depthPitch.ValueOrDie());
|
||||
|
||||
for (unsigned int i = 0; i < mipLevels; i++)
|
||||
{
|
||||
unsigned int mipWidth = std::max(width >> i, 1U);
|
||||
unsigned int mipHeight = std::max(height >> i, 1U);
|
||||
|
||||
- unsigned int mipRowPitch = dxgiFormatInfo.pixelBytes * mipWidth;
|
||||
- unsigned int mipDepthPitch = mipRowPitch * mipHeight;
|
||||
+ using CheckedUINT = angle::CheckedNumeric<UINT>;
|
||||
+ CheckedUINT mipRowPitch = CheckedUINT(dxgiFormatInfo.pixelBytes) * CheckedUINT(mipWidth);
|
||||
+ CheckedUINT mipDepthPitch = mipRowPitch * CheckedUINT(mipHeight);
|
||||
+
|
||||
+ ANGLE_CHECK_GL_ALLOC(context11, mipRowPitch.IsValid() && mipDepthPitch.IsValid());
|
||||
|
||||
outSubresourceData->at(i).pSysMem = scratchBuffer->data();
|
||||
- outSubresourceData->at(i).SysMemPitch = mipRowPitch;
|
||||
- outSubresourceData->at(i).SysMemSlicePitch = mipDepthPitch;
|
||||
+ outSubresourceData->at(i).SysMemPitch = mipRowPitch.ValueOrDie();
|
||||
+ outSubresourceData->at(i).SysMemSlicePitch = mipDepthPitch.ValueOrDie();
|
||||
}
|
||||
|
||||
return angle::Result::Continue;
|
||||
300
patches/angle/cherry-pick-d8cb996.patch
Normal file
300
patches/angle/cherry-pick-d8cb996.patch
Normal file
@@ -0,0 +1,300 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Kenneth Russell <kbr@chromium.org>
|
||||
Date: Wed, 4 Aug 2021 18:15:51 -0700
|
||||
Subject: In WebGL, constrain base level of compressed textures.
|
||||
|
||||
Enforce that if a mipmap level > 0 is specified for a compressed
|
||||
texture, that it implies that the size of the base level of the
|
||||
texture is a multiple of the format's block size.
|
||||
|
||||
Makes the test changes in
|
||||
https://github.com/KhronosGroup/WebGL/pull/3304 largely pass. There
|
||||
are some needed follow-on fixes to that PR, and this CL changes a
|
||||
sub-test result in the existing S3TC and S3TC-sRGB tests which will
|
||||
need to be suppressed Chromium-side first.
|
||||
|
||||
Bug: angleproject:6245
|
||||
Change-Id: I7723d7882091b78a353d8d273e80b819dd384021
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/3072568
|
||||
Commit-Queue: Kenneth Russell <kbr@chromium.org>
|
||||
Reviewed-by: Jamie Madill <jmadill@chromium.org>
|
||||
Reviewed-by: Shahbaz Youssefi <syoussefi@chromium.org>
|
||||
|
||||
diff --git a/src/libANGLE/validationES.cpp b/src/libANGLE/validationES.cpp
|
||||
index 656e51f17724af9e0959fcd741ceeebf25ee0f24..412b9aa0f1d75c40ce02522589c53e943d049228 100644
|
||||
--- a/src/libANGLE/validationES.cpp
|
||||
+++ b/src/libANGLE/validationES.cpp
|
||||
@@ -1006,6 +1006,15 @@ bool ValidCompressedDimension(GLsizei size, GLuint blockSize, GLint level)
|
||||
return (level > 0) || (size % blockSize == 0);
|
||||
}
|
||||
|
||||
+bool ValidCompressedBaseLevelForWebGL(GLsizei size, GLuint blockSize, GLint level)
|
||||
+{
|
||||
+ // Avoid C++ undefined behavior.
|
||||
+ constexpr int maxValidShifts = 31;
|
||||
+ if (level > maxValidShifts)
|
||||
+ return false;
|
||||
+ return ((size << level) % blockSize) == 0;
|
||||
+}
|
||||
+
|
||||
bool ValidCompressedImageSize(const Context *context,
|
||||
GLenum internalFormat,
|
||||
GLint level,
|
||||
@@ -1043,11 +1052,27 @@ bool ValidCompressedImageSize(const Context *context,
|
||||
|
||||
if (CompressedTextureFormatRequiresExactSize(internalFormat))
|
||||
{
|
||||
- if (!ValidCompressedDimension(width, formatInfo.compressedBlockWidth, level) ||
|
||||
- !ValidCompressedDimension(height, formatInfo.compressedBlockHeight, level) ||
|
||||
- !ValidCompressedDimension(depth, formatInfo.compressedBlockDepth, level))
|
||||
+ // In WebGL compatibility mode, enforce that the base level implied
|
||||
+ // by the compressed texture's mip level would conform to the block
|
||||
+ // size. This is more strict than the non-WebGL check.
|
||||
+ if (context->getExtensions().webglCompatibility)
|
||||
{
|
||||
- return false;
|
||||
+ if (!ValidCompressedBaseLevelForWebGL(width, formatInfo.compressedBlockWidth, level) ||
|
||||
+ !ValidCompressedBaseLevelForWebGL(height, formatInfo.compressedBlockHeight,
|
||||
+ level) ||
|
||||
+ !ValidCompressedBaseLevelForWebGL(depth, formatInfo.compressedBlockDepth, level))
|
||||
+ {
|
||||
+ return false;
|
||||
+ }
|
||||
+ }
|
||||
+ else
|
||||
+ {
|
||||
+ if (!ValidCompressedDimension(width, formatInfo.compressedBlockWidth, level) ||
|
||||
+ !ValidCompressedDimension(height, formatInfo.compressedBlockHeight, level) ||
|
||||
+ !ValidCompressedDimension(depth, formatInfo.compressedBlockDepth, level))
|
||||
+ {
|
||||
+ return false;
|
||||
+ }
|
||||
}
|
||||
}
|
||||
|
||||
diff --git a/src/tests/gl_tests/WebGLCompatibilityTest.cpp b/src/tests/gl_tests/WebGLCompatibilityTest.cpp
|
||||
index 40c9a02e3eafe9d437e20e72a391bad73c783516..fabaefbe33c94a048ec7c974951ac9ef886826ef 100644
|
||||
--- a/src/tests/gl_tests/WebGLCompatibilityTest.cpp
|
||||
+++ b/src/tests/gl_tests/WebGLCompatibilityTest.cpp
|
||||
@@ -296,6 +296,16 @@ void main()
|
||||
GLsizei blockSize,
|
||||
const std::string &extName,
|
||||
bool subImageAllowed);
|
||||
+
|
||||
+ GLint expectedByteLength(GLenum format, GLsizei width, GLsizei height);
|
||||
+ void testCompressedTexLevelDimension(GLenum format,
|
||||
+ GLint level,
|
||||
+ GLsizei width,
|
||||
+ GLsizei height,
|
||||
+ GLsizei expectedByteLength,
|
||||
+ GLenum expectedError,
|
||||
+ const char *explanation);
|
||||
+ void testCompressedTexImage(GLenum format);
|
||||
};
|
||||
|
||||
class WebGL2CompatibilityTest : public WebGLCompatibilityTest
|
||||
@@ -3040,6 +3050,84 @@ TEST_P(WebGLCompatibilityTest, CompressedTextureS3TC)
|
||||
ASSERT_GL_ERROR(GL_INVALID_OPERATION);
|
||||
}
|
||||
|
||||
+// Test WebGL-specific constraints on sizes of S3TC textures' mipmap levels.
|
||||
+TEST_P(WebGLCompatibilityTest, CompressedTexImageS3TC)
|
||||
+{
|
||||
+ const char *extensions[] = {
|
||||
+ "GL_EXT_texture_compression_dxt1",
|
||||
+ "GL_ANGLE_texture_compression_dxt3",
|
||||
+ "GL_ANGLE_texture_compression_dxt5",
|
||||
+ };
|
||||
+
|
||||
+ for (const char *extension : extensions)
|
||||
+ {
|
||||
+ if (IsGLExtensionRequestable(extension))
|
||||
+ {
|
||||
+ glRequestExtensionANGLE(extension);
|
||||
+ }
|
||||
+
|
||||
+ ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled(extension));
|
||||
+ }
|
||||
+
|
||||
+ // Ported from WebGL conformance suite:
|
||||
+ // sdk/tests/conformance/extensions/s3tc-and-srgb.html
|
||||
+ constexpr GLenum formats[] = {
|
||||
+ GL_COMPRESSED_RGB_S3TC_DXT1_EXT,
|
||||
+ GL_COMPRESSED_RGBA_S3TC_DXT1_EXT,
|
||||
+ GL_COMPRESSED_RGBA_S3TC_DXT3_EXT,
|
||||
+ GL_COMPRESSED_RGBA_S3TC_DXT5_EXT,
|
||||
+ };
|
||||
+
|
||||
+ for (GLenum format : formats)
|
||||
+ {
|
||||
+ testCompressedTexImage(format);
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+// Test WebGL-specific constraints on sizes of RGTC textures' mipmap levels.
|
||||
+TEST_P(WebGLCompatibilityTest, CompressedTexImageRGTC)
|
||||
+{
|
||||
+ if (IsGLExtensionRequestable("GL_EXT_texture_compression_rgtc"))
|
||||
+ {
|
||||
+ glRequestExtensionANGLE("GL_EXT_texture_compression_rgtc");
|
||||
+ }
|
||||
+
|
||||
+ ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_texture_compression_rgtc"));
|
||||
+
|
||||
+ // Ported from WebGL conformance suite:
|
||||
+ // sdk/tests/conformance/extensions/ext-texture-compression-rgtc.html
|
||||
+ constexpr GLenum formats[] = {GL_COMPRESSED_RED_RGTC1_EXT, GL_COMPRESSED_SIGNED_RED_RGTC1_EXT,
|
||||
+ GL_COMPRESSED_RED_GREEN_RGTC2_EXT,
|
||||
+ GL_COMPRESSED_SIGNED_RED_GREEN_RGTC2_EXT};
|
||||
+
|
||||
+ for (GLenum format : formats)
|
||||
+ {
|
||||
+ testCompressedTexImage(format);
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+// Test WebGL-specific constraints on sizes of BPTC textures' mipmap levels.
|
||||
+TEST_P(WebGLCompatibilityTest, CompressedTexImageBPTC)
|
||||
+{
|
||||
+ if (IsGLExtensionRequestable("GL_EXT_texture_compression_bptc"))
|
||||
+ {
|
||||
+ glRequestExtensionANGLE("GL_EXT_texture_compression_bptc");
|
||||
+ }
|
||||
+
|
||||
+ ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_EXT_texture_compression_bptc"));
|
||||
+
|
||||
+ // Ported from WebGL conformance suite:
|
||||
+ // sdk/tests/conformance/extensions/ext-texture-compression-bptc.html
|
||||
+ constexpr GLenum formats[] = {
|
||||
+ GL_COMPRESSED_RGBA_BPTC_UNORM_EXT, GL_COMPRESSED_SRGB_ALPHA_BPTC_UNORM_EXT,
|
||||
+ GL_COMPRESSED_RGB_BPTC_SIGNED_FLOAT_EXT, GL_COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT_EXT};
|
||||
+
|
||||
+ for (GLenum format : formats)
|
||||
+ {
|
||||
+ testCompressedTexImage(format);
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
TEST_P(WebGLCompatibilityTest, L32FTextures)
|
||||
{
|
||||
constexpr float textureData[] = {15.1f, 0.0f, 0.0f, 0.0f};
|
||||
@@ -4937,6 +5025,119 @@ void WebGLCompatibilityTest::validateCompressedTexImageExtensionFormat(GLenum fo
|
||||
}
|
||||
}
|
||||
|
||||
+GLint WebGLCompatibilityTest::expectedByteLength(GLenum format, GLsizei width, GLsizei height)
|
||||
+{
|
||||
+ switch (format)
|
||||
+ {
|
||||
+ case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
|
||||
+ case GL_COMPRESSED_RGBA_S3TC_DXT1_EXT:
|
||||
+ case GL_COMPRESSED_RED_RGTC1_EXT:
|
||||
+ case GL_COMPRESSED_SIGNED_RED_RGTC1_EXT:
|
||||
+ return ((width + 3) / 4) * ((height + 3) / 4) * 8;
|
||||
+ case GL_COMPRESSED_RGBA_S3TC_DXT3_EXT:
|
||||
+ case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT:
|
||||
+ case GL_COMPRESSED_RED_GREEN_RGTC2_EXT:
|
||||
+ case GL_COMPRESSED_SIGNED_RED_GREEN_RGTC2_EXT:
|
||||
+ case GL_COMPRESSED_RGBA_BPTC_UNORM_EXT:
|
||||
+ case GL_COMPRESSED_SRGB_ALPHA_BPTC_UNORM_EXT:
|
||||
+ case GL_COMPRESSED_RGB_BPTC_SIGNED_FLOAT_EXT:
|
||||
+ case GL_COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT_EXT:
|
||||
+ return ((width + 3) / 4) * ((height + 3) / 4) * 16;
|
||||
+ }
|
||||
+
|
||||
+ UNREACHABLE();
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+void WebGLCompatibilityTest::testCompressedTexLevelDimension(GLenum format,
|
||||
+ GLint level,
|
||||
+ GLsizei width,
|
||||
+ GLsizei height,
|
||||
+ GLsizei expectedByteLength,
|
||||
+ GLenum expectedError,
|
||||
+ const char *explanation)
|
||||
+{
|
||||
+ std::vector<uint8_t> tempVector(expectedByteLength, 0);
|
||||
+
|
||||
+ EXPECT_GL_NO_ERROR();
|
||||
+
|
||||
+ GLTexture sourceTexture;
|
||||
+ glBindTexture(GL_TEXTURE_2D, sourceTexture);
|
||||
+ glCompressedTexImage2D(GL_TEXTURE_2D, level, format, width, height, 0, expectedByteLength,
|
||||
+ tempVector.data());
|
||||
+ if (expectedError == 0)
|
||||
+ {
|
||||
+ EXPECT_GL_NO_ERROR() << explanation;
|
||||
+ }
|
||||
+ else
|
||||
+ {
|
||||
+ EXPECT_GL_ERROR(expectedError) << explanation;
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+void WebGLCompatibilityTest::testCompressedTexImage(GLenum format)
|
||||
+{
|
||||
+ struct TestCase
|
||||
+ {
|
||||
+ GLint level;
|
||||
+ GLsizei width;
|
||||
+ GLsizei height;
|
||||
+ GLenum expectedError;
|
||||
+ const char *explanation;
|
||||
+ };
|
||||
+
|
||||
+ constexpr TestCase testCases[] = {
|
||||
+ {0, 4, 3, GL_INVALID_OPERATION, "level is 0, height is not a multiple of 4"},
|
||||
+ {0, 3, 4, GL_INVALID_OPERATION, "level is 0, width is not a multiple of 4"},
|
||||
+ {0, 2, 2, GL_INVALID_OPERATION, "level is 0, width is not a multiple of 4"},
|
||||
+ {0, 4, 4, GL_NO_ERROR, "is valid"},
|
||||
+ {1, 1, 1, GL_INVALID_OPERATION, "implied base mip 2x2 is invalid"},
|
||||
+ {1, 1, 2, GL_INVALID_OPERATION, "implied base mip 2x4 is invalid"},
|
||||
+ {1, 2, 1, GL_INVALID_OPERATION, "implied base mip 4x2 is invalid"},
|
||||
+ {1, 2, 2, GL_NO_ERROR, "implied base mip 4x4 is valid"},
|
||||
+ };
|
||||
+
|
||||
+ constexpr TestCase webgl2TestCases[] = {
|
||||
+ {0, 0, 0, GL_NO_ERROR, "0: 0x0 is valid"},
|
||||
+ {0, 1, 1, GL_INVALID_OPERATION, "0: 1x1 is invalid"},
|
||||
+ {0, 2, 2, GL_INVALID_OPERATION, "0: 2x2 is invalid"},
|
||||
+ {0, 3, 3, GL_INVALID_OPERATION, "0: 3x3 is invalid"},
|
||||
+ {0, 10, 10, GL_INVALID_OPERATION, "0: 10x10 is invalid"},
|
||||
+ {0, 11, 11, GL_INVALID_OPERATION, "0: 11x11 is invalid"},
|
||||
+ {0, 11, 12, GL_INVALID_OPERATION, "0: 11x12 is invalid"},
|
||||
+ {0, 12, 11, GL_INVALID_OPERATION, "0: 12x11 is invalid"},
|
||||
+ {0, 12, 12, GL_NO_ERROR, "0: 12x12 is valid"},
|
||||
+ {1, 0, 0, GL_NO_ERROR, "1: 0x0 is valid"},
|
||||
+ {1, 3, 3, GL_INVALID_OPERATION, "1: 3x3 is invalid"},
|
||||
+ {1, 5, 5, GL_INVALID_OPERATION, "1: 5x5 is invalid"},
|
||||
+ {1, 5, 6, GL_INVALID_OPERATION, "1: 5x6 is invalid"},
|
||||
+ {1, 6, 5, GL_INVALID_OPERATION, "1: 6x5 is invalid"},
|
||||
+ {1, 6, 6, GL_NO_ERROR, "1: 6x6 is valid"},
|
||||
+ {2, 0, 0, GL_NO_ERROR, "2: 0x0 is valid"},
|
||||
+ {2, 3, 3, GL_NO_ERROR, "2: 3x3 is valid"},
|
||||
+ {3, 1, 3, GL_NO_ERROR, "3: 1x3 is valid"},
|
||||
+ {3, 1, 1, GL_NO_ERROR, "3: 1x1 is valid"},
|
||||
+ {2, 1, 3, GL_NO_ERROR, "implied base mip 4x12 is valid"},
|
||||
+ };
|
||||
+
|
||||
+ for (const TestCase &test : testCases)
|
||||
+ {
|
||||
+ testCompressedTexLevelDimension(format, test.level, test.width, test.height,
|
||||
+ expectedByteLength(format, test.width, test.height),
|
||||
+ test.expectedError, test.explanation);
|
||||
+ }
|
||||
+
|
||||
+ if (getClientMajorVersion() >= 3)
|
||||
+ {
|
||||
+ for (const TestCase &test : webgl2TestCases)
|
||||
+ {
|
||||
+ testCompressedTexLevelDimension(format, test.level, test.width, test.height,
|
||||
+ expectedByteLength(format, test.width, test.height),
|
||||
+ test.expectedError, test.explanation);
|
||||
+ }
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
// Test enabling GL_EXT_texture_compression_dxt1 for GL_COMPRESSED_RGB_S3TC_DXT1_EXT
|
||||
TEST_P(WebGLCompatibilityTest, EnableCompressedTextureExtensionDXT1RGB)
|
||||
{
|
||||
112
patches/angle/fix_integer_overflow_in_blocklayoutencoder.patch
Normal file
112
patches/angle/fix_integer_overflow_in_blocklayoutencoder.patch
Normal file
@@ -0,0 +1,112 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Alexis Hetu <sugoi@google.com>
|
||||
Date: Wed, 15 Sep 2021 13:40:28 -0400
|
||||
Subject: Fix integer overflow in BlockLayoutEncoder
|
||||
MIME-Version: 1.0
|
||||
Content-Type: text/plain; charset=UTF-8
|
||||
Content-Transfer-Encoding: 8bit
|
||||
|
||||
BlockLayoutEncoder::mCurrentOffset's computation had the
|
||||
possibility of causing integer overflows in multiple places,
|
||||
so this CL adds CheckedNumeric variables in a number of
|
||||
these occurrences in order to prevent integer overflows and
|
||||
causing issues.
|
||||
|
||||
The issue in this case was an integer overflow causing the
|
||||
code in ValidateTypeSizeLimitations.cpp to use an invalid
|
||||
result from "layoutEncoder.getCurrentOffset()", which ended
|
||||
up compiling a shader which would later cause an OOM error.
|
||||
|
||||
Bug: chromium:1248665
|
||||
Change-Id: I688d669f21c6dc2957e43bdf91f8f8f08180a6f7
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/3163356
|
||||
Reviewed-by: Jamie Madill <jmadill@chromium.org>
|
||||
Reviewed-by: Kenneth Russell <kbr@chromium.org>
|
||||
Reviewed-by: Geoff Lang <geofflang@chromium.org>
|
||||
Commit-Queue: Alexis Hétu <sugoi@chromium.org>
|
||||
(cherry picked from commit 158ef351fc8b827c201e056a8ddba50fd4235671)
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/3194392
|
||||
|
||||
diff --git a/src/compiler/translator/blocklayout.cpp b/src/compiler/translator/blocklayout.cpp
|
||||
index 0539923bc75f5b88228dcb387c8aba4c701edc1b..1e6b143a1e1ee9a127b71685febd36416a8840f6 100644
|
||||
--- a/src/compiler/translator/blocklayout.cpp
|
||||
+++ b/src/compiler/translator/blocklayout.cpp
|
||||
@@ -199,6 +199,13 @@ BlockMemberInfo BlockLayoutEncoder::encodeType(GLenum type,
|
||||
return memberInfo;
|
||||
}
|
||||
|
||||
+size_t BlockLayoutEncoder::getCurrentOffset() const
|
||||
+{
|
||||
+ angle::base::CheckedNumeric<size_t> checkedOffset(mCurrentOffset);
|
||||
+ checkedOffset *= kBytesPerComponent;
|
||||
+ return checkedOffset.ValueOrDefault(std::numeric_limits<size_t>::max());
|
||||
+}
|
||||
+
|
||||
size_t BlockLayoutEncoder::getShaderVariableSize(const ShaderVariable &structVar, bool isRowMajor)
|
||||
{
|
||||
size_t currentOffset = mCurrentOffset;
|
||||
@@ -226,7 +233,13 @@ size_t BlockLayoutEncoder::GetBlockRegisterElement(const BlockMemberInfo &info)
|
||||
|
||||
void BlockLayoutEncoder::align(size_t baseAlignment)
|
||||
{
|
||||
- mCurrentOffset = rx::roundUp<size_t>(mCurrentOffset, baseAlignment);
|
||||
+ angle::base::CheckedNumeric<size_t> checkedOffset(mCurrentOffset);
|
||||
+ checkedOffset += baseAlignment;
|
||||
+ checkedOffset -= 1;
|
||||
+ angle::base::CheckedNumeric<size_t> checkedAlignmentOffset = checkedOffset;
|
||||
+ checkedAlignmentOffset %= baseAlignment;
|
||||
+ checkedOffset -= checkedAlignmentOffset.ValueOrDefault(std::numeric_limits<size_t>::max());
|
||||
+ mCurrentOffset = checkedOffset.ValueOrDefault(std::numeric_limits<size_t>::max());
|
||||
}
|
||||
|
||||
// StubBlockEncoder implementation.
|
||||
@@ -289,7 +302,7 @@ void Std140BlockEncoder::getBlockLayoutInfo(GLenum type,
|
||||
baseAlignment = ComponentAlignment(numComponents);
|
||||
}
|
||||
|
||||
- mCurrentOffset = rx::roundUp(mCurrentOffset, baseAlignment);
|
||||
+ align(baseAlignment);
|
||||
|
||||
*matrixStrideOut = matrixStride;
|
||||
*arrayStrideOut = arrayStride;
|
||||
@@ -303,16 +316,23 @@ void Std140BlockEncoder::advanceOffset(GLenum type,
|
||||
{
|
||||
if (!arraySizes.empty())
|
||||
{
|
||||
- mCurrentOffset += arrayStride * gl::ArraySizeProduct(arraySizes);
|
||||
+ angle::base::CheckedNumeric<size_t> checkedOffset(arrayStride);
|
||||
+ checkedOffset *= gl::ArraySizeProduct(arraySizes);
|
||||
+ checkedOffset += mCurrentOffset;
|
||||
+ mCurrentOffset = checkedOffset.ValueOrDefault(std::numeric_limits<size_t>::max());
|
||||
}
|
||||
else if (gl::IsMatrixType(type))
|
||||
{
|
||||
- const int numRegisters = gl::MatrixRegisterCount(type, isRowMajorMatrix);
|
||||
- mCurrentOffset += matrixStride * numRegisters;
|
||||
+ angle::base::CheckedNumeric<size_t> checkedOffset(matrixStride);
|
||||
+ checkedOffset *= gl::MatrixRegisterCount(type, isRowMajorMatrix);
|
||||
+ checkedOffset += mCurrentOffset;
|
||||
+ mCurrentOffset = checkedOffset.ValueOrDefault(std::numeric_limits<size_t>::max());
|
||||
}
|
||||
else
|
||||
{
|
||||
- mCurrentOffset += gl::VariableComponentCount(type);
|
||||
+ angle::base::CheckedNumeric<size_t> checkedOffset(mCurrentOffset);
|
||||
+ checkedOffset += gl::VariableComponentCount(type);
|
||||
+ mCurrentOffset = checkedOffset.ValueOrDefault(std::numeric_limits<size_t>::max());
|
||||
}
|
||||
}
|
||||
|
||||
diff --git a/src/compiler/translator/blocklayout.h b/src/compiler/translator/blocklayout.h
|
||||
index 726d76fa178f77a978ff2c82ec20fb8f1ad03f0b..ff90a2487830b365697ce41d660a689857b75319 100644
|
||||
--- a/src/compiler/translator/blocklayout.h
|
||||
+++ b/src/compiler/translator/blocklayout.h
|
||||
@@ -80,7 +80,7 @@ class BlockLayoutEncoder
|
||||
const std::vector<unsigned int> &arraySizes,
|
||||
bool isRowMajorMatrix);
|
||||
|
||||
- size_t getCurrentOffset() const { return mCurrentOffset * kBytesPerComponent; }
|
||||
+ size_t getCurrentOffset() const;
|
||||
size_t getShaderVariableSize(const ShaderVariable &structVar, bool isRowMajor);
|
||||
|
||||
// Called when entering/exiting a structure variable.
|
||||
@@ -0,0 +1,34 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Jamie Madill <jmadill@chromium.org>
|
||||
Date: Fri, 3 Sep 2021 09:34:10 -0400
|
||||
Subject: WebGL: Make unsuccessful links fail subsequent draw calls.
|
||||
|
||||
This protects against incomplete state updates during a failed
|
||||
link call that can interfere with draw calls.
|
||||
|
||||
Bug: angleproject:6358
|
||||
Bug: chromium:1241123
|
||||
Change-Id: Ie892654c3a58c69d6e35ba3c41758ab6269d8193
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/3140496
|
||||
Reviewed-by: Geoff Lang <geofflang@chromium.org>
|
||||
Commit-Queue: Yuly Novikov <ynovikov@chromium.org>
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/3152556
|
||||
Reviewed-by: Jamie Madill <jmadill@chromium.org>
|
||||
|
||||
diff --git a/src/libANGLE/validationES.cpp b/src/libANGLE/validationES.cpp
|
||||
index 412b9aa0f1d75c40ce02522589c53e943d049228..7826233f206b2ae7b926cd2564c887c726b79930 100644
|
||||
--- a/src/libANGLE/validationES.cpp
|
||||
+++ b/src/libANGLE/validationES.cpp
|
||||
@@ -3958,6 +3958,12 @@ const char *ValidateDrawStates(const Context *context)
|
||||
{
|
||||
return kVertexBufferBoundForTransformFeedback;
|
||||
}
|
||||
+
|
||||
+ // Validate that we are rendering with a linked program.
|
||||
+ if (!program->isLinked())
|
||||
+ {
|
||||
+ return kProgramNotLinked;
|
||||
+ }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,2 +1,3 @@
|
||||
expose_ripemd160.patch
|
||||
expose_aes-cfb.patch
|
||||
expose_des-ede3.patch
|
||||
|
||||
40
patches/boringssl/expose_des-ede3.patch
Normal file
40
patches/boringssl/expose_des-ede3.patch
Normal file
@@ -0,0 +1,40 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Jeremy Rose <nornagon@nornagon.net>
|
||||
Date: Wed, 24 Feb 2021 11:08:34 -0800
|
||||
Subject: expose des-ede3
|
||||
|
||||
This should be upstreamed.
|
||||
|
||||
diff --git a/crypto/cipher_extra/cipher_extra.c b/crypto/cipher_extra/cipher_extra.c
|
||||
index 588a4773437c311877f275bf3679f9688cda3c46..e771ed6589b4579cc35300d5b2a1b68d92e444f5 100644
|
||||
--- a/crypto/cipher_extra/cipher_extra.c
|
||||
+++ b/crypto/cipher_extra/cipher_extra.c
|
||||
@@ -93,6 +93,8 @@ const EVP_CIPHER *EVP_get_cipherbyname(const char *name) {
|
||||
return EVP_rc4();
|
||||
} else if (OPENSSL_strcasecmp(name, "des-cbc") == 0) {
|
||||
return EVP_des_cbc();
|
||||
+ } else if (OPENSSL_strcasecmp(name, "des-ede3") == 0) {
|
||||
+ return EVP_des_ede3();
|
||||
} else if (OPENSSL_strcasecmp(name, "des-ede3-cbc") == 0 ||
|
||||
// This is not a name used by OpenSSL, but tcpdump registers it
|
||||
// with |EVP_add_cipher_alias|. Our |EVP_add_cipher_alias| is a
|
||||
diff --git a/decrepit/evp/evp_do_all.c b/decrepit/evp/evp_do_all.c
|
||||
index 84af06fc56e4aa72d4d48801d7c037add0221747..fe412e350f43ad20758025da6b9754952d164938 100644
|
||||
--- a/decrepit/evp/evp_do_all.c
|
||||
+++ b/decrepit/evp/evp_do_all.c
|
||||
@@ -39,6 +39,7 @@ void EVP_CIPHER_do_all_sorted(void (*callback)(const EVP_CIPHER *cipher,
|
||||
callback(EVP_des_cbc(), "DES-CBC", NULL, arg);
|
||||
callback(EVP_des_ecb(), "DES-ECB", NULL, arg);
|
||||
callback(EVP_des_ede(), "DES-EDE", NULL, arg);
|
||||
+ callback(EVP_des_ede3(), "DES-EDE3", NULL, arg);
|
||||
callback(EVP_des_ede_cbc(), "DES-EDE-CBC", NULL, arg);
|
||||
callback(EVP_des_ede3_cbc(), "DES-EDE3-CBC", NULL, arg);
|
||||
callback(EVP_rc2_cbc(), "RC2-CBC", NULL, arg);
|
||||
@@ -65,6 +66,7 @@ void EVP_CIPHER_do_all_sorted(void (*callback)(const EVP_CIPHER *cipher,
|
||||
callback(EVP_des_cbc(), "des-cbc", NULL, arg);
|
||||
callback(EVP_des_ecb(), "des-ecb", NULL, arg);
|
||||
callback(EVP_des_ede(), "des-ede", NULL, arg);
|
||||
+ callback(EVP_des_ede3(), "des-ede3", NULL, arg);
|
||||
callback(EVP_des_ede_cbc(), "des-ede-cbc", NULL, arg);
|
||||
callback(EVP_des_ede3_cbc(), "des-ede3-cbc", NULL, arg);
|
||||
callback(EVP_rc2_cbc(), "rc2-cbc", NULL, arg);
|
||||
@@ -102,6 +102,7 @@ fix_export_zlib_symbols.patch
|
||||
don_t_use_potentially_null_getwebframe_-_view_when_get_blink.patch
|
||||
web_contents.patch
|
||||
fix_route_mouse_event_navigations_through_the_web_contents_delegate.patch
|
||||
webview_fullscreen.patch
|
||||
disable_unload_metrics.patch
|
||||
fix_add_check_for_sandbox_then_result.patch
|
||||
moves_background_color_setter_of_webview_to_blinks_webprefs_logic.patch
|
||||
@@ -113,3 +114,59 @@ build_libc_as_static_library.patch
|
||||
cherry-pick-3299d70b7d0f.patch
|
||||
support_runtime_configurable_key_storage_on_linux_os_crypto.patch
|
||||
make_keychain_service_account_optionally_configurable_at_runtime.patch
|
||||
don_t_run_pcscan_notifythreadcreated_if_pcscan_is_disabled.patch
|
||||
cherry-pick-cc20b36a5845.patch
|
||||
set_svgimage_page_after_document_install.patch
|
||||
cherry-pick-5487040a284a.patch
|
||||
cherry-pick-e60cc80ff744.patch
|
||||
add_gin_wrappable_crash_key.patch
|
||||
cherry-pick-cd98d7c0dae9.patch
|
||||
cherry-pick-ac9dc1235e28.patch
|
||||
cherry-pick-4ce2abc17078.patch
|
||||
cherry-pick-e2123a8e0943.patch
|
||||
cherry-pick-1227933.patch
|
||||
cherry-pick-1230767.patch
|
||||
cherry-pick-1231134.patch
|
||||
cherry-pick-1233564.patch
|
||||
cherry-pick-1234009.patch
|
||||
fix_media_key_usage_with_globalshortcuts.patch
|
||||
attach_to_correct_frame_in.patch
|
||||
merge_m92_speculative_fix_for_crash_in.patch
|
||||
cherry-pick-d727013bb543.patch
|
||||
pa_make_getusablesize_handle_nullptr_gracefully.patch
|
||||
dpwas_window_control_overlay_api_values_account_for_page_zoom_factor.patch
|
||||
reland_make_clientview_a_child_of_the_nonclientframeview.patch
|
||||
content-visibility_force_range_base_extent_when_computing_visual.patch
|
||||
cherry-pick-6215793f008f.patch
|
||||
cherry-pick-6048fcd52f42.patch
|
||||
contentindex_add_origin_checks_to_mojo_methods.patch
|
||||
m93_indexeddb_add_browser-side_checks_for_committing_transactions.patch
|
||||
m93_indexeddb_don_t_reportbadmessage_for_commit_calls.patch
|
||||
cherry-pick-8623d711677d.patch
|
||||
cherry-pick-ddc4cf156505.patch
|
||||
skip_webgl_conformance_programs_program-test_html_on_all_platforms.patch
|
||||
linux_sandbox_update_syscall_numbers_for_all_platforms.patch
|
||||
linux_sandbox_return_enosys_for_clone3.patch
|
||||
content-visibility_add_a_clipper_fix_for_content-visibility.patch
|
||||
kill_a_renderer_if_it_provides_an_unexpected_frameownerelementtype.patch
|
||||
m90-lts_backgroundfetch_check_whether_the_sw_id_is_valid_for.patch
|
||||
cherry-pick-096afc1c5428.patch
|
||||
cherry-pick-4e528a5a8d83.patch
|
||||
cherry-pick-3a5bafa35def.patch
|
||||
cherry-pick-b2c4e4dc21e5.patch
|
||||
check_direction_of_rtcencodedframes.patch
|
||||
cherry-pick-6a8a2098f9fa.patch
|
||||
speculative_fix_for_eye_dropper_getcolor_crash.patch
|
||||
mas_gate_private_enterprise_APIs
|
||||
cherry-pick-c69dddfe1cde.patch
|
||||
cherry-pick-8af66de55aad.patch
|
||||
move_networkstateobserver_from_document_to_window.patch
|
||||
cherry-pick-0894af410c4e.patch
|
||||
disable_quictransport_explicitly_in_the_network_service.patch
|
||||
cherry-pick-91dd4f79ab5b.patch
|
||||
introduce_crossthreadcopier_skbitmap.patch
|
||||
allow_null_skbitmap_to_be_transferred_across_threads.patch
|
||||
use_weakptrs_for_the_threadediconloader_s_background_tasks.patch
|
||||
cachestorage_store_partial_opaque_responses.patch
|
||||
cherry-pick-a5f54612590d.patch
|
||||
m96_fileapi_move_origin_checks_in_bloburlstore_sooner.patch
|
||||
|
||||
48
patches/chromium/add_gin_wrappable_crash_key.patch
Normal file
48
patches/chromium/add_gin_wrappable_crash_key.patch
Normal file
@@ -0,0 +1,48 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: VerteDinde <khammond@slack-corp.com>
|
||||
Date: Thu, 15 Jul 2021 12:16:50 -0700
|
||||
Subject: chore: add gin::wrappable wrapperinfo crash key
|
||||
|
||||
This patch adds an additional crash key for gin::Wrappable, to help
|
||||
debug a crash that is occurring during garbage collection in SecondWeakCallback.
|
||||
|
||||
The crash seems to be due to a class that is holding a reference to
|
||||
gin::Wrappable even after being deleted. This added crash key compares
|
||||
the soon-to-be-deleted WrapperInfo with known WrapperInfo components to
|
||||
help determine where the crash originated from.
|
||||
|
||||
This patch should not be upstreamed, and can be removed in Electron 15 and
|
||||
beyond once we identify the cause of the crash.
|
||||
|
||||
diff --git a/gin/wrappable.cc b/gin/wrappable.cc
|
||||
index fe07eb94a8e679859bba6d76ff0d6ee86bd0c67e..ecb0aa2c4ec57e1814f4c94194e775440f4e35ee 100644
|
||||
--- a/gin/wrappable.cc
|
||||
+++ b/gin/wrappable.cc
|
||||
@@ -8,6 +8,11 @@
|
||||
#include "gin/object_template_builder.h"
|
||||
#include "gin/per_isolate_data.h"
|
||||
|
||||
+#if !defined(MAS_BUILD)
|
||||
+#include "components/crash/core/common/crash_key.h"
|
||||
+#include "electron/shell/common/crash_keys.h"
|
||||
+#endif
|
||||
+
|
||||
namespace gin {
|
||||
|
||||
WrappableBase::WrappableBase() = default;
|
||||
@@ -36,6 +41,15 @@ void WrappableBase::FirstWeakCallback(
|
||||
void WrappableBase::SecondWeakCallback(
|
||||
const v8::WeakCallbackInfo<WrappableBase>& data) {
|
||||
WrappableBase* wrappable = data.GetParameter();
|
||||
+
|
||||
+#if !defined(MAS_BUILD)
|
||||
+ WrapperInfo* wrapperInfo = static_cast<WrapperInfo*>(data.GetInternalField(0));
|
||||
+ std::string location = electron::crash_keys::GetCrashValueForGinWrappable(wrapperInfo);
|
||||
+
|
||||
+ static crash_reporter::CrashKeyString<32> crash_key("gin-wrappable-fatal.location");
|
||||
+ crash_reporter::ScopedCrashKeyString auto_clear(&crash_key, location);
|
||||
+#endif
|
||||
+
|
||||
delete wrappable;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,40 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Yutaka Hirano <yhirano@chromium.org>
|
||||
Date: Tue, 9 Nov 2021 09:03:17 +0000
|
||||
Subject: Allow null SkBitmap to be transferred across threads
|
||||
|
||||
(cherry picked from commit dad0c0e5162bcc49b8f60354d3bca92224d8381b)
|
||||
|
||||
Bug: 1241091
|
||||
Change-Id: Ie96932c14c8884d6d3eafa76dab5043e7aa31888
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3251815
|
||||
Reviewed-by: Florin Malita <fmalita@chromium.org>
|
||||
Commit-Queue: Yutaka Hirano <yhirano@chromium.org>
|
||||
Cr-Original-Commit-Position: refs/heads/main@{#936861}
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3268018
|
||||
Auto-Submit: Yutaka Hirano <yhirano@chromium.org>
|
||||
Reviewed-by: Kentaro Hara <haraken@chromium.org>
|
||||
Commit-Queue: Kentaro Hara <haraken@chromium.org>
|
||||
Cr-Commit-Position: refs/branch-heads/4664@{#893}
|
||||
Cr-Branched-From: 24dc4ee75e01a29d390d43c9c264372a169273a7-refs/heads/main@{#929512}
|
||||
|
||||
diff --git a/third_party/blink/renderer/platform/graphics/skia/skia_utils.h b/third_party/blink/renderer/platform/graphics/skia/skia_utils.h
|
||||
index 3bd49cac3f5dfcad0fcc1140fcf876fe37558930..c037b85210bf2dedeb8478cf918633ad94885048 100644
|
||||
--- a/third_party/blink/renderer/platform/graphics/skia/skia_utils.h
|
||||
+++ b/third_party/blink/renderer/platform/graphics/skia/skia_utils.h
|
||||
@@ -209,11 +209,13 @@ struct CrossThreadCopier<SkBitmap> {
|
||||
|
||||
using Type = SkBitmap;
|
||||
static SkBitmap Copy(const SkBitmap& bitmap) {
|
||||
- CHECK(bitmap.isImmutable()) << "Only immutable bitmaps can be transferred.";
|
||||
+ CHECK(bitmap.isImmutable() || bitmap.isNull())
|
||||
+ << "Only immutable bitmaps can be transferred.";
|
||||
return bitmap;
|
||||
}
|
||||
static SkBitmap Copy(SkBitmap&& bitmap) {
|
||||
- CHECK(bitmap.isImmutable()) << "Only immutable bitmaps can be transferred.";
|
||||
+ CHECK(bitmap.isImmutable() || bitmap.isNull())
|
||||
+ << "Only immutable bitmaps can be transferred.";
|
||||
return std::move(bitmap);
|
||||
}
|
||||
};
|
||||
353
patches/chromium/attach_to_correct_frame_in.patch
Normal file
353
patches/chromium/attach_to_correct_frame_in.patch
Normal file
@@ -0,0 +1,353 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Kevin McNee <mcnee@chromium.org>
|
||||
Date: Fri, 4 Jun 2021 22:52:55 +0000
|
||||
Subject: Attach to correct frame in
|
||||
WebContentsImplBrowserTest.AttachNestedInnerWebContents
|
||||
|
||||
This test attempts to attach an inner contents at the outer contents'
|
||||
main frame which is incorrect. This appears to have been done for
|
||||
testing convenience rather than being part of the repro case based on
|
||||
the comments on the CL that introduced it [1]. Indeed, the inner
|
||||
contents don't render with the test as is.
|
||||
|
||||
We adjust the test, enforce the assumption of a subframe in
|
||||
|AttachInnerWebContents|, and remove a bail-out from a
|
||||
WebContentsObserver that was confused by this.
|
||||
|
||||
Furthermore, in the corrected version of the test, we experience a bad
|
||||
cast on Mac and Android, but not Aura, as replacing the platform
|
||||
WebContentsView does not necessarily destroy the platform
|
||||
RenderWidgetHostView which is later assumed to be a
|
||||
RenderWidgetHostViewChildFrame. We now perform that destruction if
|
||||
needed.
|
||||
|
||||
[1] https://chromium-review.googlesource.com/c/chromium/src/+/1498458/6#message-c6af19c82b27d707044a5c1cbbecf48f491bc1bd
|
||||
|
||||
Bug: 1133361, 1208438, 1216595
|
||||
Change-Id: I4de002ab25726f1c05044c764156b69a15bdde41
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2895924
|
||||
Commit-Queue: Kevin McNee <mcnee@chromium.org>
|
||||
Reviewed-by: Chris Hamilton <chrisha@chromium.org>
|
||||
Reviewed-by: Alex Moshchuk <alexmos@chromium.org>
|
||||
Reviewed-by: W. James MacLean <wjmaclean@chromium.org>
|
||||
Cr-Commit-Position: refs/heads/master@{#889495}
|
||||
|
||||
diff --git a/components/performance_manager/performance_manager_tab_helper.cc b/components/performance_manager/performance_manager_tab_helper.cc
|
||||
index 7b2672713e705060ea3d2100492f29d6aa4ad35b..7463423c065e0b74b65b41c2bcf80e9b2025d574 100644
|
||||
--- a/components/performance_manager/performance_manager_tab_helper.cc
|
||||
+++ b/components/performance_manager/performance_manager_tab_helper.cc
|
||||
@@ -394,16 +394,7 @@ void PerformanceManagerTabHelper::InnerWebContentsAttached(
|
||||
// severed.
|
||||
}
|
||||
DCHECK_NE(PageNode::OpenedType::kInvalid, opened_type);
|
||||
- if (!frame) {
|
||||
- DCHECK(!render_frame_host->IsRenderFrameCreated());
|
||||
- DCHECK(!inner_web_contents->IsPortal());
|
||||
- // TODO(crbug.com/1133361):
|
||||
- // WebContentsImplBrowserTest.AttachNestedInnerWebContents calls
|
||||
- // WebContents::AttachInnerWebContents without creating RenderFrame.
|
||||
- // Removing this conditional once either the test is fixed or this function
|
||||
- // is adjusted to handle the case without the render frame.
|
||||
- return;
|
||||
- }
|
||||
+ DCHECK(frame);
|
||||
|
||||
PerformanceManagerImpl::CallOnGraphImpl(
|
||||
FROM_HERE, base::BindOnce(&PageNodeImpl::SetOpenerFrameNodeAndOpenedType,
|
||||
diff --git a/content/browser/renderer_host/render_frame_host_impl.cc b/content/browser/renderer_host/render_frame_host_impl.cc
|
||||
index 4af3384ebbd000926a1f7606511fd6b94dc8aabe..29571b8ab59518fe93e35c1cc7f113e65ed39420 100644
|
||||
--- a/content/browser/renderer_host/render_frame_host_impl.cc
|
||||
+++ b/content/browser/renderer_host/render_frame_host_impl.cc
|
||||
@@ -5714,11 +5714,10 @@ void RenderFrameHostImpl::AdoptPortal(const blink::PortalToken& portal_token,
|
||||
|
||||
// |frame_sink_id| should be set to the associated frame. See
|
||||
// https://crbug.com/966119 for details.
|
||||
- viz::FrameSinkId frame_sink_id =
|
||||
- static_cast<RenderWidgetHostViewBase*>(proxy_host->frame_tree_node()
|
||||
- ->render_manager()
|
||||
- ->GetRenderWidgetHostView())
|
||||
- ->GetFrameSinkId();
|
||||
+ viz::FrameSinkId frame_sink_id = proxy_host->frame_tree_node()
|
||||
+ ->render_manager()
|
||||
+ ->GetRenderWidgetHostView()
|
||||
+ ->GetFrameSinkId();
|
||||
proxy_host->GetAssociatedRemoteFrame()->SetFrameSinkId(frame_sink_id);
|
||||
|
||||
std::move(callback).Run(
|
||||
diff --git a/content/browser/renderer_host/render_frame_host_manager.cc b/content/browser/renderer_host/render_frame_host_manager.cc
|
||||
index 74f9fe3a0a0de20d48bc8b2d397109381ea66481..ce524db677e36ca60f3f9be5493d974975eb82c5 100644
|
||||
--- a/content/browser/renderer_host/render_frame_host_manager.cc
|
||||
+++ b/content/browser/renderer_host/render_frame_host_manager.cc
|
||||
@@ -43,6 +43,8 @@
|
||||
#include "content/browser/renderer_host/render_view_host_factory.h"
|
||||
#include "content/browser/renderer_host/render_view_host_impl.h"
|
||||
#include "content/browser/renderer_host/render_widget_host_impl.h"
|
||||
+#include "content/browser/renderer_host/render_widget_host_view_base.h"
|
||||
+#include "content/browser/renderer_host/render_widget_host_view_child_frame.h"
|
||||
#include "content/browser/site_instance_impl.h"
|
||||
#include "content/browser/webui/web_ui_controller_factory_registry.h"
|
||||
#include "content/common/content_navigation_policy.h"
|
||||
@@ -282,9 +284,11 @@ void RenderFrameHostManager::InitChild(
|
||||
/*renderer_initiated_creation=*/false));
|
||||
}
|
||||
|
||||
-RenderWidgetHostView* RenderFrameHostManager::GetRenderWidgetHostView() const {
|
||||
+RenderWidgetHostViewBase* RenderFrameHostManager::GetRenderWidgetHostView()
|
||||
+ const {
|
||||
if (render_frame_host_)
|
||||
- return render_frame_host_->GetView();
|
||||
+ return static_cast<RenderWidgetHostViewBase*>(
|
||||
+ render_frame_host_->GetView());
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
@@ -2793,8 +2797,9 @@ void RenderFrameHostManager::SwapOuterDelegateFrame(
|
||||
}
|
||||
|
||||
void RenderFrameHostManager::SetRWHViewForInnerContents(
|
||||
- RenderWidgetHostView* child_rwhv) {
|
||||
+ RenderWidgetHostViewChildFrame* child_rwhv) {
|
||||
DCHECK(IsMainFrameForInnerDelegate());
|
||||
+ DCHECK(GetProxyToOuterDelegate());
|
||||
GetProxyToOuterDelegate()->SetChildRWHView(child_rwhv, nullptr);
|
||||
}
|
||||
|
||||
@@ -3400,8 +3405,11 @@ void RenderFrameHostManager::CommitPending(
|
||||
// Note: We do this after unloading the old RFH because that may create
|
||||
// the proxy we're looking for.
|
||||
RenderFrameProxyHost* proxy_to_parent = GetProxyToParent();
|
||||
- if (proxy_to_parent)
|
||||
- proxy_to_parent->SetChildRWHView(new_view, old_size ? &*old_size : nullptr);
|
||||
+ if (proxy_to_parent) {
|
||||
+ proxy_to_parent->SetChildRWHView(
|
||||
+ static_cast<RenderWidgetHostViewChildFrame*>(new_view),
|
||||
+ old_size ? &*old_size : nullptr);
|
||||
+ }
|
||||
|
||||
if (render_frame_host_->is_local_root()) {
|
||||
// RenderFrames are created with a hidden RenderWidgetHost. When navigation
|
||||
diff --git a/content/browser/renderer_host/render_frame_host_manager.h b/content/browser/renderer_host/render_frame_host_manager.h
|
||||
index f4ff686226002e926190829a192993cb92ed0a3e..6ca00c16ac6031bb0357cf8a43e6b77e63455807 100644
|
||||
--- a/content/browser/renderer_host/render_frame_host_manager.h
|
||||
+++ b/content/browser/renderer_host/render_frame_host_manager.h
|
||||
@@ -44,7 +44,8 @@ class RenderFrameHostManagerTest;
|
||||
class RenderFrameProxyHost;
|
||||
class RenderViewHost;
|
||||
class RenderViewHostImpl;
|
||||
-class RenderWidgetHostView;
|
||||
+class RenderWidgetHostViewBase;
|
||||
+class RenderWidgetHostViewChildFrame;
|
||||
class TestWebContents;
|
||||
|
||||
using PageBroadcastMethodCallback =
|
||||
@@ -196,7 +197,7 @@ class CONTENT_EXPORT RenderFrameHostManager
|
||||
|
||||
// Returns the view associated with the current RenderViewHost, or null if
|
||||
// there is no current one.
|
||||
- RenderWidgetHostView* GetRenderWidgetHostView() const;
|
||||
+ RenderWidgetHostViewBase* GetRenderWidgetHostView() const;
|
||||
|
||||
// Returns whether this manager is a main frame and belongs to a FrameTreeNode
|
||||
// that belongs to an inner WebContents.
|
||||
@@ -453,7 +454,7 @@ class CONTENT_EXPORT RenderFrameHostManager
|
||||
|
||||
// Sets the child RenderWidgetHostView for this frame, which must be part of
|
||||
// an inner WebContents.
|
||||
- void SetRWHViewForInnerContents(RenderWidgetHostView* child_rwhv);
|
||||
+ void SetRWHViewForInnerContents(RenderWidgetHostViewChildFrame* child_rwhv);
|
||||
|
||||
// Returns the number of RenderFrameProxyHosts for this frame.
|
||||
size_t GetProxyCount();
|
||||
diff --git a/content/browser/renderer_host/render_frame_proxy_host.cc b/content/browser/renderer_host/render_frame_proxy_host.cc
|
||||
index 54fa3b7a788de7f80a096badeac11a2b6f9b9771..343ea5e1821f55cdea16ae93a055302016d2198f 100644
|
||||
--- a/content/browser/renderer_host/render_frame_proxy_host.cc
|
||||
+++ b/content/browser/renderer_host/render_frame_proxy_host.cc
|
||||
@@ -214,10 +214,9 @@ RenderFrameProxyHost::~RenderFrameProxyHost() {
|
||||
}
|
||||
|
||||
void RenderFrameProxyHost::SetChildRWHView(
|
||||
- RenderWidgetHostView* view,
|
||||
+ RenderWidgetHostViewChildFrame* view,
|
||||
const gfx::Size* initial_frame_size) {
|
||||
- cross_process_frame_connector_->SetView(
|
||||
- static_cast<RenderWidgetHostViewChildFrame*>(view));
|
||||
+ cross_process_frame_connector_->SetView(view);
|
||||
if (initial_frame_size)
|
||||
cross_process_frame_connector_->SetLocalFrameSize(*initial_frame_size);
|
||||
}
|
||||
@@ -226,13 +225,6 @@ RenderViewHostImpl* RenderFrameProxyHost::GetRenderViewHost() {
|
||||
return render_view_host_.get();
|
||||
}
|
||||
|
||||
-RenderWidgetHostView* RenderFrameProxyHost::GetRenderWidgetHostView() {
|
||||
- return frame_tree_node_->parent()
|
||||
- ->frame_tree_node()
|
||||
- ->render_manager()
|
||||
- ->GetRenderWidgetHostView();
|
||||
-}
|
||||
-
|
||||
bool RenderFrameProxyHost::Send(IPC::Message* msg) {
|
||||
return GetAgentSchedulingGroup().Send(msg);
|
||||
}
|
||||
diff --git a/content/browser/renderer_host/render_frame_proxy_host.h b/content/browser/renderer_host/render_frame_proxy_host.h
|
||||
index cd6c90f3b7f77de0df9de1228628cde8c4333b98..e414a1665d43cc773850b23b6fcd568f9baa494a 100644
|
||||
--- a/content/browser/renderer_host/render_frame_proxy_host.h
|
||||
+++ b/content/browser/renderer_host/render_frame_proxy_host.h
|
||||
@@ -36,7 +36,7 @@ class CrossProcessFrameConnector;
|
||||
class FrameTreeNode;
|
||||
class RenderProcessHost;
|
||||
class RenderViewHostImpl;
|
||||
-class RenderWidgetHostView;
|
||||
+class RenderWidgetHostViewChildFrame;
|
||||
|
||||
// When a page's frames are rendered by multiple processes, each renderer has a
|
||||
// full copy of the frame tree. It has full RenderFrames for the frames it is
|
||||
@@ -121,11 +121,10 @@ class CONTENT_EXPORT RenderFrameProxyHost
|
||||
// the child frame will wait until the CrossProcessFrameConnector
|
||||
// receives its size from the parent via FrameHostMsg_UpdateResizeParams
|
||||
// before it begins parsing the content.
|
||||
- void SetChildRWHView(RenderWidgetHostView* view,
|
||||
+ void SetChildRWHView(RenderWidgetHostViewChildFrame* view,
|
||||
const gfx::Size* initial_frame_size);
|
||||
|
||||
RenderViewHostImpl* GetRenderViewHost();
|
||||
- RenderWidgetHostView* GetRenderWidgetHostView();
|
||||
|
||||
// IPC::Sender
|
||||
bool Send(IPC::Message* msg) override;
|
||||
diff --git a/content/browser/web_contents/web_contents_impl.cc b/content/browser/web_contents/web_contents_impl.cc
|
||||
index 14eadcb063b2b9d4734db3d6160f320ab26ffe04..ca51a8a45570fafc0dfe2b400cbb7172a9be632d 100644
|
||||
--- a/content/browser/web_contents/web_contents_impl.cc
|
||||
+++ b/content/browser/web_contents/web_contents_impl.cc
|
||||
@@ -2164,6 +2164,7 @@ void WebContentsImpl::AttachInnerWebContents(
|
||||
auto* render_frame_host_impl =
|
||||
static_cast<RenderFrameHostImpl*>(render_frame_host);
|
||||
DCHECK_EQ(&frame_tree_, render_frame_host_impl->frame_tree());
|
||||
+ DCHECK(render_frame_host_impl->GetParent());
|
||||
|
||||
// Mark |render_frame_host_impl| as outer delegate frame.
|
||||
render_frame_host_impl->SetIsOuterDelegateFrame(true);
|
||||
@@ -2184,6 +2185,16 @@ void WebContentsImpl::AttachInnerWebContents(
|
||||
GetContentClient()->browser()->GetWebContentsViewDelegate(
|
||||
inner_web_contents_impl),
|
||||
&inner_web_contents_impl->render_view_host_delegate_view_);
|
||||
+ // On platforms where destroying the WebContents' view does not also destroy
|
||||
+ // the platform RenderWidgetHostView, we need to destroy it if it exists.
|
||||
+ // TODO(mcnee): Should all platforms' WebContentsView destroy the platform
|
||||
+ // RWHV?
|
||||
+ if (RenderWidgetHostViewBase* prev_rwhv =
|
||||
+ inner_render_manager->GetRenderWidgetHostView()) {
|
||||
+ if (!prev_rwhv->IsRenderWidgetHostViewChildFrame()) {
|
||||
+ prev_rwhv->Destroy();
|
||||
+ }
|
||||
+ }
|
||||
|
||||
// When the WebContents being initialized has an opener, the browser side
|
||||
// Render{View,Frame}Host must be initialized and the RenderWidgetHostView
|
||||
@@ -2330,8 +2341,11 @@ void WebContentsImpl::ReattachToOuterWebContentsFrame() {
|
||||
auto* render_manager = GetRenderManager();
|
||||
auto* parent_frame =
|
||||
node_.OuterContentsFrameTreeNode()->current_frame_host()->GetParent();
|
||||
+ auto* child_rwhv = render_manager->GetRenderWidgetHostView();
|
||||
+ DCHECK(child_rwhv);
|
||||
+ DCHECK(child_rwhv->IsRenderWidgetHostViewChildFrame());
|
||||
render_manager->SetRWHViewForInnerContents(
|
||||
- render_manager->GetRenderWidgetHostView());
|
||||
+ static_cast<RenderWidgetHostViewChildFrame*>(child_rwhv));
|
||||
|
||||
RecursivelyRegisterFrameSinkIds();
|
||||
|
||||
diff --git a/content/browser/web_contents/web_contents_impl_browsertest.cc b/content/browser/web_contents/web_contents_impl_browsertest.cc
|
||||
index cd32d333d2810fde1fc25c80b2bc443b04568c8d..2e75cbf168dbfa48d9f094ed84398197fd0487aa 100644
|
||||
--- a/content/browser/web_contents/web_contents_impl_browsertest.cc
|
||||
+++ b/content/browser/web_contents/web_contents_impl_browsertest.cc
|
||||
@@ -3550,44 +3550,70 @@ IN_PROC_BROWSER_TEST_F(WebContentsImplBrowserTest, SetVisibilityBeforeLoad) {
|
||||
IN_PROC_BROWSER_TEST_F(WebContentsImplBrowserTest,
|
||||
AttachNestedInnerWebContents) {
|
||||
ASSERT_TRUE(embedded_test_server()->Start());
|
||||
- GURL main_url(embedded_test_server()->GetURL(
|
||||
+ const GURL url_a(embedded_test_server()->GetURL(
|
||||
"a.com", "/cross_site_iframe_factory.html?a(a)"));
|
||||
- EXPECT_TRUE(NavigateToURL(shell(), main_url));
|
||||
-
|
||||
+ const GURL url_b(embedded_test_server()->GetURL(
|
||||
+ "b.com", "/cross_site_iframe_factory.html?b(b)"));
|
||||
+ ASSERT_TRUE(NavigateToURL(shell(), url_a));
|
||||
auto* root_web_contents =
|
||||
static_cast<WebContentsImpl*>(shell()->web_contents());
|
||||
- FrameTreeNode* root = root_web_contents->GetFrameTree()->root();
|
||||
- ASSERT_EQ(1u, root->child_count());
|
||||
- FrameTreeNode* child_to_replace = root->child_at(0);
|
||||
- auto* child_to_replace_rfh = child_to_replace->current_frame_host();
|
||||
|
||||
+ // Create a child WebContents but don't attach it to the root contents yet.
|
||||
WebContents::CreateParams inner_params(
|
||||
root_web_contents->GetBrowserContext());
|
||||
-
|
||||
std::unique_ptr<WebContents> child_contents_ptr =
|
||||
WebContents::Create(inner_params);
|
||||
- auto* child_rfh =
|
||||
- static_cast<RenderFrameHostImpl*>(child_contents_ptr->GetMainFrame());
|
||||
+ WebContents* child_contents = child_contents_ptr.get();
|
||||
+ // Navigate the child to a page with a subframe, at which we will attach the
|
||||
+ // grandchild.
|
||||
+ ASSERT_TRUE(NavigateToURL(child_contents, url_b));
|
||||
|
||||
+ // Create and attach grandchild to child.
|
||||
std::unique_ptr<WebContents> grandchild_contents_ptr =
|
||||
WebContents::Create(inner_params);
|
||||
-
|
||||
- // Attach grandchild to child.
|
||||
- child_contents_ptr->AttachInnerWebContents(
|
||||
- std::move(grandchild_contents_ptr), child_rfh, false /* is_full_page */);
|
||||
+ WebContents* grandchild_contents = grandchild_contents_ptr.get();
|
||||
+ RenderFrameHost* child_contents_subframe =
|
||||
+ ChildFrameAt(child_contents->GetMainFrame(), 0);
|
||||
+ ASSERT_TRUE(child_contents_subframe);
|
||||
+ child_contents->AttachInnerWebContents(std::move(grandchild_contents_ptr),
|
||||
+ child_contents_subframe,
|
||||
+ false /* is_full_page */);
|
||||
|
||||
// At this point the child hasn't been attached to the root.
|
||||
- EXPECT_EQ(1U, root_web_contents->GetInputEventRouter()
|
||||
- ->RegisteredViewCountForTesting());
|
||||
+ {
|
||||
+ auto* root_view = static_cast<RenderWidgetHostViewBase*>(
|
||||
+ root_web_contents->GetRenderWidgetHostView());
|
||||
+ ASSERT_TRUE(root_view);
|
||||
+ auto* root_event_router = root_web_contents->GetInputEventRouter();
|
||||
+ EXPECT_EQ(1U, root_event_router->RegisteredViewCountForTesting());
|
||||
+ EXPECT_TRUE(root_event_router->IsViewInMap(root_view));
|
||||
+ }
|
||||
|
||||
// Attach child+grandchild subtree to root.
|
||||
+ RenderFrameHost* root_contents_subframe =
|
||||
+ ChildFrameAt(root_web_contents->GetMainFrame(), 0);
|
||||
+ ASSERT_TRUE(root_contents_subframe);
|
||||
root_web_contents->AttachInnerWebContents(std::move(child_contents_ptr),
|
||||
- child_to_replace_rfh,
|
||||
+ root_contents_subframe,
|
||||
false /* is_full_page */);
|
||||
|
||||
// Verify views registered for both child and grandchild.
|
||||
- EXPECT_EQ(3U, root_web_contents->GetInputEventRouter()
|
||||
- ->RegisteredViewCountForTesting());
|
||||
+ {
|
||||
+ auto* root_view = static_cast<RenderWidgetHostViewBase*>(
|
||||
+ root_web_contents->GetRenderWidgetHostView());
|
||||
+ auto* child_view = static_cast<RenderWidgetHostViewBase*>(
|
||||
+ child_contents->GetRenderWidgetHostView());
|
||||
+ auto* grandchild_view = static_cast<RenderWidgetHostViewBase*>(
|
||||
+ grandchild_contents->GetRenderWidgetHostView());
|
||||
+ ASSERT_TRUE(root_view);
|
||||
+ ASSERT_TRUE(child_view);
|
||||
+ ASSERT_TRUE(grandchild_view);
|
||||
+ auto* root_event_router = root_web_contents->GetInputEventRouter();
|
||||
+ EXPECT_EQ(3U, root_event_router->RegisteredViewCountForTesting());
|
||||
+ EXPECT_TRUE(root_event_router->IsViewInMap(root_view));
|
||||
+ EXPECT_TRUE(root_event_router->IsViewInMap(child_view));
|
||||
+ EXPECT_TRUE(root_event_router->IsViewInMap(grandchild_view));
|
||||
+ }
|
||||
}
|
||||
|
||||
IN_PROC_BROWSER_TEST_F(WebContentsImplBrowserTest,
|
||||
@@ -0,0 +1,94 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Ben Kelly <wanderview@chromium.org>
|
||||
Date: Fri, 5 Nov 2021 19:47:08 +0000
|
||||
Subject: CacheStorage: Store partial opaque responses.
|
||||
|
||||
(cherry picked from commit 802faa035409ac7cbb58ad1a385bb8507fe99077)
|
||||
|
||||
Fixed: 1260649
|
||||
Change-Id: If83156096e6aecec55490330d03c56c0c26120bc
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3251749
|
||||
Reviewed-by: Marijn Kruisselbrink <mek@chromium.org>
|
||||
Commit-Queue: Ben Kelly <wanderview@chromium.org>
|
||||
Cr-Original-Commit-Position: refs/heads/main@{#937400}
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3264366
|
||||
Bot-Commit: Rubber Stamper <rubber-stamper@appspot.gserviceaccount.com>
|
||||
Cr-Commit-Position: refs/branch-heads/4664@{#774}
|
||||
Cr-Branched-From: 24dc4ee75e01a29d390d43c9c264372a169273a7-refs/heads/main@{#929512}
|
||||
|
||||
diff --git a/content/browser/cache_storage/legacy/legacy_cache_storage_cache.cc b/content/browser/cache_storage/legacy/legacy_cache_storage_cache.cc
|
||||
index 634d72af383e4b9a52ce04202388e13077754783..c5be9cd6e579ad11701c251d48966934e71e8069 100644
|
||||
--- a/content/browser/cache_storage/legacy/legacy_cache_storage_cache.cc
|
||||
+++ b/content/browser/cache_storage/legacy/legacy_cache_storage_cache.cc
|
||||
@@ -446,10 +446,10 @@ blink::mojom::FetchAPIResponsePtr CreateResponse(
|
||||
padding = storage::ComputeRandomResponsePadding();
|
||||
}
|
||||
|
||||
- // Note that |has_range_requested| can be safely set to false since it only
|
||||
- // affects HTTP 206 (Partial) responses, which are blocked from cache storage.
|
||||
- // See https://fetch.spec.whatwg.org/#main-fetch for usage of
|
||||
- // |has_range_requested|.
|
||||
+ // While we block most partial responses from being stored, we can have
|
||||
+ // partial responses for bgfetch or opaque responses.
|
||||
+ bool has_range_requested = headers.contains(net::HttpRequestHeaders::kRange);
|
||||
+
|
||||
return blink::mojom::FetchAPIResponse::New(
|
||||
url_list, metadata.response().status_code(),
|
||||
metadata.response().status_text(),
|
||||
@@ -467,7 +467,7 @@ blink::mojom::FetchAPIResponsePtr CreateResponse(
|
||||
static_cast<net::HttpResponseInfo::ConnectionInfo>(
|
||||
metadata.response().connection_info()),
|
||||
alpn_negotiated_protocol, metadata.response().was_fetched_via_spdy(),
|
||||
- /*has_range_requested=*/false, /*auth_challenge_info=*/base::nullopt);
|
||||
+ has_range_requested, /*auth_challenge_info=*/base::nullopt);
|
||||
}
|
||||
|
||||
int64_t CalculateSideDataPadding(
|
||||
@@ -1907,7 +1907,13 @@ void LegacyCacheStorageCache::PutDidCreateEntry(
|
||||
}
|
||||
|
||||
proto::CacheResponse* response_metadata = metadata.mutable_response();
|
||||
- DCHECK_NE(put_context->response->status_code, net::HTTP_PARTIAL_CONTENT);
|
||||
+ if (owner_ != storage::mojom::CacheStorageOwner::kBackgroundFetch &&
|
||||
+ put_context->response->response_type !=
|
||||
+ network::mojom::FetchResponseType::kOpaque &&
|
||||
+ put_context->response->response_type !=
|
||||
+ network::mojom::FetchResponseType::kOpaqueRedirect) {
|
||||
+ DCHECK_NE(put_context->response->status_code, net::HTTP_PARTIAL_CONTENT);
|
||||
+ }
|
||||
response_metadata->set_status_code(put_context->response->status_code);
|
||||
response_metadata->set_status_text(put_context->response->status_text);
|
||||
response_metadata->set_response_type(FetchResponseTypeToProtoResponseType(
|
||||
diff --git a/third_party/blink/renderer/modules/cache_storage/cache.cc b/third_party/blink/renderer/modules/cache_storage/cache.cc
|
||||
index 5482ce90e5a9f591016c784a0378b73b0520be03..0ec3a20cff2fdfc1ebd0f512cfdad4c991341d89 100644
|
||||
--- a/third_party/blink/renderer/modules/cache_storage/cache.cc
|
||||
+++ b/third_party/blink/renderer/modules/cache_storage/cache.cc
|
||||
@@ -101,7 +101,7 @@ void ValidateResponseForPut(const Response* response,
|
||||
exception_state.ThrowTypeError("Vary header contains *");
|
||||
return;
|
||||
}
|
||||
- if (response->GetResponse()->InternalStatus() == 206) {
|
||||
+ if (response->GetResponse()->Status() == 206) {
|
||||
exception_state.ThrowTypeError(
|
||||
"Partial response (status code 206) is unsupported");
|
||||
return;
|
||||
diff --git a/third_party/blink/web_tests/external/wpt/service-workers/cache-storage/script-tests/cache-put.js b/third_party/blink/web_tests/external/wpt/service-workers/cache-storage/script-tests/cache-put.js
|
||||
index b45910a3b8ba089e1724efa8b9e8a8d679c59320..f60c4b905ebcb61854b83177d59861ef92095624 100644
|
||||
--- a/third_party/blink/web_tests/external/wpt/service-workers/cache-storage/script-tests/cache-put.js
|
||||
+++ b/third_party/blink/web_tests/external/wpt/service-workers/cache-storage/script-tests/cache-put.js
|
||||
@@ -144,7 +144,14 @@ cache_test(function(cache, test) {
|
||||
'Test framework error: The status code should be 0 for an ' +
|
||||
' opaque-filtered response. This is actually HTTP 206.');
|
||||
response = fetch_result.clone();
|
||||
- return promise_rejects_js(test, TypeError, cache.put(request, fetch_result));
|
||||
+ return cache.put(request, fetch_result);
|
||||
+ })
|
||||
+ .then(function() {
|
||||
+ return cache.match(test_url);
|
||||
+ })
|
||||
+ .then(function(result) {
|
||||
+ assert_not_equals(result, undefined,
|
||||
+ 'Cache.put should store an entry for the opaque response');
|
||||
});
|
||||
}, 'Cache.put with opaque-filtered HTTP 206 response');
|
||||
|
||||
174
patches/chromium/check_direction_of_rtcencodedframes.patch
Normal file
174
patches/chromium/check_direction_of_rtcencodedframes.patch
Normal file
@@ -0,0 +1,174 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Tony Herre <toprice@chromium.org>
|
||||
Date: Fri, 1 Oct 2021 19:18:45 +0000
|
||||
Subject: Check direction of RTCEncodedFrames
|
||||
|
||||
Add a check to RTCEncodedVideoUnderlyingSink of the direction of the
|
||||
underlying webrtc frame, to make sure a web app doesn't take a received
|
||||
encoded frame and pass it into a sender insertable stream, which is as
|
||||
yet unsupported in WebRTC.
|
||||
|
||||
Bug: 1247260
|
||||
Change-Id: I9ed5bd8b2bd5e5ee461f3b553f8a91f6cc2e9ed7
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3190473
|
||||
Commit-Queue: Tony Herre <toprice@chromium.org>
|
||||
Reviewed-by: Harald Alvestrand <hta@chromium.org>
|
||||
Cr-Commit-Position: refs/heads/main@{#927323}
|
||||
|
||||
diff --git a/third_party/blink/renderer/modules/peerconnection/rtc_encoded_video_underlying_sink.cc b/third_party/blink/renderer/modules/peerconnection/rtc_encoded_video_underlying_sink.cc
|
||||
index c390ab72418194cb10c3b0bc5a83b95de8dd19f6..775b837fee46836fd292b17ac8d80e4c83bd08a8 100644
|
||||
--- a/third_party/blink/renderer/modules/peerconnection/rtc_encoded_video_underlying_sink.cc
|
||||
+++ b/third_party/blink/renderer/modules/peerconnection/rtc_encoded_video_underlying_sink.cc
|
||||
@@ -14,8 +14,10 @@ namespace blink {
|
||||
|
||||
RTCEncodedVideoUnderlyingSink::RTCEncodedVideoUnderlyingSink(
|
||||
ScriptState* script_state,
|
||||
- TransformerCallback transformer_callback)
|
||||
- : transformer_callback_(std::move(transformer_callback)) {
|
||||
+ TransformerCallback transformer_callback,
|
||||
+ webrtc::TransformableFrameInterface::Direction expected_direction)
|
||||
+ : transformer_callback_(std::move(transformer_callback)),
|
||||
+ expected_direction_(expected_direction) {
|
||||
DCHECK(transformer_callback_);
|
||||
}
|
||||
|
||||
@@ -53,6 +55,12 @@ ScriptPromise RTCEncodedVideoUnderlyingSink::write(
|
||||
return ScriptPromise();
|
||||
}
|
||||
|
||||
+ if (webrtc_frame->GetDirection() != expected_direction_) {
|
||||
+ exception_state.ThrowDOMException(DOMExceptionCode::kOperationError,
|
||||
+ "Invalid frame");
|
||||
+ return ScriptPromise();
|
||||
+ }
|
||||
+
|
||||
RTCEncodedVideoStreamTransformer* transformer = transformer_callback_.Run();
|
||||
if (!transformer) {
|
||||
exception_state.ThrowDOMException(DOMExceptionCode::kInvalidStateError,
|
||||
diff --git a/third_party/blink/renderer/modules/peerconnection/rtc_encoded_video_underlying_sink.h b/third_party/blink/renderer/modules/peerconnection/rtc_encoded_video_underlying_sink.h
|
||||
index dd1cad227eb7947dd0bf2ec7ba217956cb7a8787..8591fcc6eb1c78d0e107e4f097d3133d111ab959 100644
|
||||
--- a/third_party/blink/renderer/modules/peerconnection/rtc_encoded_video_underlying_sink.h
|
||||
+++ b/third_party/blink/renderer/modules/peerconnection/rtc_encoded_video_underlying_sink.h
|
||||
@@ -7,6 +7,7 @@
|
||||
|
||||
#include "third_party/blink/renderer/core/streams/underlying_sink_base.h"
|
||||
#include "third_party/blink/renderer/modules/modules_export.h"
|
||||
+#include "third_party/webrtc/api/frame_transformer_interface.h"
|
||||
|
||||
namespace blink {
|
||||
|
||||
@@ -18,7 +19,9 @@ class MODULES_EXPORT RTCEncodedVideoUnderlyingSink final
|
||||
public:
|
||||
using TransformerCallback =
|
||||
base::RepeatingCallback<RTCEncodedVideoStreamTransformer*()>;
|
||||
- RTCEncodedVideoUnderlyingSink(ScriptState*, TransformerCallback);
|
||||
+ RTCEncodedVideoUnderlyingSink(ScriptState*,
|
||||
+ TransformerCallback,
|
||||
+ webrtc::TransformableFrameInterface::Direction);
|
||||
|
||||
// UnderlyingSinkBase
|
||||
ScriptPromise start(ScriptState*,
|
||||
@@ -37,6 +40,7 @@ class MODULES_EXPORT RTCEncodedVideoUnderlyingSink final
|
||||
|
||||
private:
|
||||
TransformerCallback transformer_callback_;
|
||||
+ webrtc::TransformableFrameInterface::Direction expected_direction_;
|
||||
};
|
||||
|
||||
} // namespace blink
|
||||
diff --git a/third_party/blink/renderer/modules/peerconnection/rtc_encoded_video_underlying_sink_test.cc b/third_party/blink/renderer/modules/peerconnection/rtc_encoded_video_underlying_sink_test.cc
|
||||
index 3f6d24941ad7a9e5c16f11bcdcffa91b2027c0db..9837fb0be84633c88fcf451cec8c276ca6e7c17c 100644
|
||||
--- a/third_party/blink/renderer/modules/peerconnection/rtc_encoded_video_underlying_sink_test.cc
|
||||
+++ b/third_party/blink/renderer/modules/peerconnection/rtc_encoded_video_underlying_sink_test.cc
|
||||
@@ -75,11 +75,15 @@ class RTCEncodedVideoUnderlyingSinkTest : public testing::Test {
|
||||
EXPECT_FALSE(transformer_.HasTransformedFrameSinkCallback(kSSRC));
|
||||
}
|
||||
|
||||
- RTCEncodedVideoUnderlyingSink* CreateSink(ScriptState* script_state) {
|
||||
+ RTCEncodedVideoUnderlyingSink* CreateSink(
|
||||
+ ScriptState* script_state,
|
||||
+ webrtc::TransformableFrameInterface::Direction expected_direction =
|
||||
+ webrtc::TransformableFrameInterface::Direction::kSender) {
|
||||
return MakeGarbageCollected<RTCEncodedVideoUnderlyingSink>(
|
||||
script_state,
|
||||
WTF::BindRepeating(&RTCEncodedVideoUnderlyingSinkTest::GetTransformer,
|
||||
- WTF::Unretained(this)));
|
||||
+ WTF::Unretained(this)),
|
||||
+ expected_direction);
|
||||
}
|
||||
|
||||
RTCEncodedVideoUnderlyingSink* CreateNullCallbackSink(
|
||||
@@ -87,15 +91,21 @@ class RTCEncodedVideoUnderlyingSinkTest : public testing::Test {
|
||||
return MakeGarbageCollected<RTCEncodedVideoUnderlyingSink>(
|
||||
script_state,
|
||||
WTF::BindRepeating(
|
||||
- []() -> RTCEncodedVideoStreamTransformer* { return nullptr; }));
|
||||
+ []() -> RTCEncodedVideoStreamTransformer* { return nullptr; }),
|
||||
+ webrtc::TransformableFrameInterface::Direction::kSender);
|
||||
}
|
||||
|
||||
RTCEncodedVideoStreamTransformer* GetTransformer() { return &transformer_; }
|
||||
|
||||
- ScriptValue CreateEncodedVideoFrameChunk(ScriptState* script_state) {
|
||||
+ ScriptValue CreateEncodedVideoFrameChunk(
|
||||
+ ScriptState* script_state,
|
||||
+ webrtc::TransformableFrameInterface::Direction direction =
|
||||
+ webrtc::TransformableFrameInterface::Direction::kSender) {
|
||||
auto mock_frame =
|
||||
std::make_unique<NiceMock<webrtc::MockTransformableVideoFrame>>();
|
||||
+
|
||||
ON_CALL(*mock_frame.get(), GetSsrc).WillByDefault(Return(kSSRC));
|
||||
+ ON_CALL(*mock_frame.get(), GetDirection).WillByDefault(Return(direction));
|
||||
RTCEncodedVideoFrame* frame =
|
||||
MakeGarbageCollected<RTCEncodedVideoFrame>(std::move(mock_frame));
|
||||
return ScriptValue(script_state->GetIsolate(),
|
||||
@@ -176,4 +186,21 @@ TEST_F(RTCEncodedVideoUnderlyingSinkTest, WriteToNullCallbackSinkFails) {
|
||||
DOMExceptionCode::kInvalidStateError));
|
||||
}
|
||||
|
||||
+TEST_F(RTCEncodedVideoUnderlyingSinkTest, WriteInvalidDirectionFails) {
|
||||
+ V8TestingScope v8_scope;
|
||||
+ ScriptState* script_state = v8_scope.GetScriptState();
|
||||
+ auto* sink = CreateSink(
|
||||
+ script_state, webrtc::TransformableFrameInterface::Direction::kSender);
|
||||
+
|
||||
+ // Write an encoded chunk with direction set to Receiver should fail as it
|
||||
+ // doesn't match the expected direction of our sink.
|
||||
+ DummyExceptionStateForTesting dummy_exception_state;
|
||||
+ sink->write(script_state,
|
||||
+ CreateEncodedVideoFrameChunk(
|
||||
+ script_state,
|
||||
+ webrtc::TransformableFrameInterface::Direction::kReceiver),
|
||||
+ nullptr, dummy_exception_state);
|
||||
+ EXPECT_TRUE(dummy_exception_state.HadException());
|
||||
+}
|
||||
+
|
||||
} // namespace blink
|
||||
diff --git a/third_party/blink/renderer/modules/peerconnection/rtc_rtp_receiver.cc b/third_party/blink/renderer/modules/peerconnection/rtc_rtp_receiver.cc
|
||||
index e654738739e18adc1937922dbb59f7f9214e651e..58cf45c9023510b4615cbebcaa3b3812481a54c3 100644
|
||||
--- a/third_party/blink/renderer/modules/peerconnection/rtc_rtp_receiver.cc
|
||||
+++ b/third_party/blink/renderer/modules/peerconnection/rtc_rtp_receiver.cc
|
||||
@@ -506,7 +506,8 @@ void RTCRtpReceiver::InitializeEncodedVideoStreams(ScriptState* script_state) {
|
||||
->GetEncodedVideoStreamTransformer()
|
||||
: nullptr;
|
||||
},
|
||||
- WrapWeakPersistent(this)));
|
||||
+ WrapWeakPersistent(this)),
|
||||
+ webrtc::TransformableFrameInterface::Direction::kReceiver);
|
||||
// The high water mark for the stream is set to 1 so that the stream seems
|
||||
// ready to write, but without queuing frames.
|
||||
WritableStream* writable_stream =
|
||||
diff --git a/third_party/blink/renderer/modules/peerconnection/rtc_rtp_sender.cc b/third_party/blink/renderer/modules/peerconnection/rtc_rtp_sender.cc
|
||||
index 20c6325e5e7eb4e47a6324033704430ed53ea3c3..44ed2f520c88b5aa694383c749da57d6681cef9a 100644
|
||||
--- a/third_party/blink/renderer/modules/peerconnection/rtc_rtp_sender.cc
|
||||
+++ b/third_party/blink/renderer/modules/peerconnection/rtc_rtp_sender.cc
|
||||
@@ -902,7 +902,8 @@ void RTCRtpSender::InitializeEncodedVideoStreams(ScriptState* script_state) {
|
||||
->GetEncodedVideoStreamTransformer()
|
||||
: nullptr;
|
||||
},
|
||||
- WrapWeakPersistent(this)));
|
||||
+ WrapWeakPersistent(this)),
|
||||
+ webrtc::TransformableFrameInterface::Direction::kSender);
|
||||
// The high water mark for the stream is set to 1 so that the stream is
|
||||
// ready to write, but without queuing frames.
|
||||
WritableStream* writable_stream =
|
||||
385
patches/chromium/cherry-pick-0894af410c4e.patch
Normal file
385
patches/chromium/cherry-pick-0894af410c4e.patch
Normal file
@@ -0,0 +1,385 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Min Qin <qinmin@chromium.org>
|
||||
Date: Tue, 31 Aug 2021 23:03:03 +0000
|
||||
Subject: Quarantine save package items that's downloaded from network
|
||||
|
||||
Currently quarantine is not performed for save page downloads. This CL
|
||||
fixes the issue.
|
||||
|
||||
BUG=1243020, 811161
|
||||
|
||||
Change-Id: I85d03cc324b0b90a45bd8b3429e4e9eec1aaf857
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3126709
|
||||
Reviewed-by: Xing Liu <xingliu@chromium.org>
|
||||
Commit-Queue: Min Qin <qinmin@chromium.org>
|
||||
Cr-Commit-Position: refs/heads/main@{#917013}
|
||||
|
||||
diff --git a/chrome/browser/download/save_page_browsertest.cc b/chrome/browser/download/save_page_browsertest.cc
|
||||
index b5e3997002f14208e84c0bab2f3fdee17a4962ef..ef21c3d4fc4c425666af4f6fbb6213fa8f79b002 100644
|
||||
--- a/chrome/browser/download/save_page_browsertest.cc
|
||||
+++ b/chrome/browser/download/save_page_browsertest.cc
|
||||
@@ -49,6 +49,7 @@
|
||||
#include "components/prefs/pref_member.h"
|
||||
#include "components/prefs/pref_service.h"
|
||||
#include "components/security_state/core/security_state.h"
|
||||
+#include "components/services/quarantine/test_support.h"
|
||||
#include "content/public/browser/download_manager.h"
|
||||
#include "content/public/browser/notification_service.h"
|
||||
#include "content/public/browser/notification_types.h"
|
||||
@@ -433,6 +434,10 @@ IN_PROC_BROWSER_TEST_F(SavePageBrowserTest, SaveFileURL) {
|
||||
EXPECT_TRUE(base::PathExists(full_file_name));
|
||||
EXPECT_FALSE(base::PathExists(dir));
|
||||
EXPECT_TRUE(base::ContentsEqual(GetTestDirFile("text.txt"), full_file_name));
|
||||
+#if defined(OS_WIN)
|
||||
+ // Local file URL will not be quarantined.
|
||||
+ EXPECT_FALSE(quarantine::IsFileQuarantined(full_file_name, GURL(), GURL()));
|
||||
+#endif
|
||||
}
|
||||
|
||||
IN_PROC_BROWSER_TEST_F(SavePageBrowserTest,
|
||||
@@ -936,6 +941,25 @@ IN_PROC_BROWSER_TEST_F(SavePageBrowserTest, SaveUnauthorizedResource) {
|
||||
EXPECT_FALSE(base::PathExists(dir.AppendASCII("should-not-save.jpg")));
|
||||
}
|
||||
|
||||
+#if defined(OS_WIN)
|
||||
+// Save a file and confirm that the file is correctly quarantined.
|
||||
+IN_PROC_BROWSER_TEST_F(SavePageBrowserTest, SaveURLQuarantine) {
|
||||
+ GURL url = embedded_test_server()->GetURL("/save_page/text.txt");
|
||||
+ ui_test_utils::NavigateToURL(browser(), url);
|
||||
+
|
||||
+ base::FilePath full_file_name, dir;
|
||||
+ SaveCurrentTab(url, content::SAVE_PAGE_TYPE_AS_ONLY_HTML, "test", 1, &dir,
|
||||
+ &full_file_name);
|
||||
+ ASSERT_FALSE(HasFailure());
|
||||
+
|
||||
+ base::ScopedAllowBlockingForTesting allow_blocking;
|
||||
+ EXPECT_TRUE(base::PathExists(full_file_name));
|
||||
+ EXPECT_FALSE(base::PathExists(dir));
|
||||
+ EXPECT_TRUE(base::ContentsEqual(GetTestDirFile("text.txt"), full_file_name));
|
||||
+ EXPECT_TRUE(quarantine::IsFileQuarantined(full_file_name, url, GURL()));
|
||||
+}
|
||||
+#endif
|
||||
+
|
||||
// Test suite that allows testing --site-per-process against cross-site frames.
|
||||
// See http://dev.chromium.org/developers/design-documents/site-isolation.
|
||||
class SavePageSitePerProcessBrowserTest : public SavePageBrowserTest {
|
||||
diff --git a/content/browser/download/download_manager_impl.h b/content/browser/download/download_manager_impl.h
|
||||
index 69fcf9abbe975ea35a2869f3601958e88aeb5951..0deb3b7c7781a37b47a5a04169ecd2e0ceaed4c8 100644
|
||||
--- a/content/browser/download/download_manager_impl.h
|
||||
+++ b/content/browser/download/download_manager_impl.h
|
||||
@@ -170,6 +170,11 @@ class CONTENT_EXPORT DownloadManagerImpl
|
||||
int frame_tree_node_id,
|
||||
bool from_download_cross_origin_redirect);
|
||||
|
||||
+ // DownloadItemImplDelegate overrides.
|
||||
+ download::QuarantineConnectionCallback GetQuarantineConnectionCallback()
|
||||
+ override;
|
||||
+ std::string GetApplicationClientIdForFileScanning() const override;
|
||||
+
|
||||
private:
|
||||
using DownloadSet = std::set<download::DownloadItem*>;
|
||||
using DownloadGuidMap =
|
||||
@@ -237,7 +242,6 @@ class CONTENT_EXPORT DownloadManagerImpl
|
||||
bool ShouldOpenDownload(download::DownloadItemImpl* item,
|
||||
ShouldOpenDownloadCallback callback) override;
|
||||
void CheckForFileRemoval(download::DownloadItemImpl* download_item) override;
|
||||
- std::string GetApplicationClientIdForFileScanning() const override;
|
||||
void ResumeInterruptedDownload(
|
||||
std::unique_ptr<download::DownloadUrlParameters> params,
|
||||
const GURL& site_url) override;
|
||||
@@ -249,8 +253,6 @@ class CONTENT_EXPORT DownloadManagerImpl
|
||||
void ReportBytesWasted(download::DownloadItemImpl* download) override;
|
||||
void BindWakeLockProvider(
|
||||
mojo::PendingReceiver<device::mojom::WakeLockProvider> receiver) override;
|
||||
- download::QuarantineConnectionCallback GetQuarantineConnectionCallback()
|
||||
- override;
|
||||
std::unique_ptr<download::DownloadItemRenameHandler>
|
||||
GetRenameHandlerForDownload(
|
||||
download::DownloadItemImpl* download_item) override;
|
||||
diff --git a/content/browser/download/save_file.cc b/content/browser/download/save_file.cc
|
||||
index 72331e60fca942820b39580cee5a1890340401ae..110f66250e9608426b26333203e93045f17e9f99 100644
|
||||
--- a/content/browser/download/save_file.cc
|
||||
+++ b/content/browser/download/save_file.cc
|
||||
@@ -63,10 +63,15 @@ void SaveFile::Finish() {
|
||||
file_.Finish();
|
||||
}
|
||||
|
||||
-void SaveFile::AnnotateWithSourceInformation() {
|
||||
- // TODO(gbillock): If this method is called, it should set the
|
||||
- // file_.SetClientGuid() method first.
|
||||
- NOTREACHED();
|
||||
+void SaveFile::AnnotateWithSourceInformation(
|
||||
+ const std::string& client_guid,
|
||||
+ const GURL& source_url,
|
||||
+ const GURL& referrer_url,
|
||||
+ mojo::PendingRemote<quarantine::mojom::Quarantine> remote_quarantine,
|
||||
+ download::BaseFile::OnAnnotationDoneCallback on_annotation_done_callback) {
|
||||
+ file_.AnnotateWithSourceInformation(client_guid, source_url, referrer_url,
|
||||
+ std::move(remote_quarantine),
|
||||
+ std::move(on_annotation_done_callback));
|
||||
}
|
||||
|
||||
base::FilePath SaveFile::FullPath() const {
|
||||
diff --git a/content/browser/download/save_file.h b/content/browser/download/save_file.h
|
||||
index 688574b07f9374e75a25caaaa13bdb405aea7b0d..1893a0031f4c6642c6c806577da2246e55e49091 100644
|
||||
--- a/content/browser/download/save_file.h
|
||||
+++ b/content/browser/download/save_file.h
|
||||
@@ -34,7 +34,12 @@ class SaveFile {
|
||||
void Detach();
|
||||
void Cancel();
|
||||
void Finish();
|
||||
- void AnnotateWithSourceInformation();
|
||||
+ void AnnotateWithSourceInformation(
|
||||
+ const std::string& client_guid,
|
||||
+ const GURL& source_url,
|
||||
+ const GURL& referrer_url,
|
||||
+ mojo::PendingRemote<quarantine::mojom::Quarantine> remote_quarantine,
|
||||
+ download::BaseFile::OnAnnotationDoneCallback on_annotation_done_callback);
|
||||
base::FilePath FullPath() const;
|
||||
bool InProgress() const;
|
||||
int64_t BytesSoFar() const;
|
||||
diff --git a/content/browser/download/save_file_manager.cc b/content/browser/download/save_file_manager.cc
|
||||
index 91786d976f7f637d659468d0700a6c858284dd66..2489b47cf864af0ff184f9250208832c31496698 100644
|
||||
--- a/content/browser/download/save_file_manager.cc
|
||||
+++ b/content/browser/download/save_file_manager.cc
|
||||
@@ -50,6 +50,7 @@ static SaveFileManager* g_save_file_manager = nullptr;
|
||||
class SaveFileManager::SimpleURLLoaderHelper
|
||||
: public network::SimpleURLLoaderStreamConsumer {
|
||||
public:
|
||||
+ using URLLoaderCompleteCallback = base::OnceCallback<void(bool success)>;
|
||||
static std::unique_ptr<SimpleURLLoaderHelper> CreateAndStartDownload(
|
||||
std::unique_ptr<network::ResourceRequest> resource_request,
|
||||
SaveItemId save_item_id,
|
||||
@@ -58,11 +59,12 @@ class SaveFileManager::SimpleURLLoaderHelper
|
||||
int render_frame_routing_id,
|
||||
const net::NetworkTrafficAnnotationTag& annotation_tag,
|
||||
network::mojom::URLLoaderFactory* url_loader_factory,
|
||||
- SaveFileManager* save_file_manager) {
|
||||
+ SaveFileManager* save_file_manager,
|
||||
+ URLLoaderCompleteCallback on_complete_cb) {
|
||||
return std::unique_ptr<SimpleURLLoaderHelper>(new SimpleURLLoaderHelper(
|
||||
std::move(resource_request), save_item_id, save_package_id,
|
||||
render_process_id, render_frame_routing_id, annotation_tag,
|
||||
- url_loader_factory, save_file_manager));
|
||||
+ url_loader_factory, save_file_manager, std::move(on_complete_cb)));
|
||||
}
|
||||
|
||||
~SimpleURLLoaderHelper() override = default;
|
||||
@@ -76,10 +78,12 @@ class SaveFileManager::SimpleURLLoaderHelper
|
||||
int render_frame_routing_id,
|
||||
const net::NetworkTrafficAnnotationTag& annotation_tag,
|
||||
network::mojom::URLLoaderFactory* url_loader_factory,
|
||||
- SaveFileManager* save_file_manager)
|
||||
+ SaveFileManager* save_file_manager,
|
||||
+ URLLoaderCompleteCallback on_complete_cb)
|
||||
: save_file_manager_(save_file_manager),
|
||||
save_item_id_(save_item_id),
|
||||
- save_package_id_(save_package_id) {
|
||||
+ save_package_id_(save_package_id),
|
||||
+ on_complete_cb_(std::move(on_complete_cb)) {
|
||||
GURL url = resource_request->url;
|
||||
url_loader_ = network::SimpleURLLoader::Create(std::move(resource_request),
|
||||
annotation_tag);
|
||||
@@ -124,9 +128,7 @@ class SaveFileManager::SimpleURLLoaderHelper
|
||||
|
||||
void OnComplete(bool success) override {
|
||||
download::GetDownloadTaskRunner()->PostTask(
|
||||
- FROM_HERE,
|
||||
- base::BindOnce(&SaveFileManager::SaveFinished, save_file_manager_,
|
||||
- save_item_id_, save_package_id_, success));
|
||||
+ FROM_HERE, base::BindOnce(std::move(on_complete_cb_), success));
|
||||
}
|
||||
|
||||
void OnRetry(base::OnceClosure start_retry) override {
|
||||
@@ -138,6 +140,7 @@ class SaveFileManager::SimpleURLLoaderHelper
|
||||
SaveItemId save_item_id_;
|
||||
SavePackageId save_package_id_;
|
||||
std::unique_ptr<network::SimpleURLLoader> url_loader_;
|
||||
+ URLLoaderCompleteCallback on_complete_cb_;
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(SimpleURLLoaderHelper);
|
||||
};
|
||||
@@ -188,17 +191,20 @@ SavePackage* SaveFileManager::LookupPackage(SaveItemId save_item_id) {
|
||||
}
|
||||
|
||||
// Call from SavePackage for starting a saving job
|
||||
-void SaveFileManager::SaveURL(SaveItemId save_item_id,
|
||||
- const GURL& url,
|
||||
- const Referrer& referrer,
|
||||
- int render_process_host_id,
|
||||
- int render_view_routing_id,
|
||||
- int render_frame_routing_id,
|
||||
- SaveFileCreateInfo::SaveFileSource save_source,
|
||||
- const base::FilePath& file_full_path,
|
||||
- BrowserContext* context,
|
||||
- StoragePartition* storage_partition,
|
||||
- SavePackage* save_package) {
|
||||
+void SaveFileManager::SaveURL(
|
||||
+ SaveItemId save_item_id,
|
||||
+ const GURL& url,
|
||||
+ const Referrer& referrer,
|
||||
+ int render_process_host_id,
|
||||
+ int render_view_routing_id,
|
||||
+ int render_frame_routing_id,
|
||||
+ SaveFileCreateInfo::SaveFileSource save_source,
|
||||
+ const base::FilePath& file_full_path,
|
||||
+ BrowserContext* context,
|
||||
+ StoragePartition* storage_partition,
|
||||
+ SavePackage* save_package,
|
||||
+ const std::string& client_guid,
|
||||
+ mojo::PendingRemote<quarantine::mojom::Quarantine> remote_quarantine) {
|
||||
DCHECK_CURRENTLY_ON(BrowserThread::UI);
|
||||
|
||||
// Insert started saving job to tracking list.
|
||||
@@ -285,11 +291,18 @@ void SaveFileManager::SaveURL(SaveItemId save_item_id,
|
||||
factory = storage_partition->GetURLLoaderFactoryForBrowserProcess().get();
|
||||
}
|
||||
|
||||
+ base::OnceCallback<void(bool /*success*/)> save_finished_cb =
|
||||
+ base::BindOnce(&SaveFileManager::OnURLLoaderComplete, this,
|
||||
+ save_item_id, save_package->id(),
|
||||
+ context->IsOffTheRecord() ? GURL() : url,
|
||||
+ context->IsOffTheRecord() ? GURL() : referrer.url,
|
||||
+ client_guid, std::move(remote_quarantine));
|
||||
+
|
||||
url_loader_helpers_[save_item_id] =
|
||||
SimpleURLLoaderHelper::CreateAndStartDownload(
|
||||
std::move(request), save_item_id, save_package->id(),
|
||||
render_process_host_id, render_frame_routing_id, traffic_annotation,
|
||||
- factory, this);
|
||||
+ factory, this, std::move(save_finished_cb));
|
||||
} else {
|
||||
// We manually start the save job.
|
||||
auto info = std::make_unique<SaveFileCreateInfo>(
|
||||
@@ -344,6 +357,36 @@ void SaveFileManager::SendCancelRequest(SaveItemId save_item_id) {
|
||||
base::BindOnce(&SaveFileManager::CancelSave, this, save_item_id));
|
||||
}
|
||||
|
||||
+void SaveFileManager::OnURLLoaderComplete(
|
||||
+ SaveItemId save_item_id,
|
||||
+ SavePackageId save_package_id,
|
||||
+ const GURL& url,
|
||||
+ const GURL& referrer_url,
|
||||
+ const std::string& client_guid,
|
||||
+ mojo::PendingRemote<quarantine::mojom::Quarantine> remote_quarantine,
|
||||
+ bool is_success) {
|
||||
+ DCHECK(download::GetDownloadTaskRunner()->RunsTasksInCurrentSequence());
|
||||
+ SaveFile* save_file = LookupSaveFile(save_item_id);
|
||||
+ if (!is_success || !save_file) {
|
||||
+ SaveFinished(save_item_id, save_package_id, is_success);
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
+ save_file->AnnotateWithSourceInformation(
|
||||
+ client_guid, url, referrer_url, std::move(remote_quarantine),
|
||||
+ base::BindOnce(&SaveFileManager::OnQuarantineComplete, this, save_item_id,
|
||||
+ save_package_id));
|
||||
+}
|
||||
+
|
||||
+void SaveFileManager::OnQuarantineComplete(
|
||||
+ SaveItemId save_item_id,
|
||||
+ SavePackageId save_package_id,
|
||||
+ download::DownloadInterruptReason result) {
|
||||
+ DCHECK(download::GetDownloadTaskRunner()->RunsTasksInCurrentSequence());
|
||||
+ SaveFinished(save_item_id, save_package_id,
|
||||
+ result == download::DOWNLOAD_INTERRUPT_REASON_NONE);
|
||||
+}
|
||||
+
|
||||
// Notifications sent from the IO thread and run on the file thread:
|
||||
|
||||
// The IO thread created |info|, but the file thread (this method) uses it
|
||||
diff --git a/content/browser/download/save_file_manager.h b/content/browser/download/save_file_manager.h
|
||||
index 51eb63a9b189be388e4dff48e04644956e968345..0d4290b273ba4f150bc9a49418e54b709a601581 100644
|
||||
--- a/content/browser/download/save_file_manager.h
|
||||
+++ b/content/browser/download/save_file_manager.h
|
||||
@@ -61,6 +61,8 @@
|
||||
|
||||
#include "base/macros.h"
|
||||
#include "base/memory/ref_counted.h"
|
||||
+#include "components/download/public/common/download_interrupt_reasons.h"
|
||||
+#include "components/services/quarantine/quarantine.h"
|
||||
#include "content/browser/download/save_types.h"
|
||||
#include "content/common/content_export.h"
|
||||
|
||||
@@ -90,17 +92,20 @@ class CONTENT_EXPORT SaveFileManager
|
||||
|
||||
// Saves the specified URL |url|. |save_package| must not be deleted before
|
||||
// the call to RemoveSaveFile. Should be called on the UI thread,
|
||||
- void SaveURL(SaveItemId save_item_id,
|
||||
- const GURL& url,
|
||||
- const Referrer& referrer,
|
||||
- int render_process_host_id,
|
||||
- int render_view_routing_id,
|
||||
- int render_frame_routing_id,
|
||||
- SaveFileCreateInfo::SaveFileSource save_source,
|
||||
- const base::FilePath& file_full_path,
|
||||
- BrowserContext* context,
|
||||
- StoragePartition* storage_partition,
|
||||
- SavePackage* save_package);
|
||||
+ void SaveURL(
|
||||
+ SaveItemId save_item_id,
|
||||
+ const GURL& url,
|
||||
+ const Referrer& referrer,
|
||||
+ int render_process_host_id,
|
||||
+ int render_view_routing_id,
|
||||
+ int render_frame_routing_id,
|
||||
+ SaveFileCreateInfo::SaveFileSource save_source,
|
||||
+ const base::FilePath& file_full_path,
|
||||
+ BrowserContext* context,
|
||||
+ StoragePartition* storage_partition,
|
||||
+ SavePackage* save_package,
|
||||
+ const std::string& client_guid,
|
||||
+ mojo::PendingRemote<quarantine::mojom::Quarantine> remote_quarantine);
|
||||
|
||||
// Notifications sent from the IO thread and run on the file thread:
|
||||
void StartSave(std::unique_ptr<SaveFileCreateInfo> info);
|
||||
@@ -159,6 +164,21 @@ class CONTENT_EXPORT SaveFileManager
|
||||
// Help function for sending notification of canceling specific request.
|
||||
void SendCancelRequest(SaveItemId save_item_id);
|
||||
|
||||
+ // Called on the file thread when the URLLoader completes saving a SaveItem.
|
||||
+ void OnURLLoaderComplete(
|
||||
+ SaveItemId save_item_id,
|
||||
+ SavePackageId save_package_id,
|
||||
+ const GURL& url,
|
||||
+ const GURL& referrer_url,
|
||||
+ const std::string& client_guid,
|
||||
+ mojo::PendingRemote<quarantine::mojom::Quarantine> remote_quarantine,
|
||||
+ bool is_success);
|
||||
+
|
||||
+ // Called on the file thread when file quarantine finishes on a SaveItem.
|
||||
+ void OnQuarantineComplete(SaveItemId save_item_id,
|
||||
+ SavePackageId save_package_id,
|
||||
+ download::DownloadInterruptReason result);
|
||||
+
|
||||
// Notifications sent from the file thread and run on the UI thread.
|
||||
|
||||
// Lookup the SaveManager for this WebContents' saving browser context and
|
||||
diff --git a/content/browser/download/save_package.cc b/content/browser/download/save_package.cc
|
||||
index 4ceea290dcc9b886fb2c65be4ff684854a0f131f..c4653492c8332201f1f6eeb2ce7dbd7fb20c7cc3 100644
|
||||
--- a/content/browser/download/save_package.cc
|
||||
+++ b/content/browser/download/save_package.cc
|
||||
@@ -843,6 +843,12 @@ void SavePackage::SaveNextFile(bool process_all_remaining_items) {
|
||||
RenderFrameHostImpl* requester_frame =
|
||||
requester_frame_tree_node->current_frame_host();
|
||||
|
||||
+ mojo::PendingRemote<quarantine::mojom::Quarantine> quarantine;
|
||||
+ auto quarantine_callback =
|
||||
+ download_manager_->GetQuarantineConnectionCallback();
|
||||
+ if (quarantine_callback)
|
||||
+ quarantine_callback.Run(quarantine.InitWithNewPipeAndPassReceiver());
|
||||
+
|
||||
file_manager_->SaveURL(
|
||||
save_item_ptr->id(), save_item_ptr->url(), save_item_ptr->referrer(),
|
||||
requester_frame->GetProcess()->GetID(),
|
||||
@@ -854,8 +860,8 @@ void SavePackage::SaveNextFile(bool process_all_remaining_items) {
|
||||
->GetRenderViewHost()
|
||||
->GetProcess()
|
||||
->GetStoragePartition(),
|
||||
- this);
|
||||
-
|
||||
+ this, download_manager_->GetApplicationClientIdForFileScanning(),
|
||||
+ std::move(quarantine));
|
||||
} while (process_all_remaining_items && !waiting_item_queue_.empty());
|
||||
}
|
||||
|
||||
106
patches/chromium/cherry-pick-096afc1c5428.patch
Normal file
106
patches/chromium/cherry-pick-096afc1c5428.patch
Normal file
@@ -0,0 +1,106 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Rayan Kanso <rayankans@google.com>
|
||||
Date: Tue, 7 Sep 2021 20:14:30 +0000
|
||||
Subject: Use less-specific error codes for CORS-failing fetches
|
||||
|
||||
(cherry picked from commit 26be5702dab1d98e4d4b076a73d4688d20c043be)
|
||||
|
||||
Bug: 1245053
|
||||
Change-Id: If0343157a3ba41a6c946b5f7401a9d114f834779
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3135676
|
||||
Commit-Queue: Rayan Kanso <rayankans@chromium.org>
|
||||
Reviewed-by: Richard Knoll <knollr@chromium.org>
|
||||
Cr-Original-Commit-Position: refs/heads/main@{#918109}
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3143786
|
||||
Commit-Queue: Richard Knoll <knollr@chromium.org>
|
||||
Cr-Commit-Position: refs/branch-heads/4606@{#833}
|
||||
Cr-Branched-From: 35b0d5a9dc8362adfd44e2614f0d5b7402ef63d0-refs/heads/master@{#911515}
|
||||
|
||||
diff --git a/content/browser/background_fetch/background_fetch_job_controller.cc b/content/browser/background_fetch/background_fetch_job_controller.cc
|
||||
index f424cadba0f42ce007c85a50b2bdb37a3a3a3499..0d08d1f744edd432c9615be811a60daff3b3c541 100644
|
||||
--- a/content/browser/background_fetch/background_fetch_job_controller.cc
|
||||
+++ b/content/browser/background_fetch/background_fetch_job_controller.cc
|
||||
@@ -173,6 +173,8 @@ void BackgroundFetchJobController::DidStartRequest(
|
||||
// TODO(crbug.com/884672): Stop the fetch if the cross origin filter fails.
|
||||
BackgroundFetchCrossOriginFilter filter(registration_id_.origin(), *request);
|
||||
request->set_can_populate_body(filter.CanPopulateBody());
|
||||
+ if (!request->can_populate_body())
|
||||
+ has_failed_cors_request_ = true;
|
||||
}
|
||||
|
||||
void BackgroundFetchJobController::DidUpdateRequest(const std::string& guid,
|
||||
@@ -253,7 +255,14 @@ uint64_t BackgroundFetchJobController::GetInProgressUploadedBytes() {
|
||||
|
||||
void BackgroundFetchJobController::AbortFromDelegate(
|
||||
BackgroundFetchFailureReason failure_reason) {
|
||||
- failure_reason_ = failure_reason;
|
||||
+ if (failure_reason == BackgroundFetchFailureReason::DOWNLOAD_TOTAL_EXCEEDED &&
|
||||
+ has_failed_cors_request_) {
|
||||
+ // Don't expose that the download total has been exceeded. Use a less
|
||||
+ // specific error.
|
||||
+ failure_reason_ = BackgroundFetchFailureReason::FETCH_ERROR;
|
||||
+ } else {
|
||||
+ failure_reason_ = failure_reason;
|
||||
+ }
|
||||
|
||||
Finish(failure_reason_, base::DoNothing());
|
||||
}
|
||||
diff --git a/content/browser/background_fetch/background_fetch_job_controller.h b/content/browser/background_fetch/background_fetch_job_controller.h
|
||||
index e635c86c1eb4237e2b107e3d6fae0242e99dcb4c..66a1c94e9dd79663fbc301c1c91918ef4ac67036 100644
|
||||
--- a/content/browser/background_fetch/background_fetch_job_controller.h
|
||||
+++ b/content/browser/background_fetch/background_fetch_job_controller.h
|
||||
@@ -210,6 +210,10 @@ class CONTENT_EXPORT BackgroundFetchJobController
|
||||
blink::mojom::BackgroundFetchFailureReason failure_reason_ =
|
||||
blink::mojom::BackgroundFetchFailureReason::NONE;
|
||||
|
||||
+ // Whether one of the requests handled by the controller failed
|
||||
+ // the CORS checks and should not have its response exposed.
|
||||
+ bool has_failed_cors_request_ = false;
|
||||
+
|
||||
// Custom callback that runs after the controller is finished.
|
||||
FinishedCallback finished_callback_;
|
||||
|
||||
diff --git a/content/browser/background_fetch/background_fetch_job_controller_unittest.cc b/content/browser/background_fetch/background_fetch_job_controller_unittest.cc
|
||||
index ad9a31367250f90e5579525f42b8b1bde2eefbb1..eb0e8fc337061181d7764eb03bc420df12528c1a 100644
|
||||
--- a/content/browser/background_fetch/background_fetch_job_controller_unittest.cc
|
||||
+++ b/content/browser/background_fetch/background_fetch_job_controller_unittest.cc
|
||||
@@ -433,6 +433,39 @@ TEST_F(BackgroundFetchJobControllerTest, Abort) {
|
||||
GetCompletionStatus(registration_id));
|
||||
}
|
||||
|
||||
+TEST_F(BackgroundFetchJobControllerTest, AbortDownloadExceededCrossOrigin) {
|
||||
+ BackgroundFetchRegistrationId registration_id;
|
||||
+
|
||||
+ auto requests = CreateRegistrationForRequests(
|
||||
+ ®istration_id, {{GURL("https://example2.com/funny_cat.png"), "GET"}},
|
||||
+ /* auto_complete_requests= */ true);
|
||||
+
|
||||
+ EXPECT_EQ(JobCompletionStatus::kRunning,
|
||||
+ GetCompletionStatus(registration_id));
|
||||
+
|
||||
+ std::unique_ptr<BackgroundFetchJobController> controller =
|
||||
+ CreateJobController(registration_id, requests.size());
|
||||
+
|
||||
+ controller->StartRequest(requests[0], base::DoNothing());
|
||||
+
|
||||
+ controller->DidStartRequest(
|
||||
+ requests[0]->download_guid(),
|
||||
+ std::make_unique<BackgroundFetchResponse>(
|
||||
+ std::vector<GURL>{GURL("https://example2.com/funny_cat.png")},
|
||||
+ nullptr));
|
||||
+ EXPECT_FALSE(requests[0]->can_populate_body());
|
||||
+
|
||||
+ controller->AbortFromDelegate(
|
||||
+ blink::mojom::BackgroundFetchFailureReason::DOWNLOAD_TOTAL_EXCEEDED);
|
||||
+
|
||||
+ base::RunLoop().RunUntilIdle();
|
||||
+
|
||||
+ EXPECT_EQ(JobCompletionStatus::kAborted,
|
||||
+ GetCompletionStatus(registration_id));
|
||||
+ EXPECT_EQ(finished_requests_[registration_id],
|
||||
+ blink::mojom::BackgroundFetchFailureReason::FETCH_ERROR);
|
||||
+}
|
||||
+
|
||||
TEST_F(BackgroundFetchJobControllerTest, Progress) {
|
||||
BackgroundFetchRegistrationId registration_id;
|
||||
|
||||
215
patches/chromium/cherry-pick-1227933.patch
Normal file
215
patches/chromium/cherry-pick-1227933.patch
Normal file
@@ -0,0 +1,215 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Koji Ishii <kojii@chromium.org>
|
||||
Date: Mon, 26 Jul 2021 07:09:18 +0000
|
||||
Subject: Fix nested inline box fragmentation
|
||||
|
||||
This patch fixes when nested inline boxes are fragmented in a
|
||||
line due to bidi reordering.
|
||||
|
||||
Before this change, the fragmented boxes are appended to the
|
||||
end of |box_data_list_|. Then when |NGInlineLayoutStateStack::
|
||||
CreateBoxFragments| creates inline boxes in the ascending
|
||||
order of |box_data_list_|, it failed to add the fragmented
|
||||
boxes into their parent inline boxes.
|
||||
|
||||
This is critical for out-of-flow positioned objects whose
|
||||
containing block is an inline box, because they expect to be
|
||||
propagated through all ancestor inline boxes.
|
||||
|
||||
|UpdateBoxDataFragmentRange| is a little tricky by appending
|
||||
to a vector it is iterating. Changing it to insert to the
|
||||
correct position makes the function even trickier. This patch
|
||||
changes it to add fragmented boxes to a separate vector, and
|
||||
let later process |UpdateFragmentedBoxDataEdges| to merge the
|
||||
vector to |box_data_list_|.
|
||||
|
||||
(cherry picked from commit 9c8a39c14a9c80556468593cddf436f5047a16ce)
|
||||
|
||||
Bug: 1227933, 1229999
|
||||
Change-Id: I7edcd209e1fdac06bab01b16d660383e7e9c37bd
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3038308
|
||||
Commit-Queue: Koji Ishii <kojii@chromium.org>
|
||||
Reviewed-by: Yoshifumi Inoue <yosin@chromium.org>
|
||||
Cr-Original-Commit-Position: refs/heads/master@{#903356}
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3053212
|
||||
Commit-Queue: Rubber Stamper <rubber-stamper@appspot.gserviceaccount.com>
|
||||
Bot-Commit: Rubber Stamper <rubber-stamper@appspot.gserviceaccount.com>
|
||||
Auto-Submit: Koji Ishii <kojii@chromium.org>
|
||||
Cr-Commit-Position: refs/branch-heads/4577@{#145}
|
||||
Cr-Branched-From: 761ddde228655e313424edec06497d0c56b0f3c4-refs/heads/master@{#902210}
|
||||
|
||||
diff --git a/third_party/blink/renderer/core/layout/ng/inline/ng_inline_box_state.cc b/third_party/blink/renderer/core/layout/ng/inline/ng_inline_box_state.cc
|
||||
index b257014513cb881d4531694b86c05fd21edb6732..9a3f6f3af7839ebed24f7d8a32b7f95fba66cd9a 100644
|
||||
--- a/third_party/blink/renderer/core/layout/ng/inline/ng_inline_box_state.cc
|
||||
+++ b/third_party/blink/renderer/core/layout/ng/inline/ng_inline_box_state.cc
|
||||
@@ -4,6 +4,7 @@
|
||||
|
||||
#include "third_party/blink/renderer/core/layout/ng/inline/ng_inline_box_state.h"
|
||||
|
||||
+#include "base/containers/adapters.h"
|
||||
#include "third_party/blink/renderer/core/layout/geometry/logical_offset.h"
|
||||
#include "third_party/blink/renderer/core/layout/geometry/logical_size.h"
|
||||
#include "third_party/blink/renderer/core/layout/ng/inline/ng_inline_item_result.h"
|
||||
@@ -387,13 +388,14 @@ void NGInlineLayoutStateStack::UpdateAfterReorder(
|
||||
box_data.fragment_start = box_data.fragment_end = 0;
|
||||
|
||||
// Scan children and update start/end from their box_data_index.
|
||||
- unsigned box_count = box_data_list_.size();
|
||||
+ Vector<BoxData> fragmented_boxes;
|
||||
for (unsigned index = 0; index < line_box->size();)
|
||||
- index = UpdateBoxDataFragmentRange(line_box, index);
|
||||
+ index = UpdateBoxDataFragmentRange(line_box, index, &fragmented_boxes);
|
||||
|
||||
- // If any inline fragmentation due to BiDi reorder, adjust box edges.
|
||||
- if (box_count != box_data_list_.size())
|
||||
- UpdateFragmentedBoxDataEdges();
|
||||
+ // If any inline fragmentation occurred due to BiDi reorder, append them and
|
||||
+ // adjust box edges.
|
||||
+ if (UNLIKELY(!fragmented_boxes.IsEmpty()))
|
||||
+ UpdateFragmentedBoxDataEdges(&fragmented_boxes);
|
||||
|
||||
#if DCHECK_IS_ON()
|
||||
// Check all BoxData have ranges.
|
||||
@@ -410,7 +412,8 @@ void NGInlineLayoutStateStack::UpdateAfterReorder(
|
||||
|
||||
unsigned NGInlineLayoutStateStack::UpdateBoxDataFragmentRange(
|
||||
NGLogicalLineItems* line_box,
|
||||
- unsigned index) {
|
||||
+ unsigned index,
|
||||
+ Vector<BoxData>* fragmented_boxes) {
|
||||
// Find the first line box item that should create a box fragment.
|
||||
for (; index < line_box->size(); index++) {
|
||||
NGLogicalLineItem* start = &(*line_box)[index];
|
||||
@@ -438,7 +441,7 @@ unsigned NGInlineLayoutStateStack::UpdateBoxDataFragmentRange(
|
||||
// It also changes other BoxData, but not the one we're dealing with here
|
||||
// because the update is limited only when its |box_data_index| is lower.
|
||||
while (end->box_data_index && end->box_data_index < box_data_index) {
|
||||
- UpdateBoxDataFragmentRange(line_box, index);
|
||||
+ UpdateBoxDataFragmentRange(line_box, index, fragmented_boxes);
|
||||
}
|
||||
|
||||
if (box_data_index != end->box_data_index)
|
||||
@@ -453,14 +456,9 @@ unsigned NGInlineLayoutStateStack::UpdateBoxDataFragmentRange(
|
||||
} else {
|
||||
// This box is fragmented by BiDi reordering. Add a new BoxData for the
|
||||
// fragmented range.
|
||||
- box_data_list_[box_data_index - 1].fragmented_box_data_index =
|
||||
- box_data_list_.size();
|
||||
- // Do not use `emplace_back()` here because adding to |box_data_list_| may
|
||||
- // reallocate the buffer, but the `BoxData` ctor must run before the
|
||||
- // reallocation. Create a new instance and |push_back()| instead.
|
||||
- BoxData fragmented_box_data(box_data_list_[box_data_index - 1],
|
||||
- start_index, index);
|
||||
- box_data_list_.push_back(fragmented_box_data);
|
||||
+ BoxData& fragmented_box = fragmented_boxes->emplace_back(
|
||||
+ box_data_list_[box_data_index - 1], start_index, index);
|
||||
+ fragmented_box.fragmented_box_data_index = box_data_index;
|
||||
}
|
||||
// If this box has parent boxes, we need to process it again.
|
||||
if (box_data_list_[box_data_index - 1].parent_box_data_index)
|
||||
@@ -470,7 +468,43 @@ unsigned NGInlineLayoutStateStack::UpdateBoxDataFragmentRange(
|
||||
return index;
|
||||
}
|
||||
|
||||
-void NGInlineLayoutStateStack::UpdateFragmentedBoxDataEdges() {
|
||||
+void NGInlineLayoutStateStack::UpdateFragmentedBoxDataEdges(
|
||||
+ Vector<BoxData>* fragmented_boxes) {
|
||||
+ DCHECK(!fragmented_boxes->IsEmpty());
|
||||
+ // Append in the descending order of |fragmented_box_data_index| because the
|
||||
+ // indices will change as boxes are inserted into |box_data_list_|.
|
||||
+ std::sort(fragmented_boxes->begin(), fragmented_boxes->end(),
|
||||
+ [](const BoxData& a, const BoxData& b) {
|
||||
+ if (a.fragmented_box_data_index != b.fragmented_box_data_index) {
|
||||
+ return a.fragmented_box_data_index <
|
||||
+ b.fragmented_box_data_index;
|
||||
+ }
|
||||
+ DCHECK_NE(a.fragment_start, b.fragment_start);
|
||||
+ return a.fragment_start < b.fragment_start;
|
||||
+ });
|
||||
+ for (BoxData& fragmented_box : base::Reversed(*fragmented_boxes)) {
|
||||
+ // Insert the fragmented box to right after the box it was fragmented from.
|
||||
+ // The order in the |box_data_list_| is critical when propagating child
|
||||
+ // fragment data such as OOF to ancestors.
|
||||
+ const unsigned insert_at = fragmented_box.fragmented_box_data_index;
|
||||
+ DCHECK_GT(insert_at, 0u);
|
||||
+ fragmented_box.fragmented_box_data_index = 0;
|
||||
+ box_data_list_.insert(insert_at, fragmented_box);
|
||||
+
|
||||
+ // Adjust box data indices by the insertion.
|
||||
+ for (BoxData& box_data : box_data_list_) {
|
||||
+ if (box_data.fragmented_box_data_index >= insert_at)
|
||||
+ ++box_data.fragmented_box_data_index;
|
||||
+ }
|
||||
+
|
||||
+ // Set the index of the last fragment to the original box. This is needed to
|
||||
+ // update fragment edges.
|
||||
+ const unsigned fragmented_from = insert_at - 1;
|
||||
+ if (!box_data_list_[fragmented_from].fragmented_box_data_index)
|
||||
+ box_data_list_[fragmented_from].fragmented_box_data_index = insert_at;
|
||||
+ }
|
||||
+
|
||||
+ // Move the line-right edge to the last fragment.
|
||||
for (BoxData& box_data : box_data_list_) {
|
||||
if (box_data.fragmented_box_data_index)
|
||||
box_data.UpdateFragmentEdges(box_data_list_);
|
||||
diff --git a/third_party/blink/renderer/core/layout/ng/inline/ng_inline_box_state.h b/third_party/blink/renderer/core/layout/ng/inline/ng_inline_box_state.h
|
||||
index 82ecfef8fe4d404d5713f0f67d83b38ecfbfca4c..9d079266efd7f2ccc43cef40d8d89e4fc6edda9e 100644
|
||||
--- a/third_party/blink/renderer/core/layout/ng/inline/ng_inline_box_state.h
|
||||
+++ b/third_party/blink/renderer/core/layout/ng/inline/ng_inline_box_state.h
|
||||
@@ -156,17 +156,6 @@ class CORE_EXPORT NGInlineLayoutStateStack {
|
||||
// reordering.
|
||||
void UpdateAfterReorder(NGLogicalLineItems*);
|
||||
|
||||
- // Update start/end of the first BoxData found at |index|.
|
||||
- //
|
||||
- // If inline fragmentation is found, a new BoxData is added.
|
||||
- //
|
||||
- // Returns the index to process next. It should be given to the next call to
|
||||
- // this function.
|
||||
- unsigned UpdateBoxDataFragmentRange(NGLogicalLineItems*, unsigned index);
|
||||
-
|
||||
- // Update edges of inline fragmented boxes.
|
||||
- void UpdateFragmentedBoxDataEdges();
|
||||
-
|
||||
// Compute inline positions of fragments and boxes.
|
||||
LayoutUnit ComputeInlinePositions(NGLogicalLineItems*, LayoutUnit position);
|
||||
|
||||
@@ -259,6 +248,19 @@ class CORE_EXPORT NGInlineLayoutStateStack {
|
||||
scoped_refptr<const NGLayoutResult> CreateBoxFragment(NGLogicalLineItems*);
|
||||
};
|
||||
|
||||
+ // Update start/end of the first BoxData found at |index|.
|
||||
+ //
|
||||
+ // If inline fragmentation is found, a new BoxData is added.
|
||||
+ //
|
||||
+ // Returns the index to process next. It should be given to the next call to
|
||||
+ // this function.
|
||||
+ unsigned UpdateBoxDataFragmentRange(NGLogicalLineItems*,
|
||||
+ unsigned index,
|
||||
+ Vector<BoxData>* fragmented_boxes);
|
||||
+
|
||||
+ // Update edges of inline fragmented boxes.
|
||||
+ void UpdateFragmentedBoxDataEdges(Vector<BoxData>* fragmented_boxes);
|
||||
+
|
||||
Vector<NGInlineBoxState, 4> stack_;
|
||||
Vector<BoxData, 4> box_data_list_;
|
||||
|
||||
diff --git a/third_party/blink/web_tests/external/wpt/css/CSS2/text/crashtests/bidi-inline-fragment-oof-crash.html b/third_party/blink/web_tests/external/wpt/css/CSS2/text/crashtests/bidi-inline-fragment-oof-crash.html
|
||||
new file mode 100644
|
||||
index 0000000000000000000000000000000000000000..b701d2b5688ace54aa99530c12fa8143f1e6a508
|
||||
--- /dev/null
|
||||
+++ b/third_party/blink/web_tests/external/wpt/css/CSS2/text/crashtests/bidi-inline-fragment-oof-crash.html
|
||||
@@ -0,0 +1,13 @@
|
||||
+<!DOCTYPE html>
|
||||
+<link rel="author" href="mailto:mstensho@chromium.org">
|
||||
+<link rel="help" href="https://crbug.com/1229999">
|
||||
+<div style="direction:rtl; width:500px">
|
||||
+ <span style="border:solid">
|
||||
+ <span style="position:relative">
|
||||
+ <div style="display:inline-block; width:1000%; height:10px"></div>
|
||||
+ <span dir="ltr">
|
||||
+ <div style="position:absolute"></div>
|
||||
+ </span>
|
||||
+ </span>
|
||||
+ </span>
|
||||
+</div>
|
||||
115
patches/chromium/cherry-pick-1230767.patch
Normal file
115
patches/chromium/cherry-pick-1230767.patch
Normal file
@@ -0,0 +1,115 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Harald Alvestrand <hta@chromium.org>
|
||||
Date: Tue, 10 Aug 2021 10:49:27 +0000
|
||||
Subject: Protect candidate better from garbage collection during negotiation.
|
||||
|
||||
Includes a test that was reliably observed to produce an UAF on Linux
|
||||
when compiled with ASAN before the fix.
|
||||
|
||||
Bug: chromium:1230767
|
||||
Change-Id: I02dd29332a6d00790dcace41b6584b96413ef6f4
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3057049
|
||||
Reviewed-by: Florent Castelli <orphis@chromium.org>
|
||||
Commit-Queue: Harald Alvestrand <hta@chromium.org>
|
||||
Cr-Commit-Position: refs/heads/master@{#910244}
|
||||
|
||||
diff --git a/third_party/blink/renderer/modules/peerconnection/rtc_peer_connection_handler.cc b/third_party/blink/renderer/modules/peerconnection/rtc_peer_connection_handler.cc
|
||||
index 9265e14be8f86d2f1a2d888a789c121ddb514e88..84a8825ec87bcd9f1c0d7c502034bfbc3bfcafd1 100644
|
||||
--- a/third_party/blink/renderer/modules/peerconnection/rtc_peer_connection_handler.cc
|
||||
+++ b/third_party/blink/renderer/modules/peerconnection/rtc_peer_connection_handler.cc
|
||||
@@ -1629,7 +1629,8 @@ void RTCPeerConnectionHandler::AddICECandidate(
|
||||
handler_weak_ptr = weak_factory_.GetWeakPtr(),
|
||||
tracker_weak_ptr =
|
||||
WrapCrossThreadWeakPersistent(peer_connection_tracker_.Get()),
|
||||
- candidate, persistent_request = WrapCrossThreadPersistent(request),
|
||||
+ persistent_candidate = WrapCrossThreadPersistent(candidate),
|
||||
+ persistent_request = WrapCrossThreadPersistent(request),
|
||||
callback_on_task_runner =
|
||||
std::move(callback_on_task_runner)](webrtc::RTCError result) {
|
||||
// Grab a snapshot of all the session descriptions. AddIceCandidate may
|
||||
@@ -1657,7 +1658,7 @@ void RTCPeerConnectionHandler::AddICECandidate(
|
||||
std::move(current_local_description),
|
||||
std::move(pending_remote_description),
|
||||
std::move(current_remote_description),
|
||||
- WrapCrossThreadPersistent(candidate), std::move(result),
|
||||
+ std::move(persistent_candidate), std::move(result),
|
||||
std::move(persistent_request)));
|
||||
});
|
||||
}
|
||||
diff --git a/third_party/blink/web_tests/fast/peerconnection/poc-123067.html b/third_party/blink/web_tests/fast/peerconnection/poc-123067.html
|
||||
new file mode 100644
|
||||
index 0000000000000000000000000000000000000000..ff169f1d1e1333b9ccfcae7eaa833ec645779218
|
||||
--- /dev/null
|
||||
+++ b/third_party/blink/web_tests/fast/peerconnection/poc-123067.html
|
||||
@@ -0,0 +1,71 @@
|
||||
+<!DOCTYPE html>
|
||||
+<html>
|
||||
+
|
||||
+ <head>
|
||||
+ <script src="../../resources/testharness.js"></script>
|
||||
+ <script src="../../resources/testharnessreport.js"></script>
|
||||
+ <script src="../../resources/gc.js"></script>
|
||||
+ </head>
|
||||
+ <body>
|
||||
+ <script>
|
||||
+ 'use strict';
|
||||
+ promise_test(async t => {
|
||||
+ const var_caller_1 = new RTCPeerConnection();
|
||||
+ const var_callee_1 = new RTCPeerConnection();
|
||||
+ var_caller_1.addTransceiver('audio');
|
||||
+ const var_prom_1 = new Promise(resolve => {
|
||||
+ var_caller_1.onicecandidate = e => resolve(e.candidate);
|
||||
+ });
|
||||
+ await var_caller_1.setLocalDescription(await var_caller_1.createOffer());
|
||||
+ await var_callee_1.setRemoteDescription(var_caller_1.localDescription);
|
||||
+ const candidate = await var_prom_1;
|
||||
+ var arrProm = [];
|
||||
+ gc();
|
||||
+ var_callee_1.setLocalDescription().then(() => {
|
||||
+ })
|
||||
+ var_callee_1.setLocalDescription().then(() => {
|
||||
+ })
|
||||
+ var_callee_1.setLocalDescription().then(() => {
|
||||
+ })
|
||||
+ var_callee_1.setLocalDescription().then(() => {
|
||||
+ })
|
||||
+ var_callee_1.setLocalDescription().then(() => {
|
||||
+ })
|
||||
+ var_callee_1.setLocalDescription().then(() => {
|
||||
+ })
|
||||
+ var_callee_1.setLocalDescription().then(() => {
|
||||
+ })
|
||||
+ var_callee_1.setLocalDescription().then(() => {
|
||||
+ })
|
||||
+ var_callee_1.setLocalDescription().then(() => {
|
||||
+ })
|
||||
+ var_callee_1.setLocalDescription().then(() => {
|
||||
+ })
|
||||
+ var_callee_1.setLocalDescription().then(() => {
|
||||
+ })
|
||||
+ var_callee_1.setLocalDescription().then(() => {
|
||||
+ })
|
||||
+ var_callee_1.setLocalDescription().then(() => {
|
||||
+ })
|
||||
+ var_callee_1.setLocalDescription().then(() => {
|
||||
+ })
|
||||
+ var_callee_1.setLocalDescription().then(() => {
|
||||
+ })
|
||||
+ var_callee_1.setLocalDescription().then(() => {
|
||||
+ })
|
||||
+ var_callee_1.setLocalDescription().then(() => {
|
||||
+ })
|
||||
+ var_callee_1.setLocalDescription().then(() => {
|
||||
+ })
|
||||
+ var_callee_1.setLocalDescription().then(() => {
|
||||
+ })
|
||||
+ var_callee_1.addIceCandidate(candidate).then(() => {
|
||||
+ })
|
||||
+ await Promise.all(arrProm);
|
||||
+ }, 'Running this script does not cause an UAF');
|
||||
+ </script>
|
||||
+</head>
|
||||
+
|
||||
+<body></body>
|
||||
+
|
||||
+</html>
|
||||
163
patches/chromium/cherry-pick-1231134.patch
Normal file
163
patches/chromium/cherry-pick-1231134.patch
Normal file
@@ -0,0 +1,163 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Lei Zhang <thestig@chromium.org>
|
||||
Date: Tue, 10 Aug 2021 21:38:36 +0000
|
||||
Subject: Do more class validity checks in PrintViewManagerBase.
|
||||
|
||||
PrintViewManagerBase runs a nested loop. In some situations,
|
||||
PrintViewManagerBase and related classes like PrintViewManager and
|
||||
PrintPreviewHandler can get deleted while the nested loop is running.
|
||||
When this happens, the nested loop exists to a PrintViewManagerBase
|
||||
that is no longer valid.
|
||||
|
||||
Use base::WeakPtrs liberally to check for this condition and exit
|
||||
safely.
|
||||
|
||||
(cherry picked from commit a2cb1fb333d2faacb2fe1380f8d2621b5ee6af7e)
|
||||
|
||||
Bug: 1231134
|
||||
Change-Id: I21ec131574331ce973d22594c11e70088147e149
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3057880
|
||||
Reviewed-by: Alan Screen <awscreen@chromium.org>
|
||||
Commit-Queue: Lei Zhang <thestig@chromium.org>
|
||||
Cr-Original-Commit-Position: refs/heads/master@{#906269}
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3086110
|
||||
Bot-Commit: Rubber Stamper <rubber-stamper@appspot.gserviceaccount.com>
|
||||
Cr-Commit-Position: refs/branch-heads/4515@{#2024}
|
||||
Cr-Branched-From: 488fc70865ddaa05324ac00a54a6eb783b4bc41c-refs/heads/master@{#885287}
|
||||
|
||||
diff --git a/chrome/browser/printing/print_view_manager.cc b/chrome/browser/printing/print_view_manager.cc
|
||||
index 26271f6689f1f887b82333d281f26012d2752d63..e73d0972b1b6d6db1fbb3825791e5b90146c2c5e 100644
|
||||
--- a/chrome/browser/printing/print_view_manager.cc
|
||||
+++ b/chrome/browser/printing/print_view_manager.cc
|
||||
@@ -89,7 +89,11 @@ bool PrintViewManager::PrintForSystemDialogNow(
|
||||
DCHECK(!on_print_dialog_shown_callback_);
|
||||
on_print_dialog_shown_callback_ = std::move(dialog_shown_callback);
|
||||
is_switching_to_system_dialog_ = true;
|
||||
+
|
||||
+ auto weak_this = weak_factory_.GetWeakPtr();
|
||||
DisconnectFromCurrentPrintJob();
|
||||
+ if (!weak_this)
|
||||
+ return false;
|
||||
|
||||
// Don't print / print preview crashed tabs.
|
||||
if (IsCrashed())
|
||||
diff --git a/chrome/browser/printing/print_view_manager.h b/chrome/browser/printing/print_view_manager.h
|
||||
index 8b2f150a1e6a042898cba14c971e1f80d04116ca..b5cba8a2dfb9021527e4cc5569635770e85949b3 100644
|
||||
--- a/chrome/browser/printing/print_view_manager.h
|
||||
+++ b/chrome/browser/printing/print_view_manager.h
|
||||
@@ -128,6 +128,11 @@ class PrintViewManager : public PrintViewManagerBase,
|
||||
|
||||
WEB_CONTENTS_USER_DATA_KEY_DECL();
|
||||
|
||||
+ // Keep this last so that all weak pointers will be invalidated at the
|
||||
+ // beginning of destruction. Note that PrintViewManagerBase has its own
|
||||
+ // base::WeakPtrFactory as well, but PrintViewManager should use this one.
|
||||
+ base::WeakPtrFactory<PrintViewManager> weak_factory_{this};
|
||||
+
|
||||
DISALLOW_COPY_AND_ASSIGN(PrintViewManager);
|
||||
};
|
||||
|
||||
diff --git a/chrome/browser/printing/print_view_manager_base.cc b/chrome/browser/printing/print_view_manager_base.cc
|
||||
index 3b6e1d2609af952fa825688833387518cafdb352..3ddd927654e0134c28a7f73c6ec30b0c1ffe5c49 100644
|
||||
--- a/chrome/browser/printing/print_view_manager_base.cc
|
||||
+++ b/chrome/browser/printing/print_view_manager_base.cc
|
||||
@@ -370,7 +370,10 @@ bool PrintViewManagerBase::PrintNow(content::RenderFrameHost* rfh,
|
||||
bool silent,
|
||||
base::Value settings,
|
||||
CompletionCallback callback) {
|
||||
+ auto weak_this = weak_ptr_factory_.GetWeakPtr();
|
||||
DisconnectFromCurrentPrintJob();
|
||||
+ if (!weak_this)
|
||||
+ return false;
|
||||
|
||||
// Don't print / print preview crashed tabs.
|
||||
if (IsCrashed())
|
||||
@@ -850,6 +853,8 @@ bool PrintViewManagerBase::RenderAllMissingPagesNow() {
|
||||
// or in DidPrintDocument(). The check is done in
|
||||
// ShouldQuitFromInnerMessageLoop().
|
||||
// BLOCKS until all the pages are received. (Need to enable recursive task)
|
||||
+ // WARNING: Do not do any work after RunInnerMessageLoop() returns, as `this`
|
||||
+ // may have gone away.
|
||||
if (!RunInnerMessageLoop()) {
|
||||
// This function is always called from DisconnectFromCurrentPrintJob() so we
|
||||
// know that the job will be stopped/canceled in any case.
|
||||
@@ -876,8 +881,11 @@ bool PrintViewManagerBase::CreateNewPrintJob(
|
||||
DCHECK(query);
|
||||
|
||||
if (callback_.is_null()) {
|
||||
+ auto weak_this = weak_ptr_factory_.GetWeakPtr();
|
||||
// Disconnect the current |print_job_| only when calling window.print()
|
||||
DisconnectFromCurrentPrintJob();
|
||||
+ if (!weak_this)
|
||||
+ return false;
|
||||
}
|
||||
|
||||
// We can't print if there is no renderer.
|
||||
@@ -906,7 +914,10 @@ bool PrintViewManagerBase::CreateNewPrintJob(
|
||||
void PrintViewManagerBase::DisconnectFromCurrentPrintJob() {
|
||||
// Make sure all the necessary rendered page are done. Don't bother with the
|
||||
// return value.
|
||||
+ auto weak_this = weak_ptr_factory_.GetWeakPtr();
|
||||
bool result = RenderAllMissingPagesNow();
|
||||
+ if (!weak_this)
|
||||
+ return;
|
||||
|
||||
// Verify that assertion.
|
||||
if (print_job_ && print_job_->document() &&
|
||||
@@ -988,7 +999,10 @@ bool PrintViewManagerBase::RunInnerMessageLoop() {
|
||||
|
||||
quit_inner_loop_ = run_loop.QuitClosure();
|
||||
|
||||
+ auto weak_this = weak_ptr_factory_.GetWeakPtr();
|
||||
run_loop.Run();
|
||||
+ if (!weak_this)
|
||||
+ return false;
|
||||
|
||||
// If the inner-loop quit closure is still set then we timed out.
|
||||
bool success = !quit_inner_loop_;
|
||||
diff --git a/chrome/browser/printing/print_view_manager_base.h b/chrome/browser/printing/print_view_manager_base.h
|
||||
index ccb9808bdb334a78ed7b64dd3030caff52055ad6..b2ad5c1010b233e038cad9e2b5e39f3c0027d63e 100644
|
||||
--- a/chrome/browser/printing/print_view_manager_base.h
|
||||
+++ b/chrome/browser/printing/print_view_manager_base.h
|
||||
@@ -122,6 +122,8 @@ class PrintViewManagerBase : public content::NotificationObserver,
|
||||
|
||||
// Makes sure the current print_job_ has all its data before continuing, and
|
||||
// disconnect from it.
|
||||
+ // WARNING: `this` may not be alive after DisconnectFromCurrentPrintJob()
|
||||
+ // returns.
|
||||
void DisconnectFromCurrentPrintJob();
|
||||
|
||||
// Manages the low-level talk to the printer.
|
||||
@@ -168,6 +170,7 @@ class PrintViewManagerBase : public content::NotificationObserver,
|
||||
// Requests the RenderView to render all the missing pages for the print job.
|
||||
// No-op if no print job is pending. Returns true if at least one page has
|
||||
// been requested to the renderer.
|
||||
+ // WARNING: `this` may not be alive after RenderAllMissingPagesNow() returns.
|
||||
bool RenderAllMissingPagesNow();
|
||||
|
||||
// Checks that synchronization is correct with |print_job_| based on |cookie|.
|
||||
@@ -201,6 +204,7 @@ class PrintViewManagerBase : public content::NotificationObserver,
|
||||
// while the blocking inner message loop is running. This is useful in cases
|
||||
// where the RenderView is about to be destroyed while a printing job isn't
|
||||
// finished.
|
||||
+ // WARNING: `this` may not be alive after RunInnerMessageLoop() returns.
|
||||
bool RunInnerMessageLoop();
|
||||
|
||||
// In the case of Scripted Printing, where the renderer is controlling the
|
||||
diff --git a/chrome/browser/ui/webui/print_preview/print_preview_handler.cc b/chrome/browser/ui/webui/print_preview/print_preview_handler.cc
|
||||
index 82a2ac9bc0e5d32438a6ec6bd500cae7da8739fe..fe8a580e2fc5dbb74a57bf8488888a9696ce0007 100644
|
||||
--- a/chrome/browser/ui/webui/print_preview/print_preview_handler.cc
|
||||
+++ b/chrome/browser/ui/webui/print_preview/print_preview_handler.cc
|
||||
@@ -726,9 +726,12 @@ void PrintPreviewHandler::HandleShowSystemDialog(
|
||||
if (!initiator)
|
||||
return;
|
||||
|
||||
+ auto weak_this = weak_factory_.GetWeakPtr();
|
||||
auto* print_view_manager = PrintViewManager::FromWebContents(initiator);
|
||||
print_view_manager->PrintForSystemDialogNow(base::BindOnce(
|
||||
&PrintPreviewHandler::ClosePreviewDialog, weak_factory_.GetWeakPtr()));
|
||||
+ if (!weak_this)
|
||||
+ return;
|
||||
|
||||
// Cancel the pending preview request if exists.
|
||||
print_preview_ui()->OnCancelPendingPreviewRequest();
|
||||
77
patches/chromium/cherry-pick-1233564.patch
Normal file
77
patches/chromium/cherry-pick-1233564.patch
Normal file
@@ -0,0 +1,77 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Hongchan Choi <hongchan@chromium.org>
|
||||
Date: Mon, 9 Aug 2021 18:43:22 +0000
|
||||
Subject: Protect HRTF database loader thread from access by different threads
|
||||
|
||||
This patch add a new mutex locker around the HRTF database loader
|
||||
thread to ensure the safe exclusive access of the loader thread
|
||||
and the HRTF database.
|
||||
|
||||
(cherry picked from commit 6811e850ee10847da16c4d5fdc0f845494586b65)
|
||||
|
||||
Bug: 1233564
|
||||
Change-Id: Ie12b99ffe520d3747e34af387a37637a10aab38a
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3068260
|
||||
Auto-Submit: Hongchan Choi <hongchan@chromium.org>
|
||||
Commit-Queue: Kentaro Hara <haraken@chromium.org>
|
||||
Reviewed-by: Kentaro Hara <haraken@chromium.org>
|
||||
Cr-Original-Commit-Position: refs/heads/master@{#908269}
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3082114
|
||||
Reviewed-by: Chris Mumford <cmumford@google.com>
|
||||
Commit-Queue: Hongchan Choi <hongchan@chromium.org>
|
||||
Cr-Commit-Position: refs/branch-heads/4577@{#601}
|
||||
Cr-Branched-From: 761ddde228655e313424edec06497d0c56b0f3c4-refs/heads/master@{#902210}
|
||||
|
||||
diff --git a/third_party/blink/renderer/platform/audio/hrtf_database_loader.cc b/third_party/blink/renderer/platform/audio/hrtf_database_loader.cc
|
||||
index 034ded03d11fa42f0d0f62c6a91f6e20ee5f93e1..01cb98a1116fe1eb6a13ff6345b6bdf4e136badc 100644
|
||||
--- a/third_party/blink/renderer/platform/audio/hrtf_database_loader.cc
|
||||
+++ b/third_party/blink/renderer/platform/audio/hrtf_database_loader.cc
|
||||
@@ -86,6 +86,8 @@ void HRTFDatabaseLoader::LoadTask() {
|
||||
void HRTFDatabaseLoader::LoadAsynchronously() {
|
||||
DCHECK(IsMainThread());
|
||||
|
||||
+ MutexLocker locker(lock_);
|
||||
+
|
||||
// m_hrtfDatabase and m_thread should both be unset because this should be a
|
||||
// new HRTFDatabaseLoader object that was just created by
|
||||
// createAndLoadAsynchronouslyIfNecessary and because we haven't started
|
||||
@@ -122,6 +124,10 @@ void HRTFDatabaseLoader::CleanupTask(base::WaitableEvent* sync) {
|
||||
}
|
||||
|
||||
void HRTFDatabaseLoader::WaitForLoaderThreadCompletion() {
|
||||
+ // We can lock this because this is called from either the main thread or
|
||||
+ // the offline audio rendering thread.
|
||||
+ MutexLocker locker(lock_);
|
||||
+
|
||||
if (!thread_)
|
||||
return;
|
||||
|
||||
diff --git a/third_party/blink/renderer/platform/audio/hrtf_database_loader.h b/third_party/blink/renderer/platform/audio/hrtf_database_loader.h
|
||||
index 3ce476fa68e066d6faf40011e94203f0fb778e71..a94997b4f7e06f96018187967faa524d4acfd5f6 100644
|
||||
--- a/third_party/blink/renderer/platform/audio/hrtf_database_loader.h
|
||||
+++ b/third_party/blink/renderer/platform/audio/hrtf_database_loader.h
|
||||
@@ -64,8 +64,8 @@ class PLATFORM_EXPORT HRTFDatabaseLoader final
|
||||
// must be called from the audio thread.
|
||||
bool IsLoaded() { return Database(); }
|
||||
|
||||
- // waitForLoaderThreadCompletion() may be called more than once and is
|
||||
- // thread-safe.
|
||||
+ // May be called from both main and audio thread, and also can be called more
|
||||
+ // than once.
|
||||
void WaitForLoaderThreadCompletion();
|
||||
|
||||
// Returns the database or nullptr if the database doesn't yet exist. Must
|
||||
@@ -87,11 +87,10 @@ class PLATFORM_EXPORT HRTFDatabaseLoader final
|
||||
void LoadTask();
|
||||
void CleanupTask(base::WaitableEvent*);
|
||||
|
||||
- // Holding a m_lock is required when accessing m_hrtfDatabase since we access
|
||||
- // it from multiple threads.
|
||||
+ // |lock_| MUST be held when accessing |hrtf_database_| or |thread_| because
|
||||
+ // it can be accessed by multiple threads (e.g multiple AudioContexts).
|
||||
Mutex lock_;
|
||||
std::unique_ptr<HRTFDatabase> hrtf_database_;
|
||||
-
|
||||
std::unique_ptr<Thread> thread_;
|
||||
|
||||
float database_sample_rate_;
|
||||
138
patches/chromium/cherry-pick-1234009.patch
Normal file
138
patches/chromium/cherry-pick-1234009.patch
Normal file
@@ -0,0 +1,138 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Sam McNally <sammc@chromium.org>
|
||||
Date: Tue, 10 Aug 2021 02:14:43 +0000
|
||||
Subject: Defer looking up the WebContents for the directory confirmation
|
||||
dialog.
|
||||
|
||||
Look up the WebContents to use for the sensitive directory confirmation
|
||||
dialog immediately before it's used instead of before performing some
|
||||
blocking file access to determine whether it's necessary.
|
||||
|
||||
(cherry picked from commit 18236a0db8341302120c60781ae3129e94fbaf1c)
|
||||
|
||||
Bug: 1234009
|
||||
Change-Id: I5e00c7fa199b3da522e1fdb73242891d7f5f7423
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3063743
|
||||
Reviewed-by: Alex Danilo <adanilo@chromium.org>
|
||||
Reviewed-by: Ben Wells <benwells@chromium.org>
|
||||
Commit-Queue: Sam McNally <sammc@chromium.org>
|
||||
Cr-Original-Commit-Position: refs/heads/master@{#907467}
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3083204
|
||||
Bot-Commit: Rubber Stamper <rubber-stamper@appspot.gserviceaccount.com>
|
||||
Cr-Commit-Position: refs/branch-heads/4577@{#648}
|
||||
Cr-Branched-From: 761ddde228655e313424edec06497d0c56b0f3c4-refs/heads/master@{#902210}
|
||||
|
||||
diff --git a/extensions/browser/api/file_system/file_system_api.cc b/extensions/browser/api/file_system/file_system_api.cc
|
||||
index e9023c877b7b35c0067642f05bc540858cbd7706..110f768c12d94fcfae0ac509fd0ce61c0e6049b8 100644
|
||||
--- a/extensions/browser/api/file_system/file_system_api.cc
|
||||
+++ b/extensions/browser/api/file_system/file_system_api.cc
|
||||
@@ -197,6 +197,9 @@ void PassFileInfoToUIThread(FileInfoOptCallback callback,
|
||||
content::WebContents* GetWebContentsForRenderFrameHost(
|
||||
content::BrowserContext* browser_context,
|
||||
content::RenderFrameHost* render_frame_host) {
|
||||
+ if (!render_frame_host)
|
||||
+ return nullptr;
|
||||
+
|
||||
content::WebContents* web_contents =
|
||||
content::WebContents::FromRenderFrameHost(render_frame_host);
|
||||
// Check if there is an app window associated with the web contents; if not,
|
||||
@@ -508,15 +511,6 @@ void FileSystemChooseEntryFunction::FilesSelected(
|
||||
}
|
||||
|
||||
if (is_directory_) {
|
||||
- // Get the WebContents for the app window to be the parent window of the
|
||||
- // confirmation dialog if necessary.
|
||||
- content::WebContents* const web_contents = GetWebContentsForRenderFrameHost(
|
||||
- browser_context(), render_frame_host());
|
||||
- if (!web_contents) {
|
||||
- Respond(Error(kInvalidCallingPage));
|
||||
- return;
|
||||
- }
|
||||
-
|
||||
DCHECK_EQ(paths.size(), 1u);
|
||||
bool non_native_path = false;
|
||||
#if BUILDFLAG(IS_CHROMEOS_ASH)
|
||||
@@ -530,7 +524,7 @@ void FileSystemChooseEntryFunction::FilesSelected(
|
||||
FROM_HERE, {base::MayBlock(), base::TaskPriority::BEST_EFFORT},
|
||||
base::BindOnce(
|
||||
&FileSystemChooseEntryFunction::ConfirmDirectoryAccessAsync, this,
|
||||
- non_native_path, paths, web_contents));
|
||||
+ non_native_path, paths));
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -543,8 +537,7 @@ void FileSystemChooseEntryFunction::FileSelectionCanceled() {
|
||||
|
||||
void FileSystemChooseEntryFunction::ConfirmDirectoryAccessAsync(
|
||||
bool non_native_path,
|
||||
- const std::vector<base::FilePath>& paths,
|
||||
- content::WebContents* web_contents) {
|
||||
+ const std::vector<base::FilePath>& paths) {
|
||||
const base::FilePath check_path =
|
||||
non_native_path ? paths[0] : base::MakeAbsoluteFilePath(paths[0]);
|
||||
if (check_path.empty()) {
|
||||
@@ -576,7 +569,7 @@ void FileSystemChooseEntryFunction::ConfirmDirectoryAccessAsync(
|
||||
FROM_HERE,
|
||||
base::BindOnce(
|
||||
&FileSystemChooseEntryFunction::ConfirmSensitiveDirectoryAccess,
|
||||
- this, paths, web_contents));
|
||||
+ this, paths));
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -587,8 +580,7 @@ void FileSystemChooseEntryFunction::ConfirmDirectoryAccessAsync(
|
||||
}
|
||||
|
||||
void FileSystemChooseEntryFunction::ConfirmSensitiveDirectoryAccess(
|
||||
- const std::vector<base::FilePath>& paths,
|
||||
- content::WebContents* web_contents) {
|
||||
+ const std::vector<base::FilePath>& paths) {
|
||||
if (ExtensionsBrowserClient::Get()->IsShuttingDown()) {
|
||||
FileSelectionCanceled();
|
||||
return;
|
||||
@@ -601,6 +593,13 @@ void FileSystemChooseEntryFunction::ConfirmSensitiveDirectoryAccess(
|
||||
return;
|
||||
}
|
||||
|
||||
+ content::WebContents* const web_contents =
|
||||
+ GetWebContentsForRenderFrameHost(browser_context(), render_frame_host());
|
||||
+ if (!web_contents) {
|
||||
+ Respond(Error(kInvalidCallingPage));
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
delegate->ConfirmSensitiveDirectoryAccess(
|
||||
app_file_handler_util::HasFileSystemWritePermission(extension_.get()),
|
||||
base::UTF8ToUTF16(extension_->name()), web_contents,
|
||||
diff --git a/extensions/browser/api/file_system/file_system_api.h b/extensions/browser/api/file_system/file_system_api.h
|
||||
index ae1588ce8536e4cee5474c3d4db370e95018c52e..0895a174a0dd1ba031fa358fe6451a1ebf198594 100644
|
||||
--- a/extensions/browser/api/file_system/file_system_api.h
|
||||
+++ b/extensions/browser/api/file_system/file_system_api.h
|
||||
@@ -19,10 +19,6 @@
|
||||
#include "extensions/common/api/file_system.h"
|
||||
#include "ui/shell_dialogs/select_file_dialog.h"
|
||||
|
||||
-namespace content {
|
||||
-class WebContents;
|
||||
-} // namespace content
|
||||
-
|
||||
namespace extensions {
|
||||
class ExtensionPrefs;
|
||||
|
||||
@@ -168,13 +164,12 @@ class FileSystemChooseEntryFunction : public FileSystemEntryFunction {
|
||||
// directory. If so, calls ConfirmSensitiveDirectoryAccess. Otherwise, calls
|
||||
// OnDirectoryAccessConfirmed.
|
||||
void ConfirmDirectoryAccessAsync(bool non_native_path,
|
||||
- const std::vector<base::FilePath>& paths,
|
||||
- content::WebContents* web_contents);
|
||||
+ const std::vector<base::FilePath>& paths);
|
||||
|
||||
// Shows a dialog to confirm whether the user wants to open the directory.
|
||||
// Calls OnDirectoryAccessConfirmed or FileSelectionCanceled.
|
||||
- void ConfirmSensitiveDirectoryAccess(const std::vector<base::FilePath>& paths,
|
||||
- content::WebContents* web_contents);
|
||||
+ void ConfirmSensitiveDirectoryAccess(
|
||||
+ const std::vector<base::FilePath>& paths);
|
||||
|
||||
void OnDirectoryAccessConfirmed(const std::vector<base::FilePath>& paths);
|
||||
|
||||
36
patches/chromium/cherry-pick-3a5bafa35def.patch
Normal file
36
patches/chromium/cherry-pick-3a5bafa35def.patch
Normal file
@@ -0,0 +1,36 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Alex Gough <ajgo@chromium.org>
|
||||
Date: Fri, 1 Oct 2021 23:30:09 +0000
|
||||
Subject: Tell clang not to devirtualize TargetServices
|
||||
|
||||
Before this change in official builds a child process's delayed
|
||||
integrity level was not being set correctly. With this change
|
||||
renderers run at Untrusted IL as intended.
|
||||
|
||||
(cherry picked from commit 19d2be5d47e0edc406ef7d93096f54009e47937f)
|
||||
|
||||
Tests: https://bugs.chromium.org/p/chromium/issues/detail?id=1254631#c13
|
||||
Bug: 1254631
|
||||
Change-Id: I52c149cca3de5218033ed0f37d9f76782b9a6302
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3198382
|
||||
Reviewed-by: Will Harris <wfh@chromium.org>
|
||||
Commit-Queue: Will Harris <wfh@chromium.org>
|
||||
Cr-Original-Commit-Position: refs/heads/main@{#926934}
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3200146
|
||||
Commit-Queue: Alex Gough <ajgo@chromium.org>
|
||||
Cr-Commit-Position: refs/branch-heads/4606@{#1285}
|
||||
Cr-Branched-From: 35b0d5a9dc8362adfd44e2614f0d5b7402ef63d0-refs/heads/master@{#911515}
|
||||
|
||||
diff --git a/sandbox/win/src/sandbox.h b/sandbox/win/src/sandbox.h
|
||||
index 9dfebfcc1721a2c2c34397666976e67b78812d7b..d4ab27f084aeb1b9db54eacf227250cf2364c4e2 100644
|
||||
--- a/sandbox/win/src/sandbox.h
|
||||
+++ b/sandbox/win/src/sandbox.h
|
||||
@@ -140,7 +140,7 @@ class BrokerServices {
|
||||
// }
|
||||
//
|
||||
// For more information see the BrokerServices API documentation.
|
||||
-class TargetServices {
|
||||
+class [[clang::lto_visibility_public]] TargetServices {
|
||||
public:
|
||||
// Initializes the target. Must call this function before any other.
|
||||
// returns ALL_OK if successful. All other return values imply failure.
|
||||
135
patches/chromium/cherry-pick-4ce2abc17078.patch
Normal file
135
patches/chromium/cherry-pick-4ce2abc17078.patch
Normal file
@@ -0,0 +1,135 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Robert Flack <flackr@chromium.org>
|
||||
Date: Fri, 30 Jul 2021 18:51:38 +0000
|
||||
Subject: Forbid script execution for entire lifecycle update
|
||||
|
||||
We should not execute script during the lifecycle update except in cases where we we know it is safe to do so, either because we will rerun the lifecycle steps if anything is invalidated (resize observers, intersection observers) or because the script does not have access to invalidate the DOM (e.g. paint worklets).
|
||||
|
||||
(cherry picked from commit a73237da91de8aa49aaa5d9479bae51cf387f090)
|
||||
|
||||
Bug: 1196853
|
||||
Change-Id: Id1fdbbb25107cfdc6c234123f845406c28d32914
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2815619
|
||||
Reviewed-by: Stefan Zager <szager@chromium.org>
|
||||
Commit-Queue: Robert Flack <flackr@chromium.org>
|
||||
Cr-Original-Commit-Position: refs/heads/master@{#901110}
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3058973
|
||||
Auto-Submit: Robert Flack <flackr@chromium.org>
|
||||
Commit-Queue: Stefan Zager <szager@chromium.org>
|
||||
Cr-Commit-Position: refs/branch-heads/4472@{#1588}
|
||||
Cr-Branched-From: 3d60439cfb36485e76a1c5bb7f513d3721b20da1-refs/heads/master@{#870763}
|
||||
|
||||
diff --git a/third_party/blink/renderer/core/exported/web_plugin_container_impl.cc b/third_party/blink/renderer/core/exported/web_plugin_container_impl.cc
|
||||
index 1901d2128035abdcdefcf9747db0c18580ec2073..55dccfbe7d9046a479afc9c0b141accd0b998c87 100644
|
||||
--- a/third_party/blink/renderer/core/exported/web_plugin_container_impl.cc
|
||||
+++ b/third_party/blink/renderer/core/exported/web_plugin_container_impl.cc
|
||||
@@ -95,6 +95,7 @@
|
||||
#include "third_party/blink/renderer/core/script/classic_script.h"
|
||||
#include "third_party/blink/renderer/core/scroll/scroll_animator_base.h"
|
||||
#include "third_party/blink/renderer/core/scroll/scrollbar_theme.h"
|
||||
+#include "third_party/blink/renderer/platform/bindings/script_forbidden_scope.h"
|
||||
#include "third_party/blink/renderer/platform/exported/wrapped_resource_response.h"
|
||||
#include "third_party/blink/renderer/platform/geometry/layout_rect.h"
|
||||
#include "third_party/blink/renderer/platform/graphics/graphics_context.h"
|
||||
@@ -803,6 +804,8 @@ void WebPluginContainerImpl::Dispose() {
|
||||
}
|
||||
|
||||
if (web_plugin_) {
|
||||
+ // Plugins may execute script on being detached during the lifecycle update.
|
||||
+ ScriptForbiddenScope::AllowUserAgentScript allow_script;
|
||||
CHECK(web_plugin_->Container() == this);
|
||||
web_plugin_->Destroy();
|
||||
web_plugin_ = nullptr;
|
||||
diff --git a/third_party/blink/renderer/core/frame/local_frame_view.cc b/third_party/blink/renderer/core/frame/local_frame_view.cc
|
||||
index 30c2b00056873410c46177ccfe5fba1f7155dbb2..3538b4841a9f752fa0c5e8966cd10ab78d369f5c 100644
|
||||
--- a/third_party/blink/renderer/core/frame/local_frame_view.cc
|
||||
+++ b/third_party/blink/renderer/core/frame/local_frame_view.cc
|
||||
@@ -2539,6 +2539,7 @@ bool LocalFrameView::UpdateLifecyclePhases(
|
||||
|
||||
void LocalFrameView::UpdateLifecyclePhasesInternal(
|
||||
DocumentLifecycle::LifecycleState target_state) {
|
||||
+ ScriptForbiddenScope forbid_script;
|
||||
// RunScrollTimelineSteps must not run more than once.
|
||||
bool should_run_scroll_timeline_steps = true;
|
||||
|
||||
@@ -2636,6 +2637,10 @@ void LocalFrameView::UpdateLifecyclePhasesInternal(
|
||||
continue;
|
||||
}
|
||||
|
||||
+ // At this point in time, script is allowed to run as we will repeat the
|
||||
+ // lifecycle update if anything is invalidated.
|
||||
+ ScriptForbiddenScope::AllowUserAgentScript allow_script;
|
||||
+
|
||||
// ResizeObserver and post-layout IntersectionObserver observation
|
||||
// deliveries may dirty style and layout. RunResizeObserverSteps will return
|
||||
// true if any observer ran that may have dirtied style or layout;
|
||||
@@ -2894,6 +2899,7 @@ bool LocalFrameView::AnyFrameIsPrintingOrPaintingPreview() {
|
||||
}
|
||||
|
||||
void LocalFrameView::RunPaintLifecyclePhase(PaintBenchmarkMode benchmark_mode) {
|
||||
+ DCHECK(ScriptForbiddenScope::IsScriptForbidden());
|
||||
TRACE_EVENT0("blink,benchmark", "LocalFrameView::RunPaintLifecyclePhase");
|
||||
// While printing or capturing a paint preview of a document, the paint walk
|
||||
// is done into a special canvas. There is no point doing a normal paint step
|
||||
@@ -2925,17 +2931,11 @@ void LocalFrameView::RunPaintLifecyclePhase(PaintBenchmarkMode benchmark_mode) {
|
||||
for (PaintLayerScrollableArea* area : *animating_scrollable_areas)
|
||||
area->UpdateCompositorScrollAnimations();
|
||||
}
|
||||
- {
|
||||
- // Updating animations can notify ready promises which could mutate
|
||||
- // the DOM. We should delay these until we have finished the lifecycle
|
||||
- // update. https://crbug.com/1196781
|
||||
- ScriptForbiddenScope forbid_script;
|
||||
- frame_view.GetLayoutView()
|
||||
- ->GetDocument()
|
||||
- .GetDocumentAnimations()
|
||||
- .UpdateAnimations(DocumentLifecycle::kPaintClean,
|
||||
- paint_artifact_compositor_.get());
|
||||
- }
|
||||
+ frame_view.GetLayoutView()
|
||||
+ ->GetDocument()
|
||||
+ .GetDocumentAnimations()
|
||||
+ .UpdateAnimations(DocumentLifecycle::kPaintClean,
|
||||
+ paint_artifact_compositor_.get());
|
||||
Document& document = frame_view.GetLayoutView()->GetDocument();
|
||||
total_animations_count +=
|
||||
document.GetDocumentAnimations().GetAnimationsCount();
|
||||
@@ -4512,6 +4512,7 @@ void LocalFrameView::RenderThrottlingStatusChanged() {
|
||||
// so painting the tree should just clear the previous painted output.
|
||||
DCHECK(!IsUpdatingLifecycle());
|
||||
AllowThrottlingScope allow_throtting(*this);
|
||||
+ ScriptForbiddenScope forbid_script;
|
||||
RunPaintLifecyclePhase();
|
||||
}
|
||||
|
||||
@@ -5018,6 +5019,7 @@ void LocalFrameView::RunPaintBenchmark(int repeat_count,
|
||||
// quantization when the time is very small.
|
||||
base::LapTimer timer(kWarmupRuns, kTimeLimit, kTimeCheckInterval);
|
||||
do {
|
||||
+ ScriptForbiddenScope forbid_script;
|
||||
RunPaintLifecyclePhase(mode);
|
||||
timer.NextLap();
|
||||
} while (!timer.HasTimeLimitExpired());
|
||||
diff --git a/third_party/blink/renderer/modules/csspaint/paint_worklet.cc b/third_party/blink/renderer/modules/csspaint/paint_worklet.cc
|
||||
index e6e0c5b909c4d073963bcbb074bfb091a6ccb83b..618e08fbb5157c06348feee5f0120bd28ed0bc44 100644
|
||||
--- a/third_party/blink/renderer/modules/csspaint/paint_worklet.cc
|
||||
+++ b/third_party/blink/renderer/modules/csspaint/paint_worklet.cc
|
||||
@@ -17,6 +17,7 @@
|
||||
#include "third_party/blink/renderer/modules/csspaint/paint_worklet_global_scope.h"
|
||||
#include "third_party/blink/renderer/modules/csspaint/paint_worklet_id_generator.h"
|
||||
#include "third_party/blink/renderer/modules/csspaint/paint_worklet_messaging_proxy.h"
|
||||
+#include "third_party/blink/renderer/platform/bindings/script_forbidden_scope.h"
|
||||
#include "third_party/blink/renderer/platform/graphics/paint_generated_image.h"
|
||||
|
||||
namespace blink {
|
||||
@@ -126,6 +127,10 @@ scoped_refptr<Image> PaintWorklet::Paint(const String& name,
|
||||
layout_object.GetDocument(), layout_object.StyleRef(),
|
||||
paint_definition->NativeInvalidationProperties(),
|
||||
paint_definition->CustomInvalidationProperties());
|
||||
+ // The PaintWorkletGlobalScope is sufficiently isolated that it is safe to
|
||||
+ // run during the lifecycle update without concern for it causing
|
||||
+ // invalidations to the lifecycle.
|
||||
+ ScriptForbiddenScope::AllowUserAgentScript allow_script;
|
||||
sk_sp<PaintRecord> paint_record = paint_definition->Paint(
|
||||
container_size, zoom, style_map, data, device_scale_factor);
|
||||
if (!paint_record)
|
||||
62
patches/chromium/cherry-pick-4e528a5a8d83.patch
Normal file
62
patches/chromium/cherry-pick-4e528a5a8d83.patch
Normal file
@@ -0,0 +1,62 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Austin Sullivan <asully@chromium.org>
|
||||
Date: Wed, 15 Sep 2021 23:57:27 +0000
|
||||
Subject: FSA: Fix race condition in manager
|
||||
|
||||
(cherry picked from commit 951339b41022b08a67ad94ba5960b05c84bf4cf2)
|
||||
|
||||
Bug: 1248030
|
||||
Change-Id: I1ea819d1d6ac63ec8f400a45c893da49596235ef
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3154425
|
||||
Commit-Queue: Marijn Kruisselbrink <mek@chromium.org>
|
||||
Auto-Submit: Austin Sullivan <asully@chromium.org>
|
||||
Reviewed-by: Marijn Kruisselbrink <mek@chromium.org>
|
||||
Cr-Original-Commit-Position: refs/heads/main@{#920376}
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3160301
|
||||
Commit-Queue: Austin Sullivan <asully@chromium.org>
|
||||
Cr-Commit-Position: refs/branch-heads/4606@{#1077}
|
||||
Cr-Branched-From: 35b0d5a9dc8362adfd44e2614f0d5b7402ef63d0-refs/heads/master@{#911515}
|
||||
|
||||
diff --git a/content/browser/file_system_access/file_system_access_manager_impl.cc b/content/browser/file_system_access/file_system_access_manager_impl.cc
|
||||
index e58be73ae495dbc3c04802caf8fd163bcafaf992..a47eceba374b2c589fe8a0d007e4e1c803baab32 100644
|
||||
--- a/content/browser/file_system_access/file_system_access_manager_impl.cc
|
||||
+++ b/content/browser/file_system_access/file_system_access_manager_impl.cc
|
||||
@@ -448,6 +448,11 @@ void FileSystemAccessManagerImpl::ResolveDefaultDirectory(
|
||||
std::move(callback))));
|
||||
}
|
||||
|
||||
+void FileSystemAccessManagerImpl::Shutdown() {
|
||||
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
|
||||
+ permission_context_ = nullptr;
|
||||
+}
|
||||
+
|
||||
void FileSystemAccessManagerImpl::SetDefaultPathAndShowPicker(
|
||||
const BindingContext& context,
|
||||
blink::mojom::FilePickerOptionsPtr options,
|
||||
diff --git a/content/browser/file_system_access/file_system_access_manager_impl.h b/content/browser/file_system_access/file_system_access_manager_impl.h
|
||||
index 4c9303aa11349f8de5181ca1dcd92f20f2b74a99..e06a3d347f2af5f62ade1fc70e8ad49ca878628f 100644
|
||||
--- a/content/browser/file_system_access/file_system_access_manager_impl.h
|
||||
+++ b/content/browser/file_system_access/file_system_access_manager_impl.h
|
||||
@@ -257,6 +257,8 @@ class CONTENT_EXPORT FileSystemAccessManagerImpl
|
||||
PathType path_type,
|
||||
const base::FilePath& path);
|
||||
|
||||
+ void Shutdown();
|
||||
+
|
||||
private:
|
||||
friend class FileSystemAccessFileHandleImpl;
|
||||
|
||||
diff --git a/content/browser/storage_partition_impl.cc b/content/browser/storage_partition_impl.cc
|
||||
index 7ffcbd0ac22164d5e268f28e0e434a08e3eb120b..f851627cf33ac4bc2aa56eb3d7b21170eb5c0d16 100644
|
||||
--- a/content/browser/storage_partition_impl.cc
|
||||
+++ b/content/browser/storage_partition_impl.cc
|
||||
@@ -1078,6 +1078,9 @@ StoragePartitionImpl::~StoragePartitionImpl() {
|
||||
GetDatabaseTracker()));
|
||||
}
|
||||
|
||||
+ if (GetFileSystemAccessManager())
|
||||
+ GetFileSystemAccessManager()->Shutdown();
|
||||
+
|
||||
if (GetFileSystemContext())
|
||||
GetFileSystemContext()->Shutdown();
|
||||
|
||||
60
patches/chromium/cherry-pick-5487040a284a.patch
Normal file
60
patches/chromium/cherry-pick-5487040a284a.patch
Normal file
@@ -0,0 +1,60 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Dale Curtis <dalecurtis@chromium.org>
|
||||
Date: Mon, 12 Jul 2021 19:29:39 +0000
|
||||
Subject: Don't TexImage via GPU when OOP raster is disabled on Windows.
|
||||
|
||||
For some reason it's much slower than the the non-GPU based path. The
|
||||
test page https://koush.github.io/webcodecs/ goes from ~270fps decoding
|
||||
and ~5fps rendering to ~300fps decoding and >> 60fps rendering when
|
||||
running with --disable-oop-rasterization.
|
||||
|
||||
R=kbr
|
||||
|
||||
Bug: 1227921
|
||||
Change-Id: I1abbcfd5c4a515540753c8c5e681949f6f236c9c
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3018801
|
||||
Commit-Queue: Dale Curtis <dalecurtis@chromium.org>
|
||||
Reviewed-by: Kenneth Russell <kbr@chromium.org>
|
||||
Cr-Commit-Position: refs/heads/master@{#900587}
|
||||
|
||||
diff --git a/third_party/blink/renderer/modules/webgl/webgl_rendering_context_base.cc b/third_party/blink/renderer/modules/webgl/webgl_rendering_context_base.cc
|
||||
index 31a22fa48c001a07d1b848c107d22c7d1342c2a6..f70dd9b9d0eb405736e8830feb9cb32bbdb5af4a 100644
|
||||
--- a/third_party/blink/renderer/modules/webgl/webgl_rendering_context_base.cc
|
||||
+++ b/third_party/blink/renderer/modules/webgl/webgl_rendering_context_base.cc
|
||||
@@ -5955,6 +5955,14 @@ void WebGLRenderingContextBase::TexImageHelperMediaVideoFrame(
|
||||
CanUseTexImageViaGPU(format, type) &&
|
||||
transform == media::kNoTransformation;
|
||||
|
||||
+#if defined(OS_WIN)
|
||||
+ // TODO(crbug.com/1227921): When OOP GPU rasterization is disabled, uploading
|
||||
+ // via the GPU becomes extremely slow.
|
||||
+ const bool gpu_teximage_is_slow = !caps.supports_oop_raster;
|
||||
+#else
|
||||
+ const bool gpu_teximage_is_slow = false;
|
||||
+#endif
|
||||
+
|
||||
// Callers may chose to provide a renderer which ensures that generated
|
||||
// intermediates will be cached across TexImage calls for the same frame.
|
||||
std::unique_ptr<media::PaintCanvasVideoRenderer> local_video_renderer;
|
||||
@@ -6000,7 +6008,7 @@ void WebGLRenderingContextBase::TexImageHelperMediaVideoFrame(
|
||||
// TODO(crbug.com/1180879): I420A should be supported, but currently fails
|
||||
// conformance/textures/misc/texture-video-transparent.html.
|
||||
if (!media_video_frame->HasTextures() &&
|
||||
- media::IsOpaque(media_video_frame->format()) &&
|
||||
+ media::IsOpaque(media_video_frame->format()) && !gpu_teximage_is_slow &&
|
||||
video_renderer->CopyVideoFrameYUVDataToGLTexture(
|
||||
raster_context_provider, ContextGL(), media_video_frame, target,
|
||||
texture->Object(), adjusted_internalformat, format, type, level,
|
||||
@@ -6068,9 +6076,9 @@ void WebGLRenderingContextBase::TexImageHelperMediaVideoFrame(
|
||||
function_id == kTexImage2D || function_id == kTexSubImage2D;
|
||||
#endif
|
||||
|
||||
- const bool can_upload_via_gpu = function_supports_gpu_teximage &&
|
||||
- CanUseTexImageViaGPU(format, type) &&
|
||||
- source_image_rect_is_default;
|
||||
+ const bool can_upload_via_gpu =
|
||||
+ function_supports_gpu_teximage && CanUseTexImageViaGPU(format, type) &&
|
||||
+ source_image_rect_is_default && !gpu_teximage_is_slow;
|
||||
|
||||
// If we can upload via GPU, try to to use an accelerated resource provider
|
||||
// configured appropriately for video. Otherwise use the software cache.
|
||||
65
patches/chromium/cherry-pick-6048fcd52f42.patch
Normal file
65
patches/chromium/cherry-pick-6048fcd52f42.patch
Normal file
@@ -0,0 +1,65 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Koji Ishii <kojii@chromium.org>
|
||||
Date: Thu, 9 Sep 2021 23:25:48 +0000
|
||||
Subject: Merge 4577: Apply list item quirks only when the nested list is
|
||||
block-level
|
||||
|
||||
This patch changes to apply quirks for a list-item occupying
|
||||
the whole line only if the nested list is block-level.
|
||||
|
||||
When applying this quirks, list markers are handled like a
|
||||
regular child. r883403 crrev.com/c/2885398 changed to handle
|
||||
list markers at |NGBlockLayoutAlgorithm| to support NG block
|
||||
fragmentation. These two when combined causes the list marker
|
||||
not laid out if the nested list is not block-level.
|
||||
|
||||
This may change some visual behaviors, but I think this is ok:
|
||||
a) This quirks is not in the quirks spec[1] and not
|
||||
implemented in Gecko.
|
||||
b) The previous CL had a visual difference in this case in M92
|
||||
but no reports so far.
|
||||
|
||||
[1]: https://quirks.spec.whatwg.org/
|
||||
|
||||
(cherry picked from commit 6f5d97da873f0e193a732fb7281d3484258aef6d)
|
||||
|
||||
Bug: 1246932, 1206409
|
||||
Change-Id: Ia58a1b788313d3d9f221fd010cdd1a906551ab8b
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3145018
|
||||
Reviewed-by: Yoshifumi Inoue <yosin@chromium.org>
|
||||
Commit-Queue: Koji Ishii <kojii@chromium.org>
|
||||
Cr-Original-Commit-Position: refs/heads/main@{#919158}
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3151681
|
||||
Auto-Submit: Koji Ishii <kojii@chromium.org>
|
||||
Reviewed-by: Ian Kilpatrick <ikilpatrick@chromium.org>
|
||||
Cr-Commit-Position: refs/branch-heads/4577@{#1225}
|
||||
Cr-Branched-From: 761ddde228655e313424edec06497d0c56b0f3c4-refs/heads/master@{#902210}
|
||||
|
||||
diff --git a/third_party/blink/renderer/core/layout/ng/list/layout_ng_outside_list_marker.cc b/third_party/blink/renderer/core/layout/ng/list/layout_ng_outside_list_marker.cc
|
||||
index 15a3c0a3018301e40d336c8893e987b491da66d3..9b7c0e075cb5a89108c22824c5522de26eb904da 100644
|
||||
--- a/third_party/blink/renderer/core/layout/ng/list/layout_ng_outside_list_marker.cc
|
||||
+++ b/third_party/blink/renderer/core/layout/ng/list/layout_ng_outside_list_marker.cc
|
||||
@@ -26,8 +26,11 @@ bool LayoutNGOutsideListMarker::NeedsOccupyWholeLine() const {
|
||||
if (!GetDocument().InQuirksMode())
|
||||
return false;
|
||||
|
||||
+ // Apply the quirks when the next sibling is a block-level `<ul>` or `<ol>`.
|
||||
LayoutObject* next_sibling = NextSibling();
|
||||
- if (next_sibling && next_sibling->GetNode() &&
|
||||
+ if (next_sibling && !next_sibling->IsInline() &&
|
||||
+ !next_sibling->IsFloatingOrOutOfFlowPositioned() &&
|
||||
+ next_sibling->GetNode() &&
|
||||
(IsA<HTMLUListElement>(*next_sibling->GetNode()) ||
|
||||
IsA<HTMLOListElement>(*next_sibling->GetNode())))
|
||||
return true;
|
||||
diff --git a/third_party/blink/web_tests/external/wpt/quirks/crashtests/list-item-whole-line-quirks-crash.html b/third_party/blink/web_tests/external/wpt/quirks/crashtests/list-item-whole-line-quirks-crash.html
|
||||
new file mode 100644
|
||||
index 0000000000000000000000000000000000000000..b91b09db0e37727e2d3a3e13ca2c7cae25b8d761
|
||||
--- /dev/null
|
||||
+++ b/third_party/blink/web_tests/external/wpt/quirks/crashtests/list-item-whole-line-quirks-crash.html
|
||||
@@ -0,0 +1,5 @@
|
||||
+<!-- quirks -->
|
||||
+<div>a<ul><li><ul style='float: left'></ul></li></ul></div>
|
||||
+<div>a<ul><li><ul style='position: absolute'></ul></li></ul></div>
|
||||
+<div>a<ul><li><ul style='display: inline'></ul></li></ul></div>
|
||||
+<div>a<ul><li><ul style='display: inline-block'></ul></li></ul></div>
|
||||
121
patches/chromium/cherry-pick-6215793f008f.patch
Normal file
121
patches/chromium/cherry-pick-6215793f008f.patch
Normal file
@@ -0,0 +1,121 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Scott Violet <sky@chromium.org>
|
||||
Date: Wed, 8 Sep 2021 18:45:42 +0000
|
||||
Subject: compositor: fix bug in sending damage regions
|
||||
|
||||
Specifically if a layer is added when sending damaged regions the
|
||||
iterator would be invalidated. This converts to iterating over the
|
||||
size.
|
||||
|
||||
BUG=1242257
|
||||
TEST=CompositorTestWithMessageLoop.AddLayerDuringUpdateVisualState
|
||||
|
||||
(cherry picked from commit 7c0b0577c3ac1060945b7d05ad69f0dec33479b4)
|
||||
|
||||
Change-Id: I09f2bd34afce5d3c9402ef470f14923bbc76b8ae
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3140178
|
||||
Reviewed-by: Ian Vollick <vollick@chromium.org>
|
||||
Commit-Queue: Scott Violet <sky@chromium.org>
|
||||
Cr-Original-Commit-Position: refs/heads/main@{#917886}
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3149110
|
||||
Commit-Queue: enne <enne@chromium.org>
|
||||
Auto-Submit: Scott Violet <sky@chromium.org>
|
||||
Reviewed-by: enne <enne@chromium.org>
|
||||
Cr-Commit-Position: refs/branch-heads/4577@{#1206}
|
||||
Cr-Branched-From: 761ddde228655e313424edec06497d0c56b0f3c4-refs/heads/master@{#902210}
|
||||
|
||||
diff --git a/ui/compositor/compositor.cc b/ui/compositor/compositor.cc
|
||||
index 34f84bbdc2c21e3f8b8085edaf3fcad86c584672..350efae9200e1646449902e201c985b09ad47e0d 100644
|
||||
--- a/ui/compositor/compositor.cc
|
||||
+++ b/ui/compositor/compositor.cc
|
||||
@@ -653,8 +653,10 @@ void Compositor::BeginMainFrameNotExpectedUntil(base::TimeTicks time) {}
|
||||
|
||||
static void SendDamagedRectsRecursive(ui::Layer* layer) {
|
||||
layer->SendDamagedRects();
|
||||
- for (auto* child : layer->children())
|
||||
- SendDamagedRectsRecursive(child);
|
||||
+ // Iterate using the size for the case of mutation during sending damaged
|
||||
+ // regions. https://crbug.com/1242257.
|
||||
+ for (size_t i = 0; i < layer->children().size(); ++i)
|
||||
+ SendDamagedRectsRecursive(layer->children()[i]);
|
||||
}
|
||||
|
||||
void Compositor::UpdateLayerTreeHost() {
|
||||
diff --git a/ui/compositor/compositor_unittest.cc b/ui/compositor/compositor_unittest.cc
|
||||
index 7eaa8bbe4ab34e455c2afc67511c867a1d6d7e39..389b8630b4db323458aae65b61ef0b7d91a9797c 100644
|
||||
--- a/ui/compositor/compositor_unittest.cc
|
||||
+++ b/ui/compositor/compositor_unittest.cc
|
||||
@@ -12,12 +12,14 @@
|
||||
#include "base/test/test_mock_time_task_runner.h"
|
||||
#include "base/threading/thread_task_runner_handle.h"
|
||||
#include "base/time/time.h"
|
||||
+#include "build/build_config.h"
|
||||
#include "cc/metrics/frame_sequence_tracker.h"
|
||||
#include "components/viz/common/surfaces/parent_local_surface_id_allocator.h"
|
||||
#include "testing/gmock/include/gmock/gmock.h"
|
||||
#include "testing/gtest/include/gtest/gtest.h"
|
||||
#include "ui/compositor/compositor.h"
|
||||
#include "ui/compositor/layer.h"
|
||||
+#include "ui/compositor/layer_delegate.h"
|
||||
#include "ui/compositor/test/draw_waiter_for_test.h"
|
||||
#include "ui/compositor/test/in_process_context_factory.h"
|
||||
#include "ui/compositor/test/test_context_factories.h"
|
||||
@@ -356,4 +358,58 @@ TEST_F(CompositorTestWithMessageLoop, MAYBE_CreateAndReleaseOutputSurface) {
|
||||
compositor()->SetRootLayer(nullptr);
|
||||
}
|
||||
|
||||
+class LayerDelegateThatAddsDuringUpdateVisualState : public LayerDelegate {
|
||||
+ public:
|
||||
+ explicit LayerDelegateThatAddsDuringUpdateVisualState(Layer* parent)
|
||||
+ : parent_(parent) {}
|
||||
+
|
||||
+ bool update_visual_state_called() const {
|
||||
+ return update_visual_state_called_;
|
||||
+ }
|
||||
+
|
||||
+ // LayerDelegate:
|
||||
+ void UpdateVisualState() override {
|
||||
+ added_layers_.push_back(std::make_unique<Layer>(ui::LAYER_SOLID_COLOR));
|
||||
+ parent_->Add(added_layers_.back().get());
|
||||
+ update_visual_state_called_ = true;
|
||||
+ }
|
||||
+ void OnPaintLayer(const PaintContext& context) override {}
|
||||
+ void OnDeviceScaleFactorChanged(float old_device_scale_factor,
|
||||
+ float new_device_scale_factor) override {}
|
||||
+
|
||||
+ private:
|
||||
+ Layer* parent_;
|
||||
+ std::vector<std::unique_ptr<Layer>> added_layers_;
|
||||
+ bool update_visual_state_called_ = false;
|
||||
+};
|
||||
+
|
||||
+TEST_F(CompositorTestWithMessageLoop, AddLayerDuringUpdateVisualState) {
|
||||
+ std::unique_ptr<Layer> root_layer =
|
||||
+ std::make_unique<Layer>(ui::LAYER_SOLID_COLOR);
|
||||
+ std::unique_ptr<Layer> child_layer =
|
||||
+ std::make_unique<Layer>(ui::LAYER_TEXTURED);
|
||||
+ std::unique_ptr<Layer> child_layer2 =
|
||||
+ std::make_unique<Layer>(ui::LAYER_SOLID_COLOR);
|
||||
+ LayerDelegateThatAddsDuringUpdateVisualState child_layer_delegate(
|
||||
+ root_layer.get());
|
||||
+ child_layer->set_delegate(&child_layer_delegate);
|
||||
+ root_layer->Add(child_layer.get());
|
||||
+ root_layer->Add(child_layer2.get());
|
||||
+
|
||||
+ viz::ParentLocalSurfaceIdAllocator allocator;
|
||||
+ allocator.GenerateId();
|
||||
+ root_layer->SetBounds(gfx::Rect(10, 10));
|
||||
+ compositor()->SetRootLayer(root_layer.get());
|
||||
+ compositor()->SetScaleAndSize(1.0f, gfx::Size(10, 10),
|
||||
+ allocator.GetCurrentLocalSurfaceId());
|
||||
+ ASSERT_TRUE(compositor()->IsVisible());
|
||||
+ compositor()->ScheduleDraw();
|
||||
+ DrawWaiterForTest::WaitForCompositingEnded(compositor());
|
||||
+ EXPECT_TRUE(child_layer_delegate.update_visual_state_called());
|
||||
+ compositor()->SetRootLayer(nullptr);
|
||||
+ child_layer2.reset();
|
||||
+ child_layer.reset();
|
||||
+ root_layer.reset();
|
||||
+}
|
||||
+
|
||||
} // namespace ui
|
||||
230
patches/chromium/cherry-pick-6a8a2098f9fa.patch
Normal file
230
patches/chromium/cherry-pick-6a8a2098f9fa.patch
Normal file
@@ -0,0 +1,230 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Erik Chen <erikchen@chromium.org>
|
||||
Date: Wed, 29 Sep 2021 21:16:47 +0000
|
||||
Subject: Prevents non-browser processes from requesting memory dumps.
|
||||
|
||||
This CL makes several changes:
|
||||
|
||||
(1) Causes the browser to reset non-browser
|
||||
mojo::PendingReceiver<Coordinator>. This means that non-browser
|
||||
processes will never be able to use the Coordinator interface.
|
||||
|
||||
(2) Add CHECKs to existing code to prevent non-browser processes from
|
||||
attempting to use the Coordinator interface.
|
||||
|
||||
A code audit shows that all Coordinator usages should already only be
|
||||
from the browser process.
|
||||
|
||||
Note that (2) is important since attempting to use an unbound interface
|
||||
will trigger a nullptr dereference, which is undefined behavior.
|
||||
|
||||
(cherry picked from commit d9cc471e122e9a2391a68fa7cd72ea50587d8d97)
|
||||
|
||||
Bug: 1251787
|
||||
Change-Id: Ifbe9610cc0e373edaaa60fad46b447e8bdb3ec04
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3174305
|
||||
Reviewed-by: Kinuko Yasuda <kinuko@chromium.org>
|
||||
Reviewed-by: ssid <ssid@chromium.org>
|
||||
Auto-Submit: Erik Chen <erikchen@chromium.org>
|
||||
Commit-Queue: Erik Chen <erikchen@chromium.org>
|
||||
Cr-Original-Commit-Position: refs/heads/main@{#923693}
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3194811
|
||||
Reviewed-by: Avi Drissman <avi@chromium.org>
|
||||
Reviewed-by: Krishna Govind <govind@chromium.org>
|
||||
Commit-Queue: Krishna Govind <govind@chromium.org>
|
||||
Owners-Override: Krishna Govind <govind@chromium.org>
|
||||
Cr-Commit-Position: refs/branch-heads/4606@{#1253}
|
||||
Cr-Branched-From: 35b0d5a9dc8362adfd44e2614f0d5b7402ef63d0-refs/heads/master@{#911515}
|
||||
|
||||
diff --git a/content/browser/browser_child_process_host_impl.cc b/content/browser/browser_child_process_host_impl.cc
|
||||
index 562eb4c2e1341b9aeb77ce3cfaf6740fa4876a61..8d155fa573c5b67f282d43b6fc8bfc0b98cbfeb1 100644
|
||||
--- a/content/browser/browser_child_process_host_impl.cc
|
||||
+++ b/content/browser/browser_child_process_host_impl.cc
|
||||
@@ -704,6 +704,9 @@ void BrowserChildProcessHostImpl::RegisterCoordinatorClient(
|
||||
mojo::PendingReceiver<memory_instrumentation::mojom::Coordinator> receiver,
|
||||
mojo::PendingRemote<memory_instrumentation::mojom::ClientProcess>
|
||||
client_process) {
|
||||
+ // Intentionally disallow non-browser processes from getting a Coordinator.
|
||||
+ receiver.reset();
|
||||
+
|
||||
// The child process may have already terminated by the time this message is
|
||||
// dispatched. We do nothing in that case.
|
||||
if (!IsProcessLaunched())
|
||||
diff --git a/content/browser/renderer_host/render_process_host_impl.cc b/content/browser/renderer_host/render_process_host_impl.cc
|
||||
index c2341d7e2b4149c5a83676b237f4c21ba5e9798a..be4a24917f9c5f8cf6c7c68761b3a9873d9b35aa 100644
|
||||
--- a/content/browser/renderer_host/render_process_host_impl.cc
|
||||
+++ b/content/browser/renderer_host/render_process_host_impl.cc
|
||||
@@ -2632,6 +2632,9 @@ void RenderProcessHostImpl::RegisterCoordinatorClient(
|
||||
mojo::PendingReceiver<memory_instrumentation::mojom::Coordinator> receiver,
|
||||
mojo::PendingRemote<memory_instrumentation::mojom::ClientProcess>
|
||||
client_process) {
|
||||
+ // Intentionally disallow non-browser processes from getting a Coordinator.
|
||||
+ receiver.reset();
|
||||
+
|
||||
if (!GetProcess().IsValid()) {
|
||||
// If the process dies before we get this message. we have no valid PID
|
||||
// and there's nothing to register.
|
||||
diff --git a/services/resource_coordinator/memory_instrumentation/coordinator_impl.cc b/services/resource_coordinator/memory_instrumentation/coordinator_impl.cc
|
||||
index 77cd931b5fe94dc11440c1f67c17d653db11bbb1..c16affe3949505d6144d4c4db6ece453005d6fea 100644
|
||||
--- a/services/resource_coordinator/memory_instrumentation/coordinator_impl.cc
|
||||
+++ b/services/resource_coordinator/memory_instrumentation/coordinator_impl.cc
|
||||
@@ -105,7 +105,8 @@ void CoordinatorImpl::RegisterClientProcess(
|
||||
const base::Optional<std::string>& service_name) {
|
||||
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
|
||||
mojo::Remote<mojom::ClientProcess> process(std::move(client_process));
|
||||
- coordinator_receivers_.Add(this, std::move(receiver), process_id);
|
||||
+ if (receiver.is_valid())
|
||||
+ coordinator_receivers_.Add(this, std::move(receiver), process_id);
|
||||
process.set_disconnect_handler(
|
||||
base::BindOnce(&CoordinatorImpl::UnregisterClientProcess,
|
||||
base::Unretained(this), process_id));
|
||||
diff --git a/services/resource_coordinator/public/cpp/memory_instrumentation/client_process_impl.cc b/services/resource_coordinator/public/cpp/memory_instrumentation/client_process_impl.cc
|
||||
index ca0e8d8441a53fce370b375930b149a0b8dd6974..ae9ef93eafe0196c7a16743211f04eebe2c87d34 100644
|
||||
--- a/services/resource_coordinator/public/cpp/memory_instrumentation/client_process_impl.cc
|
||||
+++ b/services/resource_coordinator/public/cpp/memory_instrumentation/client_process_impl.cc
|
||||
@@ -24,6 +24,11 @@ void ClientProcessImpl::CreateInstance(
|
||||
mojo::PendingReceiver<mojom::ClientProcess> receiver,
|
||||
mojo::PendingRemote<mojom::Coordinator> coordinator,
|
||||
bool is_browser_process) {
|
||||
+ // Intentionally disallow non-browser processes from ever holding a
|
||||
+ // Coordinator.
|
||||
+ if (!is_browser_process)
|
||||
+ coordinator.reset();
|
||||
+
|
||||
static ClientProcessImpl* instance = nullptr;
|
||||
if (!instance) {
|
||||
instance = new ClientProcessImpl(
|
||||
@@ -39,10 +44,12 @@ ClientProcessImpl::ClientProcessImpl(
|
||||
mojo::PendingRemote<mojom::Coordinator> coordinator,
|
||||
bool is_browser_process,
|
||||
bool initialize_memory_instrumentation)
|
||||
- : receiver_(this, std::move(receiver)) {
|
||||
+ : receiver_(this, std::move(receiver)),
|
||||
+ is_browser_process_(is_browser_process) {
|
||||
if (initialize_memory_instrumentation) {
|
||||
// Initialize the public-facing MemoryInstrumentation helper.
|
||||
- MemoryInstrumentation::CreateInstance(std::move(coordinator));
|
||||
+ MemoryInstrumentation::CreateInstance(std::move(coordinator),
|
||||
+ is_browser_process);
|
||||
} else {
|
||||
coordinator_.Bind(std::move(coordinator));
|
||||
}
|
||||
@@ -109,6 +116,8 @@ void ClientProcessImpl::OnChromeMemoryDumpDone(
|
||||
void ClientProcessImpl::RequestGlobalMemoryDump_NoCallback(
|
||||
base::trace_event::MemoryDumpType dump_type,
|
||||
base::trace_event::MemoryDumpLevelOfDetail level_of_detail) {
|
||||
+ CHECK(is_browser_process_);
|
||||
+
|
||||
if (!task_runner_->RunsTasksInCurrentSequence()) {
|
||||
task_runner_->PostTask(
|
||||
FROM_HERE,
|
||||
diff --git a/services/resource_coordinator/public/cpp/memory_instrumentation/client_process_impl.h b/services/resource_coordinator/public/cpp/memory_instrumentation/client_process_impl.h
|
||||
index 6dd8c55823de34ccef4244036b4d4c8cda92f74a..8c2c20c449a2e3bf8c7465ccbc2fba6fd1cb402b 100644
|
||||
--- a/services/resource_coordinator/public/cpp/memory_instrumentation/client_process_impl.h
|
||||
+++ b/services/resource_coordinator/public/cpp/memory_instrumentation/client_process_impl.h
|
||||
@@ -96,6 +96,9 @@ class COMPONENT_EXPORT(RESOURCE_COORDINATOR_PUBLIC_MEMORY_INSTRUMENTATION)
|
||||
mojo::Remote<mojom::Coordinator> coordinator_;
|
||||
scoped_refptr<base::SingleThreadTaskRunner> task_runner_;
|
||||
|
||||
+ // Only browser process is allowed to request memory dumps.
|
||||
+ const bool is_browser_process_;
|
||||
+
|
||||
// TODO(crbug.com/728199): The observer is only used to setup and tear down
|
||||
// MemoryDumpManager in each process. Setting up MemoryDumpManager should
|
||||
// be moved away from TracingObserver.
|
||||
diff --git a/services/resource_coordinator/public/cpp/memory_instrumentation/memory_instrumentation.cc b/services/resource_coordinator/public/cpp/memory_instrumentation/memory_instrumentation.cc
|
||||
index c81d5f83bf9e1ad5e7a77d7c187fa33bd02812d5..ec90ab9211ede586d441f40e3e2bc2c820658fb1 100644
|
||||
--- a/services/resource_coordinator/public/cpp/memory_instrumentation/memory_instrumentation.cc
|
||||
+++ b/services/resource_coordinator/public/cpp/memory_instrumentation/memory_instrumentation.cc
|
||||
@@ -21,10 +21,11 @@ void WrapGlobalMemoryDump(
|
||||
|
||||
// static
|
||||
void MemoryInstrumentation::CreateInstance(
|
||||
- mojo::PendingRemote<memory_instrumentation::mojom::Coordinator>
|
||||
- coordinator) {
|
||||
+ mojo::PendingRemote<memory_instrumentation::mojom::Coordinator> coordinator,
|
||||
+ bool is_browser_process) {
|
||||
DCHECK(!g_instance);
|
||||
- g_instance = new MemoryInstrumentation(std::move(coordinator));
|
||||
+ g_instance =
|
||||
+ new MemoryInstrumentation(std::move(coordinator), is_browser_process);
|
||||
}
|
||||
|
||||
// static
|
||||
@@ -33,8 +34,10 @@ MemoryInstrumentation* MemoryInstrumentation::GetInstance() {
|
||||
}
|
||||
|
||||
MemoryInstrumentation::MemoryInstrumentation(
|
||||
- mojo::PendingRemote<memory_instrumentation::mojom::Coordinator> coordinator)
|
||||
- : coordinator_(std::move(coordinator)) {}
|
||||
+ mojo::PendingRemote<memory_instrumentation::mojom::Coordinator> coordinator,
|
||||
+ bool is_browser_process)
|
||||
+ : coordinator_(std::move(coordinator)),
|
||||
+ is_browser_process_(is_browser_process) {}
|
||||
|
||||
MemoryInstrumentation::~MemoryInstrumentation() {
|
||||
g_instance = nullptr;
|
||||
@@ -43,6 +46,7 @@ MemoryInstrumentation::~MemoryInstrumentation() {
|
||||
void MemoryInstrumentation::RequestGlobalDump(
|
||||
const std::vector<std::string>& allocator_dump_names,
|
||||
RequestGlobalDumpCallback callback) {
|
||||
+ CHECK(is_browser_process_);
|
||||
coordinator_->RequestGlobalMemoryDump(
|
||||
MemoryDumpType::SUMMARY_ONLY, MemoryDumpLevelOfDetail::BACKGROUND,
|
||||
MemoryDumpDeterminism::NONE, allocator_dump_names,
|
||||
@@ -52,6 +56,7 @@ void MemoryInstrumentation::RequestGlobalDump(
|
||||
void MemoryInstrumentation::RequestPrivateMemoryFootprint(
|
||||
base::ProcessId pid,
|
||||
RequestGlobalDumpCallback callback) {
|
||||
+ CHECK(is_browser_process_);
|
||||
coordinator_->RequestPrivateMemoryFootprint(
|
||||
pid, base::BindOnce(&WrapGlobalMemoryDump, std::move(callback)));
|
||||
}
|
||||
@@ -60,6 +65,7 @@ void MemoryInstrumentation::RequestGlobalDumpForPid(
|
||||
base::ProcessId pid,
|
||||
const std::vector<std::string>& allocator_dump_names,
|
||||
RequestGlobalDumpCallback callback) {
|
||||
+ CHECK(is_browser_process_);
|
||||
coordinator_->RequestGlobalMemoryDumpForPid(
|
||||
pid, allocator_dump_names,
|
||||
base::BindOnce(&WrapGlobalMemoryDump, std::move(callback)));
|
||||
@@ -70,6 +76,7 @@ void MemoryInstrumentation::RequestGlobalDumpAndAppendToTrace(
|
||||
MemoryDumpLevelOfDetail level_of_detail,
|
||||
MemoryDumpDeterminism determinism,
|
||||
RequestGlobalMemoryDumpAndAppendToTraceCallback callback) {
|
||||
+ CHECK(is_browser_process_);
|
||||
coordinator_->RequestGlobalMemoryDumpAndAppendToTrace(
|
||||
dump_type, level_of_detail, determinism, std::move(callback));
|
||||
}
|
||||
diff --git a/services/resource_coordinator/public/cpp/memory_instrumentation/memory_instrumentation.h b/services/resource_coordinator/public/cpp/memory_instrumentation/memory_instrumentation.h
|
||||
index 3264917890cc30179c4477657158fd359a9d1e01..72157b5345fb003452f67045e2b2c984e748958a 100644
|
||||
--- a/services/resource_coordinator/public/cpp/memory_instrumentation/memory_instrumentation.h
|
||||
+++ b/services/resource_coordinator/public/cpp/memory_instrumentation/memory_instrumentation.h
|
||||
@@ -34,7 +34,8 @@ class COMPONENT_EXPORT(RESOURCE_COORDINATOR_PUBLIC_MEMORY_INSTRUMENTATION)
|
||||
|
||||
static void CreateInstance(
|
||||
mojo::PendingRemote<memory_instrumentation::mojom::Coordinator>
|
||||
- coordinator);
|
||||
+ coordinator,
|
||||
+ bool is_browser_process);
|
||||
static MemoryInstrumentation* GetInstance();
|
||||
|
||||
// Retrieves a Coordinator interface to communicate with the service. This is
|
||||
@@ -100,12 +101,16 @@ class COMPONENT_EXPORT(RESOURCE_COORDINATOR_PUBLIC_MEMORY_INSTRUMENTATION)
|
||||
private:
|
||||
explicit MemoryInstrumentation(
|
||||
mojo::PendingRemote<memory_instrumentation::mojom::Coordinator>
|
||||
- coordinator);
|
||||
+ coordinator,
|
||||
+ bool is_browser_process);
|
||||
~MemoryInstrumentation();
|
||||
|
||||
const mojo::SharedRemote<memory_instrumentation::mojom::Coordinator>
|
||||
coordinator_;
|
||||
|
||||
+ // Only browser process is allowed to request memory dumps.
|
||||
+ const bool is_browser_process_;
|
||||
+
|
||||
DISALLOW_COPY_AND_ASSIGN(MemoryInstrumentation);
|
||||
};
|
||||
|
||||
274
patches/chromium/cherry-pick-8623d711677d.patch
Normal file
274
patches/chromium/cherry-pick-8623d711677d.patch
Normal file
@@ -0,0 +1,274 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Ian Kilpatrick <ikilpatrick@chromium.org>
|
||||
Date: Thu, 9 Sep 2021 23:20:48 +0000
|
||||
Subject: Remove limit from LayoutInline::SplitInlines.
|
||||
|
||||
After 200 elements the code "gave up" causing the layout tree to be
|
||||
"strange".
|
||||
|
||||
This caused a To<LayoutInline> to fail in the OOF code. Relaxing this
|
||||
To<> to a DynamicTo<> caused additional CHECKs / DCHECKs all over the
|
||||
place (not just in NG but in Legacy as well).
|
||||
|
||||
This patch removes the limit at which we "give up". This may cause
|
||||
additional render hangs.
|
||||
|
||||
However we currently have a project "block-in-inline" which will (for
|
||||
most cases) stop inline-splitting for occuring (except in legacy
|
||||
fallback).
|
||||
|
||||
(cherry picked from commit bbd315efb49a4ae257509dd0f0d85c6b5906e0e4)
|
||||
|
||||
(cherry picked from commit d760d2ae1d51c0b4fda87a0a3af4e7ed30d2ff4c)
|
||||
|
||||
Bug: 1245786
|
||||
Change-Id: I5f1c4d6a4b81a8345974de40c0c50a27a839b7b4
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3140144
|
||||
Reviewed-by: Koji Ishii <kojii@chromium.org>
|
||||
Commit-Queue: Ian Kilpatrick <ikilpatrick@chromium.org>
|
||||
Cr-Original-Original-Commit-Position: refs/heads/main@{#917771}
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3149698
|
||||
Cr-Original-Commit-Position: refs/branch-heads/4606@{#876}
|
||||
Cr-Original-Branched-From: 35b0d5a9dc8362adfd44e2614f0d5b7402ef63d0-refs/heads/master@{#911515}
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3152301
|
||||
Bot-Commit: Rubber Stamper <rubber-stamper@appspot.gserviceaccount.com>
|
||||
Cr-Commit-Position: refs/branch-heads/4577@{#1224}
|
||||
Cr-Branched-From: 761ddde228655e313424edec06497d0c56b0f3c4-refs/heads/master@{#902210}
|
||||
|
||||
diff --git a/third_party/blink/renderer/core/layout/layout_inline.cc b/third_party/blink/renderer/core/layout/layout_inline.cc
|
||||
index e59adae1204e5ecb6e399f4fe0ca8a3642701717..d3fa773216bc507208fc6bde3e216e1b8bacf390 100644
|
||||
--- a/third_party/blink/renderer/core/layout/layout_inline.cc
|
||||
+++ b/third_party/blink/renderer/core/layout/layout_inline.cc
|
||||
@@ -574,15 +574,13 @@ void LayoutInline::SplitInlines(LayoutBlockFlow* from_block,
|
||||
// nest to a much greater depth (see bugzilla bug 13430) but for now we have a
|
||||
// limit. This *will* result in incorrect rendering, but the alternative is to
|
||||
// hang forever.
|
||||
- const unsigned kCMaxSplitDepth = 200;
|
||||
Vector<LayoutInline*> inlines_to_clone;
|
||||
LayoutInline* top_most_inline = this;
|
||||
for (LayoutObject* o = this; o != from_block; o = o->Parent()) {
|
||||
if (o->IsLayoutNGInsideListMarker())
|
||||
continue;
|
||||
top_most_inline = To<LayoutInline>(o);
|
||||
- if (inlines_to_clone.size() < kCMaxSplitDepth)
|
||||
- inlines_to_clone.push_back(top_most_inline);
|
||||
+ inlines_to_clone.push_back(top_most_inline);
|
||||
// Keep walking up the chain to ensure |topMostInline| is a child of
|
||||
// |fromBlock|, to avoid assertion failure when |fromBlock|'s children are
|
||||
// moved to |toBlock| below.
|
||||
diff --git a/third_party/blink/web_tests/external/wpt/css/css-inline/inline-crash.html b/third_party/blink/web_tests/external/wpt/css/css-inline/inline-crash.html
|
||||
new file mode 100644
|
||||
index 0000000000000000000000000000000000000000..65008f74ce6e0b4397a5b333099c692382d64353
|
||||
--- /dev/null
|
||||
+++ b/third_party/blink/web_tests/external/wpt/css/css-inline/inline-crash.html
|
||||
@@ -0,0 +1,210 @@
|
||||
+<!DOCTYPE html>
|
||||
+<link rel="help" href="https://bugs.chromium.org/p/chromium/issues/detail?id=1245786">
|
||||
+<style>
|
||||
+ nav{ position: absolute; }
|
||||
+ body > * { position: relative; }
|
||||
+</style>
|
||||
+<body>
|
||||
+<span>
|
||||
+<span>
|
||||
+<span>
|
||||
+<span>
|
||||
+<span>
|
||||
+<span>
|
||||
+<span>
|
||||
+<span>
|
||||
+<span>
|
||||
+<span>
|
||||
+<span>
|
||||
+<span>
|
||||
+<span>
|
||||
+<span>
|
||||
+<span>
|
||||
+<span>
|
||||
+<span>
|
||||
+<span>
|
||||
+<span>
|
||||
+<span>
|
||||
+<span>
|
||||
+<span>
|
||||
+<span>
|
||||
+<span>
|
||||
+<span>
|
||||
+<span>
|
||||
+<span>
|
||||
+<span>
|
||||
+<span>
|
||||
+<span>
|
||||
+<span>
|
||||
+<span>
|
||||
+<span>
|
||||
+<span>
|
||||
+<span>
|
||||
+<span>
|
||||
+<span>
|
||||
+<span>
|
||||
+<span>
|
||||
+<span>
|
||||
+<span>
|
||||
+<span>
|
||||
+<span>
|
||||
+<span>
|
||||
+<span>
|
||||
+<span>
|
||||
+<span>
|
||||
+<span>
|
||||
+<span>
|
||||
+<span>
|
||||
+<span>
|
||||
+<span>
|
||||
+<span>
|
||||
+<span>
|
||||
+<span>
|
||||
+<span>
|
||||
+<span>
|
||||
+<span>
|
||||
+<span>
|
||||
+<span>
|
||||
+<span>
|
||||
+<span>
|
||||
+<span>
|
||||
+<span>
|
||||
+<span>
|
||||
+<span>
|
||||
+<span>
|
||||
+<span>
|
||||
+<span>
|
||||
+<span>
|
||||
+<span>
|
||||
+<span>
|
||||
+<span>
|
||||
+<span>
|
||||
+<span>
|
||||
+<span>
|
||||
+<span>
|
||||
+<span>
|
||||
+<span>
|
||||
+<span>
|
||||
+<span>
|
||||
+<span>
|
||||
+<span>
|
||||
+<span>
|
||||
+<span>
|
||||
+<span>
|
||||
+<span>
|
||||
+<span>
|
||||
+<span>
|
||||
+<span>
|
||||
+<span>
|
||||
+<span>
|
||||
+<span>
|
||||
+<span>
|
||||
+<span>
|
||||
+<span>
|
||||
+<span>
|
||||
+<span>
|
||||
+<span>
|
||||
+<span>
|
||||
+<span>
|
||||
+<span>
|
||||
+<span>
|
||||
+<span>
|
||||
+<span>
|
||||
+<span>
|
||||
+<span>
|
||||
+<span>
|
||||
+<span>
|
||||
+<span>
|
||||
+<span>
|
||||
+<span>
|
||||
+<span>
|
||||
+<span>
|
||||
+<span>
|
||||
+<span>
|
||||
+<span>
|
||||
+<span>
|
||||
+<span>
|
||||
+<span>
|
||||
+<span>
|
||||
+<span>
|
||||
+<span>
|
||||
+<span>
|
||||
+<span>
|
||||
+<span>
|
||||
+<span>
|
||||
+<span>
|
||||
+<span>
|
||||
+<span>
|
||||
+<span>
|
||||
+<span>
|
||||
+<span>
|
||||
+<span>
|
||||
+<span>
|
||||
+<span>
|
||||
+<span>
|
||||
+<span>
|
||||
+<span>
|
||||
+<span>
|
||||
+<span>
|
||||
+<span>
|
||||
+<span>
|
||||
+<span>
|
||||
+<span>
|
||||
+<span>
|
||||
+<span>
|
||||
+<span>
|
||||
+<span>
|
||||
+<span>
|
||||
+<span>
|
||||
+<span>
|
||||
+<span>
|
||||
+<span>
|
||||
+<span>
|
||||
+<span>
|
||||
+<span>
|
||||
+<span>
|
||||
+<span>
|
||||
+<span>
|
||||
+<span>
|
||||
+<span>
|
||||
+<span>
|
||||
+<span>
|
||||
+<span>
|
||||
+<span>
|
||||
+<span>
|
||||
+<span>
|
||||
+<span>
|
||||
+<span>
|
||||
+<span>
|
||||
+<span>
|
||||
+<span>
|
||||
+<span>
|
||||
+<span>
|
||||
+<span>
|
||||
+<span>
|
||||
+<span>
|
||||
+<span>
|
||||
+<span>
|
||||
+<span>
|
||||
+<span>
|
||||
+<span>
|
||||
+<span>
|
||||
+<span>
|
||||
+<span>
|
||||
+<span>
|
||||
+<span>
|
||||
+<span>
|
||||
+<span>
|
||||
+<span>
|
||||
+<span>
|
||||
+<span>
|
||||
+<span>
|
||||
+<span>
|
||||
+<span>
|
||||
+<span>
|
||||
+<span>
|
||||
+<span>
|
||||
+<span>
|
||||
+<span>
|
||||
+<div>
|
||||
+<nav>
|
||||
126
patches/chromium/cherry-pick-8af66de55aad.patch
Normal file
126
patches/chromium/cherry-pick-8af66de55aad.patch
Normal file
@@ -0,0 +1,126 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Antonio Sartori <antoniosartori@chromium.org>
|
||||
Date: Tue, 24 Aug 2021 15:01:17 +0000
|
||||
Subject: Limit length of 'csp' attribute
|
||||
|
||||
Most servers limit the length of request headers anywhere. 4Kb seems
|
||||
like a reasonable limit, which some popular http servers have by
|
||||
default, and which we already enforce for Referer
|
||||
(https://crrev.com/c/1595872).
|
||||
|
||||
I would have liked the constant 4096 to be shared between //content
|
||||
and blink. This would have required putting it somewhere like in
|
||||
//services/network or in //third_party/blink/common, creating a new
|
||||
file for it. I thought it would be easier to avoid that for this
|
||||
change.
|
||||
|
||||
It would be safer to not load the iframe document, or to impose some
|
||||
very strict CSP like "default-src 'none'", instead than just ignoring
|
||||
the 'csp' attribute if that's too long. However, ignoring is what we
|
||||
already do if the attribute contains illegal characters or does not
|
||||
match the CSP grammary or is not subsumed by the parent iframe's csp
|
||||
attribute. For this change, I believe it's better to stay consistent
|
||||
with that, and later change the CSPEE code to block loading in all
|
||||
those cases.
|
||||
|
||||
Bug: 1233067
|
||||
Change-Id: Ie9cd3db82287a76892cca76a0bf0d4a1613a3055
|
||||
Fixed: 1233067
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3057048
|
||||
Commit-Queue: Antonio Sartori <antoniosartori@chromium.org>
|
||||
Reviewed-by: Arthur Sonzogni <arthursonzogni@chromium.org>
|
||||
Reviewed-by: Mike West <mkwst@chromium.org>
|
||||
Cr-Commit-Position: refs/heads/main@{#914730}
|
||||
|
||||
diff --git a/content/browser/content_security_policy_browsertest.cc b/content/browser/content_security_policy_browsertest.cc
|
||||
index 1d0631955600449d142697ce68c474f1957eae75..f95fe16e3c3f8c8b6c603f7cd19dcdb915deacfa 100644
|
||||
--- a/content/browser/content_security_policy_browsertest.cc
|
||||
+++ b/content/browser/content_security_policy_browsertest.cc
|
||||
@@ -225,4 +225,21 @@ IN_PROC_BROWSER_TEST_F(ContentSecurityPolicyBrowserTest, FileURLs) {
|
||||
}
|
||||
}
|
||||
|
||||
+// Test that a 'csp' attribute longer than 4096 bytes is ignored.
|
||||
+IN_PROC_BROWSER_TEST_F(ContentSecurityPolicyBrowserTest, CSPAttributeTooLong) {
|
||||
+ std::string long_csp_attribute = "script-src 'none' ";
|
||||
+ long_csp_attribute.resize(4097, 'a');
|
||||
+ std::string page = "data:text/html,<body><iframe csp=\"" +
|
||||
+ long_csp_attribute + "\"></iframe></body>";
|
||||
+
|
||||
+ GURL url(page);
|
||||
+ WebContentsConsoleObserver console_observer(web_contents());
|
||||
+ console_observer.SetPattern("'csp' attribute too long*");
|
||||
+ EXPECT_TRUE(NavigateToURL(shell(), url));
|
||||
+ console_observer.Wait();
|
||||
+
|
||||
+ EXPECT_EQ(current_frame_host()->child_count(), 1u);
|
||||
+ EXPECT_FALSE(current_frame_host()->child_at(0)->csp_attribute());
|
||||
+}
|
||||
+
|
||||
} // namespace content
|
||||
diff --git a/content/browser/renderer_host/render_frame_host_impl.cc b/content/browser/renderer_host/render_frame_host_impl.cc
|
||||
index 39717e91a88f04d42b489b2217c67f65ee797b4c..db01f3ea0423d780763ba82e50725bb0a12e5018 100644
|
||||
--- a/content/browser/renderer_host/render_frame_host_impl.cc
|
||||
+++ b/content/browser/renderer_host/render_frame_host_impl.cc
|
||||
@@ -837,9 +837,11 @@ enum class VerifyDidCommitParamsDifference {
|
||||
};
|
||||
|
||||
bool ValidateCSPAttribute(const std::string& value) {
|
||||
+ static const size_t kMaxLengthCSPAttribute = 4096;
|
||||
if (!base::IsStringASCII(value))
|
||||
return false;
|
||||
- if (value.find('\n') != std::string::npos ||
|
||||
+ if (value.length() > kMaxLengthCSPAttribute ||
|
||||
+ value.find('\n') != std::string::npos ||
|
||||
value.find('\r') != std::string::npos) {
|
||||
return false;
|
||||
}
|
||||
diff --git a/third_party/blink/renderer/core/html/html_iframe_element.cc b/third_party/blink/renderer/core/html/html_iframe_element.cc
|
||||
index 589580b9795f3908c4f5d978bd4366c98e52847a..40b8af83cdb2dc61b78628c223c0d95f7ec43d5b 100644
|
||||
--- a/third_party/blink/renderer/core/html/html_iframe_element.cc
|
||||
+++ b/third_party/blink/renderer/core/html/html_iframe_element.cc
|
||||
@@ -207,16 +207,27 @@ void HTMLIFrameElement::ParseAttribute(
|
||||
UpdateContainerPolicy();
|
||||
}
|
||||
} else if (name == html_names::kCspAttr) {
|
||||
+ static const size_t kMaxLengthCSPAttribute = 4096;
|
||||
if (value && (value.Contains('\n') || value.Contains('\r') ||
|
||||
!MatchesTheSerializedCSPGrammar(value.GetString()))) {
|
||||
+ // TODO(antoniosartori): It would be safer to block loading iframes with
|
||||
+ // invalid 'csp' attribute.
|
||||
required_csp_ = g_null_atom;
|
||||
GetDocument().AddConsoleMessage(MakeGarbageCollected<ConsoleMessage>(
|
||||
mojom::blink::ConsoleMessageSource::kOther,
|
||||
mojom::blink::ConsoleMessageLevel::kError,
|
||||
"'csp' attribute is invalid: " + value));
|
||||
- return;
|
||||
- }
|
||||
- if (required_csp_ != value) {
|
||||
+ } else if (value && value.length() > kMaxLengthCSPAttribute) {
|
||||
+ // TODO(antoniosartori): It would be safer to block loading iframes with
|
||||
+ // invalid 'csp' attribute.
|
||||
+ required_csp_ = g_null_atom;
|
||||
+ GetDocument().AddConsoleMessage(MakeGarbageCollected<ConsoleMessage>(
|
||||
+ mojom::blink::ConsoleMessageSource::kOther,
|
||||
+ mojom::blink::ConsoleMessageLevel::kError,
|
||||
+ String::Format("'csp' attribute too long. The max length for the "
|
||||
+ "'csp' attribute is %zu bytes.",
|
||||
+ kMaxLengthCSPAttribute)));
|
||||
+ } else if (required_csp_ != value) {
|
||||
required_csp_ = value;
|
||||
CSPAttributeChanged();
|
||||
UseCounter::Count(GetDocument(), WebFeature::kIFrameCSPAttribute);
|
||||
diff --git a/third_party/blink/web_tests/external/wpt/content-security-policy/embedded-enforcement/required_csp-header.html b/third_party/blink/web_tests/external/wpt/content-security-policy/embedded-enforcement/required_csp-header.html
|
||||
index a9ad787408786e594ccb554d2bd9186a9e8e7c1e..e0a31db8e28fb1a9d2884c7677597072d4badba2 100644
|
||||
--- a/third_party/blink/web_tests/external/wpt/content-security-policy/embedded-enforcement/required_csp-header.html
|
||||
+++ b/third_party/blink/web_tests/external/wpt/content-security-policy/embedded-enforcement/required_csp-header.html
|
||||
@@ -59,6 +59,9 @@
|
||||
{ "name": "Wrong and dangerous value of `csp` should not trigger sending Sec-Required-CSP Header - report-to present",
|
||||
"csp": "script-src 'unsafe-inline'; report-to resources/dummy-report.php",
|
||||
"expected": null },
|
||||
+ { "name": "Sec-Required-CSP is not sent if `csp` attribute is longer than 4096 bytes",
|
||||
+ "csp": "style-src " + Array.from(Array(2044).keys()).map(i => 'a').join(' '),
|
||||
+ "expected": null },
|
||||
];
|
||||
|
||||
tests.forEach(test => {
|
||||
48
patches/chromium/cherry-pick-91dd4f79ab5b.patch
Normal file
48
patches/chromium/cherry-pick-91dd4f79ab5b.patch
Normal file
@@ -0,0 +1,48 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Ken Rockot <rockot@google.com>
|
||||
Date: Mon, 25 Oct 2021 18:22:50 +0000
|
||||
Subject: Validate INTRODUCE source node
|
||||
|
||||
INTRODUCE NodeChannel messages should only be acknowledged when coming
|
||||
from the broker process.
|
||||
|
||||
(cherry picked from commit 6e74f7b5cb2f48b17403f0431f3e4f3a2e716265)
|
||||
|
||||
Fixed: 1252858
|
||||
Change-Id: I2dff6d5cab102ce744ad2ad66a9f24b4202cbea8
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3193798
|
||||
Reviewed-by: Alex Gough <ajgo@chromium.org>
|
||||
Commit-Queue: Ken Rockot <rockot@google.com>
|
||||
Cr-Original-Commit-Position: refs/heads/main@{#926430}
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3229034
|
||||
Auto-Submit: Ken Rockot <rockot@google.com>
|
||||
Reviewed-by: Oksana Zhuravlova <oksamyt@chromium.org>
|
||||
Commit-Queue: Oksana Zhuravlova <oksamyt@chromium.org>
|
||||
Cr-Commit-Position: refs/branch-heads/4638@{#964}
|
||||
Cr-Branched-From: 159257cab5585bc8421abf347984bb32fdfe9eb9-refs/heads/main@{#920003}
|
||||
|
||||
diff --git a/mojo/core/node_controller.cc b/mojo/core/node_controller.cc
|
||||
index 475b5cb2d0a301badcd6fb90b5ad90c47e4b5cc4..b8251bf0780f2d9c0346d480839caeab36082721 100644
|
||||
--- a/mojo/core/node_controller.cc
|
||||
+++ b/mojo/core/node_controller.cc
|
||||
@@ -21,6 +21,7 @@
|
||||
#include "mojo/core/broker.h"
|
||||
#include "mojo/core/broker_host.h"
|
||||
#include "mojo/core/configuration.h"
|
||||
+#include "mojo/core/ports/name.h"
|
||||
#include "mojo/core/request_context.h"
|
||||
#include "mojo/core/user_message_impl.h"
|
||||
#include "mojo/public/cpp/platform/named_platform_channel.h"
|
||||
@@ -1129,6 +1130,12 @@ void NodeController::OnIntroduce(const ports::NodeName& from_node,
|
||||
const uint64_t remote_capabilities) {
|
||||
DCHECK(io_task_runner_->RunsTasksInCurrentSequence());
|
||||
|
||||
+ if (broker_name_ == ports::kInvalidNodeName || from_node != broker_name_) {
|
||||
+ DVLOG(1) << "Ignoring introduction from non-broker process.";
|
||||
+ DropPeer(from_node, nullptr);
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
if (!channel_handle.is_valid()) {
|
||||
node_->LostConnectionToNode(name);
|
||||
|
||||
649
patches/chromium/cherry-pick-a5f54612590d.patch
Normal file
649
patches/chromium/cherry-pick-a5f54612590d.patch
Normal file
@@ -0,0 +1,649 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Victor Costan <pwnall@chromium.org>
|
||||
Date: Wed, 10 Nov 2021 21:14:03 +0000
|
||||
Subject: M96: Storage Foundation: Avoid cross-thread access of
|
||||
DOMArrayBufferView.
|
||||
|
||||
blink::NativeIOFile::{read, write}() (in the Storage Foundation API
|
||||
implementation) pass DOMArrayBufferView instances to
|
||||
blink::NativeIOFile::Do{Read,Write}() via CrossThreadPersistent.
|
||||
blink::NativeIOFile::Do{Read,Write}() accesses these instances.
|
||||
|
||||
CrossThreadPersistent can be used across threads to keep a garbage
|
||||
collected object alive. However, accessing the object on a different
|
||||
thread is not safe. cppgc::subtle::CrossThreadPersistent
|
||||
(blink::CrossThreadPersistent is an alias to that) has comments
|
||||
explaining that the garbage collected heap can go away while the
|
||||
CrossThreadPersistent instance exists.
|
||||
|
||||
This CL bypasses the problem by having Do{Read,Write}() receive a
|
||||
ArrayBufferContents that has the DOMArrayBufferView's backing buffer.
|
||||
ArrayBufferContents is not garbage-collected, so it can be safely used
|
||||
across threads.
|
||||
|
||||
This CL introduces a NativeIODataBuffer class that contains the logic
|
||||
and state for tearing a DOMArrayBufferView apart into its components
|
||||
(backing buffer, view type, view offset, view length) and putting it
|
||||
back together into a new DOMArrayBufferView, after it doesn't need to be
|
||||
accessed cross-thread anymore.
|
||||
|
||||
(cherry picked from commit 5200793c2aea5979cc79f3350a4e3d6c0795d6f2)
|
||||
|
||||
Bug: 1268274
|
||||
Change-Id: I51588f5bfe963de96ce426e0f480e8c5b4902688
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3269366
|
||||
Commit-Queue: Victor Costan <pwnall@chromium.org>
|
||||
Reviewed-by: enne <enne@chromium.org>
|
||||
Reviewed-by: Joshua Bell <jsbell@chromium.org>
|
||||
Cr-Original-Commit-Position: refs/heads/main@{#940070}
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3272377
|
||||
Bot-Commit: Rubber Stamper <rubber-stamper@appspot.gserviceaccount.com>
|
||||
Cr-Commit-Position: refs/branch-heads/4664@{#941}
|
||||
Cr-Branched-From: 24dc4ee75e01a29d390d43c9c264372a169273a7-refs/heads/main@{#929512}
|
||||
|
||||
diff --git a/third_party/blink/renderer/modules/native_io/native_io_file.cc b/third_party/blink/renderer/modules/native_io/native_io_file.cc
|
||||
index b25cf909f05be73f690fabee7942ee1fa83c1e04..4d5aa4efa13930aea4886bac0fd8ba892ce8b5a5 100644
|
||||
--- a/third_party/blink/renderer/modules/native_io/native_io_file.cc
|
||||
+++ b/third_party/blink/renderer/modules/native_io/native_io_file.cc
|
||||
@@ -24,7 +24,9 @@
|
||||
#include "third_party/blink/renderer/core/execution_context/execution_context.h"
|
||||
#include "third_party/blink/renderer/core/execution_context/execution_context_lifecycle_observer.h"
|
||||
#include "third_party/blink/renderer/core/execution_context/execution_context_lifecycle_state_observer.h"
|
||||
+#include "third_party/blink/renderer/core/typed_arrays/array_buffer/array_buffer_contents.h"
|
||||
#include "third_party/blink/renderer/core/typed_arrays/dom_array_buffer.h"
|
||||
+#include "third_party/blink/renderer/core/typed_arrays/dom_array_buffer_view.h"
|
||||
#include "third_party/blink/renderer/modules/native_io/native_io_error.h"
|
||||
#include "third_party/blink/renderer/modules/native_io/native_io_file_utils.h"
|
||||
#include "third_party/blink/renderer/platform/bindings/exception_code.h"
|
||||
@@ -256,39 +258,41 @@ ScriptPromise NativeIOFile::read(ScriptState* script_state,
|
||||
"The file was already closed"));
|
||||
return ScriptPromise();
|
||||
}
|
||||
+
|
||||
+ // TODO(pwnall): This assignment should move right before the
|
||||
+ // worker_pool::PostTask() call.
|
||||
+ //
|
||||
+ // `io_pending_` should only be set to true when we know for sure we'll post a
|
||||
+ // task that eventually results in getting `io_pending_` set back to false.
|
||||
+ // Having `io_pending_` set to true in an early return case (rejecting with an
|
||||
+ // exception) leaves the NativeIOFile "stuck" in a state where all future I/O
|
||||
+ // method calls will reject.
|
||||
io_pending_ = true;
|
||||
|
||||
int read_size = NativeIOOperationSize(*buffer);
|
||||
|
||||
- DOMArrayBufferView* result_buffer =
|
||||
- TransferToNewArrayBufferView(script_state->GetIsolate(), buffer);
|
||||
- if (!result_buffer) {
|
||||
+ std::unique_ptr<NativeIODataBuffer> result_buffer_data =
|
||||
+ NativeIODataBuffer::Create(script_state, buffer);
|
||||
+ if (!result_buffer_data) {
|
||||
exception_state.ThrowTypeError("Could not transfer buffer");
|
||||
return ScriptPromise();
|
||||
}
|
||||
+ DCHECK(result_buffer_data->IsValid());
|
||||
DCHECK(buffer->IsDetached());
|
||||
|
||||
- char* result_buffer_data = static_cast<char*>(result_buffer->BaseAddress());
|
||||
-
|
||||
auto* resolver = MakeGarbageCollected<ScriptPromiseResolver>(script_state);
|
||||
// The first CrossThreadUnretained() is safe here because the
|
||||
// NativeIOFile::FileState instance is owned by this NativeIOFile, which is
|
||||
// also passed to the task via WrapCrossThreadPersistent. Therefore, the
|
||||
// FileState instance is guaranteed to remain alive during the task's
|
||||
// execution.
|
||||
- //
|
||||
- // The second CrossThreadUnretained() is safe here because result_buffer_data
|
||||
- // is backed by a DOMArrayBufferView that is also passed to the task via
|
||||
- // WrapCrossThreadPersistent. Therefore, the buffer is guaranteed to remain
|
||||
- // alive during the task's execution.
|
||||
worker_pool::PostTask(
|
||||
FROM_HERE, {base::MayBlock()},
|
||||
- CrossThreadBindOnce(
|
||||
- &DoRead, WrapCrossThreadPersistent(this),
|
||||
- WrapCrossThreadPersistent(resolver),
|
||||
- WrapCrossThreadPersistent(result_buffer),
|
||||
- CrossThreadUnretained(file_state_.get()), resolver_task_runner_,
|
||||
- CrossThreadUnretained(result_buffer_data), file_offset, read_size));
|
||||
+ CrossThreadBindOnce(&DoRead, WrapCrossThreadPersistent(this),
|
||||
+ WrapCrossThreadPersistent(resolver),
|
||||
+ CrossThreadUnretained(file_state_.get()),
|
||||
+ resolver_task_runner_, std::move(result_buffer_data),
|
||||
+ file_offset, read_size));
|
||||
return resolver->Promise();
|
||||
}
|
||||
|
||||
@@ -344,35 +348,28 @@ ScriptPromise NativeIOFile::write(ScriptState* script_state,
|
||||
|
||||
io_pending_ = true;
|
||||
|
||||
- DOMArrayBufferView* result_buffer =
|
||||
- TransferToNewArrayBufferView(script_state->GetIsolate(), buffer);
|
||||
- if (!result_buffer) {
|
||||
+ std::unique_ptr<NativeIODataBuffer> result_buffer_data =
|
||||
+ NativeIODataBuffer::Create(script_state, buffer);
|
||||
+ if (!result_buffer_data) {
|
||||
exception_state.ThrowTypeError("Could not transfer buffer");
|
||||
return ScriptPromise();
|
||||
}
|
||||
+ DCHECK(result_buffer_data->IsValid());
|
||||
DCHECK(buffer->IsDetached());
|
||||
|
||||
- char* result_buffer_data = static_cast<char*>(result_buffer->BaseAddress());
|
||||
-
|
||||
auto* resolver = MakeGarbageCollected<ScriptPromiseResolver>(script_state);
|
||||
// The first CrossThreadUnretained() is safe here because the
|
||||
// NativeIOFile::FileState instance is owned by this NativeIOFile, which is
|
||||
// also passed to the task via WrapCrossThreadPersistent. Therefore, the
|
||||
// FileState instance is guaranteed to remain alive during the task's
|
||||
// execution.
|
||||
- //
|
||||
- // The second CrossThreadUnretained() is safe here because result_buffer_data
|
||||
- // is backed by a DOMArrayBufferView that is also passed to the task via
|
||||
- // WrapCrossThreadPersistent. Therefore, the data is guaranteed to remain
|
||||
- // alive during the task's execution.
|
||||
worker_pool::PostTask(
|
||||
FROM_HERE, {base::MayBlock()},
|
||||
- CrossThreadBindOnce(
|
||||
- &DoWrite, WrapCrossThreadPersistent(this),
|
||||
- WrapCrossThreadPersistent(resolver),
|
||||
- WrapCrossThreadPersistent(result_buffer),
|
||||
- CrossThreadUnretained(file_state_.get()), resolver_task_runner_,
|
||||
- CrossThreadUnretained(result_buffer_data), file_offset, write_size));
|
||||
+ CrossThreadBindOnce(&DoWrite, WrapCrossThreadPersistent(this),
|
||||
+ WrapCrossThreadPersistent(resolver),
|
||||
+ CrossThreadUnretained(file_state_.get()),
|
||||
+ resolver_task_runner_, std::move(result_buffer_data),
|
||||
+ file_offset, write_size));
|
||||
return resolver->Promise();
|
||||
}
|
||||
|
||||
@@ -676,22 +673,29 @@ void NativeIOFile::DidSetLengthIpc(
|
||||
void NativeIOFile::DoRead(
|
||||
CrossThreadPersistent<NativeIOFile> native_io_file,
|
||||
CrossThreadPersistent<ScriptPromiseResolver> resolver,
|
||||
- CrossThreadPersistent<DOMArrayBufferView> result_buffer,
|
||||
NativeIOFile::FileState* file_state,
|
||||
scoped_refptr<base::SequencedTaskRunner> resolver_task_runner,
|
||||
- char* result_buffer_data,
|
||||
+ std::unique_ptr<NativeIODataBuffer> result_buffer_data,
|
||||
uint64_t file_offset,
|
||||
int read_size) {
|
||||
DCHECK(!IsMainThread()) << "File I/O should not happen on the main thread";
|
||||
|
||||
+ DCHECK(resolver_task_runner);
|
||||
+ DCHECK(result_buffer_data);
|
||||
+ DCHECK(result_buffer_data->IsValid());
|
||||
+ DCHECK_GE(read_size, 0);
|
||||
+#if DCHECK_IS_ON()
|
||||
+ DCHECK_LE(static_cast<size_t>(read_size), result_buffer_data->DataLength());
|
||||
+#endif // DCHECK_IS_ON()
|
||||
+
|
||||
int read_bytes;
|
||||
base::File::Error read_error;
|
||||
{
|
||||
WTF::MutexLocker mutex_locker(file_state->mutex);
|
||||
DCHECK(file_state->file.IsValid())
|
||||
<< "file I/O operation queued after file closed";
|
||||
- read_bytes =
|
||||
- file_state->file.Read(file_offset, result_buffer_data, read_size);
|
||||
+ read_bytes = file_state->file.Read(file_offset, result_buffer_data->Data(),
|
||||
+ read_size);
|
||||
read_error = (read_bytes < 0) ? file_state->file.GetLastFileError()
|
||||
: base::File::FILE_OK;
|
||||
}
|
||||
@@ -699,15 +703,18 @@ void NativeIOFile::DoRead(
|
||||
PostCrossThreadTask(
|
||||
*resolver_task_runner, FROM_HERE,
|
||||
CrossThreadBindOnce(&NativeIOFile::DidRead, std::move(native_io_file),
|
||||
- std::move(resolver), std::move(result_buffer),
|
||||
+ std::move(resolver), std::move(result_buffer_data),
|
||||
read_bytes, read_error));
|
||||
}
|
||||
|
||||
void NativeIOFile::DidRead(
|
||||
CrossThreadPersistent<ScriptPromiseResolver> resolver,
|
||||
- CrossThreadPersistent<DOMArrayBufferView> result_buffer,
|
||||
+ std::unique_ptr<NativeIODataBuffer> result_buffer_data,
|
||||
int read_bytes,
|
||||
base::File::Error read_error) {
|
||||
+ DCHECK(result_buffer_data);
|
||||
+ DCHECK(result_buffer_data->IsValid());
|
||||
+
|
||||
ScriptState* script_state = resolver->GetScriptState();
|
||||
if (!script_state->ContextIsValid())
|
||||
return;
|
||||
@@ -727,7 +734,7 @@ void NativeIOFile::DidRead(
|
||||
DCHECK_EQ(read_error, base::File::FILE_OK)
|
||||
<< "Error set but positive number of bytes read.";
|
||||
NativeIOReadResult* read_result = MakeGarbageCollected<NativeIOReadResult>();
|
||||
- read_result->setBuffer(NotShared<DOMArrayBufferView>(result_buffer));
|
||||
+ read_result->setBuffer(result_buffer_data->Take());
|
||||
read_result->setReadBytes(read_bytes);
|
||||
resolver->Resolve(read_result);
|
||||
}
|
||||
@@ -736,13 +743,19 @@ void NativeIOFile::DidRead(
|
||||
void NativeIOFile::DoWrite(
|
||||
CrossThreadPersistent<NativeIOFile> native_io_file,
|
||||
CrossThreadPersistent<ScriptPromiseResolver> resolver,
|
||||
- CrossThreadPersistent<DOMArrayBufferView> result_buffer,
|
||||
NativeIOFile::FileState* file_state,
|
||||
scoped_refptr<base::SequencedTaskRunner> resolver_task_runner,
|
||||
- const char* result_buffer_data,
|
||||
+ std::unique_ptr<NativeIODataBuffer> result_buffer_data,
|
||||
uint64_t file_offset,
|
||||
int write_size) {
|
||||
DCHECK(!IsMainThread()) << "File I/O should not happen on the main thread";
|
||||
+ DCHECK(resolver_task_runner);
|
||||
+ DCHECK(result_buffer_data);
|
||||
+ DCHECK(result_buffer_data->IsValid());
|
||||
+ DCHECK_GE(write_size, 0);
|
||||
+#if DCHECK_IS_ON()
|
||||
+ DCHECK_LE(static_cast<size_t>(write_size), result_buffer_data->DataLength());
|
||||
+#endif // DCHECK_IS_ON()
|
||||
|
||||
int written_bytes;
|
||||
int64_t actual_file_length_on_failure = 0;
|
||||
@@ -751,8 +764,8 @@ void NativeIOFile::DoWrite(
|
||||
WTF::MutexLocker mutex_locker(file_state->mutex);
|
||||
DCHECK(file_state->file.IsValid())
|
||||
<< "file I/O operation queued after file closed";
|
||||
- written_bytes =
|
||||
- file_state->file.Write(file_offset, result_buffer_data, write_size);
|
||||
+ written_bytes = file_state->file.Write(
|
||||
+ file_offset, result_buffer_data->Data(), write_size);
|
||||
write_error = (written_bytes < 0) ? file_state->file.GetLastFileError()
|
||||
: base::File::FILE_OK;
|
||||
if (written_bytes < write_size || write_error != base::File::FILE_OK) {
|
||||
@@ -767,18 +780,21 @@ void NativeIOFile::DoWrite(
|
||||
PostCrossThreadTask(
|
||||
*resolver_task_runner, FROM_HERE,
|
||||
CrossThreadBindOnce(&NativeIOFile::DidWrite, std::move(native_io_file),
|
||||
- std::move(resolver), std::move(result_buffer),
|
||||
+ std::move(resolver), std::move(result_buffer_data),
|
||||
written_bytes, write_error, write_size,
|
||||
actual_file_length_on_failure));
|
||||
}
|
||||
|
||||
void NativeIOFile::DidWrite(
|
||||
CrossThreadPersistent<ScriptPromiseResolver> resolver,
|
||||
- CrossThreadPersistent<DOMArrayBufferView> result_buffer,
|
||||
+ std::unique_ptr<NativeIODataBuffer> result_buffer_data,
|
||||
int written_bytes,
|
||||
base::File::Error write_error,
|
||||
int write_size,
|
||||
int64_t actual_file_length_on_failure) {
|
||||
+ DCHECK(result_buffer_data);
|
||||
+ DCHECK(result_buffer_data->IsValid());
|
||||
+
|
||||
ScriptState* script_state = resolver->GetScriptState();
|
||||
if (!script_state->ContextIsValid())
|
||||
return;
|
||||
@@ -821,7 +837,7 @@ void NativeIOFile::DidWrite(
|
||||
DCHECK_EQ(write_error, base::File::FILE_OK);
|
||||
NativeIOWriteResult* write_result =
|
||||
MakeGarbageCollected<NativeIOWriteResult>();
|
||||
- write_result->setBuffer(NotShared<DOMArrayBufferView>(result_buffer));
|
||||
+ write_result->setBuffer(result_buffer_data->Take());
|
||||
write_result->setWrittenBytes(written_bytes);
|
||||
resolver->Resolve(write_result);
|
||||
}
|
||||
diff --git a/third_party/blink/renderer/modules/native_io/native_io_file.h b/third_party/blink/renderer/modules/native_io/native_io_file.h
|
||||
index 2e41efeefbcf9805ec2b2ed70d018c717c5c75d1..8ae49ebc2d36d547d152d4e56192e30f8cacd641 100644
|
||||
--- a/third_party/blink/renderer/modules/native_io/native_io_file.h
|
||||
+++ b/third_party/blink/renderer/modules/native_io/native_io_file.h
|
||||
@@ -16,6 +16,7 @@
|
||||
#include "third_party/blink/renderer/core/typed_arrays/array_buffer_view_helpers.h"
|
||||
#include "third_party/blink/renderer/core/typed_arrays/dom_array_buffer_view.h"
|
||||
#include "third_party/blink/renderer/modules/native_io/native_io_capacity_tracker.h"
|
||||
+#include "third_party/blink/renderer/modules/native_io/native_io_file_utils.h"
|
||||
#include "third_party/blink/renderer/platform/bindings/script_wrappable.h"
|
||||
#include "third_party/blink/renderer/platform/heap/handle.h"
|
||||
#include "third_party/blink/renderer/platform/heap/persistent.h"
|
||||
@@ -127,15 +128,14 @@ class NativeIOFile final : public ScriptWrappable {
|
||||
// Performs the file I/O part of read(), off the main thread.
|
||||
static void DoRead(CrossThreadPersistent<NativeIOFile> native_io_file,
|
||||
CrossThreadPersistent<ScriptPromiseResolver> resolver,
|
||||
- CrossThreadPersistent<DOMArrayBufferView> result_buffer,
|
||||
NativeIOFile::FileState* file_state,
|
||||
scoped_refptr<base::SequencedTaskRunner> file_task_runner,
|
||||
- char* result_buffer_data,
|
||||
+ std::unique_ptr<NativeIODataBuffer> result_buffer_data,
|
||||
uint64_t file_offset,
|
||||
int read_size);
|
||||
// Performs the post file I/O part of read(), on the main thread.
|
||||
void DidRead(CrossThreadPersistent<ScriptPromiseResolver> resolver,
|
||||
- CrossThreadPersistent<DOMArrayBufferView> result_buffer,
|
||||
+ std::unique_ptr<NativeIODataBuffer> result_buffer_data,
|
||||
int read_bytes,
|
||||
base::File::Error read_error);
|
||||
|
||||
@@ -143,10 +143,9 @@ class NativeIOFile final : public ScriptWrappable {
|
||||
static void DoWrite(
|
||||
CrossThreadPersistent<NativeIOFile> native_io_file,
|
||||
CrossThreadPersistent<ScriptPromiseResolver> resolver,
|
||||
- CrossThreadPersistent<DOMArrayBufferView> result_buffer,
|
||||
NativeIOFile::FileState* file_state,
|
||||
scoped_refptr<base::SequencedTaskRunner> resolver_task_runner,
|
||||
- const char* result_buffer_data,
|
||||
+ std::unique_ptr<NativeIODataBuffer> result_buffer_data,
|
||||
uint64_t file_offset,
|
||||
int write_size);
|
||||
// Performs the post file I/O part of write(), on the main thread.
|
||||
@@ -154,7 +153,7 @@ class NativeIOFile final : public ScriptWrappable {
|
||||
// `actual_file_length_on_failure` is negative if the I/O operation was
|
||||
// unsuccessful and the correct length of the file could not be determined.
|
||||
void DidWrite(CrossThreadPersistent<ScriptPromiseResolver> resolver,
|
||||
- CrossThreadPersistent<DOMArrayBufferView> result_buffer,
|
||||
+ std::unique_ptr<NativeIODataBuffer> result_buffer_data,
|
||||
int written_bytes,
|
||||
base::File::Error write_error,
|
||||
int write_size,
|
||||
diff --git a/third_party/blink/renderer/modules/native_io/native_io_file_utils.cc b/third_party/blink/renderer/modules/native_io/native_io_file_utils.cc
|
||||
index c50a0a94d111d9ea4eb1eac8a7da920936e0d1a3..3e98a12059374d41b22c8d5c706c31e81581aeae 100644
|
||||
--- a/third_party/blink/renderer/modules/native_io/native_io_file_utils.cc
|
||||
+++ b/third_party/blink/renderer/modules/native_io/native_io_file_utils.cc
|
||||
@@ -3,9 +3,16 @@
|
||||
// found in the LICENSE file.
|
||||
|
||||
#include "third_party/blink/renderer/modules/native_io/native_io_file_utils.h"
|
||||
+
|
||||
#include "base/numerics/safe_conversions.h"
|
||||
+#include "base/sequence_checker.h"
|
||||
+#include "base/types/pass_key.h"
|
||||
+#include "third_party/blink/renderer/core/typed_arrays/dom_array_buffer.h"
|
||||
+#include "third_party/blink/renderer/core/typed_arrays/dom_array_buffer_view.h"
|
||||
#include "third_party/blink/renderer/core/typed_arrays/dom_data_view.h"
|
||||
#include "third_party/blink/renderer/core/typed_arrays/dom_typed_array.h"
|
||||
+#include "third_party/blink/renderer/platform/bindings/script_state.h"
|
||||
+#include "v8/include/v8.h"
|
||||
|
||||
namespace blink {
|
||||
|
||||
@@ -72,4 +79,140 @@ DOMArrayBufferView* TransferToNewArrayBufferView(
|
||||
return target;
|
||||
}
|
||||
|
||||
+// static
|
||||
+std::unique_ptr<NativeIODataBuffer> NativeIODataBuffer::Create(
|
||||
+ ScriptState* script_state,
|
||||
+ NotShared<DOMArrayBufferView> source) {
|
||||
+ DCHECK(script_state);
|
||||
+ DCHECK(source);
|
||||
+
|
||||
+ DOMArrayBufferView::ViewType type = source->GetType();
|
||||
+ size_t offset = source->byteOffset();
|
||||
+ size_t byte_length = source->byteLength();
|
||||
+ size_t length = byte_length / source->TypeSize();
|
||||
+
|
||||
+ // Explicitly fail if the source buffer is not detachable. On its own,
|
||||
+ // Transfer() copies non-detachable input buffers.
|
||||
+ DOMArrayBuffer* buffer = source->buffer();
|
||||
+ v8::Isolate* isolate = script_state->GetIsolate();
|
||||
+ if (!buffer->IsDetachable(isolate))
|
||||
+ return nullptr;
|
||||
+
|
||||
+ ArrayBufferContents contents;
|
||||
+ if (!buffer->Transfer(isolate, contents))
|
||||
+ return nullptr;
|
||||
+ DCHECK(source->IsDetached());
|
||||
+
|
||||
+ return std::make_unique<NativeIODataBuffer>(
|
||||
+ std::move(contents), type, offset,
|
||||
+#if DCHECK_IS_ON()
|
||||
+ byte_length,
|
||||
+#endif // DCHECK_IS_ON()
|
||||
+ length, base::PassKey<NativeIODataBuffer>());
|
||||
+}
|
||||
+
|
||||
+NativeIODataBuffer::NativeIODataBuffer(ArrayBufferContents contents,
|
||||
+ DOMArrayBufferView::ViewType type,
|
||||
+ size_t offset,
|
||||
+#if DCHECK_IS_ON()
|
||||
+ size_t byte_length,
|
||||
+#endif // DCHECK_IS_ON()
|
||||
+ size_t length,
|
||||
+ base::PassKey<NativeIODataBuffer>)
|
||||
+ : contents_(std::move(contents)),
|
||||
+ type_(type),
|
||||
+ offset_(offset),
|
||||
+#if DCHECK_IS_ON()
|
||||
+ byte_length_(byte_length),
|
||||
+#endif // DCHECK_IS_ON()
|
||||
+ length_(length) {
|
||||
+ DCHECK(IsValid());
|
||||
+ DCHECK(!contents_.IsShared());
|
||||
+
|
||||
+ // DataLength() returns 0 when called on an invalid ArrayBufferContents
|
||||
+ // (backing an empty array). This works as expected.
|
||||
+ DCHECK_LE(offset, contents_.DataLength());
|
||||
+#if DCHECK_IS_ON()
|
||||
+ DCHECK_LE(length, byte_length);
|
||||
+ DCHECK_LE(byte_length, contents_.DataLength() - offset);
|
||||
+#endif // DCHECK_IS_ON()
|
||||
+}
|
||||
+
|
||||
+NativeIODataBuffer::~NativeIODataBuffer() {
|
||||
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
|
||||
+}
|
||||
+
|
||||
+bool NativeIODataBuffer::IsValid() const {
|
||||
+ // The ArrayBufferContents is not shared when this instance is constructed. It
|
||||
+ // should not become shared while the instance is valid, because no other code
|
||||
+ // can gain access and make it shared.
|
||||
+ //
|
||||
+ // ArrayBufferContents::IsShared() returns false for invalid instances, which
|
||||
+ // works out well for this check.
|
||||
+ DCHECK(!contents_.IsShared());
|
||||
+
|
||||
+ // Transferring the data out of an empty ArrayBuffer yields an invalid
|
||||
+ // ArrayBufferContents.
|
||||
+ return length_ == 0 || contents_.IsValid();
|
||||
+}
|
||||
+
|
||||
+NotShared<DOMArrayBufferView> NativeIODataBuffer::Take() {
|
||||
+ DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
|
||||
+ DCHECK(IsValid());
|
||||
+
|
||||
+ DOMArrayBuffer* array_buffer = DOMArrayBuffer::Create(std::move(contents_));
|
||||
+
|
||||
+ DOMArrayBufferView* view = nullptr;
|
||||
+ switch (type_) {
|
||||
+ case DOMArrayBufferView::kTypeInt8:
|
||||
+ view = DOMInt8Array::Create(array_buffer, offset_, length_);
|
||||
+ break;
|
||||
+
|
||||
+ case DOMArrayBufferView::kTypeUint8:
|
||||
+ view = DOMUint8Array::Create(array_buffer, offset_, length_);
|
||||
+ break;
|
||||
+
|
||||
+ case DOMArrayBufferView::kTypeUint8Clamped:
|
||||
+ view = DOMUint8ClampedArray::Create(array_buffer, offset_, length_);
|
||||
+ break;
|
||||
+
|
||||
+ case DOMArrayBufferView::kTypeInt16:
|
||||
+ view = DOMInt16Array::Create(array_buffer, offset_, length_);
|
||||
+ break;
|
||||
+
|
||||
+ case DOMArrayBufferView::kTypeUint16:
|
||||
+ view = DOMUint16Array::Create(array_buffer, offset_, length_);
|
||||
+ break;
|
||||
+
|
||||
+ case DOMArrayBufferView::kTypeInt32:
|
||||
+ view = DOMInt32Array::Create(array_buffer, offset_, length_);
|
||||
+ break;
|
||||
+
|
||||
+ case DOMArrayBufferView::kTypeUint32:
|
||||
+ view = DOMUint32Array::Create(array_buffer, offset_, length_);
|
||||
+ break;
|
||||
+
|
||||
+ case DOMArrayBufferView::kTypeFloat32:
|
||||
+ view = DOMFloat32Array::Create(array_buffer, offset_, length_);
|
||||
+ break;
|
||||
+
|
||||
+ case DOMArrayBufferView::kTypeFloat64:
|
||||
+ view = DOMFloat64Array::Create(array_buffer, offset_, length_);
|
||||
+ break;
|
||||
+
|
||||
+ case DOMArrayBufferView::kTypeBigInt64:
|
||||
+ view = DOMBigInt64Array::Create(array_buffer, offset_, length_);
|
||||
+ break;
|
||||
+
|
||||
+ case DOMArrayBufferView::kTypeBigUint64:
|
||||
+ view = DOMBigUint64Array::Create(array_buffer, offset_, length_);
|
||||
+ break;
|
||||
+
|
||||
+ case DOMArrayBufferView::kTypeDataView:
|
||||
+ view = DOMDataView::Create(array_buffer, offset_, length_);
|
||||
+ break;
|
||||
+ }
|
||||
+ return NotShared<DOMArrayBufferView>(view);
|
||||
+}
|
||||
+
|
||||
} // namespace blink
|
||||
diff --git a/third_party/blink/renderer/modules/native_io/native_io_file_utils.h b/third_party/blink/renderer/modules/native_io/native_io_file_utils.h
|
||||
index 355a67a8125ea11158dfe435a71c1c01b1ece361..a500d38bcdf8340e7c747cbde949db8f980ea272 100644
|
||||
--- a/third_party/blink/renderer/modules/native_io/native_io_file_utils.h
|
||||
+++ b/third_party/blink/renderer/modules/native_io/native_io_file_utils.h
|
||||
@@ -5,11 +5,19 @@
|
||||
#ifndef THIRD_PARTY_BLINK_RENDERER_MODULES_NATIVE_IO_NATIVE_IO_FILE_UTILS_H_
|
||||
#define THIRD_PARTY_BLINK_RENDERER_MODULES_NATIVE_IO_NATIVE_IO_FILE_UTILS_H_
|
||||
|
||||
+#include <cstddef>
|
||||
+#include <memory>
|
||||
+
|
||||
+#include "base/sequence_checker.h"
|
||||
+#include "base/types/pass_key.h"
|
||||
+#include "third_party/blink/renderer/core/typed_arrays/array_buffer/array_buffer_contents.h"
|
||||
#include "third_party/blink/renderer/core/typed_arrays/array_buffer_view_helpers.h"
|
||||
#include "third_party/blink/renderer/core/typed_arrays/dom_array_buffer_view.h"
|
||||
|
||||
namespace blink {
|
||||
|
||||
+class ScriptState;
|
||||
+
|
||||
// Extracts the read/write operation size from the buffer size.
|
||||
int NativeIOOperationSize(const DOMArrayBufferView& buffer);
|
||||
|
||||
@@ -20,6 +28,121 @@ DOMArrayBufferView* TransferToNewArrayBufferView(
|
||||
v8::Isolate* isolate,
|
||||
NotShared<DOMArrayBufferView> source);
|
||||
|
||||
+// Provides cross-thread access to the buffer backing a DOMArrayBufferView.
|
||||
+//
|
||||
+// This class is necessary because DOMArrayBufferView is garbage-collected,
|
||||
+// which entails that each DOMArrayBufferView instance can only be safely
|
||||
+// accessed on the thread where it was created. Note that CrossThreadPersistent
|
||||
+// can be used to keep a DOMArrayBufferView alive across threads, but the
|
||||
+// instance cannot be safely accessed on a different thread. See the comments on
|
||||
+// cppgc::subtle::CrossThreadPersistent for details.
|
||||
+//
|
||||
+// An instance takes over a DOMArrayBufferView's backing buffer at construction.
|
||||
+// The instance exposes the backing buffer via the Data() and DataLength()
|
||||
+// methods. At some point, the backing buffer is turned back into a
|
||||
+// DOMArrayBufferView via the Take() method. Once Take() is called, the instance
|
||||
+// is invalid, and Data() / DataLength() must not be called anymore.
|
||||
+//
|
||||
+// An instance should be owned by a single sequence at a time. Changing the
|
||||
+// owning sequence should be accomplished by PostTask-ing an owning pointer to
|
||||
+// the instance.
|
||||
+//
|
||||
+// Each instance must be destroyed on the same sequence where it was created.
|
||||
+// Take() must be called on the same sequence where the instance was created.
|
||||
+class NativeIODataBuffer {
|
||||
+ public:
|
||||
+ // Detaches the buffer backing `source`.
|
||||
+ //
|
||||
+ // Returns nullptr if detaching failed.
|
||||
+ static std::unique_ptr<NativeIODataBuffer> Create(
|
||||
+ ScriptState* script_state,
|
||||
+ NotShared<DOMArrayBufferView> source);
|
||||
+
|
||||
+ // Exposed for std::make_unique. Instances should be obtained from Create().
|
||||
+ NativeIODataBuffer(ArrayBufferContents contents,
|
||||
+ DOMArrayBufferView::ViewType type,
|
||||
+ size_t offset,
|
||||
+#if DCHECK_IS_ON()
|
||||
+ size_t byte_length,
|
||||
+#endif // DCHECK_IS_ON()
|
||||
+ size_t length,
|
||||
+ base::PassKey<NativeIODataBuffer>);
|
||||
+
|
||||
+ NativeIODataBuffer(const NativeIODataBuffer&) = delete;
|
||||
+ NativeIODataBuffer& operator=(const NativeIODataBuffer&) = delete;
|
||||
+
|
||||
+ ~NativeIODataBuffer();
|
||||
+
|
||||
+ // Re-creates the DOMArrayBufferView.
|
||||
+ //
|
||||
+ // Must only be called while this instance is onwed by the same sequence where
|
||||
+ // Create() was called. Must only be called if IsValid() is true.
|
||||
+ // After the call, IsValid() will return false.
|
||||
+ NotShared<DOMArrayBufferView> Take();
|
||||
+
|
||||
+ // Exposed for DCHECKs.
|
||||
+ //
|
||||
+ // Can be called while this instance is owned by any sequence.
|
||||
+ bool IsValid() const;
|
||||
+
|
||||
+ // Returns a raw pointer to the DOMArrayBufferView's view.
|
||||
+ //
|
||||
+ // The return type was chosen so that the raw pointer can be conveniently
|
||||
+ // passed to base::File methods.
|
||||
+ //
|
||||
+ // Can be called while this instance is owned by any sequence. Must only be
|
||||
+ // called if IsValid() is true.
|
||||
+ char* Data() {
|
||||
+ DCHECK(IsValid());
|
||||
+
|
||||
+ // An invalid ArrayBufferContents (backing an empty array) returns nullptr
|
||||
+ // when Data() is called. However, in that case, the offset must be zero.
|
||||
+ DCHECK(contents_.Data() || contents_.DataLength() == 0);
|
||||
+ DCHECK(contents_.Data() || offset_ == 0);
|
||||
+
|
||||
+ // According to the DCHECKs above, this branch isn't strictly needed. The
|
||||
+ // return statement below the branch will never do pointer arithmetic on
|
||||
+ // nullptr, because `offset_` is guaranteed to be zero when
|
||||
+ // the ArrayBufferContents is not valid but this instance is.
|
||||
+ char* data = static_cast<char*>(contents_.Data());
|
||||
+ if (!data) {
|
||||
+ DCHECK_EQ(offset_, 0u);
|
||||
+ return data;
|
||||
+ }
|
||||
+
|
||||
+ return data + offset_;
|
||||
+ }
|
||||
+
|
||||
+#if DCHECK_IS_ON()
|
||||
+ // Returns the size of the DOMArrayBufferView's view, in bytes.
|
||||
+ //
|
||||
+ // Exposed for DCHECKs around base::File calls.
|
||||
+ //
|
||||
+ // Can be called while this instance is owned by any sequence. Must only be
|
||||
+ // called if IsValid() is true.
|
||||
+ size_t DataLength() const {
|
||||
+ DCHECK(IsValid());
|
||||
+ return byte_length_;
|
||||
+ }
|
||||
+#endif // DCHECK_IS_ON()
|
||||
+
|
||||
+ private:
|
||||
+ SEQUENCE_CHECKER(sequence_checker_);
|
||||
+
|
||||
+ // May not be valid, as reported by ArrayBufferContents::IsValid().
|
||||
+ //
|
||||
+ // If valid, guaranteed not to be shared, as reported by
|
||||
+ // ArrayBufferContents::IsShared().
|
||||
+ ArrayBufferContents contents_;
|
||||
+
|
||||
+ DOMArrayBufferView::ViewType type_;
|
||||
+ const size_t offset_;
|
||||
+#if DCHECK_IS_ON()
|
||||
+ const size_t byte_length_;
|
||||
+#endif // DCHECK_IS_ON()
|
||||
+ const size_t length_;
|
||||
+};
|
||||
+
|
||||
} // namespace blink
|
||||
|
||||
#endif // THIRD_PARTY_BLINK_RENDERER_MODULES_NATIVE_IO_NATIVE_IO_FILE_UTILS_H_
|
||||
103
patches/chromium/cherry-pick-ac9dc1235e28.patch
Normal file
103
patches/chromium/cherry-pick-ac9dc1235e28.patch
Normal file
@@ -0,0 +1,103 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Ilya Nikolaevskiy <ilnik@chromium.org>
|
||||
Date: Mon, 17 May 2021 08:34:41 +0000
|
||||
Subject: Add locks and empty string checks to FakeV4L2Impl
|
||||
|
||||
FakeV4L2Impl is crashed by fuzzer with some weird ASAN errors, which
|
||||
turned out to be a threading issue.
|
||||
|
||||
Bug: 1205059,1196302
|
||||
Change-Id: Ieb3a917c9a4549b655862e69214774e183a70bc3
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2883613
|
||||
Reviewed-by: Ricky Liang <jcliang@chromium.org>
|
||||
Commit-Queue: Ilya Nikolaevskiy <ilnik@chromium.org>
|
||||
Cr-Commit-Position: refs/heads/master@{#883390}
|
||||
|
||||
diff --git a/media/capture/video/linux/fake_v4l2_impl.cc b/media/capture/video/linux/fake_v4l2_impl.cc
|
||||
index 4a976815d009e68b3740aa71e8c8fd641bf91493..09647474bed3c7c7b34cd9fb161edd2a7d2e170f 100644
|
||||
--- a/media/capture/video/linux/fake_v4l2_impl.cc
|
||||
+++ b/media/capture/video/linux/fake_v4l2_impl.cc
|
||||
@@ -380,10 +380,16 @@ FakeV4L2Impl::~FakeV4L2Impl() = default;
|
||||
|
||||
void FakeV4L2Impl::AddDevice(const std::string& device_name,
|
||||
const FakeV4L2DeviceConfig& config) {
|
||||
+ base::AutoLock lock(lock_);
|
||||
device_configs_.emplace(device_name, config);
|
||||
}
|
||||
|
||||
int FakeV4L2Impl::open(const char* device_name, int flags) {
|
||||
+ if (!device_name)
|
||||
+ return kInvalidId;
|
||||
+
|
||||
+ base::AutoLock lock(lock_);
|
||||
+
|
||||
std::string device_name_as_string(device_name);
|
||||
auto device_configs_iter = device_configs_.find(device_name_as_string);
|
||||
if (device_configs_iter == device_configs_.end())
|
||||
@@ -403,6 +409,7 @@ int FakeV4L2Impl::open(const char* device_name, int flags) {
|
||||
}
|
||||
|
||||
int FakeV4L2Impl::close(int fd) {
|
||||
+ base::AutoLock lock(lock_);
|
||||
auto device_iter = opened_devices_.find(fd);
|
||||
if (device_iter == opened_devices_.end())
|
||||
return kErrorReturnValue;
|
||||
@@ -412,6 +419,7 @@ int FakeV4L2Impl::close(int fd) {
|
||||
}
|
||||
|
||||
int FakeV4L2Impl::ioctl(int fd, int request, void* argp) {
|
||||
+ base::AutoLock lock(lock_);
|
||||
auto device_iter = opened_devices_.find(fd);
|
||||
if (device_iter == opened_devices_.end())
|
||||
return EBADF;
|
||||
@@ -518,6 +526,7 @@ void* FakeV4L2Impl::mmap(void* /*start*/,
|
||||
int flags,
|
||||
int fd,
|
||||
off_t offset) {
|
||||
+ base::AutoLock lock(lock_);
|
||||
if (flags & MAP_FIXED) {
|
||||
errno = EINVAL;
|
||||
return MAP_FAILED;
|
||||
@@ -543,10 +552,12 @@ void* FakeV4L2Impl::mmap(void* /*start*/,
|
||||
}
|
||||
|
||||
int FakeV4L2Impl::munmap(void* start, size_t length) {
|
||||
+ base::AutoLock lock(lock_);
|
||||
return kSuccessReturnValue;
|
||||
}
|
||||
|
||||
int FakeV4L2Impl::poll(struct pollfd* ufds, unsigned int nfds, int timeout) {
|
||||
+ base::AutoLock lock(lock_);
|
||||
if (nfds != 1) {
|
||||
// We only support polling of a single device.
|
||||
errno = EINVAL;
|
||||
diff --git a/media/capture/video/linux/fake_v4l2_impl.h b/media/capture/video/linux/fake_v4l2_impl.h
|
||||
index 0a035a97dd8761b08eb4cfdbe2865efc346f0e23..ae7167f95163581c756ab4951717fd4352c67757 100644
|
||||
--- a/media/capture/video/linux/fake_v4l2_impl.h
|
||||
+++ b/media/capture/video/linux/fake_v4l2_impl.h
|
||||
@@ -10,6 +10,7 @@
|
||||
|
||||
#include <linux/videodev2.h>
|
||||
|
||||
+#include "base/synchronization/lock.h"
|
||||
#include "media/capture/capture_export.h"
|
||||
#include "media/capture/video/linux/v4l2_capture_device.h"
|
||||
#include "media/capture/video/video_capture_device_descriptor.h"
|
||||
@@ -52,11 +53,13 @@ class CAPTURE_EXPORT FakeV4L2Impl : public V4L2CaptureDevice {
|
||||
private:
|
||||
class OpenedDevice;
|
||||
|
||||
- int next_id_to_return_from_open_;
|
||||
- std::map<std::string, FakeV4L2DeviceConfig> device_configs_;
|
||||
- std::map<std::string, int> device_name_to_open_id_map_;
|
||||
+ base::Lock lock_;
|
||||
+
|
||||
+ int next_id_to_return_from_open_ GUARDED_BY(lock_);
|
||||
+ std::map<std::string, FakeV4L2DeviceConfig> device_configs_ GUARDED_BY(lock_);
|
||||
+ std::map<std::string, int> device_name_to_open_id_map_ GUARDED_BY(lock_);
|
||||
std::map<int /*value returned by open()*/, std::unique_ptr<OpenedDevice>>
|
||||
- opened_devices_;
|
||||
+ opened_devices_ GUARDED_BY(lock_);
|
||||
};
|
||||
|
||||
} // namespace media
|
||||
36
patches/chromium/cherry-pick-b2c4e4dc21e5.patch
Normal file
36
patches/chromium/cherry-pick-b2c4e4dc21e5.patch
Normal file
@@ -0,0 +1,36 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Reilly Grant <reillyg@chromium.org>
|
||||
Date: Mon, 4 Oct 2021 23:02:19 +0000
|
||||
Subject: mojo: CHECK when array has too many elements to serialize
|
||||
|
||||
This change turns an early return into a CHECK because the surrounding
|
||||
code expects memory allocation to succeed.
|
||||
|
||||
(cherry picked from commit 588cb74f661269a5b2b69f52619c0f7a09867d6f)
|
||||
|
||||
Bug: 1236318
|
||||
Change-Id: Ib11e0564fb0fa653cb50c82e1973c76ec0c9c725
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3139712
|
||||
Commit-Queue: Reilly Grant <reillyg@chromium.org>
|
||||
Commit-Queue: Ken Rockot <rockot@google.com>
|
||||
Auto-Submit: Reilly Grant <reillyg@chromium.org>
|
||||
Reviewed-by: Ken Rockot <rockot@google.com>
|
||||
Cr-Original-Commit-Position: refs/heads/main@{#917908}
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3203131
|
||||
Cr-Commit-Position: refs/branch-heads/4606@{#1301}
|
||||
Cr-Branched-From: 35b0d5a9dc8362adfd44e2614f0d5b7402ef63d0-refs/heads/master@{#911515}
|
||||
|
||||
diff --git a/mojo/public/cpp/bindings/lib/message_fragment.h b/mojo/public/cpp/bindings/lib/message_fragment.h
|
||||
index 226c3644689fd10bfc47b4bd86f4d2cca58adbf1..b380da4131b538e185cc2e326bbe2f38c1810953 100644
|
||||
--- a/mojo/public/cpp/bindings/lib/message_fragment.h
|
||||
+++ b/mojo/public/cpp/bindings/lib/message_fragment.h
|
||||
@@ -149,8 +149,7 @@ class MessageFragment<Array_Data<T>> {
|
||||
static_assert(
|
||||
std::numeric_limits<uint32_t>::max() > Traits::kMaxNumElements,
|
||||
"Max num elements castable to 32bit");
|
||||
- if (num_elements > Traits::kMaxNumElements)
|
||||
- return;
|
||||
+ CHECK_LE(num_elements, Traits::kMaxNumElements);
|
||||
|
||||
const uint32_t num_bytes =
|
||||
Traits::GetStorageSize(static_cast<uint32_t>(num_elements));
|
||||
122
patches/chromium/cherry-pick-c69dddfe1cde.patch
Normal file
122
patches/chromium/cherry-pick-c69dddfe1cde.patch
Normal file
@@ -0,0 +1,122 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Hongchan Choi <hongchan@chromium.org>
|
||||
Date: Mon, 11 Oct 2021 23:53:51 +0000
|
||||
Subject: Use zero when the starting value of exponential ramp is zero
|
||||
|
||||
The calculation of an exponential curve is done by the specification:
|
||||
https://webaudio.github.io/web-audio-api/#dom-audioparam-exponentialramptovalueattime
|
||||
|
||||
However, it missed a case where V0 (value1) is zero where it causes
|
||||
a NaN.
|
||||
|
||||
(cherry picked from commit 4e2dcd84dc33f29b032b52e053726ab49e4d0b4d)
|
||||
|
||||
Bug: 1253746,1240610
|
||||
Test: third_party/blink/web_tests/webaudio/AudioParam/exponential-ramp-crash-1253746.html
|
||||
Change-Id: Ib4a95f9298b4300705eda6a2eea64169de7cb002
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3205982
|
||||
Reviewed-by: Ryan Sleevi <rsleevi@chromium.org>
|
||||
Reviewed-by: Chrome Cunningham <chcunningham@chromium.org>
|
||||
Commit-Queue: Hongchan Choi <hongchan@chromium.org>
|
||||
Cr-Original-Commit-Position: refs/heads/main@{#928673}
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3218139
|
||||
Reviewed-by: Hongchan Choi <hongchan@chromium.org>
|
||||
Cr-Commit-Position: refs/branch-heads/4638@{#766}
|
||||
Cr-Branched-From: 159257cab5585bc8421abf347984bb32fdfe9eb9-refs/heads/main@{#920003}
|
||||
|
||||
diff --git a/third_party/blink/renderer/modules/webaudio/audio_param_timeline.cc b/third_party/blink/renderer/modules/webaudio/audio_param_timeline.cc
|
||||
index cf863b343bce3d9c1707be784e01114b594c24f7..f6a0dc5e5cf097f684c0443137b720865601d19c 100644
|
||||
--- a/third_party/blink/renderer/modules/webaudio/audio_param_timeline.cc
|
||||
+++ b/third_party/blink/renderer/modules/webaudio/audio_param_timeline.cc
|
||||
@@ -37,6 +37,7 @@
|
||||
#include "third_party/blink/renderer/platform/bindings/exception_messages.h"
|
||||
#include "third_party/blink/renderer/platform/bindings/exception_state.h"
|
||||
#include "third_party/blink/renderer/platform/wtf/math_extras.h"
|
||||
+#include "third_party/blink/renderer/platform/wtf/std_lib_extras.h"
|
||||
#include "third_party/fdlibm/ieee754.h"
|
||||
|
||||
#if defined(ARCH_CPU_X86_FAMILY)
|
||||
@@ -133,7 +134,12 @@ float AudioParamTimeline::ExponentialRampAtTime(double t,
|
||||
double time1,
|
||||
float value2,
|
||||
double time2) {
|
||||
- return value1 * fdlibm::pow(value2 / value1, (t - time1) / (time2 - time1));
|
||||
+ DCHECK(!std::isnan(value1) && std::isfinite(value1));
|
||||
+ DCHECK(!std::isnan(value2) && std::isfinite(value2));
|
||||
+
|
||||
+ return (value1 == 0.0f || std::signbit(value1) != std::signbit(value2))
|
||||
+ ? value1
|
||||
+ : value1 * fdlibm::pow(value2 / value1, (t - time1) / (time2 - time1));
|
||||
}
|
||||
|
||||
// Compute the value of a set target event at time t with the given event
|
||||
@@ -998,6 +1004,8 @@ float AudioParamTimeline::ValuesForFrameRangeImpl(
|
||||
std::tie(value2, time2, next_event_type) =
|
||||
HandleCancelValues(event, next_event, value2, time2);
|
||||
|
||||
+ DCHECK(!std::isnan(value1));
|
||||
+ DCHECK(!std::isnan(value2));
|
||||
DCHECK_GE(time2, time1);
|
||||
|
||||
// |fillToEndFrame| is the exclusive upper bound of the last frame to be
|
||||
@@ -1057,7 +1065,6 @@ float AudioParamTimeline::ValuesForFrameRangeImpl(
|
||||
value = event->Value();
|
||||
write_index =
|
||||
FillWithDefault(values, value, fill_to_frame, write_index);
|
||||
-
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -1400,6 +1407,7 @@ AudioParamTimeline::HandleCancelValues(const ParamEvent* current_event,
|
||||
value2 = ExponentialRampAtTime(next_event->Time(), value1, time1,
|
||||
saved_event->Value(),
|
||||
saved_event->Time());
|
||||
+ DCHECK(!std::isnan(value1));
|
||||
break;
|
||||
case ParamEvent::kSetValueCurve:
|
||||
case ParamEvent::kSetValueCurveEnd:
|
||||
diff --git a/third_party/blink/web_tests/webaudio/AudioParam/exponential-ramp-crash-1253746.html b/third_party/blink/web_tests/webaudio/AudioParam/exponential-ramp-crash-1253746.html
|
||||
new file mode 100644
|
||||
index 0000000000000000000000000000000000000000..85397c5cc6757ae1464a0cd6733283b6b60abeee
|
||||
--- /dev/null
|
||||
+++ b/third_party/blink/web_tests/webaudio/AudioParam/exponential-ramp-crash-1253746.html
|
||||
@@ -0,0 +1,39 @@
|
||||
+<!DOCTYPE html>
|
||||
+<html>
|
||||
+<head>
|
||||
+ <title>
|
||||
+ Test if a corner case crashes the exponential ramp.
|
||||
+ </title>
|
||||
+ <script src="../../resources/testharness.js"></script>
|
||||
+ <script src="../../resources/testharnessreport.js"></script>
|
||||
+</head>
|
||||
+<body>
|
||||
+ <script>
|
||||
+ const t = async_test('exponential-ramp-crash');
|
||||
+
|
||||
+ const onload = () => {
|
||||
+ const context = new OfflineAudioContext(2, 441000, 44100);
|
||||
+ const source = new ConstantSourceNode(context);
|
||||
+ const delay_node = context.createDelay(30);
|
||||
+ delay_node.connect(context.destination);
|
||||
+ // The time overlap between 4.1s and 4s caused a crash in M95:
|
||||
+ // https://crbug.com/1253746
|
||||
+ delay_node.delayTime.exponentialRampToValueAtTime(2, 4.1);
|
||||
+ delay_node.delayTime.cancelAndHoldAtTime(4);
|
||||
+ context.oncomplete = t.step_func_done(() => {
|
||||
+ // The |delay_node.delayTime| value should be zero because it does not
|
||||
+ // have the previous anchor value. Based on the specification, if the
|
||||
+ // beginning of an expoential ramp is zero, the resulting value falls
|
||||
+ // into zero. In this case, there was no value point before the
|
||||
+ // exponential ramp, and having no value point is treated as a
|
||||
+ // default value, which is zero for |delayTime|.
|
||||
+ assert_equals(delay_node.delayTime.value, 0);
|
||||
+ assert_equals(context.state, 'closed');
|
||||
+ });
|
||||
+ context.startRendering();
|
||||
+ };
|
||||
+
|
||||
+ window.addEventListener('load', t.step_func(onload));
|
||||
+ </script>
|
||||
+</body>
|
||||
+</html>
|
||||
41
patches/chromium/cherry-pick-cc20b36a5845.patch
Normal file
41
patches/chromium/cherry-pick-cc20b36a5845.patch
Normal file
@@ -0,0 +1,41 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Philip Rogers <pdr@chromium.org>
|
||||
Date: Wed, 19 May 2021 16:11:29 +0000
|
||||
Subject: Use a 100ms timer in
|
||||
MacScrollbarAnimatorImpl::StartScrollbarPaintTimer
|
||||
|
||||
MacScrollbarAnimatorImpl::StartScrollbarPaintTimer has a timer that
|
||||
runs while ShouldSuspendScrollAnimations is true. The timer was changed
|
||||
from 100ms to 1ms in https://crrev.com/376453. This was later changed to
|
||||
0ms in https://crrev.com/434428 which caused a performance regression
|
||||
(https://crbug.com/713669). The timer was then changed back to 1ms in
|
||||
https://crrev.com/470823 with a comment about giving other tasks time to
|
||||
cancel the timer. This patch restores the 100ms timer. The comment has
|
||||
been removed because this timer is more of a polling mechanism.
|
||||
|
||||
Bug: 1090000
|
||||
Change-Id: I4041d9ba5869abbe4ff7d55d56d921c7d90a72ad
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2903830
|
||||
Reviewed-by: Hiroki Nakagawa <nhiroki@chromium.org>
|
||||
Commit-Queue: Philip Rogers <pdr@chromium.org>
|
||||
Cr-Commit-Position: refs/heads/master@{#884506}
|
||||
|
||||
diff --git a/third_party/blink/renderer/core/scroll/mac_scrollbar_animator_impl.mm b/third_party/blink/renderer/core/scroll/mac_scrollbar_animator_impl.mm
|
||||
index cb3c5b0493410a1cb8d099ec3349e8cbb8dd629d..b7257f954d4f7f85128b5fd24651c27d2ce8bd85 100644
|
||||
--- a/third_party/blink/renderer/core/scroll/mac_scrollbar_animator_impl.mm
|
||||
+++ b/third_party/blink/renderer/core/scroll/mac_scrollbar_animator_impl.mm
|
||||
@@ -814,13 +814,11 @@ - (void)invalidate {
|
||||
}
|
||||
|
||||
void MacScrollbarAnimatorImpl::StartScrollbarPaintTimer() {
|
||||
- // Post a task with 1 ms delay to give a chance to run other immediate tasks
|
||||
- // that may cancel this.
|
||||
initial_scrollbar_paint_task_handle_ = PostDelayedCancellableTask(
|
||||
*task_runner_, FROM_HERE,
|
||||
WTF::Bind(&MacScrollbarAnimatorImpl::InitialScrollbarPaintTask,
|
||||
WrapWeakPersistent(this)),
|
||||
- base::TimeDelta::FromMilliseconds(1));
|
||||
+ base::TimeDelta::FromMilliseconds(100));
|
||||
}
|
||||
|
||||
bool MacScrollbarAnimatorImpl::ScrollbarPaintTimerIsActive() const {
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user