Compare commits

...

111 Commits

Author SHA1 Message Date
trop[bot]
1a7c546c3a fix: sync api::Screen wrapper method sigs to upstream (#38632)
refactor: sync api::Screen getter sigs to upstream

ui::Display GetAllDisplays(), GetPrimaryDisplay(), GetDisplayMatching(),
and GetDisplayNearestPoint() methods are all const, so make our wrappers
const too.

ui::Display GetAllDisplays() returns a const reference, so make our
wrapper return a const reference too. This avoids creating a new
std::vector<display::Display> each time it's called.

Co-authored-by: trop[bot] <37223003+trop[bot]@users.noreply.github.com>
Co-authored-by: Charles Kerr <charles@charleskerr.com>
2023-06-07 12:09:25 +02:00
trop[bot]
748c4bfbcb docs: removed outdated Appveyor doc (#38627)
Co-authored-by: trop[bot] <37223003+trop[bot]@users.noreply.github.com>
Co-authored-by: John Kleinschmidt <jkleinsc@electronjs.org>
2023-06-06 23:11:32 -07:00
trop[bot]
9ec8b1d21c refactor: remove unused switches (#38529)
* refactor: remove unused declaration of electron::kSHA1Certificate

usage removed in 13a1d79

Co-authored-by: Charles Kerr <charles@charleskerr.com>

* refactor: remove unused declaration of electron::kSHA1MajorDescription

usage removed in 13a1d79

Co-authored-by: Charles Kerr <charles@charleskerr.com>

* refactor: remove unused declaration of electron::kSHA1MinorDescription

usage removed in 13a1d79

Co-authored-by: Charles Kerr <charles@charleskerr.com>

* refactor: remove unused declaration of electron::kCertificateError

usage removed in 13a1d79

Co-authored-by: Charles Kerr <charles@charleskerr.com>

* refactor: remove unused declaration of electron::kValidCertificate

usage removed in 13a1d79

Co-authored-by: Charles Kerr <charles@charleskerr.com>

* refactor: remove unused declaration of electron::kValidCertificateDescription

usage removed in 13a1d79

Co-authored-by: Charles Kerr <charles@charleskerr.com>

* refactor: remove unused declaration of electron::kSecureProtocol, kSecureProtocolDescription

usage removed in 497f5a1

Co-authored-by: Charles Kerr <charles@charleskerr.com>

* refactor: remove electron::options::kPreloadScripts

removed in bad8d5e0

Co-authored-by: Charles Kerr <charles@charleskerr.com>

* refactor: remove electron::options::kImageAnimationPolicy

removed in 385d0f5

Co-authored-by: Charles Kerr <charles@charleskerr.com>

---------

Co-authored-by: trop[bot] <37223003+trop[bot]@users.noreply.github.com>
Co-authored-by: Charles Kerr <charles@charleskerr.com>
2023-06-06 17:27:12 -04:00
trop[bot]
32138c6405 refactor: remove redundant resizing strategy equality check (#38619)
* refactor: remove redundant resizing strategy equality check

Upstream already checks this.

Co-authored-by: Charles Kerr <charles@charleskerr.com>

* refactor: remove devtools_settings.h from iwc header

Co-authored-by: Charles Kerr <charles@charleskerr.com>

* refactor: remove unused <vectro> from iwc header

Co-authored-by: Charles Kerr <charles@charleskerr.com>

---------

Co-authored-by: trop[bot] <37223003+trop[bot]@users.noreply.github.com>
Co-authored-by: Charles Kerr <charles@charleskerr.com>
2023-06-06 17:25:33 -04:00
trop[bot]
bc458c97dc fix: account for BrowserView bounds in setting autofill popup bounds (#38609)
fix: account for BrowserView bounds in setting autofill popup bounds

Co-authored-by: trop[bot] <37223003+trop[bot]@users.noreply.github.com>
Co-authored-by: Shelley Vohr <shelley.vohr@gmail.com>
2023-06-06 21:50:47 +02:00
electron-roller[bot]
06ac9d989f chore: bump chromium to 114.0.5735.106 (25-x-y) (#38613)
* chore: bump chromium in DEPS to 114.0.5735.106

* 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-06-06 14:15:39 -04:00
trop[bot]
e8ef5f4ae4 refactor: use process_util.h helpers (#38605)
refactor: use process_util.h helpers

Co-authored-by: trop[bot] <37223003+trop[bot]@users.noreply.github.com>
Co-authored-by: Milan Burda <milan.burda@gmail.com>
2023-06-06 14:29:39 +02:00
Charles Kerr
6c136d5582 refactor: in NativeWindowViews, aggregate fields directly (#38595)
Manual backport of #38559

Manual backport needed due to very minor code shear
2023-06-06 17:16:51 +09:00
trop[bot]
7ddb80fbb1 chore: type check JS in docs (#38585) 2023-06-05 11:55:37 +02:00
trop[bot]
3a2306d9e4 docs: clarify which electron modules are exposed in sandboxed renderers (#38580)
Co-authored-by: trop[bot] <37223003+trop[bot]@users.noreply.github.com>
Co-authored-by: Milan Burda <milan.burda@gmail.com>
2023-06-05 11:34:09 +02:00
trop[bot]
38d83cfefc docs: fix SerialPort typing (#38581)
Co-authored-by: trop[bot] <37223003+trop[bot]@users.noreply.github.com>
Co-authored-by: David Sanders <dsanders11@ucsbalum.com>
2023-06-05 11:33:50 +02:00
Charles Kerr
d61f6309a2 chore: remove unused electron::api::View code (#38572)
chore: remove unused electron::api::View code (#38561)

chore: remove unused electron::api::View methods

Remove code that was added in 2c8dc9e but never used.

Manually backport #38561 .
2023-06-05 10:15:25 +02:00
trop[bot]
126897bd6b perf: avoid unnecessary base value clone (#38563) 2023-06-02 17:04:01 -05:00
trop[bot]
d3f0970964 build: fix doc-only early exit on Appveyor (#38551)
Co-authored-by: trop[bot] <37223003+trop[bot]@users.noreply.github.com>
Co-authored-by: Shelley Vohr <shelley.vohr@gmail.com>
2023-06-01 15:09:27 -04:00
trop[bot]
012774a0eb feat: add USB protected classes handler (#38493)
* feat: add USB protected classes handler

Co-authored-by: John Kleinschmidt <jkleinsc@electronjs.org>

* chore: apply review suggestions

Co-authored-by: Charles Kerr <charles@charleskerr.com>

Co-authored-by: John Kleinschmidt <jkleinsc@electronjs.org>

* chore: update docs

Co-authored-by: John Kleinschmidt <jkleinsc@electronjs.org>

* chore: apply review suggestions

Co-authored-by: John Kleinschmidt <jkleinsc@electronjs.org>

* update doc per suggestion

Co-authored-by: John Kleinschmidt <jkleinsc@electronjs.org>

---------

Co-authored-by: trop[bot] <37223003+trop[bot]@users.noreply.github.com>
Co-authored-by: John Kleinschmidt <jkleinsc@electronjs.org>
2023-06-01 10:15:56 -04:00
trop[bot]
a546545a53 feat: add USB protected classes handler (#38493)
* feat: add USB protected classes handler

Co-authored-by: John Kleinschmidt <jkleinsc@electronjs.org>

* chore: apply review suggestions

Co-authored-by: Charles Kerr <charles@charleskerr.com>

Co-authored-by: John Kleinschmidt <jkleinsc@electronjs.org>

* chore: update docs

Co-authored-by: John Kleinschmidt <jkleinsc@electronjs.org>

* chore: apply review suggestions

Co-authored-by: John Kleinschmidt <jkleinsc@electronjs.org>

* update doc per suggestion

Co-authored-by: John Kleinschmidt <jkleinsc@electronjs.org>

---------

Co-authored-by: trop[bot] <37223003+trop[bot]@users.noreply.github.com>
Co-authored-by: John Kleinschmidt <jkleinsc@electronjs.org>
2023-06-01 10:13:07 -04:00
trop[bot]
742bd735e6 chore: make contentTracing.stopRecording() failure clearer (#38519)
chore: make contentTracing.stopRecording() failure clearer

Co-authored-by: trop[bot] <37223003+trop[bot]@users.noreply.github.com>
Co-authored-by: Shelley Vohr <shelley.vohr@gmail.com>
2023-05-31 16:06:59 -04:00
trop[bot]
a54725b6b5 build: combine and elaborate on exposed BoringSSL ciphers (#38521)
build: combine and elaborate on exposed BoringSSL ciphers

Co-authored-by: trop[bot] <37223003+trop[bot]@users.noreply.github.com>
Co-authored-by: Shelley Vohr <shelley.vohr@gmail.com>
2023-05-31 16:06:38 -04:00
electron-roller[bot]
be61126d30 chore: bump chromium to 114.0.5735.91 (25-x-y) (#38516)
chore: bump chromium in DEPS to 114.0.5735.91

Co-authored-by: electron-roller[bot] <84116207+electron-roller[bot]@users.noreply.github.com>
2023-05-31 15:52:02 -04:00
trop[bot]
7fbc867eaf docs: add <webview> new-window event removal to breaking-changes.md (#38523)
Co-authored-by: trop[bot] <37223003+trop[bot]@users.noreply.github.com>
Co-authored-by: Milan Burda <miburda@microsoft.com>
2023-05-31 15:51:42 -04:00
trop[bot]
0c4134fefe ci: clean up docs only change logic (#38495)
Co-authored-by: trop[bot] <37223003+trop[bot]@users.noreply.github.com>
Co-authored-by: Shelley Vohr <shelley.vohr@gmail.com>
2023-05-31 20:58:55 +02:00
trop[bot]
b19a3a65a4 chore: cherry-pick 0e1cc35 from v8 (#38510)
* fix: v8 patch [mksnapshot] Set proper instruction start for builtins

Co-authored-by: mjhenkes <mjhenkes@gmail.com>

* update index

Co-authored-by: mjhenkes <mjhenkes@gmail.com>

* apply ci generated patch

Co-authored-by: mjhenkes <mjhenkes@gmail.com>

* chore: update patches

---------

Co-authored-by: trop[bot] <37223003+trop[bot]@users.noreply.github.com>
Co-authored-by: mjhenkes <mjhenkes@gmail.com>
Co-authored-by: PatchUp <73610968+patchup[bot]@users.noreply.github.com>
2023-05-31 10:28:29 -04:00
trop[bot]
563a0622d9 fix: DCHECK minimizing parent window with non-modal child (#38509)
Co-authored-by: trop[bot] <37223003+trop[bot]@users.noreply.github.com>
Co-authored-by: Shelley Vohr <shelley.vohr@gmail.com>
2023-05-31 14:05:31 +02:00
trop[bot]
6a5bd8dc28 chore: process.mainModule -> require.main (#38477)
chore: process.mainModule -> require.main

Co-authored-by: trop[bot] <37223003+trop[bot]@users.noreply.github.com>
Co-authored-by: Shelley Vohr <shelley.vohr@gmail.com>
2023-05-29 09:42:50 -04:00
trop[bot]
b78c30a6d8 build: make ReactiveObjC/Mantle deps format consistent (#38480)
Co-authored-by: trop[bot] <37223003+trop[bot]@users.noreply.github.com>
Co-authored-by: Shelley Vohr <shelley.vohr@gmail.com>
2023-05-29 09:41:56 -04:00
trop[bot]
9ecd8910de fix: Windows FrameView always appearing inactive (#38473)
Co-authored-by: trop[bot] <37223003+trop[bot]@users.noreply.github.com>
Co-authored-by: Shelley Vohr <shelley.vohr@gmail.com>
2023-05-28 20:41:03 -04:00
electron-roller[bot]
da87a471fe chore: bump chromium to 114.0.5735.45 (25-x-y) (#38447)
* chore: bump chromium in DEPS to 114.0.5735.45

* 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-05-25 12:14:56 -04:00
trop[bot]
6544df1992 build: upgrade @electron/github-app-auth to 2.0.0 (#38446)
Co-authored-by: trop[bot] <37223003+trop[bot]@users.noreply.github.com>
Co-authored-by: David Sanders <dsanders11@ucsbalum.com>
2023-05-25 11:14:32 -04:00
trop[bot]
c9f7ebf821 docs: ensure app.md examples are runnable (#38440)
docs: ensure app.md examples are runnable

Co-authored-by: trop[bot] <37223003+trop[bot]@users.noreply.github.com>
Co-authored-by: Shelley Vohr <shelley.vohr@gmail.com>
2023-05-25 09:58:39 +02:00
trop[bot]
d3a0a255b1 build: fix build with "enable_pdf_viewer=false" (#38436)
* build: fix build with "enable_pdf_viewer=false"

Co-authored-by: Alexey Kuzmin <alex.s.kuzmin@gmail.com>

* fixup! build: fix build with "enable_pdf_viewer=false"

Co-authored-by: Alexey Kuzmin <alex.s.kuzmin@gmail.com>

---------

Co-authored-by: trop[bot] <37223003+trop[bot]@users.noreply.github.com>
Co-authored-by: Alexey Kuzmin <alex.s.kuzmin@gmail.com>
2023-05-24 16:40:21 -04:00
trop[bot]
2d3819e2a8 fix: MediaDevices missing DisplayMediaInformation (#38433)
fix: MediaDevices missing DisplayMediaInformation

Co-authored-by: trop[bot] <37223003+trop[bot]@users.noreply.github.com>
Co-authored-by: Shelley Vohr <shelley.vohr@gmail.com>
2023-05-24 19:15:32 +02:00
trop[bot]
bd384b5301 build: update yarn.lock (#38427)
Co-authored-by: trop[bot] <37223003+trop[bot]@users.noreply.github.com>
Co-authored-by: David Sanders <dsanders11@ucsbalum.com>
2023-05-24 11:15:05 -04:00
David Sanders
1e13475e89 build: disable v8 builtins pgo (#38281)
* build: disable v8 builtins pgo (#38252)

* Revert "build: revert builtins PGO logging file changes (#38235)"

This reverts commit a0e6ca8dab.

---------

Co-authored-by: Keeley Hammond <vertedinde@electronjs.org>
2023-05-23 21:52:24 -04:00
trop[bot]
8ce23c425d docs: fix typing of message box type value (#38352)
* docs: fix typing of dialog type value

Co-authored-by: David Sanders <dsanders11@ucsbalum.com>

* test: add smoke tests

Co-authored-by: David Sanders <dsanders11@ucsbalum.com>

* test: update test

Co-authored-by: David Sanders <dsanders11@ucsbalum.com>

---------

Co-authored-by: trop[bot] <37223003+trop[bot]@users.noreply.github.com>
Co-authored-by: David Sanders <dsanders11@ucsbalum.com>
2023-05-23 13:17:32 +02:00
John Kleinschmidt
c891980848 build: fixup patches (#38400) 2023-05-22 16:30:21 -04:00
trop[bot]
15f4e8ef88 docs: disablewebsecurity on webview-tag can not be changed for an active session (#38398)
disablewebsecurity on webview-tag can not be changed for an active session

Co-authored-by: trop[bot] <37223003+trop[bot]@users.noreply.github.com>
Co-authored-by: Kilian Valkhof <kilian@kilianvalkhof.com>
2023-05-22 15:19:39 -04:00
electron-roller[bot]
b6b4971da0 chore: bump chromium to 114.0.5735.35 (25-x-y) (#38320)
* chore: bump chromium in DEPS to 114.0.5735.26

* chore: update patches

* chore: bump chromium in DEPS to 114.0.5735.35

* chore: update patches

* refactor: add WebViewGuestDelegate::GetGuestDelegateWeakPtr()

Xref: https://chromium-review.googlesource.com/c/chromium/src/+/4515455

This approach copied from GuestViewBase::GetGuestDelegateWeakPtr() approach in that same commit.

(cherry picked from commit 3f3ab39e3a1077f71aa90319d7a81d53cfb3c55e)

---------

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: Charles Kerr <charles@charleskerr.com>
2023-05-22 10:50:48 -04:00
trop[bot]
14918767d8 fix: linker error missing uv__strtok (#38393)
fix: linker error missing uv__strtok

This symbol is referenced inside what seems to be dead code
in `uv__search_path` in third_party/electron_node/deps/uv/src/unix/core.c
When compiling in LTO mode, the reference is removed,
but not during a non-LTO build.

Co-authored-by: trop[bot] <37223003+trop[bot]@users.noreply.github.com>
Co-authored-by: Bruno Pitrus <brunopitrus@hotmail.com>
2023-05-22 16:18:10 +02:00
Keeley Hammond
f7a16f33a8 chore: cherry-pick 8 changes from Release-1-M113 (#38329)
* chore: [25-x-y] cherry-pick 8 changes from Release-1-M113

* 91fce3345668 from v8
* 2c8a019f39d2 from v8
* b8020e1973d7 from v8
* d6272b794cbb from chromium
* 48785f698b1c from chromium
* d0ee0197ddff from angle
* 9b6ca211234b from chromium
* 675562695049 from chromium

* chore: update patches

* chore: check test failure

* build: revert patch causing test failures

---------

Co-authored-by: PatchUp <73610968+patchup[bot]@users.noreply.github.com>
2023-05-22 20:01:49 +09:00
Shelley Vohr
662fa261da feat: support Mica/Acrylic on Windows (#38357) 2023-05-22 11:39:59 +02:00
trop[bot]
8ceb20c75c docs: fix devtools-open-url ts definition (#38353)
docs: fix devtools-open-url ts definition

Co-authored-by: trop[bot] <37223003+trop[bot]@users.noreply.github.com>
Co-authored-by: Shelley Vohr <shelley.vohr@gmail.com>
2023-05-22 09:59:40 +02:00
trop[bot]
e0e824f069 build: use @octokit/request v6.2.4 (#38379)
Co-authored-by: trop[bot] <37223003+trop[bot]@users.noreply.github.com>
Co-authored-by: Shelley Vohr <shelley.vohr@gmail.com>
2023-05-19 12:05:27 -07:00
trop[bot]
ab0a13eed6 feat: emit context-menu event from extensions (#38356)
feat: emit context-menu event from extensions

Co-authored-by: trop[bot] <37223003+trop[bot]@users.noreply.github.com>
Co-authored-by: Shelley Vohr <shelley.vohr@gmail.com>
2023-05-18 16:58:40 -04:00
trop[bot]
7910ace135 feat: surface more webContents text selection commands (#38362)
* feat: surface more text selection commands

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

* refactor: use options argument

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

* docs: correct for 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-05-18 16:55:34 -04:00
trop[bot]
eb8eb6fae2 chore: implement WebContentsDelegate::GetFullscreenState (#38355)
chore: implement WebContentsDelegate::GetFullscreenState

Refs https://chromium-review.googlesource.com/c/chromium/src/+/4255184

Co-authored-by: trop[bot] <37223003+trop[bot]@users.noreply.github.com>
Co-authored-by: Shelley Vohr <shelley.vohr@gmail.com>
2023-05-18 16:54:38 -04:00
trop[bot]
c9bea8b712 feat: add missing 'cursor-changed' type values (#38363)
Co-authored-by: trop[bot] <37223003+trop[bot]@users.noreply.github.com>
Co-authored-by: Shelley Vohr <shelley.vohr@gmail.com>
2023-05-18 12:15:31 -04:00
trop[bot]
71ee04a3e2 build: modify gclient.py with unified patch (#38359)
* build: modify gclient.py with unified patch

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

* ci: ensure depot_tools does not update

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

* ci: move auto-update disable outside if

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-05-17 16:38:02 -04:00
trop[bot]
f7f55d096a fix: getNormalBounds() for transparent windows on Windows (#38348)
fix: getNormalBounds for transparent windows on Windows

Co-authored-by: trop[bot] <37223003+trop[bot]@users.noreply.github.com>
Co-authored-by: Shelley Vohr <shelley.vohr@gmail.com>
2023-05-17 15:57:08 +02:00
trop[bot]
ad6155f08e fix: win.isMaximized() for transparent windows on Windows (#38345)
fix: win.isMaximized() for transparent windows

Co-authored-by: trop[bot] <37223003+trop[bot]@users.noreply.github.com>
Co-authored-by: Shelley Vohr <shelley.vohr@gmail.com>
2023-05-17 13:14:42 +02:00
trop[bot]
37caca046f chore: cherry-pick e6e23ba00379 from chromium (#38333)
* chore: cherry-pick e6e23ba00379 from chromium

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

* make it work

Co-authored-by: Samuel Attard <marshallofsound@electronjs.org>

* build: remove incorrectly cherry-picked patch

* chore: update patches

---------

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: Samuel Attard <marshallofsound@electronjs.org>
Co-authored-by: VerteDinde <vertedinde@electronjs.org>
Co-authored-by: PatchUp <73610968+patchup[bot]@users.noreply.github.com>
2023-05-17 10:20:25 +02:00
trop[bot]
ea6a8eea22 fix: unify BrowserWindow.isVisible() logic cross-platform (#38314)
fix: unify BrowserWindow.isVisible() logic cross-platform

Co-authored-by: trop[bot] <37223003+trop[bot]@users.noreply.github.com>
Co-authored-by: Shelley Vohr <shelley.vohr@gmail.com>
2023-05-16 11:15:41 -04:00
trop[bot]
d314b4e18b build: bump brew cache to v6 (#38318)
Co-authored-by: trop[bot] <37223003+trop[bot]@users.noreply.github.com>
Co-authored-by: Shelley Vohr <shelley.vohr@gmail.com>
2023-05-16 11:08:26 -04:00
trop[bot]
1bc8549ce5 fix: enable BrowserWindow.id access post-destruction (#38311)
fix: enable BrowserWindow id access post-destruction

Co-authored-by: trop[bot] <37223003+trop[bot]@users.noreply.github.com>
Co-authored-by: Shelley Vohr <shelley.vohr@gmail.com>
2023-05-16 12:04:53 +02:00
trop[bot]
8e6c8cc384 fix: isMaximized after minimize/fullscreen on macOS (#38307)
fix: isMaximized after isMinimized on macOS

Co-authored-by: trop[bot] <37223003+trop[bot]@users.noreply.github.com>
Co-authored-by: Shelley Vohr <shelley.vohr@gmail.com>
2023-05-16 11:47:23 +02:00
David Sanders
5c13da7c40 test: prewarm Node headers cache if specifying Electron version (#38297) 2023-05-16 09:38:59 +02:00
David Sanders
45a5827e09 chore: fix lint:js-in-markdown script (#38300)
chore: fix lint:js-in-markdown script (#38260)
2023-05-15 19:26:58 -04:00
trop[bot]
e809a5a043 build: drop python2 from CI (#38304)
* build: drop python2 from CI

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

* python3

Co-authored-by: Samuel Attard <sam@electronjs.org>

* python3 uses linux not linux2

Co-authored-by: Samuel Attard <sam@electronjs.org>

---------

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: Samuel Attard <sam@electronjs.org>
2023-05-15 19:18:31 -04:00
David Sanders
4f2e369bdc chore: migrate to @electron/lint-roller for Markdown linting (#38280)
chore: migrate to @electron/lint-roller for Markdown linting (#38191)
2023-05-14 15:01:04 +02:00
Samuel Attard
eef9787c48 build: fix octokit resolution with patch-package 2023-05-10 03:47:44 -07:00
Samuel Attard
81fe8993ec build: fix octokit resolution 2023-05-10 03:24:45 -07:00
Keeley Hammond
55b5c85f92 build: handle duplex option for Node 18 MacOS upload (#38237)
* build: handle duplex option for Node 18 upload

* build: remove patch-package, pin sha fix
2023-05-09 22:19:44 -07:00
Keeley Hammond
a0e6ca8dab build: revert builtins PGO logging file changes (#38235)
* build: revert builtins PGO error for release builds

* build: warn instead of aborting on bad profile
2023-05-09 14:50:41 -07:00
Shelley Vohr
e30b25269d fix: printing crash when settings invalid (#38230)
Co-authored-by: trop[bot] <37223003+trop[bot]@users.noreply.github.com>
2023-05-09 12:16:03 -04:00
Shelley Vohr
319d77a4ee docs: fix typing of session.setDevicePermissionHandler (#38229)
docs: fix typing of session.setDevicePermissionHandler

Co-authored-by: trop[bot] <37223003+trop[bot]@users.noreply.github.com>
Co-authored-by: David Sanders <dsanders11@ucsbalum.com>
2023-05-09 12:08:17 -04:00
Shelley Vohr
e22767b1e7 docs: update dead link to Apple Human Interface notification guidelines (#38226)
Co-authored-by: trop[bot] <37223003+trop[bot]@users.noreply.github.com>
Co-authored-by: astone123 <adams@cypress.io>
2023-05-09 12:06:32 -04:00
Shelley Vohr
5008e3ecab fix: handle AXManualAccessibility attribute cross-protocol (#38223)
fix: handle `AXManualAccessibility` attribute cross-protocol (#38142)

* fix: handle AXManualAccessibility attribute cross-protocol

* Update shell/browser/mac/electron_application.mm



---------

Co-authored-by: Robo <hop2deep@gmail.com>
2023-05-09 12:04:00 -04:00
Shelley Vohr
d69776bfb0 chore: stop using a RenderWidgetHost observer in FileSelectHelper (#38222)
chore: stop using a `RenderWidgetHost` observer in `FileSelectHelper` (#38168)

chore: stop using a RenderWidgetHost observer in FileSelectHelper
2023-05-09 12:03:30 -04:00
Shelley Vohr
b56e4287d3 refactor: remove IPC from mouse_util (#38220)
refactor: remove IPC from mouse_util (#38183)
2023-05-09 12:01:52 -04:00
electron-roller[bot]
1254a684dd chore: bump chromium to 114.0.5735.16 (25-x-y) (#38118)
* chore: bump chromium in DEPS to 114.0.5733.2

* chore: bump chromium in DEPS to 114.0.5735.6

* chore: bump chromium in DEPS to 114.0.5735.9

* chore: update patches

* 4450570: Clean up content shell
https://chromium-review.googlesource.com/c/chromium/src/+/4450570

(cherry picked from commit d89b76e6857a332dc779bdb0a04913f3e7541524)

* 4262527: geolocation: Introduce mojom::GeopositionResult
https://chromium-review.googlesource.com/c/chromium/src/+/4262527

(cherry picked from commit 9b350a60c234653109520b407d16d0ad71ea3ed7)

* 4450327: Android/Nav: Stop taking content timeout timer from old host.
https://chromium-review.googlesource.com/c/chromium/src/+/4450327

Also, see:
4451366: Reland "Prerender: Fix prerender new content timeout start timing"
https://chromium-review.googlesource.com/c/chromium/src/+/4451366

(cherry picked from commit 7039603714cbfac7ebb20cb1ab0135c8249a89fd)

* chore: bump CircleCI xcode version
this will hopefully get us the necessary macOS sdk 13.3 on CI.

(cherry picked from commit b3283351cdd0a079d5fe65fe46b642c7def74f38)

* test: fix geolocation test

(cherry picked from commit bddbc573ada91511d07dbc6b4622ac95358f0993)

* fixup patch

* chore: bump chromium in DEPS to 114.0.5735.16

* chore: update patches

* 4336172: Include client-drawn window decorations in aspect ratio. |
Ref: https://chromium-review.googlesource.com/c/chromium/src/+/4336172

* build: bump appveyor image to fix windows cache

* spec: fix race condition in alwaysOnTop test

* build: use xcode 14.2 not 14.3

* build: use macOS 12 to run tests

The new macOS 13 VMs appear to have different screen / display behavior

---------

Co-authored-by: electron-roller[bot] <84116207+electron-roller[bot]@users.noreply.github.com>
Co-authored-by: John Kleinschmidt <jkleinsc@electronjs.org>
Co-authored-by: clavin <clavin@electronjs.org>
Co-authored-by: PatchUp <73610968+patchup[bot]@users.noreply.github.com>
Co-authored-by: VerteDinde <keeleymhammond@gmail.com>
Co-authored-by: Keeley Hammond <vertedinde@electronjs.org>
Co-authored-by: Samuel Attard <samuel.r.attard@gmail.com>
2023-05-09 11:03:33 -04:00
trop[bot]
99a81e4ef0 chore: fix TrustedTypes policy in chrome://accessibility (#38211)
chore: fix TrustedTypes policy in chrome://accessibility

Co-authored-by: trop[bot] <37223003+trop[bot]@users.noreply.github.com>
Co-authored-by: Shelley Vohr <shelley.vohr@gmail.com>
2023-05-08 15:57:44 +02:00
Shelley Vohr
36d5706ea9 feat: net.resolveHost (#38152)
feat: net.resolveHost (#37853)

Co-authored-by: Fedor Indutny <238531+indutny@users.noreply.github.com>
2023-05-08 09:46:11 +02:00
Alexey Kuzmin
2ae9588e1c test: use await to call "closeWindow" (#38174) 2023-05-04 14:26:50 +02:00
David Sanders
320415edf9 docs: moves icpMain.handle call in tutorial part 3 (#38175)
docs: moves icpMain.handle call in tutorial part 3 (#38138)

Co-authored-by: Russell Carpenella <russellcarpenella@gmail.com>
2023-05-04 12:25:50 +02:00
Shelley Vohr
dd59115ac6 fix: AXManualAccessibility showing failure (#38146) 2023-05-04 10:38:54 +02:00
David Sanders
80a378a9de fix: falsy transparent shouldn't affect webContents background (#38157)
fix: falsy transparent shouldn't affect webContents background (#36914)
2023-05-03 15:42:27 +02:00
Shelley Vohr
8d2530437e chore: add ocr scaffolding to pdf viewer (#38148)
* chore: add OCR scaffolding to PDF Viewer

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

* chore: remove unnecessary gn file

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

---------

Co-authored-by: trop[bot] <37223003+trop[bot]@users.noreply.github.com>
2023-05-03 09:56:36 +02:00
Shelley Vohr
dde3a0f1ba chore: correct extra qualification causing build error with gcc (#38143)
* chore: correct extra qualification causing build error with GCC

Co-authored-by: Bruno Pitrus <brunopitrus@hotmail.com>

* fixup for lint

Co-authored-by: John Kleinschmidt <kleinschmidtorama@gmail.com>

* chore: fix lint

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

---------

Co-authored-by: trop[bot] <37223003+trop[bot]@users.noreply.github.com>
Co-authored-by: Bruno Pitrus <brunopitrus@hotmail.com>
Co-authored-by: John Kleinschmidt <kleinschmidtorama@gmail.com>
2023-05-02 11:20:29 -04:00
trop[bot]
ce079c02bc fix: crash on missing RenderWidgetHostView (#38115)
chore: fix crash on missing RenderWidgetHostView

Co-authored-by: trop[bot] <37223003+trop[bot]@users.noreply.github.com>
Co-authored-by: Shelley Vohr <shelley.vohr@gmail.com>
2023-04-25 15:29:25 -07:00
trop[bot]
f23df11352 docs: fix start highlight tutorial-2-first-app.md (#38114)
doc: fix start highlight tutorial-2-first-app.md

Co-authored-by: trop[bot] <37223003+trop[bot]@users.noreply.github.com>
Co-authored-by: Francis Chartrand <chartrandf@users.noreply.github.com>
2023-04-25 13:16:32 +02:00
trop[bot]
abb86a7ea1 fix: webContents return type incorrect (#38107)
* fix: webContents type incorrect

Co-authored-by: Black-Hole1 <bh@bugs.cc>

* fix: ci failed

Co-authored-by: Black-Hole1 <bh@bugs.cc>

* fix: ci failed 2

Co-authored-by: Black-Hole1 <bh@bugs.cc>

---------

Co-authored-by: trop[bot] <37223003+trop[bot]@users.noreply.github.com>
Co-authored-by: Black-Hole1 <bh@bugs.cc>
2023-04-25 12:08:01 +02:00
trop[bot]
8f96b2192a chore: always lint JS in docs/fiddles (#38109)
Co-authored-by: trop[bot] <37223003+trop[bot]@users.noreply.github.com>
Co-authored-by: David Sanders <dsanders11@ucsbalum.com>
2023-04-24 19:44:46 +02:00
trop[bot]
977a7eb1d0 docs: fix 'usb-device-added', 'usb-device-removed', 'usb-device-revoked' typings (#38095)
* Fix 'usb-device-added', 'usb-device-removed', 'usb-device-revoked' typings

Co-authored-by: Quang Lam <quang.lam@webcatalog.io>

* Add webContents

Co-authored-by: Quang Lam <quang.lam@webcatalog.io>

---------

Co-authored-by: trop[bot] <37223003+trop[bot]@users.noreply.github.com>
Co-authored-by: Quang Lam <quang.lam@webcatalog.io>
2023-04-24 09:43:32 -04:00
trop[bot]
504588c861 fix: crash in utilityProcess when generating code from strings (#38039)
Co-authored-by: trop[bot] <37223003+trop[bot]@users.noreply.github.com>
Co-authored-by: deepak1556 <hop2deep@gmail.com>
2023-04-23 22:17:03 +02:00
trop[bot]
5bc09dda1a fix: defaults broken in shell.openExternal() options (#38071)
Co-authored-by: trop[bot] <37223003+trop[bot]@users.noreply.github.com>
Co-authored-by: Milan Burda <miburda@microsoft.com>
2023-04-21 12:43:25 -07:00
trop[bot]
6b72837203 chore: bump chromium to 114.0.5719.0 (25-x-y) (#38034)
* chore: bump chromium in DEPS to 114.0.5719.0

Co-authored-by: electron-roller[bot] <84116207+electron-roller[bot]@users.noreply.github.com>

* chore: update patches

Co-authored-by: PatchUp <73610968+patchup[bot]@users.noreply.github.com>

* revert eb07a797cc

Co-authored-by: Jeremy Rose <jeremya@chromium.org>

---------

Co-authored-by: trop[bot] <37223003+trop[bot]@users.noreply.github.com>
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: Jeremy Rose <jeremya@chromium.org>
2023-04-21 13:14:34 -04:00
trop[bot]
9f2bef9a65 feat: add thermal states to powerMonitor (#38028)
* feat: add thermal states to powerMonitor

Co-authored-by: Jeremy Rose <jeremya@chromium.org>

* update docs

Co-authored-by: Jeremy Rose <jeremya@chromium.org>

---------

Co-authored-by: trop[bot] <37223003+trop[bot]@users.noreply.github.com>
Co-authored-by: Jeremy Rose <jeremya@chromium.org>
2023-04-20 12:27:08 +02:00
trop[bot]
d0273d83ef feat: add did-resign-active event on app (#38018)
feat: add did-resign-active event on app

Co-authored-by: trop[bot] <37223003+trop[bot]@users.noreply.github.com>
Co-authored-by: Shelley Vohr <shelley.vohr@gmail.com>
2023-04-20 12:25:17 +02:00
trop[bot]
248dc89217 build: fix building with no PDF support (#38006)
Co-authored-by: trop[bot] <37223003+trop[bot]@users.noreply.github.com>
Co-authored-by: Alexey Kuzmin <alex.s.kuzmin@gmail.com>
2023-04-17 21:58:37 -04:00
trop[bot]
a75a867997 chore: bump chromium to 114.0.5715.0 (25-x-y) (#38010)
* chore: bump chromium in DEPS to 114.0.5712.0

Co-authored-by: electron-roller[bot] <84116207+electron-roller[bot]@users.noreply.github.com>

* chore: update patches

Co-authored-by: PatchUp <73610968+patchup[bot]@users.noreply.github.com>

* 4401084: Remove extensions::InfoMap which is no longer needed. | https://chromium-review.googlesource.com/c/chromium/src/+/4401084

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

* 4415646: Add more details to print settings error log | https://chromium-review.googlesource.com/c/chromium/src/+/4415646

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

* chore: bump chromium in DEPS to 114.0.5714.0

Co-authored-by: electron-roller[bot] <84116207+electron-roller[bot]@users.noreply.github.com>

* chore: update patches

Co-authored-by: PatchUp <73610968+patchup[bot]@users.noreply.github.com>

* chore: update libcxx filenames

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

* chore: bump chromium in DEPS to 114.0.5715.0

Co-authored-by: electron-roller[bot] <84116207+electron-roller[bot]@users.noreply.github.com>

* chore: update patches

Co-authored-by: PatchUp <73610968+patchup[bot]@users.noreply.github.com>

* fix extensions test

Co-authored-by: Jeremy Rose <jeremya@chromium.org>

---------

Co-authored-by: trop[bot] <37223003+trop[bot]@users.noreply.github.com>
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: VerteDinde <vertedinde@electronjs.org>
Co-authored-by: Jeremy Rose <jeremya@chromium.org>
2023-04-17 21:06:38 -04:00
trop[bot]
0d82286a23 docs: update github.com links (#37990)
Co-authored-by: trop[bot] <37223003+trop[bot]@users.noreply.github.com>
Co-authored-by: David Sanders <dsanders11@ucsbalum.com>
2023-04-17 11:16:54 -04:00
trop[bot]
4553ec2a2a docs: add note to win.setFullScreen(flag) (#37997)
docs: add note to win.setFullScreen(flag)

Co-authored-by: trop[bot] <37223003+trop[bot]@users.noreply.github.com>
Co-authored-by: Shelley Vohr <shelley.vohr@gmail.com>
2023-04-17 11:13:48 -04:00
trop[bot]
62f64f9f03 chore: replace uses of ComPtr::GetAddressOf() with ComPtr::operator& (#37993)
chore: replace uses of ComPtr::GetAddressOf() with ComPtr::operator&

Co-authored-by: trop[bot] <37223003+trop[bot]@users.noreply.github.com>
Co-authored-by: Shelley Vohr <shelley.vohr@gmail.com>
2023-04-17 11:44:55 +02:00
trop[bot]
f35adf303b chore: drop patch for fixed Linux menus issue in Views (#37988)
Co-authored-by: trop[bot] <37223003+trop[bot]@users.noreply.github.com>
Co-authored-by: David Sanders <dsanders11@ucsbalum.com>
2023-04-16 17:06:40 -07:00
trop[bot]
f236478b2b fix: defaultFontFamily in webPreferences (#37967)
* fix: defaultFontFamily in webPreferences

Co-authored-by: David Sanders <dsanders11@ucsbalum.com>

* chore: check if default_font_family_ is empty

Co-authored-by: David Sanders <dsanders11@ucsbalum.com>

---------

Co-authored-by: trop[bot] <37223003+trop[bot]@users.noreply.github.com>
Co-authored-by: David Sanders <dsanders11@ucsbalum.com>
2023-04-14 09:17:39 -07:00
trop[bot]
b69de7c412 fix: swipe event emission on macOS (#37966)
Co-authored-by: trop[bot] <37223003+trop[bot]@users.noreply.github.com>
Co-authored-by: Shelley Vohr <shelley.vohr@gmail.com>
2023-04-13 13:06:40 -04:00
trop[bot]
8c3bbded4f docs: Fix the syntax error for code fragment (#37961)
By using `app.on('ready').then(xxx)`, application will throw a TypeError

Co-authored-by: trop[bot] <37223003+trop[bot]@users.noreply.github.com>
Co-authored-by: Zenkie Bear <62818957+ZenkieBear@users.noreply.github.com>
2023-04-13 13:28:35 +02:00
trop[bot]
d9019fc54b chore: bump chromium to 114.0.5710.0 (25-x-y) (#37957)
* chore: bump chromium in DEPS to 114.0.5710.0

Co-authored-by: electron-roller[bot] <84116207+electron-roller[bot]@users.noreply.github.com>

* chore: update patches

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

* 4411421: [json-schema-compiler] Support separating numbers in enum entries | https://chromium-review.googlesource.com/c/chromium/src/+/4411421

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

* 4400251: Remove MayBlock and TaskShutdownBehavior from BrowserTaskTraits | https://chromium-review.googlesource.com/c/chromium/src/+/4400251

Co-authored-by: VerteDinde <keeleymhammond@gmail.com>

---------

Co-authored-by: trop[bot] <37223003+trop[bot]@users.noreply.github.com>
Co-authored-by: electron-roller[bot] <84116207+electron-roller[bot]@users.noreply.github.com>
Co-authored-by: Keeley Hammond <vertedinde@electronjs.org>
Co-authored-by: VerteDinde <keeleymhammond@gmail.com>
2023-04-12 20:51:49 -07:00
trop[bot]
7c624c17fa docs: update 22-x-y EOL dates (#37956)
To account for https://www.electronjs.org/blog/electron-22-0#windows-7881-support-update

Not sure if it is worth adding as a historical change though

Co-authored-by: trop[bot] <37223003+trop[bot]@users.noreply.github.com>
Co-authored-by: Michaela Laurencin <35157522+mlaurencin@users.noreply.github.com>
2023-04-12 20:22:20 -07:00
trop[bot]
3e336d2923 chore: bump chromium to 114.0.5708.0 (25-x-y) (#37953)
chore: bump chromium to 114.0.5708.0 25-x-y

* chore: bump chromium in DEPS to 114.0.5696.0

* chore: update patches

* chore: revert clang revert

(cherry picked from commit 4c3ffa8001b5fdbfc99374bf77895d8d8e35ee31)

* test: remove unneeded test for title on ses.setCertificateVerifyProc

This test is unnecessary because all that really needs to be verified is that the request was rejected.

* chore: Revert "Reland "[BRP] Enable clang plugin check for Linux""

* chore: bump chromium in DEPS to 114.0.5697.0

* chore: bump chromium in DEPS to 114.0.5698.0

* chore: update patches

* chore: bump chromium in DEPS to 114.0.5700.0

* chore: update patches

* chore: bump chromium in DEPS to 114.0.5702.0

* chore: bump chromium in DEPS to 114.0.5704.0

* chore: update patches

* chore: bump chromium in DEPS to 114.0.5705.0

* 4368281: Add bottom-up CertVerifier change observer flow. |
https://chromium-review.googlesource.com/c/chromium/src/+/4368281

* 4402277: Enable check_raw_ptr_fields for Linux |
https://chromium-review.googlesource.com/c/chromium/src/+/4402277

* 4389621: [ChromeAppsDeprecation] Remove deprecated chrome apps from AppService |
https://chromium-review.googlesource.com/c/chromium/src/+/4389621

* 4402191: Allow default initializing BrowserTaskTraits |
https://chromium-review.googlesource.com/c/chromium/src/+/4402191

* chore: bump chromium in DEPS to 114.0.5708.0

* chore: remove incorrectly re-added clang patch

* chore: update patches (clean sync)

* ci: use newer clang for 32-bit Linux ARM

Fixes crash on compiling skia/skia/SkPatchUtils.cpp

* build: generate new libcxx filenames

* 4409898: Update paper printable area in UpdatePrintSettings |
https://chromium-review.googlesource.com/c/chromium/src/+/4409898

* chore: update sysroots.json
Sysroot CL: https://chromium-review.googlesource.com/c/chromium/src/+/4383374
Chromium CL: 4246577: media/gpu: Add CQP AV1 VA-API video encoder | https://chromium-review.googlesource.com/c/chromium/src/+/4246577

* 4336198: [task] Move source location and use it in v8 platform | https://chromium-review.googlesource.com/c/v8/v8/+/4336198

---------

Co-authored-by: trop[bot] <37223003+trop[bot]@users.noreply.github.com>
Co-authored-by: electron-roller[bot] <84116207+electron-roller[bot]@users.noreply.github.com>
2023-04-12 18:11:07 -07:00
trop[bot]
95b727ccdb fix: recommended node-gyp version in node.h error (#37926)
fix: recommended node-gyp version in node.h error

In
https://github.com/electron/electron/blob/main/docs/tutorial/using-native-node-modules.md#using-npm,
we recommend setting the `npm_config_disturl` variable but doing that
does not work on node-gyp v8.4.0 because after
https://github.com/nodejs/node-gyp/pull/2497
landed, the dist URL was read only from `gyp.opts['dist-url']`. The fix
for reading the value from `npm_config_disturl` by parsing
`gyp.opts.disturl` was landed in
https://github.com/nodejs/node-gyp/pull/2547 and that change was
released in node-gyp v9.0.0, so this change updates the error macro to
recommend node-gyp v9.0.0 as the minimum required version.

Co-authored-by: trop[bot] <37223003+trop[bot]@users.noreply.github.com>
Co-authored-by: Darshan Sen <raisinten@gmail.com>
2023-04-11 22:13:52 +02:00
trop[bot]
382b19f816 fix: exceptions during function/promise result conversions live in calling world (#37922)
Co-authored-by: trop[bot] <37223003+trop[bot]@users.noreply.github.com>
Co-authored-by: Samuel Attard <marshallofsound@electronjs.org>
2023-04-11 09:23:15 -07:00
trop[bot]
a1b3b506d7 fix: menus on Linux after window modification (#37905)
* fix: menus on Linux after window modification

Co-authored-by: David Sanders <dsanders11@ucsbalum.com>

* test: don't run on CI

Co-authored-by: David Sanders <dsanders11@ucsbalum.com>

---------

Co-authored-by: trop[bot] <37223003+trop[bot]@users.noreply.github.com>
Co-authored-by: David Sanders <dsanders11@ucsbalum.com>
2023-04-11 15:44:56 +02:00
trop[bot]
9b25d6b91b chore: use nested namespaces (#37917)
Co-authored-by: trop[bot] <37223003+trop[bot]@users.noreply.github.com>
Co-authored-by: David Sanders <dsanders11@ucsbalum.com>
2023-04-11 12:52:59 +02:00
trop[bot]
b113c5d583 fix: broken buttons in PDF viewer (#37920)
Co-authored-by: trop[bot] <37223003+trop[bot]@users.noreply.github.com>
Co-authored-by: Shelley Vohr <shelley.vohr@gmail.com>
2023-04-11 12:39:12 +02:00
trop[bot]
a36e44c973 chore: change some for loops to range-based (#37912)
Co-authored-by: trop[bot] <37223003+trop[bot]@users.noreply.github.com>
Co-authored-by: David Sanders <dsanders11@ucsbalum.com>
2023-04-11 12:25:55 +02:00
trop[bot]
8ae741102d test: support 'latest'/'latest@X' Electron version strings (#37866)
Co-authored-by: trop[bot] <37223003+trop[bot]@users.noreply.github.com>
Co-authored-by: David Sanders <dsanders11@ucsbalum.com>
2023-04-11 11:57:55 +02:00
trop[bot]
666e8f9647 chore: use emplace when possible (#37909)
Co-authored-by: trop[bot] <37223003+trop[bot]@users.noreply.github.com>
Co-authored-by: David Sanders <dsanders11@ucsbalum.com>
2023-04-11 11:57:26 +02:00
trop[bot]
fdceacce44 fix: showAboutPanel also on linux (#37873)
showAboutPanel also on linux

Co-authored-by: trop[bot] <37223003+trop[bot]@users.noreply.github.com>
Co-authored-by: Mikael Finstad <finstaden@gmail.com>
2023-04-11 15:20:05 +09:00
trop[bot]
0ad8ffa3d2 fix: exceptions in nested conversions live in the target world (#37896)
Co-authored-by: trop[bot] <37223003+trop[bot]@users.noreply.github.com>
Co-authored-by: Samuel Attard <marshallofsound@electronjs.org>
2023-04-10 18:00:55 -07:00
trop[bot]
031283003c docs: update E24/E25 breaking changes (#37882) 2023-04-07 12:51:31 -07:00
trop[bot]
63fdcba0c8 docs: update 21-x-y EOL dates (#37871)
* docs: update 21-x-y EOL dates

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

* doc: update node versions

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

---------

Co-authored-by: trop[bot] <37223003+trop[bot]@users.noreply.github.com>
Co-authored-by: Keeley Hammond <vertedinde@electronjs.org>
2023-04-06 13:01:56 -07:00
335 changed files with 5530 additions and 3424 deletions

View File

@@ -52,9 +52,14 @@ executors:
size: size:
description: "macOS executor size" description: "macOS executor size"
type: enum type: enum
enum: ["macos.x86.medium.gen2", "large"] enum: ["macos.x86.medium.gen2"]
version:
description: "xcode version"
type: enum
enum: ["14.3.0", "14.0.0"]
default: 14.3.0
macos: macos:
xcode: 14.0.0 xcode: << parameters.version >>
resource_class: << parameters.size >> resource_class: << parameters.size >>
# Electron Runners # Electron Runners
@@ -245,14 +250,27 @@ step-depot-tools-get: &step-depot-tools-get
sed -i '/ninjalog_uploader_wrapper.py/d' ./depot_tools/autoninja sed -i '/ninjalog_uploader_wrapper.py/d' ./depot_tools/autoninja
# Remove swift-format dep from cipd on macOS until we send a patch upstream. # Remove swift-format dep from cipd on macOS until we send a patch upstream.
cd depot_tools cd depot_tools
patch gclient.py -R \<<'EOF' cat > gclient.diff \<< 'EOF'
676,677c676 diff --git a/gclient.py b/gclient.py
< packages = dep_value.get('packages', []) index 3a9c5c6..f222043 100755
< for package in (x for x in packages if "infra/3pp/tools/swift-format" not in x.get('package')): --- a/gclient.py
--- +++ b/gclient.py
> for package in dep_value.get('packages', []): @@ -712,7 +712,8 @@ class Dependency(gclient_utils.WorkItem, DependencySettings):
if dep_type == 'cipd':
cipd_root = self.GetCipdRoot()
- for package in dep_value.get('packages', []):
+ packages = dep_value.get('packages', [])
+ for package in (x for x in packages if "infra/3pp/tools/swift-format" not in x.get('package')):
deps_to_add.append(
CipdDependency(
parent=self,
EOF EOF
git apply --3way gclient.diff
fi fi
# Ensure depot_tools does not update.
test -d depot_tools && cd depot_tools
touch .disable_auto_update
step-depot-tools-add-to-path: &step-depot-tools-add-to-path step-depot-tools-add-to-path: &step-depot-tools-add-to-path
run: run:
@@ -274,7 +292,7 @@ step-gclient-sync: &step-gclient-sync
ELECTRON_USE_THREE_WAY_MERGE_FOR_PATCHES=1 gclient sync --with_branch_heads --with_tags ELECTRON_USE_THREE_WAY_MERGE_FOR_PATCHES=1 gclient sync --with_branch_heads --with_tags
if [ "$IS_RELEASE" != "true" ]; then if [ "$IS_RELEASE" != "true" ]; then
# Re-export all the patches to check if there were changes. # Re-export all the patches to check if there were changes.
python src/electron/script/export_all_patches.py src/electron/patches/config.json python3 src/electron/script/export_all_patches.py src/electron/patches/config.json
cd src/electron cd src/electron
git update-index --refresh || true git update-index --refresh || true
if ! git diff-index --quiet HEAD --; then if ! git diff-index --quiet HEAD --; then
@@ -357,14 +375,14 @@ step-restore-brew-cache: &step-restore-brew-cache
- /usr/local/Cellar/gnu-tar - /usr/local/Cellar/gnu-tar
- /usr/local/bin/gtar - /usr/local/bin/gtar
keys: keys:
- v5-brew-cache-{{ arch }} - v6-brew-cache-{{ arch }}
step-save-brew-cache: &step-save-brew-cache step-save-brew-cache: &step-save-brew-cache
save_cache: save_cache:
paths: paths:
- /usr/local/Cellar/gnu-tar - /usr/local/Cellar/gnu-tar
- /usr/local/bin/gtar - /usr/local/bin/gtar
key: v5-brew-cache-{{ arch }} key: v6-brew-cache-{{ arch }}
name: Persisting brew cache name: Persisting brew cache
step-get-more-space-on-mac: &step-get-more-space-on-mac step-get-more-space-on-mac: &step-get-more-space-on-mac
@@ -675,9 +693,9 @@ step-verify-mksnapshot: &step-verify-mksnapshot
if [ "$IS_ASAN" != "1" ]; then if [ "$IS_ASAN" != "1" ]; then
cd src cd src
if [ "$TARGET_ARCH" == "arm" ] || [ "$TARGET_ARCH" == "arm64" ]; then if [ "$TARGET_ARCH" == "arm" ] || [ "$TARGET_ARCH" == "arm64" ]; then
python electron/script/verify-mksnapshot.py --source-root "$PWD" --build-dir out/Default --snapshot-files-dir $PWD/cross-arch-snapshots python3 electron/script/verify-mksnapshot.py --source-root "$PWD" --build-dir out/Default --snapshot-files-dir $PWD/cross-arch-snapshots
else else
python electron/script/verify-mksnapshot.py --source-root "$PWD" --build-dir out/Default python3 electron/script/verify-mksnapshot.py --source-root "$PWD" --build-dir out/Default
fi fi
fi fi
@@ -687,7 +705,7 @@ step-verify-chromedriver: &step-verify-chromedriver
command: | command: |
if [ "$IS_ASAN" != "1" ]; then if [ "$IS_ASAN" != "1" ]; then
cd src cd src
python electron/script/verify-chromedriver.py --source-root "$PWD" --build-dir out/Default python3 electron/script/verify-chromedriver.py --source-root "$PWD" --build-dir out/Default
fi fi
step-setup-linux-for-headless-testing: &step-setup-linux-for-headless-testing step-setup-linux-for-headless-testing: &step-setup-linux-for-headless-testing
@@ -813,7 +831,7 @@ step-maybe-cross-arch-snapshot: &step-maybe-cross-arch-snapshot
elif [ "`uname`" == "Darwin" ]; then elif [ "`uname`" == "Darwin" ]; then
cp "out/Default/$MKSNAPSHOT_PATH/libffmpeg.dylib" out/Default cp "out/Default/$MKSNAPSHOT_PATH/libffmpeg.dylib" out/Default
fi fi
python electron/script/verify-mksnapshot.py --source-root "$PWD" --build-dir out/Default --create-snapshot-only python3 electron/script/verify-mksnapshot.py --source-root "$PWD" --build-dir out/Default --create-snapshot-only
mkdir cross-arch-snapshots mkdir cross-arch-snapshots
cp out/Default-mksnapshot-test/*.bin cross-arch-snapshots cp out/Default-mksnapshot-test/*.bin cross-arch-snapshots
# Clean up so that ninja does not get confused # Clean up so that ninja does not get confused
@@ -970,7 +988,6 @@ step-ts-compile: &step-ts-compile
# List of all steps. # List of all steps.
steps-electron-gn-check: &steps-electron-gn-check steps-electron-gn-check: &steps-electron-gn-check
steps: steps:
- install-python2-mac
- *step-setup-goma-for-build - *step-setup-goma-for-build
- checkout-from-cache - checkout-from-cache
- *step-setup-env-for-build - *step-setup-env-for-build
@@ -989,31 +1006,6 @@ steps-electron-ts-compile-for-doc-change: &steps-electron-ts-compile-for-doc-cha
# Command Aliases # Command Aliases
commands: commands:
install-python2-mac:
steps:
- restore_cache:
keys:
- v2.7.18-python-cache-{{ arch }}
name: Restore python cache
- run:
name: Install python2 on macos
command: |
if [ "`uname`" == "Darwin" ] && [ "$IS_ELECTRON_RUNNER" != "1" ]; then
if [ ! -f "python-downloads/python-2.7.18-macosx10.9.pkg" ]; then
mkdir python-downloads
echo 'Downloading Python 2.7.18'
curl -O https://dev-cdn.electronjs.org/python/python-2.7.18-macosx10.9.pkg
mv python-2.7.18-macosx10.9.pkg python-downloads
else
echo 'Using Python install from cache'
fi
sudo installer -pkg python-downloads/python-2.7.18-macosx10.9.pkg -target /
fi
- save_cache:
paths:
- python-downloads
key: v2.7.18-python-cache-{{ arch }}
name: Persisting python cache
maybe-restore-portaled-src-cache: maybe-restore-portaled-src-cache:
parameters: parameters:
halt-if-successful: halt-if-successful:
@@ -1310,7 +1302,6 @@ commands:
- run: rm -rf src/electron - run: rm -rf src/electron
- *step-restore-brew-cache - *step-restore-brew-cache
- *step-install-gnutar-on-mac - *step-install-gnutar-on-mac
- install-python2-mac
- *step-save-brew-cache - *step-save-brew-cache
- when: - when:
condition: << parameters.build >> condition: << parameters.build >>
@@ -1471,7 +1462,6 @@ commands:
- *step-setup-linux-for-headless-testing - *step-setup-linux-for-headless-testing
- *step-restore-brew-cache - *step-restore-brew-cache
- *step-fix-known-hosts-linux - *step-fix-known-hosts-linux
- install-python2-mac
- *step-install-signing-cert-on-mac - *step-install-signing-cert-on-mac
- run: - run:
@@ -1581,7 +1571,6 @@ commands:
- *step-depot-tools-get - *step-depot-tools-get
- *step-depot-tools-add-to-path - *step-depot-tools-add-to-path
- *step-restore-brew-cache - *step-restore-brew-cache
- install-python2-mac
- *step-get-more-space-on-mac - *step-get-more-space-on-mac
- when: - when:
condition: << parameters.checkout >> condition: << parameters.checkout >>
@@ -2142,6 +2131,7 @@ jobs:
executor: executor:
name: macos name: macos
size: macos.x86.medium.gen2 size: macos.x86.medium.gen2
version: 14.0.0
environment: environment:
<<: *env-mac-large <<: *env-mac-large
<<: *env-stack-dumping <<: *env-stack-dumping
@@ -2165,6 +2155,7 @@ jobs:
executor: executor:
name: macos name: macos
size: macos.x86.medium.gen2 size: macos.x86.medium.gen2
version: 14.0.0
environment: environment:
<<: *env-mac-large <<: *env-mac-large
<<: *env-stack-dumping <<: *env-stack-dumping

View File

@@ -1,27 +1,3 @@
{ {
"commands-show-output": false, "extends": "@electron/lint-roller/configs/markdownlint.json"
"first-line-h1": false,
"header-increment": false,
"line-length": {
"code_blocks": false,
"tables": false,
"stern": true,
"line_length": -1
},
"no-bare-urls": false,
"no-blanks-blockquote": false,
"no-duplicate-header": {
"allow_different_nesting": true
},
"no-emphasis-as-header": false,
"no-hard-tabs": {
"code_blocks": false
},
"no-space-in-emphasis": false,
"no-trailing-punctuation": false,
"no-trailing-spaces": {
"br_spaces": 0
},
"single-h1": false,
"no-inline-html": false
} }

View File

@@ -772,6 +772,8 @@ source_set("electron_lib") {
sources += [ sources += [
"shell/browser/electron_pdf_web_contents_helper_client.cc", "shell/browser/electron_pdf_web_contents_helper_client.cc",
"shell/browser/electron_pdf_web_contents_helper_client.h", "shell/browser/electron_pdf_web_contents_helper_client.h",
"shell/browser/extensions/api/pdf_viewer_private/pdf_viewer_private_api.cc",
"shell/browser/extensions/api/pdf_viewer_private/pdf_viewer_private_api.h",
] ]
} }

12
DEPS
View File

@@ -2,13 +2,17 @@ gclient_gn_args_from = 'src'
vars = { vars = {
'chromium_version': 'chromium_version':
'114.0.5694.0', '114.0.5735.106',
'node_version': 'node_version':
'v18.15.0', 'v18.15.0',
'nan_version': 'nan_version':
'16fa32231e2ccd89d2804b3f765319128b20c4ac', '16fa32231e2ccd89d2804b3f765319128b20c4ac',
'squirrel.mac_version': 'squirrel.mac_version':
'0e5d146ba13101a1302d59ea6e6e0b3cace4ae38', '0e5d146ba13101a1302d59ea6e6e0b3cace4ae38',
'reactiveobjc_version':
'74ab5baccc6f7202c8ac69a8d1e152c29dc1ea76',
'mantle_version':
'78d3966b3c331292ea29ec38661b25df0a245948',
'pyyaml_version': '3.12', 'pyyaml_version': '3.12',
@@ -17,6 +21,8 @@ vars = {
'nodejs_git': 'https://github.com/nodejs', 'nodejs_git': 'https://github.com/nodejs',
'yaml_git': 'https://github.com/yaml', 'yaml_git': 'https://github.com/yaml',
'squirrel_git': 'https://github.com/Squirrel', 'squirrel_git': 'https://github.com/Squirrel',
'reactiveobjc_git': 'https://github.com/ReactiveCocoa',
'mantle_git': 'https://github.com/Mantle',
# KEEP IN SYNC WITH utils.js FILE # KEEP IN SYNC WITH utils.js FILE
'yarn_version': '1.15.2', 'yarn_version': '1.15.2',
@@ -87,11 +93,11 @@ deps = {
'condition': 'process_deps', 'condition': 'process_deps',
}, },
'src/third_party/squirrel.mac/vendor/ReactiveObjC': { 'src/third_party/squirrel.mac/vendor/ReactiveObjC': {
'url': 'https://github.com/ReactiveCocoa/ReactiveObjC.git@74ab5baccc6f7202c8ac69a8d1e152c29dc1ea76', 'url': Var("reactiveobjc_git") + '/ReactiveObjC.git@' + Var("reactiveobjc_version"),
'condition': 'process_deps' 'condition': 'process_deps'
}, },
'src/third_party/squirrel.mac/vendor/Mantle': { 'src/third_party/squirrel.mac/vendor/Mantle': {
'url': 'https://github.com/Mantle/Mantle.git@78d3966b3c331292ea29ec38661b25df0a245948', 'url': Var("mantle_git") + '/Mantle.git@' + Var("mantle_version"),
'condition': 'process_deps', 'condition': 'process_deps',
} }
} }

View File

@@ -29,7 +29,7 @@
version: 1.0.{build} version: 1.0.{build}
build_cloud: electronhq-16-core build_cloud: electronhq-16-core
image: e-114.0.5684.0 image: e-114.0.5735.16-bust-cache
environment: environment:
GIT_CACHE_PATH: C:\Users\appveyor\libcc_cache GIT_CACHE_PATH: C:\Users\appveyor\libcc_cache
ELECTRON_OUT_DIR: Default ELECTRON_OUT_DIR: Default
@@ -66,11 +66,13 @@ for:
build_script: build_script:
- ps: | - ps: |
node script/yarn.js install --frozen-lockfile node script/yarn.js install --frozen-lockfile
node script/doc-only-change.js --prNumber=$env:APPVEYOR_PULL_REQUEST_NUMBER --prBranch=$env:APPVEYOR_REPO_BRANCH node script/doc-only-change.js --prNumber=$env:APPVEYOR_PULL_REQUEST_NUMBER
if ($LASTEXITCODE -eq 0) { if ($LASTEXITCODE -eq 0) {
Write-warning "Skipping build for doc only change"; Exit-AppveyorBuild Write-warning "Skipping build for doc only change"
Exit-AppveyorBuild
} else {
$global:LASTEXITCODE = 0
} }
$global:LASTEXITCODE = 0
- cd .. - cd ..
- ps: Write-Host "Building $env:GN_CONFIG build" - ps: Write-Host "Building $env:GN_CONFIG build"
- git config --global core.longpaths true - git config --global core.longpaths true
@@ -220,11 +222,13 @@ for:
build_script: build_script:
- ps: | - ps: |
node script/yarn.js install --frozen-lockfile node script/yarn.js install --frozen-lockfile
node script/doc-only-change.js --prNumber=$env:APPVEYOR_PULL_REQUEST_NUMBER --prBranch=$env:APPVEYOR_REPO_BRANCH node script/doc-only-change.js --prNumber=$env:APPVEYOR_PULL_REQUEST_NUMBER
if ($LASTEXITCODE -eq 0) { if ($LASTEXITCODE -eq 0) {
Write-warning "Skipping build for doc only change"; Exit-AppveyorBuild Write-warning "Skipping build for doc only change"
Exit-AppveyorBuild
} else {
$global:LASTEXITCODE = 0
} }
$global:LASTEXITCODE = 0
- cd .. - cd ..
- mkdir out\Default - mkdir out\Default
- cd .. - cd ..

View File

@@ -29,7 +29,7 @@
version: 1.0.{build} version: 1.0.{build}
build_cloud: electronhq-16-core build_cloud: electronhq-16-core
image: e-114.0.5684.0 image: e-114.0.5735.16-bust-cache
environment: environment:
GIT_CACHE_PATH: C:\Users\appveyor\libcc_cache GIT_CACHE_PATH: C:\Users\appveyor\libcc_cache
ELECTRON_OUT_DIR: Default ELECTRON_OUT_DIR: Default
@@ -64,11 +64,13 @@ for:
build_script: build_script:
- ps: | - ps: |
node script/yarn.js install --frozen-lockfile node script/yarn.js install --frozen-lockfile
node script/doc-only-change.js --prNumber=$env:APPVEYOR_PULL_REQUEST_NUMBER --prBranch=$env:APPVEYOR_REPO_BRANCH node script/doc-only-change.js --prNumber=$env:APPVEYOR_PULL_REQUEST_NUMBER
if ($LASTEXITCODE -eq 0) { if ($LASTEXITCODE -eq 0) {
Write-warning "Skipping build for doc only change"; Exit-AppveyorBuild Write-warning "Skipping build for doc only change"
Exit-AppveyorBuild
} else {
$global:LASTEXITCODE = 0
} }
$global:LASTEXITCODE = 0
- cd .. - cd ..
- ps: Write-Host "Building $env:GN_CONFIG build" - ps: Write-Host "Building $env:GN_CONFIG build"
- git config --global core.longpaths true - git config --global core.longpaths true
@@ -216,11 +218,13 @@ for:
build_script: build_script:
- ps: | - ps: |
node script/yarn.js install --frozen-lockfile node script/yarn.js install --frozen-lockfile
node script/doc-only-change.js --prNumber=$env:APPVEYOR_PULL_REQUEST_NUMBER --prBranch=$env:APPVEYOR_REPO_BRANCH node script/doc-only-change.js --prNumber=$env:APPVEYOR_PULL_REQUEST_NUMBER
if ($LASTEXITCODE -eq 0) { if ($LASTEXITCODE -eq 0) {
Write-warning "Skipping build for doc only change"; Exit-AppveyorBuild Write-warning "Skipping build for doc only change"
Exit-AppveyorBuild
} else {
$global:LASTEXITCODE = 0
} }
$global:LASTEXITCODE = 0
- cd .. - cd ..
- mkdir out\Default - mkdir out\Default
- cd .. - cd ..

View File

@@ -49,3 +49,9 @@ use_qt = false
# https://chromium-review.googlesource.com/c/chromium/src/+/4365718 # https://chromium-review.googlesource.com/c/chromium/src/+/4365718
# TODO(codebytere): fix perfetto incompatibility with Node.js. # TODO(codebytere): fix perfetto incompatibility with Node.js.
use_perfetto_client_library = false use_perfetto_client_library = false
# Ref: https://chromium-review.googlesource.com/c/chromium/src/+/4402277
enable_check_raw_ptr_fields = false
# Disables the builtins PGO for V8
v8_builtins_profiling_log_file = ""

View File

@@ -7,7 +7,7 @@ Process: [Main](../glossary.md#main-process)
The following example shows how to quit the application when the last window is The following example shows how to quit the application when the last window is
closed: closed:
```javascript ```js
const { app } = require('electron') const { app } = require('electron')
app.on('window-all-closed', () => { app.on('window-all-closed', () => {
app.quit() app.quit()
@@ -150,9 +150,20 @@ Returns:
* `event` Event * `event` Event
Emitted when mac application become active. Difference from `activate` event is Emitted when the application becomes active. This differs from the `activate` event in
that `did-become-active` is emitted every time the app becomes active, not only that `did-become-active` is emitted every time the app becomes active, not only
when Dock icon is clicked or application is re-launched. when Dock icon is clicked or application is re-launched. It is also emitted when a user
switches to the app via the macOS App Switcher.
### Event: 'did-resign-active' _macOS_
Returns:
* `event` Event
Emitted when the app is no longer active and doesnt have focus. This can be triggered,
for example, by clicking on another application or by using the macOS App Switcher to
switch to another application.
### Event: 'continue-activity' _macOS_ ### Event: 'continue-activity' _macOS_
@@ -285,7 +296,7 @@ Emitted when failed to verify the `certificate` for `url`, to trust the
certificate you should prevent the default behavior with certificate you should prevent the default behavior with
`event.preventDefault()` and call `callback(true)`. `event.preventDefault()` and call `callback(true)`.
```javascript ```js
const { app } = require('electron') const { app } = require('electron')
app.on('certificate-error', (event, webContents, url, error, certificate, callback) => { app.on('certificate-error', (event, webContents, url, error, certificate, callback) => {
@@ -317,7 +328,7 @@ and `callback` can be called with an entry filtered from the list. Using
`event.preventDefault()` prevents the application from using the first `event.preventDefault()` prevents the application from using the first
certificate from the store. certificate from the store.
```javascript ```js
const { app } = require('electron') const { app } = require('electron')
app.on('select-client-certificate', (event, webContents, url, list, callback) => { app.on('select-client-certificate', (event, webContents, url, list, callback) => {
@@ -350,7 +361,7 @@ The default behavior is to cancel all authentications. To override this you
should prevent the default behavior with `event.preventDefault()` and call should prevent the default behavior with `event.preventDefault()` and call
`callback(username, password)` with the credentials. `callback(username, password)` with the credentials.
```javascript ```js
const { app } = require('electron') const { app } = require('electron')
app.on('login', (event, webContents, details, authInfo, callback) => { app.on('login', (event, webContents, details, authInfo, callback) => {
@@ -470,7 +481,7 @@ Returns:
Emitted when Electron has created a new `session`. Emitted when Electron has created a new `session`.
```javascript ```js
const { app } = require('electron') const { app } = require('electron')
app.on('session-created', (session) => { app.on('session-created', (session) => {
@@ -555,7 +566,7 @@ started after current instance exited.
An example of restarting current instance immediately and adding a new command An example of restarting current instance immediately and adding a new command
line argument to the new instance: line argument to the new instance:
```javascript ```js
const { app } = require('electron') const { app } = require('electron')
app.relaunch({ args: process.argv.slice(1).concat(['--relaunch']) }) app.relaunch({ args: process.argv.slice(1).concat(['--relaunch']) })
@@ -940,7 +951,7 @@ List, nor will it be displayed.
Here's a very simple example of creating a custom Jump List: Here's a very simple example of creating a custom Jump List:
```javascript ```js
const { app } = require('electron') const { app } = require('electron')
app.setJumpList([ app.setJumpList([
@@ -960,7 +971,7 @@ app.setJumpList([
title: 'Tool A', title: 'Tool A',
program: process.execPath, program: process.execPath,
args: '--run-tool-a', args: '--run-tool-a',
icon: process.execPath, iconPath: process.execPath,
iconIndex: 0, iconIndex: 0,
description: 'Runs Tool A' description: 'Runs Tool A'
}, },
@@ -969,7 +980,7 @@ app.setJumpList([
title: 'Tool B', title: 'Tool B',
program: process.execPath, program: process.execPath,
args: '--run-tool-b', args: '--run-tool-b',
icon: process.execPath, iconPath: process.execPath,
iconIndex: 0, iconIndex: 0,
description: 'Runs Tool B' description: 'Runs Tool B'
} }
@@ -1023,8 +1034,8 @@ use this method to ensure single instance.
An example of activating the window of primary instance when a second instance An example of activating the window of primary instance when a second instance
starts: starts:
```javascript ```js
const { app } = require('electron') const { app, BrowserWindow } = require('electron')
let myWindow = null let myWindow = null
const additionalData = { myKey: 'myValue' } const additionalData = { myKey: 'myValue' }
@@ -1044,9 +1055,9 @@ if (!gotTheLock) {
} }
}) })
// Create myWindow, load the rest of the app, etc...
app.whenReady().then(() => { app.whenReady().then(() => {
myWindow = createWindow() myWindow = new BrowserWindow({})
myWindow.loadURL('https://electronjs.org')
}) })
} }
``` ```
@@ -1169,11 +1180,15 @@ case the user's DNS configuration does not include a provider that supports
DoH. DoH.
```js ```js
app.configureHostResolver({ const { app } = require('electron')
secureDnsMode: 'secure',
secureDnsServers: [ app.whenReady().then(() => {
'https://cloudflare-dns.com/dns-query' app.configureHostResolver({
] secureDnsMode: 'secure',
secureDnsServers: [
'https://cloudflare-dns.com/dns-query'
]
})
}) })
``` ```
@@ -1325,7 +1340,10 @@ To work with Electron's `autoUpdater` on Windows, which uses [Squirrel][Squirrel
you'll want to set the launch path to Update.exe, and pass arguments that specify your you'll want to set the launch path to Update.exe, and pass arguments that specify your
application name. For example: application name. For example:
``` javascript ``` js
const { app } = require('electron')
const path = require('path')
const appFolder = path.dirname(process.execPath) const appFolder = path.dirname(process.execPath)
const updateExe = path.resolve(appFolder, '..', 'Update.exe') const updateExe = path.resolve(appFolder, '..', 'Update.exe')
const exeName = path.basename(process.execPath) const exeName = path.basename(process.execPath)
@@ -1335,7 +1353,7 @@ app.setLoginItemSettings({
path: updateExe, path: updateExe,
args: [ args: [
'--processStart', `"${exeName}"`, '--processStart', `"${exeName}"`,
'--process-start-args', `"--hidden"` '--process-start-args', '"--hidden"'
] ]
}) })
``` ```
@@ -1394,11 +1412,22 @@ Show the platform's native emoji picker.
Returns `Function` - This function **must** be called once you have finished accessing the security scoped file. If you do not remember to stop accessing the bookmark, [kernel resources will be leaked](https://developer.apple.com/reference/foundation/nsurl/1417051-startaccessingsecurityscopedreso?language=objc) and your app will lose its ability to reach outside the sandbox completely, until your app is restarted. Returns `Function` - This function **must** be called once you have finished accessing the security scoped file. If you do not remember to stop accessing the bookmark, [kernel resources will be leaked](https://developer.apple.com/reference/foundation/nsurl/1417051-startaccessingsecurityscopedreso?language=objc) and your app will lose its ability to reach outside the sandbox completely, until your app is restarted.
```js ```js
// Start accessing the file. const { app, dialog } = require('electron')
const stopAccessingSecurityScopedResource = app.startAccessingSecurityScopedResource(data) const fs = require('fs')
// You can now access the file outside of the sandbox 🎉
// Remember to stop accessing the file once you've finished with it. let filepath
let bookmark
dialog.showOpenDialog(null, { securityScopedBookmarks: true }).then(({ filePaths, bookmarks }) => {
filepath = filePaths[0]
bookmark = bookmarks[0]
fs.readFileSync(filepath)
})
// ... restart app ...
const stopAccessingSecurityScopedResource = app.startAccessingSecurityScopedResource(bookmark)
fs.readFileSync(filepath)
stopAccessingSecurityScopedResource() stopAccessingSecurityScopedResource()
``` ```
@@ -1439,6 +1468,8 @@ By default, if an app of the same name as the one being moved exists in the Appl
For example: For example:
```js ```js
const { app, dialog } = require('electron')
app.moveToApplicationsFolder({ app.moveToApplicationsFolder({
conflictHandler: (conflictType) => { conflictHandler: (conflictType) => {
if (conflictType === 'exists') { if (conflictType === 'exists') {

View File

@@ -137,7 +137,7 @@ application starts.
[squirrel-mac]: https://github.com/Squirrel/Squirrel.Mac [squirrel-mac]: https://github.com/Squirrel/Squirrel.Mac
[server-support]: https://github.com/Squirrel/Squirrel.Mac#server-support [server-support]: https://github.com/Squirrel/Squirrel.Mac#server-support
[squirrel-windows]: https://github.com/Squirrel/Squirrel.Windows [squirrel-windows]: https://github.com/Squirrel/Squirrel.Windows
[installer]: https://github.com/electron/grunt-electron-installer [installer]: https://github.com/electron-archive/grunt-electron-installer
[installer-lib]: https://github.com/electron/windows-installer [installer-lib]: https://github.com/electron/windows-installer
[electron-forge-lib]: https://github.com/electron/forge [electron-forge-lib]: https://github.com/electron/forge
[app-user-model-id]: https://learn.microsoft.com/en-us/windows/win32/shell/appids [app-user-model-id]: https://learn.microsoft.com/en-us/windows/win32/shell/appids

View File

@@ -104,6 +104,7 @@ window, you have to set both `parent` and `modal` options:
```javascript ```javascript
const { BrowserWindow } = require('electron') const { BrowserWindow } = require('electron')
const top = new BrowserWindow()
const child = new BrowserWindow({ parent: top, modal: true, show: false }) const child = new BrowserWindow({ parent: top, modal: true, show: false })
child.loadURL('https://github.com') child.loadURL('https://github.com')
child.once('ready-to-show', () => { child.once('ready-to-show', () => {
@@ -262,6 +263,9 @@ It creates a new `BrowserWindow` with native properties as set by the `options`.
`tooltip`, `content`, `under-window`, or `under-page`. Please note that `tooltip`, `content`, `under-window`, or `under-page`. Please note that
`appearance-based`, `light`, `dark`, `medium-light`, and `ultra-dark` are `appearance-based`, `light`, `dark`, `medium-light`, and `ultra-dark` are
deprecated and have been removed in macOS Catalina (10.15). deprecated and have been removed in macOS Catalina (10.15).
* `backgroundMaterial` string (optional) _Windows_ - Set the window's
system-drawn background material, including behind the non-client area.
Can be `auto`, `none`, `mica`, `acrylic` or `tabbed`. See [win.setBackgroundMaterial](#winsetbackgroundmaterialmaterial-windows) for more information.
* `zoomToPageWidth` boolean (optional) _macOS_ - Controls the behavior on * `zoomToPageWidth` boolean (optional) _macOS_ - Controls the behavior on
macOS when option-clicking the green stoplight button on the toolbar or by macOS when option-clicking the green stoplight button on the toolbar or by
clicking the Window > Zoom menu item. If `true`, the window will grow to clicking the Window > Zoom menu item. If `true`, the window will grow to
@@ -884,7 +888,7 @@ On Linux the setter is a no-op, although the getter returns `true`.
A `boolean` property that determines whether the window is excluded from the applications Windows menu. `false` by default. A `boolean` property that determines whether the window is excluded from the applications Windows menu. `false` by default.
```js ```js @ts-expect-error=[11]
const win = new BrowserWindow({ height: 600, width: 600 }) const win = new BrowserWindow({ height: 600, width: 600 })
const template = [ const template = [
@@ -954,7 +958,7 @@ Hides the window.
#### `win.isVisible()` #### `win.isVisible()`
Returns `boolean` - Whether the window is visible to the user. Returns `boolean` - Whether the window is visible to the user in the foreground of the app.
#### `win.isModal()` #### `win.isModal()`
@@ -992,6 +996,8 @@ Returns `boolean` - Whether the window is minimized.
Sets whether the window should be in fullscreen mode. Sets whether the window should be in fullscreen mode.
**Note:** On macOS, fullscreen transitions take place asynchronously. If further actions depend on the fullscreen state, use the ['enter-full-screen'](browser-window.md#event-enter-full-screen) or ['leave-full-screen'](browser-window.md#event-leave-full-screen) events.
#### `win.isFullScreen()` #### `win.isFullScreen()`
Returns `boolean` - Whether the window is in fullscreen mode. Returns `boolean` - Whether the window is in fullscreen mode.
@@ -1485,6 +1491,9 @@ Node's [`url.format`](https://nodejs.org/api/url.html#url_url_format_urlobject)
method: method:
```javascript ```javascript
const { BrowserWindow } = require('electron')
const win = new BrowserWindow()
const url = require('url').format({ const url = require('url').format({
protocol: 'file', protocol: 'file',
slashes: true, slashes: true,
@@ -1498,6 +1507,9 @@ You can load a URL using a `POST` request with URL-encoded data by doing
the following: the following:
```javascript ```javascript
const { BrowserWindow } = require('electron')
const win = new BrowserWindow()
win.loadURL('http://localhost:8000/post', { win.loadURL('http://localhost:8000/post', {
postData: [{ postData: [{
type: 'rawData', type: 'rawData',
@@ -1842,6 +1854,21 @@ will remove the vibrancy effect on the window.
Note that `appearance-based`, `light`, `dark`, `medium-light`, and `ultra-dark` have been Note that `appearance-based`, `light`, `dark`, `medium-light`, and `ultra-dark` have been
deprecated and will be removed in an upcoming version of macOS. deprecated and will be removed in an upcoming version of macOS.
#### `win.setBackgroundMaterial(material)` _Windows_
* `material` string
* `auto` - Let the Desktop Window Manager (DWM) automatically decide the system-drawn backdrop material for this window. This is the default.
* `none` - Don't draw any system backdrop.
* `mica` - Draw the backdrop material effect corresponding to a long-lived window.
* `acrylic` - Draw the backdrop material effect corresponding to a transient window.
* `tabbed` - Draw the backdrop material effect corresponding to a window with a tabbed title bar.
This method sets the browser window's system-drawn background material, including behind the non-client area.
See the [Windows documentation](https://learn.microsoft.com/en-us/windows/win32/api/dwmapi/ne-dwmapi-dwm_systembackdrop_type) for more details.
**Note:** This method is only supported on Windows 11 22H2 and up.
#### `win.setWindowButtonPosition(position)` _macOS_ #### `win.setWindowButtonPosition(position)` _macOS_
* `position` [Point](structures/point.md) | null * `position` [Point](structures/point.md) | null

View File

@@ -65,7 +65,7 @@ strictly follow the Node.js model as described in the
For instance, we could have created the same request to 'github.com' as follows: For instance, we could have created the same request to 'github.com' as follows:
```JavaScript ```javascript
const request = net.request({ const request = net.request({
method: 'GET', method: 'GET',
protocol: 'https:', protocol: 'https:',
@@ -104,7 +104,7 @@ The `callback` function is expected to be called back with user credentials:
* `username` string * `username` string
* `password` string * `password` string
```JavaScript ```javascript @ts-type={request:Electron.ClientRequest}
request.on('login', (authInfo, callback) => { request.on('login', (authInfo, callback) => {
callback('username', 'password') callback('username', 'password')
}) })
@@ -113,9 +113,9 @@ request.on('login', (authInfo, callback) => {
Providing empty credentials will cancel the request and report an authentication Providing empty credentials will cancel the request and report an authentication
error on the response object: error on the response object:
```JavaScript ```javascript @ts-type={request:Electron.ClientRequest}
request.on('response', (response) => { request.on('response', (response) => {
console.log(`STATUS: ${response.statusCode}`); console.log(`STATUS: ${response.statusCode}`)
response.on('error', (error) => { response.on('error', (error) => {
console.log(`ERROR: ${JSON.stringify(error)}`) console.log(`ERROR: ${JSON.stringify(error)}`)
}) })

View File

@@ -148,10 +148,7 @@ clipboard.
```js ```js
const { clipboard } = require('electron') const { clipboard } = require('electron')
clipboard.writeBookmark({ clipboard.writeBookmark('Electron Homepage', 'https://electronjs.org')
text: 'https://electronjs.org',
bookmark: 'Electron Homepage'
})
``` ```
### `clipboard.readFindText()` _macOS_ ### `clipboard.readFindText()` _macOS_

View File

@@ -18,7 +18,7 @@ contextBridge.exposeInMainWorld(
) )
``` ```
```javascript ```javascript @ts-nocheck
// Renderer (Main World) // Renderer (Main World)
window.electron.doThing() window.electron.doThing()
@@ -104,7 +104,7 @@ contextBridge.exposeInIsolatedWorld(
) )
``` ```
```javascript ```javascript @ts-nocheck
// Renderer (In isolated world id1004) // Renderer (In isolated world id1004)
window.electron.doThing() window.electron.doThing()

View File

@@ -16,7 +16,7 @@ crashReporter.start({ submitURL: 'https://your-domain.com/url-to-submit' })
For setting up a server to accept and process crash reports, you can use For setting up a server to accept and process crash reports, you can use
following projects: following projects:
* [socorro](https://github.com/mozilla/socorro) * [socorro](https://github.com/mozilla-services/socorro)
* [mini-breakpad-server](https://github.com/electron/mini-breakpad-server) * [mini-breakpad-server](https://github.com/electron/mini-breakpad-server)
> **Note:** Electron uses Crashpad, not Breakpad, to collect and upload > **Note:** Electron uses Crashpad, not Breakpad, to collect and upload

View File

@@ -10,7 +10,9 @@ title is `Electron`:
```javascript ```javascript
// In the main process. // In the main process.
const { desktopCapturer } = require('electron') const { BrowserWindow, desktopCapturer } = require('electron')
const mainWindow = new BrowserWindow()
desktopCapturer.getSources({ types: ['window', 'screen'] }).then(async sources => { desktopCapturer.getSources({ types: ['window', 'screen'] }).then(async sources => {
for (const source of sources) { for (const source of sources) {
@@ -22,7 +24,7 @@ desktopCapturer.getSources({ types: ['window', 'screen'] }).then(async sources =
}) })
``` ```
```javascript ```javascript @ts-nocheck
// In the preload script. // In the preload script.
const { ipcRenderer } = require('electron') const { ipcRenderer } = require('electron')

View File

@@ -72,7 +72,7 @@ and a directory selector, so if you set `properties` to
`['openFile', 'openDirectory']` on these platforms, a directory selector will be `['openFile', 'openDirectory']` on these platforms, a directory selector will be
shown. shown.
```js ```js @ts-type={mainWindow:Electron.BrowserWindow}
dialog.showOpenDialogSync(mainWindow, { dialog.showOpenDialogSync(mainWindow, {
properties: ['openFile', 'openDirectory'] properties: ['openFile', 'openDirectory']
}) })
@@ -139,7 +139,7 @@ and a directory selector, so if you set `properties` to
`['openFile', 'openDirectory']` on these platforms, a directory selector will be `['openFile', 'openDirectory']` on these platforms, a directory selector will be
shown. shown.
```js ```js @ts-type={mainWindow:Electron.BrowserWindow}
dialog.showOpenDialog(mainWindow, { dialog.showOpenDialog(mainWindow, {
properties: ['openFile', 'openDirectory'] properties: ['openFile', 'openDirectory']
}).then(result => { }).then(result => {
@@ -223,10 +223,10 @@ expanding and collapsing the dialog.
* `browserWindow` [BrowserWindow](browser-window.md) (optional) * `browserWindow` [BrowserWindow](browser-window.md) (optional)
* `options` Object * `options` Object
* `message` string - Content of the message box. * `message` string - Content of the message box.
* `type` string (optional) - Can be `"none"`, `"info"`, `"error"`, `"question"` or * `type` string (optional) - Can be `none`, `info`, `error`, `question` or
`"warning"`. On Windows, `"question"` displays the same icon as `"info"`, unless `warning`. On Windows, `question` displays the same icon as `info`, unless
you set an icon using the `"icon"` option. On macOS, both `"warning"` and you set an icon using the `icon` option. On macOS, both `warning` and
`"error"` display the same warning icon. `error` display the same warning icon.
* `buttons` string[]&#32;(optional) - Array of texts for buttons. On Windows, an empty array * `buttons` string[]&#32;(optional) - Array of texts for buttons. On Windows, an empty array
will result in one button labeled "OK". will result in one button labeled "OK".
* `defaultId` Integer (optional) - Index of the button in the buttons array which will * `defaultId` Integer (optional) - Index of the button in the buttons array which will
@@ -266,10 +266,10 @@ If `browserWindow` is not shown dialog will not be attached to it. In such case
* `browserWindow` [BrowserWindow](browser-window.md) (optional) * `browserWindow` [BrowserWindow](browser-window.md) (optional)
* `options` Object * `options` Object
* `message` string - Content of the message box. * `message` string - Content of the message box.
* `type` string (optional) - Can be `"none"`, `"info"`, `"error"`, `"question"` or * `type` string (optional) - Can be `none`, `info`, `error`, `question` or
`"warning"`. On Windows, `"question"` displays the same icon as `"info"`, unless `warning`. On Windows, `question` displays the same icon as `info`, unless
you set an icon using the `"icon"` option. On macOS, both `"warning"` and you set an icon using the `icon` option. On macOS, both `warning` and
`"error"` display the same warning icon. `error` display the same warning icon.
* `buttons` string[]&#32;(optional) - Array of texts for buttons. On Windows, an empty array * `buttons` string[]&#32;(optional) - Array of texts for buttons. On Windows, an empty array
will result in one button labeled "OK". will result in one button labeled "OK".
* `defaultId` Integer (optional) - Index of the button in the buttons array which will * `defaultId` Integer (optional) - Index of the button in the buttons array which will

View File

@@ -89,7 +89,7 @@ tuples. So, the even-numbered offsets are key values, and the odd-numbered
offsets are the associated values. Header names are not lowercased, and offsets are the associated values. Header names are not lowercased, and
duplicates are not merged. duplicates are not merged.
```javascript ```javascript @ts-type={response:Electron.IncomingMessage}
// Prints something like: // Prints something like:
// //
// [ 'user-agent', // [ 'user-agent',
@@ -100,5 +100,5 @@ duplicates are not merged.
// '127.0.0.1:8000', // '127.0.0.1:8000',
// 'ACCEPT', // 'ACCEPT',
// '*/*' ] // '*/*' ]
console.log(request.rawHeaders) console.log(response.rawHeaders)
``` ```

View File

@@ -83,14 +83,14 @@ If `listener` returns a Promise, the eventual result of the promise will be
returned as a reply to the remote caller. Otherwise, the return value of the returned as a reply to the remote caller. Otherwise, the return value of the
listener will be used as the value of the reply. listener will be used as the value of the reply.
```js title='Main Process' ```js title='Main Process' @ts-type={somePromise:(...args:unknown[])=>Promise<unknown>}
ipcMain.handle('my-invokable-ipc', async (event, ...args) => { ipcMain.handle('my-invokable-ipc', async (event, ...args) => {
const result = await somePromise(...args) const result = await somePromise(...args)
return result return result
}) })
``` ```
```js title='Renderer Process' ```js title='Renderer Process' @ts-type={arg1:unknown} @ts-type={arg2:unknown}
async () => { async () => {
const result = await ipcRenderer.invoke('my-invokable-ipc', arg1, arg2) const result = await ipcRenderer.invoke('my-invokable-ipc', arg1, arg2)
// ... // ...

View File

@@ -101,7 +101,7 @@ The main process should listen for `channel` with
For example: For example:
```javascript ```javascript @ts-type={someArgument:unknown} @ts-type={doSomeWork:(arg:unknown)=>Promise<unknown>}
// Renderer process // Renderer process
ipcRenderer.invoke('some-name', someArgument).then((result) => { ipcRenderer.invoke('some-name', someArgument).then((result) => {
// ... // ...

View File

@@ -147,27 +147,29 @@ can have a submenu.
An example of creating the application menu with the simple template API: An example of creating the application menu with the simple template API:
```javascript ```javascript @ts-expect-error=[107]
const { app, Menu } = require('electron') const { app, Menu } = require('electron')
const isMac = process.platform === 'darwin' const isMac = process.platform === 'darwin'
const template = [ const template = [
// { role: 'appMenu' } // { role: 'appMenu' }
...(isMac ? [{ ...(isMac
label: app.name, ? [{
submenu: [ label: app.name,
{ role: 'about' }, submenu: [
{ type: 'separator' }, { role: 'about' },
{ role: 'services' }, { type: 'separator' },
{ type: 'separator' }, { role: 'services' },
{ role: 'hide' }, { type: 'separator' },
{ role: 'hideOthers' }, { role: 'hide' },
{ role: 'unhide' }, { role: 'hideOthers' },
{ type: 'separator' }, { role: 'unhide' },
{ role: 'quit' } { type: 'separator' },
] { role: 'quit' }
}] : []), ]
}]
: []),
// { role: 'fileMenu' } // { role: 'fileMenu' }
{ {
label: 'File', label: 'File',
@@ -185,23 +187,25 @@ const template = [
{ role: 'cut' }, { role: 'cut' },
{ role: 'copy' }, { role: 'copy' },
{ role: 'paste' }, { role: 'paste' },
...(isMac ? [ ...(isMac
{ role: 'pasteAndMatchStyle' }, ? [
{ role: 'delete' }, { role: 'pasteAndMatchStyle' },
{ role: 'selectAll' }, { role: 'delete' },
{ type: 'separator' }, { role: 'selectAll' },
{ { type: 'separator' },
label: 'Speech', {
submenu: [ label: 'Speech',
{ role: 'startSpeaking' }, submenu: [
{ role: 'stopSpeaking' } { role: 'startSpeaking' },
{ role: 'stopSpeaking' }
]
}
] ]
} : [
] : [ { role: 'delete' },
{ role: 'delete' }, { type: 'separator' },
{ type: 'separator' }, { role: 'selectAll' }
{ role: 'selectAll' } ])
])
] ]
}, },
// { role: 'viewMenu' } // { role: 'viewMenu' }
@@ -225,14 +229,16 @@ const template = [
submenu: [ submenu: [
{ role: 'minimize' }, { role: 'minimize' },
{ role: 'zoom' }, { role: 'zoom' },
...(isMac ? [ ...(isMac
{ type: 'separator' }, ? [
{ role: 'front' }, { type: 'separator' },
{ type: 'separator' }, { role: 'front' },
{ role: 'window' } { type: 'separator' },
] : [ { role: 'window' }
{ role: 'close' } ]
]) : [
{ role: 'close' }
])
] ]
}, },
{ {
@@ -261,7 +267,7 @@ menu on behalf of the renderer.
Below is an example of showing a menu when the user right clicks the page: Below is an example of showing a menu when the user right clicks the page:
```js ```js @ts-expect-error=[21]
// renderer // renderer
window.addEventListener('contextmenu', (e) => { window.addEventListener('contextmenu', (e) => {
e.preventDefault() e.preventDefault()
@@ -283,7 +289,7 @@ ipcMain.on('show-context-menu', (event) => {
{ label: 'Menu Item 2', type: 'checkbox', checked: true } { label: 'Menu Item 2', type: 'checkbox', checked: true }
] ]
const menu = Menu.buildFromTemplate(template) const menu = Menu.buildFromTemplate(template)
menu.popup(BrowserWindow.fromWebContents(event.sender)) menu.popup({ window: BrowserWindow.fromWebContents(event.sender) })
}) })
``` ```

View File

@@ -17,7 +17,8 @@ Example:
```js ```js
// Main process // Main process
const { MessageChannelMain } = require('electron') const { BrowserWindow, MessageChannelMain } = require('electron')
const w = new BrowserWindow()
const { port1, port2 } = new MessageChannelMain() const { port1, port2 } = new MessageChannelMain()
w.webContents.postMessage('port', null, [port2]) w.webContents.postMessage('port', null, [port2])
port1.postMessage({ some: 'message' }) port1.postMessage({ some: 'message' })
@@ -26,9 +27,9 @@ port1.postMessage({ some: 'message' })
const { ipcRenderer } = require('electron') const { ipcRenderer } = require('electron')
ipcRenderer.on('port', (e) => { ipcRenderer.on('port', (e) => {
// e.ports is a list of ports sent along with this message // e.ports is a list of ports sent along with this message
e.ports[0].on('message', (messageEvent) => { e.ports[0].onmessage = (messageEvent) => {
console.log(messageEvent.data) console.log(messageEvent.data)
}) }
}) })
``` ```

View File

@@ -5,7 +5,7 @@
Process: [Main](../glossary.md#main-process) Process: [Main](../glossary.md#main-process)
```javascript ```javascript
const { netLog } = require('electron') const { app, netLog } = require('electron')
app.whenReady().then(async () => { app.whenReady().then(async () => {
await netLog.startLogging('/path/to/net-log') await netLog.startLogging('/path/to/net-log')

View File

@@ -129,6 +129,45 @@ won't be able to connect to remote sites. However, a return value of
whether a particular connection attempt to a particular remote site whether a particular connection attempt to a particular remote site
will be successful. will be successful.
#### `net.resolveHost(host, [options])`
* `host` string - Hostname to resolve.
* `options` Object (optional)
* `queryType` string (optional) - Requested DNS query type. If unspecified,
resolver will pick A or AAAA (or both) based on IPv4/IPv6 settings:
* `A` - Fetch only A records
* `AAAA` - Fetch only AAAA records.
* `source` string (optional) - The source to use for resolved addresses.
Default allows the resolver to pick an appropriate source. Only affects use
of big external sources (e.g. calling the system for resolution or using
DNS). Even if a source is specified, results can still come from cache,
resolving "localhost" or IP literals, etc. One of the following values:
* `any` (default) - Resolver will pick an appropriate source. Results could
come from DNS, MulticastDNS, HOSTS file, etc
* `system` - Results will only be retrieved from the system or OS, e.g. via
the `getaddrinfo()` system call
* `dns` - Results will only come from DNS queries
* `mdns` - Results will only come from Multicast DNS queries
* `localOnly` - No external sources will be used. Results will only come
from fast local sources that are available no matter the source setting,
e.g. cache, hosts file, IP literal resolution, etc.
* `cacheUsage` string (optional) - Indicates what DNS cache entries, if any,
can be used to provide a response. One of the following values:
* `allowed` (default) - Results may come from the host cache if non-stale
* `staleAllowed` - Results may come from the host cache even if stale (by
expiration or network changes)
* `disallowed` - Results will not come from the host cache.
* `secureDnsPolicy` string (optional) - Controls the resolver's Secure DNS
behavior for this request. One of the following values:
* `allow` (default)
* `disable`
Returns [`Promise<ResolvedHost>`](structures/resolved-host.md) - Resolves with the resolved IP addresses for the `host`.
This method will resolve hosts from the [default
session](session.md#sessiondefaultsession). To resolve a host from
another session, use [ses.resolveHost()](session.md#sesresolvehosthost-options).
## Properties ## Properties
### `net.online` _Readonly_ ### `net.online` _Readonly_

View File

@@ -24,6 +24,30 @@ Emitted when the system changes to AC power.
Emitted when system changes to battery power. Emitted when system changes to battery power.
### Event: 'thermal-state-change' _macOS_
* `state` string - The system's new thermal state. Can be `unknown`, `nominal`, `fair`, `serious`, `critical`.
Emitted when the thermal state of the system changes. Notification of a change
in the thermal status of the system, such as entering a critical temperature
range. Depending on the severity, the system might take steps to reduce said
temperature, for example, throttling the CPU or switching on the fans if
available.
Apps may react to the new state by reducing expensive computing tasks (e.g.
video encoding), or notifying the user. The same state might be received
repeatedly.
See https://developer.apple.com/library/archive/documentation/Performance/Conceptual/power_efficiency_guidelines_osx/RespondToThermalStateChanges.html
### Event: 'speed-limit-change' _macOS_ _Windows_
* `limit` number - The operating system's advertised speed limit for CPUs, in percent.
Notification of a change in the operating system's advertised speed limit for
CPUs, in percent. Values below 100 indicate that the system is impairing
processing power due to thermal management.
### Event: 'shutdown' _Linux_ _macOS_ ### Event: 'shutdown' _Linux_ _macOS_
Emitted when the system is about to reboot or shut down. If the event handler Emitted when the system is about to reboot or shut down. If the event handler
@@ -55,7 +79,7 @@ The `powerMonitor` module has the following methods:
* `idleThreshold` Integer * `idleThreshold` Integer
Returns `string` - The system's current state. Can be `active`, `idle`, `locked` or `unknown`. Returns `string` - The system's current idle state. Can be `active`, `idle`, `locked` or `unknown`.
Calculate the system idle state. `idleThreshold` is the amount of time (in seconds) Calculate the system idle state. `idleThreshold` is the amount of time (in seconds)
before considered idle. `locked` is available on supported systems only. before considered idle. `locked` is available on supported systems only.
@@ -66,6 +90,10 @@ Returns `Integer` - Idle time in seconds
Calculate system idle time in seconds. Calculate system idle time in seconds.
### `powerMonitor.getCurrentThermalState()` _macOS_
Returns `string` - The system's current thermal state. Can be `unknown`, `nominal`, `fair`, `serious`, or `critical`.
### `powerMonitor.isOnBatteryPower()` ### `powerMonitor.isOnBatteryPower()`
Returns `boolean` - Whether the system is on battery power. Returns `boolean` - Whether the system is on battery power.

View File

@@ -32,7 +32,7 @@ To have your custom protocol work in combination with a custom session, you need
to register it to that session explicitly. to register it to that session explicitly.
```javascript ```javascript
const { session, app, protocol } = require('electron') const { app, BrowserWindow, net, protocol, session } = require('electron')
const path = require('path') const path = require('path')
const url = require('url') const url = require('url')
@@ -41,11 +41,11 @@ app.whenReady().then(() => {
const ses = session.fromPartition(partition) const ses = session.fromPartition(partition)
ses.protocol.handle('atom', (request) => { ses.protocol.handle('atom', (request) => {
const path = request.url.slice('atom://'.length) const filePath = request.url.slice('atom://'.length)
return net.fetch(url.pathToFileURL(path.join(__dirname, path))) return net.fetch(url.pathToFileURL(path.join(__dirname, filePath)).toString())
}) })
mainWindow = new BrowserWindow({ webPreferences: { partition } }) const mainWindow = new BrowserWindow({ webPreferences: { partition } })
}) })
``` ```
@@ -121,9 +121,9 @@ Either a `Response` or a `Promise<Response>` can be returned.
Example: Example:
```js ```js
import { app, protocol } from 'electron' const { app, net, protocol } = require('electron')
import { join } from 'path' const { join } = require('path')
import { pathToFileURL } from 'url' const { pathToFileURL } = require('url')
protocol.registerSchemesAsPrivileged([ protocol.registerSchemesAsPrivileged([
{ {
@@ -131,7 +131,7 @@ protocol.registerSchemesAsPrivileged([
privileges: { privileges: {
standard: true, standard: true,
secure: true, secure: true,
supportsFetchAPI: true supportFetchAPI: true
} }
} }
]) ])
@@ -147,7 +147,7 @@ app.whenReady().then(() => {
} }
// NB, this does not check for paths that escape the bundle, e.g. // NB, this does not check for paths that escape the bundle, e.g.
// app://bundle/../../secret_file.txt // app://bundle/../../secret_file.txt
return net.fetch(pathToFileURL(join(__dirname, pathname))) return net.fetch(pathToFileURL(join(__dirname, pathname)).toString())
} else if (host === 'api') { } else if (host === 'api') {
return net.fetch('https://api.my-server.com/' + pathname, { return net.fetch('https://api.my-server.com/' + pathname, {
method: req.method, method: req.method,

View File

@@ -98,7 +98,7 @@ Emitted when Electron is about to download `item` in `webContents`.
Calling `event.preventDefault()` will cancel the download and `item` will not be Calling `event.preventDefault()` will cancel the download and `item` will not be
available from next tick of the process. available from next tick of the process.
```javascript ```javascript @ts-expect-error=[4]
const { session } = require('electron') const { session } = require('electron')
session.defaultSession.on('will-download', (event, item, webContents) => { session.defaultSession.on('will-download', (event, item, webContents) => {
event.preventDefault() event.preventDefault()
@@ -214,7 +214,7 @@ cancel the request. Additionally, permissioning on `navigator.hid` can
be further managed by using [`ses.setPermissionCheckHandler(handler)`](#sessetpermissioncheckhandlerhandler) be further managed by using [`ses.setPermissionCheckHandler(handler)`](#sessetpermissioncheckhandlerhandler)
and [`ses.setDevicePermissionHandler(handler)`](#sessetdevicepermissionhandlerhandler). and [`ses.setDevicePermissionHandler(handler)`](#sessetdevicepermissionhandlerhandler).
```javascript ```javascript @ts-type={fetchGrantedDevices:()=>(Array<Electron.DevicePermissionHandlerHandlerDetails['device']>)}
const { app, BrowserWindow } = require('electron') const { app, BrowserWindow } = require('electron')
let win = null let win = null
@@ -253,7 +253,7 @@ app.whenReady().then(() => {
win.webContents.session.on('select-hid-device', (event, details, callback) => { win.webContents.session.on('select-hid-device', (event, details, callback) => {
event.preventDefault() event.preventDefault()
const selectedDevice = details.deviceList.find((device) => { const selectedDevice = details.deviceList.find((device) => {
return device.vendorId === '9025' && device.productId === '67' return device.vendorId === 9025 && device.productId === 67
}) })
callback(selectedDevice?.deviceId) callback(selectedDevice?.deviceId)
}) })
@@ -320,7 +320,7 @@ cancel the request. Additionally, permissioning on `navigator.serial` can
be managed by using [ses.setPermissionCheckHandler(handler)](#sessetpermissioncheckhandlerhandler) be managed by using [ses.setPermissionCheckHandler(handler)](#sessetpermissioncheckhandlerhandler)
with the `serial` permission. with the `serial` permission.
```javascript ```javascript @ts-type={fetchGrantedDevices:()=>(Array<Electron.DevicePermissionHandlerHandlerDetails['device']>)}
const { app, BrowserWindow } = require('electron') const { app, BrowserWindow } = require('electron')
let win = null let win = null
@@ -463,7 +463,7 @@ cancel the request. Additionally, permissioning on `navigator.usb` can
be further managed by using [`ses.setPermissionCheckHandler(handler)`](#sessetpermissioncheckhandlerhandler) be further managed by using [`ses.setPermissionCheckHandler(handler)`](#sessetpermissioncheckhandlerhandler)
and [`ses.setDevicePermissionHandler(handler)`](#sessetdevicepermissionhandlerhandler). and [`ses.setDevicePermissionHandler(handler)`](#sessetdevicepermissionhandlerhandler).
```javascript ```javascript @ts-type={fetchGrantedDevices:()=>(Array<Electron.DevicePermissionHandlerHandlerDetails['device']>)} @ts-type={updateGrantedDevices:(devices:Array<Electron.DevicePermissionHandlerHandlerDetails['device']>)=>void}
const { app, BrowserWindow } = require('electron') const { app, BrowserWindow } = require('electron')
let win = null let win = null
@@ -502,7 +502,7 @@ app.whenReady().then(() => {
win.webContents.session.on('select-usb-device', (event, details, callback) => { win.webContents.session.on('select-usb-device', (event, details, callback) => {
event.preventDefault() event.preventDefault()
const selectedDevice = details.deviceList.find((device) => { const selectedDevice = details.deviceList.find((device) => {
return device.vendorId === '9025' && device.productId === '67' return device.vendorId === 9025 && device.productId === 67
}) })
if (selectedDevice) { if (selectedDevice) {
// Optionally, add this to the persisted devices (updateGrantedDevices needs to be implemented by developer to persist permissions) // Optionally, add this to the persisted devices (updateGrantedDevices needs to be implemented by developer to persist permissions)
@@ -519,9 +519,8 @@ app.whenReady().then(() => {
Returns: Returns:
* `event` Event * `event` Event
* `details` Object * `device` [USBDevice](structures/usb-device.md)
* `device` [USBDevice](structures/usb-device.md) * `webContents` [WebContents](web-contents.md)
* `frame` [WebFrameMain](web-frame-main.md)
Emitted after `navigator.usb.requestDevice` has been called and Emitted after `navigator.usb.requestDevice` has been called and
`select-usb-device` has fired if a new device becomes available before `select-usb-device` has fired if a new device becomes available before
@@ -534,9 +533,8 @@ with the newly added device.
Returns: Returns:
* `event` Event * `event` Event
* `details` Object * `device` [USBDevice](structures/usb-device.md)
* `device` [USBDevice](structures/usb-device.md) * `webContents` [WebContents](web-contents.md)
* `frame` [WebFrameMain](web-frame-main.md)
Emitted after `navigator.usb.requestDevice` has been called and Emitted after `navigator.usb.requestDevice` has been called and
`select-usb-device` has fired if a device has been removed before the callback `select-usb-device` has fired if a device has been removed before the callback
@@ -550,7 +548,7 @@ Returns:
* `event` Event * `event` Event
* `details` Object * `details` Object
* `device` [USBDevice[]](structures/usb-device.md) * `device` [USBDevice](structures/usb-device.md)
* `origin` string (optional) - The origin that the device has been revoked from. * `origin` string (optional) - The origin that the device has been revoked from.
Emitted after `USBDevice.forget()` has been called. This event can be used Emitted after `USBDevice.forget()` has been called. This event can be used
@@ -757,15 +755,17 @@ Sets download saving directory. By default, the download directory will be the
Emulates network with the given configuration for the `session`. Emulates network with the given configuration for the `session`.
```javascript ```javascript
const win = new BrowserWindow()
// To emulate a GPRS connection with 50kbps throughput and 500 ms latency. // To emulate a GPRS connection with 50kbps throughput and 500 ms latency.
window.webContents.session.enableNetworkEmulation({ win.webContents.session.enableNetworkEmulation({
latency: 500, latency: 500,
downloadThroughput: 6400, downloadThroughput: 6400,
uploadThroughput: 6400 uploadThroughput: 6400
}) })
// To emulate a network outage. // To emulate a network outage.
window.webContents.session.enableNetworkEmulation({ offline: true }) win.webContents.session.enableNetworkEmulation({ offline: true })
``` ```
#### `ses.preconnect(options)` #### `ses.preconnect(options)`
@@ -1026,7 +1026,7 @@ Passing `null` instead of a function resets the handler to its default state.
* `details` Object * `details` Object
* `deviceType` string - The type of device that permission is being requested on, can be `hid`, `serial`, or `usb`. * `deviceType` string - The type of device that permission is being requested on, can be `hid`, `serial`, or `usb`.
* `origin` string - The origin URL of the device permission check. * `origin` string - The origin URL of the device permission check.
* `device` [HIDDevice](structures/hid-device.md) | [SerialPort](structures/serial-port.md)- the device that permission is being requested for. * `device` [HIDDevice](structures/hid-device.md) | [SerialPort](structures/serial-port.md) | [USBDevice](structures/usb-device.md) - the device that permission is being requested for.
Sets the handler which can be used to respond to device permission checks for the `session`. Sets the handler which can be used to respond to device permission checks for the `session`.
Returning `true` will allow the device to be permitted and `false` will reject it. Returning `true` will allow the device to be permitted and `false` will reject it.
@@ -1038,7 +1038,7 @@ Additionally, the default behavior of Electron is to store granted device permis
If longer term storage is needed, a developer can store granted device If longer term storage is needed, a developer can store granted device
permissions (eg when handling the `select-hid-device` event) and then read from that storage with `setDevicePermissionHandler`. permissions (eg when handling the `select-hid-device` event) and then read from that storage with `setDevicePermissionHandler`.
```javascript ```javascript @ts-type={fetchGrantedDevices:()=>(Array<Electron.DevicePermissionHandlerHandlerDetails['device']>)}
const { app, BrowserWindow } = require('electron') const { app, BrowserWindow } = require('electron')
let win = null let win = null
@@ -1086,9 +1086,58 @@ app.whenReady().then(() => {
win.webContents.session.on('select-hid-device', (event, details, callback) => { win.webContents.session.on('select-hid-device', (event, details, callback) => {
event.preventDefault() event.preventDefault()
const selectedDevice = details.deviceList.find((device) => { const selectedDevice = details.deviceList.find((device) => {
return device.vendorId === '9025' && device.productId === '67' return device.vendorId === 9025 && device.productId === 67
})
callback(selectedDevice?.deviceId)
})
})
```
#### `ses.setUSBProtectedClassesHandler(handler)`
* `handler` Function\<string[]> | null
* `details` Object
* `protectedClasses` string[] - The current list of protected USB classes. Possible class values are:
* `audio`
* `audio-video`
* `hid`
* `mass-storage`
* `smart-card`
* `video`
* `wireless`
Sets the handler which can be used to override which [USB classes are protected](https://wicg.github.io/webusb/#usbinterface-interface).
The return value for the handler is a string array of USB classes which should be considered protected (eg not available in the renderer). Valid values for the array are:
* `audio`
* `audio-video`
* `hid`
* `mass-storage`
* `smart-card`
* `video`
* `wireless`
Returning an empty string array from the handler will allow all USB classes; returning the passed in array will maintain the default list of protected USB classes (this is also the default behavior if a handler is not defined).
To clear the handler, call `setUSBProtectedClassesHandler(null)`.
```javascript
const { app, BrowserWindow } = require('electron')
let win = null
app.whenReady().then(() => {
win = new BrowserWindow()
win.webContents.session.setUSBProtectedClassesHandler((details) => {
// Allow all classes:
// return []
// Keep the current set of protected classes:
// return details.protectedClasses
// Selectively remove classes:
return details.protectedClasses.filter((usbClass) => {
// Exclude classes except for audio classes
return usbClass.indexOf('audio') === -1
}) })
callback(selectedPort?.deviceId)
}) })
}) })
``` ```
@@ -1127,32 +1176,32 @@ macOS does not require a handler because macOS handles the pairing
automatically. To clear the handler, call `setBluetoothPairingHandler(null)`. automatically. To clear the handler, call `setBluetoothPairingHandler(null)`.
```javascript ```javascript
const { app, BrowserWindow, session } = require('electron')
const { app, BrowserWindow, ipcMain, session } = require('electron') const path = require('path')
let bluetoothPinCallback = null
function createWindow () { function createWindow () {
let bluetoothPinCallback = null
const mainWindow = new BrowserWindow({ const mainWindow = new BrowserWindow({
webPreferences: { webPreferences: {
preload: path.join(__dirname, 'preload.js') preload: path.join(__dirname, 'preload.js')
} }
}) })
mainWindow.webContents.session.setBluetoothPairingHandler((details, callback) => {
bluetoothPinCallback = callback
// Send a IPC message to the renderer to prompt the user to confirm the pairing.
// Note that this will require logic in the renderer to handle this message and
// display a prompt to the user.
mainWindow.webContents.send('bluetooth-pairing-request', details)
})
// Listen for an IPC message from the renderer to get the response for the Bluetooth pairing.
mainWindow.webContents.ipc.on('bluetooth-pairing-response', (event, response) => {
bluetoothPinCallback(response)
})
} }
// Listen for an IPC message from the renderer to get the response for the Bluetooth pairing.
ipcMain.on('bluetooth-pairing-response', (event, response) => {
bluetoothPinCallback(response)
})
mainWindow.webContents.session.setBluetoothPairingHandler((details, callback) => {
bluetoothPinCallback = callback
// Send a IPC message to the renderer to prompt the user to confirm the pairing.
// Note that this will require logic in the renderer to handle this message and
// display a prompt to the user.
mainWindow.webContents.send('bluetooth-pairing-request', details)
})
app.whenReady().then(() => { app.whenReady().then(() => {
createWindow() createWindow()
}) })
@@ -1483,7 +1532,7 @@ app.whenReady().then(() => {
const protocol = session.fromPartition('some-partition').protocol const protocol = session.fromPartition('some-partition').protocol
if (!protocol.registerFileProtocol('atom', (request, callback) => { if (!protocol.registerFileProtocol('atom', (request, callback) => {
const url = request.url.substr(7) const url = request.url.substr(7)
callback({ path: path.normalize(`${__dirname}/${url}`) }) callback({ path: path.normalize(path.join(__dirname, url)) })
})) { })) {
console.error('Failed to register protocol') console.error('Failed to register protocol')
} }

View File

@@ -2,9 +2,9 @@
* `portId` string - Unique identifier for the port. * `portId` string - Unique identifier for the port.
* `portName` string - Name of the port. * `portName` string - Name of the port.
* `displayName` string - A string suitable for display to the user for describing this device. * `displayName` string (optional) - A string suitable for display to the user for describing this device.
* `vendorId` string - Optional USB vendor ID. * `vendorId` string (optional) - The USB vendor ID.
* `productId` string - Optional USB product ID. * `productId` string (optional) - The USB product ID.
* `serialNumber` string - The USB device serial number. * `serialNumber` string (optional) - The USB device serial number.
* `usbDriverName` string (optional) - Represents a single serial port on macOS can be enumerated by multiple drivers. * `usbDriverName` string (optional) _macOS_ - Represents a single serial port on macOS can be enumerated by multiple drivers.
* `deviceInstanceId` string (optional) - A stable identifier on Windows that can be used for device permissions. * `deviceInstanceId` string (optional) _Windows_ - A stable identifier on Windows that can be used for device permissions.

View File

@@ -228,10 +228,10 @@ const win = new BrowserWindow(browserOptions)
// Navigate. // Navigate.
if (browserOptions.transparent) { if (browserOptions.transparent) {
win.loadURL(`file://${__dirname}/index.html`) win.loadFile('index.html')
} else { } else {
// No transparency, so we load a fallback that uses basic styles. // No transparency, so we load a fallback that uses basic styles.
win.loadURL(`file://${__dirname}/fallback.html`) win.loadFile('fallback.html')
} }
``` ```

View File

@@ -87,12 +87,12 @@ const { TouchBarLabel, TouchBarButton, TouchBarSpacer } = TouchBar
let spinning = false let spinning = false
// Reel labels // Reel labels
const reel1 = new TouchBarLabel() const reel1 = new TouchBarLabel({ label: '' })
const reel2 = new TouchBarLabel() const reel2 = new TouchBarLabel({ label: '' })
const reel3 = new TouchBarLabel() const reel3 = new TouchBarLabel({ label: '' })
// Spin result label // Spin result label
const result = new TouchBarLabel() const result = new TouchBarLabel({ label: '' })
// Spin button // Spin button
const spin = new TouchBarButton({ const spin = new TouchBarButton({

View File

@@ -65,28 +65,28 @@ for all windows, webviews, opened devtools, and devtools extension background pa
### `webContents.getFocusedWebContents()` ### `webContents.getFocusedWebContents()`
Returns `WebContents` | null - The web contents that is focused in this application, otherwise Returns `WebContents | null` - The web contents that is focused in this application, otherwise
returns `null`. returns `null`.
### `webContents.fromId(id)` ### `webContents.fromId(id)`
* `id` Integer * `id` Integer
Returns `WebContents` | undefined - A WebContents instance with the given ID, or Returns `WebContents | undefined` - A WebContents instance with the given ID, or
`undefined` if there is no WebContents associated with the given ID. `undefined` if there is no WebContents associated with the given ID.
### `webContents.fromFrame(frame)` ### `webContents.fromFrame(frame)`
* `frame` WebFrameMain * `frame` WebFrameMain
Returns `WebContents` | undefined - A WebContents instance with the given WebFrameMain, or Returns `WebContents | undefined` - A WebContents instance with the given WebFrameMain, or
`undefined` if there is no WebContents associated with the given WebFrameMain. `undefined` if there is no WebContents associated with the given WebFrameMain.
### `webContents.fromDevToolsTargetId(targetId)` ### `webContents.fromDevToolsTargetId(targetId)`
* `targetId` string - The Chrome DevTools Protocol [TargetID](https://chromedevtools.github.io/devtools-protocol/tot/Target/#type-TargetID) associated with the WebContents instance. * `targetId` string - The Chrome DevTools Protocol [TargetID](https://chromedevtools.github.io/devtools-protocol/tot/Target/#type-TargetID) associated with the WebContents instance.
Returns `WebContents` | undefined - A WebContents instance with the given TargetID, or Returns `WebContents | undefined` - A WebContents instance with the given TargetID, or
`undefined` if there is no WebContents associated with the given TargetID. `undefined` if there is no WebContents associated with the given TargetID.
When communicating with the [Chrome DevTools Protocol](https://chromedevtools.github.io/devtools-protocol/), When communicating with the [Chrome DevTools Protocol](https://chromedevtools.github.io/devtools-protocol/),
@@ -98,7 +98,7 @@ async function lookupTargetId (browserWindow) {
await wc.debugger.attach('1.3') await wc.debugger.attach('1.3')
const { targetInfo } = await wc.debugger.sendCommand('Target.getTargetInfo') const { targetInfo } = await wc.debugger.sendCommand('Target.getTargetInfo')
const { targetId } = targetInfo const { targetId } = targetInfo
const targetWebContents = await webContents.fromDevToolsTargetId(targetId) const targetWebContents = await wc.fromDevToolsTargetId(targetId)
} }
``` ```
@@ -601,6 +601,7 @@ window.
Returns: Returns:
* `event` Event
* `url` string - URL of the link that was clicked or selected. * `url` string - URL of the link that was clicked or selected.
Emitted when a link is clicked in DevTools or 'Open in new tab' is selected for a link in its context menu. Emitted when a link is clicked in DevTools or 'Open in new tab' is selected for a link in its context menu.
@@ -736,14 +737,16 @@ Returns:
* `size` [Size](structures/size.md) (optional) - the size of the `image`. * `size` [Size](structures/size.md) (optional) - the size of the `image`.
* `hotspot` [Point](structures/point.md) (optional) - coordinates of the custom cursor's hotspot. * `hotspot` [Point](structures/point.md) (optional) - coordinates of the custom cursor's hotspot.
Emitted when the cursor's type changes. The `type` parameter can be `default`, Emitted when the cursor's type changes. The `type` parameter can be `pointer`,
`crosshair`, `pointer`, `text`, `wait`, `help`, `e-resize`, `n-resize`, `crosshair`, `hand`, `text`, `wait`, `help`, `e-resize`, `n-resize`, `ne-resize`,
`ne-resize`, `nw-resize`, `s-resize`, `se-resize`, `sw-resize`, `w-resize`, `nw-resize`, `s-resize`, `se-resize`, `sw-resize`, `w-resize`, `ns-resize`, `ew-resize`,
`ns-resize`, `ew-resize`, `nesw-resize`, `nwse-resize`, `col-resize`, `nesw-resize`, `nwse-resize`, `col-resize`, `row-resize`, `m-panning`, `m-panning-vertical`,
`row-resize`, `m-panning`, `e-panning`, `n-panning`, `ne-panning`, `nw-panning`, `m-panning-horizontal`, `e-panning`, `n-panning`, `ne-panning`, `nw-panning`, `s-panning`,
`s-panning`, `se-panning`, `sw-panning`, `w-panning`, `move`, `vertical-text`, `se-panning`, `sw-panning`, `w-panning`, `move`, `vertical-text`, `cell`, `context-menu`,
`cell`, `context-menu`, `alias`, `progress`, `nodrop`, `copy`, `none`, `alias`, `progress`, `nodrop`, `copy`, `none`, `not-allowed`, `zoom-in`, `zoom-out`, `grab`,
`not-allowed`, `zoom-in`, `zoom-out`, `grab`, `grabbing` or `custom`. `grabbing`, `custom`, `null`, `drag-drop-none`, `drag-drop-move`, `drag-drop-copy`,
`drag-drop-link`, `ns-no-resize`, `ew-no-resize`, `nesw-no-resize`, `nwse-no-resize`,
or `default`.
If the `type` parameter is `custom`, the `image` parameter will hold the custom If the `type` parameter is `custom`, the `image` parameter will hold the custom
cursor image in a [`NativeImage`](native-image.md), and `scale`, `size` and `hotspot` will hold cursor image in a [`NativeImage`](native-image.md), and `scale`, `size` and `hotspot` will hold
@@ -863,7 +866,7 @@ app.whenReady().then(() => {
}) })
if (!result) { if (!result) {
// The device wasn't found so we need to either wait longer (eg until the // The device wasn't found so we need to either wait longer (eg until the
// device is turned on) or cancel the request by calling the callback // device is turned on) or cancel the request by calling the callback
// with an empty string. // with an empty string.
callback('') callback('')
} else { } else {
@@ -1017,9 +1020,9 @@ e.g. the `http://` or `file://`. If the load should bypass http cache then
use the `pragma` header to achieve it. use the `pragma` header to achieve it.
```javascript ```javascript
const { webContents } = require('electron') const win = new BrowserWindow()
const options = { extraHeaders: 'pragma: no-cache\n' } const options = { extraHeaders: 'pragma: no-cache\n' }
webContents.loadURL('https://github.com', options) win.webContents.loadURL('https://github.com', options)
``` ```
#### `contents.loadFile(filePath[, options])` #### `contents.loadFile(filePath[, options])`
@@ -1049,6 +1052,7 @@ an app structure like this:
Would require code like this Would require code like this
```js ```js
const win = new BrowserWindow()
win.loadFile('src/index.html') win.loadFile('src/index.html')
``` ```
@@ -1185,7 +1189,9 @@ when this process is unstable or unusable, for instance in order to recover
from the `unresponsive` event. from the `unresponsive` event.
```js ```js
contents.on('unresponsive', async () => { const win = new BrowserWindow()
win.webContents.on('unresponsive', async () => {
const { response } = await dialog.showMessageBox({ const { response } = await dialog.showMessageBox({
message: 'App X has become unresponsive', message: 'App X has become unresponsive',
title: 'Do you want to try forcefully reloading the app?', title: 'Do you want to try forcefully reloading the app?',
@@ -1193,8 +1199,8 @@ contents.on('unresponsive', async () => {
cancelId: 1 cancelId: 1
}) })
if (response === 0) { if (response === 0) {
contents.forcefullyCrashRenderer() win.webContents.forcefullyCrashRenderer()
contents.reload() win.webContents.reload()
} }
}) })
``` ```
@@ -1221,8 +1227,9 @@ Injects CSS into the current web page and returns a unique key for the inserted
stylesheet. stylesheet.
```js ```js
contents.on('did-finish-load', () => { const win = new BrowserWindow()
contents.insertCSS('html, body { background-color: #f00; }') win.webContents.on('did-finish-load', () => {
win.webContents.insertCSS('html, body { background-color: #f00; }')
}) })
``` ```
@@ -1236,9 +1243,11 @@ Removes the inserted CSS from the current web page. The stylesheet is identified
by its key, which is returned from `contents.insertCSS(css)`. by its key, which is returned from `contents.insertCSS(css)`.
```js ```js
contents.on('did-finish-load', async () => { const win = new BrowserWindow()
const key = await contents.insertCSS('html, body { background-color: #f00; }')
contents.removeInsertedCSS(key) win.webContents.on('did-finish-load', async () => {
const key = await win.webContents.insertCSS('html, body { background-color: #f00; }')
win.webContents.removeInsertedCSS(key)
}) })
``` ```
@@ -1259,7 +1268,9 @@ this limitation.
Code execution will be suspended until web page stop loading. Code execution will be suspended until web page stop loading.
```js ```js
contents.executeJavaScript('fetch("https://jsonplaceholder.typicode.com/users/1").then(resp => resp.json())', true) const win = new BrowserWindow()
win.webContents.executeJavaScript('fetch("https://jsonplaceholder.typicode.com/users/1").then(resp => resp.json())', true)
.then((result) => { .then((result) => {
console.log(result) // Will be the JSON object from the fetch call console.log(result) // Will be the JSON object from the fetch call
}) })
@@ -1370,7 +1381,8 @@ Sets the maximum and minimum pinch-to-zoom level.
> **NOTE**: Visual zoom is disabled by default in Electron. To re-enable it, call: > **NOTE**: Visual zoom is disabled by default in Electron. To re-enable it, call:
> >
> ```js > ```js
> contents.setVisualZoomLevelLimits(1, 3) > const win = new BrowserWindow()
> win.webContents.setVisualZoomLevelLimits(1, 3)
> ``` > ```
#### `contents.undo()` #### `contents.undo()`
@@ -1389,6 +1401,10 @@ Executes the editing command `cut` in web page.
Executes the editing command `copy` in web page. Executes the editing command `copy` in web page.
#### `contents.centerSelection()`
Centers the current text selection in web page.
#### `contents.copyImageAt(x, y)` #### `contents.copyImageAt(x, y)`
* `x` Integer * `x` Integer
@@ -1416,6 +1432,46 @@ Executes the editing command `selectAll` in web page.
Executes the editing command `unselect` in web page. Executes the editing command `unselect` in web page.
#### `contents.scrollToTop()`
Scrolls to the top of the current `webContents`.
#### `contents.scrollToBottom()`
Scrolls to the bottom of the current `webContents`.
#### `contents.adjustSelection(options)`
* `options` Object
* `start` Number (optional) - Amount to shift the start index of the current selection.
* `end` Number (optional) - Amount to shift the end index of the current selection.
Adjusts the current text selection starting and ending points in the focused frame by the given amounts. A negative amount moves the selection towards the beginning of the document, and a positive amount moves the selection towards the end of the document.
Example:
```js
const win = new BrowserWindow()
// Adjusts the beginning of the selection 1 letter forward,
// and the end of the selection 5 letters forward.
win.webContents.adjustSelection({ start: 1, end: 5 })
// Adjusts the beginning of the selection 2 letters forward,
// and the end of the selection 3 letters backward.
win.webContents.adjustSelection({ start: 2, end: -3 })
```
For a call of `win.webContents.adjustSelection({ start: 1, end: 5 })`
Before:
<img width="487" alt="Image Before Text Selection Adjustment" src="https://user-images.githubusercontent.com/2036040/231761306-cd4e7b15-c2ed-46cf-8e80-10811f6de83e.png">
After:
<img width="487" alt="Image After Text Selection Adjustment" src="https://user-images.githubusercontent.com/2036040/231761169-887eb8ef-06fb-46e4-9efa-898bcb0d6a2b.png">
#### `contents.replace(text)` #### `contents.replace(text)`
* `text` string * `text` string
@@ -1461,12 +1517,12 @@ can be obtained by subscribing to [`found-in-page`](web-contents.md#event-found-
Stops any `findInPage` request for the `webContents` with the provided `action`. Stops any `findInPage` request for the `webContents` with the provided `action`.
```javascript ```javascript
const { webContents } = require('electron') const win = new BrowserWindow()
webContents.on('found-in-page', (event, result) => { win.webContents.on('found-in-page', (event, result) => {
if (result.finalUpdate) webContents.stopFindInPage('clearSelection') if (result.finalUpdate) win.webContents.stopFindInPage('clearSelection')
}) })
const requestId = webContents.findInPage('api') const requestId = win.webContents.findInPage('api')
console.log(requestId) console.log(requestId)
``` ```
@@ -1546,6 +1602,7 @@ Use `page-break-before: always;` CSS style to force to print to a new page.
Example usage: Example usage:
```js ```js
const win = new BrowserWindow()
const options = { const options = {
silent: true, silent: true,
deviceName: 'My-Printer', deviceName: 'My-Printer',
@@ -1842,8 +1899,9 @@ For example:
```js ```js
// Main process // Main process
const win = new BrowserWindow()
const { port1, port2 } = new MessageChannelMain() const { port1, port2 } = new MessageChannelMain()
webContents.postMessage('port', { message: 'hello' }, [port1]) win.webContents.postMessage('port', { message: 'hello' }, [port1])
// Renderer process // Renderer process
ipcRenderer.on('port', (e, msg) => { ipcRenderer.on('port', (e, msg) => {

View File

@@ -128,8 +128,9 @@ For example:
```js ```js
// Main process // Main process
const win = new BrowserWindow()
const { port1, port2 } = new MessageChannelMain() const { port1, port2 } = new MessageChannelMain()
webContents.mainFrame.postMessage('port', { message: 'hello' }, [port1]) win.webContents.mainFrame.postMessage('port', { message: 'hello' }, [port1])
// Renderer process // Renderer process
ipcRenderer.on('port', (e, msg) => { ipcRenderer.on('port', (e, msg) => {

View File

@@ -96,13 +96,12 @@ with an array of misspelt words when complete.
An example of using [node-spellchecker][spellchecker] as provider: An example of using [node-spellchecker][spellchecker] as provider:
```javascript ```javascript @ts-expect-error=[2,6]
const { webFrame } = require('electron') const { webFrame } = require('electron')
const spellChecker = require('spellchecker') const spellChecker = require('spellchecker')
webFrame.setSpellCheckProvider('en-US', { webFrame.setSpellCheckProvider('en-US', {
spellCheck (words, callback) { spellCheck (words, callback) {
setTimeout(() => { setTimeout(() => {
const spellchecker = require('spellchecker')
const misspelled = words.filter(x => spellchecker.isMisspelled(x)) const misspelled = words.filter(x => spellchecker.isMisspelled(x))
callback(misspelled) callback(misspelled)
}, 0) }, 0)

View File

@@ -184,6 +184,8 @@ page is loaded, use the `setUserAgent` method to change the user agent.
A `boolean`. When this attribute is present the guest page will have web security disabled. A `boolean`. When this attribute is present the guest page will have web security disabled.
Web security is enabled by default. Web security is enabled by default.
This value can only be modified before the first navigation.
### `partition` ### `partition`
```html ```html
@@ -253,7 +255,7 @@ The `webview` tag has the following methods:
**Example** **Example**
```javascript ```javascript @ts-expect-error=[3]
const webview = document.querySelector('webview') const webview = document.querySelector('webview')
webview.addEventListener('dom-ready', () => { webview.addEventListener('dom-ready', () => {
webview.openDevTools() webview.openDevTools()
@@ -463,6 +465,10 @@ Executes editing command `cut` in page.
Executes editing command `copy` in page. Executes editing command `copy` in page.
#### `<webview>.centerSelection()`
Centers the current text selection in page.
### `<webview>.paste()` ### `<webview>.paste()`
Executes editing command `paste` in page. Executes editing command `paste` in page.
@@ -483,6 +489,25 @@ Executes editing command `selectAll` in page.
Executes editing command `unselect` in page. Executes editing command `unselect` in page.
#### `<webview>.scrollToTop()`
Scrolls to the top of the current `<webview>`.
#### `<webview>.scrollToBottom()`
Scrolls to the bottom of the current `<webview>`.
#### `<webview>.adjustSelection(options)`
* `options` Object
* `start` Number (optional) - Amount to shift the start index of the current selection.
* `end` Number (optional) - Amount to shift the end index of the current selection.
Adjusts the current text selection starting and ending points in the focused frame by the given amounts. A negative amount moves the selection towards the beginning of the document, and a positive amount moves the selection towards the end of the document.
See [`webContents.adjustSelection`](web-contents.md#contentsadjustselectionoptions) for
examples.
### `<webview>.replace(text)` ### `<webview>.replace(text)`
* `text` string * `text` string
@@ -774,7 +799,7 @@ Fired when the guest window logs a console message.
The following example code forwards all log messages to the embedder's console The following example code forwards all log messages to the embedder's console
without regard for log level or other properties. without regard for log level or other properties.
```javascript ```javascript @ts-expect-error=[3]
const webview = document.querySelector('webview') const webview = document.querySelector('webview')
webview.addEventListener('console-message', (e) => { webview.addEventListener('console-message', (e) => {
console.log('Guest page logged a message:', e.message) console.log('Guest page logged a message:', e.message)
@@ -795,7 +820,7 @@ Returns:
Fired when a result is available for Fired when a result is available for
[`webview.findInPage`](#webviewfindinpagetext-options) request. [`webview.findInPage`](#webviewfindinpagetext-options) request.
```javascript ```javascript @ts-expect-error=[3,6]
const webview = document.querySelector('webview') const webview = document.querySelector('webview')
webview.addEventListener('found-in-page', (e) => { webview.addEventListener('found-in-page', (e) => {
webview.stopFindInPage('keepSelection') webview.stopFindInPage('keepSelection')
@@ -920,7 +945,7 @@ Fired when the guest page attempts to close itself.
The following example code navigates the `webview` to `about:blank` when the The following example code navigates the `webview` to `about:blank` when the
guest attempts to close itself. guest attempts to close itself.
```javascript ```javascript @ts-expect-error=[3]
const webview = document.querySelector('webview') const webview = document.querySelector('webview')
webview.addEventListener('close', () => { webview.addEventListener('close', () => {
webview.src = 'about:blank' webview.src = 'about:blank'
@@ -940,7 +965,7 @@ Fired when the guest page has sent an asynchronous message to embedder page.
With `sendToHost` method and `ipc-message` event you can communicate With `sendToHost` method and `ipc-message` event you can communicate
between guest page and embedder page: between guest page and embedder page:
```javascript ```javascript @ts-expect-error=[4,7]
// In embedder page. // In embedder page.
const webview = document.querySelector('webview') const webview = document.querySelector('webview')
webview.addEventListener('ipc-message', (event) => { webview.addEventListener('ipc-message', (event) => {

View File

@@ -61,6 +61,44 @@ protocol.handle('some-protocol', () => {
}) })
``` ```
### Deprecated: `BrowserWindow.setTrafficLightPosition(position)`
`BrowserWindow.setTrafficLightPosition(position)` has been deprecated, the
`BrowserWindow.setWindowButtonPosition(position)` API should be used instead
which accepts `null` instead of `{ x: 0, y: 0 }` to reset the position to
system default.
```js
// Deprecated in Electron 25
win.setTrafficLightPosition({ x: 10, y: 10 })
win.setTrafficLightPosition({ x: 0, y: 0 })
// Replace with
win.setWindowButtonPosition({ x: 10, y: 10 })
win.setWindowButtonPosition(null)
```
### Deprecated: `BrowserWindow.getTrafficLightPosition()`
`BrowserWindow.getTrafficLightPosition()` has been deprecated, the
`BrowserWindow.getWindowButtonPosition()` API should be used instead
which returns `null` instead of `{ x: 0, y: 0 }` when there is no custom
position.
```js
// Deprecated in Electron 25
const pos = win.getTrafficLightPosition()
if (pos.x === 0 && pos.y === 0) {
// No custom position.
}
// Replace with
const ret = win.getWindowButtonPosition()
if (ret === null) {
// No custom position.
}
```
## Planned Breaking API Changes (24.0) ## Planned Breaking API Changes (24.0)
### API Changed: `nativeImage.createThumbnailFromPath(path, size)` ### API Changed: `nativeImage.createThumbnailFromPath(path, size)`
@@ -98,44 +136,6 @@ nativeImage.createThumbnailFromPath(imagePath, size).then(result => {
}) })
``` ```
### Deprecated: `BrowserWindow.setTrafficLightPosition(position)`
`BrowserWindow.setTrafficLightPosition(position)` has been deprecated, the
`BrowserWindow.setWindowButtonPosition(position)` API should be used instead
which accepts `null` instead of `{ x: 0, y: 0 }` to reset the position to
system default.
```js
// Removed in Electron 24
win.setTrafficLightPosition({ x: 10, y: 10 })
win.setTrafficLightPosition({ x: 0, y: 0 })
// Replace with
win.setWindowButtonPosition({ x: 10, y: 10 })
win.setWindowButtonPosition(null)
```
### Deprecated: `BrowserWindow.getTrafficLightPosition()`
`BrowserWindow.getTrafficLightPosition()` has been deprecated, the
`BrowserWindow.getWindowButtonPosition()` API should be used instead
which returns `null` instead of `{ x: 0, y: 0 }` when there is no custom
position.
```js
// Removed in Electron 24
const pos = win.getTrafficLightPosition()
if (pos.x === 0 && pos.y === 0) {
// No custom position.
}
// Replace with
const ret = win.getWindowButtonPosition()
if (ret === null) {
// No custom position.
}
```
## Planned Breaking API Changes (23.0) ## Planned Breaking API Changes (23.0)
### Behavior Changed: Draggable Regions on macOS ### Behavior Changed: Draggable Regions on macOS
@@ -278,6 +278,39 @@ webContents.setWindowOpenHandler((details) => {
}) })
``` ```
### Removed: `<webview>` `new-window` event
The `new-window` event of `<webview>` has been removed. There is no direct replacement.
```js
// Removed in Electron 22
webview.addEventListener('new-window', (event) => {})
```
```javascript fiddle='docs/fiddles/ipc/webview-new-window'
// Replace with
// main.js
mainWindow.webContents.on('did-attach-webview', (event, wc) => {
wc.setWindowOpenHandler((details) => {
mainWindow.webContents.send('webview-new-window', wc.id, details)
return { action: 'deny' }
})
})
// preload.js
const { ipcRenderer } = require('electron')
ipcRenderer.on('webview-new-window', (e, webContentsId, details) => {
console.log('webview-new-window', webContentsId, details)
document.getElementById('webview').dispatchEvent(new Event('new-window'))
})
// renderer.js
document.getElementById('webview').addEventListener('new-window', () => {
console.log('got new-window event')
})
```
### Deprecated: BrowserWindow `scroll-touch-*` events ### Deprecated: BrowserWindow `scroll-touch-*` events
The `scroll-touch-begin`, `scroll-touch-end` and `scroll-touch-edge` events on The `scroll-touch-begin`, `scroll-touch-end` and `scroll-touch-edge` events on

View File

@@ -1,62 +0,0 @@
# Updating an Appveyor Azure Image
Electron CI on Windows uses AppVeyor, which in turn uses Azure VM images to run. Occasionally, these VM images need to be updated due to changes in Chromium requirements. In order to update you will need [PowerShell](https://learn.microsoft.com/en-us/powershell/scripting/install/installing-powershell?view=powershell-7.3&viewFallbackFrom=powershell-6) and the [Azure PowerShell module](https://learn.microsoft.com/en-us/powershell/azure/install-az-ps?view=azps-9.5.0&viewFallbackFrom=azps-1.8.0).
Occasionally we need to update these images owing to changes in Chromium or other miscellaneous build requirement changes.
Example Use Case:
* We need `VS15.9` and we have `VS15.7` installed; this would require us to update an Azure image.
1. Identify the image you wish to modify.
* In [appveyor.yml](https://github.com/electron/electron/blob/main/appveyor.yml), the image is identified by the property _image_.
* The names used correspond to the _"images"_ defined for a build cloud, eg the [libcc-20 cloud](https://windows-ci.electronjs.org/build-clouds/8).
* Find the image you wish to modify in the build cloud and make note of the **VHD Blob Path** for that image, which is the value for that corresponding key.
* You will need this URI path to copy into a new image.
* You will also need the storage account name which is labeled in AppVeyor as the **Disk Storage Account Name**
2. Get the Azure storage account key
* Log into Azure using credentials stored in LastPass (under Azure Enterprise) and then find the storage account corresponding to the name found in AppVeyor.
* Example, for `appveyorlibccbuilds` **Disk Storage Account Name** you'd look for `appveyorlibccbuilds` in the list of storage accounts @ Home < Storage Accounts
* Click into it and look for `Access Keys`, and then you can use any of the keys present in the list.
3. Get the full virtual machine image URI from Azure
* Navigate to Home < Storage Accounts < `$ACCT_NAME` < Blobs < Images
* In the following list, look for the VHD path name you got from Appveyor and then click on it.
* Copy the whole URL from the top of the subsequent window.
4. Copy the image using the [Copy Master Image PowerShell script](https://github.com/appveyor/ci/blob/master/scripts/enterprise/copy-master-image-azure.ps1).
* It is essential to copy the VM because if you spin up a VM against an image that image cannot at the same time be used by AppVeyor.
* Use the storage account name, key, and URI obtained from Azure to run this script.
* See Step 3 for URI & when prompted, press enter to use same storage account as destination.
* Use default destination container name `(images)`
* Also, when naming the copy, use a name that indicates what the new image will contain (if that has changed) and date stamp.
* Ex. `libcc-20core-vs2017-15.9-2019-04-15.vhd`
* Go into Azure and get the URI for the newly created image as described in a previous step
5. Spin up a new VM using the [Create Master VM from VHD PowerShell](https://github.com/appveyor/ci/blob/master/scripts/enterprise/create_master_vm_from_vhd.ps1).
* From PowerShell, execute `ps1` file with `./create_master_vm_from_vhd.ps1`
* You will need the credential information available in the AppVeyor build cloud definition.
* This includes:
* Client ID
* Client Secret
* Tenant ID
* Subscription ID
* Resource Group
* Virtual Network
* You will also need to specify
* Master VM name - just a unique name to identify the temporary VM
* Master VM size - use `Standard_F32s_v2`
* Master VHD URI - use URI obtained @ end of previous step
* Location use `East US`
6. Log back into Azure and find the VM you just created in Home < Virtual Machines < `$YOUR_NEW_VM`
* You can download a RDP (Remote Desktop) file to access the VM.
7. Using Microsoft Remote Desktop, click `Connect` to connect to the VM.
* Credentials for logging into the VM are found in LastPass under the `AppVeyor Enterprise master VM` credentials.
8. Modify the VM as required.
9. Shut down the VM and then delete it in Azure.
10. Add the new image to the Appveyor Cloud settings or modify an existing image to point to the new VHD.

View File

@@ -49,7 +49,7 @@ formatted correctly.
* Write [standard](https://www.npmjs.com/package/standard) JavaScript style. * Write [standard](https://www.npmjs.com/package/standard) JavaScript style.
* File names should be concatenated with `-` instead of `_`, e.g. * File names should be concatenated with `-` instead of `_`, e.g.
`file-name.js` rather than `file_name.js`, because in `file-name.js` rather than `file_name.js`, because in
[github/atom](https://github.com/github/atom) module names are usually in [atom/atom](https://github.com/atom/atom) module names are usually in
the `module-name` form. This rule only applies to `.js` files. the `module-name` form. This rule only applies to `.js` files.
* Use newer ES6/ES2015 syntax where appropriate * Use newer ES6/ES2015 syntax where appropriate
* [`const`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/const) * [`const`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/const)

View File

@@ -2,5 +2,5 @@ const NOTIFICATION_TITLE = 'Title'
const NOTIFICATION_BODY = 'Notification from the Renderer process. Click to log to console.' const NOTIFICATION_BODY = 'Notification from the Renderer process. Click to log to console.'
const CLICK_MESSAGE = 'Notification clicked!' const CLICK_MESSAGE = 'Notification clicked!'
new Notification(NOTIFICATION_TITLE, { body: NOTIFICATION_BODY }) new window.Notification(NOTIFICATION_TITLE, { body: NOTIFICATION_BODY })
.onclick = () => document.getElementById('output').innerText = CLICK_MESSAGE .onclick = () => { document.getElementById('output').innerText = CLICK_MESSAGE }

View File

@@ -4,16 +4,31 @@ const path = require('path')
app.disableHardwareAcceleration() app.disableHardwareAcceleration()
let win function createWindow () {
const win = new BrowserWindow({
width: 800,
height: 600,
webPreferences: {
offscreen: true
}
})
app.whenReady().then(() => {
win = new BrowserWindow({ webPreferences: { offscreen: true } })
win.loadURL('https://github.com') win.loadURL('https://github.com')
win.webContents.on('paint', (event, dirty, image) => { win.webContents.on('paint', (event, dirty, image) => {
fs.writeFileSync('ex.png', image.toPNG()) fs.writeFileSync('ex.png', image.toPNG())
}) })
win.webContents.setFrameRate(60) win.webContents.setFrameRate(60)
console.log(`The screenshot has been successfully saved to ${path.join(process.cwd(), 'ex.png')}`) console.log(`The screenshot has been successfully saved to ${path.join(process.cwd(), 'ex.png')}`)
}
app.whenReady().then(() => {
createWindow()
app.on('activate', () => {
if (BrowserWindow.getAllWindows().length === 0) {
createWindow()
}
})
}) })
app.on('window-all-closed', () => { app.on('window-all-closed', () => {
@@ -21,9 +36,3 @@ app.on('window-all-closed', () => {
app.quit() app.quit()
} }
}) })
app.on('activate', () => {
if (BrowserWindow.getAllWindows().length === 0) {
createWindow()
}
})

View File

@@ -1,7 +1,7 @@
const { app, BrowserWindow, ipcMain } = require('electron') const { app, BrowserWindow, ipcMain } = require('electron')
const path = require('path') const path = require('path')
let bluetoothPinCallback let bluetoothPinCallback
let selectBluetoothCallback let selectBluetoothCallback
function createWindow () { function createWindow () {
@@ -24,13 +24,12 @@ function createWindow () {
} else { } else {
// The device wasn't found so we need to either wait longer (eg until the // The device wasn't found so we need to either wait longer (eg until the
// device is turned on) or until the user cancels the request // device is turned on) or until the user cancels the request
} }
}) })
ipcMain.on('cancel-bluetooth-request', (event) => { ipcMain.on('cancel-bluetooth-request', (event) => {
selectBluetoothCallback('') selectBluetoothCallback('')
}) })
// Listen for a message from the renderer to get the response for the Bluetooth pairing. // Listen for a message from the renderer to get the response for the Bluetooth pairing.
ipcMain.on('bluetooth-pairing-response', (event, response) => { ipcMain.on('bluetooth-pairing-response', (event, response) => {

View File

@@ -7,7 +7,7 @@ async function testIt () {
document.getElementById('clickme').addEventListener('click', testIt) document.getElementById('clickme').addEventListener('click', testIt)
function cancelRequest() { function cancelRequest () {
window.electronAPI.cancelBluetoothRequest() window.electronAPI.cancelBluetoothRequest()
} }
@@ -18,15 +18,15 @@ window.electronAPI.bluetoothPairingRequest((event, details) => {
switch (details.pairingKind) { switch (details.pairingKind) {
case 'confirm': { case 'confirm': {
response.confirmed = confirm(`Do you want to connect to device ${details.deviceId}?`) response.confirmed = window.confirm(`Do you want to connect to device ${details.deviceId}?`)
break break
} }
case 'confirmPin': { case 'confirmPin': {
response.confirmed = confirm(`Does the pin ${details.pin} match the pin displayed on device ${details.deviceId}?`) response.confirmed = window.confirm(`Does the pin ${details.pin} match the pin displayed on device ${details.deviceId}?`)
break break
} }
case 'providePin': { case 'providePin': {
const pin = prompt(`Please provide a pin for ${details.deviceId}.`) const pin = window.prompt(`Please provide a pin for ${details.deviceId}.`)
if (pin) { if (pin) {
response.pin = pin response.pin = pin
response.confirmed = true response.confirmed = true

View File

@@ -23,6 +23,7 @@ function createWindow () {
if (portList && portList.length > 0) { if (portList && portList.length > 0) {
callback(portList[0].portId) callback(portList[0].portId)
} else { } else {
// eslint-disable-next-line n/no-callback-literal
callback('') // Could not find any matching devices callback('') // Could not find any matching devices
} }
}) })

View File

@@ -24,9 +24,7 @@ function createWindow () {
event.preventDefault() event.preventDefault()
if (details.deviceList && details.deviceList.length > 0) { if (details.deviceList && details.deviceList.length > 0) {
const deviceToReturn = details.deviceList.find((device) => { const deviceToReturn = details.deviceList.find((device) => {
if (!grantedDeviceThroughPermHandler || (device.deviceId !== grantedDeviceThroughPermHandler.deviceId)) { return !grantedDeviceThroughPermHandler || (device.deviceId !== grantedDeviceThroughPermHandler.deviceId)
return true
}
}) })
if (deviceToReturn) { if (deviceToReturn) {
callback(deviceToReturn.deviceId) callback(deviceToReturn.deviceId)
@@ -53,6 +51,13 @@ function createWindow () {
} }
}) })
mainWindow.webContents.session.setUSBProtectedClassesHandler((details) => {
return details.protectedClasses.filter((usbClass) => {
// Exclude classes except for audio classes
return usbClass.indexOf('audio') === -1
})
})
mainWindow.loadFile('index.html') mainWindow.loadFile('index.html')
} }

View File

@@ -20,7 +20,7 @@ async function testIt () {
const grantedDevice = await navigator.usb.requestDevice({ const grantedDevice = await navigator.usb.requestDevice({
filters: [] filters: []
}) })
grantedDeviceList += `<hr>${getDeviceDetails(device)}</hr>` grantedDeviceList += `<hr>${getDeviceDetails(grantedDevice)}</hr>`
} catch (ex) { } catch (ex) {
if (ex.name === 'NotFoundError') { if (ex.name === 'NotFoundError') {
grantedDeviceList = noDevicesFoundMsg grantedDeviceList = noDevicesFoundMsg

View File

@@ -3,9 +3,7 @@ const path = require('path')
async function handleFileOpen () { async function handleFileOpen () {
const { canceled, filePaths } = await dialog.showOpenDialog() const { canceled, filePaths } = await dialog.showOpenDialog()
if (canceled) { if (!canceled) {
} else {
return filePaths[0] return filePaths[0]
} }
} }

View File

@@ -0,0 +1,3 @@
<body>
<a href="child.html" target="_blank">new window</a>
</body>

View File

@@ -0,0 +1,4 @@
<body>
<webview id=webview src="child.html" allowpopups></webview>
<script src="renderer.js"></script>
</body>

View File

@@ -0,0 +1,51 @@
// Modules to control application life and create native browser window
const { app, BrowserWindow } = require('electron')
const path = require('path')
function createWindow () {
// Create the browser window.
const mainWindow = new BrowserWindow({
width: 800,
height: 600,
webPreferences: {
preload: path.join(__dirname, 'preload.js'),
webviewTag: true
}
})
mainWindow.webContents.on('did-attach-webview', (event, wc) => {
wc.setWindowOpenHandler((details) => {
mainWindow.webContents.send('webview-new-window', wc.id, details)
return { action: 'deny' }
})
})
// and load the index.html of the app.
mainWindow.loadFile('index.html')
// Open the DevTools.
// mainWindow.webContents.openDevTools()
}
// This method will be called when Electron has finished
// initialization and is ready to create browser windows.
// Some APIs can only be used after this event occurs.
app.whenReady().then(() => {
createWindow()
app.on('activate', function () {
// On macOS it's common to re-create a window in the app when the
// dock icon is clicked and there are no other windows open.
if (BrowserWindow.getAllWindows().length === 0) createWindow()
})
})
// Quit when all windows are closed, except on macOS. There, it's common
// for applications and their menu bar to stay active until the user quits
// explicitly with Cmd + Q.
app.on('window-all-closed', function () {
if (process.platform !== 'darwin') app.quit()
})
// In this file you can include the rest of your app's specific main process
// code. You can also put them in separate files and require them here.

View File

@@ -0,0 +1,6 @@
const { ipcRenderer } = require('electron')
const webview = document.getElementById('webview')
ipcRenderer.on('webview-new-window', (e, webContentsId, details) => {
console.log('webview-new-window', webContentsId, details)
webview.dispatchEvent(new Event('new-window'))
})

View File

@@ -0,0 +1,4 @@
const webview = document.getElementById('webview')
webview.addEventListener('new-window', () => {
console.log('got new-window event')
})

View File

@@ -5,17 +5,3 @@ const exLinksBtn = document.getElementById('open-ex-links')
exLinksBtn.addEventListener('click', (event) => { exLinksBtn.addEventListener('click', (event) => {
shell.openExternal('https://electronjs.org') shell.openExternal('https://electronjs.org')
}) })
const OpenAllOutboundLinks = () => {
const links = document.querySelectorAll('a[href]')
Array.prototype.forEach.call(links, (link) => {
const url = link.getAttribute('href')
if (url.indexOf('http') === 0) {
link.addEventListener('click', (e) => {
e.preventDefault()
shell.openExternal(url)
})
}
})
}

View File

@@ -4,5 +4,5 @@ const copyInput = document.getElementById('copy-to-input')
copyBtn.addEventListener('click', () => { copyBtn.addEventListener('click', () => {
if (copyInput.value !== '') copyInput.value = '' if (copyInput.value !== '') copyInput.value = ''
copyInput.placeholder = 'Copied! Paste here to see.' copyInput.placeholder = 'Copied! Paste here to see.'
clipboard.writeText('Electron Demo!') window.clipboard.writeText('Electron Demo!')
}) })

View File

@@ -1,7 +1,7 @@
const pasteBtn = document.getElementById('paste-to') const pasteBtn = document.getElementById('paste-to')
pasteBtn.addEventListener('click', async () => { pasteBtn.addEventListener('click', async () => {
await clipboard.writeText('What a demo!') await window.clipboard.writeText('What a demo!')
const message = `Clipboard contents: ${await clipboard.readText()}` const message = `Clipboard contents: ${await window.clipboard.readText()}`
document.getElementById('paste-from').innerHTML = message document.getElementById('paste-from').innerHTML = message
}) })

View File

@@ -1,7 +1,7 @@
const { ipcRenderer } = require('electron') const { ipcRenderer, shell } = require('electron')
const appInfoBtn = document.getElementById('app-info') const appInfoBtn = document.getElementById('app-info')
const electron_doc_link = document.querySelectorAll('a[href]') const electronDocLink = document.querySelectorAll('a[href]')
appInfoBtn.addEventListener('click', () => { appInfoBtn.addEventListener('click', () => {
ipcRenderer.send('get-app-path') ipcRenderer.send('get-app-path')
@@ -12,7 +12,8 @@ ipcRenderer.on('got-app-path', (event, path) => {
document.getElementById('got-app-info').innerHTML = message document.getElementById('got-app-info').innerHTML = message
}) })
electron_doc_link.addEventListener('click', (e) => { electronDocLink.addEventListener('click', (e) => {
e.preventDefault() e.preventDefault()
const url = e.target.getAttribute('href')
shell.openExternal(url) shell.openExternal(url)
}) })

View File

@@ -1,2 +1,2 @@
const information = document.getElementById('info') const information = document.getElementById('info')
information.innerText = `This app is using Chrome (v${versions.chrome()}), Node.js (v${versions.node()}), and Electron (v${versions.electron()})` information.innerText = `This app is using Chrome (v${window.versions.chrome()}), Node.js (v${window.versions.node()}), and Electron (v${window.versions.electron()})`

View File

@@ -23,23 +23,21 @@ function createWindow () {
// This method will be called when Electron has finished // This method will be called when Electron has finished
// initialization and is ready to create browser windows. // initialization and is ready to create browser windows.
// Some APIs can only be used after this event occurs. // Some APIs can only be used after this event occurs.
app.whenReady().then(createWindow) app.whenReady().then(() => {
createWindow()
// Quit when all windows are closed. app.on('activate', function () {
app.on('window-all-closed', function () { // On macOS it's common to re-create a window in the app when the
// On macOS it is common for applications and their menu bar // dock icon is clicked and there are no other windows open.
// to stay active until the user quits explicitly with Cmd + Q if (BrowserWindow.getAllWindows().length === 0) createWindow()
if (process.platform !== 'darwin') { })
app.quit()
}
}) })
app.on('activate', function () { // Quit when all windows are closed, except on macOS. There, it's common
// On macOS it is common to re-create a window in the app when the // for applications and their menu bar to stay active until the user quits
// dock icon is clicked and there are no other windows open. // explicitly with Cmd + Q.
if (mainWindow === null) { app.on('window-all-closed', function () {
createWindow() if (process.platform !== 'darwin') app.quit()
}
}) })
// In this file you can include the rest of your app's specific main process // In this file you can include the rest of your app's specific main process

View File

@@ -18,7 +18,7 @@ ipcMain.on('create-demo-window', (event) => {
function createWindow () { function createWindow () {
// Create the browser window. // Create the browser window.
mainWindow = new BrowserWindow({ const mainWindow = new BrowserWindow({
width: 800, width: 800,
height: 600, height: 600,
webPreferences: { webPreferences: {
@@ -33,23 +33,21 @@ function createWindow () {
// This method will be called when Electron has finished // This method will be called when Electron has finished
// initialization and is ready to create browser windows. // initialization and is ready to create browser windows.
// Some APIs can only be used after this event occurs. // Some APIs can only be used after this event occurs.
app.whenReady().then(createWindow) app.whenReady().then(() => {
createWindow()
// Quit when all windows are closed. app.on('activate', function () {
app.on('window-all-closed', function () { // On macOS it's common to re-create a window in the app when the
// On macOS it is common for applications and their menu bar // dock icon is clicked and there are no other windows open.
// to stay active until the user quits explicitly with Cmd + Q if (BrowserWindow.getAllWindows().length === 0) createWindow()
if (process.platform !== 'darwin') { })
app.quit()
}
}) })
app.on('activate', function () { // Quit when all windows are closed, except on macOS. There, it's common
// On macOS it is common to re-create a window in the app when the // for applications and their menu bar to stay active until the user quits
// dock icon is clicked and there are no other windows open. // explicitly with Cmd + Q.
if (mainWindow === null) { app.on('window-all-closed', function () {
createWindow() if (process.platform !== 'darwin') app.quit()
}
}) })
// In this file you can include the rest of your app's specific main process // In this file you can include the rest of your app's specific main process

View File

@@ -23,23 +23,21 @@ function createWindow () {
// This method will be called when Electron has finished // This method will be called when Electron has finished
// initialization and is ready to create browser windows. // initialization and is ready to create browser windows.
// Some APIs can only be used after this event occurs. // Some APIs can only be used after this event occurs.
app.whenReady().then(createWindow) app.whenReady().then(() => {
createWindow()
// Quit when all windows are closed. app.on('activate', function () {
app.on('window-all-closed', function () { // On macOS it's common to re-create a window in the app when the
// On macOS it is common for applications and their menu bar // dock icon is clicked and there are no other windows open.
// to stay active until the user quits explicitly with Cmd + Q if (BrowserWindow.getAllWindows().length === 0) createWindow()
if (process.platform !== 'darwin') { })
app.quit()
}
}) })
app.on('activate', function () { // Quit when all windows are closed, except on macOS. There, it's common
// On macOS it is common to re-create a window in the app when the // for applications and their menu bar to stay active until the user quits
// dock icon is clicked and there are no other windows open. // explicitly with Cmd + Q.
if (mainWindow === null) { app.on('window-all-closed', function () {
createWindow() if (process.platform !== 'darwin') app.quit()
}
}) })
// In this file you can include the rest of your app's specific main process // In this file you can include the rest of your app's specific main process

View File

@@ -41,23 +41,21 @@ function createWindow () {
// This method will be called when Electron has finished // This method will be called when Electron has finished
// initialization and is ready to create browser windows. // initialization and is ready to create browser windows.
// Some APIs can only be used after this event occurs. // Some APIs can only be used after this event occurs.
app.whenReady().then(createWindow) app.whenReady().then(() => {
createWindow()
// Quit when all windows are closed. app.on('activate', function () {
app.on('window-all-closed', function () { // On macOS it's common to re-create a window in the app when the
// On macOS it is common for applications and their menu bar // dock icon is clicked and there are no other windows open.
// to stay active until the user quits explicitly with Cmd + Q if (BrowserWindow.getAllWindows().length === 0) createWindow()
if (process.platform !== 'darwin') { })
app.quit()
}
}) })
app.on('activate', function () { // Quit when all windows are closed, except on macOS. There, it's common
// On macOS it is common to re-create a window in the app when the // for applications and their menu bar to stay active until the user quits
// dock icon is clicked and there are no other windows open. // explicitly with Cmd + Q.
if (mainWindow === null) { app.on('window-all-closed', function () {
createWindow() if (process.platform !== 'darwin') app.quit()
}
}) })
// In this file you can include the rest of your app's specific main process // In this file you can include the rest of your app's specific main process

View File

@@ -28,6 +28,8 @@ On macOS, third-party assistive technology can toggle accessibility features ins
Electron applications by setting the `AXManualAccessibility` attribute Electron applications by setting the `AXManualAccessibility` attribute
programmatically: programmatically:
Using Objective-C:
```objc ```objc
CFStringRef kAXManualAccessibility = CFSTR("AXManualAccessibility"); CFStringRef kAXManualAccessibility = CFSTR("AXManualAccessibility");
@@ -43,5 +45,16 @@ CFStringRef kAXManualAccessibility = CFSTR("AXManualAccessibility");
} }
``` ```
Using Swift:
```swift
import Cocoa
let name = CommandLine.arguments.count >= 2 ? CommandLine.arguments[1] : "Electron"
let pid = NSWorkspace.shared.runningApplications.first(where: {$0.localizedName == name})!.processIdentifier
let axApp = AXUIElementCreateApplication(pid)
let result = AXUIElementSetAttributeValue(axApp, "AXManualAccessibility" as CFString, true as CFTypeRef)
print("Setting 'AXManualAccessibility' \(error.rawValue == 0 ? "succeeded" : "failed")")
```
[a11y-docs]: https://www.chromium.org/developers/design-documents/accessibility#TOC-How-Chrome-detects-the-presence-of-Assistive-Technology [a11y-docs]: https://www.chromium.org/developers/design-documents/accessibility#TOC-How-Chrome-detects-the-presence-of-Assistive-Technology
[setAccessibilitySupportEnabled]: ../api/app.md#appsetaccessibilitysupportenabledenabled-macos-windows [setAccessibilitySupportEnabled]: ../api/app.md#appsetaccessibilitysupportenabledenabled-macos-windows

View File

@@ -55,7 +55,7 @@ fs.readdirSync('/path/to/example.asar')
Use a module from the archive: Use a module from the archive:
```javascript ```javascript @ts-nocheck
require('./path/to/example.asar/dir/module.js') require('./path/to/example.asar/dir/module.js')
``` ```

View File

@@ -40,7 +40,7 @@ Valid `algorithm` values are currently `SHA256` only. The `hash` is a hash of t
ASAR integrity checking is currently disabled by default and can be enabled by toggling a fuse. See [Electron Fuses](fuses.md) for more information on what Electron Fuses are and how they work. When enabling this fuse you typically also want to enable the `onlyLoadAppFromAsar` fuse otherwise the validity checking can be bypassed via the Electron app code search path. ASAR integrity checking is currently disabled by default and can be enabled by toggling a fuse. See [Electron Fuses](fuses.md) for more information on what Electron Fuses are and how they work. When enabling this fuse you typically also want to enable the `onlyLoadAppFromAsar` fuse otherwise the validity checking can be bypassed via the Electron app code search path.
```js ```js @ts-nocheck
require('@electron/fuses').flipFuses( require('@electron/fuses').flipFuses(
// E.g. /a/b/Foo.app // E.g. /a/b/Foo.app
pathToPackagedApp, pathToPackagedApp,

View File

@@ -37,7 +37,7 @@ This installs all necessary packages for you and generates a `wdio.conf.js` conf
Update the capabilities in your configuration file to point to your Electron app binary: Update the capabilities in your configuration file to point to your Electron app binary:
```javascript title='wdio.conf.js' ```javascript title='wdio.conf.js'
export.config = { exports.config = {
// ... // ...
capabilities: [{ capabilities: [{
browserName: 'chrome', browserName: 'chrome',
@@ -90,7 +90,7 @@ Usage of `selenium-webdriver` with Electron is the same as with
normal websites, except that you have to manually specify how to connect normal websites, except that you have to manually specify how to connect
ChromeDriver and where to find the binary of your Electron app: ChromeDriver and where to find the binary of your Electron app:
```js title='test.js' ```js title='test.js' @ts-expect-error=[1]
const webdriver = require('selenium-webdriver') const webdriver = require('selenium-webdriver')
const driver = new webdriver.Builder() const driver = new webdriver.Builder()
// The "9515" is the port opened by ChromeDriver. // The "9515" is the port opened by ChromeDriver.
@@ -155,7 +155,7 @@ Playwright launches your app in development mode through the `_electron.launch`
To point this API to your Electron app, you can pass the path to your main process To point this API to your Electron app, you can pass the path to your main process
entry point (here, it is `main.js`). entry point (here, it is `main.js`).
```js {5} ```js {5} @ts-nocheck
const { _electron: electron } = require('playwright') const { _electron: electron } = require('playwright')
const { test } = require('@playwright/test') const { test } = require('@playwright/test')
@@ -169,7 +169,7 @@ test('launch app', async () => {
After that, you will access to an instance of Playwright's `ElectronApp` class. This After that, you will access to an instance of Playwright's `ElectronApp` class. This
is a powerful class that has access to main process modules for example: is a powerful class that has access to main process modules for example:
```js {6-11} ```js {6-11} @ts-nocheck
const { _electron: electron } = require('playwright') const { _electron: electron } = require('playwright')
const { test } = require('@playwright/test') const { test } = require('@playwright/test')
@@ -189,7 +189,7 @@ test('get isPackaged', async () => {
It can also create individual [Page][playwright-page] objects from Electron BrowserWindow instances. It can also create individual [Page][playwright-page] objects from Electron BrowserWindow instances.
For example, to grab the first BrowserWindow and save a screenshot: For example, to grab the first BrowserWindow and save a screenshot:
```js {6-7} ```js {6-7} @ts-nocheck
const { _electron: electron } = require('playwright') const { _electron: electron } = require('playwright')
const { test } = require('@playwright/test') const { test } = require('@playwright/test')
@@ -205,7 +205,7 @@ test('save screenshot', async () => {
Putting all this together using the PlayWright Test runner, let's create a `example.spec.js` Putting all this together using the PlayWright Test runner, let's create a `example.spec.js`
test file with a single test and assertion: test file with a single test and assertion:
```js title='example.spec.js' ```js title='example.spec.js' @ts-nocheck
const { _electron: electron } = require('playwright') const { _electron: electron } = require('playwright')
const { test, expect } = require('@playwright/test') const { test, expect } = require('@playwright/test')
@@ -214,10 +214,10 @@ test('example test', async () => {
const isPackaged = await electronApp.evaluate(async ({ app }) => { const isPackaged = await electronApp.evaluate(async ({ app }) => {
// This runs in Electron's main process, parameter here is always // This runs in Electron's main process, parameter here is always
// the result of the require('electron') in the main app script. // the result of the require('electron') in the main app script.
return app.isPackaged; return app.isPackaged
}); })
expect(isPackaged).toBe(false); expect(isPackaged).toBe(false)
// Wait for the first BrowserWindow to open // Wait for the first BrowserWindow to open
// and return its Page object // and return its Page object
@@ -226,7 +226,7 @@ test('example test', async () => {
// close app // close app
await electronApp.close() await electronApp.close()
}); })
``` ```
Then, run Playwright Test using `npx playwright test`. You should see the test pass in your Then, run Playwright Test using `npx playwright test`. You should see the test pass in your
@@ -259,7 +259,7 @@ 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. 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: The test suite will spawn the Electron process, then establish a simple messaging protocol:
```js title='testDriver.js' ```js title='testDriver.js' @ts-nocheck
const childProcess = require('child_process') const childProcess = require('child_process')
const electronPath = require('electron') const electronPath = require('electron')
@@ -296,7 +296,7 @@ For convenience, you may want to wrap `appProcess` in a driver object that provi
high-level functions. Here is an example of how you can do this. Let's start by creating high-level functions. Here is an example of how you can do this. Let's start by creating
a `TestDriver` class: a `TestDriver` class:
```js title='testDriver.js' ```js title='testDriver.js' @ts-nocheck
class TestDriver { class TestDriver {
constructor ({ path, args, env }) { constructor ({ path, args, env }) {
this.rpcCalls = [] this.rpcCalls = []
@@ -338,7 +338,7 @@ class TestDriver {
} }
} }
module.exports = { TestDriver }; module.exports = { TestDriver }
``` ```
In your app code, can then write a simple handler to receive RPC calls: In your app code, can then write a simple handler to receive RPC calls:
@@ -378,7 +378,7 @@ framework of your choosing. The following example uses
[`ava`](https://www.npmjs.com/package/ava), but other popular choices like Jest [`ava`](https://www.npmjs.com/package/ava), but other popular choices like Jest
or Mocha would work as well: or Mocha would work as well:
```js title='test.js' ```js title='test.js' @ts-nocheck
const test = require('ava') const test = require('ava')
const electronPath = require('electron') const electronPath = require('electron')
const { TestDriver } = require('./testDriver') const { TestDriver } = require('./testDriver')

View File

@@ -52,7 +52,7 @@ You can find more information and documentation in [the repository](https://gith
## electron-react-boilerplate ## electron-react-boilerplate
If you don't want any tools but only a solid boilerplate to build from, If you don't want any tools but only a solid boilerplate to build from,
CT Lin's [`electron-react-boilerplate`](https://github.com/chentsulin/electron-react-boilerplate) might be worth CT Lin's [`electron-react-boilerplate`](https://github.com/electron-react-boilerplate/electron-react-boilerplate) might be worth
a look. It's quite popular in the community and uses `electron-builder` a look. It's quite popular in the community and uses `electron-builder`
internally. internally.

View File

@@ -67,7 +67,7 @@ are likely using [`electron-packager`][], which includes [`@electron/osx-sign`][
If you're using Packager's API, you can pass [in configuration that both signs If you're using Packager's API, you can pass [in configuration that both signs
and notarizes your application](https://electron.github.io/electron-packager/main/interfaces/electronpackager.options.html). and notarizes your application](https://electron.github.io/electron-packager/main/interfaces/electronpackager.options.html).
```js ```js @ts-nocheck
const packager = require('electron-packager') const packager = require('electron-packager')
packager({ packager({
@@ -116,7 +116,7 @@ Electron app. This is the tool used under the hood by Electron Forge's
`electron-winstaller` directly, use the `certificateFile` and `certificatePassword` configuration `electron-winstaller` directly, use the `certificateFile` and `certificatePassword` configuration
options when creating your installer. options when creating your installer.
```js {10-11} ```js {10-11} @ts-nocheck
const electronInstaller = require('electron-winstaller') const electronInstaller = require('electron-winstaller')
// NB: Use this syntax within an async function, Node does not have support for // NB: Use this syntax within an async function, Node does not have support for
// top-level await as of Node 12. // top-level await as of Node 12.
@@ -127,7 +127,7 @@ try {
authors: 'My App Inc.', authors: 'My App Inc.',
exe: 'myapp.exe', exe: 'myapp.exe',
certificateFile: './cert.pfx', certificateFile: './cert.pfx',
certificatePassword: 'this-is-a-secret', certificatePassword: 'this-is-a-secret'
}) })
console.log('It worked!') console.log('It worked!')
} catch (e) { } catch (e) {
@@ -146,7 +146,7 @@ If you're not using Electron Forge and want to use `electron-wix-msi` directly,
`certificateFile` and `certificatePassword` configuration options `certificateFile` and `certificatePassword` configuration options
or pass in parameters directly to [SignTool.exe][] with the `signWithParams` option. or pass in parameters directly to [SignTool.exe][] with the `signWithParams` option.
```js {12-13} ```js {12-13} @ts-nocheck
import { MSICreator } from 'electron-wix-msi' import { MSICreator } from 'electron-wix-msi'
// Step 1: Instantiate the MSICreator // Step 1: Instantiate the MSICreator
@@ -159,7 +159,7 @@ const msiCreator = new MSICreator({
version: '1.1.2', version: '1.1.2',
outputDirectory: '/path/to/output/folder', outputDirectory: '/path/to/output/folder',
certificateFile: './cert.pfx', certificateFile: './cert.pfx',
certificatePassword: 'this-is-a-secret', certificatePassword: 'this-is-a-secret'
}) })
// Step 2: Create a .wxs template file // Step 2: Create a .wxs template file

View File

@@ -16,7 +16,7 @@ Context isolation has been enabled by default since Electron 12, and it is a rec
Exposing APIs from your preload script to a loaded website in the renderer process is a common use-case. With context isolation disabled, your preload script would share a common global `window` object with the renderer. You could then attach arbitrary properties to a preload script: Exposing APIs from your preload script to a loaded website in the renderer process is a common use-case. With context isolation disabled, your preload script would share a common global `window` object with the renderer. You could then attach arbitrary properties to a preload script:
```javascript title='preload.js' ```javascript title='preload.js' @ts-nocheck
// preload with contextIsolation disabled // preload with contextIsolation disabled
window.myAPI = { window.myAPI = {
doAThing: () => {} doAThing: () => {}
@@ -25,7 +25,7 @@ window.myAPI = {
The `doAThing()` function could then be used directly in the renderer process: The `doAThing()` function could then be used directly in the renderer process:
```javascript title='renderer.js' ```javascript title='renderer.js' @ts-nocheck
// use the exposed API in the renderer // use the exposed API in the renderer
window.myAPI.doAThing() window.myAPI.doAThing()
``` ```
@@ -43,7 +43,7 @@ contextBridge.exposeInMainWorld('myAPI', {
}) })
``` ```
```javascript title='renderer.js' ```javascript title='renderer.js' @ts-nocheck
// use the exposed API in the renderer // use the exposed API in the renderer
window.myAPI.doAThing() window.myAPI.doAThing()
``` ```
@@ -98,7 +98,7 @@ declare global {
Doing so will ensure that the TypeScript compiler will know about the `electronAPI` property on your global `window` object when writing scripts in your renderer process: Doing so will ensure that the TypeScript compiler will know about the `electronAPI` property on your global `window` object when writing scripts in your renderer process:
```typescript title='renderer.ts' ```typescript title='renderer.ts' @ts-nocheck
window.electronAPI.loadPreferences() window.electronAPI.loadPreferences()
``` ```

View File

@@ -116,7 +116,7 @@ Now the renderer process can communicate with the main process securely and perf
The `renderer.js` file is responsible for controlling the `<button>` functionality. The `renderer.js` file is responsible for controlling the `<button>` functionality.
```js title='renderer.js' ```js title='renderer.js' @ts-expect-error=[2,7]
document.getElementById('toggle-dark-mode').addEventListener('click', async () => { document.getElementById('toggle-dark-mode').addEventListener('click', async () => {
const isDarkMode = await window.darkMode.toggle() const isDarkMode = await window.darkMode.toggle()
document.getElementById('theme-source').innerHTML = isDarkMode ? 'Dark' : 'Light' document.getElementById('theme-source').innerHTML = isDarkMode ? 'Dark' : 'Light'

View File

@@ -129,7 +129,7 @@ Electron provides several APIs for working with the WebUSB API:
when handling the `select-usb-device` event. when handling the `select-usb-device` event.
**Note:** These two events only fire until the callback from `select-usb-device` **Note:** These two events only fire until the callback from `select-usb-device`
is called. They are not intended to be used as a generic usb device listener. is called. They are not intended to be used as a generic usb device listener.
* The [`usb-device-revoked' event on the Session](../api/session.md#event-usb-device-revoked) can * The [`usb-device-revoked` event on the Session](../api/session.md#event-usb-device-revoked) can
be used to respond when [device.forget()](https://developer.chrome.com/articles/usb/#revoke-access) be used to respond when [device.forget()](https://developer.chrome.com/articles/usb/#revoke-access)
is called on a USB device. is called on a USB device.
* [`ses.setDevicePermissionHandler(handler)`](../api/session.md#sessetdevicepermissionhandlerhandler) * [`ses.setDevicePermissionHandler(handler)`](../api/session.md#sessetdevicepermissionhandlerhandler)
@@ -142,6 +142,8 @@ Electron provides several APIs for working with the WebUSB API:
`setDevicePermissionHandler`. `setDevicePermissionHandler`.
* [`ses.setPermissionCheckHandler(handler)`](../api/session.md#sessetpermissioncheckhandlerhandler) * [`ses.setPermissionCheckHandler(handler)`](../api/session.md#sessetpermissioncheckhandlerhandler)
can be used to disable USB access for specific origins. can be used to disable USB access for specific origins.
* [`ses.setUSBProtectedClassesHandler](../api/session.md#sessetusbprotectedclasseshandlerhandler)
can be used to allow usage of [protected USB classes](https://wicg.github.io/webusb/#usbinterface-interface) that are not available by default.
### Example ### Example

View File

@@ -34,19 +34,19 @@ Using the [React Developer Tools][react-devtools] as an example:
API. For React Developer Tools `v4.9.0`, it looks something like: API. For React Developer Tools `v4.9.0`, it looks something like:
```javascript ```javascript
const { app, session } = require('electron') const { app, session } = require('electron')
const path = require('path') const path = require('path')
const os = require('os') const os = require('os')
// on macOS // on macOS
const reactDevToolsPath = path.join( const reactDevToolsPath = path.join(
os.homedir(), os.homedir(),
'/Library/Application Support/Google/Chrome/Default/Extensions/fmkadmapgofadopljbjfkapdkoienihi/4.9.0_0' '/Library/Application Support/Google/Chrome/Default/Extensions/fmkadmapgofadopljbjfkapdkoienihi/4.9.0_0'
) )
app.whenReady().then(async () => { app.whenReady().then(async () => {
await session.defaultSession.loadExtension(reactDevToolsPath) await session.defaultSession.loadExtension(reactDevToolsPath)
}) })
``` ```
**Notes:** **Notes:**

View File

@@ -9,11 +9,11 @@ check out our [Electron Versioning](./electron-versioning.md) doc.
| Electron | Alpha | Beta | Stable | EOL | Chrome | Node | Supported | | Electron | Alpha | Beta | Stable | EOL | Chrome | Node | Supported |
| ------- | ----- | ------- | ------ | ------ | ---- | ---- | ---- | | ------- | ----- | ------- | ------ | ------ | ---- | ---- | ---- |
| 25.0.0 | 2023-Apr-10 | 2023-May-02 | 2023-May-30 | TBD | M114 | TBD | TBD | | 25.0.0 | 2023-Apr-10 | 2023-May-02 | 2023-May-30 | 2023-Dec-05 | M114 | TBD | |
| 24.0.0 | 2022-Feb-09 | 2023-Mar-07 | 2023-Apr-08 | TBD | M112 | TBD | ✅ | | 24.0.0 | 2022-Feb-09 | 2023-Mar-07 | 2023-Apr-04 | 2023-Oct-03 | M112 | v18.14 | ✅ |
| 23.0.0 | 2022-Dec-01 | 2023-Jan-10 | 2023-Feb-07 | TBD | M110 | TBD | ✅ | | 23.0.0 | 2022-Dec-01 | 2023-Jan-10 | 2023-Feb-07 | 2023-Aug-08 | M110 | v18.12 | ✅ |
| 22.0.0 | 2022-Sep-29 | 2022-Oct-25 | 2022-Nov-29 | TBD | M108 | v16.17 | ✅ | | 22.0.0 | 2022-Sep-29 | 2022-Oct-25 | 2022-Nov-29 | 2023-Oct-10 | M108 | v16.17 | ✅ |
| 21.0.0 | 2022-Aug-04 | 2022-Aug-30 | 2022-Sep-27 | TBD | M106 | v16.16 | | | 21.0.0 | 2022-Aug-04 | 2022-Aug-30 | 2022-Sep-27 | 2023-Apr-04 | M106 | v16.16 | 🚫 |
| 20.0.0 | 2022-May-26 | 2022-Jun-21 | 2022-Aug-02 | 2023-Feb-07 | M104 | v16.15 | 🚫 | | 20.0.0 | 2022-May-26 | 2022-Jun-21 | 2022-Aug-02 | 2023-Feb-07 | M104 | v16.15 | 🚫 |
| 19.0.0 | 2022-Mar-31 | 2022-Apr-26 | 2022-May-24 | 2022-Nov-29 | M102 | v16.14 | 🚫 | | 19.0.0 | 2022-Mar-31 | 2022-Apr-26 | 2022-May-24 | 2022-Nov-29 | M102 | v16.14 | 🚫 |
| 18.0.0 | 2022-Feb-03 | 2022-Mar-03 | 2022-Mar-29 | 2022-Sep-27 | M100 | v16.13 | 🚫 | | 18.0.0 | 2022-Feb-03 | 2022-Mar-03 | 2022-Mar-29 | 2022-Sep-27 | M100 | v16.13 | 🚫 |

View File

@@ -67,7 +67,7 @@ The loadBrowserProcessSpecificV8Snapshot fuse changes which V8 snapshot file is
We've made a handy module, [`@electron/fuses`](https://npmjs.com/package/@electron/fuses), to make flipping these fuses easy. Check out the README of that module for more details on usage and potential error cases. We've made a handy module, [`@electron/fuses`](https://npmjs.com/package/@electron/fuses), to make flipping these fuses easy. Check out the README of that module for more details on usage and potential error cases.
```js ```js @ts-nocheck
require('@electron/fuses').flipFuses( require('@electron/fuses').flipFuses(
// Path to electron // Path to electron
require('electron'), require('electron'),

View File

@@ -66,7 +66,7 @@ You can use environment variables to override the base URL, the path at which to
look for Electron binaries, and the binary filename. The URL used by `@electron/get` look for Electron binaries, and the binary filename. The URL used by `@electron/get`
is composed as follows: is composed as follows:
```javascript ```javascript @ts-nocheck
url = ELECTRON_MIRROR + ELECTRON_CUSTOM_DIR + '/' + ELECTRON_CUSTOM_FILENAME url = ELECTRON_MIRROR + ELECTRON_CUSTOM_DIR + '/' + ELECTRON_CUSTOM_FILENAME
``` ```

View File

@@ -51,10 +51,10 @@ sections.
In the main process, set an IPC listener on the `set-title` channel with the `ipcMain.on` API: In the main process, set an IPC listener on the `set-title` channel with the `ipcMain.on` API:
```javascript {6-10,22} title='main.js (Main Process)' ```javascript {6-10,22} title='main.js (Main Process)'
const {app, BrowserWindow, ipcMain} = require('electron') const { app, BrowserWindow, ipcMain } = require('electron')
const path = require('path') const path = require('path')
//... // ...
function handleSetTitle (event, title) { function handleSetTitle (event, title) {
const webContents = event.sender const webContents = event.sender
@@ -74,8 +74,8 @@ function createWindow () {
app.whenReady().then(() => { app.whenReady().then(() => {
ipcMain.on('set-title', handleSetTitle) ipcMain.on('set-title', handleSetTitle)
createWindow() createWindow()
} })
//... // ...
``` ```
The above `handleSetTitle` callback has two parameters: an [IpcMainEvent][] structure and a The above `handleSetTitle` callback has two parameters: an [IpcMainEvent][] structure and a
@@ -100,7 +100,7 @@ variable to your renderer process.
const { contextBridge, ipcRenderer } = require('electron') const { contextBridge, ipcRenderer } = require('electron')
contextBridge.exposeInMainWorld('electronAPI', { contextBridge.exposeInMainWorld('electronAPI', {
setTitle: (title) => ipcRenderer.send('set-title', title) setTitle: (title) => ipcRenderer.send('set-title', title)
}) })
``` ```
@@ -138,13 +138,13 @@ To make these elements interactive, we'll be adding a few lines of code in the i
`renderer.js` file that leverages the `window.electronAPI` functionality exposed from the preload `renderer.js` file that leverages the `window.electronAPI` functionality exposed from the preload
script: script:
```javascript title='renderer.js (Renderer Process)' ```javascript title='renderer.js (Renderer Process)' @ts-expect-error=[4,5]
const setButton = document.getElementById('btn') const setButton = document.getElementById('btn')
const titleInput = document.getElementById('title') const titleInput = document.getElementById('title')
setButton.addEventListener('click', () => { setButton.addEventListener('click', () => {
const title = titleInput.value const title = titleInput.value
window.electronAPI.setTitle(title) window.electronAPI.setTitle(title)
}); })
``` ```
At this point, your demo should be fully functional. Try using the input field and see what happens At this point, your demo should be fully functional. Try using the input field and see what happens
@@ -182,16 +182,14 @@ provided to the renderer process. Please refer to
::: :::
```javascript {6-13,25} title='main.js (Main Process)' ```javascript {6-13,25} title='main.js (Main Process)'
const { BrowserWindow, dialog, ipcMain } = require('electron') const { app, BrowserWindow, dialog, ipcMain } = require('electron')
const path = require('path') const path = require('path')
//... // ...
async function handleFileOpen() { async function handleFileOpen () {
const { canceled, filePaths } = await dialog.showOpenDialog() const { canceled, filePaths } = await dialog.showOpenDialog({})
if (canceled) { if (!canceled) {
return
} else {
return filePaths[0] return filePaths[0]
} }
} }
@@ -205,11 +203,11 @@ function createWindow () {
mainWindow.loadFile('index.html') mainWindow.loadFile('index.html')
} }
app.whenReady(() => { app.whenReady().then(() => {
ipcMain.handle('dialog:openFile', handleFileOpen) ipcMain.handle('dialog:openFile', handleFileOpen)
createWindow() createWindow()
}) })
//... // ...
``` ```
:::tip on channel names :::tip on channel names
@@ -265,7 +263,7 @@ The UI consists of a single `#btn` button element that will be used to trigger o
a `#filePath` element that will be used to display the path of the selected file. Making these a `#filePath` element that will be used to display the path of the selected file. Making these
pieces work will take a few lines of code in the renderer process script: pieces work will take a few lines of code in the renderer process script:
```javascript title='renderer.js (Renderer Process)' ```javascript title='renderer.js (Renderer Process)' @ts-expect-error=[5]
const btn = document.getElementById('btn') const btn = document.getElementById('btn')
const filePathElement = document.getElementById('filePath') const filePathElement = document.getElementById('filePath')
@@ -379,7 +377,7 @@ module that uses the `webContents.send` API to send an IPC message from the main
target renderer. target renderer.
```javascript {11-26} title='main.js (Main Process)' ```javascript {11-26} title='main.js (Main Process)'
const {app, BrowserWindow, Menu, ipcMain} = require('electron') const { app, BrowserWindow, Menu, ipcMain } = require('electron')
const path = require('path') const path = require('path')
function createWindow () { function createWindow () {
@@ -395,11 +393,11 @@ function createWindow () {
submenu: [ submenu: [
{ {
click: () => mainWindow.webContents.send('update-counter', 1), click: () => mainWindow.webContents.send('update-counter', 1),
label: 'Increment', label: 'Increment'
}, },
{ {
click: () => mainWindow.webContents.send('update-counter', -1), click: () => mainWindow.webContents.send('update-counter', -1),
label: 'Decrement', label: 'Decrement'
} }
] ]
} }
@@ -408,14 +406,13 @@ function createWindow () {
mainWindow.loadFile('index.html') mainWindow.loadFile('index.html')
} }
//... // ...
``` ```
For the purposes of the tutorial, it's important to note that the `click` handler For the purposes of the tutorial, it's important to note that the `click` handler
sends a message (either `1` or `-1`) to the renderer process through the `update-counter` channel. sends a message (either `1` or `-1`) to the renderer process through the `update-counter` channel.
```javascript ```javascript @ts-nocheck
click: () => mainWindow.webContents.send('update-counter', -1) click: () => mainWindow.webContents.send('update-counter', -1)
``` ```
@@ -432,7 +429,7 @@ modules in the preload script to expose IPC functionality to the renderer proces
const { contextBridge, ipcRenderer } = require('electron') const { contextBridge, ipcRenderer } = require('electron')
contextBridge.exposeInMainWorld('electronAPI', { contextBridge.exposeInMainWorld('electronAPI', {
onUpdateCounter: (callback) => ipcRenderer.on('update-counter', callback) onUpdateCounter: (callback) => ipcRenderer.on('update-counter', callback)
}) })
``` ```
@@ -452,12 +449,12 @@ rather than exposing it over the context bridge.
const { ipcRenderer } = require('electron') const { ipcRenderer } = require('electron')
window.addEventListener('DOMContentLoaded', () => { window.addEventListener('DOMContentLoaded', () => {
const counter = document.getElementById('counter') const counter = document.getElementById('counter')
ipcRenderer.on('update-counter', (_event, value) => { ipcRenderer.on('update-counter', (_event, value) => {
const oldValue = Number(counter.innerText) const oldValue = Number(counter.innerText)
const newValue = oldValue + value const newValue = oldValue + value
counter.innerText = newValue counter.innerText = newValue
}) })
}) })
``` ```
@@ -489,13 +486,13 @@ To tie it all together, we'll create an interface in the loaded HTML file that c
Finally, to make the values update in the HTML document, we'll add a few lines of DOM manipulation Finally, to make the values update in the HTML document, we'll add a few lines of DOM manipulation
so that the value of the `#counter` element is updated whenever we fire an `update-counter` event. so that the value of the `#counter` element is updated whenever we fire an `update-counter` event.
```javascript title='renderer.js (Renderer Process)' ```javascript title='renderer.js (Renderer Process)' @ts-nocheck
const counter = document.getElementById('counter') const counter = document.getElementById('counter')
window.electronAPI.onUpdateCounter((_event, value) => { window.electronAPI.onUpdateCounter((_event, value) => {
const oldValue = Number(counter.innerText) const oldValue = Number(counter.innerText)
const newValue = oldValue + value const newValue = oldValue + value
counter.innerText = newValue counter.innerText = newValue
}) })
``` ```
@@ -512,7 +509,7 @@ We can demonstrate this with slight modifications to the code from the previous
renderer process, use the `event` parameter to send a reply back to the main process through the renderer process, use the `event` parameter to send a reply back to the main process through the
`counter-value` channel. `counter-value` channel.
```javascript title='renderer.js (Renderer Process)' ```javascript title='renderer.js (Renderer Process)' @ts-nocheck
const counter = document.getElementById('counter') const counter = document.getElementById('counter')
window.electronAPI.onUpdateCounter((event, value) => { window.electronAPI.onUpdateCounter((event, value) => {
@@ -526,11 +523,11 @@ window.electronAPI.onUpdateCounter((event, value) => {
In the main process, listen for `counter-value` events and handle them appropriately. In the main process, listen for `counter-value` events and handle them appropriately.
```javascript title='main.js (Main Process)' ```javascript title='main.js (Main Process)'
//... // ...
ipcMain.on('counter-value', (_event, value) => { ipcMain.on('counter-value', (_event, value) => {
console.log(value) // will print value to Node console console.log(value) // will print value to Node console
}) })
//... // ...
``` ```
## Pattern 4: Renderer to renderer ## Pattern 4: Renderer to renderer

View File

@@ -56,7 +56,7 @@ Starting with a working application from the
[Quick Start Guide](quick-start.md), update the `main.js` file with the [Quick Start Guide](quick-start.md), update the `main.js` file with the
following lines: following lines:
```javascript fiddle='docs/fiddles/features/keyboard-shortcuts/global' ```javascript fiddle='docs/fiddles/features/keyboard-shortcuts/global' @ts-type={createWindow:()=>void}
const { app, globalShortcut } = require('electron') const { app, globalShortcut } = require('electron')
app.whenReady().then(() => { app.whenReady().then(() => {
@@ -84,11 +84,11 @@ renderer process using the [addEventListener() API][addEventListener-api].
```javascript fiddle='docs/fiddles/features/keyboard-shortcuts/web-apis|focus=renderer.js' ```javascript fiddle='docs/fiddles/features/keyboard-shortcuts/web-apis|focus=renderer.js'
const handleKeyPress = (event) => { const handleKeyPress = (event) => {
// You can put code here to handle the keypress. // You can put code here to handle the keypress.
document.getElementById("last-keypress").innerText = event.key; document.getElementById('last-keypress').innerText = event.key
console.log(`You pressed ${event.key}`); console.log(`You pressed ${event.key}`)
} }
window.addEventListener('keyup', handleKeyPress, true); window.addEventListener('keyup', handleKeyPress, true)
``` ```
> Note: the third parameter `true` indicates that the listener will always receive > Note: the third parameter `true` indicates that the listener will always receive
@@ -131,7 +131,7 @@ If you don't want to do manual shortcut parsing, there are libraries that do
advanced key detection, such as [mousetrap][]. Below are examples of usage of the advanced key detection, such as [mousetrap][]. Below are examples of usage of the
`mousetrap` running in the Renderer process: `mousetrap` running in the Renderer process:
```js ```js @ts-nocheck
Mousetrap.bind('4', () => { console.log('4') }) Mousetrap.bind('4', () => { console.log('4') })
Mousetrap.bind('?', () => { console.log('show shortcuts!') }) Mousetrap.bind('?', () => { console.log('show shortcuts!') })
Mousetrap.bind('esc', () => { console.log('escape') }, 'keyup') Mousetrap.bind('esc', () => { console.log('escape') }, 'keyup')

View File

@@ -45,6 +45,8 @@ if (process.defaultApp) {
We will now define the function in charge of creating our browser window and load our application's `index.html` file. We will now define the function in charge of creating our browser window and load our application's `index.html` file.
```javascript ```javascript
let mainWindow
const createWindow = () => { const createWindow = () => {
// Create the browser window. // Create the browser window.
mainWindow = new BrowserWindow({ mainWindow = new BrowserWindow({
@@ -65,7 +67,7 @@ This code will be different in Windows compared to MacOS and Linux. This is due
#### Windows code: #### Windows code:
```javascript ```javascript @ts-type={mainWindow:Electron.BrowserWindow} @ts-type={createWindow:()=>void}
const gotTheLock = app.requestSingleInstanceLock() const gotTheLock = app.requestSingleInstanceLock()
if (!gotTheLock) { if (!gotTheLock) {
@@ -91,7 +93,7 @@ if (!gotTheLock) {
#### MacOS and Linux code: #### MacOS and Linux code:
```javascript ```javascript @ts-type={createWindow:()=>void}
// This method will be called when Electron has finished // This method will be called when Electron has finished
// initialization and is ready to create browser windows. // initialization and is ready to create browser windows.
// Some APIs can only be used after this event occurs. // Some APIs can only be used after this event occurs.
@@ -166,7 +168,7 @@ If you're using Electron Packager's API, adding support for protocol handlers is
Electron Forge is handled, except Electron Forge is handled, except
`protocols` is part of the Packager options passed to the `packager` function. `protocols` is part of the Packager options passed to the `packager` function.
```javascript ```javascript @ts-nocheck
const packager = require('electron-packager') const packager = require('electron-packager')
packager({ packager({

View File

@@ -341,7 +341,7 @@ Electron uses following cryptographic algorithms:
* RIPEMD - [ISO/IEC 10118-3](https://webstore.ansi.org/RecordDetail.aspx?sku=ISO%2FIEC%2010118-3:2004) * RIPEMD - [ISO/IEC 10118-3](https://webstore.ansi.org/RecordDetail.aspx?sku=ISO%2FIEC%2010118-3:2004)
[developer-program]: https://developer.apple.com/support/compare-memberships/ [developer-program]: https://developer.apple.com/support/compare-memberships/
[@electron/osx-sign]: https://github.com/electron/electron-osx-sign [@electron/osx-sign]: https://github.com/electron/osx-sign
[app-sandboxing]: https://developer.apple.com/app-sandboxing/ [app-sandboxing]: https://developer.apple.com/app-sandboxing/
[app-notarization]: https://developer.apple.com/documentation/security/notarizing_macos_software_before_distribution [app-notarization]: https://developer.apple.com/documentation/security/notarizing_macos_software_before_distribution
[submitting-your-app]: https://developer.apple.com/library/mac/documentation/IDEs/Conceptual/AppDistributionGuide/SubmittingYourApp/SubmittingYourApp.html [submitting-your-app]: https://developer.apple.com/library/mac/documentation/IDEs/Conceptual/AppDistributionGuide/SubmittingYourApp/SubmittingYourApp.html

View File

@@ -29,7 +29,7 @@ const { app, BrowserWindow, Menu } = require('electron')
const createWindow = () => { const createWindow = () => {
const win = new BrowserWindow({ const win = new BrowserWindow({
width: 800, width: 800,
height: 600, height: 600
}) })
win.loadFile('index.html') win.loadFile('index.html')
@@ -66,7 +66,6 @@ app.on('activate', () => {
createWindow() createWindow()
} }
}) })
``` ```
After launching the Electron application, right click the application icon. After launching the Electron application, right click the application icon.

View File

@@ -126,7 +126,7 @@ app.whenReady().then(async () => {
Then, in your preload scripts you receive the port through IPC and set up the Then, in your preload scripts you receive the port through IPC and set up the
listeners. listeners.
```js title='preloadMain.js and preloadSecondary.js (Preload scripts)' ```js title='preloadMain.js and preloadSecondary.js (Preload scripts)' @ts-nocheck
const { ipcRenderer } = require('electron') const { ipcRenderer } = require('electron')
ipcRenderer.on('port', e => { ipcRenderer.on('port', e => {
@@ -148,7 +148,7 @@ That means window.electronMessagePort is globally available and you can call
`postMessage` on it from anywhere in your app to send a message to the other `postMessage` on it from anywhere in your app to send a message to the other
renderer. renderer.
```js title='renderer.js (Renderer Process)' ```js title='renderer.js (Renderer Process)' @ts-nocheck
// elsewhere in your code to send a message to the other renderers message handler // elsewhere in your code to send a message to the other renderers message handler
window.electronMessagePort.postmessage('ping') window.electronMessagePort.postmessage('ping')
``` ```
@@ -181,7 +181,7 @@ app.whenReady().then(async () => {
// We can't use ipcMain.handle() here, because the reply needs to transfer a // We can't use ipcMain.handle() here, because the reply needs to transfer a
// MessagePort. // MessagePort.
// Listen for message sent from the top-level frame // Listen for message sent from the top-level frame
mainWindow.webContents.mainFrame.on('request-worker-channel', (event) => { mainWindow.webContents.mainFrame.ipc.on('request-worker-channel', (event) => {
// Create a new channel ... // Create a new channel ...
const { port1, port2 } = new MessageChannelMain() const { port1, port2 } = new MessageChannelMain()
// ... send one end to the worker ... // ... send one end to the worker ...
@@ -245,7 +245,7 @@ Electron's built-in IPC methods only support two modes: fire-and-forget
can implement a "response stream", where a single request responds with a can implement a "response stream", where a single request responds with a
stream of data. stream of data.
```js title='renderer.js (Renderer Process)' ```js title='renderer.js (Renderer Process)' @ts-expect-error=[18]
const makeStreamingRequest = (element, callback) => { const makeStreamingRequest = (element, callback) => {
// MessageChannels are lightweight--it's cheap to create a new one for each // MessageChannels are lightweight--it's cheap to create a new one for each
// request. // request.

View File

@@ -42,7 +42,7 @@ safe.
The only way to load a native module safely for now, is to make sure the app The only way to load a native module safely for now, is to make sure the app
loads no native modules after the Web Workers get started. loads no native modules after the Web Workers get started.
```javascript ```javascript @ts-expect-error=[1]
process.dlopen = () => { process.dlopen = () => {
throw new Error('Load native module is not safe') throw new Error('Load native module is not safe')
} }

View File

@@ -22,6 +22,7 @@ In `preload.js` use the [`contextBridge`][] to inject a method `window.electron.
```js ```js
const { contextBridge, ipcRenderer } = require('electron') const { contextBridge, ipcRenderer } = require('electron')
const path = require('path')
contextBridge.exposeInMainWorld('electron', { contextBridge.exposeInMainWorld('electron', {
startDrag: (fileName) => { startDrag: (fileName) => {
@@ -43,7 +44,7 @@ Add a draggable element to `index.html`, and reference your renderer script:
In `renderer.js` set up the renderer process to handle drag events by calling the method you added via the [`contextBridge`][] above. In `renderer.js` set up the renderer process to handle drag events by calling the method you added via the [`contextBridge`][] above.
```javascript ```javascript @ts-expect-error=[3]
document.getElementById('drag').ondragstart = (event) => { document.getElementById('drag').ondragstart = (event) => {
event.preventDefault() event.preventDefault()
window.electron.startDrag('drag-and-drop.md') window.electron.startDrag('drag-and-drop.md')

View File

@@ -17,29 +17,29 @@ Notification objects created using this module do not appear unless their `show(
method is called. method is called.
```js title='Main Process' ```js title='Main Process'
const { Notification } = require("electron"); const { Notification } = require('electron')
const NOTIFICATION_TITLE = "Basic Notification"; const NOTIFICATION_TITLE = 'Basic Notification'
const NOTIFICATION_BODY = "Notification from the Main process"; const NOTIFICATION_BODY = 'Notification from the Main process'
new Notification({ new Notification({
title: NOTIFICATION_TITLE, title: NOTIFICATION_TITLE,
body: NOTIFICATION_BODY, body: NOTIFICATION_BODY
}).show(); }).show()
``` ```
Here's a full example that you can open with Electron Fiddle: Here's a full example that you can open with Electron Fiddle:
```javascript fiddle='docs/fiddles/features/notifications/main' ```javascript fiddle='docs/fiddles/features/notifications/main'
const { Notification } = require("electron"); const { Notification } = require('electron')
const NOTIFICATION_TITLE = "Basic Notification"; const NOTIFICATION_TITLE = 'Basic Notification'
const NOTIFICATION_BODY = "Notification from the Main process"; const NOTIFICATION_BODY = 'Notification from the Main process'
new Notification({ new Notification({
title: NOTIFICATION_TITLE, title: NOTIFICATION_TITLE,
body: NOTIFICATION_BODY, body: NOTIFICATION_BODY
}).show(); }).show()
``` ```
### Show notifications in the renderer process ### Show notifications in the renderer process
@@ -48,25 +48,25 @@ Notifications can be displayed directly from the renderer process with the
[web Notifications API](https://developer.mozilla.org/en-US/docs/Web/API/Notifications_API/Using_the_Notifications_API). [web Notifications API](https://developer.mozilla.org/en-US/docs/Web/API/Notifications_API/Using_the_Notifications_API).
```js title='Renderer Process' ```js title='Renderer Process'
const NOTIFICATION_TITLE = "Title"; const NOTIFICATION_TITLE = 'Title'
const NOTIFICATION_BODY = const NOTIFICATION_BODY =
"Notification from the Renderer process. Click to log to console."; 'Notification from the Renderer process. Click to log to console.'
const CLICK_MESSAGE = "Notification clicked"; const CLICK_MESSAGE = 'Notification clicked'
new Notification(NOTIFICATION_TITLE, { body: NOTIFICATION_BODY }).onclick = new Notification(NOTIFICATION_TITLE, { body: NOTIFICATION_BODY }).onclick =
() => console.log(CLICK_MESSAGE); () => console.log(CLICK_MESSAGE)
``` ```
Here's a full example that you can open with Electron Fiddle: Here's a full example that you can open with Electron Fiddle:
```javascript fiddle='docs/fiddles/features/notifications/renderer' ```javascript fiddle='docs/fiddles/features/notifications/renderer'
const NOTIFICATION_TITLE = "Title"; const NOTIFICATION_TITLE = 'Title'
const NOTIFICATION_BODY = const NOTIFICATION_BODY =
"Notification from the Renderer process. Click to log to console."; 'Notification from the Renderer process. Click to log to console.'
const CLICK_MESSAGE = "Notification clicked"; const CLICK_MESSAGE = 'Notification clicked'
new Notification(NOTIFICATION_TITLE, { body: NOTIFICATION_BODY }).onclick = new Notification(NOTIFICATION_TITLE, { body: NOTIFICATION_BODY }).onclick =
() => console.log(CLICK_MESSAGE); () => console.log(CLICK_MESSAGE)
``` ```
## Platform considerations ## Platform considerations
@@ -146,6 +146,6 @@ GNOME, and KDE.
[set-app-user-model-id]: ../api/app.md#appsetappusermodelidid-windows [set-app-user-model-id]: ../api/app.md#appsetappusermodelidid-windows
[squirrel-events]: https://github.com/electron/windows-installer/blob/main/README.md#handling-squirrel-events [squirrel-events]: https://github.com/electron/windows-installer/blob/main/README.md#handling-squirrel-events
[toast-activator-clsid]: https://learn.microsoft.com/en-us/windows/win32/properties/props-system-appusermodel-toastactivatorclsid [toast-activator-clsid]: https://learn.microsoft.com/en-us/windows/win32/properties/props-system-appusermodel-toastactivatorclsid
[apple-notification-guidelines]: https://developer.apple.com/macos/human-interface-guidelines/system-capabilities/notifications/ [apple-notification-guidelines]: https://developer.apple.com/design/human-interface-guidelines/notifications
[windows-notification-state]: https://github.com/felixrieseberg/windows-notification-state [windows-notification-state]: https://github.com/felixrieseberg/windows-notification-state
[macos-notification-state]: https://github.com/felixrieseberg/macos-notification-state [macos-notification-state]: https://github.com/felixrieseberg/macos-notification-state

View File

@@ -172,7 +172,7 @@ in the fictitious `.foo` format. In order to do that, it relies on the
equally fictitious `foo-parser` module. In traditional Node.js development, equally fictitious `foo-parser` module. In traditional Node.js development,
you might write code that eagerly loads dependencies: you might write code that eagerly loads dependencies:
```js title='parser.js' ```js title='parser.js' @ts-expect-error=[2]
const fs = require('fs') const fs = require('fs')
const fooParser = require('foo-parser') const fooParser = require('foo-parser')
@@ -195,7 +195,7 @@ In the above example, we're doing a lot of work that's being executed as soon
as the file is loaded. Do we need to get parsed files right away? Could we as the file is loaded. Do we need to get parsed files right away? Could we
do this work a little later, when `getParsedFiles()` is actually called? do this work a little later, when `getParsedFiles()` is actually called?
```js title='parser.js' ```js title='parser.js' @ts-expect-error=[20]
// "fs" is likely already being loaded, so the `require()` call is cheap // "fs" is likely already being loaded, so the `require()` call is cheap
const fs = require('fs') const fs = require('fs')
@@ -204,7 +204,7 @@ class Parser {
// Touch the disk as soon as `getFiles` is called, not sooner. // Touch the disk as soon as `getFiles` is called, not sooner.
// Also, ensure that we're not blocking other operations by using // Also, ensure that we're not blocking other operations by using
// the asynchronous version. // the asynchronous version.
this.files = this.files || await fs.readdir('.') this.files = this.files || await fs.promises.readdir('.')
return this.files return this.files
} }

View File

@@ -158,13 +158,13 @@ A preload script can be attached to the main process in the `BrowserWindow` cons
```js title='main.js' ```js title='main.js'
const { BrowserWindow } = require('electron') const { BrowserWindow } = require('electron')
//... // ...
const win = new BrowserWindow({ const win = new BrowserWindow({
webPreferences: { webPreferences: {
preload: 'path/to/preload.js', preload: 'path/to/preload.js'
}, }
}) })
//... // ...
``` ```
Because the preload script shares a global [`Window`][window-mdn] interface with the Because the preload script shares a global [`Window`][window-mdn] interface with the
@@ -175,13 +175,13 @@ Although preload scripts share a `window` global with the renderer they're attac
you cannot directly attach any variables from the preload script to `window` because of you cannot directly attach any variables from the preload script to `window` because of
the [`contextIsolation`][context-isolation] default. the [`contextIsolation`][context-isolation] default.
```js title='preload.js' ```js title='preload.js' @ts-nocheck
window.myAPI = { window.myAPI = {
desktop: true, desktop: true
} }
``` ```
```js title='renderer.js' ```js title='renderer.js' @ts-nocheck
console.log(window.myAPI) console.log(window.myAPI)
// => undefined // => undefined
``` ```
@@ -196,11 +196,11 @@ securely:
const { contextBridge } = require('electron') const { contextBridge } = require('electron')
contextBridge.exposeInMainWorld('myAPI', { contextBridge.exposeInMainWorld('myAPI', {
desktop: true, desktop: true
}) })
``` ```
```js title='renderer.js' ```js title='renderer.js' @ts-nocheck
console.log(window.myAPI) console.log(window.myAPI)
// => { desktop: true } // => { desktop: true }
``` ```

View File

@@ -182,7 +182,7 @@ In Electron, browser windows can only be created after the `app` module's
[`app.whenReady()`][app-when-ready] API. Call `createWindow()` after `whenReady()` [`app.whenReady()`][app-when-ready] API. Call `createWindow()` after `whenReady()`
resolves its Promise. resolves its Promise.
```js ```js @ts-type={createWindow:()=>void}
app.whenReady().then(() => { app.whenReady().then(() => {
createWindow() createWindow()
}) })
@@ -239,7 +239,7 @@ from within your existing `whenReady()` callback.
[activate]: ../api/app.md#event-activate-macos [activate]: ../api/app.md#event-activate-macos
```js ```js @ts-type={createWindow:()=>void}
app.whenReady().then(() => { app.whenReady().then(() => {
createWindow() createWindow()
@@ -290,6 +290,7 @@ To attach this script to your renderer process, pass in the path to your preload
to the `webPreferences.preload` option in your existing `BrowserWindow` constructor. to the `webPreferences.preload` option in your existing `BrowserWindow` constructor.
```js ```js
const { app, BrowserWindow } = require('electron')
// include the Node.js 'path' module at the top of your file // include the Node.js 'path' module at the top of your file
const path = require('path') const path = require('path')

View File

@@ -29,7 +29,7 @@ To set the represented file of window, you can use the
```javascript fiddle='docs/fiddles/features/represented-file' ```javascript fiddle='docs/fiddles/features/represented-file'
const { app, BrowserWindow } = require('electron') const { app, BrowserWindow } = require('electron')
const os = require('os'); const os = require('os')
const createWindow = () => { const createWindow = () => {
const win = new BrowserWindow({ const win = new BrowserWindow({

View File

@@ -46,7 +46,7 @@ scripts attached to sandboxed renderers will still have a polyfilled subset of N
APIs available. A `require` function similar to Node's `require` module is exposed, APIs available. A `require` function similar to Node's `require` module is exposed,
but can only import a subset of Electron and Node's built-in modules: but can only import a subset of Electron and Node's built-in modules:
* `electron` (only renderer process modules) * `electron` (following renderer process modules: `contextBridge`, `crashReporter`, `ipcRenderer`, `nativeImage`, `webFrame`)
* [`events`](https://nodejs.org/api/events.html) * [`events`](https://nodejs.org/api/events.html)
* [`timers`](https://nodejs.org/api/timers.html) * [`timers`](https://nodejs.org/api/timers.html)
* [`url`](https://nodejs.org/api/url.html) * [`url`](https://nodejs.org/api/url.html)

View File

@@ -9,7 +9,7 @@ toc_max_heading_level: 3
:::info Reporting security issues :::info Reporting security issues
For information on how to properly disclose an Electron vulnerability, For information on how to properly disclose an Electron vulnerability,
see [SECURITY.md](https://github.com/electron/electron/tree/main/SECURITY.md). see [SECURITY.md](https://github.com/electron/electron/blob/main/SECURITY.md).
For upstream Chromium vulnerabilities: Electron keeps up to date with alternating For upstream Chromium vulnerabilities: Electron keeps up to date with alternating
Chromium releases. For more information, see the Chromium releases. For more information, see the
@@ -141,7 +141,7 @@ like `HTTP`. Similarly, we recommend the use of `WSS` over `WS`, `FTPS` over
#### How? #### How?
```js title='main.js (Main Process)' ```js title='main.js (Main Process)' @ts-type={browserWindow:Electron.BrowserWindow}
// Bad // Bad
browserWindow.loadURL('http://example.com') browserWindow.loadURL('http://example.com')
@@ -278,7 +278,7 @@ security-conscious developers might want to assume the very opposite.
```js title='main.js (Main Process)' ```js title='main.js (Main Process)'
const { session } = require('electron') const { session } = require('electron')
const URL = require('url').URL const { URL } = require('url')
session session
.fromPartition('some-partition') .fromPartition('some-partition')
@@ -608,7 +608,8 @@ sometimes be fooled - a `startsWith('https://example.com')` test would let
`https://example.com.attacker.com` through. `https://example.com.attacker.com` through.
```js title='main.js (Main Process)' ```js title='main.js (Main Process)'
const URL = require('url').URL const { URL } = require('url')
const { app } = require('electron')
app.on('web-contents-created', (event, contents) => { app.on('web-contents-created', (event, contents) => {
contents.on('will-navigate', (event, navigationUrl) => { contents.on('will-navigate', (event, navigationUrl) => {
@@ -647,8 +648,8 @@ receive, amongst other parameters, the `url` the window was requested to open
and the options used to create it. We recommend that you register a handler to and the options used to create it. We recommend that you register a handler to
monitor the creation of windows, and deny any unexpected window creation. monitor the creation of windows, and deny any unexpected window creation.
```js title='main.js (Main Process)' ```js title='main.js (Main Process)' @ts-type={isSafeForExternalOpen:(url:string)=>boolean}
const { shell } = require('electron') const { app, shell } = require('electron')
app.on('web-contents-created', (event, contents) => { app.on('web-contents-created', (event, contents) => {
contents.setWindowOpenHandler(({ url }) => { contents.setWindowOpenHandler(({ url }) => {
@@ -683,7 +684,7 @@ leveraged to execute arbitrary commands.
#### How? #### How?
```js title='main.js (Main Process)' ```js title='main.js (Main Process)' @ts-type={USER_CONTROLLED_DATA_HERE:string}
// Bad // Bad
const { shell } = require('electron') const { shell } = require('electron')
shell.openExternal(USER_CONTROLLED_DATA_HERE) shell.openExternal(USER_CONTROLLED_DATA_HERE)
@@ -739,22 +740,22 @@ You should be validating the `sender` of **all** IPC messages by default.
#### How? #### How?
```js title='main.js (Main Process)' ```js title='main.js (Main Process)' @ts-type={getSecrets:()=>unknown}
// Bad // Bad
ipcMain.handle('get-secrets', () => { ipcMain.handle('get-secrets', () => {
return getSecrets(); return getSecrets()
}); })
// Good // Good
ipcMain.handle('get-secrets', (e) => { ipcMain.handle('get-secrets', (e) => {
if (!validateSender(e.senderFrame)) return null; if (!validateSender(e.senderFrame)) return null
return getSecrets(); return getSecrets()
}); })
function validateSender(frame) { function validateSender (frame) {
// Value the host of the URL using an actual URL parser and an allowlist // Value the host of the URL using an actual URL parser and an allowlist
if ((new URL(frame.url)).host === 'electronjs.org') return true; if ((new URL(frame.url)).host === 'electronjs.org') return true
return false; return false
} }
``` ```

View File

@@ -72,7 +72,7 @@ npx electron-installer-snap --src=out/myappname-linux-x64
If you have an existing build pipeline, you can use `electron-installer-snap` If you have an existing build pipeline, you can use `electron-installer-snap`
programmatically. For more information, see the [Snapcraft API docs][snapcraft-syntax]. programmatically. For more information, see the [Snapcraft API docs][snapcraft-syntax].
```js ```js @ts-nocheck
const snap = require('electron-installer-snap') const snap = require('electron-installer-snap')
snap(options) snap(options)
@@ -241,5 +241,5 @@ apps:
[electron-packager]: https://github.com/electron/electron-packager [electron-packager]: https://github.com/electron/electron-packager
[electron-forge]: https://github.com/electron/forge [electron-forge]: https://github.com/electron/forge
[electron-builder]: https://github.com/electron-userland/electron-builder [electron-builder]: https://github.com/electron-userland/electron-builder
[electron-installer-debian]: https://github.com/unindented/electron-installer-debian [electron-installer-debian]: https://github.com/electron-userland/electron-installer-debian
[electron-winstaller]: https://github.com/electron/windows-installer [electron-winstaller]: https://github.com/electron/windows-installer

View File

@@ -20,12 +20,12 @@ On macOS as we use the native APIs there is no way to set the language that the
For Windows and Linux there are a few Electron APIs you should use to set the languages for the spellchecker. For Windows and Linux there are a few Electron APIs you should use to set the languages for the spellchecker.
```js ```js @ts-type={myWindow:Electron.BrowserWindow}
// Sets the spellchecker to check English US and French // Sets the spellchecker to check English US and French
myWindow.session.setSpellCheckerLanguages(['en-US', 'fr']) myWindow.webContents.session.setSpellCheckerLanguages(['en-US', 'fr'])
// An array of all available language codes // An array of all available language codes
const possibleLanguages = myWindow.session.availableSpellCheckerLanguages const possibleLanguages = myWindow.webContents.session.availableSpellCheckerLanguages
``` ```
By default the spellchecker will enable the language matching the current OS locale. By default the spellchecker will enable the language matching the current OS locale.
@@ -35,7 +35,7 @@ By default the spellchecker will enable the language matching the current OS loc
All the required information to generate a context menu is provided in the [`context-menu`](../api/web-contents.md#event-context-menu) event on each `webContents` instance. A small example All the required information to generate a context menu is provided in the [`context-menu`](../api/web-contents.md#event-context-menu) event on each `webContents` instance. A small example
of how to make a context menu with this information is provided below. of how to make a context menu with this information is provided below.
```js ```js @ts-type={myWindow:Electron.BrowserWindow}
const { Menu, MenuItem } = require('electron') const { Menu, MenuItem } = require('electron')
myWindow.webContents.on('context-menu', (event, params) => { myWindow.webContents.on('context-menu', (event, params) => {
@@ -45,7 +45,7 @@ myWindow.webContents.on('context-menu', (event, params) => {
for (const suggestion of params.dictionarySuggestions) { for (const suggestion of params.dictionarySuggestions) {
menu.append(new MenuItem({ menu.append(new MenuItem({
label: suggestion, label: suggestion,
click: () => mainWindow.webContents.replaceMisspelling(suggestion) click: () => myWindow.webContents.replaceMisspelling(suggestion)
})) }))
} }
@@ -54,7 +54,7 @@ myWindow.webContents.on('context-menu', (event, params) => {
menu.append( menu.append(
new MenuItem({ new MenuItem({
label: 'Add to dictionary', label: 'Add to dictionary',
click: () => mainWindow.webContents.session.addWordToSpellCheckerDictionary(params.misspelledWord) click: () => myWindow.webContents.session.addWordToSpellCheckerDictionary(params.misspelledWord)
}) })
) )
} }
@@ -67,8 +67,8 @@ myWindow.webContents.on('context-menu', (event, params) => {
Although the spellchecker itself does not send any typings, words or user input to Google services the hunspell dictionary files are downloaded from a Google CDN by default. If you want to avoid this you can provide an alternative URL to download the dictionaries from. Although the spellchecker itself does not send any typings, words or user input to Google services the hunspell dictionary files are downloaded from a Google CDN by default. If you want to avoid this you can provide an alternative URL to download the dictionaries from.
```js ```js @ts-type={myWindow:Electron.BrowserWindow}
myWindow.session.setSpellCheckerDictionaryDownloadURL('https://example.com/dictionaries/') myWindow.webContents.session.setSpellCheckerDictionaryDownloadURL('https://example.com/dictionaries/')
``` ```
Check out the docs for [`session.setSpellCheckerDictionaryDownloadURL`](../api/session.md#sessetspellcheckerdictionarydownloadurlurl) for more information on where to get the dictionary files from and how you need to host them. Check out the docs for [`session.setSpellCheckerDictionaryDownloadURL`](../api/session.md#sessetspellcheckerdictionarydownloadurlurl) for more information on where to get the dictionary files from and how you need to host them.

View File

@@ -51,7 +51,7 @@ app.whenReady().then(() => {
Great! Now we can start attaching a context menu to our Tray, like so: Great! Now we can start attaching a context menu to our Tray, like so:
```js ```js @ts-expect-error=[8]
const contextMenu = Menu.buildFromTemplate([ const contextMenu = Menu.buildFromTemplate([
{ label: 'Item1', type: 'radio' }, { label: 'Item1', type: 'radio' },
{ label: 'Item2', type: 'radio' }, { label: 'Item2', type: 'radio' },
@@ -68,7 +68,7 @@ To read more about constructing native menus, click
Finally, let's give our tray a tooltip and a title. Finally, let's give our tray a tooltip and a title.
```js ```js @ts-type={tray:Electron.Tray}
tray.setToolTip('This is my application') tray.setToolTip('This is my application')
tray.setTitle('This is my title') tray.setTitle('This is my title')
``` ```

View File

@@ -125,7 +125,7 @@ main process entry point is configured correctly. Create a `main.js` file in the
of your project with a single line of code: of your project with a single line of code:
```js title='main.js' ```js title='main.js'
console.log(`Hello from Electron 👋`) console.log('Hello from Electron 👋')
``` ```
Because Electron's main process is a Node.js runtime, you can execute arbitrary Node.js code Because Electron's main process is a Node.js runtime, you can execute arbitrary Node.js code
@@ -134,7 +134,7 @@ add `electron .` to the `start` command in the [`scripts`][package-scripts]
field of your package.json. This command will tell the Electron executable to look for the main field of your package.json. This command will tell the Electron executable to look for the main
script in the current directory and run it in dev mode. script in the current directory and run it in dev mode.
```json {8-10} title='package.json' ```json {7} title='package.json'
{ {
"name": "my-electron-app", "name": "my-electron-app",
"version": "1.0.0", "version": "1.0.0",
@@ -199,7 +199,7 @@ const { app, BrowserWindow } = require('electron')
const createWindow = () => { const createWindow = () => {
const win = new BrowserWindow({ const win = new BrowserWindow({
width: 800, width: 800,
height: 600, height: 600
}) })
win.loadFile('index.html') win.loadFile('index.html')
@@ -247,7 +247,7 @@ The `createWindow()` function loads your web page into a new BrowserWindow insta
const createWindow = () => { const createWindow = () => {
const win = new BrowserWindow({ const win = new BrowserWindow({
width: 800, width: 800,
height: 600, height: 600
}) })
win.loadFile('index.html') win.loadFile('index.html')
@@ -256,7 +256,7 @@ const createWindow = () => {
### Calling your function when the app is ready ### Calling your function when the app is ready
```js title='main.js (Lines 12-14)' ```js title='main.js (Lines 12-14)' @ts-type={createWindow:()=>void}
app.whenReady().then(() => { app.whenReady().then(() => {
createWindow() createWindow()
}) })
@@ -274,7 +274,7 @@ calling `createWindow()` once its promise is fulfilled.
You typically listen to Node.js events by using an emitter's `.on` function. You typically listen to Node.js events by using an emitter's `.on` function.
```diff ```diff
+ app.on('ready').then(() => { + app.on('ready', () => {
- app.whenReady().then(() => { - app.whenReady().then(() => {
createWindow() createWindow()
}) })
@@ -336,7 +336,7 @@ Because windows cannot be created before the `ready` event, you should only list
`activate` events after your app is initialized. Do this by only listening for activate `activate` events after your app is initialized. Do this by only listening for activate
events inside your existing `whenReady()` callback. events inside your existing `whenReady()` callback.
```js ```js @ts-type={createWindow:()=>void}
app.whenReady().then(() => { app.whenReady().then(() => {
createWindow() createWindow()

View File

@@ -73,7 +73,7 @@ const { contextBridge } = require('electron')
contextBridge.exposeInMainWorld('versions', { contextBridge.exposeInMainWorld('versions', {
node: () => process.versions.node, node: () => process.versions.node,
chrome: () => process.versions.chrome, chrome: () => process.versions.chrome,
electron: () => process.versions.electron, electron: () => process.versions.electron
// we can also expose variables, not just functions // we can also expose variables, not just functions
}) })
``` ```
@@ -90,8 +90,8 @@ const createWindow = () => {
width: 800, width: 800,
height: 600, height: 600,
webPreferences: { webPreferences: {
preload: path.join(__dirname, 'preload.js'), preload: path.join(__dirname, 'preload.js')
}, }
}) })
win.loadFile('index.html') win.loadFile('index.html')
@@ -118,7 +118,7 @@ information in the window. This variable can be accessed via `window.versions` o
`versions`. Create a `renderer.js` script that uses the [`document.getElementById`][] `versions`. Create a `renderer.js` script that uses the [`document.getElementById`][]
DOM API to replace the displayed text for the HTML element with `info` as its `id` property. DOM API to replace the displayed text for the HTML element with `info` as its `id` property.
```js title="renderer.js" ```js title="renderer.js" @ts-nocheck
const information = document.getElementById('info') const information = document.getElementById('info')
information.innerText = `This app is using Chrome (v${versions.chrome()}), Node.js (v${versions.node()}), and Electron (v${versions.electron()})` information.innerText = `This app is using Chrome (v${versions.chrome()}), Node.js (v${versions.node()}), and Electron (v${versions.electron()})`
``` ```
@@ -183,7 +183,7 @@ contextBridge.exposeInMainWorld('versions', {
node: () => process.versions.node, node: () => process.versions.node,
chrome: () => process.versions.chrome, chrome: () => process.versions.chrome,
electron: () => process.versions.electron, electron: () => process.versions.electron,
ping: () => ipcRenderer.invoke('ping'), ping: () => ipcRenderer.invoke('ping')
// we can also expose variables, not just functions // we can also expose variables, not just functions
}) })
``` ```
@@ -202,7 +202,7 @@ Then, set up your `handle` listener in the main process. We do this _before_
loading the HTML file so that the handler is guaranteed to be ready before loading the HTML file so that the handler is guaranteed to be ready before
you send out the `invoke` call from the renderer. you send out the `invoke` call from the renderer.
```js {1,12} title="main.js" ```js {1,15} title="main.js"
const { app, BrowserWindow, ipcMain } = require('electron') const { app, BrowserWindow, ipcMain } = require('electron')
const path = require('path') const path = require('path')
@@ -211,19 +211,21 @@ const createWindow = () => {
width: 800, width: 800,
height: 600, height: 600,
webPreferences: { webPreferences: {
preload: path.join(__dirname, 'preload.js'), preload: path.join(__dirname, 'preload.js')
}, }
}) })
ipcMain.handle('ping', () => 'pong')
win.loadFile('index.html') win.loadFile('index.html')
} }
app.whenReady().then(createWindow) app.whenReady().then(() => {
ipcMain.handle('ping', () => 'pong')
createWindow()
})
``` ```
Once you have the sender and receiver set up, you can now send messages from the renderer Once you have the sender and receiver set up, you can now send messages from the renderer
to the main process through the `'ping'` channel you just defined. to the main process through the `'ping'` channel you just defined.
```js title='renderer.js' ```js title='renderer.js' @ts-expect-error=[2]
const func = async () => { const func = async () => {
const response = await window.versions.ping() const response = await window.versions.ping()
console.log(response) // prints out 'pong' console.log(response) // prints out 'pong'

View File

@@ -153,14 +153,14 @@ For more information on code signing, check out the
module.exports = { module.exports = {
packagerConfig: { packagerConfig: {
osxSign: {}, osxSign: {},
//... // ...
osxNotarize: { osxNotarize: {
tool: 'notarytool', tool: 'notarytool',
appleId: process.env.APPLE_ID, appleId: process.env.APPLE_ID,
appleIdPassword: process.env.APPLE_PASSWORD, appleIdPassword: process.env.APPLE_PASSWORD,
teamId: process.env.APPLE_TEAM_ID, teamId: process.env.APPLE_TEAM_ID
} }
//... // ...
} }
} }
``` ```
@@ -170,17 +170,17 @@ module.exports = {
```js title='forge.config.js' ```js title='forge.config.js'
module.exports = { module.exports = {
//... // ...
makers: [ makers: [
{ {
name: '@electron-forge/maker-squirrel', name: '@electron-forge/maker-squirrel',
config: { config: {
certificateFile: './cert.pfx', certificateFile: './cert.pfx',
certificatePassword: process.env.CERTIFICATE_PASSWORD, certificatePassword: process.env.CERTIFICATE_PASSWORD
}, }
}, }
], ]
//... // ...
} }
``` ```

View File

@@ -86,13 +86,13 @@ module.exports = {
config: { config: {
repository: { repository: {
owner: 'github-user-name', owner: 'github-user-name',
name: 'github-repo-name', name: 'github-repo-name'
}, },
prerelease: false, prerelease: false,
draft: true, draft: true
}, }
}, }
], ]
} }
``` ```
@@ -188,7 +188,7 @@ npm install update-electron-app
Then, import the module and call it immediately in the main process. Then, import the module and call it immediately in the main process.
```js title='main.js' ```js title='main.js' @ts-nocheck
require('update-electron-app')() require('update-electron-app')()
``` ```

View File

@@ -32,7 +32,7 @@ npm install update-electron-app
Then, invoke the updater from your app's main process file: Then, invoke the updater from your app's main process file:
```js title="main.js" ```js title="main.js" @ts-nocheck
require('update-electron-app')() require('update-electron-app')()
``` ```
@@ -104,8 +104,7 @@ setInterval(() => {
``` ```
Once your application is [packaged](./application-distribution.md), Once your application is [packaged](./application-distribution.md),
it will receive an update for each new it will receive an update for each new [GitHub Release][gh-releases] that you
[GitHub Release](https://help.github.com/articles/creating-releases/) that you
publish. publish.
### Step 3: Notifying users when updates are available ### Step 3: Notifying users when updates are available
@@ -114,7 +113,7 @@ Now that you've configured the basic update mechanism for your application, you
need to ensure that the user will get notified when there's an update. This need to ensure that the user will get notified when there's an update. This
can be achieved using the [autoUpdater API events](../api/auto-updater.md#events): can be achieved using the [autoUpdater API events](../api/auto-updater.md#events):
```javascript title="main.js" ```javascript title="main.js" @ts-expect-error=[11]
autoUpdater.on('update-downloaded', (event, releaseNotes, releaseName) => { autoUpdater.on('update-downloaded', (event, releaseNotes, releaseName) => {
const dialogOpts = { const dialogOpts = {
type: 'info', type: 'info',
@@ -122,7 +121,7 @@ autoUpdater.on('update-downloaded', (event, releaseNotes, releaseName) => {
title: 'Application Update', title: 'Application Update',
message: process.platform === 'win32' ? releaseNotes : releaseName, message: process.platform === 'win32' ? releaseNotes : releaseName,
detail: detail:
'A new version has been downloaded. Restart the application to apply the updates.', 'A new version has been downloaded. Restart the application to apply the updates.'
} }
dialog.showMessageBox(dialogOpts).then((returnValue) => { dialog.showMessageBox(dialogOpts).then((returnValue) => {
@@ -155,7 +154,7 @@ server-communication aspect of the process by loading your update from a local d
[vercel]: https://vercel.com [vercel]: https://vercel.com
[hazel]: https://github.com/vercel/hazel [hazel]: https://github.com/vercel/hazel
[nuts]: https://github.com/GitbookIO/nuts [nuts]: https://github.com/GitbookIO/nuts
[gh-releases]: https://help.github.com/articles/creating-releases/ [gh-releases]: https://docs.github.com/en/repositories/releasing-projects-on-github/managing-releases-in-a-repository#creating-a-release
[electron-release-server]: https://github.com/ArekSredzki/electron-release-server [electron-release-server]: https://github.com/ArekSredzki/electron-release-server
[nucleus]: https://github.com/atlassian/nucleus [nucleus]: https://github.com/atlassian/nucleus
[update.electronjs.org]: https://github.com/electron/update.electronjs.org [update.electronjs.org]: https://github.com/electron/update.electronjs.org

View File

@@ -196,9 +196,9 @@ const win = new BrowserWindow({
} }
}) })
ipcMain.on('set-ignore-mouse-events', (event, ...args) => { ipcMain.on('set-ignore-mouse-events', (event, ignore, options) => {
const win = BrowserWindow.fromWebContents(event.sender) const win = BrowserWindow.fromWebContents(event.sender)
win.setIgnoreMouseEvents(...args) win.setIgnoreMouseEvents(ignore, options)
}) })
``` ```

View File

@@ -152,7 +152,7 @@ Once installation succeeded, you can move on to compiling your Electron app.
[app-converter]: https://docs.microsoft.com/en-us/windows/uwp/porting/desktop-to-uwp-run-desktop-app-converter [app-converter]: https://docs.microsoft.com/en-us/windows/uwp/porting/desktop-to-uwp-run-desktop-app-converter
[add-appxpackage]: https://technet.microsoft.com/en-us/library/hh856048.aspx [add-appxpackage]: https://technet.microsoft.com/en-us/library/hh856048.aspx
[electron-packager]: https://github.com/electron/electron-packager [electron-packager]: https://github.com/electron/electron-packager
[electron-windows-store]: https://github.com/catalystcode/electron-windows-store [electron-windows-store]: https://github.com/electron-userland/electron-windows-store
[background-task]: https://github.com/felixrieseberg/electron-uwp-background [background-task]: https://github.com/felixrieseberg/electron-uwp-background
[centennial-campaigns]: https://developer.microsoft.com/en-us/windows/projects/campaigns/desktop-bridge [centennial-campaigns]: https://developer.microsoft.com/en-us/windows/projects/campaigns/desktop-bridge
[how-to-update]: https://blogs.windows.com/windowsexperience/2016/08/02/how-to-get-the-windows-10-anniversary-update [how-to-update]: https://blogs.windows.com/windowsexperience/2016/08/02/how-to-get-the-windows-10-anniversary-update

View File

@@ -125,7 +125,7 @@ Starting with a working application from the
following lines: following lines:
```javascript ```javascript
const { BrowserWindow } = require('electron') const { BrowserWindow, nativeImage } = require('electron')
const path = require('path') const path = require('path')
const win = new BrowserWindow() const win = new BrowserWindow()
@@ -133,11 +133,11 @@ const win = new BrowserWindow()
win.setThumbarButtons([ win.setThumbarButtons([
{ {
tooltip: 'button1', tooltip: 'button1',
icon: path.join(__dirname, 'button1.png'), icon: nativeImage.createFromPath(path.join(__dirname, 'button1.png')),
click () { console.log('button1 clicked') } click () { console.log('button1 clicked') }
}, { }, {
tooltip: 'button2', tooltip: 'button2',
icon: path.join(__dirname, 'button2.png'), icon: nativeImage.createFromPath(path.join(__dirname, 'button2.png')),
flags: ['enabled', 'dismissonclick'], flags: ['enabled', 'dismissonclick'],
click () { console.log('button2 clicked.') } click () { console.log('button2 clicked.') }
} }
@@ -189,11 +189,11 @@ Starting with a working application from the
following lines: following lines:
```javascript ```javascript
const { BrowserWindow } = require('electron') const { BrowserWindow, nativeImage } = require('electron')
const win = new BrowserWindow() const win = new BrowserWindow()
win.setOverlayIcon('path/to/overlay.png', 'Description for overlay') win.setOverlayIcon(nativeImage.createFromPath('path/to/overlay.png'), 'Description for overlay')
``` ```
[msdn-icon-overlay]: https://learn.microsoft.com/en-us/windows/win32/shell/taskbar-extensions#icon-overlays [msdn-icon-overlay]: https://learn.microsoft.com/en-us/windows/win32/shell/taskbar-extensions#icon-overlays

View File

@@ -637,8 +637,6 @@ filenames = {
"shell/common/language_util.h", "shell/common/language_util.h",
"shell/common/logging.cc", "shell/common/logging.cc",
"shell/common/logging.h", "shell/common/logging.h",
"shell/common/mouse_util.cc",
"shell/common/mouse_util.h",
"shell/common/node_bindings.cc", "shell/common/node_bindings.cc",
"shell/common/node_bindings.h", "shell/common/node_bindings.h",
"shell/common/node_includes.h", "shell/common/node_includes.h",

View File

@@ -304,7 +304,6 @@ libcxx_headers = [
"//buildtools/third_party/libc++/trunk/include/__coroutine/trivial_awaitables.h", "//buildtools/third_party/libc++/trunk/include/__coroutine/trivial_awaitables.h",
"//buildtools/third_party/libc++/trunk/include/__debug", "//buildtools/third_party/libc++/trunk/include/__debug",
"//buildtools/third_party/libc++/trunk/include/__debug_utils/randomize_range.h", "//buildtools/third_party/libc++/trunk/include/__debug_utils/randomize_range.h",
"//buildtools/third_party/libc++/trunk/include/__errc",
"//buildtools/third_party/libc++/trunk/include/__exception/exception.h", "//buildtools/third_party/libc++/trunk/include/__exception/exception.h",
"//buildtools/third_party/libc++/trunk/include/__exception/exception_ptr.h", "//buildtools/third_party/libc++/trunk/include/__exception/exception_ptr.h",
"//buildtools/third_party/libc++/trunk/include/__exception/nested_exception.h", "//buildtools/third_party/libc++/trunk/include/__exception/nested_exception.h",
@@ -571,7 +570,6 @@ libcxx_headers = [
"//buildtools/third_party/libc++/trunk/include/__ranges/views.h", "//buildtools/third_party/libc++/trunk/include/__ranges/views.h",
"//buildtools/third_party/libc++/trunk/include/__ranges/zip_view.h", "//buildtools/third_party/libc++/trunk/include/__ranges/zip_view.h",
"//buildtools/third_party/libc++/trunk/include/__split_buffer", "//buildtools/third_party/libc++/trunk/include/__split_buffer",
"//buildtools/third_party/libc++/trunk/include/__std_stream",
"//buildtools/third_party/libc++/trunk/include/__string/char_traits.h", "//buildtools/third_party/libc++/trunk/include/__string/char_traits.h",
"//buildtools/third_party/libc++/trunk/include/__string/constexpr_c_functions.h", "//buildtools/third_party/libc++/trunk/include/__string/constexpr_c_functions.h",
"//buildtools/third_party/libc++/trunk/include/__string/extern_template_lists.h", "//buildtools/third_party/libc++/trunk/include/__string/extern_template_lists.h",
@@ -591,20 +589,25 @@ libcxx_headers = [
"//buildtools/third_party/libc++/trunk/include/__support/xlocale/__nop_locale_mgmt.h", "//buildtools/third_party/libc++/trunk/include/__support/xlocale/__nop_locale_mgmt.h",
"//buildtools/third_party/libc++/trunk/include/__support/xlocale/__posix_l_fallback.h", "//buildtools/third_party/libc++/trunk/include/__support/xlocale/__posix_l_fallback.h",
"//buildtools/third_party/libc++/trunk/include/__support/xlocale/__strtonum_fallback.h", "//buildtools/third_party/libc++/trunk/include/__support/xlocale/__strtonum_fallback.h",
"//buildtools/third_party/libc++/trunk/include/__system_error/errc.h",
"//buildtools/third_party/libc++/trunk/include/__system_error/error_category.h",
"//buildtools/third_party/libc++/trunk/include/__system_error/error_code.h",
"//buildtools/third_party/libc++/trunk/include/__system_error/error_condition.h",
"//buildtools/third_party/libc++/trunk/include/__system_error/system_error.h",
"//buildtools/third_party/libc++/trunk/include/__thread/poll_with_backoff.h", "//buildtools/third_party/libc++/trunk/include/__thread/poll_with_backoff.h",
"//buildtools/third_party/libc++/trunk/include/__thread/timed_backoff_policy.h", "//buildtools/third_party/libc++/trunk/include/__thread/timed_backoff_policy.h",
"//buildtools/third_party/libc++/trunk/include/__threading_support", "//buildtools/third_party/libc++/trunk/include/__threading_support",
"//buildtools/third_party/libc++/trunk/include/__tree", "//buildtools/third_party/libc++/trunk/include/__tree",
"//buildtools/third_party/libc++/trunk/include/__tuple_dir/apply_cv.h", "//buildtools/third_party/libc++/trunk/include/__tuple/apply_cv.h",
"//buildtools/third_party/libc++/trunk/include/__tuple_dir/make_tuple_types.h", "//buildtools/third_party/libc++/trunk/include/__tuple/make_tuple_types.h",
"//buildtools/third_party/libc++/trunk/include/__tuple_dir/pair_like.h", "//buildtools/third_party/libc++/trunk/include/__tuple/pair_like.h",
"//buildtools/third_party/libc++/trunk/include/__tuple_dir/sfinae_helpers.h", "//buildtools/third_party/libc++/trunk/include/__tuple/sfinae_helpers.h",
"//buildtools/third_party/libc++/trunk/include/__tuple_dir/tuple_element.h", "//buildtools/third_party/libc++/trunk/include/__tuple/tuple_element.h",
"//buildtools/third_party/libc++/trunk/include/__tuple_dir/tuple_indices.h", "//buildtools/third_party/libc++/trunk/include/__tuple/tuple_indices.h",
"//buildtools/third_party/libc++/trunk/include/__tuple_dir/tuple_like.h", "//buildtools/third_party/libc++/trunk/include/__tuple/tuple_like.h",
"//buildtools/third_party/libc++/trunk/include/__tuple_dir/tuple_like_ext.h", "//buildtools/third_party/libc++/trunk/include/__tuple/tuple_like_ext.h",
"//buildtools/third_party/libc++/trunk/include/__tuple_dir/tuple_size.h", "//buildtools/third_party/libc++/trunk/include/__tuple/tuple_size.h",
"//buildtools/third_party/libc++/trunk/include/__tuple_dir/tuple_types.h", "//buildtools/third_party/libc++/trunk/include/__tuple/tuple_types.h",
"//buildtools/third_party/libc++/trunk/include/__type_traits/add_const.h", "//buildtools/third_party/libc++/trunk/include/__type_traits/add_const.h",
"//buildtools/third_party/libc++/trunk/include/__type_traits/add_cv.h", "//buildtools/third_party/libc++/trunk/include/__type_traits/add_cv.h",
"//buildtools/third_party/libc++/trunk/include/__type_traits/add_lvalue_reference.h", "//buildtools/third_party/libc++/trunk/include/__type_traits/add_lvalue_reference.h",

View File

@@ -12,6 +12,14 @@ BrowserWindow.prototype._init = function (this: BWT) {
// Avoid recursive require. // Avoid recursive require.
const { app } = require('electron'); const { app } = require('electron');
// Set ID at constructon time so it's accessible after
// underlying window destruction.
const id = this.id;
Object.defineProperty(this, 'id', {
value: id,
writable: false
});
const nativeSetBounds = this.setBounds; const nativeSetBounds = this.setBounds;
this.setBounds = (bounds, ...opts) => { this.setBounds = (bounds, ...opts) => {
bounds = { bounds = {

Some files were not shown because too many files have changed in this diff Show More