Compare commits

...

18 Commits

Author SHA1 Message Date
Sudowoodo Release Bot
2a2a1a834c Bump v17.0.0-nightly.20211102 2021-11-02 06:04:29 -07:00
Cheng Zhao
c4d35cd18c fix: do not run dialog callback inside transaction commit (#31606) 2021-11-01 17:08:31 -04:00
electron-roller[bot]
1e618ef06c chore: bump node to v16.13.0 (main) (#31607)
* chore: bump node in DEPS to v16.13.0

* 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>
2021-11-01 16:58:35 -04:00
John Kleinschmidt
c40a292099 test: fix test-datetime-change-notify after daylight change (#31654) 2021-11-01 16:31:12 -04:00
John Kleinschmidt
5899a72df9 fix: clipboard.read() to recognize custom types (#31623) 2021-11-01 10:00:36 -04:00
John Kleinschmidt
a938af3f54 fix: use disable-hid-blocklist to allow FIDO (#31626) 2021-11-01 10:00:07 -04:00
Sudowoodo Release Bot
97a109991e Bump v17.0.0-nightly.20211101 2021-11-01 06:04:57 -07:00
Shelley Vohr
20b4813cf8 fix: crash on close window when webContents destroyed (#31620) 2021-11-01 13:32:54 +09:00
Sudowoodo Release Bot
a6e5ff3607 Bump v17.0.0-nightly.20211029 2021-10-29 06:02:06 -07:00
Shelley Vohr
639f4428a5 fix: navigator.keyboard.lock() not working (#31572)
* fix: navigator.keyboard.lock() not working

* chore: address review feedback
2021-10-28 10:23:05 -04:00
Sudowoodo Release Bot
120cff38c5 Bump v17.0.0-nightly.20211028 2021-10-28 06:01:45 -07:00
Erick Zhao
ec34c6c6e7 docs: update test automation doc (#31506)
* Update WebdriverIO documentation

* Update docs/tutorial/using-selenium-and-webdriver.md

Co-authored-by: Jeremy Rose <nornagon@nornagon.net>

* Update docs/tutorial/using-selenium-and-webdriver.md

Co-authored-by: Jeremy Rose <nornagon@nornagon.net>

* docs: update automated testing docs

* lint

* update

* Update docs/tutorial/automated-testing.md

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

* fixes

Co-authored-by: Christian Bromann <github@christian-bromann.com>
Co-authored-by: Jeremy Rose <nornagon@nornagon.net>
2021-10-28 11:17:43 +09:00
Robo
3bf42593ba fix: use shorter paths for creating singleton sockets (#31608) 2021-10-27 12:25:08 -07:00
Sudowoodo Release Bot
e88a2955da Bump v17.0.0-nightly.20211027 2021-10-27 06:05:09 -07:00
Keeley Hammond
0f0ed5921d chore: fix supported versions automation (#31602) 2021-10-26 22:26:17 -07:00
Shelley Vohr
771a8f70da docs: update development-related documentation (#31043)
* docs: update chromium development-related documentation

* chore: remove obsolete clang-format doc

clang-format linting and fixing is a pre-commit hook now

* docs: update debugging documentation

* docs: misc updates

* Update docs/development/debugging-on-windows.md

Co-authored-by: Micha Hanselmann <mh74182@gmail.com>

* Update docs/development/README.md

Co-authored-by: Mark Lee <malept@users.noreply.github.com>

* Update docs/development/README.md

Co-authored-by: Mark Lee <malept@users.noreply.github.com>

* Update docs/development/README.md

Co-authored-by: Mark Lee <malept@users.noreply.github.com>

* Update docs/development/README.md

Co-authored-by: Mark Lee <malept@users.noreply.github.com>

* Update docs/development/README.md

Co-authored-by: Mark Lee <malept@users.noreply.github.com>

* Update docs/development/README.md

Co-authored-by: Mark Lee <malept@users.noreply.github.com>

* Update docs/development/debugging-on-macos.md

Co-authored-by: Mark Lee <malept@users.noreply.github.com>

* Update docs/development/testing.md

Co-authored-by: Mark Lee <malept@users.noreply.github.com>

* Update docs/development/testing.md

Co-authored-by: Mark Lee <malept@users.noreply.github.com>

Co-authored-by: Micha Hanselmann <mh74182@gmail.com>
Co-authored-by: Mark Lee <malept@users.noreply.github.com>
Co-authored-by: Cheng Zhao <zcbenz@gmail.com>
2021-10-27 10:18:38 +09:00
Erick Zhao
3193d7e99b docs: link to Apple developer docs for app.ready event (#31583)
Changes some links around. There was no link for `NSUserNotification`, and
`UNNotificationResponse` incorrectly linked to our own `NotificationResponse`
API structure doc.
2021-10-27 09:06:01 +09:00
Milan Burda
be8b1a2727 chore: update chore_add_context_to_context_aware_module_prevention.patch (#31579) 2021-10-26 15:50:29 -04:00
49 changed files with 814 additions and 606 deletions

2
DEPS
View File

@@ -17,7 +17,7 @@ vars = {
'chromium_version':
'96.0.4664.4',
'node_version':
'v16.12.0',
'v16.13.0',
'nan_version':
# The following commit hash of NAN is v2.14.2 with *only* changes to the
# test suite. This should be updated to a specific tag when one becomes

View File

@@ -1 +1 @@
17.0.0-nightly.20211026
17.0.0-nightly.20211102

View File

@@ -15,6 +15,8 @@ static_library("chrome") {
sources = [
"//chrome/browser/accessibility/accessibility_ui.cc",
"//chrome/browser/accessibility/accessibility_ui.h",
"//chrome/browser/app_mode/app_mode_utils.cc",
"//chrome/browser/app_mode/app_mode_utils.h",
"//chrome/browser/browser_process.cc",
"//chrome/browser/browser_process.h",
"//chrome/browser/devtools/devtools_contents_resizing_strategy.cc",
@@ -51,6 +53,20 @@ static_library("chrome") {
"//chrome/browser/process_singleton.h",
"//chrome/browser/ui/browser_dialogs.cc",
"//chrome/browser/ui/browser_dialogs.h",
"//chrome/browser/ui/exclusive_access/exclusive_access_bubble_type.cc",
"//chrome/browser/ui/exclusive_access/exclusive_access_bubble_type.h",
"//chrome/browser/ui/exclusive_access/exclusive_access_controller_base.cc",
"//chrome/browser/ui/exclusive_access/exclusive_access_controller_base.h",
"//chrome/browser/ui/exclusive_access/exclusive_access_manager.cc",
"//chrome/browser/ui/exclusive_access/exclusive_access_manager.h",
"//chrome/browser/ui/exclusive_access/fullscreen_controller.cc",
"//chrome/browser/ui/exclusive_access/fullscreen_controller.h",
"//chrome/browser/ui/exclusive_access/fullscreen_within_tab_helper.cc",
"//chrome/browser/ui/exclusive_access/fullscreen_within_tab_helper.h",
"//chrome/browser/ui/exclusive_access/keyboard_lock_controller.cc",
"//chrome/browser/ui/exclusive_access/keyboard_lock_controller.h",
"//chrome/browser/ui/exclusive_access/mouse_lock_controller.cc",
"//chrome/browser/ui/exclusive_access/mouse_lock_controller.h",
"//chrome/browser/ui/views/autofill/autofill_popup_view_utils.cc",
"//chrome/browser/ui/views/autofill/autofill_popup_view_utils.h",
"//chrome/browser/ui/views/eye_dropper/eye_dropper.cc",
@@ -114,6 +130,7 @@ static_library("chrome") {
"//components/keyed_service/content",
"//components/paint_preview/buildflags",
"//components/proxy_config",
"//components/services/language_detection/public/mojom",
"//content/public/browser",
"//services/strings",
]

View File

@@ -59,10 +59,9 @@ an issue:
* [Testing and Debugging](tutorial/application-debugging.md)
* [Debugging the Main Process](tutorial/debugging-main-process.md)
* [Debugging with Visual Studio Code](tutorial/debugging-vscode.md)
* [Using Selenium and WebDriver](tutorial/using-selenium-and-webdriver.md)
* [Testing on Headless CI Systems (Travis, Jenkins)](tutorial/testing-on-headless-ci.md)
* [DevTools Extension](tutorial/devtools-extension.md)
* [Automated Testing with a Custom Driver](tutorial/automated-testing-with-a-custom-driver.md)
* [Automated Testing](tutorial/automated-testing.md)
* [REPL](tutorial/repl.md)
* [Distribution](tutorial/application-distribution.md)
* [Supported Platforms](tutorial/support.md#supported-platforms)

View File

@@ -36,10 +36,10 @@ Returns:
* `launchInfo` Record<string, any> | [NotificationResponse](structures/notification-response.md) _macOS_
Emitted once, when Electron has finished initializing. On macOS, `launchInfo`
holds the `userInfo` of the `NSUserNotification` or information from
[`UNNotificationResponse`](structures/notification-response.md) that was used to open the
application, if it was launched from Notification Center. You can also call
`app.isReady()` to check if this event has already fired and `app.whenReady()`
holds the `userInfo` of the [`NSUserNotification`](https://developer.apple.com/documentation/foundation/nsusernotification)
or information from [`UNNotificationResponse`](https://developer.apple.com/documentation/usernotifications/unnotificationresponse)
that was used to open the application, if it was launched from Notification Center.
You can also call `app.isReady()` to check if this event has already fired and `app.whenReady()`
to get a Promise that is fulfilled when Electron is initialized.
### Event: 'window-all-closed'

View File

@@ -197,7 +197,7 @@ Returns `Boolean` - Whether the clipboard supports the specified `format`.
```js
const { clipboard } = require('electron')
const hasFormat = clipboard.has('<p>selection</p>')
const hasFormat = clipboard.has('public/utf8-plain-text')
console.log(hasFormat)
// 'true' or 'false'
```

View File

@@ -4,23 +4,77 @@ These guides are intended for people working on the Electron project itself.
For guides on Electron app development, see
[/docs/README.md](../README.md#guides-and-tutorials).
* [Code of Conduct](https://github.com/electron/electron/blob/main/CODE_OF_CONDUCT.md)
* [Contributing to Electron](https://github.com/electron/electron/blob/main/CONTRIBUTING.md)
## Table of Contents
* [Issues](issues.md)
* [Pull Requests](pull-requests.md)
* [Documentation Styleguide](coding-style.md#documentation)
* [Source Code Directory Structure](source-code-directory-structure.md)
* [Coding Style](coding-style.md)
* [Using clang-format on C++ Code](clang-format.md)
* [Using clang-tidy on C++ Code](clang-tidy.md)
* [Build System Overview](build-system-overview.md)
* [Build Instructions (macOS)](build-instructions-macos.md)
* [Build Instructions (Windows)](build-instructions-windows.md)
* [Build Instructions (Linux)](build-instructions-linux.md)
* [Build Instructions](build-instructions-gn.md)
* [macOS](build-instructions-macos.md)
* [Windows](build-instructions-windows.md)
* [Linux](build-instructions-linux.md)
* [Chromium Development](chromium-development.md)
* [V8 Development](v8-development.md)
* [Testing](testing.md)
* [Debugging on Windows](debug-instructions-windows.md)
* [Debugging on macOS](debugging-instructions-macos.md)
* [Setting Up Symbol Server in Debugger](setting-up-symbol-server.md)
* [Debugging](debugging.md)
* [Patches](patches.md)
## Getting Started
In order to contribute to Electron, the first thing you'll want to do is get the code.
[Electron's `build-tools`](https://github.com/electron/build-tools) automate much of the setup for compiling Electron from source with different configurations and build targets.
If you would prefer to build Electron manually, see the [build instructions](build-instructions-gn.md).
Once you've checked out and built the code, you may want to take a look around the source tree to get a better idea
of what each directory is responsible for. The [source code directory structure](source-code-directory-structure.md) gives a good overview of the purpose of each directory.
## Opening Issues on Electron
For any issue, there are generally three ways an individual can contribute:
1. By opening the issue for discussion
* If you believe that you have found a new bug in Electron, you should report it by creating a new issue in
the [`electron/electron` issue tracker](https://github.com/electron/electron/issues).
2. By helping to triage the issue
* You can do this either by providing assistive details (a reproducible test case that demonstrates a bug) or by providing suggestions to address the issue.
3. By helping to resolve the issue
* This can be done by demonstrating that the issue is not a bug or is fixed;
but more often, by opening a pull request that changes the source in `electron/electron`
in a concrete and reviewable manner.
See [issues](issues.md) for more information.
## Making a Pull Request to Electron
Most pull requests opened against the `electron/electron` repository include
changes to either the C/C++ code in the `shell/` folder,
the TypeScript code in the `lib/` folder, the documentation in `docs/`,
or tests in the `spec/` and `spec-main/` folders.
See [pull requests](pull-requests.md) for more information.
If you want to add a new API module to Electron, you'll want to look in [creating API](creating-api.md).
## Governance
Electron has a fully-fledged governance system that oversees activity in Electron and whose working groups are responsible for areas like APIs, releases, and upgrades to Electron's dependencies including Chromium and Node.js. Depending on how frequently and to what end you want to contribute, you may want to consider joining a working group.
Details about each group and their reponsibilities can be found in the [governance repo](https://github.com/electron/governance).
## Patches in Electron
Electron is built on two major upstream projects: Chromium and Node.js. Each of these projects has several of their own dependencies, too. We try our best to use these dependencies exactly as they are but sometimes we can't achieve our goals without patching those upstream dependencies to fit our use cases.
As such, we maintain a collection of patches as part of our source tree. The process for adding or altering one of these patches to Electron's source tree via a pull request can be found in [patches](patches.md).
## Debugging
There are many different approaches to debugging issues and bugs in Electron, many of which
are platform specific.
For an overview of information related to debugging Electron itself (and not an app _built with Electron_), see [debugging](debugging.md).

View File

@@ -16,6 +16,19 @@ Check the build prerequisites for your platform before proceeding
[Electron's Build Tools](https://github.com/electron/build-tools) automate much of the setup for compiling Electron from source with different configurations and build targets. If you wish to set up the environment manually, the instructions are listed below.
Electron uses [GN](https://gn.googlesource.com/gn) for project generation and
[ninja](https://ninja-build.org/) for building. Project configurations can
be found in the `.gn` and `.gni` files.
## GN Files
The following `gn` files contain the main rules for building Electron:
* `BUILD.gn` defines how Electron itself is built and
includes the default configurations for linking with Chromium.
* `build/args/{testing,release,all}.gn` contain the default build arguments for
building Electron.
## GN prerequisites
You'll need to install [`depot_tools`][depot-tools], the toolset

View File

@@ -1,80 +0,0 @@
# Build System Overview
Electron uses [GN](https://gn.googlesource.com/gn) for project generation and
[ninja](https://ninja-build.org/) for building. Project configurations can
be found in the `.gn` and `.gni` files.
## GN Files
The following `gn` files contain the main rules for building Electron:
* `BUILD.gn` defines how Electron itself is built and
includes the default configurations for linking with Chromium.
* `build/args/{debug,release,all}.gn` contain the default build arguments for
building Electron.
## Component Build
Since Chromium is quite a large project, the final linking stage can take
quite a few minutes, which makes it hard for development. In order to solve
this, Chromium introduced the "component build", which builds each component as
a separate shared library, making linking very quick but sacrificing file size
and performance.
Electron inherits this build option from Chromium. In `Debug` builds, the
binary will be linked to a shared library version of Chromium's components to
achieve fast linking time; for `Release` builds, the binary will be linked to
the static library versions, so we can have the best possible binary size and
performance.
## Tests
**NB** _this section is out of date and contains information that is no longer
relevant to the GN-built electron._
Test your changes conform to the project coding style using:
```sh
$ npm run lint
```
Test functionality using:
```sh
$ npm test
```
Whenever you make changes to Electron source code, you'll need to re-run the
build before the tests:
```sh
$ npm run build && npm test
```
You can make the test suite run faster by isolating the specific test or block
you're currently working on using Mocha's
[exclusive tests](https://mochajs.org/#exclusive-tests) feature. Append
`.only` to any `describe` or `it` function call:
```js
describe.only('some feature', () => {
// ... only tests in this block will be run
})
```
Alternatively, you can use mocha's `grep` option to only run tests matching the
given regular expression pattern:
```sh
$ npm test -- --grep child_process
```
Tests that include native modules (e.g. `runas`) can't be executed with the
debug build (see [#2558](https://github.com/electron/electron/issues/2558) for
details), but they will work with the release build.
To run the tests with the release build use:
```sh
$ npm test -- -R
```

View File

@@ -1,13 +1,39 @@
# Chromium Development
> A collection of resources for learning about Chromium and tracking its development
- [@ChromiumDev](https://twitter.com/ChromiumDev) on Twitter
- [@googlechrome](https://twitter.com/googlechrome) on Twitter
- [Blog](https://blog.chromium.org)
- [Code Search](https://cs.chromium.org/)
- [Source Code](https://cs.chromium.org/chromium/src/)
- [Development Calendar and Release Info](https://www.chromium.org/developers/calendar)
- [Discussion Groups](https://www.chromium.org/developers/discussion-groups)
> A collection of resources for learning about Chromium and tracking its development.
See also [V8 Development](v8-development.md)
## Contributing to Chromium
- [Checking Out and Building](https://chromium.googlesource.com/chromium/src/+/main/docs/#checking-out-and-building)
- [Windows](https://chromium.googlesource.com/chromium/src/+/main/docs/windows_build_instructions.md)
- [macOS](https://chromium.googlesource.com/chromium/src/+/main/docs/mac_build_instructions.md)
- [Linux](https://chromium.googlesource.com/chromium/src/+/main/docs/linux/build_instructions.md)
- [Contributing](https://chromium.googlesource.com/chromium/src/+/refs/heads/main/docs/contributing.md) - This document outlines the process of getting a code change merged to the Chromium source tree.
- Assumes a working Chromium checkout and build.
## Resources for Chromium Development
### Code Resources
- [Code Search](https://cs.chromium.org/) - Indexed and searchable source code for Chromium and associated projects.
- [Source Code](https://cs.chromium.org/chromium/src/) - The source code for Chromium itself.
- [Chromium Review](https://chromium-review.googlesource.com) - The searchable code host which facilitates code reviews for Chromium and related projects.
### Informational Resources
- [Chromium Dash](https://chromiumdash.appspot.com/home) - Chromium Dash ties together multiple data sources in order to present a consolidated view of what's going on in Chromium and Chrome, plus related projects like V8, WebRTC & Skia.
- [Schedule](https://chromiumdash.appspot.com/schedule) - Review upcoming Chromium release schedule.
- [Branches](https://chromiumdash.appspot.com/branches) - Look up which branch corresponds to which milestone.
- [Releases](https://chromiumdash.appspot.com/releases) - See what version of Chromium is shipping to each release channel and look up changes between each version.
- [Commits](https://chromiumdash.appspot.com/commits) - See and search for commits to the Chromium source tree by commit SHA or committer username.
- [Discussion Groups](https://www.chromium.org/developers/discussion-groups) - Subscribe to the following groups to get project updates and discuss the Chromium projects, and to get help in developing for Chromium-based browsers.
- [Chromium Slack](https://www.chromium.org/developers/slack) - a virtual meeting place where Chromium ecosystem developers can foster community and coordinate work.
## Social Links
- [Blog](https://blog.chromium.org) - News and developments from Chromium.
- [@ChromiumDev](https://twitter.com/ChromiumDev) - Twitter account containing news & guidance for developers from the Google Chrome Developer Relations team.
- [@googlechrome](https://twitter.com/googlechrome) - Official Twitter account for the Google Chrome browser.

View File

@@ -1,35 +0,0 @@
# Using clang-format on C++ Code
[`clang-format`](https://clang.llvm.org/docs/ClangFormat.html) is a tool to
automatically format C/C++/Objective-C code, so that developers don't need to
worry about style issues during code reviews.
It is highly recommended to format your changed C++ code before opening pull
requests, which will save you and the reviewers' time.
You can install `clang-format` and `git-clang-format` via
`npm install -g clang-format`.
To automatically format a file according to Electron C++ code style, run
`clang-format -i path/to/electron/file.cc`. It should work on macOS/Linux/Windows.
The workflow to format your changed code:
1. Make codes changes in Electron repository.
2. Run `git add your_changed_file.cc`.
3. Run `git-clang-format`, and you will probably see modifications in
`your_changed_file.cc`, these modifications are generated from `clang-format`.
4. Run `git add your_changed_file.cc`, and commit your change.
5. Now the branch is ready to be opened as a pull request.
If you want to format the changed code on your latest git commit (HEAD), you can
run `git-clang-format HEAD~1`. See `git-clang-format -h` for more details.
## Editor Integration
You can also integrate `clang-format` directly into your favorite editors.
For further guidance on setting up editor integration, see these pages:
* [Atom](https://atom.io/packages/clang-format)
* [Vim & Emacs](https://clang.llvm.org/docs/ClangFormat.html#vim-integration)
* [Visual Studio Code](https://marketplace.visualstudio.com/items?itemName=xaver.clang-format)

View File

@@ -25,9 +25,8 @@ You can run `npm run lint` to show any style issues detected by `cpplint` and
## C++ and Python
For C++ and Python, we follow Chromium's [Coding
Style](https://chromium.googlesource.com/chromium/src/+/refs/heads/main/styleguide/styleguide.md). You can use
[clang-format](clang-format.md) to format the C++ code automatically. There is
also a script `script/cpplint.py` to check whether all files conform.
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.

View File

@@ -2,25 +2,22 @@
If you experience crashes or issues in Electron that you believe are not caused
by your JavaScript application, but instead by Electron itself, debugging can
be a little bit tricky, especially for developers not used to native/C++
debugging. However, using lldb, and the Electron source code, you can enable
be a little bit tricky especially for developers not used to native/C++
debugging. However, using `lldb` and the Electron source code, you can enable
step-through debugging with breakpoints inside Electron's source code.
You can also use [XCode for debugging](debugging-instructions-macos-xcode.md) if
you prefer a graphical interface.
You can also use [XCode for debugging](debugging-with-xcode.md) if you prefer a graphical interface.
## Requirements
* **A debug build of Electron**: The easiest way is usually building it
yourself, using the tools and prerequisites listed in the
[build instructions for macOS](build-instructions-macos.md). While you can
attach to and debug Electron as you can download it directly, you will
find that it is heavily optimized, making debugging substantially more
difficult: The debugger will not be able to show you the content of all
* **A testing build of Electron**: The easiest way is usually to build it from source,
which you can do by following the instructions in the [build instructions](./build-instructions-macos.md). While you can attach to and debug Electron as you can download it directly, you will
find that it is heavily optimized, making debugging substantially more difficult.
In this case the debugger will not be able to show you the content of all
variables and the execution path can seem strange because of inlining,
tail calls, and other compiler optimizations.
* **Xcode**: In addition to Xcode, also install the Xcode command line tools.
They include LLDB, the default debugger in Xcode on macOS. It supports
* **Xcode**: In addition to Xcode, you should also install the Xcode command line tools.
They include [LLDB](https://lldb.llvm.org/), the default debugger in Xcode on macOS. It supports
debugging C, Objective-C and C++ on the desktop and iOS devices and simulator.
* **.lldbinit**: Create or edit `~/.lldbinit` to allow Chromium code to be properly source-mapped.

View File

@@ -22,7 +22,7 @@ with breakpoints inside Electron's source code.
* **Visual Studio with C++ Tools**: The free community editions of Visual
Studio 2013 and Visual Studio 2015 both work. Once installed,
[configure Visual Studio to use Electron's Symbol server](setting-up-symbol-server.md).
[configure Visual Studio to use Electron's Symbol server](debugging-with-symbol-server.md).
It will enable Visual Studio to gain a better understanding of what happens
inside Electron, making it easier to present variables in a human-readable
format.
@@ -90,3 +90,20 @@ out [this video tutorial][procmon-instructions] provided by Microsoft.
[sys-internals]: https://technet.microsoft.com/en-us/sysinternals/processmonitor.aspx
[procmon-instructions]: https://channel9.msdn.com/shows/defrag-tools/defrag-tools-4-process-monitor
## Using WinDbg
<!-- TODO(@codebytere): add images and more information here? -->
It's possible to debug crashes and issues in the Renderer process with [WinDbg](https://docs.microsoft.com/en-us/windows-hardware/drivers/debugger/getting-started-with-windbg).
To attach to a debug a process with WinDbg:
1. Add `--renderer-startup-dialog` as a command line flag to Electron.
2. Launch the app you are intending to debug.
3. A dialog box will appear with a pid: “Renderer starting with pid: 1234”.
4. Launch WinDbg and choose “File > Attach to process” in the application menu.
5. Enter in pid from the dialog box in Step 3.
6. See that the debugger will be in a paused state, and that there is a command line in the app to enter text into.
7. Type “g” into the above command line to start the debuggee.
8. Press the enter key to continue the program.
9. Go back to the dialog box and press “ok”.

View File

@@ -0,0 +1,49 @@
# Electron Debugging
There are many different approaches to debugging issues and bugs in Electron, many of which
are platform specific.
Some of the more common approaches are outlined below.
## Generic Debugging
Chromium contains logging macros which can aid debugging by printing information to console in C++ and Objective-C++.
You might use this to print out variable values, function names, and line numbers, amonst other things.
Some examples:
```cpp
LOG(INFO) << "bitmap.width(): " << bitmap.width();
LOG(INFO, bitmap.width() > 10) << "bitmap.width() is greater than 10!";
```
There are also different levels of logging severity: `INFO`, `WARN`, and `ERROR`.
See [logging.h](https://chromium.googlesource.com/chromium/src/base/+/refs/heads/main/logging.h) in Chromium's source tree for more information and examples.
## Printing Stacktraces
Chromium contains a helper to print stack traces to console without interrrupting the program.
```cpp
#include "base/debug/stack_trace.h"
...
base::debug::StackTrace().Print();
```
This will allow you to observe call chains and identify potential issue areas.
## Platform-Specific Debugging
<!-- TODO(@codebytere): add debugging file for Linux-->
- [macOS Debugging](debugging-on-macos.md)
- [Debugging with Xcode](debugging-with-xcode.md)
- [Windows Debugging](debugging-on-windows.md)
## Debugging with the Symbol Server
Debug symbols allow you to have better debugging sessions. They have information about the functions contained in executables and dynamic libraries and provide you with information to get clean call stacks. A Symbol Server allows the debugger to load the correct symbols, binaries and sources automatically without forcing users to download large debugging files.
For more information about how to set up a symbol server for Electron, see [debugging with a symbol server](debugging-with-symbol-server.md).

View File

@@ -25,16 +25,14 @@ in your config file.
When you are using Goma you can run `ninja` with a substantially higher `j`
value than would normally be supported by your machine.
Please do not set a value higher than **200** on Windows or Linux and
**50** on macOS. We monitor Goma system usage, and users found to be abusing
it with unreasonable concurrency will be de-activated.
Please do not set a value higher than **200**. We monitor Goma system usage, and users
found to be abusing it with unreasonable concurrency will be de-activated.
```bash
ninja -C out/Testing electron -j 200
```
If you're using `build-tools`, appropriate `-j` values will automatically
be used for you.
If you're using `build-tools`, appropriate `-j` values will automatically be used for you.
## Monitoring Goma

View File

@@ -79,7 +79,7 @@ $ git add my/changed/files
$ git commit
```
Note that multiple commits often get squashed when they are landed.
Note that multiple commits get squashed when they are landed.
#### Commit message guidelines
@@ -180,18 +180,10 @@ $ git push origin my-branch
### Step 9: Opening the Pull Request
From within GitHub, opening a new pull request will present you with a template
that should be filled out:
that should be filled out. It can be found [here](../../.github/PULL_REQUEST_TEMPLATE.md).
```markdown
<!--
Thank you for your pull request. Please provide a description above and review
the requirements below.
Bug fixes and new features should include tests and possibly benchmarks.
Contributors guide: https://github.com/electron/electron/blob/main/CONTRIBUTING.md
-->
```
If you do not adequately complete this template, your PR may be delayed in being merged as maintainers
seek more information or clarify ambiguities.
### Step 10: Discuss and update

View File

@@ -12,29 +12,18 @@ coding style, please see the [coding-style](coding-style.md) document.
## Linting
To ensure that your JavaScript is in compliance with the Electron coding
style, run `npm run lint-js`, which will run `standard` against both
Electron itself as well as the unit tests. If you are using an editor
with a plugin/addon system, you might want to use one of the many
[StandardJS addons][standard-addons] to be informed of coding style
violations before you ever commit them.
To ensure that your changes are in compliance with the Electron coding
style, run `npm run lint`, which will run a variety of linting checks
against your changes depending on which areas of the code they touch.
To run `standard` with parameters, run `npm run lint-js --` followed by
arguments you want passed to `standard`.
To ensure that your C++ is in compliance with the Electron coding style,
run `npm run lint-cpp`, which runs a `cpplint` script. We recommend that
you use `clang-format` and prepared [a short tutorial](clang-format.md).
There is not a lot of Python in this repository, but it too is governed
by coding style rules. `npm run lint-py` will check all Python, using
`pylint` to do so.
Many of these checks are included as precommit hooks, so it's likely
you error would be caught at commit time.
## Unit Tests
If you are not using [build-tools](https://github.com/electron/build-tools),
ensure that that name you have configured for your
local build of Electron is one of `Testing`, `Release`, `Default`, `Debug`, or
local build of Electron is one of `Testing`, `Release`, `Default`, or
you have set `process.env.ELECTRON_OUT_DIR`. Without these set, Electron will fail
to perform some pre-testing steps.
@@ -43,12 +32,34 @@ app (surprise!) that can be found in the `spec` folder. Note that it has
its own `package.json` and that its dependencies are therefore not defined
in the top-level `package.json`.
To run only tests in a specific process, run `npm run test --runners=PROCESS`
where `PROCESS` is one of `main` or `remote`.
To run only specific tests matching a pattern, run `npm run test --
-g=PATTERN`, replacing the `PATTERN` with a regex that matches the tests
you would like to run. As an example: If you want to run only IPC tests, you
would run `npm run test -- -g ipc`.
[standard-addons]: https://standardjs.com/#are-there-text-editor-plugins
## Node.js Smoke Tests
If you've made changes that might affect the way Node.js is embedded into Electron,
we have a test runner that runs all of the tests from Node.js, using Electron's custom fork
of Node.js.
To run all of the Node.js tests:
```bash
$ node script/node-spec-runner.js
```
To run a single Node.js test:
```bash
$ node script/node-spec-runner.js parallel/test-crypto-keygen
```
where the argument passed to the runner is the path to the test in
the Node.js source tree.
### Testing on Windows 10 devices

View File

@@ -1,48 +1,7 @@
# Accessibility
Making accessible applications is important and we're happy to provide
functionality to [Devtron][devtron] and [Spectron][spectron] that gives
developers the opportunity to make their apps better for everyone.
---
Accessibility concerns in Electron applications are similar to those of
websites because they're both ultimately HTML. With Electron apps, however,
you can't use the online resources for accessibility audits because your app
doesn't have a URL to point the auditor to.
These features bring those auditing tools to your Electron app. You can
choose to add audits to your tests with Spectron or use them within DevTools
with Devtron. Read on for a summary of the tools.
## Spectron
In the testing framework Spectron, you can now audit each window and `<webview>`
tag in your application. For example:
```javascript
app.client.auditAccessibility().then((audit) => {
if (audit.failed) {
console.error(audit.message)
}
})
```
You can read more about this feature in [Spectron's documentation][spectron-a11y].
## Devtron
In Devtron, there is an accessibility tab which will allow you to audit a
page in your app, sort and filter the results.
![devtron screenshot][devtron-screenshot]
Both of these tools are using the [Accessibility Developer Tools][a11y-devtools]
library built by Google for Chrome. You can learn more about the accessibility
audit rules this library uses on that [repository's wiki][a11y-devtools-wiki].
If you know of other great accessibility tools for Electron, add them to the
accessibility documentation with a pull request.
websites because they're both ultimately HTML.
## Manually enabling accessibility features
@@ -84,10 +43,6 @@ CFStringRef kAXManualAccessibility = CFSTR("AXManualAccessibility");
}
```
[devtron]: https://electronjs.org/devtron
[devtron-screenshot]: https://cloud.githubusercontent.com/assets/1305617/17156618/9f9bcd72-533f-11e6-880d-389115f40a2a.png
[spectron]: https://electronjs.org/spectron
[spectron-a11y]: https://github.com/electron/spectron#accessibility-testing
[a11y-docs]: https://www.chromium.org/developers/design-documents/accessibility#TOC-How-Chrome-detects-the-presence-of-Assistive-Technology
[a11y-devtools]: https://github.com/GoogleChrome/accessibility-developer-tools
[a11y-devtools-wiki]: https://github.com/GoogleChrome/accessibility-developer-tools/wiki/Audit-Rules

View File

@@ -1,135 +0,0 @@
# Automated Testing with a Custom Driver
To write automated tests for your Electron app, you will need a way to "drive" your application. [Spectron](https://electronjs.org/spectron) is a commonly-used solution which lets you emulate user actions via [WebDriver](https://webdriver.io/). However, it's also possible to write your own custom driver using node's builtin IPC-over-STDIO. The benefit of a custom driver is that it tends to require less overhead than Spectron, and lets you expose custom methods to your test suite.
To create a custom driver, we'll use Node.js' [child_process](https://nodejs.org/api/child_process.html) API. The test suite will spawn the Electron process, then establish a simple messaging protocol:
```js
const childProcess = require('child_process')
const electronPath = require('electron')
// spawn the process
const env = { /* ... */ }
const stdio = ['inherit', 'inherit', 'inherit', 'ipc']
const appProcess = childProcess.spawn(electronPath, ['./app'], { stdio, env })
// listen for IPC messages from the app
appProcess.on('message', (msg) => {
// ...
})
// send an IPC message to the app
appProcess.send({ my: 'message' })
```
From within the Electron app, you can listen for messages and send replies using the Node.js [process](https://nodejs.org/api/process.html) API:
```js
// listen for IPC messages from the test suite
process.on('message', (msg) => {
// ...
})
// send an IPC message to the test suite
process.send({ my: 'message' })
```
We can now communicate from the test suite to the Electron app using the `appProcess` object.
For convenience, you may want to wrap `appProcess` in a driver object that provides more high-level functions. Here is an example of how you can do this:
```js
class TestDriver {
constructor ({ path, args, env }) {
this.rpcCalls = []
// start child process
env.APP_TEST_DRIVER = 1 // let the app know it should listen for messages
this.process = childProcess.spawn(path, args, { stdio: ['inherit', 'inherit', 'inherit', 'ipc'], env })
// handle rpc responses
this.process.on('message', (message) => {
// pop the handler
const rpcCall = this.rpcCalls[message.msgId]
if (!rpcCall) return
this.rpcCalls[message.msgId] = null
// reject/resolve
if (message.reject) rpcCall.reject(message.reject)
else rpcCall.resolve(message.resolve)
})
// wait for ready
this.isReady = this.rpc('isReady').catch((err) => {
console.error('Application failed to start', err)
this.stop()
process.exit(1)
})
}
// simple RPC call
// to use: driver.rpc('method', 1, 2, 3).then(...)
async rpc (cmd, ...args) {
// send rpc request
const msgId = this.rpcCalls.length
this.process.send({ msgId, cmd, args })
return new Promise((resolve, reject) => this.rpcCalls.push({ resolve, reject }))
}
stop () {
this.process.kill()
}
}
```
In the app, you'd need to write a simple handler for the RPC calls:
```js
const METHODS = {
isReady () {
// do any setup needed
return true
}
// define your RPC-able methods here
}
const onMessage = async ({ msgId, cmd, args }) => {
let method = METHODS[cmd]
if (!method) method = () => new Error('Invalid method: ' + cmd)
try {
const resolve = await method(...args)
process.send({ msgId, resolve })
} catch (err) {
const reject = {
message: err.message,
stack: err.stack,
name: err.name
}
process.send({ msgId, reject })
}
}
if (process.env.APP_TEST_DRIVER) {
process.on('message', onMessage)
}
```
Then, in your test suite, you can use your test-driver as follows:
```js
const test = require('ava')
const electronPath = require('electron')
const app = new TestDriver({
path: electronPath,
args: ['./app'],
env: {
NODE_ENV: 'test'
}
})
test.before(async t => {
await app.isReady
})
test.after.always('cleanup', async t => {
await app.stop()
})
```

View File

@@ -0,0 +1,265 @@
# Automated Testing
Test automation is an efficient way of validating that your application code works as intended.
While Electron doesn't actively maintain its own testing solution, this guide will go over a couple
ways you can run end-to-end automated tests on your Electron app.
## Using the WebDriver interface
From [ChromeDriver - WebDriver for Chrome][chrome-driver]:
> WebDriver is an open source tool for automated testing of web apps across many
> browsers. It provides capabilities for navigating to web pages, user input,
> JavaScript execution, and more. ChromeDriver is a standalone server which
> implements WebDriver's wire protocol for Chromium. It is being developed by
> members of the Chromium and WebDriver teams.
There are a few ways that you can set up testing using WebDriver.
### With WebdriverIO
[WebdriverIO](https://webdriver.io/) (WDIO) is a test automation framework that provides a
Node.js package for testing with WebDriver. Its ecosystem also includes various plugins
(e.g. reporter and services) that can help you put together your test setup.
#### Install the testrunner
First you need to run the WebdriverIO starter toolkit in your project root directory:
```sh npm2yarn
npx wdio . --yes
```
This installs all necessary packages for you and generates a `wdio.conf.js` configuration file.
#### Connect WDIO to your Electron app
Update the capabilities in your configuration file to point to your Electron app binary:
```javascript title='wdio.conf.js'
export.config = {
// ...
capabilities: [{
browserName: 'chrome',
'goog:chromeOptions': {
binary: '/path/to/your/electron/binary', // Path to your Electron binary.
args: [/* cli arguments */] // Optional, perhaps 'app=' + /path/to/your/app/
}
}]
// ...
}
```
#### Run your tests
To run your tests:
```sh
$ npx wdio run wdio.conf.js
```
[chrome-driver]: https://sites.google.com/chromium.org/driver/
### With Selenium
[Selenium](https://www.selenium.dev/) is a web automation framework that
exposes bindings to WebDriver APIs in many languages. Their Node.js bindings
are available under the `selenium-webdriver` package on NPM.
#### Run a ChromeDriver server
In order to use Selenium with Electron, you need to download the `electron-chromedriver`
binary, and run it:
```sh npm2yarn
npm install --save-dev electron-chromedriver
./node_modules/.bin/chromedriver
Starting ChromeDriver (v2.10.291558) on port 9515
Only local connections are allowed.
```
Remember the port number `9515`, which will be used later.
#### Connect Selenium to ChromeDriver
Next, install Selenium into your project:
```sh npm2yarn
npm install --save-dev selenium-webdriver
```
Usage of `selenium-webdriver` with Electron is the same as with
normal websites, except that you have to manually specify how to connect
ChromeDriver and where to find the binary of your Electron app:
```js title='test.js'
const webdriver = require('selenium-webdriver')
const driver = new webdriver.Builder()
// The "9515" is the port opened by ChromeDriver.
.usingServer('http://localhost:9515')
.withCapabilities({
'goog:chromeOptions': {
// Here is the path to your Electron binary.
binary: '/Path-to-Your-App.app/Contents/MacOS/Electron'
}
})
.forBrowser('chrome') // note: use .forBrowser('electron') for selenium-webdriver <= 3.6.0
.build()
driver.get('http://www.google.com')
driver.findElement(webdriver.By.name('q')).sendKeys('webdriver')
driver.findElement(webdriver.By.name('btnG')).click()
driver.wait(() => {
return driver.getTitle().then((title) => {
return title === 'webdriver - Google Search'
})
}, 1000)
driver.quit()
```
## Using a custom test driver
It's also possible to write your own custom driver using Node.js' built-in IPC-over-STDIO.
Custom test drivers require you to write additional app code, but have lower overhead and let you
expose custom methods to your test suite.
To create a custom driver, we'll use Node.js' [`child_process`](https://nodejs.org/api/child_process.html) API.
The test suite will spawn the Electron process, then establish a simple messaging protocol:
```js title='testDriver.js'
const childProcess = require('child_process')
const electronPath = require('electron')
// spawn the process
const env = { /* ... */ }
const stdio = ['inherit', 'inherit', 'inherit', 'ipc']
const appProcess = childProcess.spawn(electronPath, ['./app'], { stdio, env })
// listen for IPC messages from the app
appProcess.on('message', (msg) => {
// ...
})
// send an IPC message to the app
appProcess.send({ my: 'message' })
```
From within the Electron app, you can listen for messages and send replies using the Node.js
[`process`](https://nodejs.org/api/process.html) API:
```js title='main.js'
// listen for messages from the test suite
process.on('message', (msg) => {
// ...
})
// send a message to the test suite
process.send({ my: 'message' })
```
We can now communicate from the test suite to the Electron app using the `appProcess` object.
For convenience, you may want to wrap `appProcess` in a driver object that provides more
high-level functions. Here is an example of how you can do this. Let's start by creating
a `TestDriver` class:
```js title='testDriver.js'
class TestDriver {
constructor ({ path, args, env }) {
this.rpcCalls = []
// start child process
env.APP_TEST_DRIVER = 1 // let the app know it should listen for messages
this.process = childProcess.spawn(path, args, { stdio: ['inherit', 'inherit', 'inherit', 'ipc'], env })
// handle rpc responses
this.process.on('message', (message) => {
// pop the handler
const rpcCall = this.rpcCalls[message.msgId]
if (!rpcCall) return
this.rpcCalls[message.msgId] = null
// reject/resolve
if (message.reject) rpcCall.reject(message.reject)
else rpcCall.resolve(message.resolve)
})
// wait for ready
this.isReady = this.rpc('isReady').catch((err) => {
console.error('Application failed to start', err)
this.stop()
process.exit(1)
})
}
// simple RPC call
// to use: driver.rpc('method', 1, 2, 3).then(...)
async rpc (cmd, ...args) {
// send rpc request
const msgId = this.rpcCalls.length
this.process.send({ msgId, cmd, args })
return new Promise((resolve, reject) => this.rpcCalls.push({ resolve, reject }))
}
stop () {
this.process.kill()
}
}
module.exports = { TestDriver };
```
In your app code, can then write a simple handler to receive RPC calls:
```js title='main.js'
const METHODS = {
isReady () {
// do any setup needed
return true
}
// define your RPC-able methods here
}
const onMessage = async ({ msgId, cmd, args }) => {
let method = METHODS[cmd]
if (!method) method = () => new Error('Invalid method: ' + cmd)
try {
const resolve = await method(...args)
process.send({ msgId, resolve })
} catch (err) {
const reject = {
message: err.message,
stack: err.stack,
name: err.name
}
process.send({ msgId, reject })
}
}
if (process.env.APP_TEST_DRIVER) {
process.on('message', onMessage)
}
```
Then, in your test suite, you can use your `TestDriver` class with the test automation
framework of your choosing. The following example uses
[`ava`](https://www.npmjs.com/package/ava), but other popular choices like Jest
or Mocha would work as well:
```js title='test.js'
const test = require('ava')
const electronPath = require('electron')
const { TestDriver } = require('./testDriver')
const app = new TestDriver({
path: electronPath,
args: ['./app'],
env: {
NODE_ENV: 'test'
}
})
test.before(async t => {
await app.isReady
})
test.after.always('cleanup', async t => {
await app.stop()
})
```

View File

@@ -73,7 +73,7 @@ until the maintainers feel the maintenance burden is too high to continue doing
* 17.x.y
* 16.x.y
* 15.x.y
* 13
* 14.x.y
### End-of-life

View File

@@ -1,173 +0,0 @@
# Selenium and WebDriver
From [ChromeDriver - WebDriver for Chrome][chrome-driver]:
> WebDriver is an open source tool for automated testing of web apps across many
> browsers. It provides capabilities for navigating to web pages, user input,
> JavaScript execution, and more. ChromeDriver is a standalone server which
> implements WebDriver's wire protocol for Chromium. It is being developed by
> members of the Chromium and WebDriver teams.
## Setting up Spectron
[Spectron][spectron] is the officially supported ChromeDriver testing framework
for Electron. It is built on top of [WebdriverIO](https://webdriver.io/) and
has helpers to access Electron APIs in your tests and bundles ChromeDriver.
```sh
$ npm install --save-dev spectron
```
```javascript
// A simple test to verify a visible window is opened with a title
const Application = require('spectron').Application
const assert = require('assert')
const myApp = new Application({
path: '/Applications/MyApp.app/Contents/MacOS/MyApp'
})
const verifyWindowIsVisibleWithTitle = async (app) => {
await app.start()
try {
// Check if the window is visible
const isVisible = await app.browserWindow.isVisible()
// Verify the window is visible
assert.strictEqual(isVisible, true)
// Get the window's title
const title = await app.client.getTitle()
// Verify the window's title
assert.strictEqual(title, 'My App')
} catch (error) {
// Log any failures
console.error('Test failed', error.message)
}
// Stop the application
await app.stop()
}
verifyWindowIsVisibleWithTitle(myApp)
```
## Setting up with WebDriverJs
[WebDriverJs](https://www.selenium.dev/selenium/docs/api/javascript/index.html) provides
a Node package for testing with web driver, we will use it as an example.
### 1. Start ChromeDriver
First you need to download the `chromedriver` binary, and run it:
```sh
$ npm install electron-chromedriver
$ ./node_modules/.bin/chromedriver
Starting ChromeDriver (v2.10.291558) on port 9515
Only local connections are allowed.
```
Remember the port number `9515`, which will be used later
### 2. Install WebDriverJS
```sh
$ npm install selenium-webdriver
```
### 3. Connect to ChromeDriver
The usage of `selenium-webdriver` with Electron is the same with
upstream, except that you have to manually specify how to connect
chrome driver and where to find Electron's binary:
```javascript
const webdriver = require('selenium-webdriver')
const driver = new webdriver.Builder()
// The "9515" is the port opened by chrome driver.
.usingServer('http://localhost:9515')
.withCapabilities({
'goog:chromeOptions': {
// Here is the path to your Electron binary.
binary: '/Path-to-Your-App.app/Contents/MacOS/Electron'
}
})
.forBrowser('chrome') // note: use .forBrowser('electron') for selenium-webdriver <= 3.6.0
.build()
driver.get('http://www.google.com')
driver.findElement(webdriver.By.name('q')).sendKeys('webdriver')
driver.findElement(webdriver.By.name('btnG')).click()
driver.wait(() => {
return driver.getTitle().then((title) => {
return title === 'webdriver - Google Search'
})
}, 1000)
driver.quit()
```
## Setting up with WebdriverIO
[WebdriverIO](https://webdriver.io/) provides a Node package for testing with web
driver.
### 1. Start ChromeDriver
First you need to download the `chromedriver` binary, and run it:
```sh
$ npm install electron-chromedriver
$ ./node_modules/.bin/chromedriver --url-base=wd/hub --port=9515
Starting ChromeDriver (v2.10.291558) on port 9515
Only local connections are allowed.
```
Remember the port number `9515`, which will be used later
### 2. Install WebdriverIO
```sh
$ npm install webdriverio
```
### 3. Connect to chrome driver
```javascript
const webdriverio = require('webdriverio')
const options = {
host: 'localhost', // Use localhost as chrome driver server
port: 9515, // "9515" is the port opened by chrome driver.
desiredCapabilities: {
browserName: 'chrome',
'goog:chromeOptions': {
binary: '/Path-to-Your-App/electron', // Path to your Electron binary.
args: [/* cli arguments */] // Optional, perhaps 'app=' + /path/to/your/app/
}
}
}
const client = webdriverio.remote(options)
client
.init()
.url('http://google.com')
.setValue('#q', 'webdriverio')
.click('#btnG')
.getTitle().then((title) => {
console.log('Title was: ' + title)
})
.end()
```
## Workflow
To test your application without rebuilding Electron,
[place](application-distribution.md)
your app source into Electron's resource directory.
Alternatively, pass an argument to run with your Electron binary that points to
your app's folder. This eliminates the need to copy-paste your app into
Electron's resource directory.
[chrome-driver]: https://sites.google.com/a/chromium.org/chromedriver/
[spectron]: https://electronjs.org/spectron

View File

@@ -93,7 +93,7 @@ Debugging native modules can be done with Visual Studio 2017 (running on your de
1. Launch your app `.exe` on the target device via the _Command Prompt_ (passing `--inspect-brk` to pause it before any native modules are loaded).
2. Launch Visual Studio 2017 on your development machine.
3. Connect to the target device by selecting _Debug > Attach to Process..._ and enter the device's IP address and the port number displayed by the Visual Studio Remote Debugger tool.
4. Click _Refresh_ and select the [appropriate Electron process to attach](../development/debug-instructions-windows.md).
4. Click _Refresh_ and select the [appropriate Electron process to attach](../development/debugging-on-windows.md).
5. You may need to make sure that any symbols for native modules in your app are loaded correctly. To configure this, head to _Debug > Options..._ in Visual Studio 2017, and add the folders containing your `.pdb` symbols under _Debugging > Symbols_.
6. Once attached, set any appropriate breakpoints and resume JavaScript execution using Chrome's [remote tools for Node](debugging-main-process.md).

View File

@@ -1,6 +1,6 @@
{
"name": "electron",
"version": "17.0.0-nightly.20211026",
"version": "17.0.0-nightly.20211102",
"repository": "https://github.com/electron/electron",
"description": "Build cross platform desktop apps with JavaScript, HTML, and CSS",
"devDependencies": {

View File

@@ -109,3 +109,4 @@ fix_expose_decrementcapturercount_in_web_contents_impl.patch
feat_add_data_parameter_to_processsingleton.patch
mas_gate_private_enterprise_APIs
load_v8_snapshot_in_browser_process.patch
fix_patch_out_permissions_checks_in_exclusive_access.patch

View File

@@ -61,7 +61,7 @@ index eec994c4252f17d9c9c41e66d5dae6509ed98a18..e538c9b76da4d4435e10cd3848438446
#if defined(OS_WIN)
bool EscapeVirtualization(const base::FilePath& user_data_dir);
diff --git a/chrome/browser/process_singleton_posix.cc b/chrome/browser/process_singleton_posix.cc
index 727333dd6abec99643e31bc77ed2cc8f3d5a0a0b..e5361397f78636816507355e7db6a9e55e6ed234 100644
index a04d139f958a7aaef9b96e8c29317ccf7c97f009..29188668a69047b3ad3bebd1f0057565a330b509 100644
--- a/chrome/browser/process_singleton_posix.cc
+++ b/chrome/browser/process_singleton_posix.cc
@@ -567,6 +567,7 @@ class ProcessSingleton::LinuxWatcher

View File

@@ -0,0 +1,51 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Shelley Vohr <shelley.vohr@gmail.com>
Date: Mon, 25 Oct 2021 21:45:57 +0200
Subject: fix: patch out permissions checks in exclusive_access
This patch is necessary in order to properly enable
navigator.keyboard.{(un)?lock}() functionality. We don't have a concept
of PermissionManager nor of a Profile, so this would not affect usage of
the API.
We might consider potentially using our own permissions handler,
but it's not strictly necessary for this API to work to spec.
Profile check has been upstreamed at https://chromium-review.googlesource.com/c/chromium/src/+/3247196
diff --git a/chrome/browser/ui/exclusive_access/fullscreen_controller.cc b/chrome/browser/ui/exclusive_access/fullscreen_controller.cc
index e9c8a4a4bb7334682ceeec05b3a3e872de0192ab..861307591f3721c398c454126cb5a9be9a5e9764 100644
--- a/chrome/browser/ui/exclusive_access/fullscreen_controller.cc
+++ b/chrome/browser/ui/exclusive_access/fullscreen_controller.cc
@@ -368,13 +368,9 @@ void FullscreenController::EnterFullscreenModeInternal(
// Do not enter fullscreen mode if disallowed by pref. This prevents the user
// from manually entering fullscreen mode and also disables kiosk mode on
// desktop platforms.
- if (!exclusive_access_manager()
- ->context()
- ->GetProfile()
- ->GetPrefs()
- ->GetBoolean(prefs::kFullscreenAllowed)) {
+ auto* profile = exclusive_access_manager()->context()->GetProfile();
+ if (!profile || !profile->GetPrefs()->GetBoolean(prefs::kFullscreenAllowed))
return;
- }
#endif
toggled_into_fullscreen_ = true;
@@ -387,6 +383,7 @@ void FullscreenController::EnterFullscreenModeInternal(
url = extension_caused_fullscreen_;
}
+#if 0
if (display_id != display::kInvalidDisplayId) {
// Check, but do not prompt, for permission to request a specific screen.
// Sites generally need permission to get the display id in the first place.
@@ -400,6 +397,7 @@ void FullscreenController::EnterFullscreenModeInternal(
display_id = display::kInvalidDisplayId;
}
}
+#endif
if (option == BROWSER)
base::RecordAction(base::UserMetricsAction("ToggleFullscreen"));

View File

@@ -76,7 +76,7 @@ index 0d7c1db6489d95a40c66808c3f838b0740e46ff6..eec994c4252f17d9c9c41e66d5dae650
#if defined(OS_MAC)
diff --git a/chrome/browser/process_singleton_posix.cc b/chrome/browser/process_singleton_posix.cc
index 4547eb8563e1af57aad991d9d1e2cf02c778380a..727333dd6abec99643e31bc77ed2cc8f3d5a0a0b 100644
index 4547eb8563e1af57aad991d9d1e2cf02c778380a..a04d139f958a7aaef9b96e8c29317ccf7c97f009 100644
--- a/chrome/browser/process_singleton_posix.cc
+++ b/chrome/browser/process_singleton_posix.cc
@@ -80,6 +80,7 @@
@@ -171,7 +171,7 @@ index 4547eb8563e1af57aad991d9d1e2cf02c778380a..727333dd6abec99643e31bc77ed2cc8f
ProcessSingleton::NotifyResult
ProcessSingleton::NotifyOtherProcessWithTimeoutOrCreate(
const base::CommandLine& command_line,
@@ -999,12 +1039,26 @@ bool ProcessSingleton::Create() {
@@ -999,14 +1039,32 @@ bool ProcessSingleton::Create() {
#endif
}
@@ -180,15 +180,15 @@ index 4547eb8563e1af57aad991d9d1e2cf02c778380a..727333dd6abec99643e31bc77ed2cc8f
- // do not support Unix domain sockets.
- if (!socket_dir_.CreateUniqueTempDir()) {
- LOG(ERROR) << "Failed to create socket directory.";
- return false;
+ base::FilePath tmp_dir;
+ if (!base::GetTempDir(&tmp_dir)) {
+ LOG(ERROR) << "Failed to get temporary directory.";
return false;
}
+ if (IsAppSandboxed()) {
+ // For sandboxed applications, the tmp dir could be too long to fit
+ // addr->sun_path, so we need to make it as short as possible.
+ base::FilePath tmp_dir;
+ if (!base::GetTempDir(&tmp_dir)) {
+ LOG(ERROR) << "Failed to get temporary directory.";
+ return false;
+ }
+ if (!socket_dir_.Set(tmp_dir.Append("S"))) {
+ LOG(ERROR) << "Failed to set socket directory.";
+ return false;
@@ -197,14 +197,19 @@ index 4547eb8563e1af57aad991d9d1e2cf02c778380a..727333dd6abec99643e31bc77ed2cc8f
+ // Create the socket file somewhere in /tmp which is usually mounted as a
+ // normal filesystem. Some network filesystems (notably AFS) are screwy and
+ // do not support Unix domain sockets.
+ if (!socket_dir_.CreateUniqueTempDir()) {
+ // Prefer CreateUniqueTempDirUnderPath rather than CreateUniqueTempDir as
+ // the latter will calculate unique paths based on bundle ids which can
+ // increase the socket path length than what is allowed.
+ if (!socket_dir_.CreateUniqueTempDirUnderPath(tmp_dir)) {
+ LOG(ERROR) << "Failed to create socket directory.";
+ return false;
+ }
}
+ }
+
// Check that the directory was created with the correct permissions.
@@ -1046,10 +1100,13 @@ bool ProcessSingleton::Create() {
int dir_mode = 0;
CHECK(base::GetPosixFilePermissions(socket_dir_.GetPath(), &dir_mode) &&
@@ -1046,10 +1104,13 @@ bool ProcessSingleton::Create() {
if (listen(sock, 5) < 0)
NOTREACHED() << "listen failed: " << base::safe_strerror(errno);

View File

@@ -24,3 +24,4 @@ repl_fix_crash_when_sharedarraybuffer_disabled.patch
fix_readbarrier_undefined_symbol_error_on_woa_arm64.patch
chore_fix_-wimplicit-fallthrough.patch
fix_event_with_invalid_timestamp_in_trace_log.patch
test_fix_test-datetime-change-notify_after_daylight_change.patch

View File

@@ -1772,7 +1772,7 @@ index 0000000000000000000000000000000000000000..d1d6b51e8c0c5bc6a5d09e217eb30483
+ args = rebase_path(inputs + outputs, root_build_dir)
+}
diff --git a/src/node_version.h b/src/node_version.h
index 7d8e7e507b2481e1f49c8da7c75a58dc8f90640e..d8ed5d33c3cf786ba2df9d37083c1ef103e06489 100644
index 08e957472cfeca84af8cdc951af3c0de99c7b56c..330d77e868a50e1d0b71d773ab6b4b337ab20428 100644
--- a/src/node_version.h
+++ b/src/node_version.h
@@ -89,7 +89,10 @@

View File

@@ -8,7 +8,7 @@ modules from being used in the renderer process. This should be upstreamed as
a customizable error message.
diff --git a/src/node_binding.cc b/src/node_binding.cc
index e323f76261f2028ef58da74066f9112d8a5a8df2..02d8566caffb86d05645fb602ca7b5c6b8c71aa9 100644
index e323f76261f2028ef58da74066f9112d8a5a8df2..bec34a61e0be78d863e476c75647e3496aa6a2c5 100644
--- a/src/node_binding.cc
+++ b/src/node_binding.cc
@@ -4,6 +4,7 @@
@@ -27,7 +27,7 @@ index e323f76261f2028ef58da74066f9112d8a5a8df2..02d8566caffb86d05645fb602ca7b5c6
+ char errmsg[1024];
+ snprintf(errmsg,
+ sizeof(errmsg),
+ "Loading non-context-aware native module in renderer: '%s', but app.allowRendererProcessReuse is true. See https://github.com/electron/electron/issues/18397.",
+ "Loading non-context-aware native module in renderer: '%s'. See https://github.com/electron/electron/issues/18397.",
+ *filename);
+ env->ThrowError(errmsg);
return false;

View File

@@ -0,0 +1,39 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Piotr Rybak <rybak.piotr@yahoo.com>
Date: Sun, 31 Oct 2021 17:58:09 +0900
Subject: test: fix test-datetime-change-notify after daylight change
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Add standard timezone name for Dublin without daylight saving
PR-URL: https://github.com/nodejs/node/pull/40684
Reviewed-By: Michaël Zasso <targos@protonmail.com>
Reviewed-By: Tobias Nießen <tniessen@tnie.de>
Reviewed-By: Voltrex <mohammadkeyvanzade94@gmail.com>
(cherry picked from commit 747ef34fb0c9c1f2924ab1b79ea000c87e67a8eb)
diff --git a/test/parallel/test-datetime-change-notify.js b/test/parallel/test-datetime-change-notify.js
index 9cd6d7abfd898ac6781b04422362a6b459b7dc2c..01843511907077857be22c9bc7e7f8568fc677d1 100644
--- a/test/parallel/test-datetime-change-notify.js
+++ b/test/parallel/test-datetime-change-notify.js
@@ -18,15 +18,15 @@ const cases = [
},
{
timeZone: 'America/New_York',
- expected: /Eastern (Standard|Daylight) Time/,
+ expected: /Eastern (?:Standard|Daylight) Time/,
},
{
timeZone: 'America/Los_Angeles',
- expected: /Pacific (Standard|Daylight) Time/,
+ expected: /Pacific (?:Standard|Daylight) Time/,
},
{
timeZone: 'Europe/Dublin',
- expected: /Irish/,
+ expected: /Irish Standard Time|Greenwich Mean Time/,
},
];

View File

@@ -90,6 +90,7 @@ const LINTERS = [{
spawnAndCheckExitCode('python', ['script/run-clang-format.py', ...filenames]);
}
const filter = [
'-readability/braces',
'-readability/casting',
'-whitespace/braces',
'-whitespace/indent',

View File

@@ -174,7 +174,7 @@ async function updateWinRC (components) {
// updates support.md file with new semver values (stable only)
async function updateSupported (version, filePath) {
const v = parseInt(version);
const newVersions = [`* ${v}.x.y`, `* ${v - 1}.x.y`, `* ${v - 2}.x.y`, `* ${v - 3}`];
const newVersions = [`* ${v}.x.y`, `* ${v - 1}.x.y`, `* ${v - 2}.x.y`, `* ${v - 3}.x.y`];
const contents = await readFile(filePath, 'utf8');
const previousVersions = contents.split('\n').filter((elem) => {
return (/[^\n]*\.x\.y[^\n]*/).test(elem);

View File

@@ -254,7 +254,7 @@ void BrowserWindow::OnCloseButtonClicked(bool* prevent_default) {
ScheduleUnresponsiveEvent(5000);
// Already closed by renderer.
if (!web_contents())
if (!web_contents() || !api_web_contents_)
return;
// Required to make beforeunload handler work.

View File

@@ -26,6 +26,7 @@
#include "base/threading/thread_task_runner_handle.h"
#include "base/values.h"
#include "chrome/browser/browser_process.h"
#include "chrome/browser/ui/exclusive_access/exclusive_access_manager.h"
#include "chrome/browser/ui/views/eye_dropper/eye_dropper.h"
#include "chrome/common/pref_names.h"
#include "components/prefs/pref_service.h"
@@ -630,6 +631,7 @@ WebContents::WebContents(v8::Isolate* isolate,
id_(GetAllWebContents().Add(this)),
devtools_file_system_indexer_(
base::MakeRefCounted<DevToolsFileSystemIndexer>()),
exclusive_access_manager_(std::make_unique<ExclusiveAccessManager>(this)),
file_task_runner_(
base::ThreadPool::CreateSequencedTaskRunner({base::MayBlock()}))
#if BUILDFLAG(ENABLE_PRINTING)
@@ -668,6 +670,7 @@ WebContents::WebContents(v8::Isolate* isolate,
id_(GetAllWebContents().Add(this)),
devtools_file_system_indexer_(
base::MakeRefCounted<DevToolsFileSystemIndexer>()),
exclusive_access_manager_(std::make_unique<ExclusiveAccessManager>(this)),
file_task_runner_(
base::ThreadPool::CreateSequencedTaskRunner({base::MayBlock()}))
#if BUILDFLAG(ENABLE_PRINTING)
@@ -688,6 +691,7 @@ WebContents::WebContents(v8::Isolate* isolate,
: id_(GetAllWebContents().Add(this)),
devtools_file_system_indexer_(
base::MakeRefCounted<DevToolsFileSystemIndexer>()),
exclusive_access_manager_(std::make_unique<ExclusiveAccessManager>(this)),
file_task_runner_(
base::ThreadPool::CreateSequencedTaskRunner({base::MayBlock()}))
#if BUILDFLAG(ENABLE_PRINTING)
@@ -1252,6 +1256,40 @@ void WebContents::ContentsZoomChange(bool zoom_in) {
Emit("zoom-changed", zoom_in ? "in" : "out");
}
Profile* WebContents::GetProfile() {
return nullptr;
}
bool WebContents::IsFullscreen() const {
return owner_window_ && owner_window_->IsFullscreen();
}
void WebContents::EnterFullscreen(const GURL& url,
ExclusiveAccessBubbleType bubble_type,
const int64_t display_id) {}
void WebContents::ExitFullscreen() {}
void WebContents::UpdateExclusiveAccessExitBubbleContent(
const GURL& url,
ExclusiveAccessBubbleType bubble_type,
ExclusiveAccessBubbleHideCallback bubble_first_hide_callback,
bool force_update) {}
void WebContents::OnExclusiveAccessUserInput() {}
content::WebContents* WebContents::GetActiveWebContents() {
return web_contents();
}
bool WebContents::CanUserExitFullscreen() const {
return true;
}
bool WebContents::IsExclusiveAccessBubbleDisplayed() const {
return false;
}
void WebContents::EnterFullscreenModeForTab(
content::RenderFrameHost* requesting_frame,
const blink::mojom::FullscreenOptions& options) {
@@ -1262,6 +1300,8 @@ void WebContents::EnterFullscreenModeForTab(
base::BindRepeating(&WebContents::OnEnterFullscreenModeForTab,
base::Unretained(this), requesting_frame, options);
permission_helper->RequestFullscreenPermission(callback);
exclusive_access_manager_->fullscreen_controller()->EnterFullscreenModeForTab(
requesting_frame, options.display_id);
}
void WebContents::OnEnterFullscreenModeForTab(
@@ -1298,6 +1338,9 @@ void WebContents::ExitFullscreenModeForTab(content::WebContents* source) {
// `chrome/browser/ui/exclusive_access/fullscreen_controller.cc`.
source->GetRenderViewHost()->GetWidget()->SynchronizeVisualProperties();
}
exclusive_access_manager_->fullscreen_controller()->ExitFullscreenModeForTab(
source);
}
void WebContents::RendererUnresponsive(
@@ -1346,6 +1389,18 @@ void WebContents::FindReply(content::WebContents* web_contents,
Emit("found-in-page", result.GetHandle());
}
void WebContents::RequestKeyboardLock(content::WebContents* web_contents,
bool esc_key_locked) {
exclusive_access_manager_->keyboard_lock_controller()->RequestKeyboardLock(
web_contents, esc_key_locked);
}
void WebContents::CancelKeyboardLockRequest(
content::WebContents* web_contents) {
exclusive_access_manager_->keyboard_lock_controller()
->CancelKeyboardLockRequest(web_contents);
}
bool WebContents::CheckMediaAccessPermission(
content::RenderFrameHost* render_frame_host,
const GURL& security_origin,

View File

@@ -16,6 +16,7 @@
#include "base/observer_list_types.h"
#include "chrome/browser/devtools/devtools_eye_dropper.h"
#include "chrome/browser/devtools/devtools_file_system_indexer.h"
#include "chrome/browser/ui/exclusive_access/exclusive_access_context.h" // nogncheck
#include "content/common/cursors/webcursor.h"
#include "content/common/frame.mojom.h"
#include "content/public/browser/devtools_agent_host.h"
@@ -74,6 +75,8 @@ namespace gin {
class Arguments;
}
class ExclusiveAccessManager;
namespace electron {
class ElectronBrowserContext;
@@ -98,7 +101,8 @@ using DevicePermissionMap = std::map<
std::map<url::Origin, std::vector<std::unique_ptr<base::Value>>>>>;
// Wrapper around the content::WebContents.
class WebContents : public gin::Wrappable<WebContents>,
class WebContents : public ExclusiveAccessContext,
public gin::Wrappable<WebContents>,
public gin_helper::EventEmitterMixin<WebContents>,
public gin_helper::Constructible<WebContents>,
public gin_helper::Pinnable<WebContents>,
@@ -549,6 +553,9 @@ class WebContents : public gin::Wrappable<WebContents>,
const gfx::Rect& selection_rect,
int active_match_ordinal,
bool final_update) override;
void RequestKeyboardLock(content::WebContents* web_contents,
bool esc_key_locked) override;
void CancelKeyboardLockRequest(content::WebContents* web_contents) override;
bool CheckMediaAccessPermission(content::RenderFrameHost* render_frame_host,
const GURL& security_origin,
blink::mojom::MediaStreamType type) override;
@@ -647,6 +654,24 @@ class WebContents : public gin::Wrappable<WebContents>,
void EnumerateDirectory(content::WebContents* web_contents,
scoped_refptr<content::FileSelectListener> listener,
const base::FilePath& path) override;
// ExclusiveAccessContext:
Profile* GetProfile() override;
bool IsFullscreen() const override;
void EnterFullscreen(const GURL& url,
ExclusiveAccessBubbleType bubble_type,
const int64_t display_id) override;
void ExitFullscreen() override;
void UpdateExclusiveAccessExitBubbleContent(
const GURL& url,
ExclusiveAccessBubbleType bubble_type,
ExclusiveAccessBubbleHideCallback bubble_first_hide_callback,
bool force_update) override;
void OnExclusiveAccessUserInput() override;
content::WebContents* GetActiveWebContents() override;
bool CanUserExitFullscreen() const override;
bool IsExclusiveAccessBubbleDisplayed() const override;
bool IsFullscreenForTabOrPending(const content::WebContents* source) override;
blink::SecurityStyle GetSecurityStyle(
content::WebContents* web_contents,
@@ -760,6 +785,8 @@ class WebContents : public gin::Wrappable<WebContents>,
scoped_refptr<DevToolsFileSystemIndexer> devtools_file_system_indexer_;
std::unique_ptr<ExclusiveAccessManager> exclusive_access_manager_;
std::unique_ptr<DevToolsEyeDropper> eye_dropper_;
ElectronBrowserContext* browser_context_;

View File

@@ -31,6 +31,7 @@
#include "chrome/common/chrome_version.h"
#include "components/net_log/chrome_net_log.h"
#include "components/network_hints/common/network_hints.mojom.h"
#include "content/browser/keyboard_lock/keyboard_lock_service_impl.h" // nogncheck
#include "content/browser/site_instance_impl.h" // nogncheck
#include "content/public/browser/browser_main_runner.h"
#include "content/public/browser/browser_ppapi_host.h"
@@ -1571,6 +1572,8 @@ void ElectronBrowserClient::RegisterBrowserInterfaceBindersForFrame(
base::BindRepeating(&badging::BadgeManager::BindFrameReceiver));
map->Add<electron::mojom::ElectronBrowser>(
base::BindRepeating(&BindElectronBrowser));
map->Add<blink::mojom::KeyboardLockService>(base::BindRepeating(
&content::KeyboardLockServiceImpl::CreateMojoService));
#if BUILDFLAG(ENABLE_ELECTRON_EXTENSIONS)
map->Add<extensions::mime_handler::MimeHandlerService>(
base::BindRepeating(&BindMimeHandlerService));

View File

@@ -7,7 +7,9 @@
#include <string>
#include <utility>
#include "base/command_line.h"
#include "content/public/browser/web_contents.h"
#include "services/device/public/cpp/hid/hid_switches.h"
#include "shell/browser/hid/hid_chooser_context.h"
#include "shell/browser/hid/hid_chooser_context_factory.h"
#include "shell/browser/hid/hid_chooser_controller.h"
@@ -103,7 +105,8 @@ const device::mojom::HidDeviceInfo* ElectronHidDelegate::GetDeviceInfo(
}
bool ElectronHidDelegate::IsFidoAllowedForOrigin(const url::Origin& origin) {
return false;
return base::CommandLine::ForCurrentProcess()->HasSwitch(
switches::kDisableHidBlocklist);
}
void ElectronHidDelegate::OnDeviceAdded(

View File

@@ -50,8 +50,8 @@ END
//
VS_VERSION_INFO VERSIONINFO
FILEVERSION 17,0,0,20211026
PRODUCTVERSION 17,0,0,20211026
FILEVERSION 17,0,0,20211102
PRODUCTVERSION 17,0,0,20211102
FILEFLAGSMASK 0x3fL
#ifdef _DEBUG
FILEFLAGS 0x1L

View File

@@ -16,6 +16,9 @@
#include "base/mac/mac_util.h"
#include "base/mac/scoped_cftyperef.h"
#include "base/strings/sys_string_conversions.h"
#include "base/task/post_task.h"
#include "content/public/browser/browser_task_traits.h"
#include "content/public/browser/browser_thread.h"
#include "shell/browser/native_window.h"
#include "shell/common/gin_converters/file_path_converter.h"
@@ -290,6 +293,27 @@ void ReadDialogPaths(NSOpenPanel* dialog, std::vector<base::FilePath>* paths) {
ReadDialogPathsWithBookmarks(dialog, paths, &ignored_bookmarks);
}
void ResolvePromiseInNextTick(gin_helper::Promise<v8::Local<v8::Value>> promise,
v8::Local<v8::Value> value) {
// The completionHandler runs inside a transaction commit, and we should
// not do any runModal inside it. However since we can not control what
// users will run in the microtask, we have to delay the resolution until
// next tick, otherwise crash like this may happen:
// https://github.com/electron/electron/issues/26884
base::PostTask(
FROM_HERE, {content::BrowserThread::UI},
base::BindOnce(
[](gin_helper::Promise<v8::Local<v8::Value>> promise,
v8::Global<v8::Value> global) {
v8::Isolate* isolate = promise.isolate();
v8::Locker locker(isolate);
v8::HandleScope handle_scope(isolate);
v8::Local<v8::Value> value = global.Get(isolate);
promise.Resolve(value);
},
std::move(promise), v8::Global<v8::Value>(promise.isolate(), value)));
}
} // namespace
bool ShowOpenDialogSync(const DialogSettings& settings,
@@ -320,7 +344,6 @@ void OpenDialogCompletion(int chosen,
#if defined(MAS_BUILD)
dict.Set("bookmarks", std::vector<std::string>());
#endif
promise.Resolve(dict);
} else {
std::vector<base::FilePath> paths;
dict.Set("canceled", false);
@@ -336,8 +359,9 @@ void OpenDialogCompletion(int chosen,
ReadDialogPaths(dialog, &paths);
dict.Set("filePaths", paths);
#endif
promise.Resolve(dict);
}
ResolvePromiseInNextTick(promise.As<v8::Local<v8::Value>>(),
dict.GetHandle());
}
void ShowOpenDialog(const DialogSettings& settings,
@@ -410,7 +434,8 @@ void SaveDialogCompletion(int chosen,
}
#endif
}
promise.Resolve(dict);
ResolvePromiseInNextTick(promise.As<v8::Local<v8::Value>>(),
dict.GetHandle());
}
void ShowSaveDialog(const DialogSettings& settings,

View File

@@ -17,6 +17,9 @@
#include "base/mac/scoped_nsobject.h"
#include "base/no_destructor.h"
#include "base/strings/sys_string_conversions.h"
#include "base/task/post_task.h"
#include "content/public/browser/browser_task_traits.h"
#include "content/public/browser/browser_thread.h"
#include "shell/browser/native_window.h"
#include "skia/ext/skia_utils_mac.h"
#include "ui/gfx/image/image_skia.h"
@@ -160,20 +163,26 @@ void ShowMessageBox(const MessageBoxSettings& settings,
__block absl::optional<int> id = std::move(settings.id);
__block int cancel_id = settings.cancel_id;
[alert beginSheetModalForWindow:window
completionHandler:^(NSModalResponse response) {
if (id)
GetDialogsMap().erase(*id);
// When the alert is cancelled programmatically, the
// response would be something like -1000. This currently
// only happens when users call CloseMessageBox API, and we
// should return cancelId as result.
if (response < 0)
response = cancel_id;
std::move(callback_).Run(
response, alert.suppressionButton.state == NSOnState);
[alert release];
}];
auto handler = ^(NSModalResponse response) {
if (id)
GetDialogsMap().erase(*id);
// When the alert is cancelled programmatically, the response would be
// something like -1000. This currently only happens when users call
// CloseMessageBox API, and we should return cancelId as result.
if (response < 0)
response = cancel_id;
bool suppressed = alert.suppressionButton.state == NSOnState;
[alert release];
// The completionHandler runs inside a transaction commit, and we should
// not do any runModal inside it. However since we can not control what
// users will run in the callback, we have to delay running the callback
// until next tick, otherwise crash like this may happen:
// https://github.com/electron/electron/issues/26884
base::PostTask(
FROM_HERE, {content::BrowserThread::UI},
base::BindOnce(std::move(callback_), response, suppressed));
};
[alert beginSheetModalForWindow:window completionHandler:handler];
}
}

View File

@@ -51,17 +51,7 @@ bool Clipboard::Has(const std::string& format_string,
std::string Clipboard::Read(const std::string& format_string) {
ui::Clipboard* clipboard = ui::Clipboard::GetForCurrentThread();
ui::ClipboardFormatType format(
ui::ClipboardFormatType::CustomPlatformType(format_string));
std::string data;
clipboard->ReadData(format, /* data_dst = */ nullptr, &data);
return data;
}
v8::Local<v8::Value> Clipboard::ReadBuffer(const std::string& format_string,
gin_helper::Arguments* args) {
ui::Clipboard* clipboard = ui::Clipboard::GetForCurrentThread();
std::map<std::string, std::string> custom_format_names;
custom_format_names =
clipboard->ExtractCustomPlatformNames(ui::ClipboardBuffer::kCopyPaste,
@@ -73,12 +63,24 @@ v8::Local<v8::Value> Clipboard::ReadBuffer(const std::string& format_string,
/* data_dst = */ nullptr);
}
#endif
CHECK(custom_format_names.find(format_string) != custom_format_names.end());
ui::ClipboardFormatType format(ui::ClipboardFormatType::CustomPlatformType(
custom_format_names[format_string]));
ui::ClipboardFormatType format;
if (custom_format_names.find(format_string) != custom_format_names.end()) {
format =
ui::ClipboardFormatType(ui::ClipboardFormatType::CustomPlatformType(
custom_format_names[format_string]));
} else {
format = ui::ClipboardFormatType(
ui::ClipboardFormatType::CustomPlatformType(format_string));
}
std::string data;
clipboard->ReadData(format, /* data_dst = */ nullptr, &data);
return data;
}
v8::Local<v8::Value> Clipboard::ReadBuffer(const std::string& format_string,
gin_helper::Arguments* args) {
std::string data = Read(format_string);
return node::Buffer::Copy(args->isolate(), data.data(), data.length())
.ToLocalChecked();
}

View File

@@ -106,6 +106,12 @@ class Promise : public PromiseBase {
return resolved.GetHandle();
}
// Convert to another type.
template <typename NT>
Promise<NT> As() {
return Promise<NT>(isolate(), GetInner());
}
// Promise resolution is a microtask
// We use the MicrotasksRunner to trigger the running of pending microtasks
v8::Maybe<bool> Resolve(const RT& value) {

View File

@@ -110,6 +110,11 @@ describe('BrowserWindow module', () => {
await closed;
});
it('should not crash if called after webContents is destroyed', () => {
w.webContents.destroy();
w.webContents.on('destroyed', () => w.close());
});
it('should emit unload handler', async () => {
await w.loadFile(path.join(fixtures, 'api', 'unload.html'));
const closed = emittedOnce(w, 'closed');

View File

@@ -1,7 +1,7 @@
const { expect } = require('chai');
const path = require('path');
const { Buffer } = require('buffer');
const { ifdescribe } = require('./spec-helpers');
const { ifdescribe, ifit } = require('./spec-helpers');
const { clipboard, nativeImage } = require('electron');
@@ -62,14 +62,20 @@ ifdescribe(process.platform !== 'win32' || process.arch !== 'arm64')('clipboard
});
});
ifdescribe(process.platform !== 'linux')('clipboard.read()', () => {
it('does not crash when reading various custom clipboard types', () => {
describe('clipboard.read()', () => {
ifit(process.platform !== 'linux')('does not crash when reading various custom clipboard types', () => {
const type = process.platform === 'darwin' ? 'NSFilenamesPboardType' : 'FileNameW';
expect(() => {
const result = clipboard.read(type);
}).to.not.throw();
});
it('can read data written with writeBuffer', () => {
const testText = 'Testing read';
const buffer = Buffer.from(testText, 'utf8');
clipboard.writeBuffer('public/utf8-plain-text', buffer);
expect(clipboard.read('public/utf8-plain-text')).to.equal(testText);
});
});
describe('clipboard.write()', () => {