Compare commits

..

21 Commits

Author SHA1 Message Date
trop[bot]
bb0dd34e63 fix: prevent PopUpButtonHandler premature dealloc (#40346)
fix: prevent PopUpButtonHandler dealloc

Co-authored-by: trop[bot] <37223003+trop[bot]@users.noreply.github.com>
Co-authored-by: Shelley Vohr <shelley.vohr@gmail.com>
2023-10-26 14:12:43 -04:00
trop[bot]
8148ba5398 build: upload slow, more time good (#40336)
Co-authored-by: trop[bot] <37223003+trop[bot]@users.noreply.github.com>
Co-authored-by: Samuel Attard <marshallofsound@electronjs.org>
2023-10-26 00:20:43 -07:00
trop[bot]
f6d7aba69c test: add spec for app.getAppMetrics() for utility process (#40312)
Co-authored-by: trop[bot] <37223003+trop[bot]@users.noreply.github.com>
Co-authored-by: Milan Burda <milan.burda@gmail.com>
2023-10-25 09:30:28 -04:00
trop[bot]
22687c18c4 test: add spec for child-process-gone event for utility process (#40304)
Co-authored-by: trop[bot] <37223003+trop[bot]@users.noreply.github.com>
Co-authored-by: Milan Burda <milan.burda@gmail.com>
2023-10-23 11:44:22 -07:00
trop[bot]
d1bf107bee chore: Show FIDO devices in the chooser if allowed (#40275)
chore: Show FIDO devices in the chooser if allowed (#40216)

* chore: Show FIDO devices in the chooser if allowed

* chore: tweak HidChooserContext::IsFidoAllowedForOrigin

* chore: feedback from review

---------

Co-authored-by: Shelley Vohr <shelley.vohr@gmail.com>
Co-authored-by: John Kleinschmidt <jkleinsc@electronjs.org>
2023-10-20 10:28:57 +02:00
electron-roller[bot]
eff2ea682d chore: bump chromium to 119.0.6045.33 (28-x-y) (#40278)
* chore: bump chromium in DEPS to 119.0.6045.33

* chore: update patches

* test: fix Node.js color edge snapshot stack traces

(cherry picked from commit af4943fd1b)

---------

Co-authored-by: electron-roller[bot] <84116207+electron-roller[bot]@users.noreply.github.com>
Co-authored-by: PatchUp <73610968+patchup[bot]@users.noreply.github.com>
Co-authored-by: Shelley Vohr <shelley.vohr@gmail.com>
2023-10-19 19:20:48 -04:00
trop[bot]
0310156be6 docs: fix represented file fiddle (#40252)
Co-authored-by: trop[bot] <37223003+trop[bot]@users.noreply.github.com>
Co-authored-by: David Sanders <dsanders11@ucsbalum.com>
2023-10-19 10:03:23 +02:00
trop[bot]
714e6ea49c chore: implement no-op chrome.action extension APIs (#40261)
chore: implement no-op chrome.action extension APIs

Co-authored-by: trop[bot] <37223003+trop[bot]@users.noreply.github.com>
Co-authored-by: Shelley Vohr <shelley.vohr@gmail.com>
2023-10-18 21:39:10 +02:00
trop[bot]
3cf8652027 fix: correctly track receiver for methods called via ctx bridge (#40263)
* fix: correctly track receiver for methods called via ctx bridge

Co-authored-by: Samuel Attard <samuel.r.attard@gmail.com>

* spec: test for correct contextBridge passage

Co-authored-by: Shelley Vohr <shelley.vohr@gmail.com>

---------

Co-authored-by: trop[bot] <37223003+trop[bot]@users.noreply.github.com>
Co-authored-by: Samuel Attard <samuel.r.attard@gmail.com>
Co-authored-by: Shelley Vohr <shelley.vohr@gmail.com>
2023-10-18 21:24:16 +02:00
trop[bot]
f622bd9927 build: re-enable partition alloc on mac (#40230)
* build: re-enable partition alloc on mac

Co-authored-by: VerteDinde <vertedinde@electronjs.org>

* Trigger Build

---------

Co-authored-by: trop[bot] <37223003+trop[bot]@users.noreply.github.com>
Co-authored-by: VerteDinde <vertedinde@electronjs.org>
Co-authored-by: John Kleinschmidt <jkleinsc@electronjs.org>
2023-10-18 12:50:12 -04:00
trop[bot]
9ddd08ba89 fix: support the throwIfNoEntry option to statSync and lstatSync in asar files (#40224)
Co-authored-by: trop[bot] <37223003+trop[bot]@users.noreply.github.com>
Co-authored-by: Samuel Attard <samuel.r.attard@gmail.com>
2023-10-18 11:33:48 +02:00
trop[bot]
a98d66dd23 refactor: partition HidDelegate observers by browser context (#40238)
Co-authored-by: trop[bot] <37223003+trop[bot]@users.noreply.github.com>
Co-authored-by: Shelley Vohr <shelley.vohr@gmail.com>
2023-10-18 10:06:16 +02:00
trop[bot]
1e51ee974d fix: Windows Toast notification dismissal from Action Center (#40243)
* fix: Windows Toast notification dismissal from Action Center

Co-authored-by: Shelley Vohr <shelley.vohr@gmail.com>

* docs: note Toast behavior in event

Co-authored-by: Shelley Vohr <shelley.vohr@gmail.com>

* chore: address feedback from review

Co-authored-by: Shelley Vohr <shelley.vohr@gmail.com>

---------

Co-authored-by: trop[bot] <37223003+trop[bot]@users.noreply.github.com>
Co-authored-by: Shelley Vohr <shelley.vohr@gmail.com>
2023-10-18 10:03:57 +02:00
trop[bot]
6732f63ac0 docs: Update docs on testing Electron apps with WebdriverIO (#40227)
* docs: Updated docs on testing Electron using WebdriverIO

Co-authored-by: Christian Bromann <github@christian-bromann.com>

* Update docs/tutorial/automated-testing.md

Co-authored-by: Felix Rieseberg <fr@makenotion.com>

Co-authored-by: Christian Bromann <github@christian-bromann.com>

* Update docs/tutorial/automated-testing.md

Co-authored-by: Felix Rieseberg <fr@makenotion.com>

Co-authored-by: Christian Bromann <github@christian-bromann.com>

* more updates

Co-authored-by: Christian Bromann <git@bromann.dev>

* address PR comments

Co-authored-by: Christian Bromann <git@bromann.dev>

* Update docs/tutorial/automated-testing.md

Co-authored-by: Erick Zhao <erick@hotmail.ca>

Co-authored-by: Christian Bromann <github@christian-bromann.com>

* Update docs/tutorial/automated-testing.md

Co-authored-by: Erick Zhao <erick@hotmail.ca>

Co-authored-by: Christian Bromann <github@christian-bromann.com>

* Update docs/tutorial/automated-testing.md

Co-authored-by: Erick Zhao <erick@hotmail.ca>

Co-authored-by: Christian Bromann <github@christian-bromann.com>

* Update docs/tutorial/automated-testing.md

Co-authored-by: Erick Zhao <erick@hotmail.ca>

Co-authored-by: Christian Bromann <github@christian-bromann.com>

* Update docs/tutorial/automated-testing.md

Co-authored-by: Erick Zhao <erick@hotmail.ca>

Co-authored-by: Christian Bromann <github@christian-bromann.com>

---------

Co-authored-by: trop[bot] <37223003+trop[bot]@users.noreply.github.com>
Co-authored-by: Christian Bromann <github@christian-bromann.com>
Co-authored-by: Christian Bromann <git@bromann.dev>
2023-10-17 16:54:41 +02:00
trop[bot]
641249f384 fix: incorrect wco bounds in macOS fullscreen (#40219)
Co-authored-by: trop[bot] <37223003+trop[bot]@users.noreply.github.com>
Co-authored-by: Shelley Vohr <shelley.vohr@gmail.com>
2023-10-16 15:06:39 +02:00
electron-roller[bot]
f6b135e1ac chore: bump chromium to 119.0.6045.21 (28-x-y) (#40178)
* chore: bump chromium in DEPS to 119.0.6045.9

* chore: update patches

* chore: bump chromium in DEPS to 119.0.6045.21

* chore: update patches

---------

Co-authored-by: electron-roller[bot] <84116207+electron-roller[bot]@users.noreply.github.com>
Co-authored-by: PatchUp <73610968+patchup[bot]@users.noreply.github.com>
2023-10-16 14:53:20 +02:00
trop[bot]
a5f01f0328 docs: fix some string union typings (#40199)
Co-authored-by: trop[bot] <37223003+trop[bot]@users.noreply.github.com>
Co-authored-by: David Sanders <dsanders11@ucsbalum.com>
2023-10-16 14:10:13 +09:00
trop[bot]
d65b8761f8 chore: formally deprecate gpu-process-crashed event (#40195)
Co-authored-by: trop[bot] <37223003+trop[bot]@users.noreply.github.com>
Co-authored-by: Milan Burda <milan.burda@gmail.com>
2023-10-16 09:19:27 +09:00
trop[bot]
f8d4c45f8e fix: ensure MessagePorts get GCed when not referenced (#40201)
Co-authored-by: trop[bot] <37223003+trop[bot]@users.noreply.github.com>
Co-authored-by: Shelley Vohr <shelley.vohr@gmail.com>
2023-10-16 09:18:36 +09:00
trop[bot]
6625666e40 fix: store portal restore token under the right source ID (#40192)
XDG Desktop Portal provides restore tokens to restore a previously
selected PipeWire stream instead of prompting the user again. This
restore token is single use only and it has to be replaced when the
stream is completed/stopped.

BaseCapturerPipewire maintains two source IDs: one is initialized by
the constructor for new sources (source_id_) and another is for
capturing previously selected sources (selected_source_id_). The
restore token was always being stored under `source_id_`, even if the
capture was ongoing for `selected_source_id_`. This prevents a stream
from being restored more than once. Fix that by storing the restore
token under the selected source ID if it exists.

Co-authored-by: trop[bot] <37223003+trop[bot]@users.noreply.github.com>
Co-authored-by: Athul Iddya <athul@iddya.com>
2023-10-13 22:09:09 +02:00
trop[bot]
e3e7bf3786 fix: webContents.capturePage() for hidden windows on Windows/Linux (#40185)
fix: capturePage for hidden windows on Windows/Linux

Co-authored-by: trop[bot] <37223003+trop[bot]@users.noreply.github.com>
Co-authored-by: Shelley Vohr <shelley.vohr@gmail.com>
2023-10-12 13:54:43 +02:00
42 changed files with 543 additions and 499 deletions

View File

@@ -660,6 +660,7 @@ step-nodejs-headers-build: &step-nodejs-headers-build
step-electron-publish: &step-electron-publish
run:
name: Publish Electron Dist
no_output_timeout: 30m
command: |
if [ "`uname`" == "Darwin" ]; then
rm -rf src/out/Default/obj
@@ -1210,7 +1211,7 @@ commands:
build-type: << parameters.build-type >>
- *step-maybe-electron-dist-strip
- step-electron-dist-build:
additional-targets: electron:node_headers third_party/electron_node:overlapped-checker electron:hunspell_dictionaries_zip
additional-targets: shell_browser_ui_unittests electron:node_headers third_party/electron_node:overlapped-checker electron:hunspell_dictionaries_zip
- *step-show-goma-stats

View File

@@ -1328,6 +1328,25 @@ if (is_mac) {
}
}
test("shell_browser_ui_unittests") {
sources = [
"//electron/shell/browser/ui/accelerator_util_unittests.cc",
"//electron/shell/browser/ui/run_all_unittests.cc",
]
configs += [ ":electron_lib_config" ]
deps = [
":electron_lib",
"//base",
"//base/test:test_support",
"//testing/gmock",
"//testing/gtest",
"//ui/base",
"//ui/strings",
]
}
template("dist_zip") {
_runtime_deps_target = "${target_name}__deps"
_runtime_deps_file =

4
DEPS
View File

@@ -2,9 +2,9 @@ gclient_gn_args_from = 'src'
vars = {
'chromium_version':
'119.0.6045.0',
'119.0.6045.33',
'node_version':
'v18.18.2',
'v18.18.0',
'nan_version':
'e14bdcd1f72d62bca1d541b66da43130384ec213',
'squirrel.mac_version':

View File

@@ -9,8 +9,8 @@ View these docs in other languages on our [Crowdin](https://crowdin.com/project/
The Electron framework lets you write cross-platform desktop applications
using JavaScript, HTML and CSS. It is based on [Node.js](https://nodejs.org/) and
[Chromium](https://www.chromium.org) and is used by the [Visual Studio
Code](https://github.com/Microsoft/vscode/) and many other [apps](https://electronjs.org/apps).
[Chromium](https://www.chromium.org) and is used by the [Atom
editor](https://github.com/atom/atom) and many other [apps](https://electronjs.org/apps).
Follow [@electronjs](https://twitter.com/electronjs) on Twitter for important
announcements.
@@ -41,9 +41,9 @@ Each Electron release provides binaries for macOS, Windows, and Linux.
* macOS (Catalina and up): Electron provides 64-bit Intel and ARM binaries for macOS. Apple Silicon support was added in Electron 11.
* Windows (Windows 10 and up): Electron provides `ia32` (`x86`), `x64` (`amd64`), and `arm64` binaries for Windows. Windows on ARM support was added in Electron 5.0.8. Support for Windows 7, 8 and 8.1 was [removed in Electron 23, in line with Chromium's Windows deprecation policy](https://www.electronjs.org/blog/windows-7-to-8-1-deprecation-notice).
* Linux: The prebuilt binaries of Electron are built on Ubuntu 20.04. They have also been verified to work on:
* Ubuntu 18.04 and newer
* Fedora 32 and newer
* Debian 10 and newer
* Ubuntu 14.04 and newer
* Fedora 24 and newer
* Debian 8 and newer
## Quick start & Electron Fiddle

View File

@@ -156,6 +156,7 @@ for:
- gn gen out/ffmpeg "--args=import(\"//electron/build/args/ffmpeg.gn\") %GN_EXTRA_ARGS%"
- ninja -C out/ffmpeg electron:electron_ffmpeg_zip
- ninja -C out/Default electron:electron_dist_zip
- ninja -C out/Default shell_browser_ui_unittests
- gn desc out/Default v8:run_mksnapshot_default args > out/Default/default_mksnapshot_args
# Remove unused args from mksnapshot_args
- ps: >-
@@ -194,7 +195,7 @@ for:
if ($env:SHOULD_SKIP_ARTIFACT_VALIDATION -eq 'true') {
Write-warning "Skipping artifact validation for doc-only $env:APPVEYOR_PROJECT_NAME"
} else {
$artifacts_to_validate = 'dist.zip','windows_toolchain_profile.json','chromedriver.zip','ffmpeg.zip','node_headers.zip','mksnapshot.zip','electron.lib','hunspell_dictionaries.zip'
$artifacts_to_validate = 'dist.zip','windows_toolchain_profile.json','shell_browser_ui_unittests.exe','chromedriver.zip','ffmpeg.zip','node_headers.zip','mksnapshot.zip','electron.lib','hunspell_dictionaries.zip'
foreach($artifact_name in $artifacts_to_validate) {
if ($artifact_name -eq 'ffmpeg.zip') {
$artifact_file = "out\ffmpeg\ffmpeg.zip"
@@ -232,6 +233,7 @@ for:
- cd C:\projects\src
- if exist out\Default\windows_toolchain_profile.json ( appveyor-retry appveyor PushArtifact out\Default\windows_toolchain_profile.json )
- if exist out\Default\dist.zip (appveyor-retry appveyor PushArtifact out\Default\dist.zip)
- if exist out\Default\shell_browser_ui_unittests.exe (appveyor-retry appveyor PushArtifact out\Default\shell_browser_ui_unittests.exe)
- if exist out\Default\chromedriver.zip (appveyor-retry appveyor PushArtifact out\Default\chromedriver.zip)
- if exist out\ffmpeg\ffmpeg.zip (appveyor-retry appveyor PushArtifact out\ffmpeg\ffmpeg.zip)
- if exist node_headers.zip (appveyor-retry appveyor PushArtifact node_headers.zip)
@@ -275,7 +277,7 @@ for:
if ($job.name -eq "Build Arm on X64 Windows") {
$jobId = $job.jobId
foreach($artifact_name in $artifacts_to_download) {
if ($artifact_name -eq 'electron.lib') {
if ($artifact_name -eq 'shell_browser_ui_unittests.exe' -Or $artifact_name -eq 'electron.lib') {
$outfile = "src\out\Default\$artifact_name"
} else {
$outfile = $artifact_name

View File

@@ -154,6 +154,7 @@ for:
- gn gen out/ffmpeg "--args=import(\"//electron/build/args/ffmpeg.gn\") %GN_EXTRA_ARGS%"
- ninja -C out/ffmpeg electron:electron_ffmpeg_zip
- ninja -C out/Default electron:electron_dist_zip
- ninja -C out/Default shell_browser_ui_unittests
- gn desc out/Default v8:run_mksnapshot_default args > out/Default/default_mksnapshot_args
# Remove unused args from mksnapshot_args
- ps: >-
@@ -192,7 +193,7 @@ for:
if ($env:SHOULD_SKIP_ARTIFACT_VALIDATION -eq 'true') {
Write-warning "Skipping artifact validation for doc-only $env:APPVEYOR_PROJECT_NAME"
} else {
$artifacts_to_validate = 'dist.zip','windows_toolchain_profile.json','chromedriver.zip','ffmpeg.zip','node_headers.zip','mksnapshot.zip','electron.lib','hunspell_dictionaries.zip'
$artifacts_to_validate = 'dist.zip','windows_toolchain_profile.json','shell_browser_ui_unittests.exe','chromedriver.zip','ffmpeg.zip','node_headers.zip','mksnapshot.zip','electron.lib','hunspell_dictionaries.zip'
foreach($artifact_name in $artifacts_to_validate) {
if ($artifact_name -eq 'ffmpeg.zip') {
$artifact_file = "out\ffmpeg\ffmpeg.zip"
@@ -230,6 +231,7 @@ for:
- cd C:\projects\src
- if exist out\Default\windows_toolchain_profile.json ( appveyor-retry appveyor PushArtifact out\Default\windows_toolchain_profile.json )
- if exist out\Default\dist.zip (appveyor-retry appveyor PushArtifact out\Default\dist.zip)
- if exist out\Default\shell_browser_ui_unittests.exe (appveyor-retry appveyor PushArtifact out\Default\shell_browser_ui_unittests.exe)
- if exist out\Default\chromedriver.zip (appveyor-retry appveyor PushArtifact out\Default\chromedriver.zip)
- if exist out\ffmpeg\ffmpeg.zip (appveyor-retry appveyor PushArtifact out\ffmpeg\ffmpeg.zip)
- if exist node_headers.zip (appveyor-retry appveyor PushArtifact node_headers.zip)
@@ -266,12 +268,12 @@ for:
# Download build artifacts
$apiUrl = 'https://ci.appveyor.com/api'
$build_info = Invoke-RestMethod -Method Get -Uri "$apiUrl/projects/$env:APPVEYOR_ACCOUNT_NAME/$env:APPVEYOR_PROJECT_SLUG/builds/$env:APPVEYOR_BUILD_ID"
$artifacts_to_download = @('dist.zip','chromedriver.zip','ffmpeg.zip','node_headers.zip','mksnapshot.zip','electron.lib')
$artifacts_to_download = @('dist.zip','shell_browser_ui_unittests.exe','chromedriver.zip','ffmpeg.zip','node_headers.zip','mksnapshot.zip','electron.lib')
foreach ($job in $build_info.build.jobs) {
if ($job.name -eq "Build") {
$jobId = $job.jobId
foreach($artifact_name in $artifacts_to_download) {
if ($artifact_name -eq 'electron.lib') {
if ($artifact_name -eq 'shell_browser_ui_unittests.exe' -Or $artifact_name -eq 'electron.lib') {
$outfile = "src\out\Default\$artifact_name"
} else {
$outfile = $artifact_name
@@ -305,6 +307,7 @@ for:
$env:npm_config_arch = "ia32"
}
- echo Running main test suite & node script/yarn test -- --trace-uncaught --runners=main --enable-logging=file --log-file=%cd%\electron.log
- echo Running native test suite & node script/yarn test -- --trace-uncaught --runners=native --enable-logging=file --log-file=%cd%\electron.log
- cd ..
- echo Verifying non proprietary ffmpeg & python electron\script\verify-ffmpeg.py --build-dir out\Default --source-root %cd% --ffmpeg-path out\ffmpeg
- echo "About to verify mksnapshot"

View File

@@ -391,6 +391,21 @@ which contains more information about why the child process disappeared. It
isn't always because it crashed. The `killed` boolean can be replaced by
checking `reason === 'killed'` when you switch to that event.
### Event: 'renderer-process-crashed' _Deprecated_
Returns:
* `event` Event
* `webContents` [WebContents](web-contents.md)
* `killed` boolean
Emitted when the renderer process of `webContents` crashes or is killed.
**Deprecated:** This event is superceded by the `render-process-gone` event
which contains more information about why the render process disappeared. It
isn't always because it crashed. The `killed` boolean can be replaced by
checking `reason === 'killed'` when you switch to that event.
### Event: 'render-process-gone'
Returns:
@@ -1263,10 +1278,10 @@ Returns `boolean` - Whether the current desktop environment is Unity launcher.
### `app.getLoginItemSettings([options])` _macOS_ _Windows_
* `options` Object (optional)
* `type` string (optional) _macOS_ - Can be one of `mainAppService`, `agentService`, `daemonService`, or `loginItemService`. Defaults to `mainAppService`. Only available on macOS 13 and up. See [app.setLoginItemSettings](app.md#appsetloginitemsettingssettings-macos-windows) for more information about each type.
* `serviceName` string (optional) _macOS_ - The name of the service. Required if `type` is non-default. Only available on macOS 13 and up.
* `path` string (optional) _Windows_ - The executable path to compare against. Defaults to `process.execPath`.
* `args` string[] (optional) _Windows_ - The command-line arguments to compare against. Defaults to an empty array.
* `path` string (optional) _Windows_ - The executable path to compare against.
Defaults to `process.execPath`.
* `args` string[] (optional) _Windows_ - The command-line arguments to compare
against. Defaults to an empty array.
If you provided `path` and `args` options to `app.setLoginItemSettings`, then you
need to pass the same arguments here for `openAtLogin` to be set correctly.
@@ -1274,11 +1289,17 @@ need to pass the same arguments here for `openAtLogin` to be set correctly.
Returns `Object`:
* `openAtLogin` boolean - `true` if the app is set to open at login.
* `openAsHidden` boolean _macOS_ _Deprecated_ - `true` if the app is set to open as hidden at login. This does not work on macOS 13 and up.
* `wasOpenedAtLogin` boolean _macOS_ _Deprecated_ - `true` if the app was opened at login automatically. This setting is not available on [MAS builds][mas-builds] or on macOS 13 and up.
* `wasOpenedAsHidden` boolean _macOS_ _Deprecated_ - `true` if the app was opened as a hidden login item. This indicates that the app should not open any windows at startup. This setting is not available on [MAS builds][mas-builds] or on macOS 13 and up.
* `restoreState` boolean _macOS_ _Deprecated_ - `true` if the app was opened as a login item that should restore the state from the previous session. This indicates that the app should restore the windows that were open the last time the app was closed. This setting is not available on [MAS builds][mas-builds] or on macOS 13 and up.
* `status` string _macOS_ - can be one of `not-registered`, `enabled`, `requires-approval`, or `not-found`.
* `openAsHidden` boolean _macOS_ - `true` if the app is set to open as hidden at login.
This setting is not available on [MAS builds][mas-builds].
* `wasOpenedAtLogin` boolean _macOS_ - `true` if the app was opened at login
automatically. This setting is not available on [MAS builds][mas-builds].
* `wasOpenedAsHidden` boolean _macOS_ - `true` if the app was opened as a hidden login
item. This indicates that the app should not open any windows at startup.
This setting is not available on [MAS builds][mas-builds].
* `restoreState` boolean _macOS_ - `true` if the app was opened as a login item that
should restore the state from the previous session. This indicates that the
app should restore the windows that were open the last time the app was
closed. This setting is not available on [MAS builds][mas-builds].
* `executableWillLaunchAtLogin` boolean _Windows_ - `true` if app is set to open at login and its run key is not deactivated. This differs from `openAtLogin` as it ignores the `args` option, this property will be true if the given executable would be launched at login with **any** arguments.
* `launchItems` Object[] _Windows_
* `name` string _Windows_ - name value of a registry entry.
@@ -1292,14 +1313,10 @@ Returns `Object`:
* `settings` Object
* `openAtLogin` boolean (optional) - `true` to open the app at login, `false` to remove
the app as a login item. Defaults to `false`.
* `openAsHidden` boolean (optional) _macOS_ _Deprecated_ - `true` to open the app as hidden. Defaults to `false`. The user can edit this setting from the System Preferences so `app.getLoginItemSettings().wasOpenedAsHidden` should be checked when the app is opened to know the current value. This setting is not available on [MAS build
s][mas-builds] or on macOS 13 and up.
* `type` string (optional) _macOS_ - The type of service to add as a login item. Defaults to `mainAppService`. Only available on macOS 13 and up.
* `mainAppService` - The primary application.
* `agentService` - The property list name for a launch agent. The property list name must correspond to a property list in the apps `Contents/Library/LaunchAgents` directory.
* `daemonService` string (optional) _macOS_ - The property list name for a launch agent. The property list name must correspond to a property list in the apps `Contents/Library/LaunchDaemons` directory.
* `loginItemService` string (optional) _macOS_ - The property list name for a login item service. The property list name must correspond to a property list in the apps `Contents/Library/LoginItems` directory.
* `serviceName` string (optional) _macOS_ - The name of the service. Required if `type` is non-default. Only available on macOS 13 and up.
* `openAsHidden` boolean (optional) _macOS_ - `true` to open the app as hidden. Defaults to
`false`. The user can edit this setting from the System Preferences so
`app.getLoginItemSettings().wasOpenedAsHidden` should be checked when the app
is opened to know the current value. This setting is not available on [MAS builds][mas-builds].
* `path` string (optional) _Windows_ - The executable to launch at login.
Defaults to `process.execPath`.
* `args` string[] (optional) _Windows_ - The command-line arguments to pass to
@@ -1308,7 +1325,6 @@ s][mas-builds] or on macOS 13 and up.
* `enabled` boolean (optional) _Windows_ - `true` will change the startup approved registry key and `enable / disable` the App in Task Manager and Windows Settings.
Defaults to `true`.
* `name` string (optional) _Windows_ - value name to write into registry. Defaults to the app's AppUserModelId().
Set the app's login item settings.
To work with Electron's `autoUpdater` on Windows, which uses [Squirrel][Squirrel-Windows],
@@ -1333,8 +1349,6 @@ app.setLoginItemSettings({
})
```
For more information about setting different services as login items on macOS 13 and up, see [`SMAppService`](https://developer.apple.com/documentation/servicemanagement/smappservice?language=objc).
### `app.isAccessibilitySupportEnabled()` _macOS_ _Windows_
Returns `boolean` - `true` if Chrome's accessibility support is enabled,

View File

@@ -29,7 +29,7 @@ Process: [Main](../glossary.md#main-process)<br />
* `inherit`: equivalent to \['ignore', 'inherit', 'inherit']
* `serviceName` string (optional) - Name of the process that will appear in `name` property of
[`child-process-gone` event of `app`](app.md#event-child-process-gone).
Default is `node.mojom.NodeService`.
Default is `Node Utility Process`.
* `allowLoadingUnsignedLibraries` boolean (optional) _macOS_ - With this flag, the utility process will be
launched via the `Electron Helper (Plugin).app` helper executable on macOS, which can be
codesigned with `com.apple.security.cs.disable-library-validation` and

View File

@@ -460,6 +460,20 @@ win.webContents.on('will-prevent-unload', (event) => {
**Note:** This will be emitted for `BrowserViews` but will _not_ be respected - this is because we have chosen not to tie the `BrowserView` lifecycle to its owning BrowserWindow should one exist per the [specification](https://developer.mozilla.org/en-US/docs/Web/API/Window/beforeunload_event).
#### Event: 'crashed' _Deprecated_
Returns:
* `event` Event
* `killed` boolean
Emitted when the renderer process crashes or is killed.
**Deprecated:** This event is superceded by the `render-process-gone` event
which contains more information about why the render process disappeared. It
isn't always because it crashed. The `killed` boolean can be replaced by
checking `reason === 'killed'` when you switch to that event.
#### Event: 'render-process-gone'
Returns:

View File

@@ -986,6 +986,14 @@ ipcRenderer.on('ping', () => {
})
```
### Event: 'crashed' _Deprecated_
Fired when the renderer process crashes or is killed.
**Deprecated:** This event is superceded by the `render-process-gone` event
which contains more information about why the render process disappeared. It
isn't always because it crashed.
### Event: 'render-process-gone'
Returns:

View File

@@ -12,36 +12,6 @@ This document uses the following convention to categorize breaking changes:
* **Deprecated:** An API was marked as deprecated. The API will continue to function, but will emit a deprecation warning, and will be removed in a future release.
* **Removed:** An API or feature was removed, and is no longer supported by Electron.
## Planned Breaking API Changes (29.0)
### Removed: `renderer-process-crashed` event on `app`
The `renderer-process-crashed` event on `app` has been removed.
Use the new `render-process-gone` event instead.
```js
// Removed
app.on('renderer-process-crashed', (event, webContents, killed) => { /* ... */ })
// Replace with
app.on('render-process-gone', (event, webContents, details) => { /* ... */ })
```
### Removed: `crashed` event on `WebContents` and `<webview>`
The `crashed` events on `WebContents` and `<webview>` have been removed.
Use the new `render-process-gone` event instead.
```js
// Removed
win.webContents.on('crashed', (event, killed) => { /* ... */ })
webview.addEventListener('crashed', (event) => { /* ... */ })
// Replace with
win.webContents.on('render-process-gone', (event, details) => { /* ... */ })
webview.addEventListener('render-process-gone', (event) => { /* ... */ })
```
## Planned Breaking API Changes (28.0)
### Behavior Changed: `WebContents.backgroundThrottling` set to false affects all `WebContents` in the host `BrowserWindow`

View File

@@ -82,9 +82,9 @@ contextBridge.exposeInMainWorld('electronAPI', {
})
```
You can create a `interface.d.ts` declaration file and globally augment the `Window` interface:
You can create a `renderer.d.ts` declaration file and globally augment the `Window` interface:
```typescript title='interface.d.ts' @ts-noisolate
```typescript title='renderer.d.ts' @ts-noisolate
export interface IElectronAPI {
loadPreferences: () => Promise<void>,
}

View File

@@ -118,3 +118,7 @@ deprecate.event(app, 'gpu-process-crashed', 'child-process-gone', () => {
// the old event is still emitted by App::OnGpuProcessCrashed()
return undefined;
});
deprecate.event(app, 'renderer-process-crashed', 'render-process-gone', (event: Electron.Event, webContents: Electron.WebContents, details: Electron.RenderProcessGoneDetails) => {
return [event, webContents, details.reason === 'killed'];
});

View File

@@ -187,57 +187,149 @@ WebContents.prototype.executeJavaScriptInIsolatedWorld = async function (worldId
return ipcMainUtils.invokeInWebContents(this, IPC_MESSAGES.RENDERER_WEB_FRAME_METHOD, 'executeJavaScriptInIsolatedWorld', worldId, code, !!hasUserGesture);
};
function checkType<T> (value: T, type: 'number' | 'boolean' | 'string' | 'object', name: string): T {
// eslint-disable-next-line valid-typeof
if (typeof value !== type) {
throw new TypeError(`${name} must be a ${type}`);
}
return value;
}
function parsePageSize (pageSize: string | ElectronInternal.PageSize) {
if (typeof pageSize === 'string') {
const format = paperFormats[pageSize.toLowerCase()];
if (!format) {
throw new Error(`Invalid pageSize ${pageSize}`);
}
return { paperWidth: format.width, paperHeight: format.height };
} else if (typeof pageSize === 'object') {
if (typeof pageSize.width !== 'number' || typeof pageSize.height !== 'number') {
throw new TypeError('width and height properties are required for pageSize');
}
return { paperWidth: pageSize.width, paperHeight: pageSize.height };
} else {
throw new TypeError('pageSize must be a string or an object');
}
}
// Translate the options of printToPDF.
let pendingPromise: Promise<any> | undefined;
WebContents.prototype.printToPDF = async function (options) {
const margins = checkType(options.margins ?? {}, 'object', 'margins');
const printSettings = {
const printSettings: Record<string, any> = {
requestID: getNextId(),
landscape: checkType(options.landscape ?? false, 'boolean', 'landscape'),
displayHeaderFooter: checkType(options.displayHeaderFooter ?? false, 'boolean', 'displayHeaderFooter'),
headerTemplate: checkType(options.headerTemplate ?? '', 'string', 'headerTemplate'),
footerTemplate: checkType(options.footerTemplate ?? '', 'string', 'footerTemplate'),
printBackground: checkType(options.printBackground ?? false, 'boolean', 'printBackground'),
scale: checkType(options.scale ?? 1.0, 'number', 'scale'),
marginTop: checkType(margins.top ?? 0.4, 'number', 'margins.top'),
marginBottom: checkType(margins.bottom ?? 0.4, 'number', 'margins.bottom'),
marginLeft: checkType(margins.left ?? 0.4, 'number', 'margins.left'),
marginRight: checkType(margins.right ?? 0.4, 'number', 'margins.right'),
pageRanges: checkType(options.pageRanges ?? '', 'string', 'pageRanges'),
preferCSSPageSize: checkType(options.preferCSSPageSize ?? false, 'boolean', 'preferCSSPageSize'),
generateTaggedPDF: checkType(options.generateTaggedPDF ?? false, 'boolean', 'generateTaggedPDF'),
...parsePageSize(options.pageSize ?? 'letter')
landscape: false,
displayHeaderFooter: false,
headerTemplate: '',
footerTemplate: '',
printBackground: false,
scale: 1.0,
paperWidth: 8.5,
paperHeight: 11.0,
marginTop: 0.4,
marginBottom: 0.4,
marginLeft: 0.4,
marginRight: 0.4,
pageRanges: '',
preferCSSPageSize: false,
shouldGenerateTaggedPDF: false
};
if (options.landscape !== undefined) {
if (typeof options.landscape !== 'boolean') {
throw new Error('landscape must be a Boolean');
}
printSettings.landscape = options.landscape;
}
if (options.displayHeaderFooter !== undefined) {
if (typeof options.displayHeaderFooter !== 'boolean') {
throw new Error('displayHeaderFooter must be a Boolean');
}
printSettings.displayHeaderFooter = options.displayHeaderFooter;
}
if (options.printBackground !== undefined) {
if (typeof options.printBackground !== 'boolean') {
throw new Error('printBackground must be a Boolean');
}
printSettings.shouldPrintBackgrounds = options.printBackground;
}
if (options.scale !== undefined) {
if (typeof options.scale !== 'number') {
throw new Error('scale must be a Number');
}
printSettings.scale = options.scale;
}
const { pageSize } = options;
if (pageSize !== undefined) {
if (typeof pageSize === 'string') {
const format = paperFormats[pageSize.toLowerCase()];
if (!format) {
throw new Error(`Invalid pageSize ${pageSize}`);
}
printSettings.paperWidth = format.width;
printSettings.paperHeight = format.height;
} else if (typeof options.pageSize === 'object') {
if (!pageSize.height || !pageSize.width) {
throw new Error('height and width properties are required for pageSize');
}
printSettings.paperWidth = pageSize.width;
printSettings.paperHeight = pageSize.height;
} else {
throw new Error('pageSize must be a String or Object');
}
}
const { margins } = options;
if (margins !== undefined) {
if (typeof margins !== 'object') {
throw new Error('margins must be an Object');
}
if (margins.top !== undefined) {
if (typeof margins.top !== 'number') {
throw new Error('margins.top must be a Number');
}
printSettings.marginTop = margins.top;
}
if (margins.bottom !== undefined) {
if (typeof margins.bottom !== 'number') {
throw new Error('margins.bottom must be a Number');
}
printSettings.marginBottom = margins.bottom;
}
if (margins.left !== undefined) {
if (typeof margins.left !== 'number') {
throw new Error('margins.left must be a Number');
}
printSettings.marginLeft = margins.left;
}
if (margins.right !== undefined) {
if (typeof margins.right !== 'number') {
throw new Error('margins.right must be a Number');
}
printSettings.marginRight = margins.right;
}
}
if (options.pageRanges !== undefined) {
if (typeof options.pageRanges !== 'string') {
throw new Error('pageRanges must be a String');
}
printSettings.pageRanges = options.pageRanges;
}
if (options.headerTemplate !== undefined) {
if (typeof options.headerTemplate !== 'string') {
throw new Error('headerTemplate must be a String');
}
printSettings.headerTemplate = options.headerTemplate;
}
if (options.footerTemplate !== undefined) {
if (typeof options.footerTemplate !== 'string') {
throw new Error('footerTemplate must be a String');
}
printSettings.footerTemplate = options.footerTemplate;
}
if (options.preferCSSPageSize !== undefined) {
if (typeof options.preferCSSPageSize !== 'boolean') {
throw new Error('preferCSSPageSize must be a Boolean');
}
printSettings.preferCSSPageSize = options.preferCSSPageSize;
}
if (options.generateTaggedPDF !== undefined) {
if (typeof options.generateTaggedPDF !== 'boolean') {
throw new Error('generateTaggedPDF must be a Boolean');
}
printSettings.shouldGenerateTaggedPDF = options.generateTaggedPDF;
}
if (this._printToPDF) {
if (pendingPromise) {
pendingPromise = pendingPromise.then(() => this._printToPDF(printSettings));
@@ -254,7 +346,7 @@ WebContents.prototype.printToPDF = async function (options) {
// print param logic into new file shared between printToPDF and print
WebContents.prototype.print = function (options: ElectronInternal.WebContentsPrintOptions, callback) {
if (typeof options !== 'object') {
throw new TypeError('webContents.print(): Invalid print settings specified.');
throw new Error('webContents.print(): Invalid print settings specified.');
}
const printSettings: Record<string, any> = { ...options };
@@ -269,7 +361,7 @@ WebContents.prototype.print = function (options: ElectronInternal.WebContentsPri
const height = Math.ceil(pageSize.height);
const width = Math.ceil(pageSize.width);
if (!isValidCustomPageSize(width, height)) {
throw new RangeError('height and width properties must be minimum 352 microns.');
throw new Error('height and width properties must be minimum 352 microns.');
}
printSettings.mediaSize = {
@@ -573,6 +665,10 @@ WebContents.prototype._init = function () {
ipcMain.emit(channel, event, message);
});
deprecate.event(this, 'crashed', 'render-process-gone', (event: Electron.Event, details: Electron.RenderProcessGoneDetails) => {
return [event, details.reason === 'killed'];
});
this.on('render-process-gone', (event, details) => {
app.emit('render-process-gone', event, this, details);

View File

@@ -21,6 +21,7 @@ export const webViewEvents: Record<string, readonly string[]> = {
'did-navigate-in-page': ['url', 'isMainFrame', 'frameProcessId', 'frameRoutingId'],
'-focus-change': ['focus'],
close: [],
crashed: [],
'render-process-gone': ['details'],
'plugin-crashed': ['name', 'version'],
destroyed: [],

View File

@@ -33,10 +33,10 @@ index dcf02923c21e1c4c292eb800f6325e4bb764c823..8738860b44f179685198d2c0b9729fcc
"//base",
"//build:branding_buildflags",
diff --git a/chrome/browser/BUILD.gn b/chrome/browser/BUILD.gn
index 157ee5cadc0a7bf97be0fc8bf34adb858beea1f1..20303e1712ff917a6c145ab9b1bd71524d998a7f 100644
index 7cb8d3fc03da2017fc5eaa83a9677d51013f4d92..c3a8dea68fc7d4a5c20d1b1946d3fa3120699bb5 100644
--- a/chrome/browser/BUILD.gn
+++ b/chrome/browser/BUILD.gn
@@ -4797,7 +4797,7 @@ static_library("browser") {
@@ -4801,7 +4801,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 157ee5cadc0a7bf97be0fc8bf34adb858beea1f1..20303e1712ff917a6c145ab9b1bd7152
sources += [ "certificate_viewer_stub.cc" ]
}
diff --git a/chrome/test/BUILD.gn b/chrome/test/BUILD.gn
index 6b98993d6737c22883bd9ddb31eda60060795e94..d1c6cce7ed68d1d523bd6683529e6ab003ace8e7 100644
index 317aa37c811c4b461cd8a4b8e321a820622df4c3..964514b24c16d5b43439fdb4544467dd5f9f0ecf 100644
--- a/chrome/test/BUILD.gn
+++ b/chrome/test/BUILD.gn
@@ -6899,7 +6899,6 @@ test("unit_tests") {
@@ -6900,7 +6900,6 @@ test("unit_tests") {
deps += [
"//chrome:other_version",
@@ -57,7 +57,7 @@ index 6b98993d6737c22883bd9ddb31eda60060795e94..d1c6cce7ed68d1d523bd6683529e6ab0
"//chrome//services/util_win:unit_tests",
"//chrome/app:chrome_dll_resources",
"//chrome/app:win_unit_tests",
@@ -6920,6 +6919,10 @@ test("unit_tests") {
@@ -6921,6 +6920,10 @@ test("unit_tests") {
"//ui/resources",
]

View File

@@ -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 f9295c24641e9a7322f088c869d90423bcd36991..5ea6972f03fd450272de52c84f783be9113608bc 100644
index 44ab3ea5a90eb31e2bea636c7d7a9aedc4b1823a..82d197413d990a8f08f25498a66f5097681b2793 100644
--- a/content/browser/renderer_host/render_frame_host_impl.cc
+++ b/content/browser/renderer_host/render_frame_host_impl.cc
@@ -8101,6 +8101,7 @@ void RenderFrameHostImpl::CreateNewWindow(
@@ -8119,6 +8119,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,

View File

@@ -81,7 +81,7 @@ index e4deb71ea3afa1ef9d6ddac9c61f5916ff608514..d2e6854ac2aaa3cc83c0b72ebc03193b
!command_line->HasSwitch(switches::kUIDisablePartialSwap);
diff --git a/content/browser/gpu/gpu_process_host.cc b/content/browser/gpu/gpu_process_host.cc
index 3cc40e4b0183bf8f6861a6d1240df7d2972362a9..7468b1ec1b4c4e7f29baef2fc2decd2ec692351c 100644
index 981c012dc8c3c8d1106c02570e75c7b065f6b814..02dbede2d9291a702dd3d692e849938e3f501761 100644
--- a/content/browser/gpu/gpu_process_host.cc
+++ b/content/browser/gpu/gpu_process_host.cc
@@ -227,6 +227,7 @@ GpuTerminationStatus ConvertToGpuTerminationStatus(

View File

@@ -6,10 +6,10 @@ 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 7a99c04fcf5bba1eafab94bd7d2b5ee9c58d4d85..80224052d4a3c195eabeadfb0d8863a2cf31b6e2 100644
index d7b85d4a6adbe718fe5a219a5c273d05676c3ec6..b85d2f53e55131491c32eff5475cffa7c9d65e25 100644
--- a/content/browser/renderer_host/render_widget_host_impl.cc
+++ b/content/browser/renderer_host/render_widget_host_impl.cc
@@ -801,6 +801,9 @@ void RenderWidgetHostImpl::WasHidden() {
@@ -807,6 +807,9 @@ void RenderWidgetHostImpl::WasHidden() {
return;
}

View File

@@ -40,7 +40,7 @@ index c57305681efb469d296c90df68b6cdbea927580d..6dda1a5465e08df64b539ee203b7c403
// Called from BrowserMainLoop::PostCreateThreads().
// TODO(content/browser/gpu/OWNERS): This should probably use a
diff --git a/content/browser/gpu/gpu_data_manager_impl_private.cc b/content/browser/gpu/gpu_data_manager_impl_private.cc
index ef2ff9a1dd1a2b18d9896cb7e9e8adb06bf2bd18..dbf021231b9373233e55c040ea2fdb2406b90647 100644
index 5982540cdc27d7a983076af1a1ca76c996ec9082..11a888de262a8e185579fa83aabd6b5d9047985b 100644
--- a/content/browser/gpu/gpu_data_manager_impl_private.cc
+++ b/content/browser/gpu/gpu_data_manager_impl_private.cc
@@ -1222,6 +1222,12 @@ void GpuDataManagerImplPrivate::TerminateInfoCollectionGpuProcess() {

View File

@@ -6,10 +6,10 @@ Subject: mas: avoid usage of CGDisplayUsesForceToGray
Removes usage of the CGDisplayUsesForceToGray private API.
diff --git a/ui/display/mac/screen_mac.mm b/ui/display/mac/screen_mac.mm
index 074d92bd07e39d4f7d5561dae5cb09aa157b870a..6d92d63437ebf8ce68612e6fbbc1c767f23a7727 100644
index 2653ce451ee21f55824f30ee19c7b46b4c29c75e..e9144eba98b3b038f48b0c431af3bc39678ebec6 100644
--- a/ui/display/mac/screen_mac.mm
+++ b/ui/display/mac/screen_mac.mm
@@ -159,7 +159,17 @@ DisplayMac BuildDisplayForScreen(NSScreen* screen) {
@@ -170,7 +170,17 @@ DisplayMac BuildDisplayForScreen(NSScreen* screen) {
display.set_color_depth(Display::kDefaultBitsPerPixel);
display.set_depth_per_component(Display::kDefaultBitsPerComponent);
}

View File

@@ -30,10 +30,10 @@ index c4255d8dfc2e3c4f1f32506e4e9edbb90a74340a..142398a8adafc94e6724ee750b612a66
// 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 80224052d4a3c195eabeadfb0d8863a2cf31b6e2..11fde625a13a78dec5ae8245ada514e8ca6ab2c6 100644
index b85d2f53e55131491c32eff5475cffa7c9d65e25..73d9f46fd52a9bda3322d1883207a56171507692 100644
--- a/content/browser/renderer_host/render_widget_host_impl.cc
+++ b/content/browser/renderer_host/render_widget_host_impl.cc
@@ -2122,6 +2122,9 @@ void RenderWidgetHostImpl::SetCursor(const ui::Cursor& cursor) {
@@ -2128,6 +2128,9 @@ void RenderWidgetHostImpl::SetCursor(const ui::Cursor& cursor) {
if (view_) {
view_->UpdateCursor(cursor);
}

View File

@@ -15,10 +15,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 5ea6972f03fd450272de52c84f783be9113608bc..72dc42e2919fcb7bdfb15512b1ff38ea48807c7f 100644
index 82d197413d990a8f08f25498a66f5097681b2793..9d967772f7afe3987f67f1440890a43032192735 100644
--- a/content/browser/renderer_host/render_frame_host_impl.cc
+++ b/content/browser/renderer_host/render_frame_host_impl.cc
@@ -7316,6 +7316,17 @@ void RenderFrameHostImpl::EnterFullscreen(
@@ -7334,6 +7334,17 @@ void RenderFrameHostImpl::EnterFullscreen(
}
}

View File

@@ -26,7 +26,7 @@ index a4130ad4dc8158f8256b55fdd87f577687135626..3139aa65807cee23f0e8dbc85243566e
// 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 cddb519c4c893607e56ea44e17e75783fb33d373..0a3a36d2650d7aa3edb50f37898be20500fc99e5 100644
index 4ed1a50637e40df4d3a9c1a1cfb63ad948df413c..bc446fa9f6dcbaa618a06040dd215ac928388341 100644
--- a/content/renderer/renderer_blink_platform_impl.cc
+++ b/content/renderer/renderer_blink_platform_impl.cc
@@ -788,6 +788,12 @@ void RendererBlinkPlatformImpl::WillStopWorkerThread() {

View File

@@ -35,7 +35,7 @@ index 3139aa65807cee23f0e8dbc85243566ef9de89b9..19707edb1283f2432f3c0059f80fabd5
// 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 0a3a36d2650d7aa3edb50f37898be20500fc99e5..63fe14db69116258a874117232c193f4be7d8f83 100644
index bc446fa9f6dcbaa618a06040dd215ac928388341..77a9172d12af687235f303f3d38912d9b96ba6a8 100644
--- a/content/renderer/renderer_blink_platform_impl.cc
+++ b/content/renderer/renderer_blink_platform_impl.cc
@@ -800,6 +800,12 @@ void RendererBlinkPlatformImpl::WorkerContextCreated(

View File

@@ -849,10 +849,10 @@ index 0000000000000000000000000000000000000000..fb000f8ee7647c375bc190d1729d67bb
+}
diff --git a/deps/nghttp2/BUILD.gn b/deps/nghttp2/BUILD.gn
new file mode 100644
index 0000000000000000000000000000000000000000..7d2ca477db2415f43ababa270d8aefa3124b2765
index 0000000000000000000000000000000000000000..23eed033d31eced6a85c794eee550655af7a9a1d
--- /dev/null
+++ b/deps/nghttp2/BUILD.gn
@@ -0,0 +1,51 @@
@@ -0,0 +1,48 @@
+config("nghttp2_config") {
+ defines = [ "NGHTTP2_STATICLIB" ]
+ include_dirs = [ "lib/includes" ]
@@ -894,14 +894,11 @@ index 0000000000000000000000000000000000000000..7d2ca477db2415f43ababa270d8aefa3
+ "lib/nghttp2_pq.c",
+ "lib/nghttp2_priority_spec.c",
+ "lib/nghttp2_queue.c",
+ "lib/nghttp2_ratelim.c",
+ "lib/nghttp2_rcbuf.c",
+ "lib/nghttp2_session.c",
+ "lib/nghttp2_stream.c",
+ "lib/nghttp2_submit.c",
+ "lib/nghttp2_time.c",
+ "lib/nghttp2_version.c",
+ "lib/sfparse.c"
+ ]
+}
diff --git a/deps/simdutf/BUILD.gn b/deps/simdutf/BUILD.gn
@@ -932,10 +929,10 @@ index 0000000000000000000000000000000000000000..bfbd4e656db1a6c73048443f96f1d576
+}
diff --git a/deps/uv/BUILD.gn b/deps/uv/BUILD.gn
new file mode 100644
index 0000000000000000000000000000000000000000..29e66144dbb67704bad0d78c4b3f5713537c7987
index 0000000000000000000000000000000000000000..ae4d3bf68882f1aa6d7440448050fbdd9a17dca7
--- /dev/null
+++ b/deps/uv/BUILD.gn
@@ -0,0 +1,197 @@
@@ -0,0 +1,194 @@
+config("libuv_config") {
+ include_dirs = [ "include" ]
+
@@ -1008,6 +1005,7 @@ index 0000000000000000000000000000000000000000..29e66144dbb67704bad0d78c4b3f5713
+ "src/strscpy.h",
+ "src/strtok.c",
+ "src/strtok.h",
+ "src/thread-common.c",
+ "src/threadpool.c",
+ "src/timer.c",
+ "src/uv-common.c",
@@ -1112,11 +1110,7 @@ index 0000000000000000000000000000000000000000..29e66144dbb67704bad0d78c4b3f5713
+ if (is_linux) {
+ defines += [ "_GNU_SOURCE" ]
+ sources += [
+ "src/unix/epoll.c",
+ "src/unix/linux-core.c",
+ "src/unix/linux-inotify.c",
+ "src/unix/linux-syscalls.c",
+ "src/unix/linux-syscalls.h",
+ "src/unix/linux.c",
+ "src/unix/procfs-exepath.c",
+ "src/unix/random-getrandom.c",
+ "src/unix/random-sysctl-linux.c",
@@ -1179,10 +1173,10 @@ index 0000000000000000000000000000000000000000..2c9d2826c85bdd033f1df1d6188df636
+}
diff --git a/filenames.json b/filenames.json
new file mode 100644
index 0000000000000000000000000000000000000000..7d86765bf229275ba55d37a452ef24832a7afadb
index 0000000000000000000000000000000000000000..12d4706fae0d8253db8de1fc2c4e31a6380cc122
--- /dev/null
+++ b/filenames.json
@@ -0,0 +1,664 @@
@@ -0,0 +1,663 @@
+// This file is automatically generated by generate_gn_filenames_json.py
+// DO NOT EDIT
+{
@@ -1296,7 +1290,6 @@ index 0000000000000000000000000000000000000000..7d86765bf229275ba55d37a452ef2483
+ "deps/uv/include/uv/linux.h",
+ "deps/uv/include/uv/os390.h",
+ "deps/uv/include/uv/posix.h",
+ "deps/uv/include/uv/stdint-msvc2008.h",
+ "deps/uv/include/uv/sunos.h",
+ "deps/uv/include/uv/threadpool.h",
+ "deps/uv/include/uv/tree.h",
@@ -2107,7 +2100,7 @@ index 0000000000000000000000000000000000000000..4ab828dcbf322a9e28674e48c4a6868b
+ args = rebase_path(inputs + outputs, root_build_dir)
+}
diff --git a/src/node_version.h b/src/node_version.h
index 88cc915177bcf8b86eb8f9f16b215cb6d06b3aa7..8df52c22dd76a850d421075effc44fbfb32307db 100644
index 7e90c796f3bd076048a2114a1ba31db7ee876440..60a17104e0b1b19038efc1a1468ee92642d3ffd6 100644
--- a/src/node_version.h
+++ b/src/node_version.h
@@ -89,7 +89,10 @@

View File

@@ -26,10 +26,10 @@ index 0f5ddfb3ca21b7e5b38d0a4ce4b9e77387597199..ba815202fb157aa82859ec0518523cf6
.. c:function:: int uv_loop_close(uv_loop_t* loop)
diff --git a/deps/uv/include/uv.h b/deps/uv/include/uv.h
index ee1c94ccd389915ea7572cce044256a7788025ad..d31abf714d5d1433ec8473ccb1aae3b6615c477a 100644
index 02397dd0fdd43d51f86c0dde9a62046702f12bdb..3375600023e39ddacf62cc17deb4f206db942084 100644
--- a/deps/uv/include/uv.h
+++ b/deps/uv/include/uv.h
@@ -252,7 +252,8 @@ typedef struct uv_statfs_s uv_statfs_t;
@@ -260,7 +260,8 @@ typedef struct uv_metrics_s uv_metrics_t;
typedef enum {
UV_LOOP_BLOCK_SIGNAL = 0,
@@ -40,7 +40,7 @@ index ee1c94ccd389915ea7572cce044256a7788025ad..d31abf714d5d1433ec8473ccb1aae3b6
typedef enum {
diff --git a/deps/uv/src/unix/async.c b/deps/uv/src/unix/async.c
index e1805c323795e5b0c465d80100eebeb7bf838caa..dd4358c0cdaa97ba8fadf4d9755993803beddd18 100644
index 0ff2669e30a628dbb2df9e28ba14b38cf14114e5..679b17bda476d2a9c072ce8261234f837b56422f 100644
--- a/deps/uv/src/unix/async.c
+++ b/deps/uv/src/unix/async.c
@@ -38,7 +38,6 @@
@@ -49,18 +49,18 @@ index e1805c323795e5b0c465d80100eebeb7bf838caa..dd4358c0cdaa97ba8fadf4d975599380
-static void uv__async_send(uv_loop_t* loop);
static int uv__async_start(uv_loop_t* loop);
static void uv__cpu_relax(void);
@@ -70,7 +69,7 @@ int uv_async_send(uv_async_t* handle) {
return 0;
@@ -78,7 +77,7 @@ int uv_async_send(uv_async_t* handle) {
/* Wake up the other thread's event loop. */
- uv__async_send(handle->loop);
+ uv__loop_interrupt(handle->loop);
if (atomic_exchange(pending, 1) == 0)
- uv__async_send(handle->loop);
+ uv__loop_interrupt(handle->loop);
/* Tell the other thread we're done. */
if (cmpxchgi(&handle->pending, 1, 2) != 1)
@@ -165,40 +164,6 @@ static void uv__async_io(uv_loop_t* loop, uv__io_t* w, unsigned int events) {
/* Set the loop to not-busy. */
atomic_fetch_add(busy, -1);
@@ -178,40 +177,6 @@ static void uv__async_io(uv_loop_t* loop, uv__io_t* w, unsigned int events) {
}
@@ -102,10 +102,10 @@ index e1805c323795e5b0c465d80100eebeb7bf838caa..dd4358c0cdaa97ba8fadf4d975599380
int pipefd[2];
int err;
diff --git a/deps/uv/src/unix/core.c b/deps/uv/src/unix/core.c
index 54c769f37f2331136c87a37c13fb4e3f9a8f22f9..ac52ab79a5fc3050effd2b1f2f605cee9b1ab336 100644
index 25c5181f370e94983e8a5f797f02f7a8dc207e00..f4d9059796d2c65339a5d48ecb273b09d9364d21 100644
--- a/deps/uv/src/unix/core.c
+++ b/deps/uv/src/unix/core.c
@@ -900,6 +900,9 @@ void uv__io_start(uv_loop_t* loop, uv__io_t* w, unsigned int events) {
@@ -926,6 +926,9 @@ void uv__io_start(uv_loop_t* loop, uv__io_t* w, unsigned int events) {
loop->watchers[w->fd] = w;
loop->nfds++;
}
@@ -115,20 +115,20 @@ index 54c769f37f2331136c87a37c13fb4e3f9a8f22f9..ac52ab79a5fc3050effd2b1f2f605cee
}
@@ -931,6 +934,9 @@ void uv__io_stop(uv_loop_t* loop, uv__io_t* w, unsigned int events) {
@@ -957,6 +960,9 @@ void uv__io_stop(uv_loop_t* loop, uv__io_t* w, unsigned int events) {
}
else if (QUEUE_EMPTY(&w->watcher_queue))
QUEUE_INSERT_TAIL(&loop->watcher_queue, &w->watcher_queue);
else if (uv__queue_empty(&w->watcher_queue))
uv__queue_insert_tail(&loop->watcher_queue, &w->watcher_queue);
+
+ if (uv__get_internal_fields(loop)->flags & UV_LOOP_INTERRUPT_ON_IO_CHANGE)
+ uv__loop_interrupt(loop);
}
@@ -947,6 +953,9 @@ void uv__io_close(uv_loop_t* loop, uv__io_t* w) {
@@ -973,6 +979,9 @@ void uv__io_close(uv_loop_t* loop, uv__io_t* w) {
void uv__io_feed(uv_loop_t* loop, uv__io_t* w) {
if (QUEUE_EMPTY(&w->pending_queue))
QUEUE_INSERT_TAIL(&loop->pending_queue, &w->pending_queue);
if (uv__queue_empty(&w->pending_queue))
uv__queue_insert_tail(&loop->pending_queue, &w->pending_queue);
+
+ if (uv__get_internal_fields(loop)->flags & UV_LOOP_INTERRUPT_ON_IO_CHANGE)
+ uv__loop_interrupt(loop);
@@ -136,7 +136,7 @@ index 54c769f37f2331136c87a37c13fb4e3f9a8f22f9..ac52ab79a5fc3050effd2b1f2f605cee
diff --git a/deps/uv/src/unix/loop.c b/deps/uv/src/unix/loop.c
index a88e71c339351f2ebcdd6c3f933fc3b1122910ed..46fc03264b6cc1a3a4d8faf5ec5a754fc07c9b6d 100644
index a9468e8e19cbede795032980c47eb83aee1e0c68..2d28cf48efc3718de19b901b7e08b8a857d20740 100644
--- a/deps/uv/src/unix/loop.c
+++ b/deps/uv/src/unix/loop.c
@@ -217,6 +217,11 @@ int uv__loop_configure(uv_loop_t* loop, uv_loop_option option, va_list ap) {
@@ -193,10 +193,10 @@ index a88e71c339351f2ebcdd6c3f933fc3b1122910ed..46fc03264b6cc1a3a4d8faf5ec5a754f
+ abort();
+}
diff --git a/deps/uv/src/uv-common.h b/deps/uv/src/uv-common.h
index 6001b0cf68d0b0268b578218b664a737f43c9521..5d2212571f4bcb648ab332f0c5650d0fdb37c03a 100644
index cd57e5a35153d0557351b60cce0c5be7a4468b60..660caef30b1637b8009de5e55ee34f48d17e4dd0 100644
--- a/deps/uv/src/uv-common.h
+++ b/deps/uv/src/uv-common.h
@@ -140,6 +140,8 @@ int uv__loop_configure(uv_loop_t* loop, uv_loop_option option, va_list ap);
@@ -144,6 +144,8 @@ int uv__loop_configure(uv_loop_t* loop, uv_loop_option option, va_list ap);
void uv__loop_close(uv_loop_t* loop);
@@ -205,7 +205,7 @@ index 6001b0cf68d0b0268b578218b664a737f43c9521..5d2212571f4bcb648ab332f0c5650d0f
int uv__read_start(uv_stream_t* stream,
uv_alloc_cb alloc_cb,
uv_read_cb read_cb);
@@ -268,6 +270,10 @@ void uv__threadpool_cleanup(void);
@@ -280,6 +282,10 @@ void uv__threadpool_cleanup(void);
if (((h)->flags & UV_HANDLE_ACTIVE) != 0) break; \
(h)->flags |= UV_HANDLE_ACTIVE; \
if (((h)->flags & UV_HANDLE_REF) != 0) uv__active_handle_add(h); \
@@ -217,7 +217,7 @@ index 6001b0cf68d0b0268b578218b664a737f43c9521..5d2212571f4bcb648ab332f0c5650d0f
while (0)
diff --git a/deps/uv/src/win/core.c b/deps/uv/src/win/core.c
index 67af93e6571ed4324d80b6dfb2ff93db7b9cd9b1..e88008b6a288d1508c5c117d814000d63cab81c3 100644
index e9885a0f1ff3890a8d957c8793e22b01cedc0e97..ae3d09878253fe7169ad7b74b3faea0223f89de5 100644
--- a/deps/uv/src/win/core.c
+++ b/deps/uv/src/win/core.c
@@ -384,10 +384,20 @@ int uv__loop_configure(uv_loop_t* loop, uv_loop_option option, va_list ap) {
@@ -242,7 +242,7 @@ index 67af93e6571ed4324d80b6dfb2ff93db7b9cd9b1..e88008b6a288d1508c5c117d814000d6
return -1;
}
diff --git a/deps/uv/test/test-embed.c b/deps/uv/test/test-embed.c
index 1d3355fdc67310feb63738c9e30724f0e77f7895..77a63dbb4d188b2ad571c814dbc6cbc6fe5fa205 100644
index bbe56e176db17a502d7f3864ba529212f553590a..b0da9d1cddc69428e9fb3379d1338cf893ab93d2 100644
--- a/deps/uv/test/test-embed.c
+++ b/deps/uv/test/test-embed.c
@@ -25,54 +25,184 @@
@@ -463,13 +463,13 @@ index 1d3355fdc67310feb63738c9e30724f0e77f7895..77a63dbb4d188b2ad571c814dbc6cbc6
+ run_loop();
+ ASSERT_EQ(main_timer_called, 1);
MAKE_VALGRIND_HAPPY();
MAKE_VALGRIND_HAPPY(loop);
return 0;
diff --git a/deps/uv/test/test-list.h b/deps/uv/test/test-list.h
index b19c10c7e40c77061337416fd623c53d0863d276..1f54ac21c36902bccb35c64cefa8bb14dd675bb0 100644
index 78ff9c2d1621676feab5d357609970cdf1ba5864..204160f324ad1a80c9b042e62c4bedcb745666ba 100644
--- a/deps/uv/test/test-list.h
+++ b/deps/uv/test/test-list.h
@@ -265,6 +265,7 @@ TEST_DECLARE (process_priority)
@@ -273,6 +273,7 @@ TEST_DECLARE (process_priority)
TEST_DECLARE (has_ref)
TEST_DECLARE (active)
TEST_DECLARE (embed)
@@ -477,7 +477,7 @@ index b19c10c7e40c77061337416fd623c53d0863d276..1f54ac21c36902bccb35c64cefa8bb14
TEST_DECLARE (async)
TEST_DECLARE (async_null_cb)
TEST_DECLARE (eintr_handling)
@@ -867,6 +868,7 @@ TASK_LIST_START
@@ -894,6 +895,7 @@ TASK_LIST_START
TEST_ENTRY (active)
TEST_ENTRY (embed)

View File

@@ -6,10 +6,10 @@ Subject: fix: suppress clang -Wdeprecated-declarations in libuv
Should be upstreamed.
diff --git a/deps/uv/src/win/util.c b/deps/uv/src/win/util.c
index 99432053cc3b242e514268b7aba2e2d83a9e64f2..750a5424953aad104ba1e865fefd55d316485917 100644
index f6ec79cd57b5010ed5fd6829d952bcdacc8b7671..5cda078a55f7825d135a107fa98e1aa3527dd147 100644
--- a/deps/uv/src/win/util.c
+++ b/deps/uv/src/win/util.c
@@ -1743,10 +1743,17 @@ int uv_os_uname(uv_utsname_t* buffer) {
@@ -1685,10 +1685,17 @@ int uv_os_uname(uv_utsname_t* buffer) {
#ifdef _MSC_VER
#pragma warning(suppress : 4996)
#endif

View File

@@ -18,10 +18,10 @@ as launch more jobs or exit).
Fixes: https://github.com/JuliaLang/julia/issues/51461
diff --git a/deps/uv/src/win/process.c b/deps/uv/src/win/process.c
index 24c633393fd15dcf87726b174d6b027a969e0f0d..4ad9fec900fa66b0e8c6894701e94f420de903a8 100644
index 3e451e2291d6ed200ec258e874becbbea22bbc27..a71a08bdd60166ef1d4ef490ff3e083b44188852 100644
--- a/deps/uv/src/win/process.c
+++ b/deps/uv/src/win/process.c
@@ -102,6 +102,21 @@ static void uv__init_global_job_handle(void) {
@@ -105,6 +105,21 @@ static void uv__init_global_job_handle(void) {
&info,
sizeof info))
uv_fatal_error(GetLastError(), "SetInformationJobObject");
@@ -43,7 +43,7 @@ index 24c633393fd15dcf87726b174d6b027a969e0f0d..4ad9fec900fa66b0e8c6894701e94f42
}
@@ -1098,6 +1113,7 @@ int uv_spawn(uv_loop_t* loop,
@@ -1102,6 +1117,7 @@ int uv_spawn(uv_loop_t* loop,
* breakaway.
*/
process_flags |= DETACHED_PROCESS | CREATE_NEW_PROCESS_GROUP;
@@ -51,7 +51,7 @@ index 24c633393fd15dcf87726b174d6b027a969e0f0d..4ad9fec900fa66b0e8c6894701e94f42
}
if (!CreateProcessW(application_path,
@@ -1115,11 +1131,6 @@ int uv_spawn(uv_loop_t* loop,
@@ -1119,11 +1135,6 @@ int uv_spawn(uv_loop_t* loop,
goto done;
}
@@ -63,7 +63,7 @@ index 24c633393fd15dcf87726b174d6b027a969e0f0d..4ad9fec900fa66b0e8c6894701e94f42
/* If the process isn't spawned as detached, assign to the global job object
* so windows will kill it when the parent process dies. */
if (!(options->flags & UV_PROCESS_DETACHED)) {
@@ -1142,6 +1153,19 @@ int uv_spawn(uv_loop_t* loop,
@@ -1146,6 +1157,19 @@ int uv_spawn(uv_loop_t* loop,
}
}

View File

@@ -0,0 +1,3 @@
[
"shell_browser_ui_unittests"
]

View File

@@ -15,6 +15,7 @@ const fail = '✗'.red;
const args = require('minimist')(process.argv, {
string: ['runners', 'target', 'electronVersion'],
boolean: ['buildNativeTests'],
unknown: arg => unknownFlags.push(arg)
});
@@ -34,7 +35,8 @@ const BASE = path.resolve(__dirname, '../..');
const NPX_CMD = process.platform === 'win32' ? 'npx.cmd' : 'npx';
const runners = new Map([
['main', { description: 'Main process specs', run: runMainProcessElectronTests }]
['main', { description: 'Main process specs', run: runMainProcessElectronTests }],
['native', { description: 'Native specs', run: runNativeElectronTests }]
]);
const specHashPath = path.resolve(__dirname, '../spec/.hash');
@@ -181,6 +183,57 @@ async function runTestUsingElectron (specDir, testName) {
console.log(`${pass} Electron ${testName} process tests passed.`);
}
async function runNativeElectronTests () {
let testTargets = require('./native-test-targets.json');
const outDir = `out/${utils.getOutDir()}`;
// If native tests are being run, only one arg would be relevant
if (args.target && !testTargets.includes(args.target)) {
console.log(`${fail} ${args.target} must be a subset of [${[testTargets].join(', ')}]`);
process.exit(1);
}
// Optionally build all native test targets
if (args.buildNativeTests) {
for (const target of testTargets) {
const build = childProcess.spawnSync('ninja', ['-C', outDir, target], {
cwd: path.resolve(__dirname, '../..'),
stdio: 'inherit'
});
// Exit if test target failed to build
if (build.status !== 0) {
console.log(`${fail} ${target} failed to build.`);
process.exit(1);
}
}
}
// If a specific target was passed, only build and run that target
if (args.target) testTargets = [args.target];
// Run test targets
const failures = [];
for (const target of testTargets) {
console.info('\nRunning native test for target:', target);
const testRun = childProcess.spawnSync(`./${outDir}/${target}`, {
cwd: path.resolve(__dirname, '../..'),
stdio: 'inherit'
});
// Collect failures and log at end
if (testRun.status !== 0) failures.push({ target });
}
// Exit if any failures
if (failures.length > 0) {
console.log(`${fail} Electron native tests failed for the following targets: `, failures);
process.exit(1);
}
console.log(`${pass} Electron native tests passed.`);
}
async function runMainProcessElectronTests () {
await runTestUsingElectron('spec', 'main');
}

View File

@@ -85,7 +85,6 @@
#if BUILDFLAG(IS_MAC)
#include <CoreFoundation/CoreFoundation.h>
#include "base/mac/mac_util.h"
#include "shell/browser/ui/cocoa/electron_bundle_mover.h"
#endif
@@ -365,11 +364,8 @@ struct Converter<Browser::LoginItemSettings> {
dict.Get("path", &(out->path));
dict.Get("args", &(out->args));
#if BUILDFLAG(IS_WIN)
dict.Get("name", &(out->name));
dict.Get("enabled", &(out->enabled));
#elif BUILDFLAG(IS_MAC)
dict.Get("serviceName", &(out->service_name));
dict.Get("type", &(out->type));
dict.Get("name", &(out->name));
#endif
return true;
}
@@ -377,19 +373,16 @@ struct Converter<Browser::LoginItemSettings> {
static v8::Local<v8::Value> ToV8(v8::Isolate* isolate,
Browser::LoginItemSettings val) {
auto dict = gin_helper::Dictionary::CreateEmpty(isolate);
#if BUILDFLAG(IS_WIN)
dict.Set("launchItems", val.launch_items);
dict.Set("executableWillLaunchAtLogin",
val.executable_will_launch_at_login);
#elif BUILDFLAG(IS_MAC)
if (base::mac::MacOSMajorVersion() >= 13)
dict.Set("status", val.status);
#endif
dict.Set("openAtLogin", val.open_at_login);
dict.Set("openAsHidden", val.open_as_hidden);
dict.Set("restoreState", val.restore_state);
dict.Set("wasOpenedAtLogin", val.opened_at_login);
dict.Set("wasOpenedAsHidden", val.opened_as_hidden);
#if BUILDFLAG(IS_WIN)
dict.Set("launchItems", val.launch_items);
dict.Set("executableWillLaunchAtLogin",
val.executable_will_launch_at_login);
#endif
return dict.GetHandle();
}
};

View File

@@ -1877,7 +1877,7 @@ bool WebContents::EmitNavigationEvent(
dict.Set("url", url);
dict.Set("isSameDocument", is_same_document);
dict.Set("isMainFrame", is_main_frame);
dict.SetGetter("frame", frame_host);
dict.Set("frame", frame_host);
dict.SetGetter("initiator", initiator_frame_host);
EmitWithoutEvent(event_name, event, url, is_same_document, is_main_frame,
@@ -3116,7 +3116,8 @@ v8::Local<v8::Promise> WebContents::PrintToPDF(const base::Value& settings) {
auto header_template = *settings.GetDict().FindString("headerTemplate");
auto footer_template = *settings.GetDict().FindString("footerTemplate");
auto prefer_css_page_size = settings.GetDict().FindBool("preferCSSPageSize");
auto generate_tagged_pdf = settings.GetDict().FindBool("generateTaggedPDF");
auto generate_tagged_pdf =
settings.GetDict().FindBool("shouldGenerateTaggedPDF");
absl::variant<printing::mojom::PrintPagesParamsPtr, std::string>
print_pages_params = print_to_pdf::GetPrintPagesParams(

View File

@@ -135,11 +135,7 @@ class Browser : public WindowListObserver {
std::u16string path;
std::vector<std::u16string> args;
#if BUILDFLAG(IS_MAC)
std::string type = "mainAppService";
std::string service_name;
std::string status;
#elif BUILDFLAG(IS_WIN)
#if BUILDFLAG(IS_WIN)
// used in browser::setLoginItemSettings
bool enabled = true;
std::wstring name;
@@ -209,9 +205,9 @@ class Browser : public WindowListObserver {
void ApplyForcedRTL();
// Bounce the dock icon.
enum class BounceType{
kCritical = 0, // NSCriticalRequest
kInformational = 10, // NSInformationalRequest
enum class BounceType {
kCritical = 0, // NSCriticalRequest
kInformational = 10, // NSInformationalRequest
};
int DockBounce(BounceType type);
void DockCancelBounce(int request_id);

View File

@@ -8,8 +8,6 @@
#include <string>
#include <utility>
#import <ServiceManagement/ServiceManagement.h>
#include "base/apple/bridging.h"
#include "base/apple/bundle_locations.h"
#include "base/apple/scoped_cftyperef.h"
@@ -21,7 +19,6 @@
#include "chrome/browser/browser_process.h"
#include "net/base/mac/url_conversions.h"
#include "shell/browser/badging/badge_manager.h"
#include "shell/browser/javascript_environment.h"
#include "shell/browser/mac/dict_util.h"
#include "shell/browser/mac/electron_application.h"
#include "shell/browser/mac/electron_application_delegate.h"
@@ -88,15 +85,6 @@ bool CheckLoginItemStatus(bool* is_hidden) {
return true;
}
Browser::LoginItemSettings GetLoginItemSettingsDeprecated() {
Browser::LoginItemSettings settings;
settings.open_at_login = CheckLoginItemStatus(&settings.open_as_hidden);
settings.restore_state = base::mac::WasLaunchedAsLoginItemRestoreState();
settings.opened_at_login = base::mac::WasLaunchedAsLoginOrResumeItem();
settings.opened_as_hidden = base::mac::WasLaunchedAsHiddenLoginItem();
return settings;
}
#endif
} // namespace
@@ -379,71 +367,28 @@ void Browser::ApplyForcedRTL() {
Browser::LoginItemSettings Browser::GetLoginItemSettings(
const LoginItemSettings& options) {
LoginItemSettings settings;
if (options.type != "mainAppService" && options.service_name.empty()) {
gin_helper::ErrorThrower(JavascriptEnvironment::GetIsolate())
.ThrowTypeError("'name' is required when type is not mainAppService");
return settings;
}
#if IS_MAS_BUILD()
const std::string status =
platform_util::GetLoginItemEnabled(options.type, options.service_name);
settings.open_at_login =
status == "enabled" || status == "enabled-deprecated";
if (@available(macOS 13, *))
settings.status = status;
settings.open_at_login = platform_util::GetLoginItemEnabled();
#else
// If the app was previously set as a LoginItem with the deprecated API,
// we should report its LoginItemSettings via the old API.
LoginItemSettings settings_deprecated = GetLoginItemSettingsDeprecated();
if (@available(macOS 13, *)) {
const std::string status =
platform_util::GetLoginItemEnabled(options.type, options.service_name);
if (status == "enabled-deprecated") {
settings = settings_deprecated;
} else {
settings.open_at_login = status == "enabled";
settings.status = status;
}
} else {
settings = settings_deprecated;
}
settings.open_at_login = CheckLoginItemStatus(&settings.open_as_hidden);
settings.restore_state = base::mac::WasLaunchedAsLoginItemRestoreState();
settings.opened_at_login = base::mac::WasLaunchedAsLoginOrResumeItem();
settings.opened_as_hidden = base::mac::WasLaunchedAsHiddenLoginItem();
#endif
return settings;
}
void Browser::SetLoginItemSettings(LoginItemSettings settings) {
if (settings.type != "mainAppService" && settings.service_name.empty()) {
gin_helper::ErrorThrower(JavascriptEnvironment::GetIsolate())
.ThrowTypeError("'name' is required when type is not mainAppService");
return;
}
#if IS_MAS_BUILD()
platform_util::SetLoginItemEnabled(settings.type, settings.service_name,
settings.open_at_login);
if (!platform_util::SetLoginItemEnabled(settings.open_at_login)) {
LOG(ERROR) << "Unable to set login item enabled on sandboxed app.";
}
#else
const base::FilePath bundle_path = base::apple::MainBundlePath();
if (@available(macOS 13, *)) {
// If the app was previously set as a LoginItem with the old API, remove it
// as a LoginItem via the old API before re-enabling with the new API.
const std::string status =
platform_util::GetLoginItemEnabled("mainAppService", "");
if (status == "enabled-deprecated") {
base::mac::RemoveFromLoginItems(bundle_path);
if (settings.open_at_login) {
platform_util::SetLoginItemEnabled(settings.type, settings.service_name,
settings.open_at_login);
}
} else {
platform_util::SetLoginItemEnabled(settings.type, settings.service_name,
settings.open_at_login);
}
if (settings.open_at_login) {
base::mac::AddToLoginItems(base::apple::MainBundlePath(),
settings.open_as_hidden);
} else {
if (settings.open_at_login) {
base::mac::AddToLoginItems(bundle_path, settings.open_as_hidden);
} else {
base::mac::RemoveFromLoginItems(bundle_path);
}
base::mac::RemoveFromLoginItems(base::apple::MainBundlePath());
}
#endif
}

View File

@@ -66,14 +66,18 @@
// Manages the PopUpButtonHandler.
@interface ElectronAccessoryView : NSView
@property(nonatomic, strong) PopUpButtonHandler* popUpButtonHandler;
@end
@implementation ElectronAccessoryView
@synthesize popUpButtonHandler;
- (void)dealloc {
auto* popupButton =
static_cast<NSPopUpButton*>([[self subviews] objectAtIndex:1]);
popupButton.target = nil;
popUpButtonHandler = nil;
}
@end
@@ -149,6 +153,7 @@ void SetAllowedFileTypes(NSSavePanel* dialog, const Filters& filters) {
[accessoryView addSubview:label];
[accessoryView addSubview:popupButton];
[accessoryView setPopUpButtonHandler:popUpButtonHandler];
[dialog setAccessoryView:accessoryView];
}

View File

@@ -49,11 +49,8 @@ bool GetFolderPath(int key, base::FilePath* result);
#endif
#if BUILDFLAG(IS_MAC)
std::string GetLoginItemEnabled(const std::string& type,
const std::string& service_name);
bool SetLoginItemEnabled(const std::string& type,
const std::string& service_name,
bool enabled);
bool GetLoginItemEnabled();
bool SetLoginItemEnabled(bool enabled);
#endif
#if BUILDFLAG(IS_LINUX)

View File

@@ -77,81 +77,6 @@ std::string OpenPathOnThread(const base::FilePath& full_path) {
return success ? "" : "Failed to open path";
}
// https://developer.apple.com/documentation/servicemanagement/1561515-service_management_errors?language=objc
std::string GetLaunchStringForError(NSError* error) {
if (@available(macOS 13, *)) {
switch ([error code]) {
case kSMErrorAlreadyRegistered:
return "The application is already registered";
case kSMErrorAuthorizationFailure:
return "The authorization requested failed";
case kSMErrorLaunchDeniedByUser:
return "The user denied the app's launch request";
case kSMErrorInternalFailure:
return "An internal failure has occurred";
case kSMErrorInvalidPlist:
return "The app's property list is invalid";
case kSMErrorInvalidSignature:
return "The app's code signature doesn't meet the requirements to "
"perform the operation";
case kSMErrorJobMustBeEnabled:
return "The specified job is not enabled";
case kSMErrorJobNotFound:
return "The system can't find the specified job";
case kSMErrorJobPlistNotFound:
return "The app's property list cannot be found";
case kSMErrorServiceUnavailable:
return "The service necessary to perform this operation is unavailable "
"or is no longer accepting requests";
case kSMErrorToolNotValid:
return "The specified path doesn't exist or the helper tool at the "
"specified path isn't valid";
default:
return "Failed to register the login item";
}
}
return "";
}
SMAppService* GetServiceForType(const std::string& type,
const std::string& name)
API_AVAILABLE(macosx(13.0)) {
NSString* service_name = [NSString stringWithUTF8String:name.c_str()];
if (type == "mainAppService") {
return [SMAppService mainAppService];
} else if (type == "agentService") {
return [SMAppService agentServiceWithPlistName:service_name];
} else if (type == "daemonService") {
return [SMAppService daemonServiceWithPlistName:service_name];
} else if (type == "loginService") {
return [SMAppService loginItemServiceWithIdentifier:service_name];
} else {
LOG(ERROR) << "Unrecognized login item type";
return nullptr;
}
}
bool GetLoginItemEnabledDeprecated() {
BOOL enabled = NO;
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wdeprecated-declarations"
// SMJobCopyDictionary does not work in sandbox (see rdar://13626319)
CFArrayRef jobs = SMCopyAllJobDictionaries(kSMDomainUserLaunchd);
#pragma clang diagnostic pop
NSArray* jobs_ = CFBridgingRelease(jobs);
NSString* identifier = GetLoginHelperBundleIdentifier();
if (jobs_ && [jobs_ count] > 0) {
for (NSDictionary* job in jobs_) {
if ([identifier isEqualToString:[job objectForKey:@"Label"]]) {
enabled = [[job objectForKey:@"OnDemand"] boolValue];
break;
}
}
}
return enabled;
}
} // namespace
namespace platform_util {
@@ -242,50 +167,29 @@ void Beep() {
NSBeep();
}
std::string GetLoginItemEnabled(const std::string& type,
const std::string& service_name) {
bool enabled = GetLoginItemEnabledDeprecated();
if (@available(macOS 13, *)) {
SMAppService* service = GetServiceForType(type, service_name);
SMAppServiceStatus status = [service status];
if (status == SMAppServiceStatusNotRegistered)
return "not-registered";
else if (status == SMAppServiceStatusEnabled)
return "enabled";
else if (status == SMAppServiceStatusRequiresApproval)
return "requires-approval";
else if (status == SMAppServiceStatusNotFound) {
// If the login item was enabled with the old API, return that.
return enabled ? "enabled-deprecated" : "not-found";
bool GetLoginItemEnabled() {
BOOL enabled = NO;
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wdeprecated-declarations"
// SMJobCopyDictionary does not work in sandbox (see rdar://13626319)
CFArrayRef jobs = SMCopyAllJobDictionaries(kSMDomainUserLaunchd);
#pragma clang diagnostic pop
NSArray* jobs_ = CFBridgingRelease(jobs);
NSString* identifier = GetLoginHelperBundleIdentifier();
if (jobs_ && [jobs_ count] > 0) {
for (NSDictionary* job in jobs_) {
if ([identifier isEqualToString:[job objectForKey:@"Label"]]) {
enabled = [[job objectForKey:@"OnDemand"] boolValue];
break;
}
}
}
return enabled ? "enabled" : "not-registered";
return enabled;
}
bool SetLoginItemEnabled(const std::string& type,
const std::string& service_name,
bool enabled) {
if (@available(macOS 13, *)) {
#if IS_MAS_BUILD()
// If the app was previously set as a LoginItem with the old API, remove it
// as a LoginItem via the old API before re-enabling with the new API.
if (GetLoginItemEnabledDeprecated() && enabled) {
NSString* identifier = GetLoginHelperBundleIdentifier();
SMLoginItemSetEnabled((__bridge CFStringRef)identifier, false);
}
#endif
SMAppService* service = GetServiceForType(type, service_name);
NSError* error = nil;
bool result = enabled ? [service registerAndReturnError:&error]
: [service unregisterAndReturnError:&error];
if (error != nil)
LOG(ERROR) << "Unable to set login item: "
<< GetLaunchStringForError(error);
return result;
} else {
NSString* identifier = GetLoginHelperBundleIdentifier();
return SMLoginItemSetEnabled((__bridge CFStringRef)identifier, enabled);
}
bool SetLoginItemEnabled(bool enabled) {
NSString* identifier = GetLoginHelperBundleIdentifier();
return SMLoginItemSetEnabled((__bridge CFStringRef)identifier, enabled);
}
} // namespace platform_util

View File

@@ -9,9 +9,9 @@ import { promisify } from 'node:util';
import { app, BrowserWindow, Menu, session, net as electronNet, WebContents } from 'electron/main';
import { closeWindow, closeAllWindows } from './lib/window-helpers';
import { ifdescribe, ifit, listen, waitUntil } from './lib/spec-helpers';
import { expectDeprecationMessages } from './lib/deprecate-helpers';
import { once } from 'node:events';
import split = require('split')
import * as semver from 'semver';
const fixturesPath = path.resolve(__dirname, 'fixtures');
@@ -527,6 +527,27 @@ describe('app module', () => {
expect(webContents.id).to.equal(w.webContents.id);
});
// FIXME: re-enable this test on win32.
ifit(process.platform !== 'win32')('should emit renderer-process-crashed event when renderer crashes', async () => {
w = new BrowserWindow({
show: false,
webPreferences: {
nodeIntegration: true,
contextIsolation: false
}
});
await w.loadURL('about:blank');
expectDeprecationMessages(async () => {
const emitted = once(app, 'renderer-process-crashed') as Promise<[any, WebContents, boolean]>;
w.webContents.executeJavaScript('process.crash()');
const [, webContents, killed] = await emitted;
expect(webContents).to.equal(w.webContents);
expect(killed).to.be.false();
}, '\'renderer-process-crashed event\' is deprecated and will be removed. Please use \'render-process-gone event\' instead.');
});
// FIXME: re-enable this test on win32.
ifit(process.platform !== 'win32')('should emit render-process-gone event when renderer crashes', async () => {
w = new BrowserWindow({
@@ -595,9 +616,6 @@ describe('app module', () => {
});
ifdescribe(process.platform !== 'linux' && !process.mas)('app.get/setLoginItemSettings API', function () {
const isMac = process.platform === 'darwin';
const isWin = process.platform === 'win32';
const updateExe = path.resolve(path.dirname(process.execPath), '..', 'Update.exe');
const processStartArgs = [
'--processStart', `"${path.basename(process.execPath)}"`,
@@ -613,8 +631,6 @@ describe('app module', () => {
'/f',
'/d'
];
const productVersion = isMac ? cp.execSync('sw_vers -productVersion').toString().trim() : '';
const isVenturaOrHigher = semver.gt(semver.coerce(productVersion) || '0.0.0', '13.0.0');
beforeEach(() => {
app.setLoginItemSettings({ openAtLogin: false });
@@ -628,19 +644,18 @@ describe('app module', () => {
app.setLoginItemSettings({ name: 'additionalEntry', openAtLogin: false });
});
ifit(!isWin)('sets and returns the app as a login item', () => {
ifit(process.platform !== 'win32')('sets and returns the app as a login item', function () {
app.setLoginItemSettings({ openAtLogin: true });
const settings = app.getLoginItemSettings();
expect(settings.openAtLogin).to.equal(true);
expect(settings.openAsHidden).to.equal(false);
expect(settings.wasOpenedAtLogin).to.equal(false);
expect(settings.wasOpenedAsHidden).to.equal(false);
expect(settings.restoreState).to.equal(false);
if (isVenturaOrHigher) expect(settings.status).to.equal('enabled');
expect(app.getLoginItemSettings()).to.deep.equal({
openAtLogin: true,
openAsHidden: false,
wasOpenedAtLogin: false,
wasOpenedAsHidden: false,
restoreState: false
});
});
ifit(isWin)('sets and returns the app as a login item (windows)', () => {
ifit(process.platform === 'win32')('sets and returns the app as a login item (windows)', function () {
app.setLoginItemSettings({ openAtLogin: true, enabled: true });
expect(app.getLoginItemSettings()).to.deep.equal({
openAtLogin: true,
@@ -677,21 +692,18 @@ describe('app module', () => {
});
});
ifit(!isWin)('adds a login item that loads in hidden mode', () => {
ifit(process.platform !== 'win32')('adds a login item that loads in hidden mode', function () {
app.setLoginItemSettings({ openAtLogin: true, openAsHidden: true });
const settings = app.getLoginItemSettings();
expect(settings.openAtLogin).to.equal(true);
const hasOpenAsHidden = process.platform === 'darwin' && !isVenturaOrHigher;
expect(settings.openAsHidden).to.equal(hasOpenAsHidden);
expect(settings.wasOpenedAtLogin).to.equal(false);
expect(settings.wasOpenedAsHidden).to.equal(false);
expect(settings.restoreState).to.equal(false);
if (isVenturaOrHigher) expect(settings.status).to.equal('enabled');
expect(app.getLoginItemSettings()).to.deep.equal({
openAtLogin: true,
openAsHidden: process.platform === 'darwin' && !process.mas, // Only available on macOS
wasOpenedAtLogin: false,
wasOpenedAsHidden: false,
restoreState: false
});
});
ifit(isWin)('adds a login item that loads in hidden mode (windows)', () => {
ifit(process.platform === 'win32')('adds a login item that loads in hidden mode (windows)', function () {
app.setLoginItemSettings({ openAtLogin: true, openAsHidden: true });
expect(app.getLoginItemSettings()).to.deep.equal({
openAtLogin: true,
@@ -710,7 +722,7 @@ describe('app module', () => {
});
});
it('correctly sets and unsets the LoginItem', () => {
it('correctly sets and unsets the LoginItem', function () {
expect(app.getLoginItemSettings().openAtLogin).to.equal(false);
app.setLoginItemSettings({ openAtLogin: true });
@@ -720,76 +732,20 @@ describe('app module', () => {
expect(app.getLoginItemSettings().openAtLogin).to.equal(false);
});
ifit(isMac)('correctly sets and unsets the LoginItem as hidden', () => {
ifit(process.platform === 'darwin')('correctly sets and unsets the LoginItem as hidden', function () {
expect(app.getLoginItemSettings().openAtLogin).to.equal(false);
expect(app.getLoginItemSettings().openAsHidden).to.equal(false);
app.setLoginItemSettings({ openAtLogin: true, openAsHidden: true });
expect(app.getLoginItemSettings().openAtLogin).to.equal(true);
expect(app.getLoginItemSettings().openAsHidden).to.equal(!isVenturaOrHigher);
expect(app.getLoginItemSettings().openAsHidden).to.equal(true);
app.setLoginItemSettings({ openAtLogin: true, openAsHidden: false });
expect(app.getLoginItemSettings().openAtLogin).to.equal(true);
expect(app.getLoginItemSettings().openAsHidden).to.equal(false);
});
ifdescribe(isMac)('using SMAppService', () => {
ifit(isVenturaOrHigher)('can set a login item', () => {
app.setLoginItemSettings({
openAtLogin: true,
type: 'mainAppService'
});
expect(app.getLoginItemSettings()).to.deep.equal({
status: 'enabled',
openAtLogin: true,
openAsHidden: false,
restoreState: false,
wasOpenedAtLogin: false,
wasOpenedAsHidden: false
});
});
ifit(isVenturaOrHigher)('throws when setting non-default type with no name', () => {
expect(() => {
app.setLoginItemSettings({
openAtLogin: true,
type: 'daemonService'
});
}).to.throw(/'name' is required when type is not mainAppService/);
});
ifit(isVenturaOrHigher)('throws when getting non-default type with no name', () => {
expect(() => {
app.getLoginItemSettings({
type: 'daemonService'
});
}).to.throw(/'name' is required when type is not mainAppService/);
});
ifit(isVenturaOrHigher)('can unset a login item', () => {
app.setLoginItemSettings({
openAtLogin: true,
type: 'mainAppService'
});
app.setLoginItemSettings({
openAtLogin: false,
type: 'mainAppService'
});
expect(app.getLoginItemSettings()).to.deep.equal({
status: 'not-registered',
openAtLogin: false,
openAsHidden: false,
restoreState: false,
wasOpenedAtLogin: false,
wasOpenedAsHidden: false
});
});
});
ifit(isWin)('allows you to pass a custom executable and arguments', () => {
ifit(process.platform === 'win32')('allows you to pass a custom executable and arguments', function () {
app.setLoginItemSettings({ openAtLogin: true, path: updateExe, args: processStartArgs, enabled: true });
expect(app.getLoginItemSettings().openAtLogin).to.equal(false);
const openAtLoginTrueEnabledTrue = app.getLoginItemSettings({
@@ -819,7 +775,7 @@ describe('app module', () => {
expect(openAtLoginFalseEnabledFalse.executableWillLaunchAtLogin).to.equal(false);
});
ifit(isWin)('allows you to pass a custom name', () => {
ifit(process.platform === 'win32')('allows you to pass a custom name', function () {
app.setLoginItemSettings({ openAtLogin: true });
app.setLoginItemSettings({ openAtLogin: true, name: 'additionalEntry', enabled: false });
expect(app.getLoginItemSettings()).to.deep.equal({
@@ -862,7 +818,7 @@ describe('app module', () => {
});
});
ifit(isWin)('finds launch items independent of args', () => {
ifit(process.platform === 'win32')('finds launch items independent of args', function () {
app.setLoginItemSettings({ openAtLogin: true, args: ['arg1'] });
app.setLoginItemSettings({ openAtLogin: true, name: 'additionalEntry', enabled: false, args: ['arg2'] });
expect(app.getLoginItemSettings()).to.deep.equal({
@@ -888,7 +844,7 @@ describe('app module', () => {
});
});
ifit(isWin)('finds launch items independent of path quotation or casing', () => {
ifit(process.platform === 'win32')('finds launch items independent of path quotation or casing', function () {
const expectation = {
openAtLogin: false,
openAsHidden: false,
@@ -924,7 +880,7 @@ describe('app module', () => {
});
});
ifit(isWin)('detects disabled by TaskManager', async () => {
ifit(process.platform === 'win32')('detects disabled by TaskManager', async function () {
app.setLoginItemSettings({ openAtLogin: true, name: 'additionalEntry', enabled: true, args: ['arg1'] });
const appProcess = cp.spawn('reg', [...regAddArgs, '030000000000000000000000']);
await once(appProcess, 'exit');
@@ -945,7 +901,7 @@ describe('app module', () => {
});
});
ifit(isWin)('detects enabled by TaskManager', async () => {
ifit(process.platform === 'win32')('detects enabled by TaskManager', async function () {
const expectation = {
openAtLogin: false,
openAsHidden: false,

View File

@@ -1,11 +1,12 @@
import { expect } from 'chai';
import * as childProcess from 'node:child_process';
import * as path from 'node:path';
import { BrowserWindow, MessageChannelMain, utilityProcess } from 'electron/main';
import { BrowserWindow, MessageChannelMain, utilityProcess, app } from 'electron/main';
import { ifit } from './lib/spec-helpers';
import { closeWindow } from './lib/window-helpers';
import { once } from 'node:events';
import { pathToFileURL } from 'node:url';
import { setImmediate } from 'node:timers/promises';
const fixturesPath = path.resolve(__dirname, 'fixtures', 'api', 'utility-process');
const isWindowsOnArm = process.platform === 'win32' && process.arch === 'arm64';
@@ -93,6 +94,56 @@ describe('utilityProcess module', () => {
});
});
describe('app \'child-process-gone\' event', () => {
it('with default serviceName', async () => {
utilityProcess.fork(path.join(fixturesPath, 'crash.js'));
const [, details] = await once(app, 'child-process-gone') as [any, Electron.Details];
expect(details.type).to.equal('Utility');
expect(details.serviceName).to.equal('node.mojom.NodeService');
expect(details.name).to.equal('Node Utility Process');
expect(details.reason).to.be.oneOf(['crashed', 'abnormal-exit']);
});
it('with custom serviceName', async () => {
utilityProcess.fork(path.join(fixturesPath, 'crash.js'), [], { serviceName: 'Hello World!' });
const [, details] = await once(app, 'child-process-gone') as [any, Electron.Details];
expect(details.type).to.equal('Utility');
expect(details.serviceName).to.equal('node.mojom.NodeService');
expect(details.name).to.equal('Hello World!');
expect(details.reason).to.be.oneOf(['crashed', 'abnormal-exit']);
});
});
describe('app.getAppMetrics()', () => {
it('with default serviceName', async () => {
const child = utilityProcess.fork(path.join(fixturesPath, 'endless.js'));
await once(child, 'spawn');
expect(child.pid).to.not.be.null();
await setImmediate();
const details = app.getAppMetrics().find(item => item.pid === child.pid)!;
expect(details).to.be.an('object');
expect(details.type).to.equal('Utility');
expect(details.serviceName).to.to.equal('node.mojom.NodeService');
expect(details.name).to.equal('Node Utility Process');
});
it('with custom serviceName', async () => {
const child = utilityProcess.fork(path.join(fixturesPath, 'endless.js'), [], { serviceName: 'Hello World!' });
await once(child, 'spawn');
expect(child.pid).to.not.be.null();
await setImmediate();
const details = app.getAppMetrics().find(item => item.pid === child.pid)!;
expect(details).to.be.an('object');
expect(details.type).to.equal('Utility');
expect(details.serviceName).to.to.equal('node.mojom.NodeService');
expect(details.name).to.equal('Hello World!');
});
});
describe('kill() API', () => {
it('terminates the child process gracefully', async () => {
const child = utilityProcess.fork(path.join(fixturesPath, 'endless.js'), [], {

View File

@@ -6,6 +6,7 @@ import * as http from 'node:http';
import { BrowserWindow, ipcMain, webContents, session, app, BrowserView, WebContents } from 'electron/main';
import { closeAllWindows } from './lib/window-helpers';
import { ifdescribe, defer, waitUntil, listen, ifit } from './lib/spec-helpers';
import { expectDeprecationMessages } from './lib/deprecate-helpers';
import { once } from 'node:events';
import { setTimeout } from 'node:timers/promises';
@@ -2343,6 +2344,30 @@ describe('webContents module', () => {
});
});
describe('crashed event', () => {
it('does not crash main process when destroying WebContents in it', (done) => {
const contents = (webContents as typeof ElectronInternal.WebContents).create({ nodeIntegration: true });
contents.once('crashed', () => {
contents.destroy();
done();
});
contents.loadURL('about:blank').then(() => contents.forcefullyCrashRenderer());
});
it('logs a warning', async () => {
const contents = (webContents as typeof ElectronInternal.WebContents).create({ nodeIntegration: true });
await contents.loadURL('about:blank');
expectDeprecationMessages(async () => {
const crashEvent = once(contents, 'crashed');
contents.forcefullyCrashRenderer();
const [, killed] = await crashEvent;
expect(killed).to.be.a('boolean');
}, '\'crashed event\' is deprecated and will be removed. Please use \'render-process-gone event\' instead.');
});
});
describe('context-menu event', () => {
afterEach(closeAllWindows);
it('emits when right-clicked in page', async () => {

View File

@@ -90,11 +90,7 @@ app.whenReady().then(() => {
},
printBackground: true,
pageRanges: '1-3',
landscape: true,
pageSize: {
width: 100,
height: 100
}
landscape: true
}).then((data: Buffer) => console.log(data));
mainWindow.webContents.printToPDF({}).then(data => console.log(data));
@@ -441,9 +437,6 @@ app.configureHostResolver({ secureDnsMode: 'foo' });
// @ts-expect-error Removed API
console.log(app.runningUnderRosettaTranslation);
// @ts-expect-error Removed API
app.on('renderer-process-crashed', () => {});
// auto-updater
// https://github.com/electron/electron/blob/main/docs/api/auto-updater.md
@@ -1313,9 +1306,6 @@ win4.webContents.on('scroll-touch-edge', () => {});
// @ts-expect-error Removed API
win4.webContents.on('scroll-touch-end', () => {});
// @ts-expect-error Removed API
win4.webContents.on('crashed', () => {});
// TouchBar
// https://github.com/electron/electron/blob/main/docs/api/touch-bar.md