Compare commits

...

81 Commits

Author SHA1 Message Date
Shelley Vohr
8d689c565a fix: file selection when disallowed on macOS (#38557) 2023-06-05 14:08:10 +02:00
David Sanders
905aad9cb6 chore: type check JS in docs (#38423)
* build(deps): update @electron/lint-roller

* chore: type check JS in docs

* docs: add @ts-check and @ts-expect-error to code blocks

* chore: fix type check errors in docs

* chore: add ts-type to blocks
2023-06-05 16:26:26 +09:00
David Sanders
4c89061e0e docs: fix SerialPort typing (#38544) 2023-06-05 15:58:30 +09:00
Milan Burda
8fdd7de3d2 docs: clarify which electron modules are exposed in sandboxed renderers (#38568) 2023-06-05 15:57:15 +09:00
Charles Kerr
83d023747c refactor: use direct aggregation in NativeWindowViews (#38559)
* refactor: in NativeWindowViews, aggregate root_view_ directly

* refactor: in NativeWindowViews, aggregate keyboard_event_handler_ directly

* refactor: make NativeWindowClientView::window_ a raw_ref

Xref: https://chromium.googlesource.com/chromium/src/+/main/styleguide/c++/c++.md\#non_owning-pointers-in-class-fields

Prefer const raw_ref<T> whenever the held pointer will never be null

* chore: make lint happy
2023-06-05 14:37:46 +09:00
Charles Kerr
05db963f87 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.
2023-06-03 10:40:44 -05:00
Charles Kerr
f247ca3f62 perf: avoid unnecessary base value clone (#38537) 2023-06-02 08:38:29 -05:00
Shelley Vohr
d818f35ad4 build: fix doc-only early exit on Appveyor (#38547) 2023-06-01 10:40:35 -04:00
Sergey
9ffffdb6ef docs: fix performance tutorial (#38469)
* docs: fixed "Analyze runtime performance" link

* docs: added missing list item
2023-05-31 15:56:06 -04:00
Charles Kerr
c14f7b7d0b refactor: remove unused switches (#38497)
* refactor: remove unused declaration of electron::kSHA1Certificate

usage removed in 13a1d79

* refactor: remove unused declaration of electron::kSHA1MajorDescription

usage removed in 13a1d79

* refactor: remove unused declaration of electron::kSHA1MinorDescription

usage removed in 13a1d79

* refactor: remove unused declaration of electron::kCertificateError

usage removed in 13a1d79

* refactor: remove unused declaration of electron::kValidCertificate

usage removed in 13a1d79

* refactor: remove unused declaration of electron::kValidCertificateDescription

usage removed in 13a1d79

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

usage removed in 497f5a1

* refactor: remove electron::options::kPreloadScripts

removed in bad8d5e0

* refactor: remove electron::options::kImageAnimationPolicy

removed in 385d0f5
2023-05-31 15:55:21 -04:00
David Sanders
74b8133a93 ci: set description for release labels (#38528) 2023-05-31 15:49:16 -04:00
Shelley Vohr
57147d1b8d fix: navigator.connection not working as intended (#38491)
* fix: navigator.connection not working as intended

* chore: make network quality methods private
2023-05-31 11:06:25 -04:00
Milan Burda
67f273a6d6 docs: add <webview> new-window event removal to breaking-changes.md (#36985)
Co-authored-by: Milan Burda <miburda@microsoft.com>
2023-05-31 10:47:08 -04:00
Shelley Vohr
b454f8c7c1 build: combine and elaborate on exposed BoringSSL ciphers (#38506)
build: combine and elaborate on exposed BoringSSL ciphers
2023-05-31 10:30:04 -04:00
Shelley Vohr
663497dc6b chore: make contentTracing.stopRecording() failure clearer (#38488)
chore: make contentTracing.stopRecording() failure clearer
2023-05-31 09:54:41 -04:00
Shelley Vohr
115d37477e build: shrink unnecessary test changes in patch revert (#38505)
build: shrink unneccesary test changes in patch revert
2023-05-31 09:52:13 -04:00
Matt Henkes
2c742cfadb chore: cherry-pick 0e1cc35 from v8 (#38490) 2023-05-31 11:58:48 +02:00
Shelley Vohr
40e724e5dd fix: DCHECK minimizing parent window with non-modal child (#38460) 2023-05-31 11:57:44 +02:00
github-actions[bot]
13f9e2db40 build: update appveyor image to latest version (#38449)
Co-authored-by: jkleinsc <jkleinsc@users.noreply.github.com>
2023-05-30 21:13:33 -04:00
Shelley Vohr
a769b48164 ci: clean up docs only change logic (#38456) 2023-05-30 12:38:41 -04:00
John Kleinschmidt
b4ec363b3d feat: add USB protected classes handler (#38263)
* feat: add USB protected classes handler

* chore: apply review suggestions

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

* chore: update docs

* chore: apply review suggestions

* update doc per suggestion

---------

Co-authored-by: Charles Kerr <charles@charleskerr.com>
2023-05-30 12:35:25 -04:00
Milan Burda
71fb19ea14 chore: upgrade to eslint v8 (#38472)
chore: upgrade to eslint@8
2023-05-30 13:10:22 +02:00
Milan Burda
a6f7c7690d refactor: use literals instead of new RegExp() where possible (#38458) 2023-05-30 10:53:11 +02:00
Charles Kerr
0203bd3305 refactor: prefer base::Contains() over find() + end() (#38443)
* refactor: use base::Contains() in KeyWeakMap::Has()

* refactor: use base::Contains() in WebRequest::RequestFilter::MatchesType()

* refactor: use base::Contains() in BaseWindow::AddBrowserView()

* refactor: use base::Contains() in DeepFreeze()

* refactor: use base::Contains() in Clipboard::Read()

* Revert "refactor: use base::Contains() in BaseWindow::AddBrowserView()"
This reverts commit 60152359d3978451ebdd7c8eed602c2fb8a9cafa.

* refactor: use base::Contains() in BaseWindow::AddBrowserView()

* refactor: use base::Contains() in IsDevToolsFileSystemAdded()

* refactor: use base::Contains() in MessagePort::DisentanglePorts()

* refactor: use base::Contains() in PowerSaveBlocker::IsStarted()

* refactor: use base::Contains() in SpellCheckClient::OnSpellCheckDone()

* refactor: use base::Contains() in ShowTaskDialogWstr()

* refactor: use base::Contains() in PrintViewManagerElectron::ScriptedPrint()

* refactor: use base::Contains() in PrintViewManagerElectron::DidGetPrintedPagesCount()

* refactor: use base::Contains() in NativeWindow::AddDraggableRegionProvider()

* refactor: use base::Contains() in ElectronBindings::ActivateUVLoop()

* refactor: use base::Contains() in NativeWindowViews::IsVisibleOnAllWorkspaces()

* refactor: use base::Contains() in HidChooserController::OnDeviceAdded()

* refactor: use base::Contains() in ElectronSandboxedRendererClient::WillReleaseScriptContext()

* refactor: use base::Contains() in ElectronRendererClient::WillDestroyWorkerContextOnWorkerThread()

* refactor: use base::Contains() in GlobalShortcut::OnKeyPressed()
2023-05-30 10:28:43 +02:00
Shelley Vohr
9640ac441d build: make ReactiveObjC/Mantle deps format consistent (#38450) 2023-05-29 10:44:21 +02:00
Shelley Vohr
b233d0805a chore: process.mainModule -> require.main (#38452)
chore: process.mainModule -> require.main
2023-05-29 10:44:09 +02:00
Shelley Vohr
56138d879e fix: Windows FrameView always appearing inactive (#38468) 2023-05-28 18:39:13 -04:00
electron-roller[bot]
ddcec84ace chore: bump chromium to 116.0.5791.0 (main) (#38448)
* chore: bump chromium in DEPS to 116.0.5791.0

* 4504298: Relax checks in BlobDataBuilder::AppendBlob.

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

* chore: fixup patch indices

---------

Co-authored-by: electron-roller[bot] <84116207+electron-roller[bot]@users.noreply.github.com>
Co-authored-by: Shelley Vohr <shelley.vohr@gmail.com>
2023-05-25 16:10:08 +02:00
Milan Burda
185180a8e2 refactor: tweak bindings in typings/internal-ambient.d.ts for readability (#38411)
Co-authored-by: Milan Burda <miburda@microsoft.com>
2023-05-25 14:53:23 +02:00
Milan Burda
470b1d9e9d refactor: split clipboard module implementation for browser / renderer (#38429) 2023-05-25 20:36:12 +09:00
Charles Kerr
a20896f519 refactor: remove InspectableWebContents::GetAll() (#38442)
It is unused and also keeps a persistent std::list<>, so remove it.
2023-05-25 17:23:19 +09:00
electron-roller[bot]
64045fd058 chore: bump chromium to 115.0.5790.0 (main) (#38418)
* chore: bump chromium in DEPS to 115.0.5789.0

* 4550346: Revert "Convert /chrome/browser to use ARC"

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

* chore: update patches

* chore: bump chromium in DEPS to 115.0.5790.0

* chore: update patches

---------

Co-authored-by: electron-roller[bot] <84116207+electron-roller[bot]@users.noreply.github.com>
Co-authored-by: Shelley Vohr <shelley.vohr@gmail.com>
Co-authored-by: PatchUp <73610968+patchup[bot]@users.noreply.github.com>
2023-05-25 09:54:26 +02:00
David Sanders
294f196907 build: upgrade @electron/github-app-auth to 2.0.0 (#38435) 2023-05-25 09:54:09 +02:00
Milan Burda
82af000a37 chore: cleanup eslint suppressions (#38417)
* chore: cleanup eslint suppressions

* address feedback

* revert script/lib/azput.js

* revert spec/fixtures/apps/remote-control/main.js

* address feedback

* revert typings/internal-ambient.d.ts
2023-05-25 10:09:17 +09:00
github-actions[bot]
1c075e5ea0 chore: update appveyor image to latest version (#38426)
build: update appveyor image to latest version

Co-authored-by: jkleinsc <jkleinsc@users.noreply.github.com>
2023-05-24 17:03:14 -04:00
Shelley Vohr
ec85be3fb0 docs: ensure app.md examples are runnable (#38416)
docs: ensure app.md examples are runnable
2023-05-24 16:41:29 -04:00
Milan Burda
06cc9caeaa build: remove enable_desktop_capturer flag (#38412)
feat: remove enable_desktop_capturer flag

Co-authored-by: Milan Burda <miburda@microsoft.com>
2023-05-24 15:32:31 -04:00
Milan Burda
13fae292a7 build: remove unused enable_color_chooser build flag (#38419)
chore: remove unused enable_color_chooser build flag

Co-authored-by: Milan Burda <miburda@microsoft.com>
2023-05-24 21:24:42 +02:00
Alexey Kuzmin
c4c17d7534 build: fix build with "enable_pdf_viewer=false" (#38421)
* build: fix build with "enable_pdf_viewer=false"

* fixup! build: fix build with "enable_pdf_viewer=false"
2023-05-24 14:37:07 -04:00
Milan Burda
a043a60b89 refactor: cleanup global variable declarations (#38410)
refactor: eliminate duplicate isolatedApi typing

Co-authored-by: Milan Burda <miburda@microsoft.com>
2023-05-24 20:01:07 +02:00
Milan Burda
2f8e68f8b3 chore: remove ViewsDelegate::IsWindowInMetro() override (#38409)
Co-authored-by: Milan Burda <miburda@microsoft.com>
2023-05-24 20:00:52 +02:00
Shelley Vohr
16cd486356 fix: MediaDevices missing DisplayMediaInformation (#38390)
fix: MediaDevices missing DisplayMediaInformation
2023-05-24 11:17:08 -04:00
David Sanders
f07b040cb9 build: update yarn.lock (#38422) 2023-05-24 10:19:47 +02:00
Milan Burda
b6ef4a3929 build: remove unused enable_tts build flag (#38420)
chore: remove unused enable_tts build flag

Co-authored-by: Milan Burda <miburda@microsoft.com>
2023-05-24 10:18:43 +02:00
Cheng Zhao
dec9a1d9db chore: remove dead draggable region code (#38404) 2023-05-24 10:03:07 +02:00
Charles Kerr
b6c80ba646 fix: dangling_raw_ptr warning in electron_api_web_contents (#38403)
fix: dangling_raw_ptr warning in electron_api_web_contents
2023-05-23 21:52:07 -04:00
Charles Kerr
30e992dec4 chore: bump chromium to 115.0.5786.0 (main) (#38301)
* chore: bump chromium in DEPS to 115.0.5772.0

* chore: update disable_color_correct_rendering.patch

no manual changes; patch succeeded with fuzz 2.

* chore: update chromium/build_libc_as_static_library.patch

no manual changes; patch succeeded with fuzz 2 (offset 1 line).

* chore: update chromium/feat_configure_launch_options_for_service_process.patch

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

patch manually reapplied due to upstream code shear

* chore: update chromium/chore_patch_out_profile_methods_in_profile_selections_cc.patch

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

patch manually reapplied due to upstream code shear

* chore: update bundle_locations #include location

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

* chore: Remove `extension_name` from DesktopStreamsRegistry

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

* chore: bump chromium in DEPS to 115.0.5778.0

* chore: add chromium/chore_patch_out_profile_methods_in_chrome_browser_pdf.patch

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

Another instance of patching out upstream references to Profile code

* 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.

* fixup! chore: update bundle_locations #include location

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

Sync namespace use to upstream base::mac -> base::apple changes

* fixup! chore: update bundle_locations #include location

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

Sync namespace use to upstream base::mac -> base::apple changes

* chore: update chromium/mas_disable_remote_accessibility.patch

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

patch manually reapplied due to upstream code shear

* chore: update chromium/printing.patch

no manual changes; patch succeeded with fuzz

* chore: update chromium/build_add_electron_tracing_category.patch

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

no manual changes; patch succeeded with fuzz

* chore: update chromium/feat_ensure_mas_builds_of_the_same_application_can_use_safestorage.patch

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

patch manually reapplied due to upstream code shear

* chromium/build_only_use_the_mas_build_config_in_the_required_components.patch

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

patch manually reapplied due to upstream code shear

* chore: update chromium/mas-cgdisplayusesforcetogray.patch

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

no manual changes; patch succeeded with fuzz

* chore: update chromium/build_only_use_the_mas_build_config_in_the_required_components.patch

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

no manual changes; patch succeeded with fuzz

* chore: remove chromium/cherry-pick-48a136e77e6d.patch

already present upstream

* chore: remove chromium/cherry-pick-e6e23ba00379.patch

already present upstream

* [Code Health] Remove value based RegisterPref for Dict and List

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

* Remove `cxx17_backports.h` and adjust unittest file

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

Notes: mostly just removing #include and s/base::clamp/std::clamp/

* refactor: add FakeBrowserProcess helper class

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

Used in ElectronBrowserMainParts' fake_browser_process_ field. Previously
this was an BrowserProcessImpl instance, but upstream 4424072 makes that
an abstract base class. `FakeBrowserProcess` is a thin subclass with the
minimum code needed to make it concrete.

`ElectronBrowserMainParts::fake_browser_process_` is now a `shared_ptr`
instead of a `unique_ptr` so we can avoid exposing `FakeBrowserProcess`
in the header.

* fixup! refactor: add FakeBrowserProcess helper class

remove unnecessary unique_ptr

* fix: Browser::SetDockIcon() when !Browser.is_ready()

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

An alternative fix for https://github.com/electron/electron/pull/36279 .
The previous fix was to call `SetSupportedScales()` ourselves (1b1609a),
but upstream has removed this API.

CC @codebytere

* fixup! chore: remove chromium/cherry-pick-e6e23ba00379.patch

* chore: update chromium/export_gin_v8platform_pageallocator_for_usage_outside_of_the_gin.patch

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

patch manually reapplied due to upstream code shear

* chore: update patches

* chore: add dep: resource_coordinator:mojo_bindings

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

* fixup! chore: add dep: resource_coordinator:mojo_bindings

chore: make lint happy

* chore: patch out Profile methods in titlebar_config

Xref: https://chromium-review.googlesource.com/c/chromium/src/+/4508143 (primary)

Xref: https://chromium-review.googlesource.com/c/chromium/src/+/4534461 (followup)

* chore: bump chromium in DEPS to 115.0.5780.0

* chore: update chromium/disable_hidden.patch

no manual changes; patch succeeded with fuzz

* chore: update chromium/sysroot.patch

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

no manual changes; patch succeeded with fuzz

* chore: update chromium/feat_enable_offscreen_rendering_with_viz_compositor.patch

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

patch manually reapplied due to upstream code shear

* chore: update chromium/refactor_expose_cursor_changes_to_the_webcontentsobserver.patch

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

patch manually reapplied due to upstream code shear

* chore: update patches

* fixup! fix: Browser::SetDockIcon() when !Browser.is_ready()

chore: iwyu image.h

* chore: bump chromium in DEPS to 115.0.5782.0

* chore: bump chromium in DEPS to 115.0.5784.0

* 4514181: CR2023: Update filled cr-input styles.

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

* 4521894: Remove SiteInstanceDeleting usage outside of tests.

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

* 4525355: Move backup_util and bundle_locations to base/apple

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

* 4484743: webauthn: add underlying support for calling iCloud Keychain on macOS.

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

* chore: fixup patch indices

* 4546398: Convert /chrome/browser to use ARC

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

* chore: bump chromium in DEPS to 115.0.5786.0

* chore: update patches

* 4540682: Initialize PDF SDK with policy in chrome_pdf::RenderPDFPageToDC()

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

* Don't import ObjC++ fn headers into electron_api_app

* 4535715: Refactor sysroot-creator.sh

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

* fixup! refactor: add FakeBrowserProcess helper class

* 4531903: [string][test] Create/Copy strings to old space before externalization

https://chromium-review.googlesource.com/c/v8/v8/+/4531903

* 59645: Add APIs to support RSA keys with large e.

https://boringssl-review.googlesource.com/c/boringssl/+/59645

---------

Co-authored-by: Shelley Vohr <shelley.vohr@gmail.com>
2023-05-23 21:58:58 +02:00
Kilian Valkhof
e7b8bb4766 docs: disablewebsecurity on webview-tag can not be changed for an active session (#38373)
disablewebsecurity on webview-tag can not be changed for an active session
2023-05-22 16:29:41 +02:00
Shelley Vohr
aebcd3a8c4 build: try removing V8 symbol export patch for Windows (#38391) 2023-05-22 15:10:29 +02:00
Bruno Pitrus
395abf5620 fix: linker error missing uv__strtok (#38382)
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.
2023-05-22 13:00:45 +02:00
Keeley Hammond
508d7c1353 docs: update timelines for E26 (#38378)
docs: update E26 timeline, add E22 support note
2023-05-19 12:05:45 -07:00
Shelley Vohr
826c29abcc build: use @octokit/request v6.2.4 (#38346) 2023-05-18 15:37:58 -07:00
Milan Burda
2acb97aa85 chore: eliminate a few uses of base::AdaptCallbackForRepeating() (#38293) 2023-05-18 17:01:44 -04:00
Shelley Vohr
642950a00e build: try removing V8 DCHECK patch (#38341) 2023-05-18 20:53:15 +02:00
Shelley Vohr
b35ec4a23c build: modify gclient.py with unified patch (#38351)
* build: modify gclient.py with unified patch

* ci: ensure depot_tools does not update

* ci: move auto-update disable outside if
2023-05-17 14:54:26 -04:00
David Sanders
e138f5f915 docs: fix typing of message box type value (#38336)
* docs: fix typing of dialog type value

* test: add smoke tests

* test: update test
2023-05-17 10:33:30 -07:00
David Sanders
a22635bd9f docs: update example to use app.whenReady() (#38337)
* docs: update example to use app.whenReady()

* docs: retain async
2023-05-17 10:32:59 -07:00
Shelley Vohr
683235daf0 build: combine V8 BUILD.gn patches (#38342)
* build: combine V8 BUILD.gn patches

* chore: update patches

---------

Co-authored-by: PatchUp <73610968+patchup[bot]@users.noreply.github.com>
2023-05-17 13:17:52 +02:00
Shelley Vohr
32d8f84cad fix: getNormalBounds() for transparent windows on Windows (#38218) 2023-05-17 13:11:43 +02:00
Shelley Vohr
ad07712561 fix: win.isMaximized() for transparent windows on Windows (#38234) 2023-05-17 10:17:08 +02:00
Shelley Vohr
9902e01d2c build: remove CppHeapCreateParams patch (#38321)
build: remove CppHeapCreateParams patch
2023-05-17 09:52:29 +02:00
Shelley Vohr
e08c583dea build: remove V8 ARM undefined symbol patch (#38316) 2023-05-17 09:52:10 +02:00
Samuel Attard
2a16c73834 chore: cherry-pick e6e23ba00379 from chromium (#38323)
* chore: cherry-pick e6e23ba00379 from chromium

* make it work
2023-05-16 15:21:22 -07:00
David Sanders
c7ca29e80f chore: add smoke test for devtools-open-url (#38302) 2023-05-16 16:42:24 -04:00
Calvin
fa81f77f40 test: re-enable tests that aren't broken & remove old test (#38251) 2023-05-16 14:30:25 +02:00
Shelley Vohr
c05051e307 chore: remove obsoleted DecrementCapturerCount patch (#38294)
chore: remove obsoleted DecrementCapturerCount patch
2023-05-16 14:29:01 +02:00
Shelley Vohr
8b63a3fc8a build: bump brew cache to v6 (#38312) 2023-05-16 12:38:30 +02:00
Shelley Vohr
e83197669c fix: unify BrowserWindow.isVisible() logic cross-platform (#38242) 2023-05-16 11:46:45 +02:00
Shelley Vohr
9bd9d312f8 fix: enable BrowserWindow.id access post-destruction (#38241)
fix: enable BrowserWindow id access post-destruction
2023-05-16 09:29:00 +02:00
Shelley Vohr
042663e190 fix: isMaximized after minimize/fullscreen on macOS (#38291)
fix: isMaximized after isMinimized on macOS
2023-05-16 09:26:41 +02:00
Shelley Vohr
e19500fa03 feat: support Mica/Acrylic on Windows (#38163)
* feat: support Mica/Acrylic on Windows

* chore: feedback from review
2023-05-15 16:31:57 -04:00
Shelley Vohr
c2d7164021 chore: remove unnecessary spellchecker revert patch (#38248) 2023-05-15 16:17:00 -04:00
Shelley Vohr
a1b2dae68e build: add labels to appveyor update PR (#38292) 2023-05-15 16:52:25 +02:00
David Sanders
c591ecf518 test: prewarm Node headers cache if specifying Electron version (#38287) 2023-05-15 02:10:22 -07:00
Samuel Attard
d1c5e623fa build: drop python2 from CI (#38259)
* build: drop python2 from CI

* python3

* python3 uses linux not linux2
2023-05-15 02:06:12 -07:00
github-actions[bot]
9ac4787325 build: update appveyor image to latest version (#38257)
Co-authored-by: jkleinsc <jkleinsc@users.noreply.github.com>
2023-05-15 10:53:38 +02:00
Cesar Kohl
6645f49a9d chore: variable name should comply with naming convention (#38249) 2023-05-15 10:30:22 +02:00
Shelley Vohr
e7fc1a422d feat: add missing 'cursor-changed' type values (#38210) 2023-05-15 10:27:09 +02:00
David Sanders
eeb1e7d499 chore: fix lint:js-in-markdown script (#38260) 2023-05-15 09:58:35 +02:00
Milan Burda
0149ae72e6 refactor: use standard naming for enum class values (#38232) 2023-05-12 15:24:01 +02:00
Milan Burda
88a9962e22 refactor: convert HashAlgorithm to enum class (#38233) 2023-05-12 15:23:42 +02:00
329 changed files with 4159 additions and 4110 deletions

View File

@@ -250,14 +250,27 @@ step-depot-tools-get: &step-depot-tools-get
sed -i '/ninjalog_uploader_wrapper.py/d' ./depot_tools/autoninja
# Remove swift-format dep from cipd on macOS until we send a patch upstream.
cd depot_tools
patch gclient.py -R \<<'EOF'
676,677c676
< packages = dep_value.get('packages', [])
< for package in (x for x in packages if "infra/3pp/tools/swift-format" not in x.get('package')):
---
> for package in dep_value.get('packages', []):
cat > gclient.diff \<< 'EOF'
diff --git a/gclient.py b/gclient.py
index 3a9c5c6..f222043 100755
--- a/gclient.py
+++ b/gclient.py
@@ -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
git apply --3way gclient.diff
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
run:
@@ -279,7 +292,7 @@ step-gclient-sync: &step-gclient-sync
ELECTRON_USE_THREE_WAY_MERGE_FOR_PATCHES=1 gclient sync --with_branch_heads --with_tags
if [ "$IS_RELEASE" != "true" ]; then
# 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
git update-index --refresh || true
if ! git diff-index --quiet HEAD --; then
@@ -362,14 +375,14 @@ step-restore-brew-cache: &step-restore-brew-cache
- /usr/local/Cellar/gnu-tar
- /usr/local/bin/gtar
keys:
- v5-brew-cache-{{ arch }}
- v6-brew-cache-{{ arch }}
step-save-brew-cache: &step-save-brew-cache
save_cache:
paths:
- /usr/local/Cellar/gnu-tar
- /usr/local/bin/gtar
key: v5-brew-cache-{{ arch }}
key: v6-brew-cache-{{ arch }}
name: Persisting brew cache
step-get-more-space-on-mac: &step-get-more-space-on-mac
@@ -680,9 +693,9 @@ step-verify-mksnapshot: &step-verify-mksnapshot
if [ "$IS_ASAN" != "1" ]; then
cd src
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
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
@@ -692,7 +705,7 @@ step-verify-chromedriver: &step-verify-chromedriver
command: |
if [ "$IS_ASAN" != "1" ]; then
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
step-setup-linux-for-headless-testing: &step-setup-linux-for-headless-testing
@@ -818,7 +831,7 @@ step-maybe-cross-arch-snapshot: &step-maybe-cross-arch-snapshot
elif [ "`uname`" == "Darwin" ]; then
cp "out/Default/$MKSNAPSHOT_PATH/libffmpeg.dylib" out/Default
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
cp out/Default-mksnapshot-test/*.bin cross-arch-snapshots
# Clean up so that ninja does not get confused
@@ -975,7 +988,6 @@ step-ts-compile: &step-ts-compile
# List of all steps.
steps-electron-gn-check: &steps-electron-gn-check
steps:
- install-python2-mac
- *step-setup-goma-for-build
- checkout-from-cache
- *step-setup-env-for-build
@@ -994,31 +1006,6 @@ steps-electron-ts-compile-for-doc-change: &steps-electron-ts-compile-for-doc-cha
# Command Aliases
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:
parameters:
halt-if-successful:
@@ -1315,7 +1302,6 @@ commands:
- run: rm -rf src/electron
- *step-restore-brew-cache
- *step-install-gnutar-on-mac
- install-python2-mac
- *step-save-brew-cache
- when:
condition: << parameters.build >>
@@ -1476,7 +1462,6 @@ commands:
- *step-setup-linux-for-headless-testing
- *step-restore-brew-cache
- *step-fix-known-hosts-linux
- install-python2-mac
- *step-install-signing-cert-on-mac
- run:
@@ -1577,7 +1562,6 @@ commands:
- *step-depot-tools-get
- *step-depot-tools-add-to-path
- *step-restore-brew-cache
- install-python2-mac
- *step-get-more-space-on-mac
- when:
condition: << parameters.checkout >>

View File

@@ -28,8 +28,8 @@ jobs:
# Create new labels
gh label create $MAJOR-x-y --color 8d9ee8 || true
gh label create target/$MAJOR-x-y --color ad244f || true
gh label create merged/$MAJOR-x-y --color 61a3c6 || true
gh label create target/$MAJOR-x-y --color ad244f --description "PR should also be added to the \"${MAJOR}-x-y\" branch." || true
gh label create merged/$MAJOR-x-y --color 61a3c6 --description "PR was merged to the \"${MAJOR}-x-y\" branch." || true
gh label create in-flight/$MAJOR-x-y --color db69a6 || true
gh label create needs-manual-bp/$MAJOR-x-y --color 8b5dba || true

View File

@@ -66,7 +66,9 @@ jobs:
signoff: false
branch: bump-appveyor-image
delete-branch: true
reviewers: electron/wg-releases
title: 'build: update appveyor image to latest version'
labels: semver-none,no-backport
body: |
This PR updates appveyor.yml to the latest baked image, ${{ env.APPVEYOR_IMAGE_VERSION }}.
Notes: none

View File

@@ -555,6 +555,7 @@ source_set("electron_lib") {
}
frameworks = [
"AuthenticationServices.framework",
"AVFoundation.framework",
"Carbon.framework",
"LocalAuthentication.framework",
@@ -704,13 +705,6 @@ source_set("electron_lib") {
]
}
if (enable_desktop_capturer) {
sources += [
"shell/browser/api/electron_api_desktop_capturer.cc",
"shell/browser/api/electron_api_desktop_capturer.h",
]
}
if (enable_views_api) {
sources += [
"shell/browser/api/views/electron_api_image_view.cc",
@@ -772,6 +766,8 @@ source_set("electron_lib") {
sources += [
"shell/browser/electron_pdf_web_contents_helper_client.cc",
"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 = {
'chromium_version':
'115.0.5760.0',
'116.0.5791.0',
'node_version':
'v18.16.0',
'nan_version':
'16fa32231e2ccd89d2804b3f765319128b20c4ac',
'squirrel.mac_version':
'0e5d146ba13101a1302d59ea6e6e0b3cace4ae38',
'reactiveobjc_version':
'74ab5baccc6f7202c8ac69a8d1e152c29dc1ea76',
'mantle_version':
'78d3966b3c331292ea29ec38661b25df0a245948',
'pyyaml_version': '3.12',
@@ -17,6 +21,8 @@ vars = {
'nodejs_git': 'https://github.com/nodejs',
'yaml_git': 'https://github.com/yaml',
'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
'yarn_version': '1.15.2',
@@ -87,11 +93,11 @@ deps = {
'condition': 'process_deps',
},
'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'
},
'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',
}
}

View File

@@ -29,7 +29,7 @@
version: 1.0.{build}
build_cloud: electronhq-16-core
image: e-114.0.5719.0
image: e-116.0.5791.0
environment:
GIT_CACHE_PATH: C:\Users\appveyor\libcc_cache
ELECTRON_OUT_DIR: Default
@@ -66,11 +66,13 @@ for:
build_script:
- ps: |
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) {
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 ..
- ps: Write-Host "Building $env:GN_CONFIG build"
- git config --global core.longpaths true
@@ -220,11 +222,13 @@ for:
build_script:
- ps: |
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) {
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 ..
- mkdir out\Default
- cd ..

View File

@@ -29,7 +29,7 @@
version: 1.0.{build}
build_cloud: electronhq-16-core
image: e-114.0.5719.0
image: e-116.0.5791.0
environment:
GIT_CACHE_PATH: C:\Users\appveyor\libcc_cache
ELECTRON_OUT_DIR: Default
@@ -64,11 +64,13 @@ for:
build_script:
- ps: |
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) {
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 ..
- ps: Write-Host "Building $env:GN_CONFIG build"
- git config --global core.longpaths true
@@ -216,11 +218,13 @@ for:
build_script:
- ps: |
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) {
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 ..
- mkdir out\Default
- cd ..

View File

@@ -4,7 +4,7 @@ import sys
DEFINE_EXTRACT_REGEX = re.compile('^ *# *define (\w*)', re.MULTILINE)
def main(outDir, headers):
def main(out_dir, headers):
defines = []
for filename in headers:
with open(filename, 'r') as f:
@@ -15,13 +15,13 @@ def main(outDir, headers):
for define in defines:
push_and_undef += '#pragma push_macro("%s")\n' % define
push_and_undef += '#undef %s\n' % define
with open(os.path.join(outDir, 'push_and_undef_node_defines.h'), 'w') as o:
with open(os.path.join(out_dir, 'push_and_undef_node_defines.h'), 'w') as o:
o.write(push_and_undef)
pop = ''
for define in defines:
pop += '#pragma pop_macro("%s")\n' % define
with open(os.path.join(outDir, 'pop_node_defines.h'), 'w') as o:
with open(os.path.join(out_dir, 'pop_node_defines.h'), 'w') as o:
o.write(pop)
def read_defines(content):

View File

@@ -53,14 +53,6 @@ module.exports = ({
const ignoredModules = [];
if (defines.ENABLE_DESKTOP_CAPTURER === 'false') {
ignoredModules.push(
'@electron/internal/browser/desktop-capturer',
'@electron/internal/browser/api/desktop-capturer',
'@electron/internal/renderer/api/desktop-capturer'
);
}
if (defines.ENABLE_VIEWS_API === 'false') {
ignoredModules.push(
'@electron/internal/browser/api/views/image-view.js'

View File

@@ -9,13 +9,10 @@ buildflag_header("buildflags") {
header = "buildflags.h"
flags = [
"ENABLE_DESKTOP_CAPTURER=$enable_desktop_capturer",
"ENABLE_RUN_AS_NODE=$enable_run_as_node",
"ENABLE_OSR=$enable_osr",
"ENABLE_VIEWS_API=$enable_views_api",
"ENABLE_PDF_VIEWER=$enable_pdf_viewer",
"ENABLE_TTS=$enable_tts",
"ENABLE_COLOR_CHOOSER=$enable_color_chooser",
"ENABLE_ELECTRON_EXTENSIONS=$enable_electron_extensions",
"ENABLE_BUILTIN_SPELLCHECKER=$enable_builtin_spellchecker",
"ENABLE_PICTURE_IN_PICTURE=$enable_picture_in_picture",

View File

@@ -3,8 +3,6 @@
# found in the LICENSE file.
declare_args() {
enable_desktop_capturer = true
# Allow running Electron as a node binary.
enable_run_as_node = true
@@ -14,10 +12,6 @@ declare_args() {
enable_pdf_viewer = true
enable_tts = true
enable_color_chooser = true
enable_picture_in_picture = true
# Provide a fake location provider for mocking

View File

@@ -37,6 +37,14 @@ static_library("chrome") {
"//chrome/browser/icon_loader.h",
"//chrome/browser/icon_manager.cc",
"//chrome/browser/icon_manager.h",
"//chrome/browser/media/webrtc/desktop_media_list.cc",
"//chrome/browser/media/webrtc/desktop_media_list.h",
"//chrome/browser/media/webrtc/desktop_media_list_base.cc",
"//chrome/browser/media/webrtc/desktop_media_list_base.h",
"//chrome/browser/media/webrtc/desktop_media_list_observer.h",
"//chrome/browser/media/webrtc/native_desktop_media_list.cc",
"//chrome/browser/media/webrtc/native_desktop_media_list.h",
"//chrome/browser/media/webrtc/window_icon_util.h",
"//chrome/browser/net/chrome_mojo_proxy_resolver_factory.cc",
"//chrome/browser/net/chrome_mojo_proxy_resolver_factory.h",
"//chrome/browser/net/proxy_config_monitor.cc",
@@ -157,7 +165,11 @@ static_library("chrome") {
"//services/strings",
]
deps = [ "//chrome/browser:resource_prefetch_predictor_proto" ]
deps = [
"//chrome/browser:resource_prefetch_predictor_proto",
"//chrome/browser/resource_coordinator:mojo_bindings",
"//ui/snapshot",
]
if (is_linux) {
sources += [ "//chrome/browser/icon_loader_auralinux.cc" ]
@@ -188,20 +200,6 @@ static_library("chrome") {
public_deps += [ "//chrome/services/util_win:lib" ]
}
if (enable_desktop_capturer) {
sources += [
"//chrome/browser/media/webrtc/desktop_media_list.cc",
"//chrome/browser/media/webrtc/desktop_media_list.h",
"//chrome/browser/media/webrtc/desktop_media_list_base.cc",
"//chrome/browser/media/webrtc/desktop_media_list_base.h",
"//chrome/browser/media/webrtc/desktop_media_list_observer.h",
"//chrome/browser/media/webrtc/native_desktop_media_list.cc",
"//chrome/browser/media/webrtc/native_desktop_media_list.h",
"//chrome/browser/media/webrtc/window_icon_util.h",
]
deps += [ "//ui/snapshot" ]
}
if (enable_widevine) {
sources += [
"//chrome/renderer/media/chrome_key_systems.cc",

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
closed:
```javascript
```js
const { app } = require('electron')
app.on('window-all-closed', () => {
app.quit()
@@ -296,7 +296,7 @@ Emitted when failed to verify the `certificate` for `url`, to trust the
certificate you should prevent the default behavior with
`event.preventDefault()` and call `callback(true)`.
```javascript
```js
const { app } = require('electron')
app.on('certificate-error', (event, webContents, url, error, certificate, callback) => {
@@ -328,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
certificate from the store.
```javascript
```js
const { app } = require('electron')
app.on('select-client-certificate', (event, webContents, url, list, callback) => {
@@ -361,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
`callback(username, password)` with the credentials.
```javascript
```js
const { app } = require('electron')
app.on('login', (event, webContents, details, authInfo, callback) => {
@@ -481,7 +481,7 @@ Returns:
Emitted when Electron has created a new `session`.
```javascript
```js
const { app } = require('electron')
app.on('session-created', (session) => {
@@ -566,7 +566,7 @@ started after current instance exited.
An example of restarting current instance immediately and adding a new command
line argument to the new instance:
```javascript
```js
const { app } = require('electron')
app.relaunch({ args: process.argv.slice(1).concat(['--relaunch']) })
@@ -951,7 +951,7 @@ List, nor will it be displayed.
Here's a very simple example of creating a custom Jump List:
```javascript
```js
const { app } = require('electron')
app.setJumpList([
@@ -971,7 +971,7 @@ app.setJumpList([
title: 'Tool A',
program: process.execPath,
args: '--run-tool-a',
icon: process.execPath,
iconPath: process.execPath,
iconIndex: 0,
description: 'Runs Tool A'
},
@@ -980,7 +980,7 @@ app.setJumpList([
title: 'Tool B',
program: process.execPath,
args: '--run-tool-b',
icon: process.execPath,
iconPath: process.execPath,
iconIndex: 0,
description: 'Runs Tool B'
}
@@ -1034,8 +1034,8 @@ use this method to ensure single instance.
An example of activating the window of primary instance when a second instance
starts:
```javascript
const { app } = require('electron')
```js
const { app, BrowserWindow } = require('electron')
let myWindow = null
const additionalData = { myKey: 'myValue' }
@@ -1055,9 +1055,9 @@ if (!gotTheLock) {
}
})
// Create myWindow, load the rest of the app, etc...
app.whenReady().then(() => {
myWindow = createWindow()
myWindow = new BrowserWindow({})
myWindow.loadURL('https://electronjs.org')
})
}
```
@@ -1180,11 +1180,15 @@ case the user's DNS configuration does not include a provider that supports
DoH.
```js
app.configureHostResolver({
secureDnsMode: 'secure',
secureDnsServers: [
'https://cloudflare-dns.com/dns-query'
]
const { app } = require('electron')
app.whenReady().then(() => {
app.configureHostResolver({
secureDnsMode: 'secure',
secureDnsServers: [
'https://cloudflare-dns.com/dns-query'
]
})
})
```
@@ -1336,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
application name. For example:
``` javascript
``` js
const { app } = require('electron')
const path = require('path')
const appFolder = path.dirname(process.execPath)
const updateExe = path.resolve(appFolder, '..', 'Update.exe')
const exeName = path.basename(process.execPath)
@@ -1346,7 +1353,7 @@ app.setLoginItemSettings({
path: updateExe,
args: [
'--processStart', `"${exeName}"`,
'--process-start-args', `"--hidden"`
'--process-start-args', '"--hidden"'
]
})
```
@@ -1405,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.
```js
// Start accessing the file.
const stopAccessingSecurityScopedResource = app.startAccessingSecurityScopedResource(data)
// You can now access the file outside of the sandbox 🎉
const { app, dialog } = require('electron')
const fs = require('fs')
// 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()
```
@@ -1450,6 +1468,8 @@ By default, if an app of the same name as the one being moved exists in the Appl
For example:
```js
const { app, dialog } = require('electron')
app.moveToApplicationsFolder({
conflictHandler: (conflictType) => {
if (conflictType === 'exists') {

View File

@@ -104,6 +104,7 @@ window, you have to set both `parent` and `modal` options:
```javascript
const { BrowserWindow } = require('electron')
const top = new BrowserWindow()
const child = new BrowserWindow({ parent: top, modal: true, show: false })
child.loadURL('https://github.com')
child.once('ready-to-show', () => {
@@ -597,7 +598,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.
```js
```js @ts-expect-error=[11]
const win = new BrowserWindow({ height: 600, width: 600 })
const template = [
@@ -667,7 +668,7 @@ Hides the window.
#### `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()`
@@ -1200,6 +1201,9 @@ Node's [`url.format`](https://nodejs.org/api/url.html#url_url_format_urlobject)
method:
```javascript
const { BrowserWindow } = require('electron')
const win = new BrowserWindow()
const url = require('url').format({
protocol: 'file',
slashes: true,
@@ -1213,6 +1217,9 @@ You can load a URL using a `POST` request with URL-encoded data by doing
the following:
```javascript
const { BrowserWindow } = require('electron')
const win = new BrowserWindow()
win.loadURL('http://localhost:8000/post', {
postData: [{
type: 'rawData',
@@ -1557,6 +1564,21 @@ will remove the vibrancy effect on the window.
Note that `appearance-based`, `light`, `dark`, `medium-light`, and `ultra-dark` have been
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_
* `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:
```JavaScript
```javascript
const request = net.request({
method: 'GET',
protocol: 'https:',
@@ -104,7 +104,7 @@ The `callback` function is expected to be called back with user credentials:
* `username` string
* `password` string
```JavaScript
```javascript @ts-type={request:Electron.ClientRequest}
request.on('login', (authInfo, callback) => {
callback('username', 'password')
})
@@ -113,9 +113,9 @@ request.on('login', (authInfo, callback) => {
Providing empty credentials will cancel the request and report an authentication
error on the response object:
```JavaScript
```javascript @ts-type={request:Electron.ClientRequest}
request.on('response', (response) => {
console.log(`STATUS: ${response.statusCode}`);
console.log(`STATUS: ${response.statusCode}`)
response.on('error', (error) => {
console.log(`ERROR: ${JSON.stringify(error)}`)
})

View File

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

View File

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

View File

@@ -10,7 +10,9 @@ title is `Electron`:
```javascript
// 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 => {
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.
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
shown.
```js
```js @ts-type={mainWindow:Electron.BrowserWindow}
dialog.showOpenDialogSync(mainWindow, {
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
shown.
```js
```js @ts-type={mainWindow:Electron.BrowserWindow}
dialog.showOpenDialog(mainWindow, {
properties: ['openFile', 'openDirectory']
}).then(result => {
@@ -223,10 +223,10 @@ expanding and collapsing the dialog.
* `browserWindow` [BrowserWindow](browser-window.md) (optional)
* `options` Object
* `message` string - Content of the message box.
* `type` string (optional) - Can be `"none"`, `"info"`, `"error"`, `"question"` or
`"warning"`. On Windows, `"question"` displays the same icon as `"info"`, unless
you set an icon using the `"icon"` option. On macOS, both `"warning"` and
`"error"` display the same warning icon.
* `type` string (optional) - Can be `none`, `info`, `error`, `question` or
`warning`. On Windows, `question` displays the same icon as `info`, unless
you set an icon using the `icon` option. On macOS, both `warning` and
`error` display the same warning icon.
* `buttons` string[]&#32;(optional) - Array of texts for buttons. On Windows, an empty array
will result in one button labeled "OK".
* `defaultId` Integer (optional) - Index of the button in the buttons array which will
@@ -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)
* `options` Object
* `message` string - Content of the message box.
* `type` string (optional) - Can be `"none"`, `"info"`, `"error"`, `"question"` or
`"warning"`. On Windows, `"question"` displays the same icon as `"info"`, unless
you set an icon using the `"icon"` option. On macOS, both `"warning"` and
`"error"` display the same warning icon.
* `type` string (optional) - Can be `none`, `info`, `error`, `question` or
`warning`. On Windows, `question` displays the same icon as `info`, unless
you set an icon using the `icon` option. On macOS, both `warning` and
`error` display the same warning icon.
* `buttons` string[]&#32;(optional) - Array of texts for buttons. On Windows, an empty array
will result in one button labeled "OK".
* `defaultId` Integer (optional) - Index of the button in the buttons array which will

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
duplicates are not merged.
```javascript
```javascript @ts-type={response:Electron.IncomingMessage}
// Prints something like:
//
// [ 'user-agent',
@@ -100,5 +100,5 @@ duplicates are not merged.
// '127.0.0.1:8000',
// '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
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) => {
const result = await somePromise(...args)
return result
})
```
```js title='Renderer Process'
```js title='Renderer Process' @ts-type={arg1:unknown} @ts-type={arg2:unknown}
async () => {
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:
```javascript
```javascript @ts-type={someArgument:unknown} @ts-type={doSomeWork:(arg:unknown)=>Promise<unknown>}
// Renderer process
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:
```javascript
```javascript @ts-expect-error=[107]
const { app, Menu } = require('electron')
const isMac = process.platform === 'darwin'
const template = [
// { role: 'appMenu' }
...(isMac ? [{
label: app.name,
submenu: [
{ role: 'about' },
{ type: 'separator' },
{ role: 'services' },
{ type: 'separator' },
{ role: 'hide' },
{ role: 'hideOthers' },
{ role: 'unhide' },
{ type: 'separator' },
{ role: 'quit' }
]
}] : []),
...(isMac
? [{
label: app.name,
submenu: [
{ role: 'about' },
{ type: 'separator' },
{ role: 'services' },
{ type: 'separator' },
{ role: 'hide' },
{ role: 'hideOthers' },
{ role: 'unhide' },
{ type: 'separator' },
{ role: 'quit' }
]
}]
: []),
// { role: 'fileMenu' }
{
label: 'File',
@@ -185,23 +187,25 @@ const template = [
{ role: 'cut' },
{ role: 'copy' },
{ role: 'paste' },
...(isMac ? [
{ role: 'pasteAndMatchStyle' },
{ role: 'delete' },
{ role: 'selectAll' },
{ type: 'separator' },
{
label: 'Speech',
submenu: [
{ role: 'startSpeaking' },
{ role: 'stopSpeaking' }
...(isMac
? [
{ role: 'pasteAndMatchStyle' },
{ role: 'delete' },
{ role: 'selectAll' },
{ type: 'separator' },
{
label: 'Speech',
submenu: [
{ role: 'startSpeaking' },
{ role: 'stopSpeaking' }
]
}
]
}
] : [
{ role: 'delete' },
{ type: 'separator' },
{ role: 'selectAll' }
])
: [
{ role: 'delete' },
{ type: 'separator' },
{ role: 'selectAll' }
])
]
},
// { role: 'viewMenu' }
@@ -225,14 +229,16 @@ const template = [
submenu: [
{ role: 'minimize' },
{ role: 'zoom' },
...(isMac ? [
{ type: 'separator' },
{ role: 'front' },
{ type: 'separator' },
{ role: 'window' }
] : [
{ role: 'close' }
])
...(isMac
? [
{ type: 'separator' },
{ role: 'front' },
{ type: 'separator' },
{ role: 'window' }
]
: [
{ 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:
```js
```js @ts-expect-error=[21]
// renderer
window.addEventListener('contextmenu', (e) => {
e.preventDefault()
@@ -283,7 +289,7 @@ ipcMain.on('show-context-menu', (event) => {
{ label: 'Menu Item 2', type: 'checkbox', checked: true }
]
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
// Main process
const { MessageChannelMain } = require('electron')
const { BrowserWindow, MessageChannelMain } = require('electron')
const w = new BrowserWindow()
const { port1, port2 } = new MessageChannelMain()
w.webContents.postMessage('port', null, [port2])
port1.postMessage({ some: 'message' })
@@ -26,9 +27,9 @@ port1.postMessage({ some: 'message' })
const { ipcRenderer } = require('electron')
ipcRenderer.on('port', (e) => {
// 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)
})
}
})
```

View File

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

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.
```javascript
const { session, app, protocol } = require('electron')
const { app, BrowserWindow, net, protocol, session } = require('electron')
const path = require('path')
const url = require('url')
@@ -41,11 +41,11 @@ app.whenReady().then(() => {
const ses = session.fromPartition(partition)
ses.protocol.handle('atom', (request) => {
const path = request.url.slice('atom://'.length)
return net.fetch(url.pathToFileURL(path.join(__dirname, path)))
const filePath = request.url.slice('atom://'.length)
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:
```js
import { app, protocol } from 'electron'
import { join } from 'path'
import { pathToFileURL } from 'url'
const { app, net, protocol } = require('electron')
const { join } = require('path')
const { pathToFileURL } = require('url')
protocol.registerSchemesAsPrivileged([
{
@@ -131,7 +131,7 @@ protocol.registerSchemesAsPrivileged([
privileges: {
standard: 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.
// app://bundle/../../secret_file.txt
return net.fetch(pathToFileURL(join(__dirname, pathname)))
return net.fetch(pathToFileURL(join(__dirname, pathname)).toString())
} else if (host === 'api') {
return net.fetch('https://api.my-server.com/' + pathname, {
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
available from next tick of the process.
```javascript
```javascript @ts-expect-error=[4]
const { session } = require('electron')
session.defaultSession.on('will-download', (event, item, webContents) => {
event.preventDefault()
@@ -214,7 +214,7 @@ cancel the request. Additionally, permissioning on `navigator.hid` can
be further managed by using [`ses.setPermissionCheckHandler(handler)`](#sessetpermissioncheckhandlerhandler)
and [`ses.setDevicePermissionHandler(handler)`](#sessetdevicepermissionhandlerhandler).
```javascript
```javascript @ts-type={fetchGrantedDevices:()=>(Array<Electron.DevicePermissionHandlerHandlerDetails['device']>)}
const { app, BrowserWindow } = require('electron')
let win = null
@@ -253,7 +253,7 @@ app.whenReady().then(() => {
win.webContents.session.on('select-hid-device', (event, details, callback) => {
event.preventDefault()
const selectedDevice = details.deviceList.find((device) => {
return device.vendorId === '9025' && device.productId === '67'
return device.vendorId === 9025 && device.productId === 67
})
callback(selectedDevice?.deviceId)
})
@@ -320,7 +320,7 @@ cancel the request. Additionally, permissioning on `navigator.serial` can
be managed by using [ses.setPermissionCheckHandler(handler)](#sessetpermissioncheckhandlerhandler)
with the `serial` permission.
```javascript
```javascript @ts-type={fetchGrantedDevices:()=>(Array<Electron.DevicePermissionHandlerHandlerDetails['device']>)}
const { app, BrowserWindow } = require('electron')
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)
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')
let win = null
@@ -502,7 +502,7 @@ app.whenReady().then(() => {
win.webContents.session.on('select-usb-device', (event, details, callback) => {
event.preventDefault()
const selectedDevice = details.deviceList.find((device) => {
return device.vendorId === '9025' && device.productId === '67'
return device.vendorId === 9025 && device.productId === 67
})
if (selectedDevice) {
// Optionally, add this to the persisted devices (updateGrantedDevices needs to be implemented by developer to persist permissions)
@@ -755,15 +755,17 @@ Sets download saving directory. By default, the download directory will be the
Emulates network with the given configuration for the `session`.
```javascript
const win = new BrowserWindow()
// To emulate a GPRS connection with 50kbps throughput and 500 ms latency.
window.webContents.session.enableNetworkEmulation({
win.webContents.session.enableNetworkEmulation({
latency: 500,
downloadThroughput: 6400,
uploadThroughput: 6400
})
// To emulate a network outage.
window.webContents.session.enableNetworkEmulation({ offline: true })
win.webContents.session.enableNetworkEmulation({ offline: true })
```
#### `ses.preconnect(options)`
@@ -1036,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
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')
let win = null
@@ -1084,9 +1086,58 @@ app.whenReady().then(() => {
win.webContents.session.on('select-hid-device', (event, details, callback) => {
event.preventDefault()
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)
})
})
```
@@ -1125,32 +1176,32 @@ macOS does not require a handler because macOS handles the pairing
automatically. To clear the handler, call `setBluetoothPairingHandler(null)`.
```javascript
const { app, BrowserWindow, ipcMain, session } = require('electron')
let bluetoothPinCallback = null
const { app, BrowserWindow, session } = require('electron')
const path = require('path')
function createWindow () {
let bluetoothPinCallback = null
const mainWindow = new BrowserWindow({
webPreferences: {
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(() => {
createWindow()
})
@@ -1390,7 +1441,7 @@ extension to be loaded.
const { app, session } = require('electron')
const path = require('path')
app.on('ready', async () => {
app.whenReady().then(async () => {
await session.defaultSession.loadExtension(
path.join(__dirname, 'react-devtools'),
// allowFileAccess is required to load the devtools extension on file:// URLs.
@@ -1481,7 +1532,7 @@ app.whenReady().then(() => {
const protocol = session.fromPartition('some-partition').protocol
if (!protocol.registerFileProtocol('atom', (request, callback) => {
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')
}

View File

@@ -110,6 +110,9 @@
`tooltip`, `content`, `under-window`, or `under-page`. Please note that
`appearance-based`, `light`, `dark`, `medium-light`, and `ultra-dark` are
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](../browser-window.md#winsetbackgroundmaterialmaterial-windows) for more information.
* `zoomToPageWidth` boolean (optional) _macOS_ - Controls the behavior on
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

View File

@@ -2,9 +2,9 @@
* `portId` string - Unique identifier for the port.
* `portName` string - Name of the port.
* `displayName` string - A string suitable for display to the user for describing this device.
* `vendorId` string - Optional USB vendor ID.
* `productId` string - Optional USB product ID.
* `serialNumber` string - The USB device serial number.
* `usbDriverName` string (optional) - 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.
* `displayName` string (optional) - A string suitable for display to the user for describing this device.
* `vendorId` string (optional) - The USB vendor ID.
* `productId` string (optional) - The USB product ID.
* `serialNumber` string (optional) - The USB device serial number.
* `usbDriverName` string (optional) _macOS_ - Represents a single serial port on macOS can be enumerated by multiple drivers.
* `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.
if (browserOptions.transparent) {
win.loadURL(`file://${__dirname}/index.html`)
win.loadFile('index.html')
} else {
// 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
// Reel labels
const reel1 = new TouchBarLabel()
const reel2 = new TouchBarLabel()
const reel3 = new TouchBarLabel()
const reel1 = new TouchBarLabel({ label: '' })
const reel2 = new TouchBarLabel({ label: '' })
const reel3 = new TouchBarLabel({ label: '' })
// Spin result label
const result = new TouchBarLabel()
const result = new TouchBarLabel({ label: '' })
// Spin button
const spin = new TouchBarButton({

View File

@@ -98,7 +98,7 @@ async function lookupTargetId (browserWindow) {
await wc.debugger.attach('1.3')
const { targetInfo } = await wc.debugger.sendCommand('Target.getTargetInfo')
const { targetId } = targetInfo
const targetWebContents = await webContents.fromDevToolsTargetId(targetId)
const targetWebContents = await wc.fromDevToolsTargetId(targetId)
}
```
@@ -737,14 +737,16 @@ Returns:
* `size` [Size](structures/size.md) (optional) - the size of the `image`.
* `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`,
`crosshair`, `pointer`, `text`, `wait`, `help`, `e-resize`, `n-resize`,
`ne-resize`, `nw-resize`, `s-resize`, `se-resize`, `sw-resize`, `w-resize`,
`ns-resize`, `ew-resize`, `nesw-resize`, `nwse-resize`, `col-resize`,
`row-resize`, `m-panning`, `e-panning`, `n-panning`, `ne-panning`, `nw-panning`,
`s-panning`, `se-panning`, `sw-panning`, `w-panning`, `move`, `vertical-text`,
`cell`, `context-menu`, `alias`, `progress`, `nodrop`, `copy`, `none`,
`not-allowed`, `zoom-in`, `zoom-out`, `grab`, `grabbing` or `custom`.
Emitted when the cursor's type changes. The `type` parameter can be `pointer`,
`crosshair`, `hand`, `text`, `wait`, `help`, `e-resize`, `n-resize`, `ne-resize`,
`nw-resize`, `s-resize`, `se-resize`, `sw-resize`, `w-resize`, `ns-resize`, `ew-resize`,
`nesw-resize`, `nwse-resize`, `col-resize`, `row-resize`, `m-panning`, `m-panning-vertical`,
`m-panning-horizontal`, `e-panning`, `n-panning`, `ne-panning`, `nw-panning`, `s-panning`,
`se-panning`, `sw-panning`, `w-panning`, `move`, `vertical-text`, `cell`, `context-menu`,
`alias`, `progress`, `nodrop`, `copy`, `none`, `not-allowed`, `zoom-in`, `zoom-out`, `grab`,
`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
cursor image in a [`NativeImage`](native-image.md), and `scale`, `size` and `hotspot` will hold
@@ -864,7 +866,7 @@ app.whenReady().then(() => {
})
if (!result) {
// 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.
callback('')
} else {
@@ -1018,9 +1020,9 @@ e.g. the `http://` or `file://`. If the load should bypass http cache then
use the `pragma` header to achieve it.
```javascript
const { webContents } = require('electron')
const win = new BrowserWindow()
const options = { extraHeaders: 'pragma: no-cache\n' }
webContents.loadURL('https://github.com', options)
win.webContents.loadURL('https://github.com', options)
```
#### `contents.loadFile(filePath[, options])`
@@ -1050,6 +1052,7 @@ an app structure like this:
Would require code like this
```js
const win = new BrowserWindow()
win.loadFile('src/index.html')
```
@@ -1186,7 +1189,9 @@ when this process is unstable or unusable, for instance in order to recover
from the `unresponsive` event.
```js
contents.on('unresponsive', async () => {
const win = new BrowserWindow()
win.webContents.on('unresponsive', async () => {
const { response } = await dialog.showMessageBox({
message: 'App X has become unresponsive',
title: 'Do you want to try forcefully reloading the app?',
@@ -1194,8 +1199,8 @@ contents.on('unresponsive', async () => {
cancelId: 1
})
if (response === 0) {
contents.forcefullyCrashRenderer()
contents.reload()
win.webContents.forcefullyCrashRenderer()
win.webContents.reload()
}
})
```
@@ -1222,8 +1227,9 @@ Injects CSS into the current web page and returns a unique key for the inserted
stylesheet.
```js
contents.on('did-finish-load', () => {
contents.insertCSS('html, body { background-color: #f00; }')
const win = new BrowserWindow()
win.webContents.on('did-finish-load', () => {
win.webContents.insertCSS('html, body { background-color: #f00; }')
})
```
@@ -1237,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)`.
```js
contents.on('did-finish-load', async () => {
const key = await contents.insertCSS('html, body { background-color: #f00; }')
contents.removeInsertedCSS(key)
const win = new BrowserWindow()
win.webContents.on('did-finish-load', async () => {
const key = await win.webContents.insertCSS('html, body { background-color: #f00; }')
win.webContents.removeInsertedCSS(key)
})
```
@@ -1260,7 +1268,9 @@ this limitation.
Code execution will be suspended until web page stop loading.
```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) => {
console.log(result) // Will be the JSON object from the fetch call
})
@@ -1371,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:
>
> ```js
> contents.setVisualZoomLevelLimits(1, 3)
> const win = new BrowserWindow()
> win.webContents.setVisualZoomLevelLimits(1, 3)
> ```
#### `contents.undo()`
@@ -1506,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`.
```javascript
const { webContents } = require('electron')
webContents.on('found-in-page', (event, result) => {
if (result.finalUpdate) webContents.stopFindInPage('clearSelection')
const win = new BrowserWindow()
win.webContents.on('found-in-page', (event, result) => {
if (result.finalUpdate) win.webContents.stopFindInPage('clearSelection')
})
const requestId = webContents.findInPage('api')
const requestId = win.webContents.findInPage('api')
console.log(requestId)
```
@@ -1591,6 +1602,7 @@ Use `page-break-before: always;` CSS style to force to print to a new page.
Example usage:
```js
const win = new BrowserWindow()
const options = {
silent: true,
deviceName: 'My-Printer',
@@ -1887,8 +1899,9 @@ For example:
```js
// Main process
const win = new BrowserWindow()
const { port1, port2 } = new MessageChannelMain()
webContents.postMessage('port', { message: 'hello' }, [port1])
win.webContents.postMessage('port', { message: 'hello' }, [port1])
// Renderer process
ipcRenderer.on('port', (e, msg) => {

View File

@@ -128,8 +128,9 @@ For example:
```js
// Main process
const win = new BrowserWindow()
const { port1, port2 } = new MessageChannelMain()
webContents.mainFrame.postMessage('port', { message: 'hello' }, [port1])
win.webContents.mainFrame.postMessage('port', { message: 'hello' }, [port1])
// Renderer process
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:
```javascript
```javascript @ts-expect-error=[2,6]
const { webFrame } = require('electron')
const spellChecker = require('spellchecker')
webFrame.setSpellCheckProvider('en-US', {
spellCheck (words, callback) {
setTimeout(() => {
const spellchecker = require('spellchecker')
const misspelled = words.filter(x => spellchecker.isMisspelled(x))
callback(misspelled)
}, 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.
Web security is enabled by default.
This value can only be modified before the first navigation.
### `partition`
```html
@@ -253,7 +255,7 @@ The `webview` tag has the following methods:
**Example**
```javascript
```javascript @ts-expect-error=[3]
const webview = document.querySelector('webview')
webview.addEventListener('dom-ready', () => {
webview.openDevTools()
@@ -797,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
without regard for log level or other properties.
```javascript
```javascript @ts-expect-error=[3]
const webview = document.querySelector('webview')
webview.addEventListener('console-message', (e) => {
console.log('Guest page logged a message:', e.message)
@@ -818,7 +820,7 @@ Returns:
Fired when a result is available for
[`webview.findInPage`](#webviewfindinpagetext-options) request.
```javascript
```javascript @ts-expect-error=[3,6]
const webview = document.querySelector('webview')
webview.addEventListener('found-in-page', (e) => {
webview.stopFindInPage('keepSelection')
@@ -943,7 +945,7 @@ Fired when the guest page attempts to close itself.
The following example code navigates the `webview` to `about:blank` when the
guest attempts to close itself.
```javascript
```javascript @ts-expect-error=[3]
const webview = document.querySelector('webview')
webview.addEventListener('close', () => {
webview.src = 'about:blank'
@@ -963,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
between guest page and embedder page:
```javascript
```javascript @ts-expect-error=[4,7]
// In embedder page.
const webview = document.querySelector('webview')
webview.addEventListener('ipc-message', (event) => {

View File

@@ -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
The `scroll-touch-begin`, `scroll-touch-end` and `scroll-touch-edge` events on

View File

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

View File

@@ -24,9 +24,7 @@ function createWindow () {
event.preventDefault()
if (details.deviceList && details.deviceList.length > 0) {
const deviceToReturn = details.deviceList.find((device) => {
if (!grantedDeviceThroughPermHandler || (device.deviceId !== grantedDeviceThroughPermHandler.deviceId)) {
return true
}
return !grantedDeviceThroughPermHandler || (device.deviceId !== grantedDeviceThroughPermHandler.deviceId)
})
if (deviceToReturn) {
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')
}

View File

@@ -3,9 +3,7 @@ const path = require('path')
async function handleFileOpen () {
const { canceled, filePaths } = await dialog.showOpenDialog()
if (canceled) {
} else {
if (!canceled) {
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

@@ -55,7 +55,7 @@ fs.readdirSync('/path/to/example.asar')
Use a module from the archive:
```javascript
```javascript @ts-nocheck
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.
```js
```js @ts-nocheck
require('@electron/fuses').flipFuses(
// E.g. /a/b/Foo.app
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:
```javascript title='wdio.conf.js'
export.config = {
exports.config = {
// ...
capabilities: [{
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
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 driver = new webdriver.Builder()
// 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
entry point (here, it is `main.js`).
```js {5}
```js {5} @ts-nocheck
const { _electron: electron } = require('playwright')
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
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 { 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.
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 { 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`
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 { test, expect } = require('@playwright/test')
@@ -214,10 +214,10 @@ test('example test', async () => {
const isPackaged = await electronApp.evaluate(async ({ app }) => {
// This runs in Electron's main process, parameter here is always
// 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
// and return its Page object
@@ -226,7 +226,7 @@ test('example test', async () => {
// close app
await electronApp.close()
});
})
```
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.
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 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
a `TestDriver` class:
```js title='testDriver.js'
```js title='testDriver.js' @ts-nocheck
class TestDriver {
constructor ({ path, args, env }) {
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:
@@ -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
or Mocha would work as well:
```js title='test.js'
```js title='test.js' @ts-nocheck
const test = require('ava')
const electronPath = require('electron')
const { TestDriver } = require('./testDriver')

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
and notarizes your application](https://electron.github.io/electron-packager/main/interfaces/electronpackager.options.html).
```js
```js @ts-nocheck
const packager = require('electron-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
options when creating your installer.
```js {10-11}
```js {10-11} @ts-nocheck
const electronInstaller = require('electron-winstaller')
// NB: Use this syntax within an async function, Node does not have support for
// top-level await as of Node 12.
@@ -127,7 +127,7 @@ try {
authors: 'My App Inc.',
exe: 'myapp.exe',
certificateFile: './cert.pfx',
certificatePassword: 'this-is-a-secret',
certificatePassword: 'this-is-a-secret'
})
console.log('It worked!')
} 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
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'
// Step 1: Instantiate the MSICreator
@@ -159,7 +159,7 @@ const msiCreator = new MSICreator({
version: '1.1.2',
outputDirectory: '/path/to/output/folder',
certificateFile: './cert.pfx',
certificatePassword: 'this-is-a-secret',
certificatePassword: 'this-is-a-secret'
})
// 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:
```javascript title='preload.js'
```javascript title='preload.js' @ts-nocheck
// preload with contextIsolation disabled
window.myAPI = {
doAThing: () => {}
@@ -25,7 +25,7 @@ window.myAPI = {
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
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
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:
```typescript title='renderer.ts'
```typescript title='renderer.ts' @ts-nocheck
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.
```js title='renderer.js'
```js title='renderer.js' @ts-expect-error=[2,7]
document.getElementById('toggle-dark-mode').addEventListener('click', async () => {
const isDarkMode = await window.darkMode.toggle()
document.getElementById('theme-source').innerHTML = isDarkMode ? 'Dark' : 'Light'

View File

@@ -142,6 +142,8 @@ Electron provides several APIs for working with the WebUSB API:
`setDevicePermissionHandler`.
* [`ses.setPermissionCheckHandler(handler)`](../api/session.md#sessetpermissioncheckhandlerhandler)
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

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:
```javascript
const { app, session } = require('electron')
const path = require('path')
const os = require('os')
const { app, session } = require('electron')
const path = require('path')
const os = require('os')
// on macOS
const reactDevToolsPath = path.join(
os.homedir(),
'/Library/Application Support/Google/Chrome/Default/Extensions/fmkadmapgofadopljbjfkapdkoienihi/4.9.0_0'
)
// on macOS
const reactDevToolsPath = path.join(
os.homedir(),
'/Library/Application Support/Google/Chrome/Default/Extensions/fmkadmapgofadopljbjfkapdkoienihi/4.9.0_0'
)
app.whenReady().then(async () => {
await session.defaultSession.loadExtension(reactDevToolsPath)
})
app.whenReady().then(async () => {
await session.defaultSession.loadExtension(reactDevToolsPath)
})
```
**Notes:**

View File

@@ -9,6 +9,7 @@ check out our [Electron Versioning](./electron-versioning.md) doc.
| Electron | Alpha | Beta | Stable | EOL | Chrome | Node | Supported |
| ------- | ----- | ------- | ------ | ------ | ---- | ---- | ---- |
| 26.0.0 | 2023-Jun-01 | 2023-Jun-27 | 2023-Aug-08 | TBD | M116 | 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-04 | 2023-Oct-03 | M112 | v18.14 | ✅ |
| 23.0.0 | 2022-Dec-01 | 2023-Jan-10 | 2023-Feb-07 | 2023-Aug-08 | M110 | v18.12 | ✅ |
@@ -56,12 +57,12 @@ Chromium has the own public release schedule [here](https://chromiumdash.appspot
:::info
Beginning in September 2021 (Electron 15), the Electron team
will temporarily support the latest **four** stable major versions. This
extended support is intended to help Electron developers transition to
the [new 8-week release cadence](https://electronjs.org/blog/8-week-cadence),
and will continue until the release of Electron 19. At that time,
the Electron team will drop support back to the latest three stable major versions.
The Electron team will temporarily support Electron 22 until October 10, 2023.
This extended support is intended to help Electron developers who still need
support for Windows 7/8/8.1, which ended support in Electron 23. The October
support date follows the extended support dates from both Chromium and Microsoft.
On October 11, the Electron team will drop support back to the latest three
stable major versions.
:::

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.
```js
```js @ts-nocheck
require('@electron/fuses').flipFuses(
// Path to 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`
is composed as follows:
```javascript
```javascript @ts-nocheck
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:
```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')
//...
// ...
function handleSetTitle (event, title) {
const webContents = event.sender
@@ -74,8 +74,8 @@ function createWindow () {
app.whenReady().then(() => {
ipcMain.on('set-title', handleSetTitle)
createWindow()
}
//...
})
// ...
```
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')
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
script:
```javascript title='renderer.js (Renderer Process)'
```javascript title='renderer.js (Renderer Process)' @ts-expect-error=[4,5]
const setButton = document.getElementById('btn')
const titleInput = document.getElementById('title')
setButton.addEventListener('click', () => {
const title = titleInput.value
window.electronAPI.setTitle(title)
});
const title = titleInput.value
window.electronAPI.setTitle(title)
})
```
At this point, your demo should be fully functional. Try using the input field and see what happens
@@ -182,16 +182,14 @@ provided to the renderer process. Please refer to
:::
```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')
//...
// ...
async function handleFileOpen() {
const { canceled, filePaths } = await dialog.showOpenDialog()
if (canceled) {
return
} else {
async function handleFileOpen () {
const { canceled, filePaths } = await dialog.showOpenDialog({})
if (!canceled) {
return filePaths[0]
}
}
@@ -205,11 +203,11 @@ function createWindow () {
mainWindow.loadFile('index.html')
}
app.whenReady(() => {
app.whenReady().then(() => {
ipcMain.handle('dialog:openFile', handleFileOpen)
createWindow()
})
//...
// ...
```
:::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
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 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.
```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')
function createWindow () {
@@ -395,11 +393,11 @@ function createWindow () {
submenu: [
{
click: () => mainWindow.webContents.send('update-counter', 1),
label: 'Increment',
label: 'Increment'
},
{
click: () => mainWindow.webContents.send('update-counter', -1),
label: 'Decrement',
label: 'Decrement'
}
]
}
@@ -408,14 +406,13 @@ function createWindow () {
mainWindow.loadFile('index.html')
}
//...
// ...
```
For the purposes of the tutorial, it's important to note that the `click` handler
sends a message (either `1` or `-1`) to the renderer process through the `update-counter` channel.
```javascript
```javascript @ts-nocheck
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')
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')
window.addEventListener('DOMContentLoaded', () => {
const counter = document.getElementById('counter')
ipcRenderer.on('update-counter', (_event, value) => {
const oldValue = Number(counter.innerText)
const newValue = oldValue + value
counter.innerText = newValue
})
const counter = document.getElementById('counter')
ipcRenderer.on('update-counter', (_event, value) => {
const oldValue = Number(counter.innerText)
const newValue = oldValue + value
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
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')
window.electronAPI.onUpdateCounter((_event, value) => {
const oldValue = Number(counter.innerText)
const newValue = oldValue + value
counter.innerText = newValue
const oldValue = Number(counter.innerText)
const newValue = oldValue + value
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
`counter-value` channel.
```javascript title='renderer.js (Renderer Process)'
```javascript title='renderer.js (Renderer Process)' @ts-nocheck
const counter = document.getElementById('counter')
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.
```javascript title='main.js (Main Process)'
//...
// ...
ipcMain.on('counter-value', (_event, value) => {
console.log(value) // will print value to Node console
})
//...
// ...
```
## Pattern 4: Renderer to renderer

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
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')
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'
const handleKeyPress = (event) => {
// You can put code here to handle the keypress.
document.getElementById("last-keypress").innerText = event.key;
console.log(`You pressed ${event.key}`);
document.getElementById('last-keypress').innerText = 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
@@ -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
`mousetrap` running in the Renderer process:
```js
```js @ts-nocheck
Mousetrap.bind('4', () => { console.log('4') })
Mousetrap.bind('?', () => { console.log('show shortcuts!') })
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.
```javascript
let mainWindow
const createWindow = () => {
// Create the browser window.
mainWindow = new BrowserWindow({
@@ -65,7 +67,7 @@ This code will be different in Windows compared to MacOS and Linux. This is due
#### Windows code:
```javascript
```javascript @ts-type={mainWindow:Electron.BrowserWindow} @ts-type={createWindow:()=>void}
const gotTheLock = app.requestSingleInstanceLock()
if (!gotTheLock) {
@@ -91,7 +93,7 @@ if (!gotTheLock) {
#### MacOS and Linux code:
```javascript
```javascript @ts-type={createWindow:()=>void}
// 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.
@@ -166,7 +168,7 @@ If you're using Electron Packager's API, adding support for protocol handlers is
Electron Forge is handled, except
`protocols` is part of the Packager options passed to the `packager` function.
```javascript
```javascript @ts-nocheck
const packager = require('electron-packager')
packager({

View File

@@ -29,7 +29,7 @@ const { app, BrowserWindow, Menu } = require('electron')
const createWindow = () => {
const win = new BrowserWindow({
width: 800,
height: 600,
height: 600
})
win.loadFile('index.html')
@@ -66,7 +66,6 @@ app.on('activate', () => {
createWindow()
}
})
```
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
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')
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
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
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
// MessagePort.
// 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 ...
const { port1, port2 } = new MessageChannelMain()
// ... 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
stream of data.
```js title='renderer.js (Renderer Process)'
```js title='renderer.js (Renderer Process)' @ts-expect-error=[18]
const makeStreamingRequest = (element, callback) => {
// MessageChannels are lightweight--it's cheap to create a new one for each
// 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
loads no native modules after the Web Workers get started.
```javascript
```javascript @ts-expect-error=[1]
process.dlopen = () => {
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
const { contextBridge, ipcRenderer } = require('electron')
const path = require('path')
contextBridge.exposeInMainWorld('electron', {
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.
```javascript
```javascript @ts-expect-error=[3]
document.getElementById('drag').ondragstart = (event) => {
event.preventDefault()
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.
```js title='Main Process'
const { Notification } = require("electron");
const { Notification } = require('electron')
const NOTIFICATION_TITLE = "Basic Notification";
const NOTIFICATION_BODY = "Notification from the Main process";
const NOTIFICATION_TITLE = 'Basic Notification'
const NOTIFICATION_BODY = 'Notification from the Main process'
new Notification({
title: NOTIFICATION_TITLE,
body: NOTIFICATION_BODY,
}).show();
body: NOTIFICATION_BODY
}).show()
```
Here's a full example that you can open with Electron Fiddle:
```javascript fiddle='docs/fiddles/features/notifications/main'
const { Notification } = require("electron");
const { Notification } = require('electron')
const NOTIFICATION_TITLE = "Basic Notification";
const NOTIFICATION_BODY = "Notification from the Main process";
const NOTIFICATION_TITLE = 'Basic Notification'
const NOTIFICATION_BODY = 'Notification from the Main process'
new Notification({
title: NOTIFICATION_TITLE,
body: NOTIFICATION_BODY,
}).show();
body: NOTIFICATION_BODY
}).show()
```
### 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).
```js title='Renderer Process'
const NOTIFICATION_TITLE = "Title";
const NOTIFICATION_TITLE = 'Title'
const NOTIFICATION_BODY =
"Notification from the Renderer process. Click to log to console.";
const CLICK_MESSAGE = "Notification clicked";
'Notification from the Renderer process. Click to log to console.'
const CLICK_MESSAGE = 'Notification clicked'
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:
```javascript fiddle='docs/fiddles/features/notifications/renderer'
const NOTIFICATION_TITLE = "Title";
const NOTIFICATION_TITLE = 'Title'
const NOTIFICATION_BODY =
"Notification from the Renderer process. Click to log to console.";
const CLICK_MESSAGE = "Notification clicked";
'Notification from the Renderer process. Click to log to console.'
const CLICK_MESSAGE = 'Notification clicked'
new Notification(NOTIFICATION_TITLE, { body: NOTIFICATION_BODY }).onclick =
() => console.log(CLICK_MESSAGE);
() => console.log(CLICK_MESSAGE)
```
## Platform considerations

View File

@@ -54,7 +54,7 @@ at once, consider the [Chrome Tracing](https://www.chromium.org/developers/how-t
### Recommended Reading
* [Get Started With Analyzing Runtime Performance][chrome-devtools-tutorial]
* [Analyze runtime performance][chrome-devtools-tutorial]
* [Talk: "Visual Studio Code - The First Second"][vscode-first-second]
## Checklist: Performance recommendations
@@ -69,6 +69,7 @@ resource-hungry if you attempt these steps.
5. [Unnecessary polyfills](#5-unnecessary-polyfills)
6. [Unnecessary or blocking network requests](#6-unnecessary-or-blocking-network-requests)
7. [Bundle your code](#7-bundle-your-code)
8. [Call `Menu.setApplicationMenu(null)` when you do not need a default menu](#8-call-menusetapplicationmenunull-when-you-do-not-need-a-default-menu)
### 1. Carelessly including modules
@@ -172,7 +173,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,
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 fooParser = require('foo-parser')
@@ -195,7 +196,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
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
const fs = require('fs')
@@ -204,7 +205,7 @@ class Parser {
// Touch the disk as soon as `getFiles` is called, not sooner.
// Also, ensure that we're not blocking other operations by using
// the asynchronous version.
this.files = this.files || await fs.readdir('.')
this.files = this.files || await fs.promises.readdir('.')
return this.files
}
@@ -432,7 +433,7 @@ If you build your own menu or use a frameless window without native menu, you sh
Call `Menu.setApplicationMenu(null)` before `app.on("ready")`. This will prevent Electron from setting a default menu. See also https://github.com/electron/electron/issues/35512 for a related discussion.
[security]: ./security.md
[chrome-devtools-tutorial]: https://developers.google.com/web/tools/chrome-devtools/evaluate-performance/
[chrome-devtools-tutorial]: https://developer.chrome.com/docs/devtools/performance/
[worker-threads]: https://nodejs.org/api/worker_threads.html
[web-workers]: https://developer.mozilla.org/en-US/docs/Web/API/Web_Workers_API/Using_web_workers
[request-idle-callback]: https://developer.mozilla.org/en-US/docs/Web/API/Window/requestIdleCallback

View File

@@ -158,13 +158,13 @@ A preload script can be attached to the main process in the `BrowserWindow` cons
```js title='main.js'
const { BrowserWindow } = require('electron')
//...
// ...
const win = new BrowserWindow({
webPreferences: {
preload: 'path/to/preload.js',
},
preload: 'path/to/preload.js'
}
})
//...
// ...
```
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
the [`contextIsolation`][context-isolation] default.
```js title='preload.js'
```js title='preload.js' @ts-nocheck
window.myAPI = {
desktop: true,
desktop: true
}
```
```js title='renderer.js'
```js title='renderer.js' @ts-nocheck
console.log(window.myAPI)
// => undefined
```
@@ -196,11 +196,11 @@ securely:
const { contextBridge } = require('electron')
contextBridge.exposeInMainWorld('myAPI', {
desktop: true,
desktop: true
})
```
```js title='renderer.js'
```js title='renderer.js' @ts-nocheck
console.log(window.myAPI)
// => { 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()`
resolves its Promise.
```js
```js @ts-type={createWindow:()=>void}
app.whenReady().then(() => {
createWindow()
})
@@ -239,7 +239,7 @@ from within your existing `whenReady()` callback.
[activate]: ../api/app.md#event-activate-macos
```js
```js @ts-type={createWindow:()=>void}
app.whenReady().then(() => {
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.
```js
const { app, BrowserWindow } = require('electron')
// include the Node.js 'path' module at the top of your file
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'
const { app, BrowserWindow } = require('electron')
const os = require('os');
const os = require('os')
const createWindow = () => {
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,
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)
* [`timers`](https://nodejs.org/api/timers.html)
* [`url`](https://nodejs.org/api/url.html)

View File

@@ -141,7 +141,7 @@ like `HTTP`. Similarly, we recommend the use of `WSS` over `WS`, `FTPS` over
#### How?
```js title='main.js (Main Process)'
```js title='main.js (Main Process)' @ts-type={browserWindow:Electron.BrowserWindow}
// Bad
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)'
const { session } = require('electron')
const URL = require('url').URL
const { URL } = require('url')
session
.fromPartition('some-partition')
@@ -608,7 +608,8 @@ sometimes be fooled - a `startsWith('https://example.com')` test would let
`https://example.com.attacker.com` through.
```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) => {
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
monitor the creation of windows, and deny any unexpected window creation.
```js title='main.js (Main Process)'
const { shell } = require('electron')
```js title='main.js (Main Process)' @ts-type={isSafeForExternalOpen:(url:string)=>boolean}
const { app, shell } = require('electron')
app.on('web-contents-created', (event, contents) => {
contents.setWindowOpenHandler(({ url }) => {
@@ -683,7 +684,7 @@ leveraged to execute arbitrary commands.
#### How?
```js title='main.js (Main Process)'
```js title='main.js (Main Process)' @ts-type={USER_CONTROLLED_DATA_HERE:string}
// Bad
const { shell } = require('electron')
shell.openExternal(USER_CONTROLLED_DATA_HERE)
@@ -739,22 +740,22 @@ You should be validating the `sender` of **all** IPC messages by default.
#### How?
```js title='main.js (Main Process)'
```js title='main.js (Main Process)' @ts-type={getSecrets:()=>unknown}
// Bad
ipcMain.handle('get-secrets', () => {
return getSecrets();
});
return getSecrets()
})
// Good
ipcMain.handle('get-secrets', (e) => {
if (!validateSender(e.senderFrame)) return null;
return getSecrets();
});
if (!validateSender(e.senderFrame)) return null
return getSecrets()
})
function validateSender(frame) {
function validateSender (frame) {
// Value the host of the URL using an actual URL parser and an allowlist
if ((new URL(frame.url)).host === 'electronjs.org') return true;
return false;
if ((new URL(frame.url)).host === 'electronjs.org') return true
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`
programmatically. For more information, see the [Snapcraft API docs][snapcraft-syntax].
```js
```js @ts-nocheck
const snap = require('electron-installer-snap')
snap(options)

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.
```js
```js @ts-type={myWindow:Electron.BrowserWindow}
// 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
const possibleLanguages = myWindow.session.availableSpellCheckerLanguages
const possibleLanguages = myWindow.webContents.session.availableSpellCheckerLanguages
```
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
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')
myWindow.webContents.on('context-menu', (event, params) => {
@@ -45,7 +45,7 @@ myWindow.webContents.on('context-menu', (event, params) => {
for (const suggestion of params.dictionarySuggestions) {
menu.append(new MenuItem({
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(
new MenuItem({
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.
```js
myWindow.session.setSpellCheckerDictionaryDownloadURL('https://example.com/dictionaries/')
```js @ts-type={myWindow:Electron.BrowserWindow}
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.

View File

@@ -51,7 +51,7 @@ app.whenReady().then(() => {
Great! Now we can start attaching a context menu to our Tray, like so:
```js
```js @ts-expect-error=[8]
const contextMenu = Menu.buildFromTemplate([
{ label: 'Item1', 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.
```js
```js @ts-type={tray:Electron.Tray}
tray.setToolTip('This is my application')
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:
```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
@@ -199,7 +199,7 @@ const { app, BrowserWindow } = require('electron')
const createWindow = () => {
const win = new BrowserWindow({
width: 800,
height: 600,
height: 600
})
win.loadFile('index.html')
@@ -247,7 +247,7 @@ The `createWindow()` function loads your web page into a new BrowserWindow insta
const createWindow = () => {
const win = new BrowserWindow({
width: 800,
height: 600,
height: 600
})
win.loadFile('index.html')
@@ -256,7 +256,7 @@ const createWindow = () => {
### 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(() => {
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
events inside your existing `whenReady()` callback.
```js
```js @ts-type={createWindow:()=>void}
app.whenReady().then(() => {
createWindow()

View File

@@ -73,7 +73,7 @@ const { contextBridge } = require('electron')
contextBridge.exposeInMainWorld('versions', {
node: () => process.versions.node,
chrome: () => process.versions.chrome,
electron: () => process.versions.electron,
electron: () => process.versions.electron
// we can also expose variables, not just functions
})
```
@@ -90,8 +90,8 @@ const createWindow = () => {
width: 800,
height: 600,
webPreferences: {
preload: path.join(__dirname, 'preload.js'),
},
preload: path.join(__dirname, 'preload.js')
}
})
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`][]
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')
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,
chrome: () => process.versions.chrome,
electron: () => process.versions.electron,
ping: () => ipcRenderer.invoke('ping'),
ping: () => ipcRenderer.invoke('ping')
// we can also expose variables, not just functions
})
```
@@ -211,8 +211,8 @@ const createWindow = () => {
width: 800,
height: 600,
webPreferences: {
preload: path.join(__dirname, 'preload.js'),
},
preload: path.join(__dirname, 'preload.js')
}
})
win.loadFile('index.html')
}
@@ -225,7 +225,7 @@ app.whenReady().then(() => {
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.
```js title='renderer.js'
```js title='renderer.js' @ts-expect-error=[2]
const func = async () => {
const response = await window.versions.ping()
console.log(response) // prints out 'pong'

View File

@@ -153,14 +153,14 @@ For more information on code signing, check out the
module.exports = {
packagerConfig: {
osxSign: {},
//...
// ...
osxNotarize: {
tool: 'notarytool',
appleId: process.env.APPLE_ID,
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'
module.exports = {
//...
// ...
makers: [
{
name: '@electron-forge/maker-squirrel',
config: {
certificateFile: './cert.pfx',
certificatePassword: process.env.CERTIFICATE_PASSWORD,
},
},
],
//...
certificatePassword: process.env.CERTIFICATE_PASSWORD
}
}
]
// ...
}
```

View File

@@ -86,13 +86,13 @@ module.exports = {
config: {
repository: {
owner: 'github-user-name',
name: 'github-repo-name',
name: 'github-repo-name'
},
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.
```js title='main.js'
```js title='main.js' @ts-nocheck
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:
```js title="main.js"
```js title="main.js" @ts-nocheck
require('update-electron-app')()
```
@@ -113,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
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) => {
const dialogOpts = {
type: 'info',
@@ -121,7 +121,7 @@ autoUpdater.on('update-downloaded', (event, releaseNotes, releaseName) => {
title: 'Application Update',
message: process.platform === 'win32' ? releaseNotes : releaseName,
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) => {

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)
win.setIgnoreMouseEvents(...args)
win.setIgnoreMouseEvents(ignore, options)
})
```

View File

@@ -125,7 +125,7 @@ Starting with a working application from the
following lines:
```javascript
const { BrowserWindow } = require('electron')
const { BrowserWindow, nativeImage } = require('electron')
const path = require('path')
const win = new BrowserWindow()
@@ -133,11 +133,11 @@ const win = new BrowserWindow()
win.setThumbarButtons([
{
tooltip: 'button1',
icon: path.join(__dirname, 'button1.png'),
icon: nativeImage.createFromPath(path.join(__dirname, 'button1.png')),
click () { console.log('button1 clicked') }
}, {
tooltip: 'button2',
icon: path.join(__dirname, 'button2.png'),
icon: nativeImage.createFromPath(path.join(__dirname, 'button2.png')),
flags: ['enabled', 'dismissonclick'],
click () { console.log('button2 clicked.') }
}
@@ -189,11 +189,11 @@ Starting with a working application from the
following lines:
```javascript
const { BrowserWindow } = require('electron')
const { BrowserWindow, nativeImage } = require('electron')
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

View File

@@ -196,6 +196,7 @@ auto_filenames = {
"lib/browser/api/base-window.ts",
"lib/browser/api/browser-view.ts",
"lib/browser/api/browser-window.ts",
"lib/browser/api/clipboard.ts",
"lib/browser/api/content-tracing.ts",
"lib/browser/api/crash-reporter.ts",
"lib/browser/api/desktop-capturer.ts",
@@ -245,7 +246,6 @@ auto_filenames = {
"lib/browser/parse-features-string.ts",
"lib/browser/rpc-server.ts",
"lib/browser/web-view-events.ts",
"lib/common/api/clipboard.ts",
"lib/common/api/module-list.ts",
"lib/common/api/native-image.ts",
"lib/common/api/shell.ts",
@@ -256,8 +256,6 @@ auto_filenames = {
"lib/common/reset-search-paths.ts",
"lib/common/web-view-methods.ts",
"lib/common/webpack-globals-provider.ts",
"lib/renderer/ipc-renderer-internal-utils.ts",
"lib/renderer/ipc-renderer-internal.ts",
"package.json",
"tsconfig.electron.json",
"tsconfig.json",
@@ -266,7 +264,6 @@ auto_filenames = {
]
renderer_bundle_deps = [
"lib/common/api/clipboard.ts",
"lib/common/api/module-list.ts",
"lib/common/api/native-image.ts",
"lib/common/api/shell.ts",
@@ -276,6 +273,7 @@ auto_filenames = {
"lib/common/reset-search-paths.ts",
"lib/common/web-view-methods.ts",
"lib/common/webpack-provider.ts",
"lib/renderer/api/clipboard.ts",
"lib/renderer/api/context-bridge.ts",
"lib/renderer/api/crash-reporter.ts",
"lib/renderer/api/exports/electron.ts",
@@ -304,7 +302,6 @@ auto_filenames = {
]
worker_bundle_deps = [
"lib/common/api/clipboard.ts",
"lib/common/api/module-list.ts",
"lib/common/api/native-image.ts",
"lib/common/api/shell.ts",
@@ -313,6 +310,7 @@ auto_filenames = {
"lib/common/ipc-messages.ts",
"lib/common/reset-search-paths.ts",
"lib/common/webpack-provider.ts",
"lib/renderer/api/clipboard.ts",
"lib/renderer/api/context-bridge.ts",
"lib/renderer/api/crash-reporter.ts",
"lib/renderer/api/exports/electron.ts",

View File

@@ -262,6 +262,8 @@ filenames = {
"shell/browser/api/electron_api_data_pipe_holder.h",
"shell/browser/api/electron_api_debugger.cc",
"shell/browser/api/electron_api_debugger.h",
"shell/browser/api/electron_api_desktop_capturer.cc",
"shell/browser/api/electron_api_desktop_capturer.h",
"shell/browser/api/electron_api_dialog.cc",
"shell/browser/api/electron_api_download_item.cc",
"shell/browser/api/electron_api_download_item.h",
@@ -695,8 +697,6 @@ filenames = {
"shell/browser/extensions/api/management/electron_management_api_delegate.h",
"shell/browser/extensions/api/resources_private/resources_private_api.cc",
"shell/browser/extensions/api/resources_private/resources_private_api.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",
"shell/browser/extensions/api/runtime/electron_runtime_api_delegate.cc",
"shell/browser/extensions/api/runtime/electron_runtime_api_delegate.h",
"shell/browser/extensions/api/streams_private/streams_private_api.cc",

View File

@@ -574,7 +574,6 @@ export const wrapFsWithAsar = (fs: Record<string, any>) => {
};
const { readFile: readFilePromise } = fs.promises;
// eslint-disable-next-line @typescript-eslint/no-unused-vars
fs.promises.readFile = function (pathArgument: string, options: any) {
const pathInfo = splitPath(pathArgument);
if (!pathInfo.isAsar) {

View File

@@ -24,8 +24,6 @@ const spawnUpdate = function (args: string[], detached: boolean, callback: Funct
// Process spawned, different args: Return with error
// No process spawned: Spawn new process
if (spawnedProcess && !isSameArgs(args)) {
// Disabled for backwards compatibility:
// eslint-disable-next-line standard/no-callback-literal
return callback(`AutoUpdater process with arguments ${args} is already running`);
} else if (!spawnedProcess) {
spawnedProcess = spawn(updateExe, args, {
@@ -66,8 +64,6 @@ const spawnUpdate = function (args: string[], detached: boolean, callback: Funct
// Process terminated with error.
if (code !== 0) {
// Disabled for backwards compatibility:
// eslint-disable-next-line standard/no-callback-literal
return callback(`Command failed: ${signal ?? code}\n${stderr}`);
}
@@ -93,8 +89,6 @@ export function checkForUpdate (updateURL: string, callback: (error: Error | nul
const json = stdout.trim().split('\n').pop();
update = (ref = JSON.parse(json!)) != null ? (ref1 = ref.releasesToApply) != null ? typeof ref1.pop === 'function' ? ref1.pop() : undefined : undefined : undefined;
} catch {
// Disabled for backwards compatibility:
// eslint-disable-next-line standard/no-callback-literal
return callback(new Error(`Invalid result:\n${stdout}`));
}
return callback(null, update);

View File

@@ -12,6 +12,14 @@ BrowserWindow.prototype._init = function (this: BWT) {
// Avoid recursive require.
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;
this.setBounds = (bounds, ...opts) => {
bounds = {

View File

@@ -0,0 +1,3 @@
const clipboard = process._linkedBinding('electron_common_clipboard');
export default clipboard;

View File

@@ -237,8 +237,6 @@ const messageBox = (sync: boolean, window: BrowserWindow | null, options?: Messa
}
};
// eat dirt, eslint
/* eslint-disable import/export */
export function showOpenDialog(window: BrowserWindow, options: OpenDialogOptions): OpenDialogReturnValue;
export function showOpenDialog(options: OpenDialogOptions): OpenDialogReturnValue;
export function showOpenDialog (windowOrOptions: BrowserWindow | OpenDialogOptions, maybeOptions?: OpenDialogOptions): OpenDialogReturnValue {

View File

@@ -7,8 +7,10 @@ export const browserModuleList: ElectronInternal.ModuleEntry[] = [
{ name: 'BaseWindow', loader: () => require('./base-window') },
{ name: 'BrowserView', loader: () => require('./browser-view') },
{ name: 'BrowserWindow', loader: () => require('./browser-window') },
{ name: 'clipboard', loader: () => require('./clipboard') },
{ name: 'contentTracing', loader: () => require('./content-tracing') },
{ name: 'crashReporter', loader: () => require('./crash-reporter') },
{ name: 'desktopCapturer', loader: () => require('./desktop-capturer') },
{ name: 'dialog', loader: () => require('./dialog') },
{ name: 'globalShortcut', loader: () => require('./global-shortcut') },
{ name: 'ipcMain', loader: () => require('./ipc-main') },
@@ -38,12 +40,6 @@ export const browserModuleList: ElectronInternal.ModuleEntry[] = [
{ name: 'webFrameMain', loader: () => require('./web-frame-main') }
];
if (BUILDFLAG(ENABLE_DESKTOP_CAPTURER)) {
browserModuleList.push(
{ name: 'desktopCapturer', loader: () => require('./desktop-capturer') }
);
}
if (BUILDFLAG(ENABLE_VIEWS_API)) {
browserModuleList.push(
{ name: 'ImageView', loader: () => require('./views/image-view') }

View File

@@ -83,50 +83,50 @@ abstract class TouchBarItem<ConfigType> extends EventEmitter {
class TouchBarButton extends TouchBarItem<Electron.TouchBarButtonConstructorOptions> implements Electron.TouchBarButton {
@ImmutableProperty(() => 'button')
type!: string;
type!: string;
@LiveProperty<TouchBarButton>(config => config.label)
label!: string;
label!: string;
@LiveProperty<TouchBarButton>(config => config.accessibilityLabel)
accessibilityLabel!: string;
accessibilityLabel!: string;
@LiveProperty<TouchBarButton>(config => config.backgroundColor)
backgroundColor!: string;
backgroundColor!: string;
@LiveProperty<TouchBarButton>(config => config.icon)
icon!: Electron.NativeImage;
icon!: Electron.NativeImage;
@LiveProperty<TouchBarButton>(config => config.iconPosition)
iconPosition!: Electron.TouchBarButton['iconPosition'];
iconPosition!: Electron.TouchBarButton['iconPosition'];
@LiveProperty<TouchBarButton>(config => typeof config.enabled !== 'boolean' ? true : config.enabled)
enabled!: boolean;
enabled!: boolean;
@ImmutableProperty<TouchBarButton>(({ click: onClick }) => typeof onClick === 'function' ? () => onClick() : null)
onInteraction!: Function | null;
onInteraction!: Function | null;
}
class TouchBarColorPicker extends TouchBarItem<Electron.TouchBarColorPickerConstructorOptions> implements Electron.TouchBarColorPicker {
@ImmutableProperty(() => 'colorpicker')
type!: string;
type!: string;
@LiveProperty<TouchBarColorPicker>(config => config.availableColors)
availableColors!: string[];
availableColors!: string[];
@LiveProperty<TouchBarColorPicker>(config => config.selectedColor)
selectedColor!: string;
selectedColor!: string;
@ImmutableProperty<TouchBarColorPicker>(({ change: onChange }, setInternalProp) => typeof onChange === 'function' ? (details: { color: string }) => {
setInternalProp('selectedColor', details.color);
onChange(details.color);
} : null)
onInteraction!: Function | null;
onInteraction!: Function | null;
}
class TouchBarGroup extends TouchBarItem<Electron.TouchBarGroupConstructorOptions> implements Electron.TouchBarGroup {
@ImmutableProperty(() => 'group')
type!: string;
type!: string;
@LiveProperty<TouchBarGroup>(config => config.items instanceof TouchBar ? config.items : new TouchBar(config.items), (self, newChild: TouchBar) => {
if (self.child) {
@@ -138,39 +138,39 @@ class TouchBarGroup extends TouchBarItem<Electron.TouchBarGroupConstructorOption
item._addParent(self);
}
})
child!: TouchBar;
child!: TouchBar;
onInteraction = null;
}
class TouchBarLabel extends TouchBarItem<Electron.TouchBarLabelConstructorOptions> implements Electron.TouchBarLabel {
@ImmutableProperty(() => 'label')
type!: string;
type!: string;
@LiveProperty<TouchBarLabel>(config => config.label)
label!: string;
label!: string;
@LiveProperty<TouchBarLabel>(config => config.accessibilityLabel)
accessibilityLabel!: string;
accessibilityLabel!: string;
@LiveProperty<TouchBarLabel>(config => config.textColor)
textColor!: string;
textColor!: string;
onInteraction = null;
}
class TouchBarPopover extends TouchBarItem<Electron.TouchBarPopoverConstructorOptions> implements Electron.TouchBarPopover {
@ImmutableProperty(() => 'popover')
type!: string;
type!: string;
@LiveProperty<TouchBarPopover>(config => config.label)
label!: string;
label!: string;
@LiveProperty<TouchBarPopover>(config => config.icon)
icon!: Electron.NativeImage;
icon!: Electron.NativeImage;
@LiveProperty<TouchBarPopover>(config => config.showCloseButton)
showCloseButton!: boolean;
showCloseButton!: boolean;
@LiveProperty<TouchBarPopover>(config => config.items instanceof TouchBar ? config.items : new TouchBar(config.items), (self, newChild: TouchBar) => {
if (self.child) {
@@ -182,88 +182,88 @@ class TouchBarPopover extends TouchBarItem<Electron.TouchBarPopoverConstructorOp
item._addParent(self);
}
})
child!: TouchBar;
child!: TouchBar;
onInteraction = null;
}
class TouchBarSlider extends TouchBarItem<Electron.TouchBarSliderConstructorOptions> implements Electron.TouchBarSlider {
@ImmutableProperty(() => 'slider')
type!: string;
type!: string;
@LiveProperty<TouchBarSlider>(config => config.label)
label!: string;
label!: string;
@LiveProperty<TouchBarSlider>(config => config.minValue)
minValue!: number;
minValue!: number;
@LiveProperty<TouchBarSlider>(config => config.maxValue)
maxValue!: number;
maxValue!: number;
@LiveProperty<TouchBarSlider>(config => config.value)
value!: number;
value!: number;
@ImmutableProperty<TouchBarSlider>(({ change: onChange }, setInternalProp) => typeof onChange === 'function' ? (details: { value: number }) => {
setInternalProp('value', details.value);
onChange(details.value);
} : null)
onInteraction!: Function | null;
onInteraction!: Function | null;
}
class TouchBarSpacer extends TouchBarItem<Electron.TouchBarSpacerConstructorOptions> implements Electron.TouchBarSpacer {
@ImmutableProperty(() => 'spacer')
type!: string;
type!: string;
@ImmutableProperty<TouchBarSpacer>(config => config.size)
size!: Electron.TouchBarSpacer['size'];
size!: Electron.TouchBarSpacer['size'];
onInteraction = null;
}
class TouchBarSegmentedControl extends TouchBarItem<Electron.TouchBarSegmentedControlConstructorOptions> implements Electron.TouchBarSegmentedControl {
@ImmutableProperty(() => 'segmented_control')
type!: string;
type!: string;
@LiveProperty<TouchBarSegmentedControl>(config => config.segmentStyle)
segmentStyle!: Electron.TouchBarSegmentedControl['segmentStyle'];
segmentStyle!: Electron.TouchBarSegmentedControl['segmentStyle'];
@LiveProperty<TouchBarSegmentedControl>(config => config.segments || [])
segments!: Electron.SegmentedControlSegment[];
segments!: Electron.SegmentedControlSegment[];
@LiveProperty<TouchBarSegmentedControl>(config => config.selectedIndex)
selectedIndex!: number;
selectedIndex!: number;
@LiveProperty<TouchBarSegmentedControl>(config => config.mode)
mode!: Electron.TouchBarSegmentedControl['mode'];
mode!: Electron.TouchBarSegmentedControl['mode'];
@ImmutableProperty<TouchBarSegmentedControl>(({ change: onChange }, setInternalProp) => typeof onChange === 'function' ? (details: { selectedIndex: number, isSelected: boolean }) => {
setInternalProp('selectedIndex', details.selectedIndex);
onChange(details.selectedIndex, details.isSelected);
} : null)
onInteraction!: Function | null;
onInteraction!: Function | null;
}
class TouchBarScrubber extends TouchBarItem<Electron.TouchBarScrubberConstructorOptions> implements Electron.TouchBarScrubber {
@ImmutableProperty(() => 'scrubber')
type!: string;
type!: string;
@LiveProperty<TouchBarScrubber>(config => config.items)
items!: Electron.ScrubberItem[];
items!: Electron.ScrubberItem[];
@LiveProperty<TouchBarScrubber>(config => config.selectedStyle || null)
selectedStyle!: Electron.TouchBarScrubber['selectedStyle'];
selectedStyle!: Electron.TouchBarScrubber['selectedStyle'];
@LiveProperty<TouchBarScrubber>(config => config.overlayStyle || null)
overlayStyle!: Electron.TouchBarScrubber['overlayStyle'];
overlayStyle!: Electron.TouchBarScrubber['overlayStyle'];
@LiveProperty<TouchBarScrubber>(config => config.showArrowButtons || false)
showArrowButtons!: boolean;
showArrowButtons!: boolean;
@LiveProperty<TouchBarScrubber>(config => config.mode || 'free')
mode!: Electron.TouchBarScrubber['mode'];
mode!: Electron.TouchBarScrubber['mode'];
@LiveProperty<TouchBarScrubber>(config => typeof config.continuous === 'undefined' ? true : config.continuous)
continuous!: boolean;
continuous!: boolean;
@ImmutableProperty<TouchBarScrubber>(({ select: onSelect, highlight: onHighlight }) => typeof onSelect === 'function' || typeof onHighlight === 'function' ? (details: { type: 'select'; selectedIndex: number } | { type: 'highlight'; highlightedIndex: number }) => {
if (details.type === 'select') {
@@ -272,7 +272,7 @@ class TouchBarScrubber extends TouchBarItem<Electron.TouchBarScrubberConstructor
if (onHighlight) onHighlight(details.highlightedIndex);
}
} : null)
onInteraction!: Function | null;
onInteraction!: Function | null;
}
class TouchBarOtherItemsProxy extends TouchBarItem<null> implements Electron.TouchBarOtherItemsProxy {

View File

@@ -14,8 +14,8 @@ import * as deprecate from '@electron/internal/common/deprecate';
// session is not used here, the purpose is to make sure session is initialized
// before the webContents module.
// eslint-disable-next-line
session
// eslint-disable-next-line no-unused-expressions
session;
const webFrameMainBinding = process._linkedBinding('electron_browser_web_frame_main');

View File

@@ -96,7 +96,6 @@ const createGuest = function (embedder: Electron.WebContents, embedderFrameId: n
return -1;
}
// eslint-disable-next-line no-undef
const guest = (webContents as typeof ElectronInternal.WebContents).create({
...webPreferences,
type: 'webview',

View File

@@ -19,14 +19,14 @@ export class IpcMainImpl extends EventEmitter {
throw new Error(`Expected handler to be a function, but found type '${typeof fn}'`);
}
this._invokeHandlers.set(method, fn);
}
};
handleOnce: Electron.IpcMain['handleOnce'] = (method, fn) => {
this.handle(method, (e, ...args) => {
this.removeHandler(method);
return fn(e, ...args);
});
}
};
removeHandler (method: string) {
this._invokeHandlers.delete(method);

View File

@@ -1,7 +1,7 @@
import { EventEmitter } from 'events';
export class MessagePortMain extends EventEmitter {
_internalPort: any
_internalPort: any;
constructor (internalPort: any) {
super();
this._internalPort = internalPort;

View File

@@ -1,27 +0,0 @@
import { IPC_MESSAGES } from '@electron/internal/common/ipc-messages';
// eslint-disable-next-line no-restricted-imports
import type * as ipcRendererUtilsModule from '@electron/internal/renderer/ipc-renderer-internal-utils';
const clipboard = process._linkedBinding('electron_common_clipboard');
if (process.type === 'renderer') {
const ipcRendererUtils = require('@electron/internal/renderer/ipc-renderer-internal-utils') as typeof ipcRendererUtilsModule;
const makeRemoteMethod = function (method: keyof Electron.Clipboard): any {
return (...args: any[]) => ipcRendererUtils.invokeSync(IPC_MESSAGES.BROWSER_CLIPBOARD_SYNC, method, ...args);
};
if (process.platform === 'linux') {
// On Linux we could not access clipboard in renderer process.
for (const method of Object.keys(clipboard) as (keyof Electron.Clipboard)[]) {
clipboard[method] = makeRemoteMethod(method);
}
} else if (process.platform === 'darwin') {
// Read/write to find pasteboard over IPC since only main process is notified of changes
clipboard.readFindText = makeRemoteMethod('readFindText');
clipboard.writeFindText = makeRemoteMethod('writeFindText');
}
}
export default clipboard;

View File

@@ -1,6 +1,5 @@
// Common modules, please sort alphabetically
export const commonModuleList: ElectronInternal.ModuleEntry[] = [
{ name: 'clipboard', loader: () => require('./clipboard') },
{ name: 'nativeImage', loader: () => require('./native-image') },
{ name: 'shell', loader: () => require('./shell') }
];

View File

@@ -81,7 +81,8 @@ export function event (emitter: NodeJS.EventEmitter, oldName: string, newName: s
// remove a property with no replacement
export function removeProperty<T, K extends (keyof T & string)>(object: T, removedName: K, onlyForValues?: any[]): T {
// if the property's already been removed, warn about it
const info = Object.getOwnPropertyDescriptor((object as any).__proto__, removedName) // eslint-disable-line
// eslint-disable-next-line no-proto
const info = Object.getOwnPropertyDescriptor((object as any).__proto__, removedName);
if (!info) {
log(`Unable to remove property '${removedName}' from an object that lacks it.`);
return object;

View File

@@ -1,6 +1,7 @@
/* global isolatedApi */
import type * as webViewElementModule from '@electron/internal/renderer/web-view/web-view-element';
import type { WebViewImplHooks } from '@electron/internal/renderer/web-view/web-view-impl';
declare const isolatedApi: WebViewImplHooks;
if (isolatedApi.guestViewInternal) {
// Must setup the WebView element in main world.

View File

@@ -0,0 +1,21 @@
import { IPC_MESSAGES } from '@electron/internal/common/ipc-messages';
import * as ipcRendererUtils from '@electron/internal/renderer/ipc-renderer-internal-utils';
const clipboard = process._linkedBinding('electron_common_clipboard');
const makeRemoteMethod = function (method: keyof Electron.Clipboard): any {
return (...args: any[]) => ipcRendererUtils.invokeSync(IPC_MESSAGES.BROWSER_CLIPBOARD_SYNC, method, ...args);
};
if (process.platform === 'linux') {
// On Linux we could not access clipboard in renderer process.
for (const method of Object.keys(clipboard) as (keyof Electron.Clipboard)[]) {
clipboard[method] = makeRemoteMethod(method);
}
} else if (process.platform === 'darwin') {
// Read/write to find pasteboard over IPC since only main process is notified of changes
clipboard.readFindText = makeRemoteMethod('readFindText');
clipboard.writeFindText = makeRemoteMethod('writeFindText');
}
export default clipboard;

View File

@@ -1,5 +1,6 @@
// Renderer side modules, please sort alphabetically.
export const rendererModuleList: ElectronInternal.ModuleEntry[] = [
{ name: 'clipboard', loader: () => require('./clipboard') },
{ name: 'contextBridge', loader: () => require('./context-bridge') },
{ name: 'crashReporter', loader: () => require('./crash-reporter') },
{ name: 'ipcRenderer', loader: () => require('./ipc-renderer') },

View File

@@ -57,7 +57,7 @@ require('@electron/internal/renderer/common-init');
if (nodeIntegration) {
// Export node bindings to global.
const { makeRequireFunction } = __non_webpack_require__('internal/modules/cjs/helpers') // eslint-disable-line
const { makeRequireFunction } = __non_webpack_require__('internal/modules/cjs/helpers');
global.module = new Module('electron/js2c/renderer_init');
global.require = makeRequireFunction(global.module);

View File

@@ -53,7 +53,7 @@ export class WebViewAttribute implements MutationHandler {
}
// Called when the attribute's value changes.
public handleMutation: MutationHandler['handleMutation'] = () => undefined
public handleMutation: MutationHandler['handleMutation'] = () => undefined;
}
// An attribute that is treated as a Boolean.
@@ -73,7 +73,7 @@ class BooleanAttribute extends WebViewAttribute {
// Attribute representing the state of the storage partition.
export class PartitionAttribute extends WebViewAttribute {
public validPartitionId = true
public validPartitionId = true;
constructor (public webViewImpl: WebViewImpl) {
super(WEB_VIEW_ATTRIBUTES.PARTITION, webViewImpl);
@@ -92,7 +92,7 @@ export class PartitionAttribute extends WebViewAttribute {
this.validPartitionId = false;
console.error(WEB_VIEW_ERROR_MESSAGES.INVALID_PARTITION_ATTRIBUTE);
}
}
};
}
// Attribute that handles the location and navigation of the webview.
@@ -134,7 +134,7 @@ export class SrcAttribute extends WebViewAttribute {
return;
}
this.parse();
}
};
// The purpose of this mutation observer is to catch assignment to the src
// attribute without any changes to its value. This is useful in the case

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