mirror of
https://github.com/electron/electron.git
synced 2026-02-26 03:01:17 -05:00
Compare commits
88 Commits
v18.0.0-be
...
v18.1.0
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
feea88600a | ||
|
|
89188cd4e9 | ||
|
|
45c1d22489 | ||
|
|
3f39d85501 | ||
|
|
2dd7749181 | ||
|
|
5634ddc665 | ||
|
|
6de6d3966a | ||
|
|
02562e903b | ||
|
|
718ef5269f | ||
|
|
ddaa4a9686 | ||
|
|
f646744d32 | ||
|
|
75ccd1fb65 | ||
|
|
f30034d1a9 | ||
|
|
00b6524793 | ||
|
|
f8f08814a2 | ||
|
|
0a758c418c | ||
|
|
daff2057a4 | ||
|
|
67f2f9e024 | ||
|
|
3ee1a45d76 | ||
|
|
652d87282a | ||
|
|
923788b4e4 | ||
|
|
541504c8a4 | ||
|
|
490584834e | ||
|
|
a269ebd1d8 | ||
|
|
0f073186ff | ||
|
|
73e216f182 | ||
|
|
0a80eb4a9c | ||
|
|
50e386ead4 | ||
|
|
5f0810a177 | ||
|
|
65f3729bfb | ||
|
|
b5bdd26a45 | ||
|
|
9ac2ee317d | ||
|
|
a600027384 | ||
|
|
7f82836d67 | ||
|
|
769088f8dc | ||
|
|
c85bc3c932 | ||
|
|
3cd795a927 | ||
|
|
6179b03fa1 | ||
|
|
72c48aa400 | ||
|
|
befe53e5ad | ||
|
|
41aaed307d | ||
|
|
0d17fac455 | ||
|
|
5c3d6aaa81 | ||
|
|
da6996dc63 | ||
|
|
4cfa648a2e | ||
|
|
86294aa1d0 | ||
|
|
50d9fd215e | ||
|
|
06b3615e30 | ||
|
|
8680415128 | ||
|
|
35bf159cd3 | ||
|
|
f8c7408279 | ||
|
|
9b1e7a8963 | ||
|
|
765e1025f4 | ||
|
|
a5d2a56105 | ||
|
|
d8f43ed7bd | ||
|
|
f1b30c26f9 | ||
|
|
c80f701085 | ||
|
|
fa6dde3e1c | ||
|
|
bb6a072380 | ||
|
|
743e442796 | ||
|
|
4abb7e9709 | ||
|
|
8b996a478a | ||
|
|
d36dc1c7de | ||
|
|
e5c56c08a4 | ||
|
|
1763f4cfc8 | ||
|
|
700887d623 | ||
|
|
f893707c5d | ||
|
|
dcf825bed6 | ||
|
|
cee4e3707f | ||
|
|
e9fa834757 | ||
|
|
a327684118 | ||
|
|
ef5424cee0 | ||
|
|
388acd7e2a | ||
|
|
46d74390fc | ||
|
|
d305082ab7 | ||
|
|
0370583c73 | ||
|
|
91274e5a7e | ||
|
|
fc3172dd2a | ||
|
|
7e0b787a76 | ||
|
|
4556adde82 | ||
|
|
7283c257ae | ||
|
|
bf5a0cdd6a | ||
|
|
1c8e9b3651 | ||
|
|
90726a46e1 | ||
|
|
9cd76a8e52 | ||
|
|
a9b17793de | ||
|
|
134042cc43 | ||
|
|
26d729a4a3 |
@@ -328,6 +328,10 @@ step-setup-goma-for-build: &step-setup-goma-for-build
|
||||
node -e "require('./src/utils/goma.js').downloadAndPrepare({ gomaOneForAll: true })"
|
||||
export GOMA_FALLBACK_ON_AUTH_FAILURE=true
|
||||
third_party/goma/goma_ctl.py ensure_start
|
||||
if [ ! -z "$RAW_GOMA_AUTH" ] && [ "`third_party/goma/goma_auth.py info`" != "Login as Fermi Planck" ]; then
|
||||
echo "WARNING!!!!!! Goma authentication is incorrect; please update Goma auth token."
|
||||
exit 1
|
||||
fi
|
||||
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
|
||||
echo 'export GOMA_FALLBACK_ON_AUTH_FAILURE=true' >> $BASH_ENV
|
||||
@@ -465,6 +469,8 @@ step-fix-sync: &step-fix-sync
|
||||
|
||||
# Fix esbuild (wrong binary)
|
||||
echo 'infra/3pp/tools/esbuild/${platform}' `gclient getdep --deps-file=src/third_party/devtools-frontend/src/DEPS -r 'third_party/esbuild:infra/3pp/tools/esbuild/${platform}'` > esbuild_ensure_file
|
||||
# Remove extra output from calling gclient getdep which always calls update_depot_tools
|
||||
sed -i '' "s/Updating depot_tools... //g" esbuild_ensure_file
|
||||
cipd ensure --root src/third_party/devtools-frontend/src/third_party/esbuild -ensure-file esbuild_ensure_file
|
||||
fi
|
||||
|
||||
@@ -543,6 +549,7 @@ step-electron-build: &step-electron-build
|
||||
(cd out/Default; zip mksnapshot.zip mksnapshot_args clang_x64_v8_arm64/gen/v8/embedded.S)
|
||||
rm -rf out/Default/clang_x64_v8_arm64/gen
|
||||
rm -rf out/Default/clang_x64_v8_arm64/obj
|
||||
rm -rf out/Default/clang_x64_v8_arm64/thinlto-cache
|
||||
rm -rf out/Default/clang_x64/obj
|
||||
|
||||
# Regenerate because we just deleted some ninja files
|
||||
@@ -779,6 +786,7 @@ step-show-goma-stats: &step-show-goma-stats
|
||||
step-mksnapshot-build: &step-mksnapshot-build
|
||||
run:
|
||||
name: mksnapshot build
|
||||
no_output_timeout: 30m
|
||||
command: |
|
||||
cd src
|
||||
if [ "$USE_PREBUILT_V8_CONTEXT_SNAPSHOT" != "1" ]; then
|
||||
|
||||
20
.github/workflows/semantic.yml
vendored
Normal file
20
.github/workflows/semantic.yml
vendored
Normal file
@@ -0,0 +1,20 @@
|
||||
name: "Check Semantic Commit"
|
||||
|
||||
on:
|
||||
pull_request_target:
|
||||
types:
|
||||
- opened
|
||||
- edited
|
||||
- synchronize
|
||||
|
||||
jobs:
|
||||
main:
|
||||
name: Validate PR Title
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: semantic-pull-request
|
||||
uses: amannn/action-semantic-pull-request@v4
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
with:
|
||||
validateSingleCommit: false
|
||||
62
BUILD.gn
62
BUILD.gn
@@ -43,6 +43,7 @@ if (is_mac) {
|
||||
|
||||
if (is_linux) {
|
||||
import("//build/config/linux/pkg_config.gni")
|
||||
import("//tools/generate_stubs/rules.gni")
|
||||
|
||||
pkg_config("gio_unix") {
|
||||
packages = [ "gio-unix-2.0" ]
|
||||
@@ -54,6 +55,38 @@ if (is_linux) {
|
||||
"gdk-pixbuf-2.0",
|
||||
]
|
||||
}
|
||||
|
||||
generate_library_loader("libnotify_loader") {
|
||||
name = "LibNotifyLoader"
|
||||
output_h = "libnotify_loader.h"
|
||||
output_cc = "libnotify_loader.cc"
|
||||
header = "<libnotify/notify.h>"
|
||||
config = ":libnotify_config"
|
||||
|
||||
functions = [
|
||||
"notify_is_initted",
|
||||
"notify_init",
|
||||
"notify_get_server_caps",
|
||||
"notify_get_server_info",
|
||||
"notify_notification_new",
|
||||
"notify_notification_add_action",
|
||||
"notify_notification_set_image_from_pixbuf",
|
||||
"notify_notification_set_timeout",
|
||||
"notify_notification_set_urgency",
|
||||
"notify_notification_set_hint_string",
|
||||
"notify_notification_show",
|
||||
"notify_notification_close",
|
||||
]
|
||||
}
|
||||
|
||||
generate_stubs("electron_gtk_stubs") {
|
||||
sigs = [ "shell/browser/ui/electron_gtk.sigs" ]
|
||||
extra_header = "shell/browser/ui/electron_gtk.fragment"
|
||||
output_name = "electron_gtk_stubs"
|
||||
public_deps = [ "//ui/gtk:gtk_config" ]
|
||||
logging_function = "LogNoop()"
|
||||
logging_include = "ui/gtk/log_noop.h"
|
||||
}
|
||||
}
|
||||
|
||||
declare_args() {
|
||||
@@ -253,31 +286,6 @@ copy("copy_shell_devtools_discovery_page") {
|
||||
outputs = [ "$target_gen_dir/shell_devtools_discovery_page.html" ]
|
||||
}
|
||||
|
||||
if (is_linux) {
|
||||
generate_library_loader("libnotify_loader") {
|
||||
name = "LibNotifyLoader"
|
||||
output_h = "libnotify_loader.h"
|
||||
output_cc = "libnotify_loader.cc"
|
||||
header = "<libnotify/notify.h>"
|
||||
config = ":libnotify_config"
|
||||
|
||||
functions = [
|
||||
"notify_is_initted",
|
||||
"notify_init",
|
||||
"notify_get_server_caps",
|
||||
"notify_get_server_info",
|
||||
"notify_notification_new",
|
||||
"notify_notification_add_action",
|
||||
"notify_notification_set_image_from_pixbuf",
|
||||
"notify_notification_set_timeout",
|
||||
"notify_notification_set_urgency",
|
||||
"notify_notification_set_hint_string",
|
||||
"notify_notification_show",
|
||||
"notify_notification_close",
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
npm_action("electron_version_args") {
|
||||
script = "generate-version-json"
|
||||
|
||||
@@ -535,6 +543,7 @@ source_set("electron_lib") {
|
||||
if (is_linux) {
|
||||
libs = [ "xshmfence" ]
|
||||
deps += [
|
||||
":electron_gtk_stubs",
|
||||
":libnotify_loader",
|
||||
"//build/config/linux/gtk",
|
||||
"//dbus",
|
||||
@@ -557,7 +566,6 @@ source_set("electron_lib") {
|
||||
defines += [
|
||||
# Disable warnings for g_settings_list_schemas.
|
||||
"GLIB_DISABLE_DEPRECATION_WARNINGS",
|
||||
"USE_X11=1",
|
||||
]
|
||||
|
||||
sources += [
|
||||
@@ -695,6 +703,8 @@ source_set("electron_lib") {
|
||||
deps += [
|
||||
"//chrome/browser/resources/pdf:resources",
|
||||
"//components/pdf/browser",
|
||||
"//components/pdf/browser:interceptors",
|
||||
"//components/pdf/common",
|
||||
"//components/pdf/renderer",
|
||||
"//pdf:pdf_ppapi",
|
||||
]
|
||||
|
||||
2
DEPS
2
DEPS
@@ -15,7 +15,7 @@ gclient_gn_args = [
|
||||
|
||||
vars = {
|
||||
'chromium_version':
|
||||
'100.0.4894.0',
|
||||
'100.0.4896.127',
|
||||
'node_version':
|
||||
'v16.13.2',
|
||||
'nan_version':
|
||||
|
||||
@@ -1 +1 @@
|
||||
18.0.0-beta.2
|
||||
18.1.0
|
||||
40
appveyor.yml
40
appveyor.yml
@@ -67,6 +67,31 @@ build_script:
|
||||
- mkdir src
|
||||
- update_depot_tools.bat
|
||||
- ps: Move-Item $env:APPVEYOR_BUILD_FOLDER -Destination src\electron
|
||||
- ps: >-
|
||||
if (Test-Path 'env:RAW_GOMA_AUTH') {
|
||||
$env:GOMA_OAUTH2_CONFIG_FILE = "$pwd\.goma_oauth2_config"
|
||||
$env:RAW_GOMA_AUTH | Set-Content $env:GOMA_OAUTH2_CONFIG_FILE
|
||||
}
|
||||
- git clone https://github.com/electron/build-tools.git
|
||||
- cd build-tools
|
||||
- npm install
|
||||
- mkdir third_party
|
||||
- ps: >-
|
||||
node -e "require('./src/utils/goma.js').downloadAndPrepare({ gomaOneForAll: true })"
|
||||
- ps: $env:GN_GOMA_FILE = node -e "console.log(require('./src/utils/goma.js').gnFilePath)"
|
||||
- ps: $env:LOCAL_GOMA_DIR = node -e "console.log(require('./src/utils/goma.js').dir)"
|
||||
- cd ..
|
||||
- ps: .\src\electron\script\start-goma.ps1 -gomaDir $env:LOCAL_GOMA_DIR
|
||||
- ps: >-
|
||||
if (Test-Path 'env:RAW_GOMA_AUTH') {
|
||||
$goma_login = python $env:LOCAL_GOMA_DIR\goma_auth.py info
|
||||
if ($goma_login -eq 'Login as Fermi Planck') {
|
||||
Write-warning "Goma authentication is correct";
|
||||
} else {
|
||||
Write-warning "WARNING!!!!!! Goma authentication is incorrect; please update Goma auth token.";
|
||||
$host.SetShouldExit(1)
|
||||
}
|
||||
}
|
||||
- ps: $env:CHROMIUM_BUILDTOOLS_PATH="$pwd\src\buildtools"
|
||||
- ps: >-
|
||||
if ($env:GN_CONFIG -ne 'release') {
|
||||
@@ -130,21 +155,6 @@ build_script:
|
||||
Write-warning "Failed to add third_party\angle\.git; continuing anyway"
|
||||
}
|
||||
}
|
||||
- ps: >-
|
||||
if (Test-Path 'env:RAW_GOMA_AUTH') {
|
||||
$env:GOMA_OAUTH2_CONFIG_FILE = "$pwd\.goma_oauth2_config"
|
||||
$env:RAW_GOMA_AUTH | Set-Content $env:GOMA_OAUTH2_CONFIG_FILE
|
||||
}
|
||||
- git clone https://github.com/electron/build-tools.git
|
||||
- cd build-tools
|
||||
- npm install
|
||||
- mkdir third_party
|
||||
- ps: >-
|
||||
node -e "require('./src/utils/goma.js').downloadAndPrepare({ gomaOneForAll: true })"
|
||||
- ps: $env:GN_GOMA_FILE = node -e "console.log(require('./src/utils/goma.js').gnFilePath)"
|
||||
- ps: $env:LOCAL_GOMA_DIR = node -e "console.log(require('./src/utils/goma.js').dir)"
|
||||
- cd ..
|
||||
- ps: .\src\electron\script\start-goma.ps1 -gomaDir $env:LOCAL_GOMA_DIR
|
||||
- cd src
|
||||
- set BUILD_CONFIG_PATH=//electron/build/args/%GN_CONFIG%.gn
|
||||
- gn gen out/Default "--args=import(\"%BUILD_CONFIG_PATH%\") import(\"%GN_GOMA_FILE%\") %GN_EXTRA_ARGS% "
|
||||
|
||||
@@ -5,7 +5,6 @@ root_extra_deps = [ "//electron" ]
|
||||
node_module_version = 103
|
||||
|
||||
v8_promise_internal_field_count = 1
|
||||
v8_typed_array_max_size_in_heap = 0
|
||||
v8_embedder_string = "-electron.0"
|
||||
|
||||
# TODO: this breaks mksnapshot
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
#!/usr/bin/env python
|
||||
#!/usr/bin/env python3
|
||||
|
||||
import os
|
||||
import subprocess
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
#!/usr/bin/env python
|
||||
#!/usr/bin/env python3
|
||||
from __future__ import print_function
|
||||
import os
|
||||
import subprocess
|
||||
|
||||
@@ -1,9 +1,12 @@
|
||||
from __future__ import with_statement
|
||||
from __future__ import unicode_literals
|
||||
|
||||
import contextlib
|
||||
import sys
|
||||
import os
|
||||
import optparse
|
||||
import json
|
||||
import re
|
||||
import subprocess
|
||||
|
||||
sys.path.append("%s/../../build" % os.path.dirname(os.path.realpath(__file__)))
|
||||
|
||||
@@ -33,36 +36,56 @@ def calculate_hash(root):
|
||||
return CalculateHash('.', None)
|
||||
|
||||
def windows_installed_software():
|
||||
import win32com.client
|
||||
strComputer = "."
|
||||
objWMIService = win32com.client.Dispatch("WbemScripting.SWbemLocator")
|
||||
objSWbemServices = objWMIService.ConnectServer(strComputer, "root\cimv2")
|
||||
colItems = objSWbemServices.ExecQuery("Select * from Win32_Product")
|
||||
items = []
|
||||
powershell_command = [
|
||||
"Get-CimInstance",
|
||||
"-Namespace",
|
||||
"root\cimv2",
|
||||
"-Class",
|
||||
"Win32_product",
|
||||
"|",
|
||||
"Select",
|
||||
"vendor,",
|
||||
"description,",
|
||||
"@{l='install_location';e='InstallLocation'},",
|
||||
"@{l='install_date';e='InstallDate'},",
|
||||
"@{l='install_date_2';e='InstallDate2'},",
|
||||
"caption,",
|
||||
"version,",
|
||||
"name,",
|
||||
"@{l='sku_number';e='SKUNumber'}",
|
||||
"|",
|
||||
"ConvertTo-Json",
|
||||
]
|
||||
|
||||
for objItem in colItems:
|
||||
item = {}
|
||||
if objItem.Caption:
|
||||
item['caption'] = objItem.Caption
|
||||
if objItem.Caption:
|
||||
item['description'] = objItem.Description
|
||||
if objItem.InstallDate:
|
||||
item['install_date'] = objItem.InstallDate
|
||||
if objItem.InstallDate2:
|
||||
item['install_date_2'] = objItem.InstallDate2
|
||||
if objItem.InstallLocation:
|
||||
item['install_location'] = objItem.InstallLocation
|
||||
if objItem.Name:
|
||||
item['name'] = objItem.Name
|
||||
if objItem.SKUNumber:
|
||||
item['sku_number'] = objItem.SKUNumber
|
||||
if objItem.Vendor:
|
||||
item['vendor'] = objItem.Vendor
|
||||
if objItem.Version:
|
||||
item['version'] = objItem.Version
|
||||
items.append(item)
|
||||
proc = subprocess.Popen(
|
||||
["powershell.exe", "-Command", "-"],
|
||||
stdin=subprocess.PIPE,
|
||||
stdout=subprocess.PIPE,
|
||||
)
|
||||
|
||||
return items
|
||||
stdout, _ = proc.communicate(" ".join(powershell_command).encode("utf-8"))
|
||||
|
||||
if proc.returncode != 0:
|
||||
raise RuntimeError("Failed to get list of installed software")
|
||||
|
||||
# On AppVeyor there's other output related to PSReadline,
|
||||
# so grab only the JSON output and ignore everything else
|
||||
json_match = re.match(
|
||||
r".*(\[.*{.*}.*\]).*", stdout.decode("utf-8"), re.DOTALL
|
||||
)
|
||||
|
||||
if not json_match:
|
||||
raise RuntimeError(
|
||||
"Couldn't find JSON output for list of installed software"
|
||||
)
|
||||
|
||||
# Filter out missing keys
|
||||
return list(
|
||||
map(
|
||||
lambda info: {k: info[k] for k in info if info[k]},
|
||||
json.loads(json_match.group(1)),
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
def windows_profile():
|
||||
@@ -89,7 +112,7 @@ def windows_profile():
|
||||
|
||||
def main(options):
|
||||
if sys.platform == 'win32':
|
||||
with open(options.output_json, 'wb') as f:
|
||||
with open(options.output_json, 'w') as f:
|
||||
json.dump(windows_profile(), f)
|
||||
else:
|
||||
raise OSError("Unsupported OS")
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
#!/usr/bin/env python
|
||||
#!/usr/bin/env python3
|
||||
import os
|
||||
import subprocess
|
||||
import sys
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
#!/usr/bin/env python
|
||||
#!/usr/bin/env python3
|
||||
from __future__ import print_function
|
||||
import os
|
||||
import subprocess
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
#!/usr/bin/env python
|
||||
#!/usr/bin/env python3
|
||||
from __future__ import print_function
|
||||
import os
|
||||
import subprocess
|
||||
|
||||
@@ -298,13 +298,21 @@ static_library("chrome") {
|
||||
|
||||
if (enable_pdf_viewer) {
|
||||
sources += [
|
||||
"//chrome/browser/pdf/chrome_pdf_stream_delegate.cc",
|
||||
"//chrome/browser/pdf/chrome_pdf_stream_delegate.h",
|
||||
"//chrome/browser/pdf/pdf_extension_util.cc",
|
||||
"//chrome/browser/pdf/pdf_extension_util.h",
|
||||
"//chrome/browser/pdf/pdf_frame_util.cc",
|
||||
"//chrome/browser/pdf/pdf_frame_util.h",
|
||||
"//chrome/browser/plugins/pdf_iframe_navigation_throttle.cc",
|
||||
"//chrome/browser/plugins/pdf_iframe_navigation_throttle.h",
|
||||
"//chrome/renderer/pepper/chrome_pdf_print_client.cc",
|
||||
"//chrome/renderer/pepper/chrome_pdf_print_client.h",
|
||||
]
|
||||
deps += [
|
||||
"//components/pdf/browser",
|
||||
"//components/pdf/renderer",
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
@@ -332,15 +340,6 @@ source_set("plugins") {
|
||||
"//chrome/browser/renderer_host/pepper/pepper_isolated_file_system_message_filter.cc",
|
||||
"//chrome/browser/renderer_host/pepper/pepper_isolated_file_system_message_filter.h",
|
||||
]
|
||||
deps += [
|
||||
"//media:media_buildflags",
|
||||
"//ppapi/buildflags",
|
||||
"//ppapi/proxy:ipc",
|
||||
"//services/device/public/mojom",
|
||||
]
|
||||
if (enable_pdf_viewer) {
|
||||
deps += [ "//components/pdf/browser" ]
|
||||
}
|
||||
|
||||
# renderer side
|
||||
sources += [
|
||||
@@ -351,17 +350,18 @@ source_set("plugins") {
|
||||
"//chrome/renderer/pepper/pepper_shared_memory_message_filter.cc",
|
||||
"//chrome/renderer/pepper/pepper_shared_memory_message_filter.h",
|
||||
]
|
||||
if (enable_pdf_viewer) {
|
||||
deps += [ "//components/pdf/renderer" ]
|
||||
}
|
||||
|
||||
deps += [
|
||||
"//components/strings",
|
||||
"//media:media_buildflags",
|
||||
"//ppapi/buildflags",
|
||||
"//ppapi/host",
|
||||
"//ppapi/proxy",
|
||||
"//ppapi/proxy:ipc",
|
||||
"//ppapi/shared_impl",
|
||||
"//services/device/public/mojom",
|
||||
"//skia",
|
||||
"//storage/browser",
|
||||
]
|
||||
}
|
||||
|
||||
|
||||
@@ -70,5 +70,31 @@ The `bounds` of this BrowserView instance as `Object`.
|
||||
|
||||
#### `view.setBackgroundColor(color)` _Experimental_
|
||||
|
||||
* `color` string - Color in `#aarrggbb` or `#argb` form. The alpha channel is
|
||||
optional.
|
||||
* `color` string - Color in Hex, RGB, ARGB, HSL, HSLA or named CSS color format. The alpha channel is
|
||||
optional for the hex type.
|
||||
|
||||
Examples of valid `color` values:
|
||||
|
||||
* Hex
|
||||
* #fff (RGB)
|
||||
* #ffff (ARGB)
|
||||
* #ffffff (RRGGBB)
|
||||
* #ffffffff (AARRGGBB)
|
||||
* RGB
|
||||
* rgb\(([\d]+),\s*([\d]+),\s*([\d]+)\)
|
||||
* e.g. rgb(255, 255, 255)
|
||||
* RGBA
|
||||
* rgba\(([\d]+),\s*([\d]+),\s*([\d]+),\s*([\d.]+)\)
|
||||
* e.g. rgba(255, 255, 255, 1.0)
|
||||
* HSL
|
||||
* hsl\((-?[\d.]+),\s*([\d.]+)%,\s*([\d.]+)%\)
|
||||
* e.g. hsl(200, 20%, 50%)
|
||||
* HSLA
|
||||
* hsla\((-?[\d.]+),\s*([\d.]+)%,\s*([\d.]+)%,\s*([\d.]+)\)
|
||||
* e.g. hsla(200, 20%, 50%, 0.5)
|
||||
* Color name
|
||||
* Options are listed in [SkParseColor.cpp](https://source.chromium.org/chromium/chromium/src/+/main:third_party/skia/src/utils/SkParseColor.cpp;l=11-152;drc=eea4bf52cb0d55e2a39c828b017c80a5ee054148)
|
||||
* Similar to CSS Color Module Level 3 keywords, but case-sensitive.
|
||||
* e.g. `blueviolet` or `red`
|
||||
|
||||
**Note:** Hex format with alpha takes `AARRGGBB` or `ARGB`, _not_ `RRGGBBA` or `RGA`.
|
||||
|
||||
@@ -66,6 +66,18 @@ win.loadURL('https://github.com')
|
||||
Note that even for apps that use `ready-to-show` event, it is still recommended
|
||||
to set `backgroundColor` to make app feel more native.
|
||||
|
||||
Some examples of valid `backgroundColor` values include:
|
||||
|
||||
```js
|
||||
const win = new BrowserWindow()
|
||||
win.setBackgroundColor('hsl(230, 100%, 50%)')
|
||||
win.setBackgroundColor('rgb(255, 145, 145)')
|
||||
win.setBackgroundColor('#ff00a3')
|
||||
win.setBackgroundColor('blueviolet')
|
||||
```
|
||||
|
||||
For more information about these color types see valid options in [win.setBackgroundColor](browser-window.md#winsetbackgroundcolorbackgroundcolor).
|
||||
|
||||
## Parent and child windows
|
||||
|
||||
By using `parent` option, you can create child windows:
|
||||
@@ -199,9 +211,7 @@ It creates a new `BrowserWindow` with native properties as set by the `options`.
|
||||
* `enableLargerThanScreen` boolean (optional) - Enable the window to be resized larger
|
||||
than screen. Only relevant for macOS, as other OSes allow
|
||||
larger-than-screen windows by default. Default is `false`.
|
||||
* `backgroundColor` string (optional) - Window's background color as a hexadecimal value,
|
||||
like `#66CD00` or `#FFF` or `#80FFFFFF` (alpha in #AARRGGBB format is supported if
|
||||
`transparent` is set to `true`). Default is `#FFF` (white).
|
||||
* `backgroundColor` string (optional) - The window's background color in Hex, RGB, RGBA, HSL, HSLA or named CSS color format. Alpha in #AARRGGBB format is supported if `transparent` is set to `true`. Default is `#FFF` (white). See [win.setBackgroundColor](browser-window.md#winsetbackgroundcolorbackgroundcolor) for more information.
|
||||
* `hasShadow` boolean (optional) - Whether window should have a shadow. Default is `true`.
|
||||
* `opacity` number (optional) - Set the initial opacity of the window, between 0.0 (fully
|
||||
transparent) and 1.0 (fully opaque). This is only implemented on Windows and macOS.
|
||||
@@ -454,7 +464,7 @@ window.onbeforeunload = (e) => {
|
||||
// a non-void value will silently cancel the close.
|
||||
// It is recommended to use the dialog API to let the user confirm closing the
|
||||
// application.
|
||||
e.returnValue = false // equivalent to `return false` but not recommended
|
||||
e.returnValue = false
|
||||
}
|
||||
```
|
||||
|
||||
@@ -992,12 +1002,33 @@ APIs like `win.setSize`.
|
||||
|
||||
#### `win.setBackgroundColor(backgroundColor)`
|
||||
|
||||
* `backgroundColor` string - Window's background color as a hexadecimal value,
|
||||
like `#66CD00` or `#FFF` or `#80FFFFFF` (alpha is supported if `transparent`
|
||||
is `true`). Default is `#FFF` (white).
|
||||
* `backgroundColor` string - Color in Hex, RGB, RGBA, HSL, HSLA or named CSS color format. The alpha channel is optional for the hex type.
|
||||
|
||||
Sets the background color of the window. See [Setting
|
||||
`backgroundColor`](#setting-the-backgroundcolor-property).
|
||||
Examples of valid `backgroundColor` values:
|
||||
|
||||
* Hex
|
||||
* #fff (shorthand RGB)
|
||||
* #ffff (shorthand ARGB)
|
||||
* #ffffff (RGB)
|
||||
* #ffffffff (ARGB)
|
||||
* RGB
|
||||
* rgb\(([\d]+),\s*([\d]+),\s*([\d]+)\)
|
||||
* e.g. rgb(255, 255, 255)
|
||||
* RGBA
|
||||
* rgba\(([\d]+),\s*([\d]+),\s*([\d]+),\s*([\d.]+)\)
|
||||
* e.g. rgba(255, 255, 255, 1.0)
|
||||
* HSL
|
||||
* hsl\((-?[\d.]+),\s*([\d.]+)%,\s*([\d.]+)%\)
|
||||
* e.g. hsl(200, 20%, 50%)
|
||||
* HSLA
|
||||
* hsla\((-?[\d.]+),\s*([\d.]+)%,\s*([\d.]+)%,\s*([\d.]+)\)
|
||||
* e.g. hsla(200, 20%, 50%, 0.5)
|
||||
* Color name
|
||||
* Options are listed in [SkParseColor.cpp](https://source.chromium.org/chromium/chromium/src/+/main:third_party/skia/src/utils/SkParseColor.cpp;l=11-152;drc=eea4bf52cb0d55e2a39c828b017c80a5ee054148)
|
||||
* Similar to CSS Color Module Level 3 keywords, but case-sensitive.
|
||||
* e.g. `blueviolet` or `red`
|
||||
|
||||
Sets the background color of the window. See [Setting `backgroundColor`](#setting-the-backgroundcolor-property).
|
||||
|
||||
#### `win.previewFile(path[, displayName])` _macOS_
|
||||
|
||||
@@ -1041,8 +1072,11 @@ Returns [`Rectangle`](structures/rectangle.md) - The `bounds` of the window as `
|
||||
|
||||
#### `win.getBackgroundColor()`
|
||||
|
||||
Returns `string` - Gets the background color of the window. See [Setting
|
||||
`backgroundColor`](#setting-the-backgroundcolor-property).
|
||||
Returns `string` - Gets the background color of the window in Hex (`#RRGGBB`) format.
|
||||
|
||||
See [Setting `backgroundColor`](#setting-the-backgroundcolor-property).
|
||||
|
||||
**Note:** The alpha value is _not_ returned alongside the red, green, and blue values.
|
||||
|
||||
#### `win.setContentBounds(bounds[, animate])`
|
||||
|
||||
@@ -1808,6 +1842,16 @@ with `addBrowserView` or `setBrowserView`.
|
||||
**Note:** The BrowserView API is currently experimental and may change or be
|
||||
removed in future Electron releases.
|
||||
|
||||
#### `win.setTitleBarOverlay(options)` _Windows_
|
||||
|
||||
* `options` Object
|
||||
* `color` String (optional) _Windows_ - The CSS color of the Window Controls Overlay when enabled.
|
||||
* `symbolColor` String (optional) _Windows_ - The CSS color of the symbols on the Window Controls Overlay when enabled.
|
||||
* `height` Integer (optional) _Windows_ - The height of the title bar and Window Controls Overlay in pixels.
|
||||
|
||||
On a Window with Window Controls Overlay already enabled, this method updates
|
||||
the style of the title bar overlay.
|
||||
|
||||
[runtime-enabled-features]: https://cs.chromium.org/chromium/src/third_party/blink/renderer/platform/runtime_enabled_features.json5?l=70
|
||||
[page-visibility-api]: https://developer.mozilla.org/en-US/docs/Web/API/Page_Visibility_API
|
||||
[quick-look]: https://en.wikipedia.org/wiki/Quick_Look
|
||||
|
||||
@@ -67,3 +67,8 @@ or is being instructed to show a high-contrast UI.
|
||||
|
||||
A `boolean` for if the OS / Chromium currently has an inverted color scheme
|
||||
or is being instructed to use an inverted color scheme.
|
||||
|
||||
### `nativeTheme.inForcedColorsMode` _Windows_ _Readonly_
|
||||
|
||||
A `boolean` indicating whether Chromium is in forced colors mode, controlled by system accessibility settings.
|
||||
Currently, Windows high contrast is the only system setting that triggers forced colors mode.
|
||||
|
||||
@@ -178,7 +178,6 @@ Returns an object with V8 heap statistics. Note that all statistics are reported
|
||||
Returns `Object`:
|
||||
|
||||
* `allocated` Integer - Size of all allocated objects in Kilobytes.
|
||||
* `marked` Integer - Size of all marked objects in Kilobytes.
|
||||
* `total` Integer - Total allocated space in Kilobytes.
|
||||
|
||||
Returns an object with Blink memory information.
|
||||
|
||||
@@ -20,7 +20,7 @@ Returns `boolean` - Whether encryption is available.
|
||||
|
||||
On Linux, returns true if the secret key is
|
||||
available. On MacOS, returns true if Keychain is available.
|
||||
On Windows, returns true with no other preconditions.
|
||||
On Windows, returns true once the app has emitted the `ready` event.
|
||||
|
||||
### `safeStorage.encryptString(plainText)`
|
||||
|
||||
|
||||
@@ -868,6 +868,20 @@ this session just before normal `preload` scripts run.
|
||||
Returns `string[]` an array of paths to preload scripts that have been
|
||||
registered.
|
||||
|
||||
#### `ses.setCodeCachePath(path)`
|
||||
|
||||
* `path` String - Absolute path to store the v8 generated JS code cache from the renderer.
|
||||
|
||||
Sets the directory to store the generated JS [code cache](https://v8.dev/blog/code-caching-for-devs) for this session. The directory is not required to be created by the user before this call, the runtime will create if it does not exist otherwise will use the existing directory. If directory cannot be created, then code cache will not be used and all operations related to code cache will fail silently inside the runtime. By default, the directory will be `Code Cache` under the
|
||||
respective user data folder.
|
||||
|
||||
#### `ses.clearCodeCaches(options)`
|
||||
|
||||
* `options` Object
|
||||
* `urls` String[] (optional) - An array of url corresponding to the resource whose generated code cache needs to be removed. If the list is empty then all entries in the cache directory will be removed.
|
||||
|
||||
Returns `Promise<void>` - resolves when the code cache clear operation is complete.
|
||||
|
||||
#### `ses.setSpellCheckerEnabled(enable)`
|
||||
|
||||
* `enable` boolean
|
||||
|
||||
@@ -84,7 +84,7 @@ that contains the user information dictionary sent along with the notification.
|
||||
|
||||
### `systemPreferences.subscribeNotification(event, callback)` _macOS_
|
||||
|
||||
* `event` string
|
||||
* `event` string | null
|
||||
* `callback` Function
|
||||
* `event` string
|
||||
* `userInfo` Record<string, unknown>
|
||||
@@ -109,9 +109,11 @@ example values of `event` are:
|
||||
* `AppleColorPreferencesChangedNotification`
|
||||
* `AppleShowScrollBarsSettingChanged`
|
||||
|
||||
If `event` is null, the `NSDistributedNotificationCenter` doesn’t use it as criteria for delivery to the observer. See [docs](https://developer.apple.com/documentation/foundation/nsnotificationcenter/1411723-addobserverforname?language=objc) for more information.
|
||||
|
||||
### `systemPreferences.subscribeLocalNotification(event, callback)` _macOS_
|
||||
|
||||
* `event` string
|
||||
* `event` string | null
|
||||
* `callback` Function
|
||||
* `event` string
|
||||
* `userInfo` Record<string, unknown>
|
||||
@@ -122,9 +124,11 @@ Returns `number` - The ID of this subscription
|
||||
Same as `subscribeNotification`, but uses `NSNotificationCenter` for local defaults.
|
||||
This is necessary for events such as `NSUserDefaultsDidChangeNotification`.
|
||||
|
||||
If `event` is null, the `NSNotificationCenter` doesn’t use it as criteria for delivery to the observer. See [docs](https://developer.apple.com/documentation/foundation/nsnotificationcenter/1411723-addobserverforname?language=objc) for more information.
|
||||
|
||||
### `systemPreferences.subscribeWorkspaceNotification(event, callback)` _macOS_
|
||||
|
||||
* `event` string
|
||||
* `event` string | null
|
||||
* `callback` Function
|
||||
* `event` string
|
||||
* `userInfo` Record<string, unknown>
|
||||
@@ -135,6 +139,8 @@ Returns `number` - The ID of this subscription
|
||||
Same as `subscribeNotification`, but uses `NSWorkspace.sharedWorkspace.notificationCenter`.
|
||||
This is necessary for events such as `NSWorkspaceDidActivateApplicationNotification`.
|
||||
|
||||
If `event` is null, the `NSWorkspaceNotificationCenter` doesn’t use it as criteria for delivery to the observer. See [docs](https://developer.apple.com/documentation/foundation/nsnotificationcenter/1411723-addobserverforname?language=objc) for more information.
|
||||
|
||||
### `systemPreferences.unsubscribeNotification(id)` _macOS_
|
||||
|
||||
* `id` Integer
|
||||
|
||||
@@ -110,9 +110,11 @@ webFrame.setSpellCheckProvider('en-US', {
|
||||
})
|
||||
```
|
||||
|
||||
### `webFrame.insertCSS(css)`
|
||||
#### `webFrame.insertCSS(css[, options])`
|
||||
|
||||
* `css` string - CSS source code.
|
||||
* `css` string
|
||||
* `options` Object (optional)
|
||||
* `cssOrigin` string (optional) - Can be either 'user' or 'author'. Sets the [cascade origin](https://www.w3.org/TR/css3-cascade/#cascade-origin) of the inserted stylesheet. Default is 'author'.
|
||||
|
||||
Returns `string` - A key for the inserted CSS that can later be used to remove
|
||||
the CSS via `webFrame.removeInsertedCSS(key)`.
|
||||
|
||||
@@ -27,6 +27,13 @@ preload scripts _do_ depend on Node, either refactor them to remove Node usage
|
||||
from the renderer, or explicitly specify `sandbox: false` for the relevant
|
||||
renderers.
|
||||
|
||||
### Removed: `skipTaskbar` on Linux
|
||||
|
||||
On X11, `skipTaskbar` sends a `_NET_WM_STATE_SKIP_TASKBAR` message to the X11
|
||||
window manager. There is not a direct equivalent for Wayland, and the known
|
||||
workarounds have unacceptable tradeoffs (e.g. Window.is_skip_taskbar in GNOME
|
||||
requires unsafe mode), so Electron is unable to support this feature on Linux.
|
||||
|
||||
## Planned Breaking API Changes (19.0)
|
||||
|
||||
*None (yet)*
|
||||
|
||||
@@ -7,21 +7,7 @@ Follow the guidelines below for building **Electron itself** on Linux, for the p
|
||||
## Prerequisites
|
||||
|
||||
* At least 25GB disk space and 8GB RAM.
|
||||
* Python 2.7.x. Some distributions like CentOS 6.x still use Python 2.6.x
|
||||
so you may need to check your Python version with `python -V`.
|
||||
|
||||
Please also ensure that your system and Python version support at least TLS 1.2.
|
||||
For a quick test, run the following script:
|
||||
|
||||
```sh
|
||||
$ npx @electron/check-python-tls
|
||||
```
|
||||
|
||||
If the script returns that your configuration is using an outdated security
|
||||
protocol, use your system's package manager to update Python to the latest
|
||||
version in the 2.7.x branch. Alternatively, visit https://www.python.org/downloads/
|
||||
for detailed instructions.
|
||||
|
||||
* Python >= 3.7.
|
||||
* Node.js. There are various ways to install Node. You can download
|
||||
source code from [nodejs.org](https://nodejs.org) and compile it.
|
||||
Doing so permits installing Node on your own home directory as a standard user.
|
||||
|
||||
@@ -6,45 +6,12 @@ Follow the guidelines below for building **Electron itself** on macOS, for the p
|
||||
|
||||
## Prerequisites
|
||||
|
||||
* macOS >= 10.11.6
|
||||
* [Xcode](https://developer.apple.com/technologies/tools/) >= 9.0.0
|
||||
* macOS >= 11.6.0
|
||||
* [Xcode](https://developer.apple.com/technologies/tools/). The exact version
|
||||
needed depends on what branch you are building, but the latest version of
|
||||
Xcode is generally a good bet for building `main`.
|
||||
* [node.js](https://nodejs.org) (external)
|
||||
* Python 2.7 with support for TLS 1.2
|
||||
|
||||
## Python
|
||||
|
||||
Please also ensure that your system and Python version support at least TLS 1.2.
|
||||
This depends on both your version of macOS and Python. For a quick test, run:
|
||||
|
||||
```sh
|
||||
$ npx @electron/check-python-tls
|
||||
```
|
||||
|
||||
If the script returns that your configuration is using an outdated security
|
||||
protocol, you can either update macOS to High Sierra or install a new version
|
||||
of Python 2.7.x. To upgrade Python, use [Homebrew](https://brew.sh/):
|
||||
|
||||
```sh
|
||||
$ brew install python@2 && brew link python@2 --force
|
||||
```
|
||||
|
||||
If you are using Python as provided by Homebrew, you also need to install
|
||||
the following Python modules:
|
||||
|
||||
* [pyobjc](https://pypi.org/project/pyobjc/#description)
|
||||
|
||||
You can use `pip` to install it:
|
||||
|
||||
```sh
|
||||
$ pip install pyobjc
|
||||
```
|
||||
|
||||
## macOS SDK
|
||||
|
||||
If you're developing Electron and don't plan to redistribute your
|
||||
custom Electron build, you may skip this section.
|
||||
|
||||
Official Electron builds are built with [Xcode 12.2](https://download.developer.apple.com/Developer_Tools/Xcode_12.2/Xcode_12.2.xip), and the macOS 11.0 SDK. Building with a newer SDK works too, but the releases currently use the 11.0 SDK.
|
||||
* Python >= 3.7
|
||||
|
||||
## Building Electron
|
||||
|
||||
|
||||
@@ -28,7 +28,7 @@ For C++ and Python, we follow Chromium's [Coding
|
||||
Style](https://chromium.googlesource.com/chromium/src/+/refs/heads/main/styleguide/styleguide.md).
|
||||
There is also a script `script/cpplint.py` to check whether all files conform.
|
||||
|
||||
The Python version we are using now is Python 2.7.
|
||||
The Python version we are using now is Python 3.9.
|
||||
|
||||
The C++ code uses a lot of Chromium's abstractions and types, so it's
|
||||
recommended to get acquainted with them. A good place to start is
|
||||
|
||||
14
docs/fiddles/ipc/pattern-1/index.html
Normal file
14
docs/fiddles/ipc/pattern-1/index.html
Normal file
@@ -0,0 +1,14 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<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'">
|
||||
<title>Hello World!</title>
|
||||
</head>
|
||||
<body>
|
||||
Title: <input id="title"/>
|
||||
<button id="btn" type="button">Set</button>
|
||||
<script src="./renderer.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
30
docs/fiddles/ipc/pattern-1/main.js
Normal file
30
docs/fiddles/ipc/pattern-1/main.js
Normal file
@@ -0,0 +1,30 @@
|
||||
const {app, BrowserWindow, ipcMain} = require('electron')
|
||||
const path = require('path')
|
||||
|
||||
function createWindow () {
|
||||
const mainWindow = new BrowserWindow({
|
||||
webPreferences: {
|
||||
preload: path.join(__dirname, 'preload.js')
|
||||
}
|
||||
})
|
||||
|
||||
ipcMain.on('set-title', (event, title) => {
|
||||
const webContents = event.sender
|
||||
const win = BrowserWindow.fromWebContents(webContents)
|
||||
win.setTitle(title)
|
||||
})
|
||||
|
||||
mainWindow.loadFile('index.html')
|
||||
}
|
||||
|
||||
app.whenReady().then(() => {
|
||||
createWindow()
|
||||
|
||||
app.on('activate', function () {
|
||||
if (BrowserWindow.getAllWindows().length === 0) createWindow()
|
||||
})
|
||||
})
|
||||
|
||||
app.on('window-all-closed', function () {
|
||||
if (process.platform !== 'darwin') app.quit()
|
||||
})
|
||||
5
docs/fiddles/ipc/pattern-1/preload.js
Normal file
5
docs/fiddles/ipc/pattern-1/preload.js
Normal file
@@ -0,0 +1,5 @@
|
||||
const { contextBridge, ipcRenderer } = require('electron')
|
||||
|
||||
contextBridge.exposeInMainWorld('electronAPI', {
|
||||
setTitle: (title) => ipcRenderer.send('set-title', title)
|
||||
})
|
||||
6
docs/fiddles/ipc/pattern-1/renderer.js
Normal file
6
docs/fiddles/ipc/pattern-1/renderer.js
Normal file
@@ -0,0 +1,6 @@
|
||||
const setButton = document.getElementById('btn')
|
||||
const titleInput = document.getElementById('title')
|
||||
setButton.addEventListener('click', () => {
|
||||
const title = titleInput.value
|
||||
window.electronAPI.setTitle(title)
|
||||
});
|
||||
14
docs/fiddles/ipc/pattern-2/index.html
Normal file
14
docs/fiddles/ipc/pattern-2/index.html
Normal file
@@ -0,0 +1,14 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<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'">
|
||||
<title>Dialog</title>
|
||||
</head>
|
||||
<body>
|
||||
<button type="button" id="btn">Open a File</button>
|
||||
File path: <strong id="filePath"></strong>
|
||||
<script src='./renderer.js'></script>
|
||||
</body>
|
||||
</html>
|
||||
32
docs/fiddles/ipc/pattern-2/main.js
Normal file
32
docs/fiddles/ipc/pattern-2/main.js
Normal file
@@ -0,0 +1,32 @@
|
||||
const {app, BrowserWindow, ipcMain, dialog} = require('electron')
|
||||
const path = require('path')
|
||||
|
||||
async function handleFileOpen() {
|
||||
const { canceled, filePaths } = await dialog.showOpenDialog()
|
||||
if (canceled) {
|
||||
return
|
||||
} else {
|
||||
return filePaths[0]
|
||||
}
|
||||
}
|
||||
|
||||
function createWindow () {
|
||||
const mainWindow = new BrowserWindow({
|
||||
webPreferences: {
|
||||
preload: path.join(__dirname, 'preload.js')
|
||||
}
|
||||
})
|
||||
mainWindow.loadFile('index.html')
|
||||
}
|
||||
|
||||
app.whenReady().then(() => {
|
||||
ipcMain.handle('dialog:openFile', handleFileOpen)
|
||||
createWindow()
|
||||
app.on('activate', function () {
|
||||
if (BrowserWindow.getAllWindows().length === 0) createWindow()
|
||||
})
|
||||
})
|
||||
|
||||
app.on('window-all-closed', function () {
|
||||
if (process.platform !== 'darwin') app.quit()
|
||||
})
|
||||
5
docs/fiddles/ipc/pattern-2/preload.js
Normal file
5
docs/fiddles/ipc/pattern-2/preload.js
Normal file
@@ -0,0 +1,5 @@
|
||||
const { contextBridge, ipcRenderer } = require('electron')
|
||||
|
||||
contextBridge.exposeInMainWorld('electronAPI',{
|
||||
openFile: () => ipcRenderer.invoke('dialog:openFile')
|
||||
})
|
||||
7
docs/fiddles/ipc/pattern-2/renderer.js
Normal file
7
docs/fiddles/ipc/pattern-2/renderer.js
Normal file
@@ -0,0 +1,7 @@
|
||||
const btn = document.getElementById('btn')
|
||||
const filePathElement = document.getElementById('filePath')
|
||||
|
||||
btn.addEventListener('click', async () => {
|
||||
const filePath = await window.electronAPI.openFile()
|
||||
filePathElement.innerText = filePath
|
||||
})
|
||||
13
docs/fiddles/ipc/pattern-3/index.html
Normal file
13
docs/fiddles/ipc/pattern-3/index.html
Normal file
@@ -0,0 +1,13 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<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'">
|
||||
<title>Menu Counter</title>
|
||||
</head>
|
||||
<body>
|
||||
Current value: <strong id="counter">0</strong>
|
||||
<script src="./renderer.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
48
docs/fiddles/ipc/pattern-3/main.js
Normal file
48
docs/fiddles/ipc/pattern-3/main.js
Normal file
@@ -0,0 +1,48 @@
|
||||
const {app, BrowserWindow, Menu, ipcMain} = require('electron')
|
||||
const path = require('path')
|
||||
|
||||
function createWindow () {
|
||||
const mainWindow = new BrowserWindow({
|
||||
webPreferences: {
|
||||
preload: path.join(__dirname, 'preload.js')
|
||||
}
|
||||
})
|
||||
|
||||
const menu = Menu.buildFromTemplate([
|
||||
{
|
||||
label: app.name,
|
||||
submenu: [
|
||||
{
|
||||
click: () => mainWindow.webContents.send('update-counter', 1),
|
||||
label: 'Increment',
|
||||
},
|
||||
{
|
||||
click: () => mainWindow.webContents.send('update-counter', -1),
|
||||
label: 'Decrement',
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
])
|
||||
|
||||
Menu.setApplicationMenu(menu)
|
||||
mainWindow.loadFile('index.html')
|
||||
|
||||
// Open the DevTools.
|
||||
mainWindow.webContents.openDevTools()
|
||||
}
|
||||
|
||||
app.whenReady().then(() => {
|
||||
ipcMain.on('counter-value', (_event, value) => {
|
||||
console.log(value) // will print value to Node console
|
||||
})
|
||||
createWindow()
|
||||
|
||||
app.on('activate', function () {
|
||||
if (BrowserWindow.getAllWindows().length === 0) createWindow()
|
||||
})
|
||||
})
|
||||
|
||||
app.on('window-all-closed', function () {
|
||||
if (process.platform !== 'darwin') app.quit()
|
||||
})
|
||||
5
docs/fiddles/ipc/pattern-3/preload.js
Normal file
5
docs/fiddles/ipc/pattern-3/preload.js
Normal file
@@ -0,0 +1,5 @@
|
||||
const { contextBridge, ipcRenderer } = require('electron')
|
||||
|
||||
contextBridge.exposeInMainWorld('electronAPI', {
|
||||
handleCounter: (callback) => ipcRenderer.on('update-counter', callback)
|
||||
})
|
||||
8
docs/fiddles/ipc/pattern-3/renderer.js
Normal file
8
docs/fiddles/ipc/pattern-3/renderer.js
Normal file
@@ -0,0 +1,8 @@
|
||||
const counter = document.getElementById('counter')
|
||||
|
||||
window.electronAPI.handleCounter((event, value) => {
|
||||
const oldValue = Number(counter.innerText)
|
||||
const newValue = oldValue + value
|
||||
counter.innerText = newValue
|
||||
event.sender.send('counter-value', newValue)
|
||||
})
|
||||
571
docs/tutorial/ipc.md
Normal file
571
docs/tutorial/ipc.md
Normal file
@@ -0,0 +1,571 @@
|
||||
---
|
||||
title: Inter-Process Communication
|
||||
description: Use the ipcMain and ipcRenderer modules to communicate between Electron processes
|
||||
slug: ipc
|
||||
hide_title: false
|
||||
---
|
||||
|
||||
# Inter-Process Communication
|
||||
|
||||
Inter-process communication (IPC) is a key part of building feature-rich desktop applications
|
||||
in Electron. Because the main and renderer processes have different responsibilities in
|
||||
Electron's process model, IPC is the only way to perform many common tasks, such as calling a
|
||||
native API from your UI or triggering changes in your web contents from native menus.
|
||||
|
||||
## IPC channels
|
||||
|
||||
In Electron, processes communicate by passing messages through developer-defined "channels"
|
||||
with the [`ipcMain`] and [`ipcRenderer`] modules. These channels are
|
||||
**arbitrary** (you can name them anything you want) and **bidirectional** (you can use the
|
||||
same channel name for both modules).
|
||||
|
||||
In this guide, we'll be going over some fundamental IPC patterns with concrete examples that
|
||||
you can use as a reference for your app code.
|
||||
|
||||
## Understanding context-isolated processes
|
||||
|
||||
Before proceeding to implementation details, you should be familiar with the idea of using a
|
||||
[preload script] to import Node.js and Electron modules in a context-isolated renderer process.
|
||||
|
||||
* For a full overview of Electron's process model, you can read the [process model docs].
|
||||
* For a primer into exposing APIs from your preload script using the `contextBridge` module, check
|
||||
out the [context isolation tutorial].
|
||||
|
||||
## Pattern 1: Renderer to main (one-way)
|
||||
|
||||
To fire a one-way IPC message from a renderer process to the main process, you can use the
|
||||
[`ipcRenderer.send`] API to send a message that is then received by the [`ipcMain.on`] API.
|
||||
|
||||
You usually use this pattern to call a main process API from your web contents. We'll demonstrate
|
||||
this pattern by creating a simple app that can programmatically change its window title.
|
||||
|
||||
For this demo, you'll need to add code to your main process, your renderer process, and a preload
|
||||
script. The full code is below, but we'll be explaining each file individually in the following
|
||||
sections.
|
||||
|
||||
```fiddle docs/fiddles/ipc/pattern-1
|
||||
```
|
||||
|
||||
### 1. Listen for events with `ipcMain.on`
|
||||
|
||||
In the main process, set an IPC listener on the `set-title` channel with the `ipcMain.on` API:
|
||||
|
||||
```javascript {6-10,22} title='main.js (Main Process)'
|
||||
const {app, BrowserWindow, ipcMain} = require('electron')
|
||||
const path = require('path')
|
||||
|
||||
//...
|
||||
|
||||
function handleSetTitle (event, title) {
|
||||
const webContents = event.sender
|
||||
const win = BrowserWindow.fromWebContents(webContents)
|
||||
win.setTitle(title)
|
||||
}
|
||||
|
||||
function createWindow () {
|
||||
const mainWindow = new BrowserWindow({
|
||||
webPreferences: {
|
||||
preload: path.join(__dirname, 'preload.js')
|
||||
}
|
||||
})
|
||||
mainWindow.loadFile('index.html')
|
||||
}
|
||||
|
||||
app.whenReady().then(() => {
|
||||
ipcMain.on('set-title', handleSetTitle)
|
||||
createWindow()
|
||||
}
|
||||
//...
|
||||
```
|
||||
|
||||
The above `handleSetTitle` callback has two parameters: an [IpcMainEvent] structure and a
|
||||
`title` string. Whenever a message comes through the `set-title` channel, this function will
|
||||
find the BrowserWindow instance attached to the message sender and use the `win.setTitle`
|
||||
API on it.
|
||||
|
||||
:::info
|
||||
Make sure you're loading the `index.html` and `preload.js` entry points for the following steps!
|
||||
:::
|
||||
|
||||
### 2. Expose `ipcRenderer.send` via preload
|
||||
|
||||
To send messages to the listener created above, you can use the `ipcRenderer.send` API.
|
||||
By default, the renderer process has no Node.js or Electron module access. As an app developer,
|
||||
you need to choose which APIs to expose from your preload script using the `contextBridge` API.
|
||||
|
||||
In your preload script, add the following code, which will expose a global `window.electronAPI`
|
||||
variable to your renderer process.
|
||||
|
||||
```javascript title='preload.js (Preload Script)'
|
||||
const { contextBridge, ipcRenderer } = require('electron')
|
||||
|
||||
contextBridge.exposeInMainWorld('electronAPI', {
|
||||
setTitle: (title) => ipcRenderer.send('set-title', title)
|
||||
})
|
||||
```
|
||||
|
||||
At this point, you'll be able to use the `window.electronAPI.setTitle()` function in the renderer
|
||||
process.
|
||||
|
||||
:::caution Security warning
|
||||
We don't directly expose the whole `ipcRenderer.send` API for [security reasons]. Make sure to
|
||||
limit the renderer's access to Electron APIs as much as possible.
|
||||
:::
|
||||
|
||||
### 3. Build the renderer process UI
|
||||
|
||||
In our BrowserWindow's loaded HTML file, add a basic user interface consisting of a text input
|
||||
and a button:
|
||||
|
||||
```html {11-12} title='index.html'
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<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'">
|
||||
<title>Hello World!</title>
|
||||
</head>
|
||||
<body>
|
||||
Title: <input id="title"/>
|
||||
<button id="btn" type="button">Set</button>
|
||||
<script src="./renderer.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
```
|
||||
|
||||
To make these elements interactive, we'll be adding a few lines of code in the imported
|
||||
`renderer.js` file that leverages the `window.electronAPI` functionality exposed from the preload
|
||||
script:
|
||||
|
||||
```javascript title='renderer.js (Renderer Process)'
|
||||
const setButton = document.getElementById('btn')
|
||||
const titleInput = document.getElementById('title')
|
||||
setButton.addEventListener('click', () => {
|
||||
const title = titleInput.value
|
||||
window.electronAPI.setTitle(title)
|
||||
});
|
||||
```
|
||||
|
||||
At this point, your demo should be fully functional. Try using the input field and see what happens
|
||||
to your BrowserWindow title!
|
||||
|
||||
## Pattern 2: Renderer to main (two-way)
|
||||
|
||||
A common application for two-way IPC is calling a main process module from your renderer process
|
||||
code and waiting for a result. This can be done by using [`ipcRenderer.invoke`] paired with
|
||||
[`ipcMain.handle`].
|
||||
|
||||
In the following example, we'll be opening a native file dialog from the renderer process and
|
||||
returning the selected file's path.
|
||||
|
||||
For this demo, you'll need to add code to your main process, your renderer process, and a preload
|
||||
script. The full code is below, but we'll be explaining each file individually in the following
|
||||
sections.
|
||||
|
||||
```fiddle docs/fiddles/ipc/pattern-2
|
||||
```
|
||||
|
||||
### 1. Listen for events with `ipcMain.handle`
|
||||
|
||||
In the main process, we'll be creating a `handleFileOpen()` function that calls
|
||||
`dialog.showOpenDialog` and returns the value of the file path selected by the user. This function
|
||||
is used as a callback whenever an `ipcRender.invoke` message is sent through the `dialog:openFile`
|
||||
channel from the renderer process. The return value is then returned as a Promise to the original
|
||||
`invoke` call.
|
||||
|
||||
:::caution A word on error handling
|
||||
Errors thrown through `handle` in the main process are not transparent as they
|
||||
are serialized and only the `message` property from the original error is
|
||||
provided to the renderer process. Please refer to
|
||||
[#24427](https://github.com/electron/electron/issues/24427) for details.
|
||||
:::
|
||||
|
||||
```javascript {6-13,25} title='main.js (Main Process)'
|
||||
const { BrowserWindow, dialog, ipcMain } = require('electron')
|
||||
const path = require('path')
|
||||
|
||||
//...
|
||||
|
||||
async function handleFileOpen() {
|
||||
const { canceled, filePaths } = await dialog.showOpenDialog()
|
||||
if (canceled) {
|
||||
return
|
||||
} else {
|
||||
return filePaths[0]
|
||||
}
|
||||
}
|
||||
|
||||
function createWindow () {
|
||||
const mainWindow = new BrowserWindow({
|
||||
webPreferences: {
|
||||
preload: path.join(__dirname, 'preload.js')
|
||||
}
|
||||
})
|
||||
mainWindow.loadFile('index.html')
|
||||
}
|
||||
|
||||
app.whenReady(() => {
|
||||
ipcMain.handle('dialog:openFile', handleFileOpen)
|
||||
createWindow()
|
||||
})
|
||||
//...
|
||||
```
|
||||
|
||||
:::tip on channel names
|
||||
The `dialog:` prefix on the IPC channel name has no effect on the code. It only serves
|
||||
as a namespace that helps with code readability.
|
||||
:::
|
||||
|
||||
:::info
|
||||
Make sure you're loading the `index.html` and `preload.js` entry points for the following steps!
|
||||
:::
|
||||
|
||||
### 2. Expose `ipcRenderer.invoke` via preload
|
||||
|
||||
In the preload script, we expose a one-line `openFile` function that calls and returns the value of
|
||||
`ipcRenderer.invoke('dialog:openFile')`. We'll be using this API in the next step to call the
|
||||
native dialog from our renderer's user interface.
|
||||
|
||||
```javascript title='preload.js (Preload Script)'
|
||||
const { contextBridge, ipcRenderer } = require('electron')
|
||||
|
||||
contextBridge.exposeInMainWorld('electronAPI', {
|
||||
openFile: () => ipcRenderer.invoke('dialog:openFile')
|
||||
})
|
||||
```
|
||||
|
||||
:::caution Security warning
|
||||
We don't directly expose the whole `ipcRenderer.invoke` API for [security reasons]. Make sure to
|
||||
limit the renderer's access to Electron APIs as much as possible.
|
||||
:::
|
||||
|
||||
### 3. Build the renderer process UI
|
||||
|
||||
Finally, let's build the HTML file that we load into our BrowserWindow.
|
||||
|
||||
```html {10-11} title='index.html'
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<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'">
|
||||
<title>Dialog</title>
|
||||
</head>
|
||||
<body>
|
||||
<button type="button" id="btn">Open a File</button>
|
||||
File path: <strong id="filePath"></strong>
|
||||
<script src='./renderer.js'></script>
|
||||
</body>
|
||||
</html>
|
||||
```
|
||||
|
||||
The UI consists of a single `#btn` button element that will be used to trigger our preload API, and
|
||||
a `#filePath` element that will be used to display the path of the selected file. Making these
|
||||
pieces work will take a few lines of code in the renderer process script:
|
||||
|
||||
```javascript title='renderer.js (Renderer Process)'
|
||||
const btn = document.getElementById('btn')
|
||||
const filePathElement = document.getElementById('filePath')
|
||||
|
||||
btn.addEventListener('click', async () => {
|
||||
const filePath = await window.electronAPI.openFile()
|
||||
filePathElement.innerText = filePath
|
||||
})
|
||||
```
|
||||
|
||||
In the above snippet, we listen for clicks on the `#btn` button, and call our
|
||||
`window.electronAPI.openFile()` API to activate the native Open File dialog. We then display the
|
||||
selected file path in the `#filePath` element.
|
||||
|
||||
### Note: legacy approaches
|
||||
|
||||
The `ipcRenderer.invoke` API was added in Electron 7 as a developer-friendly way to tackle two-way
|
||||
IPC from the renderer process. However, there exist a couple alternative approaches to this IPC
|
||||
pattern.
|
||||
|
||||
:::warning Avoid legacy approaches if possible
|
||||
We recommend using `ipcRenderer.invoke` whenever possible. The following two-way renderer-to-main
|
||||
patterns are documented for historical purposes.
|
||||
:::
|
||||
|
||||
:::info
|
||||
For the following examples, we're calling `ipcRenderer` directly from the preload script to keep
|
||||
the code samples small.
|
||||
:::
|
||||
|
||||
#### Using `ipcRenderer.send`
|
||||
|
||||
The `ipcRenderer.send` API that we used for single-way communication can also be leveraged to
|
||||
perform two-way communication. This was the recommended way for asynchronous two-way communication
|
||||
via IPC prior to Electron 7.
|
||||
|
||||
```javascript title='preload.js (Preload Script)'
|
||||
// You can also put expose this code to the renderer
|
||||
// process with the `contextBridge` API
|
||||
const { ipcRenderer } = require('electron')
|
||||
|
||||
ipcRenderer.on('asynchronous-reply', (_event, arg) => {
|
||||
console.log(arg) // prints "pong" in the DevTools console
|
||||
})
|
||||
ipcRenderer.send('asynchronous-message', 'ping')
|
||||
```
|
||||
|
||||
```javascript title='main.js (Main Process)'
|
||||
ipcMain.on('asynchronous-message', (event, arg) => {
|
||||
console.log(arg) // prints "ping" in the Node console
|
||||
// works like `send`, but returning a message back
|
||||
// to the renderer that sent the original message
|
||||
event.reply('asynchronous-reply', 'pong')
|
||||
})
|
||||
```
|
||||
|
||||
There are a couple downsides to this approach:
|
||||
|
||||
* You need to set up a second `ipcRenderer.on` listener to handle the response in the renderer
|
||||
process. With `invoke`, you get the response value returned as a Promise to the original API call.
|
||||
* There's no obvious way to pair the `asynchronous-reply` message to the original
|
||||
`asynchronous-message` one. If you have very frequent messages going back and forth through these
|
||||
channels, you would need to add additional app code to track each call and response individually.
|
||||
|
||||
#### Using `ipcRenderer.sendSync`
|
||||
|
||||
The `ipcRenderer.sendSync` API sends a message to the main process and waits _synchronously_ for a
|
||||
response.
|
||||
|
||||
```javascript title='main.js (Main Process)'
|
||||
const { ipcMain } = require('electron')
|
||||
ipcMain.on('synchronous-message', (event, arg) => {
|
||||
console.log(arg) // prints "ping" in the Node console
|
||||
event.returnValue = 'pong'
|
||||
})
|
||||
```
|
||||
|
||||
```javascript title='preload.js (Preload Script)'
|
||||
// You can also put expose this code to the renderer
|
||||
// process with the `contextBridge` API
|
||||
const { ipcRenderer } = require('electron')
|
||||
|
||||
const result = ipcRenderer.sendSync('synchronous-message', 'ping')
|
||||
console.log(result) // prints "pong" in the DevTools console
|
||||
```
|
||||
|
||||
The structure of this code is very similar to the `invoke` model, but we recommend
|
||||
**avoiding this API** for performance reasons. Its synchronous nature means that it'll block the
|
||||
renderer process until a reply is received.
|
||||
|
||||
## Pattern 3: Main to renderer
|
||||
|
||||
When sending a message from the main process to a renderer process, you need to specify which
|
||||
renderer is receiving the message. Messages need to be sent to a renderer process
|
||||
via its [`WebContents`] instance. This WebContents instance contains a [`send`][webcontents-send] method
|
||||
that can be used in the same way as `ipcRenderer.send`.
|
||||
|
||||
To demonstrate this pattern, we'll be building a number counter controlled by the native operating
|
||||
system menu.
|
||||
|
||||
For this demo, you'll need to add code to your main process, your renderer process, and a preload
|
||||
script. The full code is below, but we'll be explaining each file individually in the following
|
||||
sections.
|
||||
|
||||
```fiddle docs/fiddles/ipc/pattern-3
|
||||
```
|
||||
|
||||
### 1. Send messages with the `webContents` module
|
||||
|
||||
For this demo, we'll need to first build a custom menu in the main process using Electron's `Menu`
|
||||
module that uses the `webContents.send` API to send an IPC message from the main process to the
|
||||
target renderer.
|
||||
|
||||
```javascript {11-26} title='main.js (Main Process)'
|
||||
const {app, BrowserWindow, Menu, ipcMain} = require('electron')
|
||||
const path = require('path')
|
||||
|
||||
function createWindow () {
|
||||
const mainWindow = new BrowserWindow({
|
||||
webPreferences: {
|
||||
preload: path.join(__dirname, 'preload.js')
|
||||
}
|
||||
})
|
||||
|
||||
const menu = Menu.buildFromTemplate([
|
||||
{
|
||||
label: app.name,
|
||||
submenu: [
|
||||
{
|
||||
click: () => mainWindow.webContents.send('update-counter', 1),
|
||||
label: 'Increment',
|
||||
},
|
||||
{
|
||||
click: () => mainWindow.webContents.send('update-counter', -1),
|
||||
label: 'Decrement',
|
||||
}
|
||||
]
|
||||
}
|
||||
])
|
||||
Menu.setApplicationMenu(menu)
|
||||
|
||||
mainWindow.loadFile('index.html')
|
||||
}
|
||||
//...
|
||||
|
||||
```
|
||||
|
||||
For the purposes of the tutorial, it's important to note that the `click` handler
|
||||
sends a message (either `1` or `-1`) to the renderer process through the `update-counter` channel.
|
||||
|
||||
```javascript
|
||||
click: () => mainWindow.webContents.send('update-counter', -1)
|
||||
```
|
||||
|
||||
:::info
|
||||
Make sure you're loading the `index.html` and `preload.js` entry points for the following steps!
|
||||
:::
|
||||
|
||||
### 2. Expose `ipcRenderer.on` via preload
|
||||
|
||||
Like in the previous renderer-to-main example, we use the `contextBridge` and `ipcRenderer`
|
||||
modules in the preload script to expose IPC functionality to the renderer process:
|
||||
|
||||
```javascript title='preload.js (Preload Script)'
|
||||
const { contextBridge, ipcRenderer } = require('electron')
|
||||
|
||||
contextBridge.exposeInMainWorld('electronAPI', {
|
||||
onUpdateCounter: (callback) => ipcRenderer.on('update-counter', callback)
|
||||
})
|
||||
```
|
||||
|
||||
After loading the preload script, your renderer process should have access to the
|
||||
`window.electronAPI.onUpdateCounter()` listener function.
|
||||
|
||||
:::caution Security warning
|
||||
We don't directly expose the whole `ipcRenderer.on` API for [security reasons]. Make sure to
|
||||
limit the renderer's access to Electron APIs as much as possible.
|
||||
:::
|
||||
|
||||
:::info
|
||||
In the case of this minimal example, you can call `ipcRenderer.on` directly in the preload script
|
||||
rather than exposing it over the context bridge.
|
||||
|
||||
```javascript title='preload.js (Preload Script)'
|
||||
const { ipcRenderer } = require('electron')
|
||||
|
||||
window.addEventListener('DOMContentLoaded', () => {
|
||||
const counter = document.getElementById('counter')
|
||||
ipcRenderer.on('update-counter', (_event, value) => {
|
||||
const oldValue = Number(counter.innerText)
|
||||
const newValue = oldValue + value
|
||||
counter.innerText = newValue
|
||||
})
|
||||
})
|
||||
```
|
||||
|
||||
However, this approach has limited flexibility compared to exposing your preload APIs
|
||||
over the context bridge, since your listener can't directly interact with your renderer code.
|
||||
:::
|
||||
|
||||
### 3. Build the renderer process UI
|
||||
|
||||
To tie it all together, we'll create an interface in the loaded HTML file that contains a
|
||||
`#counter` element that we'll use to display the values:
|
||||
|
||||
```html {10} title='index.html'
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<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'">
|
||||
<title>Menu Counter</title>
|
||||
</head>
|
||||
<body>
|
||||
Current value: <strong id="counter">0</strong>
|
||||
<script src="./renderer.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
```
|
||||
|
||||
Finally, to make the values update in the HTML document, we'll add a few lines of DOM manipulation
|
||||
so that the value of the `#counter` element is updated whenever we fire an `update-counter` event.
|
||||
|
||||
```javascript title='renderer.js (Renderer Process)'
|
||||
const counter = document.getElementById('counter')
|
||||
|
||||
window.electronAPI.onUpdateCounter((_event, value) => {
|
||||
const oldValue = Number(counter.innerText)
|
||||
const newValue = oldValue + value
|
||||
counter.innerText = newValue
|
||||
})
|
||||
```
|
||||
|
||||
In the above code, we're passing in a callback to the `window.electronAPI.onUpdateCounter` function
|
||||
exposed from our preload script. The second `value` parameter corresponds to the `1` or `-1` we
|
||||
were passing in from the `webContents.send` call from the native menu.
|
||||
|
||||
### Optional: returning a reply
|
||||
|
||||
There's no equivalent for `ipcRenderer.invoke` for main-to-renderer IPC. Instead, you can
|
||||
send a reply back to the main process from within the `ipcRenderer.on` callback.
|
||||
|
||||
We can demonstrate this with slight modifications to the code from the previous example. In the
|
||||
renderer process, use the `event` parameter to send a reply back to the main process through the
|
||||
`counter-value` channel.
|
||||
|
||||
```javascript title='renderer.js (Renderer Process)'
|
||||
const counter = document.getElementById('counter')
|
||||
|
||||
window.electronAPI.onUpdateCounter((event, value) => {
|
||||
const oldValue = Number(counter.innerText)
|
||||
const newValue = oldValue + value
|
||||
counter.innerText = newValue
|
||||
event.sender.send('counter-value', newValue)
|
||||
})
|
||||
```
|
||||
|
||||
In the main process, listen for `counter-value` events and handle them appropriately.
|
||||
|
||||
```javascript title='main.js (Main Process)'
|
||||
//...
|
||||
ipcMain.on('counter-value', (_event, value) => {
|
||||
console.log(value) // will print value to Node console
|
||||
})
|
||||
//...
|
||||
```
|
||||
|
||||
## Pattern 4: Renderer to renderer
|
||||
|
||||
There's no direct way to send messages between renderer processes in Electron using the `ipcMain`
|
||||
and `ipcRenderer` modules. To achieve this, you have two options:
|
||||
|
||||
* Use the main process as a message broker between renderers. This would involve sending a message
|
||||
from one renderer to the main process, which would forward the message to the other renderer.
|
||||
* Pass a [MessagePort] from the main process to both renderers. This will allow direct communication
|
||||
between renderers after the initial setup.
|
||||
|
||||
## Object serialization
|
||||
|
||||
Electron's IPC implementation uses the HTML standard
|
||||
[Structured Clone Algorithm][sca] to serialize objects passed between processes, meaning that
|
||||
only certain types of objects can be passed through IPC channels.
|
||||
|
||||
In particular, DOM objects (e.g. `Element`, `Location` and `DOMMatrix`), Node.js objects
|
||||
backed by C++ classes (e.g. `process.env`, some members of `Stream`), and Electron objects
|
||||
backed by C++ classes (e.g. `WebContents`, `BrowserWindow` and `WebFrame`) are not serializable
|
||||
with Structured Clone.
|
||||
|
||||
[context isolation tutorial]: context-isolation.md
|
||||
[security reasons]: ./context-isolation.md#security-considerations
|
||||
[`ipcMain`]: ../api/ipc-main.md
|
||||
[`ipcMain.handle`]: ../api/ipc-main.md#ipcmainhandlechannel-listener
|
||||
[`ipcMain.on`]: ../api/ipc-main.md
|
||||
[IpcMainEvent]: ../api/structures/ipc-main-event.md
|
||||
[`ipcRenderer`]: ../api/ipc-renderer.md
|
||||
[`ipcRenderer.invoke`]: ../api/ipc-renderer.md#ipcrendererinvokechannel-args
|
||||
[`ipcRenderer.send`]: ../api/ipc-renderer.md
|
||||
[MessagePort]: ./message-ports.md
|
||||
[preload script]: process-model.md#preload-scripts
|
||||
[process model docs]: process-model.md
|
||||
[sca]: https://developer.mozilla.org/en-US/docs/Web/API/Web_Workers_API/Structured_clone_algorithm
|
||||
[`WebContents`]: ../api/web-contents.md
|
||||
[webcontents-send]: ../api/web-contents.md#contentssendchannel-args
|
||||
@@ -175,6 +175,7 @@ template("electron_paks") {
|
||||
source_patterns = [
|
||||
"${root_gen_dir}/chrome/platform_locale_settings_",
|
||||
"${root_gen_dir}/components/strings/components_strings_",
|
||||
"${root_gen_dir}/third_party/blink/public/strings/blink_accessibility_strings_",
|
||||
"${root_gen_dir}/third_party/blink/public/strings/blink_strings_",
|
||||
"${root_gen_dir}/device/bluetooth/strings/bluetooth_strings_",
|
||||
"${root_gen_dir}/services/strings/services_strings_",
|
||||
@@ -188,6 +189,7 @@ template("electron_paks") {
|
||||
"//device/bluetooth/strings",
|
||||
"//services/strings",
|
||||
"//third_party/blink/public/strings",
|
||||
"//third_party/blink/public/strings:accessibility_strings",
|
||||
"//ui/strings:app_locale_settings",
|
||||
"//ui/strings:ax_strings",
|
||||
"//ui/strings:ui_strings",
|
||||
|
||||
@@ -145,4 +145,16 @@
|
||||
</message>
|
||||
<message name="IDS_HID_CHOOSER_ITEM_WITHOUT_NAME" desc="User option displaying the device IDs for a Human Interface Device (HID) without a device name.">
|
||||
Unknown Device (<ph name="DEVICE_ID">$1<ex>1234:abcd</ex></ph>) </message>
|
||||
<if expr="is_win">
|
||||
<then>
|
||||
<message name="IDS_AX_UNLABELED_IMAGE_ROLE_DESCRIPTION" desc="Accessibility role description for a graphic (image) on a web page or PDF that does not have a description for blind users." is_accessibility_with_no_ui="true">
|
||||
Unlabeled graphic
|
||||
</message>
|
||||
</then>
|
||||
<else>
|
||||
<message name="IDS_AX_UNLABELED_IMAGE_ROLE_DESCRIPTION" desc="Accessibility role description for an image on a web page or PDF that does not have a description for blind users." is_accessibility_with_no_ui="true">
|
||||
Unlabeled image
|
||||
</message>
|
||||
</else>
|
||||
</if>
|
||||
</grit-part>
|
||||
|
||||
@@ -53,8 +53,6 @@ filenames = {
|
||||
"shell/browser/ui/views/global_menu_bar_x11.h",
|
||||
"shell/browser/ui/x/event_disabler.cc",
|
||||
"shell/browser/ui/x/event_disabler.h",
|
||||
"shell/browser/ui/x/window_state_watcher.cc",
|
||||
"shell/browser/ui/x/window_state_watcher.h",
|
||||
"shell/browser/ui/x/x_window_utils.cc",
|
||||
"shell/browser/ui/x/x_window_utils.h",
|
||||
]
|
||||
@@ -350,6 +348,8 @@ filenames = {
|
||||
"shell/browser/child_web_contents_tracker.h",
|
||||
"shell/browser/cookie_change_notifier.cc",
|
||||
"shell/browser/cookie_change_notifier.h",
|
||||
"shell/browser/electron_api_ipc_handler_impl.cc",
|
||||
"shell/browser/electron_api_ipc_handler_impl.h",
|
||||
"shell/browser/electron_autofill_driver.cc",
|
||||
"shell/browser/electron_autofill_driver.h",
|
||||
"shell/browser/electron_autofill_driver_factory.cc",
|
||||
@@ -358,8 +358,6 @@ filenames = {
|
||||
"shell/browser/electron_browser_client.h",
|
||||
"shell/browser/electron_browser_context.cc",
|
||||
"shell/browser/electron_browser_context.h",
|
||||
"shell/browser/electron_browser_handler_impl.cc",
|
||||
"shell/browser/electron_browser_handler_impl.h",
|
||||
"shell/browser/electron_browser_main_parts.cc",
|
||||
"shell/browser/electron_browser_main_parts.h",
|
||||
"shell/browser/electron_download_manager_delegate.cc",
|
||||
@@ -376,6 +374,8 @@ filenames = {
|
||||
"shell/browser/electron_quota_permission_context.h",
|
||||
"shell/browser/electron_speech_recognition_manager_delegate.cc",
|
||||
"shell/browser/electron_speech_recognition_manager_delegate.h",
|
||||
"shell/browser/electron_web_contents_utility_handler_impl.cc",
|
||||
"shell/browser/electron_web_contents_utility_handler_impl.h",
|
||||
"shell/browser/electron_web_ui_controller_factory.cc",
|
||||
"shell/browser/electron_web_ui_controller_factory.h",
|
||||
"shell/browser/event_emitter_mixin.cc",
|
||||
|
||||
@@ -30,11 +30,13 @@ const getOrCreateArchive = (archivePath: string) => {
|
||||
return cachedArchives.get(archivePath);
|
||||
}
|
||||
|
||||
const newArchive = asar.createArchive(archivePath);
|
||||
if (!newArchive) return null;
|
||||
|
||||
cachedArchives.set(archivePath, newArchive);
|
||||
return newArchive;
|
||||
try {
|
||||
const newArchive = new asar.Archive(archivePath);
|
||||
cachedArchives.set(archivePath, newArchive);
|
||||
return newArchive;
|
||||
} catch {
|
||||
return null;
|
||||
}
|
||||
};
|
||||
|
||||
const asarRe = /\.asar/i;
|
||||
|
||||
@@ -72,7 +72,10 @@ BrowserWindow.getAllWindows = () => {
|
||||
|
||||
BrowserWindow.getFocusedWindow = () => {
|
||||
for (const window of BrowserWindow.getAllWindows()) {
|
||||
if (window.isFocused() || window.isDevToolsFocused()) return window;
|
||||
const hasWC = window.webContents && !window.webContents.isDestroyed();
|
||||
if (!window.isDestroyed() && hasWC) {
|
||||
if (window.isFocused() || window.isDevToolsFocused()) return window;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
};
|
||||
|
||||
@@ -617,6 +617,7 @@ WebContents.prototype._init = function () {
|
||||
});
|
||||
|
||||
this.on('-ipc-ports' as any, function (event: Electron.IpcMainEvent, internal: boolean, channel: string, message: any, ports: any[]) {
|
||||
addSenderFrameToEvent(event);
|
||||
event.ports = ports.map(p => new MessagePortMain(p));
|
||||
ipcMain.emit(channel, event, message);
|
||||
});
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
|
||||
// Rip global off of window (which is also global) so that webpack doesn't
|
||||
// auto replace it with a looped reference to this file
|
||||
const _global = typeof globalThis !== 'undefined' ? globalThis.global : (self as any || window as any).global as NodeJS.Global;
|
||||
const _global = typeof globalThis !== 'undefined' ? globalThis.global : (self || window).global;
|
||||
const process = _global.process;
|
||||
const Buffer = _global.Buffer;
|
||||
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"@electron/get": "^1.13.0",
|
||||
"@types/node": "^14.6.2",
|
||||
"@types/node": "^16.11.26",
|
||||
"extract-zip": "^1.0.3"
|
||||
},
|
||||
"engines": {
|
||||
|
||||
16
package.json
16
package.json
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "electron",
|
||||
"version": "18.0.0-beta.2",
|
||||
"version": "18.1.0",
|
||||
"repository": "https://github.com/electron/electron",
|
||||
"description": "Build cross platform desktop apps with JavaScript, HTML, and CSS",
|
||||
"devDependencies": {
|
||||
@@ -14,12 +14,12 @@
|
||||
"@types/chai": "^4.2.12",
|
||||
"@types/chai-as-promised": "^7.1.3",
|
||||
"@types/dirty-chai": "^2.0.2",
|
||||
"@types/express": "^4.17.7",
|
||||
"@types/express": "^4.17.13",
|
||||
"@types/fs-extra": "^9.0.1",
|
||||
"@types/klaw": "^3.0.1",
|
||||
"@types/minimist": "^1.2.0",
|
||||
"@types/mocha": "^7.0.2",
|
||||
"@types/node": "^14.6.2",
|
||||
"@types/node": "^16.11.26",
|
||||
"@types/semver": "^7.3.3",
|
||||
"@types/send": "^0.14.5",
|
||||
"@types/split": "^1.0.0",
|
||||
@@ -27,7 +27,7 @@
|
||||
"@types/temp": "^0.8.34",
|
||||
"@types/uuid": "^3.4.6",
|
||||
"@types/webpack": "^4.41.21",
|
||||
"@types/webpack-env": "^1.15.2",
|
||||
"@types/webpack-env": "^1.16.3",
|
||||
"@typescript-eslint/eslint-plugin": "^4.4.1",
|
||||
"@typescript-eslint/parser": "^4.4.1",
|
||||
"asar": "^3.1.0",
|
||||
@@ -78,14 +78,14 @@
|
||||
"generate-version-json": "node script/generate-version-json.js",
|
||||
"lint": "node ./script/lint.js && npm run lint:clang-format && npm run lint:docs",
|
||||
"lint:js": "node ./script/lint.js --js",
|
||||
"lint:clang-format": "python script/run-clang-format.py -r -c shell/ || (echo \"\\nCode not formatted correctly.\" && exit 1)",
|
||||
"lint:clang-format": "python3 script/run-clang-format.py -r -c shell/ || (echo \"\\nCode not formatted correctly.\" && exit 1)",
|
||||
"lint:clang-tidy": "ts-node ./script/run-clang-tidy.ts",
|
||||
"lint:cpp": "node ./script/lint.js --cc",
|
||||
"lint:objc": "node ./script/lint.js --objc",
|
||||
"lint:py": "node ./script/lint.js --py",
|
||||
"lint:gn": "node ./script/lint.js --gn",
|
||||
"lint:docs": "remark docs -qf && npm run lint:js-in-markdown && npm run create-typescript-definitions && npm run lint:docs-relative-links && npm run lint:markdownlint",
|
||||
"lint:docs-relative-links": "python ./script/check-relative-doc-links.py",
|
||||
"lint:docs-relative-links": "python3 ./script/check-relative-doc-links.py",
|
||||
"lint:markdownlint": "markdownlint \"*.md\" \"docs/**/*.md\"",
|
||||
"lint:js-in-markdown": "standard-markdown docs",
|
||||
"create-api-json": "electron-docs-parser --dir=./",
|
||||
@@ -116,14 +116,14 @@
|
||||
"ts-node script/gen-filenames.ts"
|
||||
],
|
||||
"*.{cc,mm,c,h}": [
|
||||
"python script/run-clang-format.py -r -c --fix"
|
||||
"python3 script/run-clang-format.py -r -c --fix"
|
||||
],
|
||||
"*.md": [
|
||||
"npm run lint:docs"
|
||||
],
|
||||
"*.{gn,gni}": [
|
||||
"npm run gn-check",
|
||||
"python script/run-gn-format.py"
|
||||
"python3 script/run-gn-format.py"
|
||||
],
|
||||
"*.py": [
|
||||
"node script/lint.js --py --fix --only --"
|
||||
|
||||
@@ -66,7 +66,6 @@ feat_enable_offscreen_rendering_with_viz_compositor.patch
|
||||
gpu_notify_when_dxdiag_request_fails.patch
|
||||
feat_allow_embedders_to_add_observers_on_created_hunspell.patch
|
||||
feat_add_onclose_to_messageport.patch
|
||||
ui_gtk_public_header.patch
|
||||
allow_in-process_windows_to_have_different_web_prefs.patch
|
||||
refactor_expose_cursor_changes_to_the_webcontentsobserver.patch
|
||||
crash_allow_setting_more_options.patch
|
||||
@@ -112,5 +111,7 @@ feat_add_data_transfer_to_requestsingleinstancelock.patch
|
||||
fix_crash_when_saving_edited_pdf_files.patch
|
||||
port_autofill_colors_to_the_color_pipeline.patch
|
||||
build_disable_partition_alloc_on_mac.patch
|
||||
build_disable_thin_lto_on_mac.patch
|
||||
fix_non-client_mouse_tracking_and_message_bubbling_on_windows.patch
|
||||
remove_incorrect_width_height_adjustments.patch
|
||||
introduce_ozoneplatform_electron_can_call_x11_property.patch
|
||||
make_gtk_getlibgtk_public.patch
|
||||
|
||||
@@ -85,10 +85,10 @@ index 14d4a00293ab0b11e733676844ce483992d6cd8e..c6c2dbb9dddd1eaa21e8c7b276d871a3
|
||||
// Visibility -----------------------------------------------------------
|
||||
|
||||
diff --git a/third_party/blink/renderer/core/exported/web_view_impl.cc b/third_party/blink/renderer/core/exported/web_view_impl.cc
|
||||
index 8cdffac8ecb9ed2c6892f1e975a953846e7e3a5c..7e7927c7258963bd95a2c064ef85e410f4d2571d 100644
|
||||
index b9d5a13bcdf981064f9970fdb8017fed5f93b35e..182f70b2b3bd9cbc6548d4c17caad797e5dad0ce 100644
|
||||
--- a/third_party/blink/renderer/core/exported/web_view_impl.cc
|
||||
+++ b/third_party/blink/renderer/core/exported/web_view_impl.cc
|
||||
@@ -3659,6 +3659,13 @@ PageScheduler* WebViewImpl::Scheduler() const {
|
||||
@@ -3668,6 +3668,13 @@ PageScheduler* WebViewImpl::Scheduler() const {
|
||||
return GetPage()->GetPageScheduler();
|
||||
}
|
||||
|
||||
@@ -102,7 +102,7 @@ index 8cdffac8ecb9ed2c6892f1e975a953846e7e3a5c..7e7927c7258963bd95a2c064ef85e410
|
||||
void WebViewImpl::SetVisibilityState(
|
||||
mojom::blink::PageVisibilityState visibility_state,
|
||||
bool is_initial_state) {
|
||||
@@ -3670,7 +3677,8 @@ void WebViewImpl::SetVisibilityState(
|
||||
@@ -3679,7 +3686,8 @@ void WebViewImpl::SetVisibilityState(
|
||||
}
|
||||
GetPage()->SetVisibilityState(visibility_state, is_initial_state);
|
||||
GetPage()->GetPageScheduler()->SetPageVisible(
|
||||
|
||||
@@ -15,7 +15,7 @@ Refs changes in:
|
||||
This patch reverts the changes to fix associated crashes in Electron.
|
||||
|
||||
diff --git a/third_party/blink/renderer/core/frame/frame.cc b/third_party/blink/renderer/core/frame/frame.cc
|
||||
index 2b0c8720866b45c2a83d639533cb4c3e5dbb70e0..97c251cdc310eb22859efb1ba3ca6312a3236fa5 100644
|
||||
index 09e6436422169ac05d5f0561f12984c86dc7af5e..7b2263f4c7fa2dffbaf5b630f4d5a83d9b68f9a5 100644
|
||||
--- a/third_party/blink/renderer/core/frame/frame.cc
|
||||
+++ b/third_party/blink/renderer/core/frame/frame.cc
|
||||
@@ -122,14 +122,6 @@ bool Frame::Detach(FrameDetachType type) {
|
||||
|
||||
@@ -9,7 +9,7 @@ and can be removed when the crash in fork is resolved.
|
||||
Related issue: https://github.com/electron/electron/issues/32718
|
||||
|
||||
diff --git a/base/allocator/allocator.gni b/base/allocator/allocator.gni
|
||||
index 56acfed89ec4ad4ee568a1b517923efa4b4e9c1f..a1da35a84f896d158ac88368ff6d95025a23ff95 100644
|
||||
index 8fa0c36007a0ae0e4553709d27a8231efb08459b..3c4f93fc98b5002572adc78cb9a21b3e78c9f3e0 100644
|
||||
--- a/base/allocator/allocator.gni
|
||||
+++ b/base/allocator/allocator.gni
|
||||
@@ -20,7 +20,7 @@ _disable_partition_alloc = is_component_build || (is_win && is_debug)
|
||||
|
||||
@@ -1,22 +0,0 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: VerteDinde <vertedinde@electronjs.org>
|
||||
Date: Tue, 1 Mar 2022 11:31:59 -0800
|
||||
Subject: build: disable thin lto on mac
|
||||
|
||||
Ths build disables thin lto for mac, in order to preserve
|
||||
disk space on mac without breaking win-ia32.
|
||||
The patch can be removed when we have more disk space on CircleCI
|
||||
|
||||
diff --git a/build/config/compiler/compiler.gni b/build/config/compiler/compiler.gni
|
||||
index 9d25c10587c7ab4e2053f8f69aef3f135ef8e9f9..8d8b8d13c62da1fdd051019c8b726de7d1783113 100644
|
||||
--- a/build/config/compiler/compiler.gni
|
||||
+++ b/build/config/compiler/compiler.gni
|
||||
@@ -74,7 +74,7 @@ declare_args() {
|
||||
use_thin_lto =
|
||||
is_cfi ||
|
||||
(is_clang && is_official_build && chrome_pgo_phase != 1 &&
|
||||
- (is_linux || is_win || is_mac ||
|
||||
+ (is_linux || is_win ||
|
||||
(is_android && target_os != "chromeos") ||
|
||||
((is_chromeos_ash || is_chromeos_lacros) && is_chromeos_device)))
|
||||
|
||||
@@ -11,7 +11,7 @@ if we ever align our .pak file generation with Chrome we can remove this
|
||||
patch.
|
||||
|
||||
diff --git a/chrome/BUILD.gn b/chrome/BUILD.gn
|
||||
index 7caaf66cad9d5b9f787cea0d49c32c26801571c2..f45691888b74643189b956928fdc796bfc5bcee3 100644
|
||||
index f2c4feac76e96575de3627b7e8f2373b4fb30411..f5fa6b21594c97a08d1aefd790a4846d9b3e1a45 100644
|
||||
--- a/chrome/BUILD.gn
|
||||
+++ b/chrome/BUILD.gn
|
||||
@@ -171,11 +171,16 @@ if (!is_android && !is_mac) {
|
||||
@@ -33,10 +33,10 @@ index 7caaf66cad9d5b9f787cea0d49c32c26801571c2..f45691888b74643189b956928fdc796b
|
||||
"//base",
|
||||
"//build:branding_buildflags",
|
||||
diff --git a/chrome/browser/BUILD.gn b/chrome/browser/BUILD.gn
|
||||
index 6a40a73520a951d7c6fd06cbd07329a40ff41544..9ca837d995160d57c7efb51c54cf27283b11b20e 100644
|
||||
index 492cd8e11e28e0b427aca227665295a3052af765..760d2171c5083820fbbf66ce5d7d3c80930b9e88 100644
|
||||
--- a/chrome/browser/BUILD.gn
|
||||
+++ b/chrome/browser/BUILD.gn
|
||||
@@ -4502,7 +4502,7 @@ static_library("browser") {
|
||||
@@ -4501,7 +4501,7 @@ static_library("browser") {
|
||||
|
||||
# On Windows, the hashes are embedded in //chrome:chrome_initial rather
|
||||
# than here in :chrome_dll.
|
||||
@@ -46,10 +46,10 @@ index 6a40a73520a951d7c6fd06cbd07329a40ff41544..9ca837d995160d57c7efb51c54cf2728
|
||||
sources += [ "certificate_viewer_stub.cc" ]
|
||||
}
|
||||
diff --git a/chrome/test/BUILD.gn b/chrome/test/BUILD.gn
|
||||
index 7be0809cfd3a08a87b29256241bc11a33abd3d17..e3c85fd9f550da204e36091bad256b1c2400ade8 100644
|
||||
index 028d269850e66db444591cda7005a0f8434193e9..cc0d14cd9798c6bbee80581c95eb8281ce7fb6ba 100644
|
||||
--- a/chrome/test/BUILD.gn
|
||||
+++ b/chrome/test/BUILD.gn
|
||||
@@ -5719,7 +5719,6 @@ test("unit_tests") {
|
||||
@@ -5722,7 +5722,6 @@ test("unit_tests") {
|
||||
|
||||
deps += [
|
||||
"//chrome:other_version",
|
||||
@@ -57,7 +57,7 @@ index 7be0809cfd3a08a87b29256241bc11a33abd3d17..e3c85fd9f550da204e36091bad256b1c
|
||||
"//chrome//services/util_win:unit_tests",
|
||||
"//chrome/app:chrome_dll_resources",
|
||||
"//chrome/browser:chrome_process_finder",
|
||||
@@ -5742,6 +5741,10 @@ test("unit_tests") {
|
||||
@@ -5745,6 +5744,10 @@ test("unit_tests") {
|
||||
"//ui/resources",
|
||||
]
|
||||
|
||||
@@ -68,7 +68,7 @@ index 7be0809cfd3a08a87b29256241bc11a33abd3d17..e3c85fd9f550da204e36091bad256b1c
|
||||
ldflags = [
|
||||
"/DELAYLOAD:api-ms-win-core-winrt-error-l1-1-0.dll",
|
||||
"/DELAYLOAD:api-ms-win-core-winrt-l1-1-0.dll",
|
||||
@@ -6428,7 +6431,6 @@ test("unit_tests") {
|
||||
@@ -6438,7 +6441,6 @@ test("unit_tests") {
|
||||
}
|
||||
|
||||
deps += [
|
||||
@@ -76,7 +76,7 @@ index 7be0809cfd3a08a87b29256241bc11a33abd3d17..e3c85fd9f550da204e36091bad256b1c
|
||||
"//chrome/browser:cart_db_content_proto",
|
||||
"//chrome/browser:coupon_db_content_proto",
|
||||
"//chrome/browser/media/router:test_support",
|
||||
@@ -6473,6 +6475,11 @@ test("unit_tests") {
|
||||
@@ -6483,6 +6485,11 @@ test("unit_tests") {
|
||||
"//ui/native_theme:test_support",
|
||||
"//ui/webui/resources/js/browser_command:mojo_bindings",
|
||||
]
|
||||
|
||||
@@ -32,7 +32,7 @@ index 7915346430db72d18474d7a011b8dc7637c3f281..cd736d988f9c5e37dc24c724268fe115
|
||||
]
|
||||
if (is_linux && !is_chromeos) {
|
||||
diff --git a/buildtools/third_party/libc++abi/BUILD.gn b/buildtools/third_party/libc++abi/BUILD.gn
|
||||
index 1b0bea340d6e8aec153add6f184e382172916f8b..f5a8193e6b72f4cc039b95783be7d254b93911d8 100644
|
||||
index 40f1285f14c0843405e0ee51879b8742285a006d..5be895d3e36df53a5960006a1513f1322400fd23 100644
|
||||
--- a/buildtools/third_party/libc++abi/BUILD.gn
|
||||
+++ b/buildtools/third_party/libc++abi/BUILD.gn
|
||||
@@ -4,7 +4,7 @@
|
||||
|
||||
@@ -9,10 +9,10 @@ potentially prevent a window from being created.
|
||||
TODO(loc): this patch is currently broken.
|
||||
|
||||
diff --git a/content/browser/renderer_host/render_frame_host_impl.cc b/content/browser/renderer_host/render_frame_host_impl.cc
|
||||
index eba372243a31d08c251ad3367d24999277a8289b..713e2883139bca4bb56dcc7e3efcf6d6dfc4a02b 100644
|
||||
index 36a8fa8d3e981707e6688379813560ba94209ab3..e36a19c847912b007a94464321bb83b15bdcdafd 100644
|
||||
--- a/content/browser/renderer_host/render_frame_host_impl.cc
|
||||
+++ b/content/browser/renderer_host/render_frame_host_impl.cc
|
||||
@@ -6703,6 +6703,7 @@ void RenderFrameHostImpl::CreateNewWindow(
|
||||
@@ -6706,6 +6706,7 @@ void RenderFrameHostImpl::CreateNewWindow(
|
||||
last_committed_origin_, params->window_container_type,
|
||||
params->target_url, params->referrer.To<Referrer>(),
|
||||
params->frame_name, params->disposition, *params->features,
|
||||
@@ -21,7 +21,7 @@ index eba372243a31d08c251ad3367d24999277a8289b..713e2883139bca4bb56dcc7e3efcf6d6
|
||||
&no_javascript_access);
|
||||
|
||||
diff --git a/content/browser/web_contents/web_contents_impl.cc b/content/browser/web_contents/web_contents_impl.cc
|
||||
index 3fe9e1e4918ef65194621661c9c7c650089229fa..c8e49eeaca8b31479aa908be9c349ccd625e9e51 100644
|
||||
index f28855f738e3b98196813a6d306ba30f7f294cb2..5afb01c9de253053243a1add87269a9d848b5297 100644
|
||||
--- a/content/browser/web_contents/web_contents_impl.cc
|
||||
+++ b/content/browser/web_contents/web_contents_impl.cc
|
||||
@@ -3925,6 +3925,14 @@ FrameTree* WebContentsImpl::CreateNewWindow(
|
||||
@@ -68,10 +68,10 @@ index ace032dc2ffac27fbdddee5a4b13c3c3e36ba5ae..80f7dd56fdaa94a9880995b2b5393af0
|
||||
|
||||
// Operation result when the renderer asks the browser to create a new window.
|
||||
diff --git a/content/public/browser/content_browser_client.cc b/content/public/browser/content_browser_client.cc
|
||||
index 85ed8b5e84813c10f97c5785d906a87455f8f67e..a11d5ba888c1489870875c859ec9eb79c67f94b7 100644
|
||||
index a0a9f51b7e62b13f62467f14e3e9245cb6fc8d84..329cbc6f8c822c6f6deac4f341baec41228dca7b 100644
|
||||
--- a/content/public/browser/content_browser_client.cc
|
||||
+++ b/content/public/browser/content_browser_client.cc
|
||||
@@ -571,6 +571,8 @@ bool ContentBrowserClient::CanCreateWindow(
|
||||
@@ -577,6 +577,8 @@ bool ContentBrowserClient::CanCreateWindow(
|
||||
const std::string& frame_name,
|
||||
WindowOpenDisposition disposition,
|
||||
const blink::mojom::WindowFeatures& features,
|
||||
@@ -81,10 +81,10 @@ index 85ed8b5e84813c10f97c5785d906a87455f8f67e..a11d5ba888c1489870875c859ec9eb79
|
||||
bool opener_suppressed,
|
||||
bool* no_javascript_access) {
|
||||
diff --git a/content/public/browser/content_browser_client.h b/content/public/browser/content_browser_client.h
|
||||
index 47527cb2e434f771f5aeb5099432ae86a0ad06ea..2fe1462a2cd92a731a5816b5fc22b059bad92fe8 100644
|
||||
index 3bbb6a39eeb719b94d0e212ea8da5051ff55d441..ceb2bb900e122840505aa8d3911923cffc9a907e 100644
|
||||
--- a/content/public/browser/content_browser_client.h
|
||||
+++ b/content/public/browser/content_browser_client.h
|
||||
@@ -168,6 +168,7 @@ class NetworkService;
|
||||
@@ -169,6 +169,7 @@ class NetworkService;
|
||||
class TrustedURLLoaderHeaderClient;
|
||||
} // namespace mojom
|
||||
struct ResourceRequest;
|
||||
@@ -92,7 +92,7 @@ index 47527cb2e434f771f5aeb5099432ae86a0ad06ea..2fe1462a2cd92a731a5816b5fc22b059
|
||||
} // namespace network
|
||||
|
||||
namespace sandbox {
|
||||
@@ -950,6 +951,8 @@ class CONTENT_EXPORT ContentBrowserClient {
|
||||
@@ -960,6 +961,8 @@ class CONTENT_EXPORT ContentBrowserClient {
|
||||
const std::string& frame_name,
|
||||
WindowOpenDisposition disposition,
|
||||
const blink::mojom::WindowFeatures& features,
|
||||
@@ -220,10 +220,10 @@ index 84d32491a56528a84b4395fba1d54cdbb38d522b..09998a83c449ef8cd9f360fbcdcf7edc
|
||||
|
||||
} // namespace blink
|
||||
diff --git a/third_party/blink/renderer/core/frame/local_dom_window.cc b/third_party/blink/renderer/core/frame/local_dom_window.cc
|
||||
index 12658b5c9ca6bc10cffd2c9e8ddf45bac697e75c..284f3ed1513009092ecdf2be6ff87641cc404cd9 100644
|
||||
index 030cc373443766b6485a888f5627885f535e06fc..7bc60b17a0f1aeb208f6d7d85cd6fa537c44c54a 100644
|
||||
--- a/third_party/blink/renderer/core/frame/local_dom_window.cc
|
||||
+++ b/third_party/blink/renderer/core/frame/local_dom_window.cc
|
||||
@@ -2051,6 +2051,7 @@ DOMWindow* LocalDOMWindow::open(v8::Isolate* isolate,
|
||||
@@ -2050,6 +2050,7 @@ DOMWindow* LocalDOMWindow::open(v8::Isolate* isolate,
|
||||
|
||||
WebWindowFeatures window_features =
|
||||
GetWindowFeaturesFromString(features, incumbent_window);
|
||||
|
||||
@@ -246,7 +246,7 @@ index c6bd5c19f8a7ceec17c9e32af5296a9617f3a619..02199b439fba7fdc617b7f7980d958b7
|
||||
void AddNewContents(content::WebContents* source,
|
||||
std::unique_ptr<content::WebContents> new_contents,
|
||||
diff --git a/content/browser/web_contents/web_contents_impl.cc b/content/browser/web_contents/web_contents_impl.cc
|
||||
index 5c63a024827359ccf697d0b7fc8fa2092eb107b7..3da88b5831717c979373c064b4c1520c28d4fd98 100644
|
||||
index 1734f93f7d06faf2c28d65d23bbc6c17f72e0b59..b19517ceafabde2ad88e83af97b9768b8a03fb60 100644
|
||||
--- a/content/browser/web_contents/web_contents_impl.cc
|
||||
+++ b/content/browser/web_contents/web_contents_impl.cc
|
||||
@@ -3873,8 +3873,7 @@ FrameTree* WebContentsImpl::CreateNewWindow(
|
||||
|
||||
@@ -7,7 +7,7 @@ spellchecker uses a few IDS_ resources. We need to load these from
|
||||
Electrons grit header instead of Chromes
|
||||
|
||||
diff --git a/chrome/browser/BUILD.gn b/chrome/browser/BUILD.gn
|
||||
index ec55c3f97988a7de06a738e61e389ba07712ad4e..6a40a73520a951d7c6fd06cbd07329a40ff41544 100644
|
||||
index 9917fcf771ecbfceaba4c02164de620d2aaf0775..492cd8e11e28e0b427aca227665295a3052af765 100644
|
||||
--- a/chrome/browser/BUILD.gn
|
||||
+++ b/chrome/browser/BUILD.gn
|
||||
@@ -7088,6 +7088,7 @@ static_library("browser") {
|
||||
|
||||
@@ -20,10 +20,10 @@ to deal with color spaces. That is being tracked at
|
||||
https://crbug.com/634542 and https://crbug.com/711107.
|
||||
|
||||
diff --git a/cc/trees/layer_tree_host_impl.cc b/cc/trees/layer_tree_host_impl.cc
|
||||
index 61ab59e0d97a392ae18c1d7ad7dd606b5cd1c567..2a899818ebb67ba4fc06ccbcff3ee03f6b83c0e6 100644
|
||||
index 3824e500fd88105e9c6d459f23097b2b4f0686ed..927ede7608a5c6992e9f9fb05e4b8e43b7e10cf8 100644
|
||||
--- a/cc/trees/layer_tree_host_impl.cc
|
||||
+++ b/cc/trees/layer_tree_host_impl.cc
|
||||
@@ -1882,6 +1882,9 @@ void LayerTreeHostImpl::SetIsLikelyToRequireADraw(
|
||||
@@ -1889,6 +1889,9 @@ void LayerTreeHostImpl::SetIsLikelyToRequireADraw(
|
||||
TargetColorParams LayerTreeHostImpl::GetTargetColorParams(
|
||||
gfx::ContentColorUsage content_color_usage) const {
|
||||
TargetColorParams params;
|
||||
@@ -240,10 +240,10 @@ index f5d73922086b5b27907fd393d4d4204a574c3b25..5b09f5ef5f04b519ed4148498c82d003
|
||||
sandbox::policy::switches::kGpuSandboxAllowSysVShm,
|
||||
sandbox::policy::switches::kGpuSandboxFailuresFatal,
|
||||
diff --git a/content/browser/renderer_host/render_process_host_impl.cc b/content/browser/renderer_host/render_process_host_impl.cc
|
||||
index ac9570fa3d9cb3b0026f70465e5b21ac7778c3df..acc0e121e7746da397cfab07b3707de7ae9a3143 100644
|
||||
index 5f2451eefad211c85460eb457ad3d6e184540d59..d9d8352c6b1b8db8d86ad1ed1d4a3d300a999fa6 100644
|
||||
--- a/content/browser/renderer_host/render_process_host_impl.cc
|
||||
+++ b/content/browser/renderer_host/render_process_host_impl.cc
|
||||
@@ -194,6 +194,7 @@
|
||||
@@ -196,6 +196,7 @@
|
||||
#include "ui/accessibility/accessibility_switches.h"
|
||||
#include "ui/base/ui_base_switches.h"
|
||||
#include "ui/display/display_switches.h"
|
||||
@@ -251,7 +251,7 @@ index ac9570fa3d9cb3b0026f70465e5b21ac7778c3df..acc0e121e7746da397cfab07b3707de7
|
||||
#include "ui/gl/gl_switches.h"
|
||||
#include "url/gurl.h"
|
||||
#include "url/origin.h"
|
||||
@@ -3283,6 +3284,7 @@ void RenderProcessHostImpl::PropagateBrowserCommandLineToRenderer(
|
||||
@@ -3293,6 +3294,7 @@ void RenderProcessHostImpl::PropagateBrowserCommandLineToRenderer(
|
||||
// Propagate the following switches to the renderer command line (along
|
||||
// with any associated values) if present in the browser command line.
|
||||
static const char* const kSwitchNames[] = {
|
||||
|
||||
@@ -6,7 +6,7 @@ Subject: disable_hidden.patch
|
||||
Electron uses this to disable background throttling for hidden windows.
|
||||
|
||||
diff --git a/content/browser/renderer_host/render_widget_host_impl.cc b/content/browser/renderer_host/render_widget_host_impl.cc
|
||||
index 03e318b14025f3c971d471351068986f8a1dd14d..59437e69e25fe85cffc9b558dec2284123ac48be 100644
|
||||
index f127b930806bc8e7b6fe8efb89eab6c43466326f..59dda38e5781132472991979d90317dfaa96028f 100644
|
||||
--- a/content/browser/renderer_host/render_widget_host_impl.cc
|
||||
+++ b/content/browser/renderer_host/render_widget_host_impl.cc
|
||||
@@ -803,6 +803,9 @@ void RenderWidgetHostImpl::WasHidden() {
|
||||
|
||||
@@ -33,10 +33,10 @@ index 14c71cc69388da46f62d9835e2a06fef0870da02..9481ea08401ae29ae9c1d960491b05b3
|
||||
|
||||
} // namespace net
|
||||
diff --git a/services/network/network_context.cc b/services/network/network_context.cc
|
||||
index ca62a13420aa9c114c00054bbe1215f96285a4e9..01be46b1eaed2aadfd24eac9d102da99521b175c 100644
|
||||
index a4cd97599e2f131fe0d97ee49a44ed5b748739b7..074ce8a372ad4d54661071cfa37632b5d1bbf067 100644
|
||||
--- a/services/network/network_context.cc
|
||||
+++ b/services/network/network_context.cc
|
||||
@@ -1331,6 +1331,13 @@ void NetworkContext::SetNetworkConditions(
|
||||
@@ -1343,6 +1343,13 @@ void NetworkContext::SetNetworkConditions(
|
||||
std::move(network_conditions));
|
||||
}
|
||||
|
||||
@@ -51,7 +51,7 @@ index ca62a13420aa9c114c00054bbe1215f96285a4e9..01be46b1eaed2aadfd24eac9d102da99
|
||||
// This may only be called on NetworkContexts created with the constructor
|
||||
// that calls MakeURLRequestContext().
|
||||
diff --git a/services/network/network_context.h b/services/network/network_context.h
|
||||
index e412608e7720004462c48698c8ec39602b2b900e..46c00e0da6beb0c2e689475fc4b9927085414e1a 100644
|
||||
index 06a36a156501b252e91037ebac45c29c2995f624..cb5435028a537baa5e1dbbab9137e6547b9ed712 100644
|
||||
--- a/services/network/network_context.h
|
||||
+++ b/services/network/network_context.h
|
||||
@@ -282,6 +282,7 @@ class COMPONENT_EXPORT(NETWORK_SERVICE) NetworkContext
|
||||
@@ -63,10 +63,10 @@ index e412608e7720004462c48698c8ec39602b2b900e..46c00e0da6beb0c2e689475fc4b99270
|
||||
void SetEnableReferrers(bool enable_referrers) override;
|
||||
#if BUILDFLAG(IS_CHROMEOS)
|
||||
diff --git a/services/network/public/mojom/network_context.mojom b/services/network/public/mojom/network_context.mojom
|
||||
index fa56cfed3703664232843ad26028096d95dca253..9852498e93939796e7ba6f80efcc7b2d827187ac 100644
|
||||
index ae0a20a7a33e5a313f5545985a34e9cb93220996..aeb0ac8731689e5495ab039d30ac3e88acab9293 100644
|
||||
--- a/services/network/public/mojom/network_context.mojom
|
||||
+++ b/services/network/public/mojom/network_context.mojom
|
||||
@@ -1067,6 +1067,9 @@ interface NetworkContext {
|
||||
@@ -1081,6 +1081,9 @@ interface NetworkContext {
|
||||
SetNetworkConditions(mojo_base.mojom.UnguessableToken throttling_profile_id,
|
||||
NetworkConditions? conditions);
|
||||
|
||||
|
||||
@@ -12,7 +12,7 @@ Ideally we could add an embedder observer pattern here but that can be
|
||||
done in future work.
|
||||
|
||||
diff --git a/third_party/blink/renderer/core/exported/web_view_impl.cc b/third_party/blink/renderer/core/exported/web_view_impl.cc
|
||||
index 7e7927c7258963bd95a2c064ef85e410f4d2571d..05353bda1169df38499e6f789bb632307d7bcfde 100644
|
||||
index 182f70b2b3bd9cbc6548d4c17caad797e5dad0ce..f78d5246a9e5f17089d47f95da22e922b6699057 100644
|
||||
--- a/third_party/blink/renderer/core/exported/web_view_impl.cc
|
||||
+++ b/third_party/blink/renderer/core/exported/web_view_impl.cc
|
||||
@@ -158,6 +158,7 @@
|
||||
|
||||
@@ -81,7 +81,7 @@ index 309422bcf85810db88a048bd0930c4072b41f234..759549f3046f4a897b597409b670bb1c
|
||||
private:
|
||||
const HWND hwnd_;
|
||||
diff --git a/components/viz/service/BUILD.gn b/components/viz/service/BUILD.gn
|
||||
index eff91b68cf4b72de41b7b2ad09c029b8b5dcf3c6..c736f772e3714c6a80703c41c8a2f0dab36b166d 100644
|
||||
index 03a9986ff94bc57e82a95e7a2a3fcc1415f28da0..79283e753512855360127471d40e145c325649ca 100644
|
||||
--- a/components/viz/service/BUILD.gn
|
||||
+++ b/components/viz/service/BUILD.gn
|
||||
@@ -139,6 +139,8 @@ viz_component("service") {
|
||||
@@ -501,7 +501,7 @@ index 583e3e2525c753a0962d481fc67a3582df75d0e9..9416ec929bebcff7f07088e635376ef2
|
||||
waiting_on_draw_ack_ = true;
|
||||
|
||||
diff --git a/components/viz/service/frame_sinks/root_compositor_frame_sink_impl.cc b/components/viz/service/frame_sinks/root_compositor_frame_sink_impl.cc
|
||||
index 4b6712b2a4f3c56a6d243ff9d93539505a5c7b86..7f62362ab27abd3497d23e8db8c8bb5a2e3392f9 100644
|
||||
index 7607a49cdc1a6028e272ce76b78806ec13415f42..e2f4350edeae766916716345327d0bbefb561e4c 100644
|
||||
--- a/components/viz/service/frame_sinks/root_compositor_frame_sink_impl.cc
|
||||
+++ b/components/viz/service/frame_sinks/root_compositor_frame_sink_impl.cc
|
||||
@@ -84,7 +84,8 @@ RootCompositorFrameSinkImpl::Create(
|
||||
@@ -619,7 +619,7 @@ index 8b74e1d2a463156f62e983f535ff68a53215f648..6ef04da46c8b097b01d5ee40dcadf222
|
||||
raw_ptr<Layer> root_layer_ = nullptr;
|
||||
|
||||
diff --git a/ui/gfx/ca_layer_params.h b/ui/gfx/ca_layer_params.h
|
||||
index 12e115cd6a128d8d150abc786d4d38b1d5119d91..b6320de28750333bee7ee83393849f4eb0a956ac 100644
|
||||
index c5fb29b30b9c5b7483998c567ed9a479d8743939..dc10d78315f76a3914ccd6e2e99af97fa909918b 100644
|
||||
--- a/ui/gfx/ca_layer_params.h
|
||||
+++ b/ui/gfx/ca_layer_params.h
|
||||
@@ -6,6 +6,7 @@
|
||||
@@ -630,7 +630,7 @@ index 12e115cd6a128d8d150abc786d4d38b1d5119d91..b6320de28750333bee7ee83393849f4e
|
||||
#include "ui/gfx/geometry/size.h"
|
||||
#include "ui/gfx/gfx_export.h"
|
||||
|
||||
@@ -51,6 +52,8 @@ struct GFX_EXPORT CALayerParams {
|
||||
@@ -41,6 +42,8 @@ struct GFX_EXPORT CALayerParams {
|
||||
gfx::ScopedRefCountedIOSurfaceMachPort io_surface_mach_port;
|
||||
#endif
|
||||
|
||||
|
||||
@@ -103,10 +103,10 @@ index 4c4cc16db82d7434573f7740855fbe72d68815e6..f71290800b6bb51a39b1f86be36f02d6
|
||||
string mime_type;
|
||||
|
||||
diff --git a/services/network/url_loader.cc b/services/network/url_loader.cc
|
||||
index 5c5aeeda64b244ab1f58556f28d2ca3c133d03a8..2f9aa4d49693a22507f668b2738c54be59802b8f 100644
|
||||
index 73b90e9b575b94f009ae3b87bd0ad76d69803bc3..e08bb784a11209f1531e8d981bd238d67db31e22 100644
|
||||
--- a/services/network/url_loader.cc
|
||||
+++ b/services/network/url_loader.cc
|
||||
@@ -469,6 +469,7 @@ URLLoader::URLLoader(
|
||||
@@ -462,6 +462,7 @@ URLLoader::URLLoader(
|
||||
mojo::SimpleWatcher::ArmingPolicy::MANUAL,
|
||||
base::SequencedTaskRunnerHandle::Get()),
|
||||
per_factory_corb_state_(context.GetMutableCorbState()),
|
||||
@@ -114,7 +114,7 @@ index 5c5aeeda64b244ab1f58556f28d2ca3c133d03a8..2f9aa4d49693a22507f668b2738c54be
|
||||
devtools_request_id_(request.devtools_request_id),
|
||||
request_mode_(request.mode),
|
||||
request_credentials_mode_(request.credentials_mode),
|
||||
@@ -636,7 +637,7 @@ URLLoader::URLLoader(
|
||||
@@ -629,7 +630,7 @@ URLLoader::URLLoader(
|
||||
url_request_->SetRequestHeadersCallback(base::BindRepeating(
|
||||
&URLLoader::SetRawRequestHeadersAndNotify, base::Unretained(this)));
|
||||
|
||||
@@ -123,7 +123,7 @@ index 5c5aeeda64b244ab1f58556f28d2ca3c133d03a8..2f9aa4d49693a22507f668b2738c54be
|
||||
url_request_->SetResponseHeadersCallback(base::BindRepeating(
|
||||
&URLLoader::SetRawResponseHeaders, base::Unretained(this)));
|
||||
}
|
||||
@@ -1395,6 +1396,19 @@ void URLLoader::OnResponseStarted(net::URLRequest* url_request, int net_error) {
|
||||
@@ -1388,6 +1389,19 @@ void URLLoader::OnResponseStarted(net::URLRequest* url_request, int net_error) {
|
||||
}
|
||||
|
||||
response_ = BuildResponseHead();
|
||||
|
||||
@@ -8,10 +8,10 @@ we invoke it in order to expose contents.decrementCapturerCount([stayHidden, sta
|
||||
to users. We should try to upstream this.
|
||||
|
||||
diff --git a/content/browser/web_contents/web_contents_impl.h b/content/browser/web_contents/web_contents_impl.h
|
||||
index 7440f2025701ccde0ade36cda22467dd0614109b..3c6ee78454dc9154a37ec9046e382878ffda0c82 100644
|
||||
index e1ac23f3adf38591ae220ea84c5c0717a28e64bb..fad1663512cf30b270289ecfa9c336b08fe67836 100644
|
||||
--- a/content/browser/web_contents/web_contents_impl.h
|
||||
+++ b/content/browser/web_contents/web_contents_impl.h
|
||||
@@ -1830,7 +1830,7 @@ class CONTENT_EXPORT WebContentsImpl : public WebContents,
|
||||
@@ -1831,7 +1831,7 @@ class CONTENT_EXPORT WebContentsImpl : public WebContents,
|
||||
// IncrementCapturerCount() is destructed.
|
||||
void DecrementCapturerCount(bool stay_hidden,
|
||||
bool stay_awake,
|
||||
|
||||
@@ -13,7 +13,7 @@ messages in the legacy window handle layer.
|
||||
These conditions are regularly hit with WCO-enabled windows on Windows.
|
||||
|
||||
diff --git a/content/browser/renderer_host/legacy_render_widget_host_win.cc b/content/browser/renderer_host/legacy_render_widget_host_win.cc
|
||||
index 4a894ef70eeb1d8489049aef552c9bae4f24ae62..f5049d730a850f2947023f976b25fb772e42107a 100644
|
||||
index 4a894ef70eeb1d8489049aef552c9bae4f24ae62..df101c53861a83f107d459270c37b3b497a00cb0 100644
|
||||
--- a/content/browser/renderer_host/legacy_render_widget_host_win.cc
|
||||
+++ b/content/browser/renderer_host/legacy_render_widget_host_win.cc
|
||||
@@ -288,12 +288,12 @@ LRESULT LegacyRenderWidgetHostHWND::OnMouseRange(UINT message,
|
||||
@@ -31,19 +31,15 @@ index 4a894ef70eeb1d8489049aef552c9bae4f24ae62..f5049d730a850f2947023f976b25fb77
|
||||
tme.hwndTrack = hwnd();
|
||||
tme.dwHoverTime = 0;
|
||||
TrackMouseEvent(&tme);
|
||||
@@ -319,12 +319,11 @@ LRESULT LegacyRenderWidgetHostHWND::OnMouseRange(UINT message,
|
||||
message, w_param, l_param, &msg_handled);
|
||||
handled = msg_handled;
|
||||
// If the parent did not handle non client mouse messages, we call
|
||||
- // DefWindowProc on the message with the parent window handle. This
|
||||
- // ensures that WM_SYSCOMMAND is generated for the parent and we are
|
||||
- // out of the picture.
|
||||
+ // DefWindowProc on the message. This ensures that WM_SYSCOMMAND is
|
||||
+ // generated.
|
||||
@@ -324,7 +324,10 @@ LRESULT LegacyRenderWidgetHostHWND::OnMouseRange(UINT message,
|
||||
// out of the picture.
|
||||
if (!handled &&
|
||||
(message >= WM_NCMOUSEMOVE && message <= WM_NCXBUTTONDBLCLK)) {
|
||||
- ret = ::DefWindowProc(GetParent(), message, w_param, l_param);
|
||||
+ ret = ::DefWindowProc(hwnd(), message, w_param, l_param);
|
||||
+ // Send WM_NCMOUSEMOVE messages using the LegacyRenderWidgetHostHWND's
|
||||
+ // handle so mouse tracking on non-client areas doesn't break.
|
||||
+ HWND target = message == WM_NCMOUSEMOVE ? hwnd() : GetParent();
|
||||
+ ret = ::DefWindowProc(target, message, w_param, l_param);
|
||||
handled = TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,7 +6,7 @@ Subject: frame_host_manager.patch
|
||||
Allows embedder to intercept site instances created by chromium.
|
||||
|
||||
diff --git a/content/browser/renderer_host/render_frame_host_manager.cc b/content/browser/renderer_host/render_frame_host_manager.cc
|
||||
index 1ca418461788e5b7d58c14b03c456d2c21f1305b..7a65b6713e3d0547f1990f8c59d0d11459532477 100644
|
||||
index 988290f88894157458641d2d201a060820813358..e19b30fc7a88c981d0dad3ed739f3219980b5aeb 100644
|
||||
--- a/content/browser/renderer_host/render_frame_host_manager.cc
|
||||
+++ b/content/browser/renderer_host/render_frame_host_manager.cc
|
||||
@@ -3089,6 +3089,9 @@ RenderFrameHostManager::GetSiteInstanceForNavigationRequest(
|
||||
@@ -20,10 +20,10 @@ index 1ca418461788e5b7d58c14b03c456d2c21f1305b..7a65b6713e3d0547f1990f8c59d0d114
|
||||
}
|
||||
|
||||
diff --git a/content/public/browser/content_browser_client.h b/content/public/browser/content_browser_client.h
|
||||
index 2fe1462a2cd92a731a5816b5fc22b059bad92fe8..a4dfa54a7844983262cc0fa635433131382e4d14 100644
|
||||
index ceb2bb900e122840505aa8d3911923cffc9a907e..c135db6a148e1d1b4af8d5a1d6a80e11ad99d9fe 100644
|
||||
--- a/content/public/browser/content_browser_client.h
|
||||
+++ b/content/public/browser/content_browser_client.h
|
||||
@@ -275,6 +275,11 @@ class CONTENT_EXPORT ContentBrowserClient {
|
||||
@@ -276,6 +276,11 @@ class CONTENT_EXPORT ContentBrowserClient {
|
||||
|
||||
virtual ~ContentBrowserClient() = default;
|
||||
|
||||
|
||||
@@ -11,7 +11,7 @@ If removing this patch causes no sync failures, it's safe to delete :+1:
|
||||
Ref https://chromium-review.googlesource.com/c/chromium/src/+/2953903
|
||||
|
||||
diff --git a/tools/clang/scripts/update.py b/tools/clang/scripts/update.py
|
||||
index ee41efe814da161cafb49229e1f02c8b82749e7c..494bbdeea2725e4b1218ba534fd126203012c100 100755
|
||||
index 0fb53bbaf4174594b46ecba6d4d28f7436ef9a72..9951fc52f06be5199b93d29d18a1b5582299f334 100755
|
||||
--- a/tools/clang/scripts/update.py
|
||||
+++ b/tools/clang/scripts/update.py
|
||||
@@ -298,6 +298,8 @@ def GetDefaultHostOs():
|
||||
|
||||
@@ -0,0 +1,37 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Marek Rusinowski <marekrusinowski@gmail.com>
|
||||
Date: Wed, 23 Mar 2022 21:09:37 +0100
|
||||
Subject: introduce OzonePlatform::electron_can_call_x11 property
|
||||
|
||||
We expose this additonal property in the OzonePlatform to be able to easily
|
||||
determine whatever we can call X11 functions without crashing the application
|
||||
at rutime. It would be best if eventually all usages of this property were
|
||||
replaced with clean ozone native implementations.
|
||||
|
||||
diff --git a/ui/ozone/platform/x11/ozone_platform_x11.cc b/ui/ozone/platform/x11/ozone_platform_x11.cc
|
||||
index 9008af973427d7dab8170449bc5767cebc9d2e9e..e312287e4aca61b51a69c8413088f56f9f704b5e 100644
|
||||
--- a/ui/ozone/platform/x11/ozone_platform_x11.cc
|
||||
+++ b/ui/ozone/platform/x11/ozone_platform_x11.cc
|
||||
@@ -200,6 +200,7 @@ class OzonePlatformX11 : public OzonePlatform,
|
||||
properties->supports_vulkan_swap_chain = true;
|
||||
properties->uses_external_vulkan_image_factory = true;
|
||||
properties->skia_can_fall_back_to_x11 = true;
|
||||
+ properties->electron_can_call_x11 = true;
|
||||
properties->platform_shows_drag_image = false;
|
||||
properties->supports_global_application_menus = true;
|
||||
properties->app_modal_dialogs_use_event_blocker = true;
|
||||
diff --git a/ui/ozone/public/ozone_platform.h b/ui/ozone/public/ozone_platform.h
|
||||
index 22ba32317a74df24249d1528dcaaa28ff18bd0f4..fa57f97520a0327be2c7f5179591ca61b801c8b0 100644
|
||||
--- a/ui/ozone/public/ozone_platform.h
|
||||
+++ b/ui/ozone/public/ozone_platform.h
|
||||
@@ -132,6 +132,10 @@ class COMPONENT_EXPORT(OZONE) OzonePlatform {
|
||||
// Linux only: determines if Skia can fall back to the X11 output device.
|
||||
bool skia_can_fall_back_to_x11 = false;
|
||||
|
||||
+ // Linux only: determines is Electron can call selected X11 functions while
|
||||
+ // it migrates to pure ozone abstractions.
|
||||
+ bool electron_can_call_x11 = false;
|
||||
+
|
||||
// Wayland only: determines whether windows which are not top level ones
|
||||
// should be given parents explicitly.
|
||||
bool set_parent_for_non_top_level_windows = false;
|
||||
52
patches/chromium/make_gtk_getlibgtk_public.patch
Normal file
52
patches/chromium/make_gtk_getlibgtk_public.patch
Normal file
@@ -0,0 +1,52 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: deepak1556 <hop2deep@gmail.com>
|
||||
Date: Thu, 7 Apr 2022 20:30:16 +0900
|
||||
Subject: Make gtk::GetLibGtk public
|
||||
|
||||
Allows embedders to get a handle to the gtk library
|
||||
already loaded in the process.
|
||||
|
||||
diff --git a/ui/gtk/gtk_compat.cc b/ui/gtk/gtk_compat.cc
|
||||
index 7104a0d5f4489c687f3cb9e63bc7cbef59d2fa62..f0b9ed834a3f7310da09377f0b2105cf635ffeb7 100644
|
||||
--- a/ui/gtk/gtk_compat.cc
|
||||
+++ b/ui/gtk/gtk_compat.cc
|
||||
@@ -86,12 +86,6 @@ void* GetLibGtk4(bool check = true) {
|
||||
return libgtk4;
|
||||
}
|
||||
|
||||
-void* GetLibGtk() {
|
||||
- if (GtkCheckVersion(4))
|
||||
- return GetLibGtk4();
|
||||
- return GetLibGtk3();
|
||||
-}
|
||||
-
|
||||
bool LoadGtk3() {
|
||||
if (!GetLibGtk3(false))
|
||||
return false;
|
||||
@@ -133,6 +127,12 @@ gfx::Insets InsetsFromGtkBorder(const GtkBorder& border) {
|
||||
|
||||
} // namespace
|
||||
|
||||
+void* GetLibGtk() {
|
||||
+ if (GtkCheckVersion(4))
|
||||
+ return GetLibGtk4();
|
||||
+ return GetLibGtk3();
|
||||
+}
|
||||
+
|
||||
bool LoadGtk() {
|
||||
static bool loaded = LoadGtkImpl();
|
||||
return loaded;
|
||||
diff --git a/ui/gtk/gtk_compat.h b/ui/gtk/gtk_compat.h
|
||||
index 72981270fe26579211afcaf3c596a412f69f5fac..b5dbfde5b011d57d26960d245e0dc61cac9341e4 100644
|
||||
--- a/ui/gtk/gtk_compat.h
|
||||
+++ b/ui/gtk/gtk_compat.h
|
||||
@@ -37,6 +37,9 @@ using SkColor = uint32_t;
|
||||
|
||||
namespace gtk {
|
||||
|
||||
+// Get handle to the currently loaded gtk library in the process.
|
||||
+void* GetLibGtk();
|
||||
+
|
||||
// Loads libgtk and related libraries and returns true on success.
|
||||
bool LoadGtk();
|
||||
|
||||
@@ -44,7 +44,7 @@ index 9734fb620a9a4010083af41a9e5cea038556eef5..05c95fb9b15f5ccbfecaee29d360dd27
|
||||
|
||||
} // namespace
|
||||
diff --git a/components/remote_cocoa/app_shim/native_widget_ns_window_bridge.mm b/components/remote_cocoa/app_shim/native_widget_ns_window_bridge.mm
|
||||
index fedefafc9837f681ad1c3fc48d06a333fea893e2..f07a090c24382c9330e8bd8baa3de47ec76da956 100644
|
||||
index cb82b91eb2e62453bcf2e3dd47f1b44d927e37d9..a35a14928d63a25284768de2ef67f2de2bedd133 100644
|
||||
--- a/components/remote_cocoa/app_shim/native_widget_ns_window_bridge.mm
|
||||
+++ b/components/remote_cocoa/app_shim/native_widget_ns_window_bridge.mm
|
||||
@@ -561,10 +561,12 @@ NSUInteger CountBridgedWindows(NSArray* child_windows) {
|
||||
@@ -167,7 +167,7 @@ index 09ada3b859e1862cbf365960422871a56af54983..58002d37ba340f84f47e2522c0d7bf7c
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
diff --git a/ui/base/BUILD.gn b/ui/base/BUILD.gn
|
||||
index 37f37c3a8e8a00cf9d4b8959ac2d97fe31629ad8..fa06bafbbaa69a20ce5a3260ca92947cb2bb9228 100644
|
||||
index 0d7d47d1260d47959b0fa9f116a039c8b8307c96..15cc28a9bbc7b33a727e7c172207262902835ccc 100644
|
||||
--- a/ui/base/BUILD.gn
|
||||
+++ b/ui/base/BUILD.gn
|
||||
@@ -317,6 +317,13 @@ component("base") {
|
||||
|
||||
@@ -6,6 +6,33 @@ Subject: mas: avoid some private APIs
|
||||
Guard usages in blink of private Mac APIs by MAS_BUILD, so they can be
|
||||
excluded for people who want to submit their apps to the Mac App store.
|
||||
|
||||
diff --git a/base/process/process_info_mac.cc b/base/process/process_info_mac.cc
|
||||
index 368405f29313d51a6eee16517b634c6d0ea95281..2553a7fbf1e8b4dea796dec3b3e906d265d3ad76 100644
|
||||
--- a/base/process/process_info_mac.cc
|
||||
+++ b/base/process/process_info_mac.cc
|
||||
@@ -5,18 +5,22 @@
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
|
||||
+#ifndef MAS_BUILD
|
||||
extern "C" {
|
||||
pid_t responsibility_get_pid_responsible_for_pid(pid_t)
|
||||
API_AVAILABLE(macosx(10.12));
|
||||
}
|
||||
+#endif
|
||||
|
||||
namespace base {
|
||||
|
||||
bool IsProcessSelfResponsible() {
|
||||
+#ifndef MAS_BUILD
|
||||
if (__builtin_available(macOS 10.14, *)) {
|
||||
const pid_t pid = getpid();
|
||||
return responsibility_get_pid_responsible_for_pid(pid) == pid;
|
||||
}
|
||||
+#endif
|
||||
return true;
|
||||
}
|
||||
|
||||
diff --git a/content/common/pseudonymization_salt.cc b/content/common/pseudonymization_salt.cc
|
||||
index 28e003bef910abff022def659fe18d4cd0549f8a..530bcbdb5d350f6486dc1e8536f7b279be69e241 100644
|
||||
--- a/content/common/pseudonymization_salt.cc
|
||||
|
||||
@@ -7,7 +7,7 @@ This adds a callback from the network service that's used to implement
|
||||
session.setCertificateVerifyCallback.
|
||||
|
||||
diff --git a/services/network/network_context.cc b/services/network/network_context.cc
|
||||
index 8ff62f92ed6efdbfc18db53db3c5bb59c1acfe34..ca62a13420aa9c114c00054bbe1215f96285a4e9 100644
|
||||
index 2ee1a3da9ca1543d032c2e05c9b340a231f0f495..a4cd97599e2f131fe0d97ee49a44ed5b748739b7 100644
|
||||
--- a/services/network/network_context.cc
|
||||
+++ b/services/network/network_context.cc
|
||||
@@ -126,6 +126,11 @@
|
||||
@@ -22,12 +22,38 @@ index 8ff62f92ed6efdbfc18db53db3c5bb59c1acfe34..ca62a13420aa9c114c00054bbe1215f9
|
||||
#if BUILDFLAG(IS_CT_SUPPORTED)
|
||||
#include "components/certificate_transparency/chrome_ct_policy_enforcer.h"
|
||||
#include "components/certificate_transparency/chrome_require_ct_delegate.h"
|
||||
@@ -433,6 +438,79 @@ bool GetFullDataFilePath(
|
||||
@@ -433,6 +438,91 @@ bool GetFullDataFilePath(
|
||||
|
||||
} // namespace
|
||||
|
||||
+class RemoteCertVerifier : public net::CertVerifier {
|
||||
+ public:
|
||||
+ class Request : public net::CertVerifier::Request {
|
||||
+ public:
|
||||
+ Request() {}
|
||||
+ ~Request() override = default;
|
||||
+ void OnRemoteResponse(
|
||||
+ const RequestParams& params,
|
||||
+ net::CertVerifyResult* verify_result,
|
||||
+ int error_from_upstream,
|
||||
+ net::CompletionOnceCallback callback,
|
||||
+ int error_from_client,
|
||||
+ const net::CertVerifyResult& verify_result_from_client) {
|
||||
+ if (error_from_client == net::ERR_ABORTED) {
|
||||
+ // use the default
|
||||
+ std::move(callback).Run(error_from_upstream);
|
||||
+ } else {
|
||||
+ // use the override
|
||||
+ verify_result->Reset();
|
||||
+ verify_result->verified_cert = verify_result_from_client.verified_cert;
|
||||
+ std::move(callback).Run(error_from_client);
|
||||
+ }
|
||||
+ }
|
||||
+ base::WeakPtr<Request> GetWeakPtr() { return weak_factory_.GetWeakPtr(); }
|
||||
+ private:
|
||||
+ base::WeakPtrFactory<Request> weak_factory_{this};
|
||||
+ };
|
||||
+
|
||||
+ RemoteCertVerifier(std::unique_ptr<net::CertVerifier> upstream): upstream_(std::move(upstream)) {
|
||||
+ }
|
||||
+ ~RemoteCertVerifier() override = default;
|
||||
@@ -44,20 +70,14 @@ index 8ff62f92ed6efdbfc18db53db3c5bb59c1acfe34..ca62a13420aa9c114c00054bbe1215f9
|
||||
+ int Verify(const RequestParams& params,
|
||||
+ net::CertVerifyResult* verify_result,
|
||||
+ net::CompletionOnceCallback callback,
|
||||
+ std::unique_ptr<Request>* out_req,
|
||||
+ std::unique_ptr<CertVerifier::Request>* out_req,
|
||||
+ const net::NetLogWithSource& net_log) override {
|
||||
+ out_req->reset();
|
||||
+
|
||||
+ net::CompletionOnceCallback callback2 = base::BindOnce(
|
||||
+ &RemoteCertVerifier::OnRequestFinished, base::Unretained(this),
|
||||
+ params, std::move(callback), verify_result);
|
||||
+ int result = upstream_->Verify(params, verify_result,
|
||||
+ std::move(callback2), out_req, net_log);
|
||||
+ if (result != net::ERR_IO_PENDING) {
|
||||
+ // Synchronous completion
|
||||
+ }
|
||||
+
|
||||
+ return result;
|
||||
+ params, std::move(callback), verify_result, out_req);
|
||||
+ return upstream_->Verify(params, verify_result, std::move(callback2), out_req, net_log);
|
||||
+ }
|
||||
+
|
||||
+
|
||||
@@ -65,35 +85,27 @@ index 8ff62f92ed6efdbfc18db53db3c5bb59c1acfe34..ca62a13420aa9c114c00054bbe1215f9
|
||||
+ upstream_->SetConfig(config);
|
||||
+ }
|
||||
+
|
||||
+ void OnRequestFinished(const RequestParams& params, net::CompletionOnceCallback callback, net::CertVerifyResult* verify_result, int error) {
|
||||
+ void OnRequestFinished(const RequestParams& params,
|
||||
+ net::CompletionOnceCallback callback,
|
||||
+ net::CertVerifyResult* verify_result,
|
||||
+ std::unique_ptr<CertVerifier::Request>* out_req,
|
||||
+ int error) {
|
||||
+ if (client_.is_bound()) {
|
||||
+ // We take a weak pointer to the request because deletion of the request
|
||||
+ // is what signals cancellation. Thus if the request is cancelled, the
|
||||
+ // callback won't be called, thus avoiding UAF, because |verify_result|
|
||||
+ // is freed when the request is cancelled.
|
||||
+ *out_req = std::make_unique<Request>();
|
||||
+ base::WeakPtr<Request> weak_req = static_cast<Request*>(out_req->get())->GetWeakPtr();
|
||||
+ client_->Verify(error, *verify_result, params.certificate(),
|
||||
+ params.hostname(), params.flags(), params.ocsp_response(),
|
||||
+ base::BindOnce(&RemoteCertVerifier::OnRemoteResponse,
|
||||
+ base::Unretained(this), params, verify_result, error,
|
||||
+ std::move(callback)));
|
||||
+ base::BindOnce(&Request::OnRemoteResponse,
|
||||
+ weak_req, params, verify_result, error, std::move(callback)));
|
||||
+ } else {
|
||||
+ std::move(callback).Run(error);
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ void OnRemoteResponse(
|
||||
+ const RequestParams& params,
|
||||
+ net::CertVerifyResult* verify_result,
|
||||
+ int error,
|
||||
+ net::CompletionOnceCallback callback,
|
||||
+ int error2,
|
||||
+ const net::CertVerifyResult& verify_result2) {
|
||||
+ if (error2 == net::ERR_ABORTED) {
|
||||
+ // use the default
|
||||
+ std::move(callback).Run(error);
|
||||
+ } else {
|
||||
+ // use the override
|
||||
+ verify_result->Reset();
|
||||
+ verify_result->verified_cert = verify_result2.verified_cert;
|
||||
+ std::move(callback).Run(error2);
|
||||
+ }
|
||||
+ }
|
||||
+ private:
|
||||
+ std::unique_ptr<net::CertVerifier> upstream_;
|
||||
+ mojo::Remote<mojom::CertVerifierClient> client_;
|
||||
@@ -102,7 +114,7 @@ index 8ff62f92ed6efdbfc18db53db3c5bb59c1acfe34..ca62a13420aa9c114c00054bbe1215f9
|
||||
constexpr uint32_t NetworkContext::kMaxOutstandingRequestsPerProcess;
|
||||
|
||||
NetworkContext::PendingCertVerify::PendingCertVerify() = default;
|
||||
@@ -671,6 +749,13 @@ void NetworkContext::SetClient(
|
||||
@@ -671,6 +761,13 @@ void NetworkContext::SetClient(
|
||||
client_.Bind(std::move(client));
|
||||
}
|
||||
|
||||
@@ -116,7 +128,7 @@ index 8ff62f92ed6efdbfc18db53db3c5bb59c1acfe34..ca62a13420aa9c114c00054bbe1215f9
|
||||
void NetworkContext::CreateURLLoaderFactory(
|
||||
mojo::PendingReceiver<mojom::URLLoaderFactory> receiver,
|
||||
mojom::URLLoaderFactoryParamsPtr params) {
|
||||
@@ -2226,6 +2311,9 @@ URLRequestContextOwner NetworkContext::MakeURLRequestContext(
|
||||
@@ -2235,6 +2332,9 @@ URLRequestContextOwner NetworkContext::MakeURLRequestContext(
|
||||
std::move(cert_verifier));
|
||||
cert_verifier = base::WrapUnique(cert_verifier_with_trust_anchors_);
|
||||
#endif // BUILDFLAG(IS_CHROMEOS)
|
||||
@@ -127,7 +139,7 @@ index 8ff62f92ed6efdbfc18db53db3c5bb59c1acfe34..ca62a13420aa9c114c00054bbe1215f9
|
||||
|
||||
builder.SetCertVerifier(IgnoreErrorsCertVerifier::MaybeWrapCertVerifier(
|
||||
diff --git a/services/network/network_context.h b/services/network/network_context.h
|
||||
index 6de81678e62d6921d0df5944ab01705402caa568..e412608e7720004462c48698c8ec39602b2b900e 100644
|
||||
index 01befea8b354ed1dd143aa895d0d9efb0d26fd35..06a36a156501b252e91037ebac45c29c2995f624 100644
|
||||
--- a/services/network/network_context.h
|
||||
+++ b/services/network/network_context.h
|
||||
@@ -105,6 +105,7 @@ class URLMatcher;
|
||||
@@ -147,7 +159,7 @@ index 6de81678e62d6921d0df5944ab01705402caa568..e412608e7720004462c48698c8ec3960
|
||||
void ResetURLLoaderFactories() override;
|
||||
void GetCookieManager(
|
||||
mojo::PendingReceiver<mojom::CookieManager> receiver) override;
|
||||
@@ -793,6 +796,8 @@ class COMPONENT_EXPORT(NETWORK_SERVICE) NetworkContext
|
||||
@@ -795,6 +798,8 @@ class COMPONENT_EXPORT(NETWORK_SERVICE) NetworkContext
|
||||
CertVerifierWithTrustAnchors* cert_verifier_with_trust_anchors_ = nullptr;
|
||||
#endif
|
||||
|
||||
@@ -157,7 +169,7 @@ index 6de81678e62d6921d0df5944ab01705402caa568..e412608e7720004462c48698c8ec3960
|
||||
// CertNetFetcher is not used by the current platform, or if the actual
|
||||
// net::CertVerifier is instantiated outside of the network service.
|
||||
diff --git a/services/network/public/mojom/network_context.mojom b/services/network/public/mojom/network_context.mojom
|
||||
index 9cd06ee552f8e592dd9efd1e73b10e5998559c04..fa56cfed3703664232843ad26028096d95dca253 100644
|
||||
index 0b1afd416381c28e5bc96fa44562c061f44a7121..ae0a20a7a33e5a313f5545985a34e9cb93220996 100644
|
||||
--- a/services/network/public/mojom/network_context.mojom
|
||||
+++ b/services/network/public/mojom/network_context.mojom
|
||||
@@ -277,6 +277,17 @@ struct NetworkContextFilePaths {
|
||||
@@ -178,7 +190,7 @@ index 9cd06ee552f8e592dd9efd1e73b10e5998559c04..fa56cfed3703664232843ad26028096d
|
||||
// Parameters for constructing a network context.
|
||||
struct NetworkContextParams {
|
||||
// The user agent string.
|
||||
@@ -807,6 +818,9 @@ interface NetworkContext {
|
||||
@@ -821,6 +832,9 @@ interface NetworkContext {
|
||||
// Sets a client for this network context.
|
||||
SetClient(pending_remote<NetworkContextClient> client);
|
||||
|
||||
|
||||
@@ -131,10 +131,10 @@ index 951075749b24814606f494c5a89ee2adf527f512..7036323ff8ee38ae92790dfd2e216df6
|
||||
const GURL& document_url,
|
||||
mojo::PendingReceiver<blink::mojom::NotificationService> receiver);
|
||||
diff --git a/content/browser/renderer_host/render_process_host_impl.cc b/content/browser/renderer_host/render_process_host_impl.cc
|
||||
index a1a3683b8da459a5859a2953536f3400a7fda213..602525302cfdd89bf2ddc2924076e7349de7562a 100644
|
||||
index a002e3972f1ed8ea8ff2a7febe1c6b7a8ffbe657..eebe90092c65dd9160a394b9b6eb2273b03de503 100644
|
||||
--- a/content/browser/renderer_host/render_process_host_impl.cc
|
||||
+++ b/content/browser/renderer_host/render_process_host_impl.cc
|
||||
@@ -2125,7 +2125,7 @@ void RenderProcessHostImpl::CreateNotificationService(
|
||||
@@ -2135,7 +2135,7 @@ void RenderProcessHostImpl::CreateNotificationService(
|
||||
document_url = rfh->GetLastCommittedURL();
|
||||
|
||||
storage_partition_impl_->GetPlatformNotificationContext()->CreateService(
|
||||
|
||||
@@ -61,10 +61,10 @@ index 1d8415814c6245e3f2dfd01de7a2de11f09cdc7a..6db48efe454820e242b862edbfaf4d40
|
||||
}
|
||||
|
||||
diff --git a/ui/color/win/native_color_mixers_win.cc b/ui/color/win/native_color_mixers_win.cc
|
||||
index 5faab22f665829e04cc07125f2486b9cb35f1f56..9776dbcc576c62ee44cbdd0d59542856363fb8f4 100644
|
||||
index 0620a389750649218865de06ed5d66f9ffe71871..575dcd925807263a9a5657d5156a3772421a0ed5 100644
|
||||
--- a/ui/color/win/native_color_mixers_win.cc
|
||||
+++ b/ui/color/win/native_color_mixers_win.cc
|
||||
@@ -136,16 +136,22 @@ void AddNativeUiColorMixer(ColorProvider* provider,
|
||||
@@ -136,6 +136,10 @@ void AddNativeUiColorMixer(ColorProvider* provider,
|
||||
SetAlpha(kColorNotificationInputForeground, gfx::kGoogleGreyAlpha700);
|
||||
mixer[kColorSliderTrack] = AlphaBlend(
|
||||
kColorNativeHighlight, kColorNativeWindow, gfx::kGoogleGreyAlpha400);
|
||||
@@ -75,8 +75,10 @@ index 5faab22f665829e04cc07125f2486b9cb35f1f56..9776dbcc576c62ee44cbdd0d59542856
|
||||
|
||||
// Window Background
|
||||
mixer[kColorBubbleFooterBackground] = {kColorNativeWindow};
|
||||
@@ -143,11 +147,13 @@ void AddNativeUiColorMixer(ColorProvider* provider,
|
||||
mixer[kColorFrameActive] = {ui::kColorNativeWindow};
|
||||
mixer[kColorFrameInactive] = {ui::kColorNativeWindow};
|
||||
mixer[kColorTooltipBackground] = {kColorNativeWindow};
|
||||
mixer[kColorButtonBackgroundProminentDisabled] = {kColorNativeWindow};
|
||||
+ mixer[kColorResultsTableNormalBackground] = {kColorNativeWindow};
|
||||
|
||||
// Window Text
|
||||
@@ -87,7 +89,7 @@ index 5faab22f665829e04cc07125f2486b9cb35f1f56..9776dbcc576c62ee44cbdd0d59542856
|
||||
|
||||
// Hyperlinks
|
||||
mixer[kColorLinkForeground] = {kColorNativeHotlight};
|
||||
@@ -179,6 +185,7 @@ void AddNativeUiColorMixer(ColorProvider* provider,
|
||||
@@ -181,6 +187,7 @@ void AddNativeUiColorMixer(ColorProvider* provider,
|
||||
mixer[kColorTextfieldForeground] = {kColorNativeBtnText};
|
||||
mixer[kColorTextfieldForegroundPlaceholder] = {kColorNativeBtnText};
|
||||
mixer[kColorTextfieldForegroundDisabled] = {kColorNativeBtnText};
|
||||
|
||||
@@ -483,7 +483,7 @@ index 51ebcb4ae399018d3fd8566656596a7ef1f148af..c0fbff95137e2e5bccb9702a8cc858df
|
||||
// Tells the browser that there are invalid printer settings.
|
||||
ShowInvalidPrinterSettingsError();
|
||||
diff --git a/components/printing/renderer/print_render_frame_helper.cc b/components/printing/renderer/print_render_frame_helper.cc
|
||||
index 553b199325714b2ac91c996ef5d32abf76169573..93821dc9c6d79d2c13e6c8db12a75cd9c832bf5a 100644
|
||||
index 0d5c467e59c85589872a41b3783110b9d84ffbdb..75a0c6c1ee04cb655261d9d385e486cbd1345f33 100644
|
||||
--- a/components/printing/renderer/print_render_frame_helper.cc
|
||||
+++ b/components/printing/renderer/print_render_frame_helper.cc
|
||||
@@ -40,6 +40,7 @@
|
||||
@@ -494,7 +494,7 @@ index 553b199325714b2ac91c996ef5d32abf76169573..93821dc9c6d79d2c13e6c8db12a75cd9
|
||||
#include "printing/units.h"
|
||||
#include "third_party/blink/public/common/associated_interfaces/associated_interface_provider.h"
|
||||
#include "third_party/blink/public/common/associated_interfaces/associated_interface_registry.h"
|
||||
@@ -1254,7 +1255,8 @@ void PrintRenderFrameHelper::ScriptedPrint(bool user_initiated) {
|
||||
@@ -1259,7 +1260,8 @@ void PrintRenderFrameHelper::ScriptedPrint(bool user_initiated) {
|
||||
if (!weak_this)
|
||||
return;
|
||||
|
||||
@@ -504,7 +504,7 @@ index 553b199325714b2ac91c996ef5d32abf76169573..93821dc9c6d79d2c13e6c8db12a75cd9
|
||||
if (!weak_this)
|
||||
return;
|
||||
|
||||
@@ -1285,7 +1287,7 @@ void PrintRenderFrameHelper::BindPrintRenderFrameReceiver(
|
||||
@@ -1290,7 +1292,7 @@ void PrintRenderFrameHelper::BindPrintRenderFrameReceiver(
|
||||
receivers_.Add(this, std::move(receiver));
|
||||
}
|
||||
|
||||
@@ -513,7 +513,7 @@ index 553b199325714b2ac91c996ef5d32abf76169573..93821dc9c6d79d2c13e6c8db12a75cd9
|
||||
ScopedIPC scoped_ipc(weak_ptr_factory_.GetWeakPtr());
|
||||
if (ipc_nesting_level_ > kAllowedIpcDepthForPrint)
|
||||
return;
|
||||
@@ -1300,7 +1302,7 @@ void PrintRenderFrameHelper::PrintRequestedPages() {
|
||||
@@ -1305,7 +1307,7 @@ void PrintRenderFrameHelper::PrintRequestedPages() {
|
||||
// plugin node and print that instead.
|
||||
auto plugin = delegate_->GetPdfElement(frame);
|
||||
|
||||
@@ -522,7 +522,7 @@ index 553b199325714b2ac91c996ef5d32abf76169573..93821dc9c6d79d2c13e6c8db12a75cd9
|
||||
|
||||
if (!render_frame_gone_)
|
||||
frame->DispatchAfterPrintEvent();
|
||||
@@ -1331,7 +1333,8 @@ void PrintRenderFrameHelper::PrintForSystemDialog() {
|
||||
@@ -1336,7 +1338,8 @@ void PrintRenderFrameHelper::PrintForSystemDialog() {
|
||||
}
|
||||
|
||||
Print(frame, print_preview_context_.source_node(),
|
||||
@@ -532,7 +532,7 @@ index 553b199325714b2ac91c996ef5d32abf76169573..93821dc9c6d79d2c13e6c8db12a75cd9
|
||||
if (!render_frame_gone_)
|
||||
print_preview_context_.DispatchAfterPrintEvent();
|
||||
// WARNING: |this| may be gone at this point. Do not do any more work here and
|
||||
@@ -1378,6 +1381,8 @@ void PrintRenderFrameHelper::PrintPreview(base::Value settings) {
|
||||
@@ -1383,6 +1386,8 @@ void PrintRenderFrameHelper::PrintPreview(base::Value settings) {
|
||||
if (ipc_nesting_level_ > kAllowedIpcDepthForPrint)
|
||||
return;
|
||||
|
||||
@@ -541,7 +541,7 @@ index 553b199325714b2ac91c996ef5d32abf76169573..93821dc9c6d79d2c13e6c8db12a75cd9
|
||||
print_preview_context_.OnPrintPreview();
|
||||
|
||||
if (print_preview_context_.IsForArc()) {
|
||||
@@ -1915,7 +1920,8 @@ void PrintRenderFrameHelper::PrintNode(const blink::WebNode& node) {
|
||||
@@ -1920,7 +1925,8 @@ void PrintRenderFrameHelper::PrintNode(const blink::WebNode& node) {
|
||||
return;
|
||||
|
||||
Print(duplicate_node.GetDocument().GetFrame(), duplicate_node,
|
||||
@@ -551,7 +551,7 @@ index 553b199325714b2ac91c996ef5d32abf76169573..93821dc9c6d79d2c13e6c8db12a75cd9
|
||||
// Check if |this| is still valid.
|
||||
if (!weak_this)
|
||||
return;
|
||||
@@ -1930,7 +1936,9 @@ void PrintRenderFrameHelper::PrintNode(const blink::WebNode& node) {
|
||||
@@ -1935,7 +1941,9 @@ void PrintRenderFrameHelper::PrintNode(const blink::WebNode& node) {
|
||||
|
||||
void PrintRenderFrameHelper::Print(blink::WebLocalFrame* frame,
|
||||
const blink::WebNode& node,
|
||||
@@ -562,7 +562,7 @@ index 553b199325714b2ac91c996ef5d32abf76169573..93821dc9c6d79d2c13e6c8db12a75cd9
|
||||
// If still not finished with earlier print request simply ignore.
|
||||
if (prep_frame_view_)
|
||||
return;
|
||||
@@ -1938,7 +1946,7 @@ void PrintRenderFrameHelper::Print(blink::WebLocalFrame* frame,
|
||||
@@ -1943,7 +1951,7 @@ void PrintRenderFrameHelper::Print(blink::WebLocalFrame* frame,
|
||||
FrameReference frame_ref(frame);
|
||||
|
||||
uint32_t expected_page_count = 0;
|
||||
@@ -571,7 +571,7 @@ index 553b199325714b2ac91c996ef5d32abf76169573..93821dc9c6d79d2c13e6c8db12a75cd9
|
||||
DidFinishPrinting(FAIL_PRINT_INIT);
|
||||
return; // Failed to init print page settings.
|
||||
}
|
||||
@@ -1957,8 +1965,15 @@ void PrintRenderFrameHelper::Print(blink::WebLocalFrame* frame,
|
||||
@@ -1962,8 +1970,15 @@ void PrintRenderFrameHelper::Print(blink::WebLocalFrame* frame,
|
||||
print_pages_params_->params->print_scaling_option;
|
||||
|
||||
auto self = weak_ptr_factory_.GetWeakPtr();
|
||||
@@ -588,7 +588,7 @@ index 553b199325714b2ac91c996ef5d32abf76169573..93821dc9c6d79d2c13e6c8db12a75cd9
|
||||
// Check if |this| is still valid.
|
||||
if (!self)
|
||||
return;
|
||||
@@ -2206,36 +2221,51 @@ void PrintRenderFrameHelper::IPCProcessed() {
|
||||
@@ -2211,36 +2226,51 @@ void PrintRenderFrameHelper::IPCProcessed() {
|
||||
}
|
||||
}
|
||||
|
||||
@@ -652,7 +652,7 @@ index 553b199325714b2ac91c996ef5d32abf76169573..93821dc9c6d79d2c13e6c8db12a75cd9
|
||||
notify_browser_of_print_failure_ = false;
|
||||
GetPrintManagerHost()->ShowInvalidPrinterSettingsError();
|
||||
return false;
|
||||
@@ -2380,7 +2410,7 @@ mojom::PrintPagesParamsPtr PrintRenderFrameHelper::GetPrintSettingsFromUser(
|
||||
@@ -2385,7 +2415,7 @@ mojom::PrintPagesParamsPtr PrintRenderFrameHelper::GetPrintSettingsFromUser(
|
||||
std::move(params),
|
||||
base::BindOnce(
|
||||
[](base::OnceClosure quit_closure, mojom::PrintPagesParamsPtr* output,
|
||||
@@ -661,7 +661,7 @@ index 553b199325714b2ac91c996ef5d32abf76169573..93821dc9c6d79d2c13e6c8db12a75cd9
|
||||
*output = std::move(input);
|
||||
std::move(quit_closure).Run();
|
||||
},
|
||||
@@ -2625,18 +2655,7 @@ void PrintRenderFrameHelper::RequestPrintPreview(PrintPreviewRequestType type,
|
||||
@@ -2630,18 +2660,7 @@ void PrintRenderFrameHelper::RequestPrintPreview(PrintPreviewRequestType type,
|
||||
}
|
||||
|
||||
bool PrintRenderFrameHelper::CheckForCancel() {
|
||||
|
||||
@@ -30,7 +30,7 @@ index 059ff2b47e7aa8b9707e71ae9a1793bfdd86d319..529637f8b6af6b8b45f9de61d27b5e9c
|
||||
// RenderWidgetHost on the primary main frame, and false otherwise.
|
||||
virtual bool IsWidgetForPrimaryMainFrame(RenderWidgetHostImpl*);
|
||||
diff --git a/content/browser/renderer_host/render_widget_host_impl.cc b/content/browser/renderer_host/render_widget_host_impl.cc
|
||||
index 59437e69e25fe85cffc9b558dec2284123ac48be..d3af2aed32f6047cbb86bd2b4ce1df9fee80437c 100644
|
||||
index 59dda38e5781132472991979d90317dfaa96028f..7d51b1d678b9b11c0dfc48a0a890a43d21830530 100644
|
||||
--- a/content/browser/renderer_host/render_widget_host_impl.cc
|
||||
+++ b/content/browser/renderer_host/render_widget_host_impl.cc
|
||||
@@ -2082,6 +2082,8 @@ void RenderWidgetHostImpl::FilterDropData(DropData* drop_data) {
|
||||
@@ -43,7 +43,7 @@ index 59437e69e25fe85cffc9b558dec2284123ac48be..d3af2aed32f6047cbb86bd2b4ce1df9f
|
||||
|
||||
void RenderWidgetHostImpl::ShowContextMenuAtPoint(
|
||||
diff --git a/content/browser/web_contents/web_contents_impl.cc b/content/browser/web_contents/web_contents_impl.cc
|
||||
index c8e49eeaca8b31479aa908be9c349ccd625e9e51..5c63a024827359ccf697d0b7fc8fa2092eb107b7 100644
|
||||
index 5afb01c9de253053243a1add87269a9d848b5297..1734f93f7d06faf2c28d65d23bbc6c17f72e0b59 100644
|
||||
--- a/content/browser/web_contents/web_contents_impl.cc
|
||||
+++ b/content/browser/web_contents/web_contents_impl.cc
|
||||
@@ -4486,6 +4486,11 @@ TextInputManager* WebContentsImpl::GetTextInputManager() {
|
||||
@@ -59,10 +59,10 @@ index c8e49eeaca8b31479aa908be9c349ccd625e9e51..5c63a024827359ccf697d0b7fc8fa209
|
||||
RenderWidgetHostImpl* render_widget_host) {
|
||||
return render_widget_host == GetMainFrame()->GetRenderWidgetHost();
|
||||
diff --git a/content/browser/web_contents/web_contents_impl.h b/content/browser/web_contents/web_contents_impl.h
|
||||
index 85b426a7552cf925157a76fcd1ed7de47cd27a54..7440f2025701ccde0ade36cda22467dd0614109b 100644
|
||||
index 5020c6674ba692c15d75d5eec981ac7b60f61bbe..e1ac23f3adf38591ae220ea84c5c0717a28e64bb 100644
|
||||
--- a/content/browser/web_contents/web_contents_impl.h
|
||||
+++ b/content/browser/web_contents/web_contents_impl.h
|
||||
@@ -965,6 +965,7 @@ class CONTENT_EXPORT WebContentsImpl : public WebContents,
|
||||
@@ -966,6 +966,7 @@ class CONTENT_EXPORT WebContentsImpl : public WebContents,
|
||||
blink::mojom::FrameVisibility visibility) override;
|
||||
void SendScreenRects() override;
|
||||
TextInputManager* GetTextInputManager() override;
|
||||
|
||||
@@ -0,0 +1,39 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Bruce Dawson <brucedawson@chromium.org>
|
||||
Date: Mon, 28 Feb 2022 19:07:41 +0000
|
||||
Subject: Remove incorrect width/height adjustments
|
||||
|
||||
In late 2016 a change which fixed some problems around window sizing
|
||||
when attaching or detaching additional displays was landed, which fixed
|
||||
some genuine bugs. Unfortunately it included a subtraction of 1 from the
|
||||
width and height of the Chrome window. I couldn't find any discussion of
|
||||
this size adjustment and I think that it was just a misunderstanding of
|
||||
how window rectangles work (inclusive versus exclusive extents).
|
||||
|
||||
This size adjustment causes non-maximized Chrome windows to shrink every
|
||||
time a monitor is added or removed. The problematic commit was found
|
||||
by the bug-filer through a bisect of more than four years of Chrome
|
||||
history - I'm just landing the fix that they suggested.
|
||||
|
||||
Bug: 1300415
|
||||
Change-Id: Ief124f584a91aa9cc3f10704b0cc1e83356dea5b
|
||||
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3492658
|
||||
Reviewed-by: Allen Bauer <kylixrd@chromium.org>
|
||||
Commit-Queue: Bruce Dawson <brucedawson@chromium.org>
|
||||
Cr-Commit-Position: refs/heads/main@{#975872}
|
||||
|
||||
diff --git a/ui/views/win/hwnd_message_handler.cc b/ui/views/win/hwnd_message_handler.cc
|
||||
index 264a9109e42c23e9be6bf7269b3cfee2634b61e4..86f06d2a2c9588a2210a9f78f47e73f1b7c5e329 100644
|
||||
--- a/ui/views/win/hwnd_message_handler.cc
|
||||
+++ b/ui/views/win/hwnd_message_handler.cc
|
||||
@@ -2834,8 +2834,8 @@ void HWNDMessageHandler::OnWindowPosChanging(WINDOWPOS* window_pos) {
|
||||
// (Win+Shift+Arrows). See crbug.com/656001.
|
||||
window_rect.left = window_pos->x;
|
||||
window_rect.top = window_pos->y;
|
||||
- window_rect.right = window_pos->x + window_pos->cx - 1;
|
||||
- window_rect.bottom = window_pos->y + window_pos->cy - 1;
|
||||
+ window_rect.right = window_pos->x + window_pos->cx;
|
||||
+ window_rect.bottom = window_pos->y + window_pos->cy;
|
||||
}
|
||||
|
||||
HMONITOR monitor;
|
||||
@@ -6,10 +6,10 @@ Subject: render_widget_host_view_base.patch
|
||||
... something to do with OSR? and maybe <webview> as well? terrifying.
|
||||
|
||||
diff --git a/content/browser/renderer_host/render_widget_host_view_base.cc b/content/browser/renderer_host/render_widget_host_view_base.cc
|
||||
index 5fd8cb63f589dd204c2477f2375ec1d3716b55f0..85e52f7a99fe350da05270cf6fde0fe82a1bec40 100644
|
||||
index 14b5b4552f8077236486c6c182a1e231b8aa8408..a6c20b9803eb9a259460ec09826cc1cb037e5e3f 100644
|
||||
--- a/content/browser/renderer_host/render_widget_host_view_base.cc
|
||||
+++ b/content/browser/renderer_host/render_widget_host_view_base.cc
|
||||
@@ -660,6 +660,13 @@ bool RenderWidgetHostViewBase::ScreenRectIsUnstableFor(
|
||||
@@ -661,6 +661,13 @@ bool RenderWidgetHostViewBase::ScreenRectIsUnstableFor(
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
@@ -52,10 +52,10 @@ Some alternatives to this patch:
|
||||
None of these options seems like a substantial maintainability win over this patch to me (@nornagon).
|
||||
|
||||
diff --git a/chrome/BUILD.gn b/chrome/BUILD.gn
|
||||
index 04546cad2b3e6355d667fe725b85836f128f0df7..7caaf66cad9d5b9f787cea0d49c32c26801571c2 100644
|
||||
index 51555df59f2bf9d0f396b9ffea0524a2533274ec..f2c4feac76e96575de3627b7e8f2373b4fb30411 100644
|
||||
--- a/chrome/BUILD.gn
|
||||
+++ b/chrome/BUILD.gn
|
||||
@@ -1591,7 +1591,7 @@ if (is_chrome_branded && !is_android) {
|
||||
@@ -1596,7 +1596,7 @@ if (is_chrome_branded && !is_android) {
|
||||
}
|
||||
}
|
||||
|
||||
@@ -64,7 +64,7 @@ index 04546cad2b3e6355d667fe725b85836f128f0df7..7caaf66cad9d5b9f787cea0d49c32c26
|
||||
chrome_paks("packed_resources") {
|
||||
if (is_mac) {
|
||||
output_dir = "$root_gen_dir/repack"
|
||||
@@ -1619,6 +1619,12 @@ if (!is_android) {
|
||||
@@ -1624,6 +1624,12 @@ if (!is_android) {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -6,7 +6,7 @@ Subject: scroll_bounce_flag.patch
|
||||
Patch to make scrollBounce option work.
|
||||
|
||||
diff --git a/content/renderer/render_thread_impl.cc b/content/renderer/render_thread_impl.cc
|
||||
index 0b42cba8667225c25df2405d99efe119a26c3585..ee8b42500499dc6a1700bc38e5b75976bb408490 100644
|
||||
index 03b92fd7a6218d3469648b96f273377d84c2f13f..d7ca333c81fd5765da047acf54aaeb5e07ab4c26 100644
|
||||
--- a/content/renderer/render_thread_impl.cc
|
||||
+++ b/content/renderer/render_thread_impl.cc
|
||||
@@ -1344,7 +1344,7 @@ bool RenderThreadImpl::IsLcdTextEnabled() {
|
||||
|
||||
@@ -22,10 +22,10 @@ However, the patch would need to be reviewed by the security team, as it
|
||||
does touch a security-sensitive class.
|
||||
|
||||
diff --git a/content/browser/renderer_host/render_process_host_impl.cc b/content/browser/renderer_host/render_process_host_impl.cc
|
||||
index 602525302cfdd89bf2ddc2924076e7349de7562a..ac9570fa3d9cb3b0026f70465e5b21ac7778c3df 100644
|
||||
index eebe90092c65dd9160a394b9b6eb2273b03de503..5f2451eefad211c85460eb457ad3d6e184540d59 100644
|
||||
--- a/content/browser/renderer_host/render_process_host_impl.cc
|
||||
+++ b/content/browser/renderer_host/render_process_host_impl.cc
|
||||
@@ -1836,9 +1836,15 @@ bool RenderProcessHostImpl::Init() {
|
||||
@@ -1838,9 +1838,15 @@ bool RenderProcessHostImpl::Init() {
|
||||
std::unique_ptr<SandboxedProcessLauncherDelegate> sandbox_delegate =
|
||||
std::make_unique<RendererSandboxedProcessLauncherDelegateWin>(
|
||||
cmd_line.get(), IsJitDisabled());
|
||||
|
||||
@@ -1,28 +0,0 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: deepak1556 <hop2deep@gmail.com>
|
||||
Date: Fri, 10 Apr 2020 17:47:18 -0700
|
||||
Subject: ui_gtk_public_header.patch
|
||||
|
||||
Allow electron to depend on //ui/gtk/gtk_util.h
|
||||
|
||||
diff --git a/ui/gtk/BUILD.gn b/ui/gtk/BUILD.gn
|
||||
index 4093df78da0bbb1d8df743942f364cf728ad3414..2f31d99b207ffc3531b5334b5a01239cc1fefb35 100644
|
||||
--- a/ui/gtk/BUILD.gn
|
||||
+++ b/ui/gtk/BUILD.gn
|
||||
@@ -69,7 +69,7 @@ generate_stubs("gtk_stubs") {
|
||||
}
|
||||
|
||||
component("gtk") {
|
||||
- public = [ "gtk_ui_factory.h" ]
|
||||
+ public = [ "gtk_ui_factory.h", "gtk_util.h" ]
|
||||
|
||||
sources = [
|
||||
"gtk_color_mixers.cc",
|
||||
@@ -85,7 +85,6 @@ component("gtk") {
|
||||
"gtk_ui_platform_stub.cc",
|
||||
"gtk_ui_platform_stub.h",
|
||||
"gtk_util.cc",
|
||||
- "gtk_util.h",
|
||||
"input_method_context_impl_gtk.cc",
|
||||
"input_method_context_impl_gtk.h",
|
||||
"native_theme_gtk.cc",
|
||||
@@ -9,7 +9,7 @@ is needed for OSR.
|
||||
Originally landed in https://github.com/electron/libchromiumcontent/pull/226.
|
||||
|
||||
diff --git a/content/browser/web_contents/web_contents_impl.cc b/content/browser/web_contents/web_contents_impl.cc
|
||||
index 3da88b5831717c979373c064b4c1520c28d4fd98..cf3ea07bb7d708f9078c46af2c4583215f9cd189 100644
|
||||
index b19517ceafabde2ad88e83af97b9768b8a03fb60..4a553eee8f5d06cb645f2b52fe3baee347b1fa94 100644
|
||||
--- a/content/browser/web_contents/web_contents_impl.cc
|
||||
+++ b/content/browser/web_contents/web_contents_impl.cc
|
||||
@@ -3040,6 +3040,13 @@ void WebContentsImpl::Init(const WebContents::CreateParams& params,
|
||||
|
||||
@@ -14,10 +14,10 @@ Note that we also need to manually update embedder's
|
||||
`api::WebContents::IsFullscreenForTabOrPending` value.
|
||||
|
||||
diff --git a/content/browser/renderer_host/render_frame_host_impl.cc b/content/browser/renderer_host/render_frame_host_impl.cc
|
||||
index 713e2883139bca4bb56dcc7e3efcf6d6dfc4a02b..be2721cc6dc0582a05c74ac3d50c123666d7d5a3 100644
|
||||
index e36a19c847912b007a94464321bb83b15bdcdafd..afd175d35096b0a50ccee3f2b14c632adbfec58a 100644
|
||||
--- a/content/browser/renderer_host/render_frame_host_impl.cc
|
||||
+++ b/content/browser/renderer_host/render_frame_host_impl.cc
|
||||
@@ -6102,6 +6102,15 @@ void RenderFrameHostImpl::EnterFullscreen(
|
||||
@@ -6105,6 +6105,15 @@ void RenderFrameHostImpl::EnterFullscreen(
|
||||
notified_instances.insert(parent_site_instance);
|
||||
}
|
||||
|
||||
|
||||
@@ -26,10 +26,10 @@ index 63ead7f8ab838693bade7163ddebd1787cc82344..8512a66eda07202b6c6faea049736fd8
|
||||
// An empty URL is returned if the URL is not overriden.
|
||||
virtual GURL OverrideFlashEmbedWithHTML(const GURL& url);
|
||||
diff --git a/content/renderer/renderer_blink_platform_impl.cc b/content/renderer/renderer_blink_platform_impl.cc
|
||||
index a64d78c9d8112610af6a17c8f8b8b9124b9d40a3..0bd64497495cfd8eee5e7cae3eca69937f2e79e0 100644
|
||||
index bd420d1cf8b5c1de687be10979921381cb770de9..0ea0012253d8348f1ba204f3b1fca7c5e2d306ce 100644
|
||||
--- a/content/renderer/renderer_blink_platform_impl.cc
|
||||
+++ b/content/renderer/renderer_blink_platform_impl.cc
|
||||
@@ -932,6 +932,12 @@ void RendererBlinkPlatformImpl::WillStopWorkerThread() {
|
||||
@@ -954,6 +954,12 @@ void RendererBlinkPlatformImpl::WillStopWorkerThread() {
|
||||
WorkerThreadRegistry::Instance()->WillStopCurrentWorkerThread();
|
||||
}
|
||||
|
||||
@@ -43,10 +43,10 @@ index a64d78c9d8112610af6a17c8f8b8b9124b9d40a3..0bd64497495cfd8eee5e7cae3eca6993
|
||||
const v8::Local<v8::Context>& worker) {
|
||||
GetContentClient()->renderer()->DidInitializeWorkerContextOnWorkerThread(
|
||||
diff --git a/content/renderer/renderer_blink_platform_impl.h b/content/renderer/renderer_blink_platform_impl.h
|
||||
index 10c96d3915e64ebebd283c70292b33e22612b8eb..9fa6853a2945e2a34ed319f874f356a4afd72dd3 100644
|
||||
index 7255ac218c8fd061c2125e33054d9a87c13d1eb4..ab771fe015c195f53ce8bb1411050635f02c69f3 100644
|
||||
--- a/content/renderer/renderer_blink_platform_impl.h
|
||||
+++ b/content/renderer/renderer_blink_platform_impl.h
|
||||
@@ -208,6 +208,7 @@ class CONTENT_EXPORT RendererBlinkPlatformImpl : public BlinkPlatformImpl {
|
||||
@@ -209,6 +209,7 @@ class CONTENT_EXPORT RendererBlinkPlatformImpl : public BlinkPlatformImpl {
|
||||
void DidStartWorkerThread() override;
|
||||
void WillStopWorkerThread() override;
|
||||
void WorkerContextCreated(const v8::Local<v8::Context>& worker) override;
|
||||
|
||||
@@ -35,10 +35,10 @@ index 8512a66eda07202b6c6faea049736fd8f16c93db..afe767350c8878da38ab2b566fa89bcb
|
||||
// from the worker thread.
|
||||
virtual void WillDestroyWorkerContextOnWorkerThread(
|
||||
diff --git a/content/renderer/renderer_blink_platform_impl.cc b/content/renderer/renderer_blink_platform_impl.cc
|
||||
index 0bd64497495cfd8eee5e7cae3eca69937f2e79e0..9ab68aabff203127dba5a0ccdf16fa62f3ef4c40 100644
|
||||
index 0ea0012253d8348f1ba204f3b1fca7c5e2d306ce..8851d8bd283e1d44a921034e969f160ff494d6f9 100644
|
||||
--- a/content/renderer/renderer_blink_platform_impl.cc
|
||||
+++ b/content/renderer/renderer_blink_platform_impl.cc
|
||||
@@ -944,6 +944,12 @@ void RendererBlinkPlatformImpl::WorkerContextCreated(
|
||||
@@ -966,6 +966,12 @@ void RendererBlinkPlatformImpl::WorkerContextCreated(
|
||||
worker);
|
||||
}
|
||||
|
||||
@@ -52,10 +52,10 @@ index 0bd64497495cfd8eee5e7cae3eca69937f2e79e0..9ab68aabff203127dba5a0ccdf16fa62
|
||||
const blink::WebSecurityOrigin& script_origin) {
|
||||
return GetContentClient()->renderer()->AllowScriptExtensionForServiceWorker(
|
||||
diff --git a/content/renderer/renderer_blink_platform_impl.h b/content/renderer/renderer_blink_platform_impl.h
|
||||
index 9fa6853a2945e2a34ed319f874f356a4afd72dd3..87f9190d227e501a648dbbaa350bbb105601fbfb 100644
|
||||
index ab771fe015c195f53ce8bb1411050635f02c69f3..a78d38985b3761a63cc4efbd354820c6fd258d9c 100644
|
||||
--- a/content/renderer/renderer_blink_platform_impl.h
|
||||
+++ b/content/renderer/renderer_blink_platform_impl.h
|
||||
@@ -208,6 +208,8 @@ class CONTENT_EXPORT RendererBlinkPlatformImpl : public BlinkPlatformImpl {
|
||||
@@ -209,6 +209,8 @@ class CONTENT_EXPORT RendererBlinkPlatformImpl : public BlinkPlatformImpl {
|
||||
void DidStartWorkerThread() override;
|
||||
void WillStopWorkerThread() override;
|
||||
void WorkerContextCreated(const v8::Local<v8::Context>& worker) override;
|
||||
|
||||
@@ -32,3 +32,16 @@ darwin_translate_eprototype_to_econnreset_3413.patch
|
||||
darwin_bump_minimum_supported_version_to_10_15_3406.patch
|
||||
fix_serdes_test.patch
|
||||
fix_failing_node_js_test_on_outdated.patch
|
||||
be_compatible_with_cppgc.patch
|
||||
process_monitor_for_exit_with_kqueue_on_bsds_3441.patch
|
||||
unix_protect_fork_in_uv_spawn_from_signals.patch
|
||||
process_bsd_handle_kevent_note_exit_failure_3451.patch
|
||||
reland_macos_use_posix_spawn_instead_of_fork_3257.patch
|
||||
process_reset_the_signal_mask_if_the_fork_fails_3537.patch
|
||||
process_only_use_f_dupfd_cloexec_if_it_is_defined_3512.patch
|
||||
unix_simplify_uv_cloexec_fcntl_3492.patch
|
||||
unix_remove_uv_cloexec_ioctl_3515.patch
|
||||
process_simplify_uv_write_int_calls_3519.patch
|
||||
macos_don_t_use_thread-unsafe_strtok_3524.patch
|
||||
process_fix_hang_after_note_exit_3521.patch
|
||||
worker_thread_add_asar_support.patch
|
||||
|
||||
97
patches/node/be_compatible_with_cppgc.patch
Normal file
97
patches/node/be_compatible_with_cppgc.patch
Normal file
@@ -0,0 +1,97 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Jeremy Rose <nornagon@nornagon.net>
|
||||
Date: Fri, 11 Mar 2022 11:17:29 -0800
|
||||
Subject: be compatible with cppgc
|
||||
|
||||
This fixes a crash that happens sporadically when Node is used in the same V8
|
||||
Isolate as Blink. For example:
|
||||
|
||||
#
|
||||
# Fatal error in ../../v8/src/objects/js-objects-inl.h, line 306
|
||||
# Debug check failed: static_cast<unsigned>(index) < static_cast<unsigned>(GetEmbedderFieldCount()) (1 vs. 1).
|
||||
#
|
||||
#
|
||||
#
|
||||
#FailureMessage Object: 0x7ffee46fd1c0
|
||||
0 Electron Framework 0x00000001181c78d9 base::debug::CollectStackTrace(void**, unsigned long) + 9
|
||||
1 Electron Framework 0x00000001180ea633 base::debug::StackTrace::StackTrace() + 19
|
||||
2 Electron Framework 0x000000011a04decd gin::(anonymous namespace)::PrintStackTrace() + 45
|
||||
3 Electron Framework 0x0000000119a9b416 V8_Fatal(char const*, int, char const*, ...) + 326
|
||||
4 Electron Framework 0x0000000119a9aeb5 v8::base::(anonymous namespace)::DefaultDcheckHandler(char const*, int, char const*) + 21
|
||||
5 Electron Framework 0x000000011530763f v8::internal::JSObject::GetEmbedderFieldOffset(int) + 207
|
||||
6 Electron Framework 0x00000001155f68e6 v8::internal::LocalEmbedderHeapTracer::EmbedderWriteBarrier(v8::internal::Heap*, v8::internal::JSObject) + 150
|
||||
7 Electron Framework 0x00000001152cd34f v8::Object::SetAlignedPointerInInternalField(int, void*) + 639
|
||||
8 Electron Framework 0x000000011d18df35 node::BaseObject::BaseObject(node::Environment*, v8::Local<v8::Object>) + 101
|
||||
9 Electron Framework 0x000000011d347b6e node::crypto::DiffieHellman::DiffieHellman(node::Environment*, v8::Local<v8::Object>) + 14
|
||||
10 Electron Framework 0x000000011d348413 node::crypto::DiffieHellman::New(v8::FunctionCallbackInfo<v8::Value> const&) + 147
|
||||
[...]
|
||||
|
||||
This crash happens because this V8 isolate has cppgc enabled. When cppgc is
|
||||
enabled, V8 assumes that the first embedder field is a "type" pointer, the
|
||||
first 16 bits of which are the embedder ID. Node did not adhere to this
|
||||
requirement. Sometimes--mostly, even--this worked _by accident_. If the first
|
||||
field in the BaseObject was a pointer to a bit of memory that happened to
|
||||
contain the two-byte little-endian value 0x0001, however, V8 would take that to
|
||||
mean that the object was a Blink object[1], and attempt to read the pointer in
|
||||
the second embedder slot, which would result in a CHECK.
|
||||
|
||||
This change adds an "embedder id" pointer as the first embedder field in all
|
||||
Node-managed objects. This ensures that cppgc will always skip over Node
|
||||
objects.
|
||||
|
||||
This patch should be upstreamed to Node.
|
||||
|
||||
[1]: https://source.chromium.org/chromium/chromium/src/+/main:gin/public/gin_embedders.h;l=20;drc=5a758a97032f0b656c3c36a3497560762495501a
|
||||
|
||||
See also: https://source.chromium.org/chromium/chromium/src/+/main:v8/include/v8-cppgc.h;l=70-76;drc=5a758a97032f0b656c3c36a3497560762495501a
|
||||
|
||||
diff --git a/src/base_object-inl.h b/src/base_object-inl.h
|
||||
index bb1e8d4b46bce3bf08f730ac5d43f7113d17ae39..6da0669943fc6465ffc47a1c8c3dadfea6beb1c9 100644
|
||||
--- a/src/base_object-inl.h
|
||||
+++ b/src/base_object-inl.h
|
||||
@@ -32,10 +32,21 @@
|
||||
|
||||
namespace node {
|
||||
|
||||
+namespace {
|
||||
+// This just has to be different from the Chromium ones:
|
||||
+// https://source.chromium.org/chromium/chromium/src/+/main:gin/public/gin_embedders.h;l=18-23;drc=5a758a97032f0b656c3c36a3497560762495501a
|
||||
+// Otherwise, when Node is loaded in an isolate which uses cppgc, cppgc will
|
||||
+// misinterpret the data stored in the embedder fields and try to garbage
|
||||
+// collect them.
|
||||
+static uint16_t kNodeEmbedderId = 0x90de;
|
||||
+}
|
||||
+
|
||||
BaseObject::BaseObject(Environment* env, v8::Local<v8::Object> object)
|
||||
: persistent_handle_(env->isolate(), object), env_(env) {
|
||||
CHECK_EQ(false, object.IsEmpty());
|
||||
- CHECK_GT(object->InternalFieldCount(), 0);
|
||||
+ CHECK_GT(object->InternalFieldCount(), BaseObject::kSlot);
|
||||
+ object->SetAlignedPointerInInternalField(BaseObject::kWrapperType,
|
||||
+ &kNodeEmbedderId);
|
||||
object->SetAlignedPointerInInternalField(
|
||||
BaseObject::kSlot,
|
||||
static_cast<void*>(this));
|
||||
@@ -151,7 +162,8 @@ bool BaseObject::IsWeakOrDetached() const {
|
||||
void BaseObject::LazilyInitializedJSTemplateConstructor(
|
||||
const v8::FunctionCallbackInfo<v8::Value>& args) {
|
||||
DCHECK(args.IsConstructCall());
|
||||
- DCHECK_GT(args.This()->InternalFieldCount(), 0);
|
||||
+ DCHECK_GT(args.This()->InternalFieldCount(), BaseObject::kSlot);
|
||||
+ args.This()->SetAlignedPointerInInternalField(BaseObject::kWrapperType, &kNodeEmbedderId);
|
||||
args.This()->SetAlignedPointerInInternalField(BaseObject::kSlot, nullptr);
|
||||
}
|
||||
|
||||
diff --git a/src/base_object.h b/src/base_object.h
|
||||
index d46a0f216009c63f45c440fc352b54d1ac4a08d8..81913c0d7762bf499ee19aaa3b63b986ca370bb4 100644
|
||||
--- a/src/base_object.h
|
||||
+++ b/src/base_object.h
|
||||
@@ -40,7 +40,7 @@ class TransferData;
|
||||
|
||||
class BaseObject : public MemoryRetainer {
|
||||
public:
|
||||
- enum InternalFields { kSlot, kInternalFieldCount };
|
||||
+ enum InternalFields { kWrapperType, kSlot, kInternalFieldCount };
|
||||
|
||||
// Associates this object with `object`. It uses the 0th internal field for
|
||||
// that, and in particular aborts if there is no such field.
|
||||
@@ -1794,11 +1794,11 @@ index 31e75367f8263f575f37243475acb58bb5c40d04..8f102792fe66847dad0ba7176299cf09
|
||||
// which the Node binary being built supports.
|
||||
diff --git a/tools/generate_gn_filenames_json.py b/tools/generate_gn_filenames_json.py
|
||||
new file mode 100755
|
||||
index 0000000000000000000000000000000000000000..8f884a41f57630ac432eb85ebfc9b8bc82cddaca
|
||||
index 0000000000000000000000000000000000000000..87621ba1d7f1c80aadb81461824b0c2edab1de22
|
||||
--- /dev/null
|
||||
+++ b/tools/generate_gn_filenames_json.py
|
||||
@@ -0,0 +1,75 @@
|
||||
+#!/usr/bin/env python
|
||||
+#!/usr/bin/env python3
|
||||
+import json
|
||||
+import os
|
||||
+import sys
|
||||
@@ -1875,11 +1875,11 @@ index 0000000000000000000000000000000000000000..8f884a41f57630ac432eb85ebfc9b8bc
|
||||
+ f.write('\n')
|
||||
diff --git a/tools/generate_node_version_header.py b/tools/generate_node_version_header.py
|
||||
new file mode 100755
|
||||
index 0000000000000000000000000000000000000000..3088ae4bdf814ae255c9805ebd393b2eee17e941
|
||||
index 0000000000000000000000000000000000000000..2a92eccfa582df361f2a889c0d9b32c1059baa7d
|
||||
--- /dev/null
|
||||
+++ b/tools/generate_node_version_header.py
|
||||
@@ -0,0 +1,25 @@
|
||||
+#!/usr/bin/env python
|
||||
+#!/usr/bin/env python3
|
||||
+import re
|
||||
+import sys
|
||||
+
|
||||
|
||||
54
patches/node/macos_don_t_use_thread-unsafe_strtok_3524.patch
Normal file
54
patches/node/macos_don_t_use_thread-unsafe_strtok_3524.patch
Normal file
@@ -0,0 +1,54 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Ben Noordhuis <info@bnoordhuis.nl>
|
||||
Date: Wed, 9 Mar 2022 11:06:39 +0100
|
||||
Subject: macos: don't use thread-unsafe strtok() (#3524)
|
||||
|
||||
Refs https://github.com/libuv/libuv/pull/3524
|
||||
|
||||
diff --git a/deps/uv/src/unix/process.c b/deps/uv/src/unix/process.c
|
||||
index 8cde389b826b6b167437845eccd5fed440dcadc4..147164e7ea25abbf655452930d78ee0a714cce36 100644
|
||||
--- a/deps/uv/src/unix/process.c
|
||||
+++ b/deps/uv/src/unix/process.c
|
||||
@@ -387,30 +387,22 @@ static void uv__spawn_init_posix_spawn_fncs(void) {
|
||||
|
||||
|
||||
static void uv__spawn_init_can_use_setsid(void) {
|
||||
- static const int MACOS_CATALINA_VERSION_MAJOR = 19;
|
||||
- char version_str[256];
|
||||
- char* version_major_str;
|
||||
- size_t version_str_size = 256;
|
||||
- int r;
|
||||
- int version_major;
|
||||
-
|
||||
- /* Get a version string */
|
||||
- r = sysctlbyname("kern.osrelease", version_str, &version_str_size, NULL, 0);
|
||||
- if (r != 0)
|
||||
+ int which[] = {CTL_KERN, KERN_OSRELEASE};
|
||||
+ unsigned major;
|
||||
+ unsigned minor;
|
||||
+ unsigned patch;
|
||||
+ char buf[256];
|
||||
+ size_t len;
|
||||
+
|
||||
+ len = sizeof(buf);
|
||||
+ if (sysctl(which, ARRAY_SIZE(which), buf, &len, NULL, 0))
|
||||
return;
|
||||
|
||||
- /* Try to get the major version number. If not found
|
||||
- * fall back to the fork/exec flow */
|
||||
- version_major_str = strtok(version_str, ".");
|
||||
- if (version_major_str == NULL)
|
||||
+ /* NULL specifies to use LC_C_LOCALE */
|
||||
+ if (3 != sscanf_l(buf, NULL, "%u.%u.%u", &major, &minor, &patch))
|
||||
return;
|
||||
|
||||
- /* Parse the version major as a number. If it is greater than
|
||||
- * the major version for macOS Catalina (aka macOS 10.15), then
|
||||
- * the POSIX_SPAWN_SETSID flag is available */
|
||||
- version_major = atoi_l(version_major_str, NULL); /* Use LC_C_LOCALE */
|
||||
- if (version_major >= MACOS_CATALINA_VERSION_MAJOR)
|
||||
- posix_spawn_can_use_setsid = 1;
|
||||
+ posix_spawn_can_use_setsid = (major >= 19); /* macOS Catalina */
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,70 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Jameson Nash <vtjnash@gmail.com>
|
||||
Date: Tue, 1 Feb 2022 15:27:12 -0500
|
||||
Subject: process,bsd: handle kevent NOTE_EXIT failure (#3451)
|
||||
|
||||
The kernel may return ESRCH if the child has already exited here.
|
||||
This is rather annoying, and means we must indirectly handle
|
||||
notification to our event loop of the process exit.
|
||||
|
||||
Refs: https://github.com/libuv/libuv/pull/3441
|
||||
Refs: https://github.com/libuv/libuv/pull/3257
|
||||
|
||||
diff --git a/deps/uv/src/unix/internal.h b/deps/uv/src/unix/internal.h
|
||||
index 16be13b99f5db77741aa276e90a437ef4eb5ba32..2dcc8b32f5165dd75061a1b55cc1abd2ab93ccc9 100644
|
||||
--- a/deps/uv/src/unix/internal.h
|
||||
+++ b/deps/uv/src/unix/internal.h
|
||||
@@ -145,7 +145,8 @@ typedef struct uv__stream_queued_fds_s uv__stream_queued_fds_t;
|
||||
|
||||
/* loop flags */
|
||||
enum {
|
||||
- UV_LOOP_BLOCK_SIGPROF = 1
|
||||
+ UV_LOOP_BLOCK_SIGPROF = 0x1,
|
||||
+ UV_LOOP_REAP_CHILDREN = 0x2
|
||||
};
|
||||
|
||||
/* flags of excluding ifaddr */
|
||||
diff --git a/deps/uv/src/unix/kqueue.c b/deps/uv/src/unix/kqueue.c
|
||||
index 35200f17495d80ed2d19ef9f6f76bbc92ee042f6..071fe0ce0938657d0fb840af62a432352e938a8a 100644
|
||||
--- a/deps/uv/src/unix/kqueue.c
|
||||
+++ b/deps/uv/src/unix/kqueue.c
|
||||
@@ -285,7 +285,7 @@ void uv__io_poll(uv_loop_t* loop, int timeout) {
|
||||
for (i = 0; i < nfds; i++) {
|
||||
ev = events + i;
|
||||
if (ev->filter == EVFILT_PROC) {
|
||||
- uv__wait_children(loop);
|
||||
+ loop->flags |= UV_LOOP_REAP_CHILDREN;
|
||||
nevents++;
|
||||
continue;
|
||||
}
|
||||
@@ -383,6 +383,11 @@ void uv__io_poll(uv_loop_t* loop, int timeout) {
|
||||
nevents++;
|
||||
}
|
||||
|
||||
+ if (loop->flags & UV_LOOP_REAP_CHILDREN) {
|
||||
+ loop->flags &= ~UV_LOOP_REAP_CHILDREN;
|
||||
+ uv__wait_children(loop);
|
||||
+ }
|
||||
+
|
||||
if (reset_timeout != 0) {
|
||||
timeout = user_timeout;
|
||||
reset_timeout = 0;
|
||||
diff --git a/deps/uv/src/unix/process.c b/deps/uv/src/unix/process.c
|
||||
index c1f6bd4b0076f0835caf83c45a6a896e7ae5def9..2920b942962357827bae9bcad23af8333e8b007f 100644
|
||||
--- a/deps/uv/src/unix/process.c
|
||||
+++ b/deps/uv/src/unix/process.c
|
||||
@@ -507,8 +507,12 @@ int uv_spawn(uv_loop_t* loop,
|
||||
#if defined(__APPLE__) || defined(__DragonFly__) || defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__)
|
||||
struct kevent event;
|
||||
EV_SET(&event, pid, EVFILT_PROC, EV_ADD | EV_ONESHOT, NOTE_EXIT, 0, 0);
|
||||
- if (kevent(loop->backend_fd, &event, 1, NULL, 0, NULL))
|
||||
- abort();
|
||||
+ if (kevent(loop->backend_fd, &event, 1, NULL, 0, NULL)) {
|
||||
+ if (errno != ESRCH)
|
||||
+ abort();
|
||||
+ /* Process already exited. Call waitpid on the next loop iteration. */
|
||||
+ loop->flags |= UV_LOOP_REAP_CHILDREN;
|
||||
+ }
|
||||
#endif
|
||||
|
||||
QUEUE_INSERT_TAIL(&loop->process_handles, &process->queue);
|
||||
158
patches/node/process_fix_hang_after_note_exit_3521.patch
Normal file
158
patches/node/process_fix_hang_after_note_exit_3521.patch
Normal file
@@ -0,0 +1,158 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Jameson Nash <vtjnash@gmail.com>
|
||||
Date: Wed, 23 Mar 2022 15:39:38 +0900
|
||||
Subject: process: fix hang after NOTE_EXIT (#3521)
|
||||
|
||||
Bug #3504 seems to affect more platforms than just OpenBSD. As this
|
||||
seems to be a race condition in these kernels, we do not want to fail
|
||||
because of it. Instead, we remove the WNOHANG flag from waitpid, and
|
||||
track exactly which processes have exited. Should also be a slight speed
|
||||
improvement for excessively large numbers of live children.
|
||||
|
||||
diff --git a/deps/uv/src/unix/kqueue.c b/deps/uv/src/unix/kqueue.c
|
||||
index 071fe0ce0938657d0fb840af62a432352e938a8a..4c4d990ff5fa6c8ab937be2e4f79ccdaf90670c2 100644
|
||||
--- a/deps/uv/src/unix/kqueue.c
|
||||
+++ b/deps/uv/src/unix/kqueue.c
|
||||
@@ -117,6 +117,7 @@ void uv__io_poll(uv_loop_t* loop, int timeout) {
|
||||
unsigned int revents;
|
||||
QUEUE* q;
|
||||
uv__io_t* w;
|
||||
+ uv_process_t* process;
|
||||
sigset_t* pset;
|
||||
sigset_t set;
|
||||
uint64_t base;
|
||||
@@ -284,12 +285,22 @@ void uv__io_poll(uv_loop_t* loop, int timeout) {
|
||||
loop->watchers[loop->nwatchers + 1] = (void*) (uintptr_t) nfds;
|
||||
for (i = 0; i < nfds; i++) {
|
||||
ev = events + i;
|
||||
+ fd = ev->ident;
|
||||
+
|
||||
+ /* Handle kevent NOTE_EXIT results */
|
||||
if (ev->filter == EVFILT_PROC) {
|
||||
- loop->flags |= UV_LOOP_REAP_CHILDREN;
|
||||
+ QUEUE_FOREACH(q, &loop->process_handles) {
|
||||
+ process = QUEUE_DATA(q, uv_process_t, queue);
|
||||
+ if (process->pid == fd) {
|
||||
+ process->flags |= UV_HANDLE_REAP;
|
||||
+ loop->flags |= UV_LOOP_REAP_CHILDREN;
|
||||
+ break;
|
||||
+ }
|
||||
+ }
|
||||
nevents++;
|
||||
continue;
|
||||
}
|
||||
- fd = ev->ident;
|
||||
+
|
||||
/* Skip invalidated events, see uv__platform_invalidate_fd */
|
||||
if (fd == -1)
|
||||
continue;
|
||||
diff --git a/deps/uv/src/unix/process.c b/deps/uv/src/unix/process.c
|
||||
index 147164e7ea25abbf655452930d78ee0a714cce36..c8816b85b7e531648064e739fb89257565ad64bb 100644
|
||||
--- a/deps/uv/src/unix/process.c
|
||||
+++ b/deps/uv/src/unix/process.c
|
||||
@@ -63,12 +63,18 @@ extern char **environ;
|
||||
# include "zos-base.h"
|
||||
#endif
|
||||
|
||||
-#if defined(__APPLE__) || defined(__DragonFly__) || defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__)
|
||||
+#if defined(__APPLE__) || \
|
||||
+ defined(__DragonFly__) || \
|
||||
+ defined(__FreeBSD__) || \
|
||||
+ defined(__NetBSD__) || \
|
||||
+ defined(__OpenBSD__)
|
||||
#include <sys/event.h>
|
||||
+#else
|
||||
+#define UV_USE_SIGCHLD
|
||||
#endif
|
||||
|
||||
|
||||
-#if !(defined(__APPLE__) || defined(__DragonFly__) || defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__))
|
||||
+#ifdef UV_USE_SIGCHLD
|
||||
static void uv__chld(uv_signal_t* handle, int signum) {
|
||||
assert(signum == SIGCHLD);
|
||||
uv__wait_children(handle->loop);
|
||||
@@ -80,6 +86,7 @@ void uv__wait_children(uv_loop_t* loop) {
|
||||
int exit_status;
|
||||
int term_signal;
|
||||
int status;
|
||||
+ int options;
|
||||
pid_t pid;
|
||||
QUEUE pending;
|
||||
QUEUE* q;
|
||||
@@ -93,19 +100,33 @@ void uv__wait_children(uv_loop_t* loop) {
|
||||
process = QUEUE_DATA(q, uv_process_t, queue);
|
||||
q = QUEUE_NEXT(q);
|
||||
|
||||
+#ifndef UV_USE_SIGCHLD
|
||||
+ if ((process->flags & UV_HANDLE_REAP) == 0)
|
||||
+ continue;
|
||||
+ options = 0;
|
||||
+ process->flags &= ~UV_HANDLE_REAP;
|
||||
+#else
|
||||
+ options = WNOHANG;
|
||||
+#endif
|
||||
+
|
||||
do
|
||||
- pid = waitpid(process->pid, &status, WNOHANG);
|
||||
+ pid = waitpid(process->pid, &status, options);
|
||||
while (pid == -1 && errno == EINTR);
|
||||
|
||||
- if (pid == 0)
|
||||
+#ifdef UV_USE_SIGCHLD
|
||||
+ if (pid == 0) /* Not yet exited */
|
||||
continue;
|
||||
+#endif
|
||||
|
||||
if (pid == -1) {
|
||||
if (errno != ECHILD)
|
||||
abort();
|
||||
+ /* The child died, and we missed it. This probably means someone else
|
||||
+ * stole the waitpid from us. Handle this by not handling it at all. */
|
||||
continue;
|
||||
}
|
||||
|
||||
+ assert(pid == process->pid);
|
||||
process->status = status;
|
||||
QUEUE_REMOVE(&process->queue);
|
||||
QUEUE_INSERT_TAIL(&pending, &process->queue);
|
||||
@@ -964,7 +985,7 @@ int uv_spawn(uv_loop_t* loop,
|
||||
goto error;
|
||||
}
|
||||
|
||||
-#if !(defined(__APPLE__) || defined(__DragonFly__) || defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__))
|
||||
+#ifdef UV_USE_SIGCHLD
|
||||
uv_signal_start(&loop->child_watcher, uv__chld, SIGCHLD);
|
||||
#endif
|
||||
|
||||
@@ -983,13 +1004,14 @@ int uv_spawn(uv_loop_t* loop,
|
||||
* fail to open a stdio handle. This ensures we can eventually reap the child
|
||||
* with waitpid. */
|
||||
if (exec_errorno == 0) {
|
||||
-#if defined(__APPLE__) || defined(__DragonFly__) || defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__)
|
||||
+#ifndef UV_USE_SIGCHLD
|
||||
struct kevent event;
|
||||
EV_SET(&event, pid, EVFILT_PROC, EV_ADD | EV_ONESHOT, NOTE_EXIT, 0, 0);
|
||||
if (kevent(loop->backend_fd, &event, 1, NULL, 0, NULL)) {
|
||||
if (errno != ESRCH)
|
||||
abort();
|
||||
/* Process already exited. Call waitpid on the next loop iteration. */
|
||||
+ process->flags |= UV_HANDLE_REAP;
|
||||
loop->flags |= UV_LOOP_REAP_CHILDREN;
|
||||
}
|
||||
#endif
|
||||
diff --git a/deps/uv/src/uv-common.h b/deps/uv/src/uv-common.h
|
||||
index 8a190bf8fa8c5a282feaf251aec2a30c95776888..6001b0cf68d0b0268b578218b664a737f43c9521 100644
|
||||
--- a/deps/uv/src/uv-common.h
|
||||
+++ b/deps/uv/src/uv-common.h
|
||||
@@ -130,7 +130,10 @@ enum {
|
||||
UV_SIGNAL_ONE_SHOT = 0x02000000,
|
||||
|
||||
/* Only used by uv_poll_t handles. */
|
||||
- UV_HANDLE_POLL_SLOW = 0x01000000
|
||||
+ UV_HANDLE_POLL_SLOW = 0x01000000,
|
||||
+
|
||||
+ /* Only used by uv_process_t handles. */
|
||||
+ UV_HANDLE_REAP = 0x10000000
|
||||
};
|
||||
|
||||
int uv__loop_configure(uv_loop_t* loop, uv_loop_option option, va_list ap);
|
||||
@@ -0,0 +1,170 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Jeremy Rose <nornagon@nornagon.net>
|
||||
Date: Mon, 31 Jan 2022 11:49:22 -0800
|
||||
Subject: process: monitor for exit with kqueue on BSDs (#3441)
|
||||
|
||||
This adds a workaround for an xnu kernel bug that sometimes results in
|
||||
SIGCHLD not being delivered. The workaround is to use kevent to listen
|
||||
for EVFILT_PROC/NOTE_EXIT events instead of relying on SIGCHLD on *BSD.
|
||||
|
||||
Apple rdar: FB9529664
|
||||
Refs: https://github.com/libuv/libuv/pull/3257
|
||||
|
||||
diff --git a/deps/uv/src/unix/internal.h b/deps/uv/src/unix/internal.h
|
||||
index 12d4da93686e993830a7d09e74d08191fc808f4f..16be13b99f5db77741aa276e90a437ef4eb5ba32 100644
|
||||
--- a/deps/uv/src/unix/internal.h
|
||||
+++ b/deps/uv/src/unix/internal.h
|
||||
@@ -282,6 +282,7 @@ uv_handle_type uv__handle_type(int fd);
|
||||
FILE* uv__open_file(const char* path);
|
||||
int uv__getpwuid_r(uv_passwd_t* pwd);
|
||||
int uv__search_path(const char* prog, char* buf, size_t* buflen);
|
||||
+void uv__wait_children(uv_loop_t* loop);
|
||||
|
||||
/* random */
|
||||
int uv__random_devurandom(void* buf, size_t buflen);
|
||||
diff --git a/deps/uv/src/unix/kqueue.c b/deps/uv/src/unix/kqueue.c
|
||||
index bf183d5fdc0ba89913469a294322eef84bc4cee8..35200f17495d80ed2d19ef9f6f76bbc92ee042f6 100644
|
||||
--- a/deps/uv/src/unix/kqueue.c
|
||||
+++ b/deps/uv/src/unix/kqueue.c
|
||||
@@ -284,6 +284,11 @@ void uv__io_poll(uv_loop_t* loop, int timeout) {
|
||||
loop->watchers[loop->nwatchers + 1] = (void*) (uintptr_t) nfds;
|
||||
for (i = 0; i < nfds; i++) {
|
||||
ev = events + i;
|
||||
+ if (ev->filter == EVFILT_PROC) {
|
||||
+ uv__wait_children(loop);
|
||||
+ nevents++;
|
||||
+ continue;
|
||||
+ }
|
||||
fd = ev->ident;
|
||||
/* Skip invalidated events, see uv__platform_invalidate_fd */
|
||||
if (fd == -1)
|
||||
diff --git a/deps/uv/src/unix/process.c b/deps/uv/src/unix/process.c
|
||||
index f4aebb0490e198cd9adcadfeb6b006de479cc993..cfcba341e0e380ecd595e4b59e39c08a7b374a48 100644
|
||||
--- a/deps/uv/src/unix/process.c
|
||||
+++ b/deps/uv/src/unix/process.c
|
||||
@@ -48,10 +48,20 @@ extern char **environ;
|
||||
# include "zos-base.h"
|
||||
#endif
|
||||
|
||||
+#if defined(__APPLE__) || defined(__DragonFly__) || defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__)
|
||||
+#include <sys/event.h>
|
||||
+#endif
|
||||
+
|
||||
|
||||
+#if !(defined(__APPLE__) || defined(__DragonFly__) || defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__))
|
||||
static void uv__chld(uv_signal_t* handle, int signum) {
|
||||
+ assert(signum == SIGCHLD);
|
||||
+ uv__wait_children(handle->loop);
|
||||
+}
|
||||
+#endif
|
||||
+
|
||||
+void uv__wait_children(uv_loop_t* loop) {
|
||||
uv_process_t* process;
|
||||
- uv_loop_t* loop;
|
||||
int exit_status;
|
||||
int term_signal;
|
||||
int status;
|
||||
@@ -60,10 +70,7 @@ static void uv__chld(uv_signal_t* handle, int signum) {
|
||||
QUEUE* q;
|
||||
QUEUE* h;
|
||||
|
||||
- assert(signum == SIGCHLD);
|
||||
-
|
||||
QUEUE_INIT(&pending);
|
||||
- loop = handle->loop;
|
||||
|
||||
h = &loop->process_handles;
|
||||
q = QUEUE_HEAD(h);
|
||||
@@ -419,7 +426,9 @@ int uv_spawn(uv_loop_t* loop,
|
||||
if (err)
|
||||
goto error;
|
||||
|
||||
+#if !(defined(__APPLE__) || defined(__DragonFly__) || defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__))
|
||||
uv_signal_start(&loop->child_watcher, uv__chld, SIGCHLD);
|
||||
+#endif
|
||||
|
||||
/* Acquire write lock to prevent opening new fds in worker threads */
|
||||
uv_rwlock_wrlock(&loop->cloexec_lock);
|
||||
@@ -478,6 +487,13 @@ int uv_spawn(uv_loop_t* loop,
|
||||
|
||||
/* Only activate this handle if exec() happened successfully */
|
||||
if (exec_errorno == 0) {
|
||||
+#if defined(__APPLE__) || defined(__DragonFly__) || defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__)
|
||||
+ struct kevent event;
|
||||
+ EV_SET(&event, pid, EVFILT_PROC, EV_ADD | EV_ONESHOT, NOTE_EXIT, 0, 0);
|
||||
+ if (kevent(loop->backend_fd, &event, 1, NULL, 0, NULL))
|
||||
+ abort();
|
||||
+#endif
|
||||
+
|
||||
QUEUE_INSERT_TAIL(&loop->process_handles, &process->queue);
|
||||
uv__handle_start(process);
|
||||
}
|
||||
diff --git a/deps/uv/test/test-list.h b/deps/uv/test/test-list.h
|
||||
index 59b95da9ebe3464bd1f9ce1c534122b1f9e06636..58489c4be7b3a7b36d5b01a1f07d411ef3d99ae3 100644
|
||||
--- a/deps/uv/test/test-list.h
|
||||
+++ b/deps/uv/test/test-list.h
|
||||
@@ -318,6 +318,7 @@ TEST_DECLARE (spawn_reads_child_path)
|
||||
TEST_DECLARE (spawn_inherit_streams)
|
||||
TEST_DECLARE (spawn_quoted_path)
|
||||
TEST_DECLARE (spawn_tcp_server)
|
||||
+TEST_DECLARE (spawn_exercise_sigchld_issue)
|
||||
TEST_DECLARE (fs_poll)
|
||||
TEST_DECLARE (fs_poll_getpath)
|
||||
TEST_DECLARE (fs_poll_close_request)
|
||||
@@ -944,6 +945,7 @@ TASK_LIST_START
|
||||
TEST_ENTRY (spawn_inherit_streams)
|
||||
TEST_ENTRY (spawn_quoted_path)
|
||||
TEST_ENTRY (spawn_tcp_server)
|
||||
+ TEST_ENTRY (spawn_exercise_sigchld_issue)
|
||||
TEST_ENTRY (fs_poll)
|
||||
TEST_ENTRY (fs_poll_getpath)
|
||||
TEST_ENTRY (fs_poll_close_request)
|
||||
diff --git a/deps/uv/test/test-spawn.c b/deps/uv/test/test-spawn.c
|
||||
index 9f2eb24b2d6daf339bec12027134409cfc3b4a82..dfd5458ef37c664af9a55a8383bdb3121885db3b 100644
|
||||
--- a/deps/uv/test/test-spawn.c
|
||||
+++ b/deps/uv/test/test-spawn.c
|
||||
@@ -1891,6 +1891,44 @@ TEST_IMPL(spawn_quoted_path) {
|
||||
#endif
|
||||
}
|
||||
|
||||
+TEST_IMPL(spawn_exercise_sigchld_issue) {
|
||||
+ int r;
|
||||
+ int i;
|
||||
+ uv_process_options_t dummy_options = {0};
|
||||
+ uv_process_t dummy_processes[100];
|
||||
+ char* args[2];
|
||||
+
|
||||
+ init_process_options("spawn_helper1", exit_cb);
|
||||
+
|
||||
+ r = uv_spawn(uv_default_loop(), &process, &options);
|
||||
+ ASSERT_EQ(r, 0);
|
||||
+
|
||||
+ // This test exercises a bug in the darwin kernel that causes SIGCHLD not to
|
||||
+ // be delivered sometimes. Calling posix_spawn many times increases the
|
||||
+ // likelihood of encountering this issue, so spin a few times to make this
|
||||
+ // test more reliable.
|
||||
+ dummy_options.file = args[0] = "program-that-had-better-not-exist";
|
||||
+ args[1] = NULL;
|
||||
+ dummy_options.args = args;
|
||||
+ dummy_options.exit_cb = fail_cb;
|
||||
+ dummy_options.flags = 0;
|
||||
+ for (i = 0; i < 100; i++) {
|
||||
+ r = uv_spawn(uv_default_loop(), &dummy_processes[i], &dummy_options);
|
||||
+ if (r != UV_ENOENT)
|
||||
+ ASSERT_EQ(r, UV_EACCES);
|
||||
+ uv_close((uv_handle_t*) &dummy_processes[i], close_cb);
|
||||
+ }
|
||||
+
|
||||
+ r = uv_run(uv_default_loop(), UV_RUN_DEFAULT);
|
||||
+ ASSERT_EQ(r, 0);
|
||||
+
|
||||
+ ASSERT_EQ(exit_cb_called, 1);
|
||||
+ ASSERT_EQ(close_cb_called, 101);
|
||||
+
|
||||
+ MAKE_VALGRIND_HAPPY();
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
/* Helper for child process of spawn_inherit_streams */
|
||||
#ifndef _WIN32
|
||||
void spawn_stdin_stdout(void) {
|
||||
@@ -0,0 +1,54 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Jameson Nash <vtjnash@gmail.com>
|
||||
Date: Sat, 5 Mar 2022 12:52:04 -0500
|
||||
Subject: process: only use F_DUPFD_CLOEXEC if it is defined (#3512)
|
||||
|
||||
We can save a syscall on most modern systems (required by POSIX 2008),
|
||||
but not on all systems.
|
||||
|
||||
Also handle errors from CLOEXEC. Even though fcntl does not really
|
||||
define there to be any, it could theoretically be EBADF if the user
|
||||
happened to pass a bad file descriptor to the same number fd (such that
|
||||
no other code happened to already fail on that).
|
||||
|
||||
diff --git a/deps/uv/src/unix/process.c b/deps/uv/src/unix/process.c
|
||||
index d208f99be40df9f36447552daf2772c1cab1ce79..7705068730cb0536998bad7d304cb87df99b72e8 100644
|
||||
--- a/deps/uv/src/unix/process.c
|
||||
+++ b/deps/uv/src/unix/process.c
|
||||
@@ -275,9 +275,20 @@ static void uv__process_child_init(const uv_process_options_t* options,
|
||||
use_fd = pipes[fd][1];
|
||||
if (use_fd < 0 || use_fd >= fd)
|
||||
continue;
|
||||
+#ifdef F_DUPFD_CLOEXEC /* POSIX 2008 */
|
||||
pipes[fd][1] = fcntl(use_fd, F_DUPFD_CLOEXEC, stdio_count);
|
||||
+#else
|
||||
+ pipes[fd][1] = fcntl(use_fd, F_DUPFD, stdio_count);
|
||||
+#endif
|
||||
if (pipes[fd][1] == -1)
|
||||
uv__write_errno(error_fd);
|
||||
+#ifndef F_DUPFD_CLOEXEC /* POSIX 2008 */
|
||||
+ n = uv__cloexec_fcntl(pipes[fd][1], 1);
|
||||
+ if (n) {
|
||||
+ uv__write_int(error_fd, n);
|
||||
+ _exit(127);
|
||||
+ }
|
||||
+#endif
|
||||
}
|
||||
|
||||
for (fd = 0; fd < stdio_count; fd++) {
|
||||
@@ -300,8 +311,13 @@ static void uv__process_child_init(const uv_process_options_t* options,
|
||||
}
|
||||
|
||||
if (fd == use_fd) {
|
||||
- if (close_fd == -1)
|
||||
- uv__cloexec_fcntl(use_fd, 0);
|
||||
+ if (close_fd == -1) {
|
||||
+ n = uv__cloexec_fcntl(use_fd, 0);
|
||||
+ if (n) {
|
||||
+ uv__write_int(error_fd, n);
|
||||
+ _exit(127);
|
||||
+ }
|
||||
+ }
|
||||
}
|
||||
else {
|
||||
fd = dup2(use_fd, fd);
|
||||
@@ -0,0 +1,36 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Jameson Nash <vtjnash@gmail.com>
|
||||
Date: Fri, 11 Mar 2022 12:05:24 -0500
|
||||
Subject: process: reset the signal mask if the fork fails (#3537)
|
||||
|
||||
Fix a regression that sneaked into posix spawn changes.
|
||||
|
||||
Refs: https://github.com/libuv/libuv/pull/3257
|
||||
|
||||
diff --git a/deps/uv/src/unix/process.c b/deps/uv/src/unix/process.c
|
||||
index b85aa3b94edd040952e0d350a47a38d9ba8a67d3..d208f99be40df9f36447552daf2772c1cab1ce79 100644
|
||||
--- a/deps/uv/src/unix/process.c
|
||||
+++ b/deps/uv/src/unix/process.c
|
||||
@@ -790,11 +790,6 @@ static int uv__spawn_and_init_child_fork(const uv_process_options_t* options,
|
||||
|
||||
*pid = fork();
|
||||
|
||||
- if (*pid == -1) {
|
||||
- /* Failed to fork */
|
||||
- return UV__ERR(errno);
|
||||
- }
|
||||
-
|
||||
if (*pid == 0) {
|
||||
/* Fork succeeded, in the child process */
|
||||
uv__process_child_init(options, stdio_count, pipes, error_fd);
|
||||
@@ -804,6 +799,10 @@ static int uv__spawn_and_init_child_fork(const uv_process_options_t* options,
|
||||
if (pthread_sigmask(SIG_SETMASK, &sigoldset, NULL) != 0)
|
||||
abort();
|
||||
|
||||
+ if (*pid == -1)
|
||||
+ /* Failed to fork */
|
||||
+ return UV__ERR(errno);
|
||||
+
|
||||
/* Fork succeeded, in the parent process */
|
||||
return 0;
|
||||
}
|
||||
63
patches/node/process_simplify_uv_write_int_calls_3519.patch
Normal file
63
patches/node/process_simplify_uv_write_int_calls_3519.patch
Normal file
@@ -0,0 +1,63 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Jameson Nash <vtjnash@gmail.com>
|
||||
Date: Mon, 7 Mar 2022 17:07:49 -0500
|
||||
Subject: process: simplify uv__write_int calls (#3519)
|
||||
|
||||
Refs https://github.com/libuv/libuv/pull/3519
|
||||
|
||||
diff --git a/deps/uv/src/unix/process.c b/deps/uv/src/unix/process.c
|
||||
index b6f9756c6a6710f5f10762b9299cc35047b98097..8cde389b826b6b167437845eccd5fed440dcadc4 100644
|
||||
--- a/deps/uv/src/unix/process.c
|
||||
+++ b/deps/uv/src/unix/process.c
|
||||
@@ -216,16 +216,14 @@ static void uv__write_int(int fd, int val) {
|
||||
n = write(fd, &val, sizeof(val));
|
||||
while (n == -1 && errno == EINTR);
|
||||
|
||||
- if (n == -1 && errno == EPIPE)
|
||||
- return; /* parent process has quit */
|
||||
-
|
||||
- assert(n == sizeof(val));
|
||||
+ /* The write might have failed (e.g. if the parent process has died),
|
||||
+ * but we have nothing left but to _exit ourself now too. */
|
||||
+ _exit(127);
|
||||
}
|
||||
|
||||
|
||||
static void uv__write_errno(int error_fd) {
|
||||
uv__write_int(error_fd, UV__ERR(errno));
|
||||
- _exit(127);
|
||||
}
|
||||
|
||||
|
||||
@@ -284,10 +282,8 @@ static void uv__process_child_init(const uv_process_options_t* options,
|
||||
uv__write_errno(error_fd);
|
||||
#ifndef F_DUPFD_CLOEXEC /* POSIX 2008 */
|
||||
n = uv__cloexec(pipes[fd][1], 1);
|
||||
- if (n) {
|
||||
+ if (n)
|
||||
uv__write_int(error_fd, n);
|
||||
- _exit(127);
|
||||
- }
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -313,10 +309,8 @@ static void uv__process_child_init(const uv_process_options_t* options,
|
||||
if (fd == use_fd) {
|
||||
if (close_fd == -1) {
|
||||
n = uv__cloexec(use_fd, 0);
|
||||
- if (n) {
|
||||
+ if (n)
|
||||
uv__write_int(error_fd, n);
|
||||
- _exit(127);
|
||||
- }
|
||||
}
|
||||
}
|
||||
else {
|
||||
@@ -368,7 +362,6 @@ static void uv__process_child_init(const uv_process_options_t* options,
|
||||
#endif
|
||||
|
||||
uv__write_errno(error_fd);
|
||||
- abort();
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -0,0 +1,889 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Jameson Nash <vtjnash@gmail.com>
|
||||
Date: Wed, 2 Mar 2022 15:15:39 -0500
|
||||
Subject: Reland "macos: use posix_spawn instead of fork" (#3257)
|
||||
|
||||
Fixes: https://github.com/libuv/libuv/issues/3050
|
||||
Refs: https://github.com/libuv/libuv/issues/3086
|
||||
Refs: https://github.com/libuv/libuv/pull/3064
|
||||
Refs: https://github.com/libuv/libuv/pull/3107
|
||||
Refs: https://github.com/libuv/libuv/pull/3064
|
||||
|
||||
This reverts commit 217fdf4265589889d00c7c0622fde2710971a020, then fixes
|
||||
several issues with it:
|
||||
|
||||
* remove error fast-cleanup code that triggers a nodejs bug
|
||||
|
||||
Refs: https://github.com/libuv/libuv/pull/3107#issuecomment-782482608
|
||||
|
||||
* protect posix_spawn from EINTR
|
||||
|
||||
This is not a documented valid error, but seems to have been observed.
|
||||
|
||||
* ignore setuid/setgid syscall
|
||||
|
||||
This kernel function is not permitted unless the process is setuid root,
|
||||
so disable this syscall. Falling back to fork/exec should be okay for
|
||||
the rare cases that the user decides they need to do setuid(getuid()) or
|
||||
setuid(geteuid()) for the child.
|
||||
|
||||
Refs: https://github.com/libuv/libuv/pull/3107#issuecomment-782482608
|
||||
|
||||
* improve posix_spawn path search
|
||||
|
||||
Ports the improvements in musl back to this function
|
||||
|
||||
* fix some additional problems and formatting issues
|
||||
|
||||
We previously might fail to start a watcher, in rare failure cases,
|
||||
resulting in a zombie that we would fail to kill. Also avoid creating
|
||||
the signal-pipe unless required (addresses a review comment from Apple)
|
||||
|
||||
* fix fd->fd mapping reuse
|
||||
|
||||
There was a chance that when duplicating the fd's into stdio_count+fd we
|
||||
might be closing a currently opened fd with that value.
|
||||
|
||||
diff --git a/deps/uv/src/unix/process.c b/deps/uv/src/unix/process.c
|
||||
index 2920b942962357827bae9bcad23af8333e8b007f..b85aa3b94edd040952e0d350a47a38d9ba8a67d3 100644
|
||||
--- a/deps/uv/src/unix/process.c
|
||||
+++ b/deps/uv/src/unix/process.c
|
||||
@@ -27,6 +27,7 @@
|
||||
#include <assert.h>
|
||||
#include <errno.h>
|
||||
#include <signal.h>
|
||||
+#include <string.h>
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/wait.h>
|
||||
@@ -35,8 +36,21 @@
|
||||
#include <poll.h>
|
||||
|
||||
#if defined(__APPLE__) && !TARGET_OS_IPHONE
|
||||
+# include <spawn.h>
|
||||
+# include <paths.h>
|
||||
+# include <sys/kauth.h>
|
||||
+# include <sys/types.h>
|
||||
+# include <sys/sysctl.h>
|
||||
+# include <dlfcn.h>
|
||||
# include <crt_externs.h>
|
||||
+# include <xlocale.h>
|
||||
# define environ (*_NSGetEnviron())
|
||||
+
|
||||
+/* macOS 10.14 back does not define this constant */
|
||||
+# ifndef POSIX_SPAWN_SETSID
|
||||
+# define POSIX_SPAWN_SETSID 1024
|
||||
+# endif
|
||||
+
|
||||
#else
|
||||
extern char **environ;
|
||||
#endif
|
||||
@@ -261,22 +275,22 @@ static void uv__process_child_init(const uv_process_options_t* options,
|
||||
use_fd = pipes[fd][1];
|
||||
if (use_fd < 0 || use_fd >= fd)
|
||||
continue;
|
||||
- pipes[fd][1] = fcntl(use_fd, F_DUPFD, stdio_count);
|
||||
+ pipes[fd][1] = fcntl(use_fd, F_DUPFD_CLOEXEC, stdio_count);
|
||||
if (pipes[fd][1] == -1)
|
||||
uv__write_errno(error_fd);
|
||||
}
|
||||
|
||||
for (fd = 0; fd < stdio_count; fd++) {
|
||||
- close_fd = pipes[fd][0];
|
||||
+ close_fd = -1;
|
||||
use_fd = pipes[fd][1];
|
||||
|
||||
if (use_fd < 0) {
|
||||
if (fd >= 3)
|
||||
continue;
|
||||
else {
|
||||
- /* redirect stdin, stdout and stderr to /dev/null even if UV_IGNORE is
|
||||
- * set
|
||||
- */
|
||||
+ /* Redirect stdin, stdout and stderr to /dev/null even if UV_IGNORE is
|
||||
+ * set. */
|
||||
+ uv__close_nocheckstdio(fd); /* Free up fd, if it happens to be open. */
|
||||
use_fd = open("/dev/null", fd == 0 ? O_RDONLY : O_RDWR);
|
||||
close_fd = use_fd;
|
||||
|
||||
@@ -285,28 +299,24 @@ static void uv__process_child_init(const uv_process_options_t* options,
|
||||
}
|
||||
}
|
||||
|
||||
- if (fd == use_fd)
|
||||
- uv__cloexec_fcntl(use_fd, 0);
|
||||
- else
|
||||
+ if (fd == use_fd) {
|
||||
+ if (close_fd == -1)
|
||||
+ uv__cloexec_fcntl(use_fd, 0);
|
||||
+ }
|
||||
+ else {
|
||||
fd = dup2(use_fd, fd);
|
||||
+ }
|
||||
|
||||
if (fd == -1)
|
||||
uv__write_errno(error_fd);
|
||||
|
||||
- if (fd <= 2)
|
||||
+ if (fd <= 2 && close_fd == -1)
|
||||
uv__nonblock_fcntl(fd, 0);
|
||||
|
||||
if (close_fd >= stdio_count)
|
||||
uv__close(close_fd);
|
||||
}
|
||||
|
||||
- for (fd = 0; fd < stdio_count; fd++) {
|
||||
- use_fd = pipes[fd][1];
|
||||
-
|
||||
- if (use_fd >= stdio_count)
|
||||
- uv__close(use_fd);
|
||||
- }
|
||||
-
|
||||
if (options->cwd != NULL && chdir(options->cwd))
|
||||
uv__write_errno(error_fd);
|
||||
|
||||
@@ -327,9 +337,8 @@ static void uv__process_child_init(const uv_process_options_t* options,
|
||||
if ((options->flags & UV_PROCESS_SETUID) && setuid(options->uid))
|
||||
uv__write_errno(error_fd);
|
||||
|
||||
- if (options->env != NULL) {
|
||||
+ if (options->env != NULL)
|
||||
environ = options->env;
|
||||
- }
|
||||
|
||||
/* Reset signal mask just before exec. */
|
||||
sigemptyset(&signewset);
|
||||
@@ -348,6 +357,562 @@ static void uv__process_child_init(const uv_process_options_t* options,
|
||||
#endif
|
||||
|
||||
|
||||
+#if defined(__APPLE__)
|
||||
+typedef struct uv__posix_spawn_fncs_tag {
|
||||
+ struct {
|
||||
+ int (*addchdir_np)(const posix_spawn_file_actions_t *, const char *);
|
||||
+ } file_actions;
|
||||
+} uv__posix_spawn_fncs_t;
|
||||
+
|
||||
+
|
||||
+static uv_once_t posix_spawn_init_once = UV_ONCE_INIT;
|
||||
+static uv__posix_spawn_fncs_t posix_spawn_fncs;
|
||||
+static int posix_spawn_can_use_setsid;
|
||||
+
|
||||
+
|
||||
+static void uv__spawn_init_posix_spawn_fncs(void) {
|
||||
+ /* Try to locate all non-portable functions at runtime */
|
||||
+ posix_spawn_fncs.file_actions.addchdir_np =
|
||||
+ dlsym(RTLD_DEFAULT, "posix_spawn_file_actions_addchdir_np");
|
||||
+}
|
||||
+
|
||||
+
|
||||
+static void uv__spawn_init_can_use_setsid(void) {
|
||||
+ static const int MACOS_CATALINA_VERSION_MAJOR = 19;
|
||||
+ char version_str[256];
|
||||
+ char* version_major_str;
|
||||
+ size_t version_str_size = 256;
|
||||
+ int r;
|
||||
+ int version_major;
|
||||
+
|
||||
+ /* Get a version string */
|
||||
+ r = sysctlbyname("kern.osrelease", version_str, &version_str_size, NULL, 0);
|
||||
+ if (r != 0)
|
||||
+ return;
|
||||
+
|
||||
+ /* Try to get the major version number. If not found
|
||||
+ * fall back to the fork/exec flow */
|
||||
+ version_major_str = strtok(version_str, ".");
|
||||
+ if (version_major_str == NULL)
|
||||
+ return;
|
||||
+
|
||||
+ /* Parse the version major as a number. If it is greater than
|
||||
+ * the major version for macOS Catalina (aka macOS 10.15), then
|
||||
+ * the POSIX_SPAWN_SETSID flag is available */
|
||||
+ version_major = atoi_l(version_major_str, NULL); /* Use LC_C_LOCALE */
|
||||
+ if (version_major >= MACOS_CATALINA_VERSION_MAJOR)
|
||||
+ posix_spawn_can_use_setsid = 1;
|
||||
+}
|
||||
+
|
||||
+
|
||||
+static void uv__spawn_init_posix_spawn(void) {
|
||||
+ /* Init handles to all potentially non-defined functions */
|
||||
+ uv__spawn_init_posix_spawn_fncs();
|
||||
+
|
||||
+ /* Init feature detection for POSIX_SPAWN_SETSID flag */
|
||||
+ uv__spawn_init_can_use_setsid();
|
||||
+}
|
||||
+
|
||||
+
|
||||
+static int uv__spawn_set_posix_spawn_attrs(
|
||||
+ posix_spawnattr_t* attrs,
|
||||
+ const uv__posix_spawn_fncs_t* posix_spawn_fncs,
|
||||
+ const uv_process_options_t* options) {
|
||||
+ int err;
|
||||
+ unsigned int flags;
|
||||
+ sigset_t signal_set;
|
||||
+
|
||||
+ err = posix_spawnattr_init(attrs);
|
||||
+ if (err != 0) {
|
||||
+ /* If initialization fails, no need to de-init, just return */
|
||||
+ return err;
|
||||
+ }
|
||||
+
|
||||
+ if (options->flags & (UV_PROCESS_SETUID | UV_PROCESS_SETGID)) {
|
||||
+ /* kauth_cred_issuser currently requires exactly uid == 0 for these
|
||||
+ * posixspawn_attrs (set_groups_np, setuid_np, setgid_np), which deviates
|
||||
+ * from the normal specification of setuid (which also uses euid), and they
|
||||
+ * are also undocumented syscalls, so we do not use them. */
|
||||
+ err = ENOSYS;
|
||||
+ goto error;
|
||||
+ }
|
||||
+
|
||||
+ /* Set flags for spawn behavior
|
||||
+ * 1) POSIX_SPAWN_CLOEXEC_DEFAULT: (Apple Extension) All descriptors in the
|
||||
+ * parent will be treated as if they had been created with O_CLOEXEC. The
|
||||
+ * only fds that will be passed on to the child are those manipulated by
|
||||
+ * the file actions
|
||||
+ * 2) POSIX_SPAWN_SETSIGDEF: Signals mentioned in spawn-sigdefault in the
|
||||
+ * spawn attributes will be reset to behave as their default
|
||||
+ * 3) POSIX_SPAWN_SETSIGMASK: Signal mask will be set to the value of
|
||||
+ * spawn-sigmask in attributes
|
||||
+ * 4) POSIX_SPAWN_SETSID: Make the process a new session leader if a detached
|
||||
+ * session was requested. */
|
||||
+ flags = POSIX_SPAWN_CLOEXEC_DEFAULT |
|
||||
+ POSIX_SPAWN_SETSIGDEF |
|
||||
+ POSIX_SPAWN_SETSIGMASK;
|
||||
+ if (options->flags & UV_PROCESS_DETACHED) {
|
||||
+ /* If running on a version of macOS where this flag is not supported,
|
||||
+ * revert back to the fork/exec flow. Otherwise posix_spawn will
|
||||
+ * silently ignore the flag. */
|
||||
+ if (!posix_spawn_can_use_setsid) {
|
||||
+ err = ENOSYS;
|
||||
+ goto error;
|
||||
+ }
|
||||
+
|
||||
+ flags |= POSIX_SPAWN_SETSID;
|
||||
+ }
|
||||
+ err = posix_spawnattr_setflags(attrs, flags);
|
||||
+ if (err != 0)
|
||||
+ goto error;
|
||||
+
|
||||
+ /* Reset all signal the child to their default behavior */
|
||||
+ sigfillset(&signal_set);
|
||||
+ err = posix_spawnattr_setsigdefault(attrs, &signal_set);
|
||||
+ if (err != 0)
|
||||
+ goto error;
|
||||
+
|
||||
+ /* Reset the signal mask for all signals */
|
||||
+ sigemptyset(&signal_set);
|
||||
+ err = posix_spawnattr_setsigmask(attrs, &signal_set);
|
||||
+ if (err != 0)
|
||||
+ goto error;
|
||||
+
|
||||
+ return err;
|
||||
+
|
||||
+error:
|
||||
+ (void) posix_spawnattr_destroy(attrs);
|
||||
+ return err;
|
||||
+}
|
||||
+
|
||||
+
|
||||
+static int uv__spawn_set_posix_spawn_file_actions(
|
||||
+ posix_spawn_file_actions_t* actions,
|
||||
+ const uv__posix_spawn_fncs_t* posix_spawn_fncs,
|
||||
+ const uv_process_options_t* options,
|
||||
+ int stdio_count,
|
||||
+ int (*pipes)[2]) {
|
||||
+ int fd;
|
||||
+ int fd2;
|
||||
+ int use_fd;
|
||||
+ int err;
|
||||
+
|
||||
+ err = posix_spawn_file_actions_init(actions);
|
||||
+ if (err != 0) {
|
||||
+ /* If initialization fails, no need to de-init, just return */
|
||||
+ return err;
|
||||
+ }
|
||||
+
|
||||
+ /* Set the current working directory if requested */
|
||||
+ if (options->cwd != NULL) {
|
||||
+ if (posix_spawn_fncs->file_actions.addchdir_np == NULL) {
|
||||
+ err = ENOSYS;
|
||||
+ goto error;
|
||||
+ }
|
||||
+
|
||||
+ err = posix_spawn_fncs->file_actions.addchdir_np(actions, options->cwd);
|
||||
+ if (err != 0)
|
||||
+ goto error;
|
||||
+ }
|
||||
+
|
||||
+ /* Do not return ENOSYS after this point, as we may mutate pipes. */
|
||||
+
|
||||
+ /* First duplicate low numbered fds, since it's not safe to duplicate them,
|
||||
+ * they could get replaced. Example: swapping stdout and stderr; without
|
||||
+ * this fd 2 (stderr) would be duplicated into fd 1, thus making both
|
||||
+ * stdout and stderr go to the same fd, which was not the intention. */
|
||||
+ for (fd = 0; fd < stdio_count; fd++) {
|
||||
+ use_fd = pipes[fd][1];
|
||||
+ if (use_fd < 0 || use_fd >= fd)
|
||||
+ continue;
|
||||
+ use_fd = stdio_count;
|
||||
+ for (fd2 = 0; fd2 < stdio_count; fd2++) {
|
||||
+ /* If we were not setting POSIX_SPAWN_CLOEXEC_DEFAULT, we would need to
|
||||
+ * also consider whether fcntl(fd, F_GETFD) returned without the
|
||||
+ * FD_CLOEXEC flag set. */
|
||||
+ if (pipes[fd2][1] == use_fd) {
|
||||
+ use_fd++;
|
||||
+ fd2 = 0;
|
||||
+ }
|
||||
+ }
|
||||
+ err = posix_spawn_file_actions_adddup2(
|
||||
+ actions,
|
||||
+ pipes[fd][1],
|
||||
+ use_fd);
|
||||
+ assert(err != ENOSYS);
|
||||
+ if (err != 0)
|
||||
+ goto error;
|
||||
+ pipes[fd][1] = use_fd;
|
||||
+ }
|
||||
+
|
||||
+ /* Second, move the descriptors into their respective places */
|
||||
+ for (fd = 0; fd < stdio_count; fd++) {
|
||||
+ use_fd = pipes[fd][1];
|
||||
+ if (use_fd < 0) {
|
||||
+ if (fd >= 3)
|
||||
+ continue;
|
||||
+ else {
|
||||
+ /* If ignored, redirect to (or from) /dev/null, */
|
||||
+ err = posix_spawn_file_actions_addopen(
|
||||
+ actions,
|
||||
+ fd,
|
||||
+ "/dev/null",
|
||||
+ fd == 0 ? O_RDONLY : O_RDWR,
|
||||
+ 0);
|
||||
+ assert(err != ENOSYS);
|
||||
+ if (err != 0)
|
||||
+ goto error;
|
||||
+ continue;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ if (fd == use_fd)
|
||||
+ err = posix_spawn_file_actions_addinherit_np(actions, fd);
|
||||
+ else
|
||||
+ err = posix_spawn_file_actions_adddup2(actions, use_fd, fd);
|
||||
+ assert(err != ENOSYS);
|
||||
+ if (err != 0)
|
||||
+ goto error;
|
||||
+
|
||||
+ /* Make sure the fd is marked as non-blocking (state shared between child
|
||||
+ * and parent). */
|
||||
+ uv__nonblock_fcntl(use_fd, 0);
|
||||
+ }
|
||||
+
|
||||
+ /* Finally, close all the superfluous descriptors */
|
||||
+ for (fd = 0; fd < stdio_count; fd++) {
|
||||
+ use_fd = pipes[fd][1];
|
||||
+ if (use_fd < stdio_count)
|
||||
+ continue;
|
||||
+
|
||||
+ /* Check if we already closed this. */
|
||||
+ for (fd2 = 0; fd2 < fd; fd2++) {
|
||||
+ if (pipes[fd2][1] == use_fd)
|
||||
+ break;
|
||||
+ }
|
||||
+ if (fd2 < fd)
|
||||
+ continue;
|
||||
+
|
||||
+ err = posix_spawn_file_actions_addclose(actions, use_fd);
|
||||
+ assert(err != ENOSYS);
|
||||
+ if (err != 0)
|
||||
+ goto error;
|
||||
+ }
|
||||
+
|
||||
+ return 0;
|
||||
+
|
||||
+error:
|
||||
+ (void) posix_spawn_file_actions_destroy(actions);
|
||||
+ return err;
|
||||
+}
|
||||
+
|
||||
+char* uv__spawn_find_path_in_env(char** env) {
|
||||
+ char** env_iterator;
|
||||
+ const char path_var[] = "PATH=";
|
||||
+
|
||||
+ /* Look for an environment variable called PATH in the
|
||||
+ * provided env array, and return its value if found */
|
||||
+ for (env_iterator = env; *env_iterator != NULL; env_iterator++) {
|
||||
+ if (strncmp(*env_iterator, path_var, sizeof(path_var) - 1) == 0) {
|
||||
+ /* Found "PATH=" at the beginning of the string */
|
||||
+ return *env_iterator + sizeof(path_var) - 1;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ return NULL;
|
||||
+}
|
||||
+
|
||||
+
|
||||
+static int uv__spawn_resolve_and_spawn(const uv_process_options_t* options,
|
||||
+ posix_spawnattr_t* attrs,
|
||||
+ posix_spawn_file_actions_t* actions,
|
||||
+ pid_t* pid) {
|
||||
+ const char *p;
|
||||
+ const char *z;
|
||||
+ const char *path;
|
||||
+ size_t l;
|
||||
+ size_t k;
|
||||
+ int err;
|
||||
+ int seen_eacces;
|
||||
+
|
||||
+ path = NULL;
|
||||
+ err = -1;
|
||||
+ seen_eacces = 0;
|
||||
+
|
||||
+ /* Short circuit for erroneous case */
|
||||
+ if (options->file == NULL)
|
||||
+ return ENOENT;
|
||||
+
|
||||
+ /* The environment for the child process is that of the parent unless overriden
|
||||
+ * by options->env */
|
||||
+ char** env = environ;
|
||||
+ if (options->env != NULL)
|
||||
+ env = options->env;
|
||||
+
|
||||
+ /* If options->file contains a slash, posix_spawn/posix_spawnp behave
|
||||
+ * the same, and don't involve PATH resolution at all. Otherwise, if
|
||||
+ * options->file does not include a slash, but no custom environment is
|
||||
+ * to be used, the environment used for path resolution as well for the
|
||||
+ * child process is that of the parent process, so posix_spawnp is the
|
||||
+ * way to go. */
|
||||
+ if (strchr(options->file, '/') != NULL || options->env == NULL) {
|
||||
+ do
|
||||
+ err = posix_spawnp(pid, options->file, actions, attrs, options->args, env);
|
||||
+ while (err == EINTR);
|
||||
+ return err;
|
||||
+ }
|
||||
+
|
||||
+ /* Look for the definition of PATH in the provided env */
|
||||
+ path = uv__spawn_find_path_in_env(options->env);
|
||||
+
|
||||
+ /* The following resolution logic (execvpe emulation) is copied from
|
||||
+ * https://git.musl-libc.org/cgit/musl/tree/src/process/execvp.c
|
||||
+ * and adapted to work for our specific usage */
|
||||
+
|
||||
+ /* If no path was provided in options->env, use the default value
|
||||
+ * to look for the executable */
|
||||
+ if (path == NULL)
|
||||
+ path = _PATH_DEFPATH;
|
||||
+
|
||||
+ k = strnlen(options->file, NAME_MAX + 1);
|
||||
+ if (k > NAME_MAX)
|
||||
+ return ENAMETOOLONG;
|
||||
+
|
||||
+ l = strnlen(path, PATH_MAX - 1) + 1;
|
||||
+
|
||||
+ for (p = path;; p = z) {
|
||||
+ /* Compose the new process file from the entry in the PATH
|
||||
+ * environment variable and the actual file name */
|
||||
+ char b[PATH_MAX + NAME_MAX];
|
||||
+ z = strchr(p, ':');
|
||||
+ if (!z)
|
||||
+ z = p + strlen(p);
|
||||
+ if ((size_t)(z - p) >= l) {
|
||||
+ if (!*z++)
|
||||
+ break;
|
||||
+
|
||||
+ continue;
|
||||
+ }
|
||||
+ memcpy(b, p, z - p);
|
||||
+ b[z - p] = '/';
|
||||
+ memcpy(b + (z - p) + (z > p), options->file, k + 1);
|
||||
+
|
||||
+ /* Try to spawn the new process file. If it fails with ENOENT, the
|
||||
+ * new process file is not in this PATH entry, continue with the next
|
||||
+ * PATH entry. */
|
||||
+ do
|
||||
+ err = posix_spawn(pid, b, actions, attrs, options->args, env);
|
||||
+ while (err == EINTR);
|
||||
+
|
||||
+ switch (err) {
|
||||
+ case EACCES:
|
||||
+ seen_eacces = 1;
|
||||
+ break; /* continue search */
|
||||
+ case ENOENT:
|
||||
+ case ENOTDIR:
|
||||
+ break; /* continue search */
|
||||
+ default:
|
||||
+ return err;
|
||||
+ }
|
||||
+
|
||||
+ if (!*z++)
|
||||
+ break;
|
||||
+ }
|
||||
+
|
||||
+ if (seen_eacces)
|
||||
+ return EACCES;
|
||||
+ return err;
|
||||
+}
|
||||
+
|
||||
+
|
||||
+static int uv__spawn_and_init_child_posix_spawn(
|
||||
+ const uv_process_options_t* options,
|
||||
+ int stdio_count,
|
||||
+ int (*pipes)[2],
|
||||
+ pid_t* pid,
|
||||
+ const uv__posix_spawn_fncs_t* posix_spawn_fncs) {
|
||||
+ int err;
|
||||
+ posix_spawnattr_t attrs;
|
||||
+ posix_spawn_file_actions_t actions;
|
||||
+
|
||||
+ err = uv__spawn_set_posix_spawn_attrs(&attrs, posix_spawn_fncs, options);
|
||||
+ if (err != 0)
|
||||
+ goto error;
|
||||
+
|
||||
+ /* This may mutate pipes. */
|
||||
+ err = uv__spawn_set_posix_spawn_file_actions(&actions,
|
||||
+ posix_spawn_fncs,
|
||||
+ options,
|
||||
+ stdio_count,
|
||||
+ pipes);
|
||||
+ if (err != 0) {
|
||||
+ (void) posix_spawnattr_destroy(&attrs);
|
||||
+ goto error;
|
||||
+ }
|
||||
+
|
||||
+ /* Try to spawn options->file resolving in the provided environment
|
||||
+ * if any */
|
||||
+ err = uv__spawn_resolve_and_spawn(options, &attrs, &actions, pid);
|
||||
+ assert(err != ENOSYS);
|
||||
+
|
||||
+ /* Destroy the actions/attributes */
|
||||
+ (void) posix_spawn_file_actions_destroy(&actions);
|
||||
+ (void) posix_spawnattr_destroy(&attrs);
|
||||
+
|
||||
+error:
|
||||
+ /* In an error situation, the attributes and file actions are
|
||||
+ * already destroyed, only the happy path requires cleanup */
|
||||
+ return UV__ERR(err);
|
||||
+}
|
||||
+#endif
|
||||
+
|
||||
+static int uv__spawn_and_init_child_fork(const uv_process_options_t* options,
|
||||
+ int stdio_count,
|
||||
+ int (*pipes)[2],
|
||||
+ int error_fd,
|
||||
+ pid_t* pid) {
|
||||
+ sigset_t signewset;
|
||||
+ sigset_t sigoldset;
|
||||
+
|
||||
+ /* Start the child with most signals blocked, to avoid any issues before we
|
||||
+ * can reset them, but allow program failures to exit (and not hang). */
|
||||
+ sigfillset(&signewset);
|
||||
+ sigdelset(&signewset, SIGKILL);
|
||||
+ sigdelset(&signewset, SIGSTOP);
|
||||
+ sigdelset(&signewset, SIGTRAP);
|
||||
+ sigdelset(&signewset, SIGSEGV);
|
||||
+ sigdelset(&signewset, SIGBUS);
|
||||
+ sigdelset(&signewset, SIGILL);
|
||||
+ sigdelset(&signewset, SIGSYS);
|
||||
+ sigdelset(&signewset, SIGABRT);
|
||||
+ if (pthread_sigmask(SIG_BLOCK, &signewset, &sigoldset) != 0)
|
||||
+ abort();
|
||||
+
|
||||
+ *pid = fork();
|
||||
+
|
||||
+ if (*pid == -1) {
|
||||
+ /* Failed to fork */
|
||||
+ return UV__ERR(errno);
|
||||
+ }
|
||||
+
|
||||
+ if (*pid == 0) {
|
||||
+ /* Fork succeeded, in the child process */
|
||||
+ uv__process_child_init(options, stdio_count, pipes, error_fd);
|
||||
+ abort();
|
||||
+ }
|
||||
+
|
||||
+ if (pthread_sigmask(SIG_SETMASK, &sigoldset, NULL) != 0)
|
||||
+ abort();
|
||||
+
|
||||
+ /* Fork succeeded, in the parent process */
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static int uv__spawn_and_init_child(
|
||||
+ uv_loop_t* loop,
|
||||
+ const uv_process_options_t* options,
|
||||
+ int stdio_count,
|
||||
+ int (*pipes)[2],
|
||||
+ pid_t* pid) {
|
||||
+ int signal_pipe[2] = { -1, -1 };
|
||||
+ int status;
|
||||
+ int err;
|
||||
+ int exec_errorno;
|
||||
+ ssize_t r;
|
||||
+
|
||||
+#if defined(__APPLE__)
|
||||
+ uv_once(&posix_spawn_init_once, uv__spawn_init_posix_spawn);
|
||||
+
|
||||
+ /* Special child process spawn case for macOS Big Sur (11.0) onwards
|
||||
+ *
|
||||
+ * Big Sur introduced a significant performance degradation on a call to
|
||||
+ * fork/exec when the process has many pages mmaped in with MAP_JIT, like, say
|
||||
+ * a javascript interpreter. Electron-based applications, for example,
|
||||
+ * are impacted; though the magnitude of the impact depends on how much the
|
||||
+ * app relies on subprocesses.
|
||||
+ *
|
||||
+ * On macOS, though, posix_spawn is implemented in a way that does not
|
||||
+ * exhibit the problem. This block implements the forking and preparation
|
||||
+ * logic with posix_spawn and its related primitives. It also takes advantage of
|
||||
+ * the macOS extension POSIX_SPAWN_CLOEXEC_DEFAULT that makes impossible to
|
||||
+ * leak descriptors to the child process. */
|
||||
+ err = uv__spawn_and_init_child_posix_spawn(options,
|
||||
+ stdio_count,
|
||||
+ pipes,
|
||||
+ pid,
|
||||
+ &posix_spawn_fncs);
|
||||
+
|
||||
+ /* The posix_spawn flow will return UV_ENOSYS if any of the posix_spawn_x_np
|
||||
+ * non-standard functions is both _needed_ and _undefined_. In those cases,
|
||||
+ * default back to the fork/execve strategy. For all other errors, just fail. */
|
||||
+ if (err != UV_ENOSYS)
|
||||
+ return err;
|
||||
+
|
||||
+#endif
|
||||
+
|
||||
+ /* This pipe is used by the parent to wait until
|
||||
+ * the child has called `execve()`. We need this
|
||||
+ * to avoid the following race condition:
|
||||
+ *
|
||||
+ * if ((pid = fork()) > 0) {
|
||||
+ * kill(pid, SIGTERM);
|
||||
+ * }
|
||||
+ * else if (pid == 0) {
|
||||
+ * execve("/bin/cat", argp, envp);
|
||||
+ * }
|
||||
+ *
|
||||
+ * The parent sends a signal immediately after forking.
|
||||
+ * Since the child may not have called `execve()` yet,
|
||||
+ * there is no telling what process receives the signal,
|
||||
+ * our fork or /bin/cat.
|
||||
+ *
|
||||
+ * To avoid ambiguity, we create a pipe with both ends
|
||||
+ * marked close-on-exec. Then, after the call to `fork()`,
|
||||
+ * the parent polls the read end until it EOFs or errors with EPIPE.
|
||||
+ */
|
||||
+ err = uv__make_pipe(signal_pipe, 0);
|
||||
+ if (err)
|
||||
+ return err;
|
||||
+
|
||||
+ /* Acquire write lock to prevent opening new fds in worker threads */
|
||||
+ uv_rwlock_wrlock(&loop->cloexec_lock);
|
||||
+
|
||||
+ err = uv__spawn_and_init_child_fork(options, stdio_count, pipes, signal_pipe[1], pid);
|
||||
+
|
||||
+ /* Release lock in parent process */
|
||||
+ uv_rwlock_wrunlock(&loop->cloexec_lock);
|
||||
+
|
||||
+ uv__close(signal_pipe[1]);
|
||||
+
|
||||
+ if (err == 0) {
|
||||
+ do
|
||||
+ r = read(signal_pipe[0], &exec_errorno, sizeof(exec_errorno));
|
||||
+ while (r == -1 && errno == EINTR);
|
||||
+
|
||||
+ if (r == 0)
|
||||
+ ; /* okay, EOF */
|
||||
+ else if (r == sizeof(exec_errorno)) {
|
||||
+ do
|
||||
+ err = waitpid(*pid, &status, 0); /* okay, read errorno */
|
||||
+ while (err == -1 && errno == EINTR);
|
||||
+ assert(err == *pid);
|
||||
+ err = exec_errorno;
|
||||
+ } else if (r == -1 && errno == EPIPE) {
|
||||
+ /* Something unknown happened to our child before spawn */
|
||||
+ do
|
||||
+ err = waitpid(*pid, &status, 0); /* okay, got EPIPE */
|
||||
+ while (err == -1 && errno == EINTR);
|
||||
+ assert(err == *pid);
|
||||
+ err = UV_EPIPE;
|
||||
+ } else
|
||||
+ abort();
|
||||
+ }
|
||||
+
|
||||
+ uv__close_nocheckstdio(signal_pipe[0]);
|
||||
+
|
||||
+ return err;
|
||||
+}
|
||||
+
|
||||
int uv_spawn(uv_loop_t* loop,
|
||||
uv_process_t* process,
|
||||
const uv_process_options_t* options) {
|
||||
@@ -355,18 +920,13 @@ int uv_spawn(uv_loop_t* loop,
|
||||
/* fork is marked __WATCHOS_PROHIBITED __TVOS_PROHIBITED. */
|
||||
return UV_ENOSYS;
|
||||
#else
|
||||
- sigset_t signewset;
|
||||
- sigset_t sigoldset;
|
||||
- int signal_pipe[2] = { -1, -1 };
|
||||
int pipes_storage[8][2];
|
||||
int (*pipes)[2];
|
||||
int stdio_count;
|
||||
- ssize_t r;
|
||||
pid_t pid;
|
||||
int err;
|
||||
int exec_errorno;
|
||||
int i;
|
||||
- int status;
|
||||
|
||||
assert(options->file != NULL);
|
||||
assert(!(options->flags & ~(UV_PROCESS_DETACHED |
|
||||
@@ -379,6 +939,7 @@ int uv_spawn(uv_loop_t* loop,
|
||||
|
||||
uv__handle_init(loop, (uv_handle_t*)process, UV_PROCESS);
|
||||
QUEUE_INIT(&process->queue);
|
||||
+ process->status = 0;
|
||||
|
||||
stdio_count = options->stdio_count;
|
||||
if (stdio_count < 3)
|
||||
@@ -403,106 +964,24 @@ int uv_spawn(uv_loop_t* loop,
|
||||
goto error;
|
||||
}
|
||||
|
||||
- /* This pipe is used by the parent to wait until
|
||||
- * the child has called `execve()`. We need this
|
||||
- * to avoid the following race condition:
|
||||
- *
|
||||
- * if ((pid = fork()) > 0) {
|
||||
- * kill(pid, SIGTERM);
|
||||
- * }
|
||||
- * else if (pid == 0) {
|
||||
- * execve("/bin/cat", argp, envp);
|
||||
- * }
|
||||
- *
|
||||
- * The parent sends a signal immediately after forking.
|
||||
- * Since the child may not have called `execve()` yet,
|
||||
- * there is no telling what process receives the signal,
|
||||
- * our fork or /bin/cat.
|
||||
- *
|
||||
- * To avoid ambiguity, we create a pipe with both ends
|
||||
- * marked close-on-exec. Then, after the call to `fork()`,
|
||||
- * the parent polls the read end until it EOFs or errors with EPIPE.
|
||||
- */
|
||||
- err = uv__make_pipe(signal_pipe, 0);
|
||||
- if (err)
|
||||
- goto error;
|
||||
-
|
||||
#if !(defined(__APPLE__) || defined(__DragonFly__) || defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__))
|
||||
uv_signal_start(&loop->child_watcher, uv__chld, SIGCHLD);
|
||||
#endif
|
||||
|
||||
- /* Acquire write lock to prevent opening new fds in worker threads */
|
||||
- uv_rwlock_wrlock(&loop->cloexec_lock);
|
||||
-
|
||||
- /* Start the child with most signals blocked, to avoid any issues before we
|
||||
- * can reset them, but allow program failures to exit (and not hang). */
|
||||
- sigfillset(&signewset);
|
||||
- sigdelset(&signewset, SIGKILL);
|
||||
- sigdelset(&signewset, SIGSTOP);
|
||||
- sigdelset(&signewset, SIGTRAP);
|
||||
- sigdelset(&signewset, SIGSEGV);
|
||||
- sigdelset(&signewset, SIGBUS);
|
||||
- sigdelset(&signewset, SIGILL);
|
||||
- sigdelset(&signewset, SIGSYS);
|
||||
- sigdelset(&signewset, SIGABRT);
|
||||
- if (pthread_sigmask(SIG_BLOCK, &signewset, &sigoldset) != 0)
|
||||
- abort();
|
||||
-
|
||||
- pid = fork();
|
||||
- if (pid == -1)
|
||||
- err = UV__ERR(errno);
|
||||
-
|
||||
- if (pid == 0)
|
||||
- uv__process_child_init(options, stdio_count, pipes, signal_pipe[1]);
|
||||
+ /* Spawn the child */
|
||||
+ exec_errorno = uv__spawn_and_init_child(loop, options, stdio_count, pipes, &pid);
|
||||
|
||||
- if (pthread_sigmask(SIG_SETMASK, &sigoldset, NULL) != 0)
|
||||
- abort();
|
||||
-
|
||||
- /* Release lock in parent process */
|
||||
- uv_rwlock_wrunlock(&loop->cloexec_lock);
|
||||
-
|
||||
- uv__close(signal_pipe[1]);
|
||||
-
|
||||
- if (pid == -1) {
|
||||
- uv__close(signal_pipe[0]);
|
||||
- goto error;
|
||||
- }
|
||||
-
|
||||
- process->status = 0;
|
||||
- exec_errorno = 0;
|
||||
- do
|
||||
- r = read(signal_pipe[0], &exec_errorno, sizeof(exec_errorno));
|
||||
- while (r == -1 && errno == EINTR);
|
||||
-
|
||||
- if (r == 0)
|
||||
- ; /* okay, EOF */
|
||||
- else if (r == sizeof(exec_errorno)) {
|
||||
- do
|
||||
- err = waitpid(pid, &status, 0); /* okay, read errorno */
|
||||
- while (err == -1 && errno == EINTR);
|
||||
- assert(err == pid);
|
||||
- } else if (r == -1 && errno == EPIPE) {
|
||||
- do
|
||||
- err = waitpid(pid, &status, 0); /* okay, got EPIPE */
|
||||
- while (err == -1 && errno == EINTR);
|
||||
- assert(err == pid);
|
||||
- } else
|
||||
- abort();
|
||||
-
|
||||
- uv__close_nocheckstdio(signal_pipe[0]);
|
||||
-
|
||||
- for (i = 0; i < options->stdio_count; i++) {
|
||||
- err = uv__process_open_stream(options->stdio + i, pipes[i]);
|
||||
- if (err == 0)
|
||||
- continue;
|
||||
-
|
||||
- while (i--)
|
||||
- uv__process_close_stream(options->stdio + i);
|
||||
-
|
||||
- goto error;
|
||||
- }
|
||||
+#if 0
|
||||
+ /* This runs into a nodejs issue (it expects initialized streams, even if the
|
||||
+ * exec failed).
|
||||
+ * See https://github.com/libuv/libuv/pull/3107#issuecomment-782482608 */
|
||||
+ if (exec_errorno != 0)
|
||||
+ goto error;
|
||||
+#endif
|
||||
|
||||
- /* Only activate this handle if exec() happened successfully */
|
||||
+ /* Activate this handle if exec() happened successfully, even if we later
|
||||
+ * fail to open a stdio handle. This ensures we can eventually reap the child
|
||||
+ * with waitpid. */
|
||||
if (exec_errorno == 0) {
|
||||
#if defined(__APPLE__) || defined(__DragonFly__) || defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__)
|
||||
struct kevent event;
|
||||
@@ -515,12 +994,22 @@ int uv_spawn(uv_loop_t* loop,
|
||||
}
|
||||
#endif
|
||||
|
||||
+ process->pid = pid;
|
||||
+ process->exit_cb = options->exit_cb;
|
||||
QUEUE_INSERT_TAIL(&loop->process_handles, &process->queue);
|
||||
uv__handle_start(process);
|
||||
}
|
||||
|
||||
- process->pid = pid;
|
||||
- process->exit_cb = options->exit_cb;
|
||||
+ for (i = 0; i < options->stdio_count; i++) {
|
||||
+ err = uv__process_open_stream(options->stdio + i, pipes[i]);
|
||||
+ if (err == 0)
|
||||
+ continue;
|
||||
+
|
||||
+ while (i--)
|
||||
+ uv__process_close_stream(options->stdio + i);
|
||||
+
|
||||
+ goto error;
|
||||
+ }
|
||||
|
||||
if (pipes != pipes_storage)
|
||||
uv__free(pipes);
|
||||
173
patches/node/unix_protect_fork_in_uv_spawn_from_signals.patch
Normal file
173
patches/node/unix_protect_fork_in_uv_spawn_from_signals.patch
Normal file
@@ -0,0 +1,173 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Jameson Nash <vtjnash@gmail.com>
|
||||
Date: Thu, 29 Jul 2021 12:09:51 -0400
|
||||
Subject: unix: protect fork in uv_spawn from signals
|
||||
|
||||
Years ago, we found that various kernels (linux, macOS) were known to
|
||||
fail if they try to deliver a signal during this syscall, so we prevent
|
||||
that from happening. They may have fixed those issues, but it is
|
||||
generally just a bad time for signals to arrive (glibc blocks them here,
|
||||
for example, including some more internal ones that it won't let us
|
||||
touch here).
|
||||
|
||||
We try to be a bit conservative, and leave many signals unblocked which
|
||||
could happen during normal execution and should terminate the process if
|
||||
they do. There is a small race window after the child starts before we
|
||||
clear the old handlers, if the user was to send an fake signal from
|
||||
elsewhere, but that should be quite unlikely.
|
||||
|
||||
PR-URL: https://github.com/libuv/libuv/pull/3251
|
||||
Reviewed-By: Ben Noordhuis <info@bnoordhuis.nl>
|
||||
|
||||
diff --git a/deps/uv/src/unix/process.c b/deps/uv/src/unix/process.c
|
||||
index cfcba341e0e380ecd595e4b59e39c08a7b374a48..c1f6bd4b0076f0835caf83c45a6a896e7ae5def9 100644
|
||||
--- a/deps/uv/src/unix/process.c
|
||||
+++ b/deps/uv/src/unix/process.c
|
||||
@@ -26,6 +26,7 @@
|
||||
#include <stdlib.h>
|
||||
#include <assert.h>
|
||||
#include <errno.h>
|
||||
+#include <signal.h>
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/wait.h>
|
||||
@@ -223,13 +224,32 @@ static void uv__process_child_init(const uv_process_options_t* options,
|
||||
int stdio_count,
|
||||
int (*pipes)[2],
|
||||
int error_fd) {
|
||||
- sigset_t set;
|
||||
+ sigset_t signewset;
|
||||
int close_fd;
|
||||
int use_fd;
|
||||
- int err;
|
||||
int fd;
|
||||
int n;
|
||||
|
||||
+ /* Reset signal disposition first. Use a hard-coded limit because NSIG is not
|
||||
+ * fixed on Linux: it's either 32, 34 or 64, depending on whether RT signals
|
||||
+ * are enabled. We are not allowed to touch RT signal handlers, glibc uses
|
||||
+ * them internally.
|
||||
+ */
|
||||
+ for (n = 1; n < 32; n += 1) {
|
||||
+ if (n == SIGKILL || n == SIGSTOP)
|
||||
+ continue; /* Can't be changed. */
|
||||
+
|
||||
+#if defined(__HAIKU__)
|
||||
+ if (n == SIGKILLTHR)
|
||||
+ continue; /* Can't be changed. */
|
||||
+#endif
|
||||
+
|
||||
+ if (SIG_ERR != signal(n, SIG_DFL))
|
||||
+ continue;
|
||||
+
|
||||
+ uv__write_errno(error_fd);
|
||||
+ }
|
||||
+
|
||||
if (options->flags & UV_PROCESS_DETACHED)
|
||||
setsid();
|
||||
|
||||
@@ -311,32 +331,10 @@ static void uv__process_child_init(const uv_process_options_t* options,
|
||||
environ = options->env;
|
||||
}
|
||||
|
||||
- /* Reset signal disposition. Use a hard-coded limit because NSIG
|
||||
- * is not fixed on Linux: it's either 32, 34 or 64, depending on
|
||||
- * whether RT signals are enabled. We are not allowed to touch
|
||||
- * RT signal handlers, glibc uses them internally.
|
||||
- */
|
||||
- for (n = 1; n < 32; n += 1) {
|
||||
- if (n == SIGKILL || n == SIGSTOP)
|
||||
- continue; /* Can't be changed. */
|
||||
-
|
||||
-#if defined(__HAIKU__)
|
||||
- if (n == SIGKILLTHR)
|
||||
- continue; /* Can't be changed. */
|
||||
-#endif
|
||||
-
|
||||
- if (SIG_ERR != signal(n, SIG_DFL))
|
||||
- continue;
|
||||
-
|
||||
- uv__write_errno(error_fd);
|
||||
- }
|
||||
-
|
||||
- /* Reset signal mask. */
|
||||
- sigemptyset(&set);
|
||||
- err = pthread_sigmask(SIG_SETMASK, &set, NULL);
|
||||
-
|
||||
- if (err != 0)
|
||||
- uv__write_errno(error_fd);
|
||||
+ /* Reset signal mask just before exec. */
|
||||
+ sigemptyset(&signewset);
|
||||
+ if (sigprocmask(SIG_SETMASK, &signewset, NULL) != 0)
|
||||
+ abort();
|
||||
|
||||
#ifdef __MVS__
|
||||
execvpe(options->file, options->args, environ);
|
||||
@@ -345,6 +343,7 @@ static void uv__process_child_init(const uv_process_options_t* options,
|
||||
#endif
|
||||
|
||||
uv__write_errno(error_fd);
|
||||
+ abort();
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -356,6 +355,8 @@ int uv_spawn(uv_loop_t* loop,
|
||||
/* fork is marked __WATCHOS_PROHIBITED __TVOS_PROHIBITED. */
|
||||
return UV_ENOSYS;
|
||||
#else
|
||||
+ sigset_t signewset;
|
||||
+ sigset_t sigoldset;
|
||||
int signal_pipe[2] = { -1, -1 };
|
||||
int pipes_storage[8][2];
|
||||
int (*pipes)[2];
|
||||
@@ -432,25 +433,41 @@ int uv_spawn(uv_loop_t* loop,
|
||||
|
||||
/* Acquire write lock to prevent opening new fds in worker threads */
|
||||
uv_rwlock_wrlock(&loop->cloexec_lock);
|
||||
- pid = fork();
|
||||
|
||||
- if (pid == -1) {
|
||||
+ /* Start the child with most signals blocked, to avoid any issues before we
|
||||
+ * can reset them, but allow program failures to exit (and not hang). */
|
||||
+ sigfillset(&signewset);
|
||||
+ sigdelset(&signewset, SIGKILL);
|
||||
+ sigdelset(&signewset, SIGSTOP);
|
||||
+ sigdelset(&signewset, SIGTRAP);
|
||||
+ sigdelset(&signewset, SIGSEGV);
|
||||
+ sigdelset(&signewset, SIGBUS);
|
||||
+ sigdelset(&signewset, SIGILL);
|
||||
+ sigdelset(&signewset, SIGSYS);
|
||||
+ sigdelset(&signewset, SIGABRT);
|
||||
+ if (pthread_sigmask(SIG_BLOCK, &signewset, &sigoldset) != 0)
|
||||
+ abort();
|
||||
+
|
||||
+ pid = fork();
|
||||
+ if (pid == -1)
|
||||
err = UV__ERR(errno);
|
||||
- uv_rwlock_wrunlock(&loop->cloexec_lock);
|
||||
- uv__close(signal_pipe[0]);
|
||||
- uv__close(signal_pipe[1]);
|
||||
- goto error;
|
||||
- }
|
||||
|
||||
- if (pid == 0) {
|
||||
+ if (pid == 0)
|
||||
uv__process_child_init(options, stdio_count, pipes, signal_pipe[1]);
|
||||
+
|
||||
+ if (pthread_sigmask(SIG_SETMASK, &sigoldset, NULL) != 0)
|
||||
abort();
|
||||
- }
|
||||
|
||||
/* Release lock in parent process */
|
||||
uv_rwlock_wrunlock(&loop->cloexec_lock);
|
||||
+
|
||||
uv__close(signal_pipe[1]);
|
||||
|
||||
+ if (pid == -1) {
|
||||
+ uv__close(signal_pipe[0]);
|
||||
+ goto error;
|
||||
+ }
|
||||
+
|
||||
process->status = 0;
|
||||
exec_errorno = 0;
|
||||
do
|
||||
91
patches/node/unix_remove_uv_cloexec_ioctl_3515.patch
Normal file
91
patches/node/unix_remove_uv_cloexec_ioctl_3515.patch
Normal file
@@ -0,0 +1,91 @@
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: Jameson Nash <vtjnash@gmail.com>
|
||||
Date: Sun, 6 Mar 2022 15:01:33 -0500
|
||||
Subject: unix: remove uv__cloexec_ioctl() (#3515)
|
||||
|
||||
Now that uv__cloexec_fcntl() is simplified
|
||||
(https://github.com/libuv/libuv/pull/3492), there is no benefit to
|
||||
maintaining duplicate code paths for the same thing.
|
||||
|
||||
diff --git a/deps/uv/src/unix/core.c b/deps/uv/src/unix/core.c
|
||||
index 6cd519ad5b3e7af8f5c71b18a59b88458a233f15..8c30802ad15316a8ec20ecedfb5123174d74276b 100644
|
||||
--- a/deps/uv/src/unix/core.c
|
||||
+++ b/deps/uv/src/unix/core.c
|
||||
@@ -597,20 +597,6 @@ int uv__nonblock_ioctl(int fd, int set) {
|
||||
|
||||
return 0;
|
||||
}
|
||||
-
|
||||
-
|
||||
-int uv__cloexec_ioctl(int fd, int set) {
|
||||
- int r;
|
||||
-
|
||||
- do
|
||||
- r = ioctl(fd, set ? FIOCLEX : FIONCLEX);
|
||||
- while (r == -1 && errno == EINTR);
|
||||
-
|
||||
- if (r)
|
||||
- return UV__ERR(errno);
|
||||
-
|
||||
- return 0;
|
||||
-}
|
||||
#endif
|
||||
|
||||
|
||||
@@ -645,7 +631,7 @@ int uv__nonblock_fcntl(int fd, int set) {
|
||||
}
|
||||
|
||||
|
||||
-int uv__cloexec_fcntl(int fd, int set) {
|
||||
+int uv__cloexec(int fd, int set) {
|
||||
int flags;
|
||||
int r;
|
||||
|
||||
diff --git a/deps/uv/src/unix/internal.h b/deps/uv/src/unix/internal.h
|
||||
index 2dcc8b32f5165dd75061a1b55cc1abd2ab93ccc9..543993989b8765247e140e9d950a25192e5e1ca5 100644
|
||||
--- a/deps/uv/src/unix/internal.h
|
||||
+++ b/deps/uv/src/unix/internal.h
|
||||
@@ -175,11 +175,9 @@ struct uv__stream_queued_fds_s {
|
||||
defined(__linux__) || \
|
||||
defined(__OpenBSD__) || \
|
||||
defined(__NetBSD__)
|
||||
-#define uv__cloexec uv__cloexec_ioctl
|
||||
#define uv__nonblock uv__nonblock_ioctl
|
||||
#define UV__NONBLOCK_IS_IOCTL 1
|
||||
#else
|
||||
-#define uv__cloexec uv__cloexec_fcntl
|
||||
#define uv__nonblock uv__nonblock_fcntl
|
||||
#define UV__NONBLOCK_IS_IOCTL 0
|
||||
#endif
|
||||
@@ -197,8 +195,7 @@ struct uv__stream_queued_fds_s {
|
||||
#endif
|
||||
|
||||
/* core */
|
||||
-int uv__cloexec_ioctl(int fd, int set);
|
||||
-int uv__cloexec_fcntl(int fd, int set);
|
||||
+int uv__cloexec(int fd, int set);
|
||||
int uv__nonblock_ioctl(int fd, int set);
|
||||
int uv__nonblock_fcntl(int fd, int set);
|
||||
int uv__close(int fd); /* preserves errno */
|
||||
diff --git a/deps/uv/src/unix/process.c b/deps/uv/src/unix/process.c
|
||||
index 7705068730cb0536998bad7d304cb87df99b72e8..b6f9756c6a6710f5f10762b9299cc35047b98097 100644
|
||||
--- a/deps/uv/src/unix/process.c
|
||||
+++ b/deps/uv/src/unix/process.c
|
||||
@@ -283,7 +283,7 @@ static void uv__process_child_init(const uv_process_options_t* options,
|
||||
if (pipes[fd][1] == -1)
|
||||
uv__write_errno(error_fd);
|
||||
#ifndef F_DUPFD_CLOEXEC /* POSIX 2008 */
|
||||
- n = uv__cloexec_fcntl(pipes[fd][1], 1);
|
||||
+ n = uv__cloexec(pipes[fd][1], 1);
|
||||
if (n) {
|
||||
uv__write_int(error_fd, n);
|
||||
_exit(127);
|
||||
@@ -312,7 +312,7 @@ static void uv__process_child_init(const uv_process_options_t* options,
|
||||
|
||||
if (fd == use_fd) {
|
||||
if (close_fd == -1) {
|
||||
- n = uv__cloexec_fcntl(use_fd, 0);
|
||||
+ n = uv__cloexec(use_fd, 0);
|
||||
if (n) {
|
||||
uv__write_int(error_fd, n);
|
||||
_exit(127);
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user